From 2e40a60e847d6c128af23e24ea7a8efebd2427da Mon Sep 17 00:00:00 2001 From: yorah Date: Thu, 11 Apr 2013 17:29:05 +0200 Subject: status: fix handling of filenames with special prefixes Fix libgit2/libgit2sharp#379 --- src/attr_file.c | 47 ++++++++++++++++++++++++++++++++++++---------- src/attr_file.h | 8 +++++++- src/ignore.c | 2 +- src/pathspec.c | 2 +- tests-clar/status/ignore.c | 34 +++++++++++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 13 deletions(-) diff --git a/src/attr_file.c b/src/attr_file.c index 85cd87624..93f6df1d9 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -85,7 +85,7 @@ int git_attr_file__parse_buffer( } /* parse the next "pattern attr attr attr" line */ - if (!(error = git_attr_fnmatch__parse( + if (!(error = git_attr_fnmatch__parse_gitattr_format( &rule->match, attrs->pool, context, &scan)) && !(error = git_attr_assignment__parse( repo, attrs->pool, &rule->assigns, &scan))) @@ -337,23 +337,16 @@ void git_attr_path__free(git_attr_path *info) * GIT_ENOTFOUND if the fnmatch does not require matching, or * another error code there was an actual problem. */ -int git_attr_fnmatch__parse( +int git_attr_fnmatch__parse_gitattr_format( git_attr_fnmatch *spec, git_pool *pool, const char *source, const char **base) { - const char *pattern, *scan; - int slash_count, allow_space; + const char *pattern; assert(spec && base && *base); - if (parse_optimized_patterns(spec, pool, *base)) - return 0; - - spec->flags = (spec->flags & GIT_ATTR_FNMATCH_ALLOWSPACE); - allow_space = (spec->flags != 0); - pattern = *base; while (git__isspace(*pattern)) pattern++; @@ -375,6 +368,39 @@ int git_attr_fnmatch__parse( pattern++; } + if (git_attr_fnmatch__parse_shellglob_format(spec, pool, + source, &pattern) < 0) + return -1; + + *base = pattern; + + return 0; +} + +/* + * Fills a spec for the purpose of pure pathspec matching, not + * related to a gitattribute file parsing. + * + * This will return 0 if the spec was filled out, or + * another error code there was an actual problem. + */ +int git_attr_fnmatch__parse_shellglob_format( + git_attr_fnmatch *spec, + git_pool *pool, + const char *source, + const char **base) +{ + const char *pattern, *scan; + int slash_count, allow_space; + + assert(spec && base && *base); + + if (parse_optimized_patterns(spec, pool, *base)) + return 0; + + allow_space = (spec->flags & GIT_ATTR_FNMATCH_ALLOWSPACE) != 0; + pattern = *base; + slash_count = 0; for (scan = pattern; *scan != '\0'; ++scan) { /* scan until (non-escaped) white space */ @@ -609,6 +635,7 @@ static void git_attr_rule__clear(git_attr_rule *rule) /* match.pattern is stored in a git_pool, so no need to free */ rule->match.pattern = NULL; rule->match.length = 0; + rule->match.flags = 0; } void git_attr_rule__free(git_attr_rule *rule) diff --git a/src/attr_file.h b/src/attr_file.h index d8abcda58..8ca7e4eb7 100644 --- a/src/attr_file.h +++ b/src/attr_file.h @@ -115,7 +115,13 @@ extern uint32_t git_attr_file__name_hash(const char *name); * other utilities */ -extern int git_attr_fnmatch__parse( +extern int git_attr_fnmatch__parse_gitattr_format( + git_attr_fnmatch *spec, + git_pool *pool, + const char *source, + const char **base); + +extern int git_attr_fnmatch__parse_shellglob_format( git_attr_fnmatch *spec, git_pool *pool, const char *source, diff --git a/src/ignore.c b/src/ignore.c index 17779522c..dae974b6e 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -49,7 +49,7 @@ static int parse_ignore_file( match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE; - if (!(error = git_attr_fnmatch__parse( + if (!(error = git_attr_fnmatch__parse_gitattr_format( match, ignores->pool, context, &scan))) { match->flags |= GIT_ATTR_FNMATCH_IGNORE; diff --git a/src/pathspec.c b/src/pathspec.c index d4eb12582..9dee55ea1 100644 --- a/src/pathspec.c +++ b/src/pathspec.c @@ -78,7 +78,7 @@ int git_pathspec_init( match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE; - ret = git_attr_fnmatch__parse(match, strpool, NULL, &pattern); + ret = git_attr_fnmatch__parse_shellglob_format(match, strpool, NULL, &pattern); if (ret == GIT_ENOTFOUND) { git__free(match); continue; diff --git a/tests-clar/status/ignore.c b/tests-clar/status/ignore.c index 2d3898ba4..6c17d2c39 100644 --- a/tests-clar/status/ignore.c +++ b/tests-clar/status/ignore.c @@ -459,3 +459,37 @@ void test_status_ignore__automatically_ignore_bad_files(void) cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/whatever.c")); cl_assert(!ignored); } + +void test_status_ignore__filenames_with_special_prefixes_do_not_interfere_with_status_retrieval(void) +{ + status_entry_single st; + char *test_cases[] = { + "!file", + "#blah", + "[blah]", + "[attr]", + "[attr]blah", + NULL + }; + int i; + + for (i = 0; *(test_cases + i) != NULL; i++) { + git_buf file = GIT_BUF_INIT; + char *file_name = *(test_cases + i); + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_buf_joinpath(&file, "empty_standard_repo", file_name)); + cl_git_mkfile(git_buf_cstr(&file), "Please don't ignore me!"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); + cl_assert(st.count == 1); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&st.status, repo, file_name)); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + cl_git_sandbox_cleanup(); + git_buf_free(&file); + } +} -- cgit v1.2.1 From 2532c903439d3116833146a89221c91a0023c3fe Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 5 Feb 2013 15:01:30 -0800 Subject: Initial blame API --- include/git2.h | 1 + include/git2/blame.h | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 include/git2/blame.h diff --git a/include/git2.h b/include/git2.h index 5f9fc4824..0623a77a7 100644 --- a/include/git2.h +++ b/include/git2.h @@ -56,5 +56,6 @@ #include "git2/message.h" #include "git2/pack.h" #include "git2/stash.h" +#include "git2/blame.h" #endif diff --git a/include/git2/blame.h b/include/git2/blame.h new file mode 100644 index 000000000..871806792 --- /dev/null +++ b/include/git2/blame.h @@ -0,0 +1,145 @@ +/* + * 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_blame_h__ +#define INCLUDE_git_blame_h__ + +#include "common.h" +#include "oid.h" + +/** + * @file git2/blame.h + * @brief Git blame routines + * @defgroup git_blame Git blame routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Flags for indicating option behavior for git_blame APIs. + */ +typedef enum { + /** Normal blame, the default */ + GIT_BLAME_NORMAL = 0, + /** Track lines that have moved within a file (like `git blame -M`) */ + GIT_BLAME_TRACK_COPIES_SAME_FILE = (1<<0), + /** Track lines that have moved across files in the same commit (like `git blame -C`) */ + GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES = (1<<1), + /** Track lines that have been copied from another file that exists in the + * same commit (like `git blame -CC`) */ + GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES = (1<<1 | 1<<2), + /** Track lines that have been copied from another file that exists in *any* + * commit (like `git blame -CCC`) */ + GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<1 | 1<<2 | 1<<3), +} git_blame_flag_t; + +/** + * Blame options structure + * + * Use zeros to indicate default settings. It's easiest to use the + * `GIT_BLAME_OPTIONS_INIT` macro: + * git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + * + * - `flags` is a combination fo teh `git_blame_flag_t` values above. + * - `min_match_characters` is the lower bound on the number of alphanumeric + * characters that must be detected as moving/copying within a file for it to + * associate those lines with the parent commit. The default value is 20. + * This value only takes effect if any of the `GIT_BLAME_TRACK_COPIES_*` + * flags are specified. + * - `newest_commitish` is a rev-parse spec that resolves to the most recent + * commit to consider. The default is HEAD. + * - `oldest_commitish` is a rev-parse spec that resolves to the oldest commit + * to consider. The default is the first commit encountered with a NULL + * parent. + * - `min_line` is the first line in the file to blame. The default is 1 (line + * numbers start with 1). + * - `max_line` is the last line in the file to blame. The default is the last + * line of the file. + */ + +typedef struct git_blame_options { + unsigned int version; + + uint32_t flags; + uint16_t min_match_characters; + const char *newest_commitish; + const char *oldest_commitish; + uint32_t min_line; + uint32_t max_line; +} git_blame_options; + +#define GIT_BLAME_OPTIONS_VERSION 1 +#define GIT_BLAME_OPTIONS_INIT {GIT_BLAME_OPTIONS_VERSION} + +/** + * Structure that represents a blame hunk. + * + * - `lines_in_hunk` is the number of lines in this hunk + * - `final_commit_id` is the OID of the commit where this line was last + * changed. + * - `final_start_line_number` is the 1-based line number where this hunk + * begins, in the final version of the file + * - `orig_commit_id` is the OID of the commit where this hunk was found. This + * will usually be the same as `final_commit_id`, except when + * `GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES` has been specified. + * - `orig_path` is the path to the file where this hunk originated, as of the + * commit specified by `orig_commit_id`. + * - `orig_start_line_number` is the 1-based line number where this hunk begins + * in the file named by `orig_path` in the commit specified by + * `orig_commit_id`. + */ +typedef struct git_blame_hunk { + uint16_t lines_in_hunk; + + git_oid final_commit_id; + uint16_t final_start_line_number; + + git_oid orig_commit_id; + const char *orig_path; + uint16_t orig_start_line_number; +} git_blame_hunk; + + +/** + * Results structure for git_blame. + * + * - `hunks` is an array of hunks. + * - `hunk_count` is the number of hunk structures in `hunks`. + */ +typedef struct git_blame_results { + const git_blame_hunk * const hunks; + uint32_t hunk_count; +} git_blame_results; + +/** + * Get the blame for a single file. + * + * @param out pointer that will receive the results object + * @param path path to file to consider + * @param options options for the blame operation. If NULL, this is treated as + * though GIT_BLAME_OPTIONS_INIT were passed. + * @return 0 on success, or an error code. (use giterr_last for information + * about the error.) + */ +GIT_EXTERN(int) git_blame_file( + git_blame_results **out, + const char *path, + git_blame_options *options); + + +/** + * Free memory allocated by git_blame. + * + * @param results results structure to free + */ +GIT_EXTERN(void) git_blame_free(git_blame_results *results); + +/** @} */ +GIT_END_DECL +#endif + -- cgit v1.2.1 From 168e9d746e906a900c55e2de161d8941baf2a2d2 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 5 Feb 2013 19:24:01 -0800 Subject: Change API based on @arrbee's feedback --- include/git2/blame.h | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/include/git2/blame.h b/include/git2/blame.h index 871806792..1dfff1719 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -51,11 +51,11 @@ typedef enum { * associate those lines with the parent commit. The default value is 20. * This value only takes effect if any of the `GIT_BLAME_TRACK_COPIES_*` * flags are specified. - * - `newest_commitish` is a rev-parse spec that resolves to the most recent + * - `newest_commit` is a rev-parse spec that resolves to the most recent * commit to consider. The default is HEAD. - * - `oldest_commitish` is a rev-parse spec that resolves to the oldest commit - * to consider. The default is the first commit encountered with a NULL - * parent. + * - `newest_commit` is the newest commit to consider. The default is HEAD. + * - `oldest_commit` is the oldest commit to consider. The default is the + * first commit encountered with a NULL parent. * - `min_line` is the first line in the file to blame. The default is 1 (line * numbers start with 1). * - `max_line` is the last line in the file to blame. The default is the last @@ -67,8 +67,8 @@ typedef struct git_blame_options { uint32_t flags; uint16_t min_match_characters; - const char *newest_commitish; - const char *oldest_commitish; + const git_commit *newest_commit; + const git_commit *oldest_commit; uint32_t min_line; uint32_t max_line; } git_blame_options; @@ -105,21 +105,40 @@ typedef struct git_blame_hunk { } git_blame_hunk; +typedef struct git_blame_results git_blame_results; + +/** + * Gets the number of hunks that exist in the results structure. + */ +GIT_EXTERN(uint32_t) git_blame_results_hunk_count(git_blame_results *results); + +/** + * Gets the blame hunk at the given index. + * + * @param results the results structure to query + * @param index index of the hunk to retrieve + * @return the hunk at the given index, or NULL on error + */ +GIT_EXTERN(const git_blame_hunk*) git_blame_results_hunk_byindex( + git_blame_results *results, + uint32_t index); + /** - * Results structure for git_blame. + * Gets the hunk that relates to the given line number in the newest commit. * - * - `hunks` is an array of hunks. - * - `hunk_count` is the number of hunk structures in `hunks`. + * @param results the results structure to query + * @param lineno the (1-based) line number to find a hunk for + * @return the hunk that contains the given line, or NULL on error */ -typedef struct git_blame_results { - const git_blame_hunk * const hunks; - uint32_t hunk_count; -} git_blame_results; +GIT_EXTERN(const git_blame_hunk*) git_blame_results_hunk_byline( + git_blame_results *results, + uint32_t lineno); /** * Get the blame for a single file. * * @param out pointer that will receive the results object + * @param repo repository whose history is to be walked * @param path path to file to consider * @param options options for the blame operation. If NULL, this is treated as * though GIT_BLAME_OPTIONS_INIT were passed. @@ -128,6 +147,7 @@ typedef struct git_blame_results { */ GIT_EXTERN(int) git_blame_file( git_blame_results **out, + git_repository *repo, const char *path, git_blame_options *options); -- cgit v1.2.1 From edcb6ee649b5f18586cfa61252e371fbaa72d090 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 7 Feb 2013 10:33:56 -0800 Subject: Introduce git_blame_buffer --- include/git2/blame.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/git2/blame.h b/include/git2/blame.h index 1dfff1719..7f0fb2617 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -152,6 +152,20 @@ GIT_EXTERN(int) git_blame_file( git_blame_options *options); +/** + * Get blame data for a file that has been modified. + * + * @param out pointer that will receive the results object + * @param reference output from git_blame_file for the file in question + * @param buffer the (possibly) modified contents of the file + * @return 0 on success, or an error code. (use giterr_last for information + * about the error) + */ +GIT_EXTERN(int) git_blame_buffer( + git_blame_results **out, + git_blame_results *reference, + const char *buffer); + /** * Free memory allocated by git_blame. * -- cgit v1.2.1 From 1a68c168a6cdbe0db6e44fb582a7026a7d536c9d Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 7 Feb 2013 19:22:31 -0800 Subject: Fix spelling, remove pesky consts --- include/git2/blame.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/git2/blame.h b/include/git2/blame.h index 7f0fb2617..443b33503 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -45,7 +45,7 @@ typedef enum { * `GIT_BLAME_OPTIONS_INIT` macro: * git_blame_options opts = GIT_BLAME_OPTIONS_INIT; * - * - `flags` is a combination fo teh `git_blame_flag_t` values above. + * - `flags` is a combination of the `git_blame_flag_t` values above. * - `min_match_characters` is the lower bound on the number of alphanumeric * characters that must be detected as moving/copying within a file for it to * associate those lines with the parent commit. The default value is 20. @@ -67,8 +67,8 @@ typedef struct git_blame_options { uint32_t flags; uint16_t min_match_characters; - const git_commit *newest_commit; - const git_commit *oldest_commit; + git_commit *newest_commit; + git_commit *oldest_commit; uint32_t min_line; uint32_t max_line; } git_blame_options; -- cgit v1.2.1 From edbaa63a7c3c319621b773bad5851b2b48c9d175 Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Tue, 25 Jun 2013 09:04:04 +0200 Subject: Unbreak git_remote_ls on a local transport after disconnecting. --- src/transports/local.c | 27 +++++++++++++++------------ tests-clar/network/remote/local.c | 12 ++++++++++++ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/transports/local.c b/src/transports/local.c index 550060958..2a85e95e7 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -119,15 +119,24 @@ on_error: static int store_refs(transport_local *t) { - unsigned int i; + size_t i; + git_remote_head *head; git_strarray ref_names = {0}; assert(t); - if (git_reference_list(&ref_names, t->repo) < 0 || - git_vector_init(&t->refs, ref_names.count, NULL) < 0) + if (git_reference_list(&ref_names, t->repo) < 0) goto on_error; + /* Clear all heads we might have fetched in a previous connect */ + git_vector_foreach(&t->refs, i, head) { + git__free(head->name); + git__free(head); + } + + /* Clear the vector so we can reuse it */ + git_vector_clear(&t->refs); + /* Sort the references first */ git__tsort((void **)ref_names.strings, ref_names.count, &git__strcmp_cb); @@ -571,8 +580,6 @@ static void local_cancel(git_transport *transport) static int local_close(git_transport *transport) { transport_local *t = (transport_local *)transport; - size_t i; - git_remote_head *head; t->connected = 0; @@ -586,13 +593,6 @@ static int local_close(git_transport *transport) t->url = NULL; } - git_vector_foreach(&t->refs, i, head) { - git__free(head->name); - git__free(head); - } - - git_vector_free(&t->refs); - return 0; } @@ -600,6 +600,8 @@ static void local_free(git_transport *transport) { transport_local *t = (transport_local *)transport; + git_vector_free(&t->refs); + /* Close the transport, if it's still open. */ local_close(transport); @@ -632,6 +634,7 @@ int git_transport_local(git_transport **out, git_remote *owner, void *param) t->parent.read_flags = local_read_flags; t->parent.cancel = local_cancel; + git_vector_init(&t->refs, 0, NULL); t->owner = owner; *out = (git_transport *) t; diff --git a/tests-clar/network/remote/local.c b/tests-clar/network/remote/local.c index 3cb8a25d6..d5d75fdc6 100644 --- a/tests-clar/network/remote/local.c +++ b/tests-clar/network/remote/local.c @@ -75,6 +75,18 @@ void test_network_remote_local__retrieve_advertised_references(void) cl_assert_equal_i(how_many_refs, 28); } +void test_network_remote_local__retrieve_advertised_references_after_disconnect(void) +{ + int how_many_refs = 0; + + connect_to_local_repository(cl_fixture("testrepo.git")); + git_remote_disconnect(remote); + + cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs)); + + cl_assert_equal_i(how_many_refs, 28); +} + void test_network_remote_local__retrieve_advertised_references_from_spaced_repository(void) { int how_many_refs = 0; -- cgit v1.2.1 From 9728cfde5f3685cb11302560a67754104d618ea2 Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Tue, 25 Jun 2013 11:17:55 +0300 Subject: Make sure we don't leak memory again. --- src/transports/local.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/transports/local.c b/src/transports/local.c index 2a85e95e7..a9da8146c 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -599,6 +599,13 @@ static int local_close(git_transport *transport) static void local_free(git_transport *transport) { transport_local *t = (transport_local *)transport; + size_t i; + git_remote_head *head; + + git_vector_foreach(&t->refs, i, head) { + git__free(head->name); + git__free(head); + } git_vector_free(&t->refs); -- cgit v1.2.1 From 022a45e0848d4cc517889aaf55573bf5f5004662 Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Tue, 25 Jun 2013 16:43:15 +0200 Subject: Revert "Work around reparse point stat issues" This reverts commit 32c12ea6a9cafd76a746af2e2be9366c95752f5b. --- src/fileops.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index d5f6acfad..1f58fa5cd 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -350,8 +350,7 @@ int git_futils_mkdir( int tmp_errno = errno; /* ignore error if directory already exists */ - if (p_stat(make_path.ptr, &st) < 0 || - !(S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))) { + if (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode)) { errno = tmp_errno; giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr); goto done; -- cgit v1.2.1 From 4753711235b817082460c2781749c27ef2d9bc78 Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Tue, 25 Jun 2013 16:46:06 +0200 Subject: Correctly handle junctions A junction has S_IFDIR | S_IFLNK set, however, only one makes sense. Signed-off-by: Sven Strickroth --- src/win32/posix_w32.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index f04974428..036632e2a 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -90,6 +90,9 @@ static int do_lstat( if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) fMode |= S_IFLNK; + if ((fMode & (S_IFDIR | S_IFLNK)) == (S_IFDIR | S_IFLNK)) // junction + fMode ^= S_IFLNK; + buf->st_ino = 0; buf->st_gid = 0; buf->st_uid = 0; -- cgit v1.2.1 From 3736b64f0520f1fb0c79cf6ef29eeca7507c167c Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Tue, 25 Jun 2013 18:36:37 +0200 Subject: Prefer younger merge bases over older ones. git-core prefers younger merge bases over older ones in case that multiple valid merge bases exists. --- src/commit_list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commit_list.c b/src/commit_list.c index bd5b5201a..64416e54d 100644 --- a/src/commit_list.c +++ b/src/commit_list.c @@ -36,7 +36,7 @@ git_commit_list *git_commit_list_insert_by_date(git_commit_list_node *item, git_ git_commit_list *p; while ((p = *pp) != NULL) { - if (git_commit_list_time_cmp(p->item, item) < 0) + if (git_commit_list_time_cmp(p->item, item) > 0) break; pp = &p->next; -- cgit v1.2.1 From 24ba6d3f8cec2524a3e18157dd9149bbfb654650 Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Tue, 25 Jun 2013 22:55:13 +0200 Subject: Add a test case. --- tests-clar/revwalk/mergebase.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests-clar/revwalk/mergebase.c b/tests-clar/revwalk/mergebase.c index e2617ab0e..a2dbbc738 100644 --- a/tests-clar/revwalk/mergebase.c +++ b/tests-clar/revwalk/mergebase.c @@ -123,6 +123,18 @@ void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void) cl_assert_equal_sz(4, behind); } +void test_revwalk_mergebase__prefer_youngest_merge_base(void) +{ + git_oid result, one, two, expected; + + cl_git_pass(git_oid_fromstr(&one, "a4a7dce85cf63874e984719f4fdd239f5145052f ")); + cl_git_pass(git_oid_fromstr(&two, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); + cl_git_pass(git_oid_fromstr(&expected, "c47800c7266a2be04c571c04d5a6614691ea99bd")); + + cl_git_pass(git_merge_base(&result, _repo, &one, &two)); + cl_assert(git_oid_cmp(&result, &expected) == 0); +} + void test_revwalk_mergebase__no_off_by_one_missing(void) { git_oid result, one, two; -- cgit v1.2.1 From c7974b49d04bc318d61a010d2c5d2e75095f410b Mon Sep 17 00:00:00 2001 From: Justin Spahr-Summers Date: Wed, 26 Jun 2013 12:03:33 -0700 Subject: Fail on unmodified deltas when they're unexpected --- tests-clar/diff/submodules.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index 6e52a6319..46fe6c21c 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -47,7 +47,7 @@ static void check_diff_patches(git_diff_list *diff, const char **expected) for (d = 0; d < num_d; ++d, git_diff_patch_free(patch)) { cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d)); - if (delta->status == GIT_DELTA_UNMODIFIED) + if (delta->status == GIT_DELTA_UNMODIFIED && expected[d] == NULL) continue; if (expected[d] && !strcmp(expected[d], "")) -- cgit v1.2.1 From c67ff958c4d8e37a717c77dd9cdb4bdfc88a6fd8 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 27 Jun 2013 07:38:27 -0700 Subject: Fix bug marking submodule diffs as unmodified There was a bug where submodules whose HEAD had not been moved were being marked as having an UNMODIFIED delta record instead of being left MODIFIED. This fixes that and fixes the tests to notice if a submodule has been incorrectly marked as UNMODIFIED. --- src/diff_patch.c | 6 +++++- tests-clar/diff/submodules.c | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/diff_patch.c b/src/diff_patch.c index 9060d0a24..1b4adac03 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -10,6 +10,7 @@ #include "diff_driver.h" #include "diff_patch.h" #include "diff_xdiff.h" +#include "fileops.h" /* cached information about a single span in a diff */ typedef struct diff_patch_line diff_patch_line; @@ -175,9 +176,12 @@ static int diff_patch_load(git_diff_patch *patch, git_diff_output *output) goto cleanup; } - /* if we were previously missing an oid, update MODIFIED->UNMODIFIED */ + /* if previously missing an oid, and now that we have it the two sides + * are the same (and not submodules), update MODIFIED -> UNMODIFIED + */ if (incomplete_data && patch->ofile.file->mode == patch->nfile.file->mode && + patch->ofile.file->mode != GIT_FILEMODE_COMMIT && git_oid_equal(&patch->ofile.file->oid, &patch->nfile.file->oid) && patch->delta->status == GIT_DELTA_MODIFIED) /* not RENAMED/COPIED! */ patch->delta->status = GIT_DELTA_UNMODIFIED; diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index 46fe6c21c..5de46732b 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -47,8 +47,10 @@ static void check_diff_patches(git_diff_list *diff, const char **expected) for (d = 0; d < num_d; ++d, git_diff_patch_free(patch)) { cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d)); - if (delta->status == GIT_DELTA_UNMODIFIED && expected[d] == NULL) + if (delta->status == GIT_DELTA_UNMODIFIED) { + cl_assert(expected[d] == NULL); continue; + } if (expected[d] && !strcmp(expected[d], "")) continue; -- cgit v1.2.1 From 1e9dd60f141cbe0c0eecf2628f7dd6f67d185b8d Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 27 Jun 2013 22:29:05 -0700 Subject: Test submodules with empty index or orphaned head In both of these cases, the submodule data should still be loaded just (obviously) without the data that comes from either the index or the HEAD. This fixes a bug in the orphaned head case. --- src/submodule.c | 7 +++-- tests-clar/submodule/lookup.c | 71 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/submodule.c b/src/submodule.c index 89eba2aa4..dcd58d016 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -1176,8 +1176,11 @@ static int load_submodule_config_from_head( git_iterator *i; const git_index_entry *entry; - if ((error = git_repository_head_tree(&head, repo)) < 0) - return error; + /* if we can't look up current head, then there's no submodule in it */ + if (git_repository_head_tree(&head, repo) < 0) { + giterr_clear(); + return 0; + } if ((error = git_iterator_for_tree(&i, head, 0, NULL, NULL)) < 0) { git_tree_free(head); diff --git a/tests-clar/submodule/lookup.c b/tests-clar/submodule/lookup.c index acf8f6462..013bbdf96 100644 --- a/tests-clar/submodule/lookup.c +++ b/tests-clar/submodule/lookup.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "submodule_helpers.h" #include "posix.h" +#include "git2/sys/repository.h" static git_repository *g_repo = NULL; @@ -112,3 +113,73 @@ void test_submodule_lookup__foreach(void) cl_git_pass(git_submodule_foreach(g_repo, sm_lookup_cb, &data)); cl_assert_equal_i(8, data.count); } + +void test_submodule_lookup__lookup_even_with_orphaned_head(void) +{ + git_reference *orphan; + git_submodule *sm; + + /* orphan the head */ + cl_git_pass(git_reference_symbolic_create( + &orphan, g_repo, "HEAD", "refs/heads/garbage", 1)); + git_reference_free(orphan); + + /* lookup existing */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_assert(sm); + + /* lookup pending change in .gitmodules that is not in HEAD */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); + cl_assert(sm); + + /* lookup pending change in .gitmodules that is neither in HEAD nor index */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); + cl_assert(sm); + + /* lookup git repo subdir that is not added as submodule */ + cl_assert_equal_i(GIT_EEXISTS, git_submodule_lookup(&sm, g_repo, "not-submodule")); + + /* lookup existing directory that is not a submodule */ + cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_dir")); + + /* lookup existing file that is not a submodule */ + cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_file")); + + /* lookup non-existent item */ + cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "no_such_file")); +} + +void test_submodule_lookup__lookup_even_with_missing_index(void) +{ + git_index *idx; + git_submodule *sm; + + /* give the repo an empty index */ + cl_git_pass(git_index_new(&idx)); + git_repository_set_index(g_repo, idx); + git_index_free(idx); + + /* lookup existing */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_assert(sm); + + /* lookup pending change in .gitmodules that is not in HEAD */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); + cl_assert(sm); + + /* lookup pending change in .gitmodules that is neither in HEAD nor index */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); + cl_assert(sm); + + /* lookup git repo subdir that is not added as submodule */ + cl_assert_equal_i(GIT_EEXISTS, git_submodule_lookup(&sm, g_repo, "not-submodule")); + + /* lookup existing directory that is not a submodule */ + cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_dir")); + + /* lookup existing file that is not a submodule */ + cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_file")); + + /* lookup non-existent item */ + cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "no_such_file")); +} -- cgit v1.2.1 From c4ac556ee7171ee206e11687907d5dbee3ce0a6d Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 29 Jun 2013 12:48:58 +0200 Subject: Fix compilation warnings --- src/diff_tform.c | 2 +- src/thread-utils.h | 2 +- src/win32/findfile.c | 8 +++----- tests-clar/clar/sandbox.h | 2 +- tests-clar/diff/rename.c | 2 +- tests-clar/merge/trees/automerge.c | 2 +- 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/diff_tform.c b/src/diff_tform.c index 8c4e96ecf..b137bd319 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -900,7 +900,7 @@ find_best_matches: } /* otherwise, if we just overwrote a source, update mapping */ else if (j > i && match_srcs[i].similarity > 0) { - match_tgts[match_srcs[i].idx].idx = j; + match_tgts[match_srcs[i].idx].idx = (uint32_t)j; } num_updates++; diff --git a/src/thread-utils.h b/src/thread-utils.h index 83148188d..f19a2ba2c 100644 --- a/src/thread-utils.h +++ b/src/thread-utils.h @@ -104,7 +104,7 @@ GIT_INLINE(void *) git___compare_and_swap( { volatile void *foundval; #if defined(GIT_WIN32) - foundval = InterlockedCompareExchangePointer(ptr, newval, oldval); + foundval = InterlockedCompareExchangePointer((volatile PVOID *)ptr, newval, oldval); #elif defined(__GNUC__) foundval = __sync_val_compare_and_swap(ptr, oldval, newval); #else diff --git a/src/win32/findfile.c b/src/win32/findfile.c index 5dd3de13d..9d9051bff 100644 --- a/src/win32/findfile.c +++ b/src/win32/findfile.c @@ -156,7 +156,7 @@ static int win32_find_git_in_registry( } static int win32_find_existing_dirs( - git_buf *out, const wchar_t *tmpl[], char *temp[]) + git_buf *out, const wchar_t *tmpl[]) { struct git_win32__path path16; git_buf buf = GIT_BUF_INIT; @@ -209,7 +209,6 @@ int git_win32__find_system_dirs(git_buf *out) int git_win32__find_global_dirs(git_buf *out) { - char *temp[3]; static const wchar_t *global_tmpls[4] = { L"%HOME%\\", L"%HOMEDRIVE%%HOMEPATH%\\", @@ -217,12 +216,11 @@ int git_win32__find_global_dirs(git_buf *out) NULL, }; - return win32_find_existing_dirs(out, global_tmpls, temp); + return win32_find_existing_dirs(out, global_tmpls); } int git_win32__find_xdg_dirs(git_buf *out) { - char *temp[6]; static const wchar_t *global_tmpls[7] = { L"%XDG_CONFIG_HOME%\\git", L"%APPDATA%\\git", @@ -233,5 +231,5 @@ int git_win32__find_xdg_dirs(git_buf *out) NULL, }; - return win32_find_existing_dirs(out, global_tmpls, temp); + return win32_find_existing_dirs(out, global_tmpls); } diff --git a/tests-clar/clar/sandbox.h b/tests-clar/clar/sandbox.h index 1ca6fcae8..5622bfab7 100644 --- a/tests-clar/clar/sandbox.h +++ b/tests-clar/clar/sandbox.h @@ -45,7 +45,7 @@ find_tmp_path(char *buffer, size_t length) #else DWORD env_len; - if ((env_len = GetEnvironmentVariable("CLAR_TMP", buffer, length)) > 0 && + if ((env_len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length)) > 0 && env_len < length) return 0; diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index 2b1873bd5..9efd9281c 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -516,7 +516,7 @@ void test_diff_rename__working_directory_changes(void) cl_git_pass(git_oid_fromstr(&id, blobsha)); cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); cl_git_pass(git_buf_set( - &content, git_blob_rawcontent(blob), git_blob_rawsize(blob))); + &content, git_blob_rawcontent(blob), (size_t)git_blob_rawsize(blob))); cl_git_rewritefile("renames/songof7cities.txt", content.ptr); git_blob_free(blob); diff --git a/tests-clar/merge/trees/automerge.c b/tests-clar/merge/trees/automerge.c index 04a7beff6..746ce5068 100644 --- a/tests-clar/merge/trees/automerge.c +++ b/tests-clar/merge/trees/automerge.c @@ -122,7 +122,7 @@ void test_merge_trees_automerge__automerge(void) cl_assert(entry->file_size == strlen(AUTOMERGEABLE_MERGED_FILE)); cl_git_pass(git_object_lookup((git_object **)&blob, repo, &entry->oid, GIT_OBJ_BLOB)); - cl_assert(memcmp(git_blob_rawcontent(blob), AUTOMERGEABLE_MERGED_FILE, entry->file_size) == 0); + cl_assert(memcmp(git_blob_rawcontent(blob), AUTOMERGEABLE_MERGED_FILE, (size_t)entry->file_size) == 0); git_index_free(index); git_blob_free(blob); -- cgit v1.2.1 From d90390c162418deb62302b3f56835ff781c0cfee Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 29 Jun 2013 13:38:27 +0200 Subject: test: Fix memory leak --- tests-clar/checkout/index.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests-clar/checkout/index.c b/tests-clar/checkout/index.c index 9d8b321ae..982bf9ee5 100644 --- a/tests-clar/checkout/index.c +++ b/tests-clar/checkout/index.c @@ -587,6 +587,8 @@ void test_checkout_index__target_directory_from_bare(void) cl_git_pass(git_futils_rmdir_r( "alternative", NULL, GIT_RMDIR_REMOVE_FILES)); + + git_object_free(head); } void test_checkout_index__can_get_repo_from_index(void) -- cgit v1.2.1 From 0b170f4dcb7f9e47eb849035a505661dda2eb6f8 Mon Sep 17 00:00:00 2001 From: Andrej Mitrovic Date: Mon, 1 Jul 2013 00:56:54 +0200 Subject: Fix docs to use proper enum names that exist. --- include/git2/refs.h | 14 +++++++------- include/git2/repository.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/git2/refs.h b/include/git2/refs.h index 795f7ab27..205bfe59d 100644 --- a/include/git2/refs.h +++ b/include/git2/refs.h @@ -32,7 +32,7 @@ GIT_BEGIN_DECL * @param out pointer to the looked-up reference * @param repo the repository to look up the reference * @param name the long name for the reference (e.g. HEAD, refs/heads/master, refs/tags/v0.1.0, ...) - * @return 0 on success, ENOTFOUND, EINVALIDSPEC or an error code. + * @return 0 on success, GIT_ENOTFOUND, GIT_EINVALIDSPEC or an error code. */ GIT_EXTERN(int) git_reference_lookup(git_reference **out, git_repository *repo, const char *name); @@ -49,7 +49,7 @@ GIT_EXTERN(int) git_reference_lookup(git_reference **out, git_repository *repo, * @param out Pointer to oid to be filled in * @param repo The repository in which to look up the reference * @param name The long name for the reference (e.g. HEAD, refs/heads/master, refs/tags/v0.1.0, ...) - * @return 0 on success, ENOTFOUND, EINVALIDSPEC or an error code. + * @return 0 on success, GIT_ENOTFOUND, GIT_EINVALIDSPEC or an error code. */ GIT_EXTERN(int) git_reference_name_to_id( git_oid *out, git_repository *repo, const char *name); @@ -94,7 +94,7 @@ GIT_EXTERN(int) git_reference_dwim(git_reference **out, git_repository *repo, co * @param name The name of the reference * @param target The target of the reference * @param force Overwrite existing references - * @return 0 on success, EEXISTS, EINVALIDSPEC or an error code + * @return 0 on success, GIT_EEXISTS, GIT_EINVALIDSPEC or an error code */ GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repository *repo, const char *name, const char *target, int force); @@ -126,7 +126,7 @@ GIT_EXTERN(int) git_reference_symbolic_create(git_reference **out, git_repositor * @param name The name of the reference * @param id The object id pointed to by the reference. * @param force Overwrite existing references - * @return 0 on success, EEXISTS, EINVALIDSPEC or an error code + * @return 0 on success, GIT_EEXISTS, GIT_EINVALIDSPEC or an error code */ GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo, const char *name, const git_oid *id, int force); @@ -225,7 +225,7 @@ GIT_EXTERN(git_repository *) git_reference_owner(const git_reference *ref); * @param out Pointer to the newly created reference * @param ref The reference * @param target The new target for the reference - * @return 0 on success, EINVALIDSPEC or an error code + * @return 0 on success, GIT_EINVALIDSPEC or an error code */ GIT_EXTERN(int) git_reference_symbolic_set_target( git_reference **out, @@ -268,7 +268,7 @@ GIT_EXTERN(int) git_reference_set_target( * @param ref The reference to rename * @param new_name The new name for the reference * @param force Overwrite an existing reference - * @return 0 on success, EINVALIDSPEC, EEXISTS or an error code + * @return 0 on success, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code * */ GIT_EXTERN(int) git_reference_rename( @@ -488,7 +488,7 @@ typedef enum { * @param name Reference name to be checked. * @param flags Flags to constrain name validation rules - see the * GIT_REF_FORMAT constants above. - * @return 0 on success, GIT_EBUFS if buffer is too small, EINVALIDSPEC + * @return 0 on success, GIT_EBUFS if buffer is too small, GIT_EINVALIDSPEC * or an error code. */ GIT_EXTERN(int) git_reference_normalize_name( diff --git a/include/git2/repository.h b/include/git2/repository.h index 2164cfac1..7cc4a1341 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -178,7 +178,7 @@ GIT_EXTERN(int) git_repository_init( * when initializing a new repo. Details of individual values are: * * * BARE - Create a bare repository with no working directory. - * * NO_REINIT - Return an EEXISTS error if the repo_path appears to + * * NO_REINIT - Return an GIT_EEXISTS error if the repo_path appears to * already be an git repository. * * NO_DOTGIT_DIR - Normally a "/.git/" will be appended to the repo * path for non-bare repos (if it is not already there), but @@ -601,7 +601,7 @@ GIT_EXTERN(int) git_repository_set_head_detached( * If the HEAD is already detached and points to a Tag, the HEAD is * updated into making it point to the peeled Commit, and 0 is returned. * - * If the HEAD is already detached and points to a non commitish, the HEAD is + * If the HEAD is already detached and points to a non commitish, the HEAD is * unaltered, and -1 is returned. * * Otherwise, the HEAD will be detached and point to the peeled Commit. -- cgit v1.2.1 From 278ce7468d3870bb18d69bd8177bae406d6cede4 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 1 Jul 2013 10:20:38 -0700 Subject: Add helpful buffer shorten function --- src/buffer.c | 9 +++++++++ src/buffer.h | 1 + src/config_file.c | 2 +- src/indexer.c | 2 +- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 6e3ffe560..b5b2fd678 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -259,6 +259,15 @@ void git_buf_truncate(git_buf *buf, size_t len) } } +void git_buf_shorten(git_buf *buf, size_t amount) +{ + if (amount > buf->size) + amount = buf->size; + + buf->size = buf->size - amount; + buf->ptr[buf->size] = '\0'; +} + void git_buf_rtruncate_at_char(git_buf *buf, char separator) { ssize_t idx = git_buf_rfind_next(buf, separator); diff --git a/src/buffer.h b/src/buffer.h index 5402f3827..f3e1d506f 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -91,6 +91,7 @@ int git_buf_vprintf(git_buf *buf, const char *format, va_list ap); void git_buf_clear(git_buf *buf); void git_buf_consume(git_buf *buf, const char *end); void git_buf_truncate(git_buf *buf, size_t len); +void git_buf_shorten(git_buf *buf, size_t amount); void git_buf_rtruncate_at_char(git_buf *path, char separator); int git_buf_join_n(git_buf *buf, char separator, int nbuf, ...); diff --git a/src/config_file.c b/src/config_file.c index dec952115..2b0732a13 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -1395,7 +1395,7 @@ static int parse_multiline_variable(diskfile_backend *cfg, git_buf *value, int i * standard, this character **has** to be last one in the buf, with * no whitespace after it */ assert(is_multiline_var(value->ptr)); - git_buf_truncate(value, git_buf_len(value) - 1); + git_buf_shorten(value, 1); proc_line = fixup_line(line, in_quotes); if (proc_line == NULL) { diff --git a/src/indexer.c b/src/indexer.c index 1b5339f23..1b638cd8a 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -602,7 +602,7 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * git_vector_sort(&idx->objects); git_buf_sets(&filename, idx->pack->pack_name); - git_buf_truncate(&filename, filename.size - strlen("pack")); + git_buf_shorten(&filename, strlen("pack")); git_buf_puts(&filename, "idx"); if (git_buf_oom(&filename)) return -1; -- cgit v1.2.1 From 55ededfd398b783fa4fbe54b8aa406c19228fbc6 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 1 Jul 2013 10:21:14 -0700 Subject: Make refspec_transform paranoid about arguments --- src/clone.c | 4 ++-- src/refspec.c | 34 ++++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/clone.c b/src/clone.c index 5b6c6f77d..5c11872cc 100644 --- a/src/clone.c +++ b/src/clone.c @@ -204,7 +204,7 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote) /* Get the remote's HEAD. This is always the first ref in remote->refs. */ remote_head = NULL; - + if (!remote->transport->ls(remote->transport, get_head_callback, &remote_head)) return -1; @@ -220,7 +220,7 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote) memset(&dummy_spec, 0, sizeof(git_refspec)); head_info.refspec = &dummy_spec; } - + /* Determine the remote tracking reference name from the local master */ if (git_refspec_transform_r( &remote_master_name, diff --git a/src/refspec.c b/src/refspec.c index a907df84c..492c6ed3f 100644 --- a/src/refspec.c +++ b/src/refspec.c @@ -225,25 +225,31 @@ int git_refspec_rtransform(char *out, size_t outlen, const git_refspec *spec, co return refspec_transform_internal(out, outlen, spec->dst, spec->src, name); } -static int refspec_transform(git_buf *out, const char *from, const char *to, const char *name) +static int refspec_transform( + git_buf *out, const char *from, const char *to, const char *name) { - if (git_buf_sets(out, to) < 0) - return -1; + size_t to_len = to ? strlen(to) : 0; + size_t from_len = from ? strlen(from) : 0; + size_t name_len = name ? strlen(name) : 0; - /* - * No '*' at the end means that it's mapped to one specific - * branch, so no actual transformation is needed. - */ - if (git_buf_len(out) > 0 && out->ptr[git_buf_len(out) - 1] != '*') - return 0; + if (git_buf_set(out, to, to_len) < 0) + return -1; - git_buf_truncate(out, git_buf_len(out) - 1); /* remove trailing '*' */ - git_buf_puts(out, name + strlen(from) - 1); + if (to_len > 0) { + /* No '*' at the end of 'to' means that refspec is mapped to one + * specific branch, so no actual transformation is needed. + */ + if (out->ptr[to_len - 1] != '*') + return 0; + git_buf_shorten(out, 1); /* remove trailing '*' copied from 'to' */ + } - if (git_buf_oom(out)) - return -1; + if (from_len > 0) /* ignore trailing '*' from 'from' */ + from_len--; + if (from_len > name_len) + from_len = name_len; - return 0; + return git_buf_put(out, name + from_len, name_len - from_len); } int git_refspec_transform_r(git_buf *out, const git_refspec *spec, const char *name) -- cgit v1.2.1 From f8ccd6c935f12c9c31754d22ba81352178980284 Mon Sep 17 00:00:00 2001 From: Andrej Mitrovic Date: Tue, 2 Jul 2013 20:23:54 +0200 Subject: Fix small typo in docs for git_repository_message. --- include/git2/repository.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/git2/repository.h b/include/git2/repository.h index 7cc4a1341..c81051969 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -471,7 +471,7 @@ GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo); * @param out Buffer to write data into or NULL to just read required size * @param len Length of `out` buffer in bytes * @param repo Repository to read prepared message from - * @return GIT_ENOUTFOUND if no message exists, other value < 0 for other + * @return GIT_ENOTFOUND if no message exists, other value < 0 for other * errors, or total bytes in message (may be > `len`) on success */ GIT_EXTERN(int) git_repository_message(char *out, size_t len, git_repository *repo); -- cgit v1.2.1 From 9b6075b25fb6fef570dd29c2b797db8bc34cf0b1 Mon Sep 17 00:00:00 2001 From: yorah Date: Wed, 3 Jul 2013 17:07:20 +0200 Subject: Fix segfault in git_status_foreach_ext() Add tests for the `GIT_STATUS_SHOW_XXX` flags. --- src/diff.c | 2 +- src/status.c | 12 ++-- tests-clar/status/status_data.h | 127 ++++++++++++++++++++++++++++++++++++++++ tests-clar/status/worktree.c | 48 +++++++++++++++ 4 files changed, 183 insertions(+), 6 deletions(-) diff --git a/src/diff.c b/src/diff.c index 26e117402..9e9528ef9 100644 --- a/src/diff.c +++ b/src/diff.c @@ -1273,7 +1273,7 @@ int git_diff__paired_foreach( git_vector_sort(&idx2wd->deltas); } } - else if (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) + else if (head2idx != NULL && head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) strcomp = git__strcasecmp; for (i = 0, j = 0; i < i_max || j < j_max; ) { diff --git a/src/status.c b/src/status.c index e520c1017..7da94edc1 100644 --- a/src/status.c +++ b/src/status.c @@ -257,6 +257,7 @@ int git_status_list_new( opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR; int error = 0; unsigned int flags = opts ? opts->flags : GIT_STATUS_OPT_DEFAULTS; + git_diff_list *head2idx = NULL; assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR); @@ -307,8 +308,10 @@ int git_status_list_new( &status->head2idx, repo, head, NULL, &diffopt)) < 0) goto done; + head2idx = status->head2idx; + if ((flags & GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX) != 0 && - (error = git_diff_find_similar(status->head2idx, NULL)) < 0) + (error = git_diff_find_similar(head2idx, NULL)) < 0) goto done; } @@ -324,15 +327,14 @@ int git_status_list_new( if (show == GIT_STATUS_SHOW_INDEX_THEN_WORKDIR) { if ((error = git_diff__paired_foreach( - status->head2idx, NULL, status_collect, status)) < 0) + head2idx, NULL, status_collect, status)) < 0) goto done; - git_diff_list_free(status->head2idx); - status->head2idx = NULL; + head2idx = NULL; } if ((error = git_diff__paired_foreach( - status->head2idx, status->idx2wd, status_collect, status)) < 0) + head2idx, status->idx2wd, status_collect, status)) < 0) goto done; if (flags & GIT_STATUS_OPT_SORT_CASE_SENSITIVELY) diff --git a/tests-clar/status/status_data.h b/tests-clar/status/status_data.h index a41bde7c2..27587843b 100644 --- a/tests-clar/status/status_data.h +++ b/tests-clar/status/status_data.h @@ -250,3 +250,130 @@ static const unsigned int entry_statuses4[] = { }; static const int entry_count4 = 23; + + +/* entries for a copy of tests/resources/status with options + * passed to the status call in order to only get the differences + * between the HEAD and the index (changes to be committed) + */ + +static const char *entry_paths5[] = { + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", +}; + +static const unsigned int entry_statuses5[] = { + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_NEW, +}; + +static const int entry_count5 = 8; + + +/* entries for a copy of tests/resources/status with options + * passed to the status call in order to only get the differences + * between the workdir and the index (changes not staged, untracked files) + */ + +static const char *entry_paths6[] = { + "file_deleted", + "ignored_file", + "modified_file", + "new_file", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_modified_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "subdir/deleted_file", + "subdir/modified_file", + "subdir/new_file", + "\xe8\xbf\x99", +}; + +static const unsigned int entry_statuses6[] = { + GIT_STATUS_WT_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, +}; + +static const int entry_count6 = 13; + + +/* entries for a copy of tests/resources/status with options + * passed to the status call in order to get the differences + * between the HEAD and the index and then between the workdir + * and the index. + */ + +static const char *entry_paths7[] = { + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "file_deleted", + "ignored_file", + "modified_file", + "new_file", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_modified_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "subdir/deleted_file", + "subdir/modified_file", + "subdir/new_file", + "\xe8\xbf\x99", +}; + +static const unsigned int entry_statuses7[] = { + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, +}; + +static const int entry_count7 = 21; diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index 920671e13..ac993767a 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -40,6 +40,54 @@ void test_status_worktree__whole_repository(void) cl_assert_equal_i(0, counts.wrong_sorted_path); } +void assert_show(const int entry_counts, const char *entry_paths[], + const unsigned int entry_statuses[], git_status_show_t show) +{ + status_entry_counts counts; + git_repository *repo = cl_git_sandbox_init("status"); + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = entry_counts; + counts.expected_paths = entry_paths; + counts.expected_statuses = entry_statuses; + + opts.flags = GIT_STATUS_OPT_DEFAULTS; + opts.show = show; + + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) + ); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +void test_status_worktree__show_index_and_workdir(void) +{ + assert_show(entry_count0, entry_paths0, entry_statuses0, + GIT_STATUS_SHOW_INDEX_AND_WORKDIR); +} + +void test_status_worktree__show_index_only(void) +{ + assert_show(entry_count5, entry_paths5, entry_statuses5, + GIT_STATUS_SHOW_INDEX_ONLY); +} + +void test_status_worktree__show_workdir_only(void) +{ + assert_show(entry_count6, entry_paths6, entry_statuses6, + GIT_STATUS_SHOW_WORKDIR_ONLY); +} + +void test_status_worktree__show_index_then_workdir_only(void) +{ + assert_show(entry_count7, entry_paths7, entry_statuses7, + GIT_STATUS_SHOW_INDEX_THEN_WORKDIR); +} + /* this test is equivalent to t18-status.c:statuscb1 */ void test_status_worktree__empty_repository(void) { -- cgit v1.2.1 From 178aa39cc297cb2d1750bcff0a3839c6ac0840a7 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 3 Jul 2013 11:42:43 -0700 Subject: Be more thread aware with some index updates The index isn't really thread safe for the most part, but we can easily be more careful and avoid double frees and the like, which are serious problems (as opposed to a lookup which might return the incorrect value but if the index in being updated, that is much harder to avoid). --- src/index.c | 74 ++++++++++++++++++++++++++++--------------------------------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/src/index.c b/src/index.c index 1d46779bf..ffa84e53f 100644 --- a/src/index.c +++ b/src/index.c @@ -261,6 +261,22 @@ static int reuc_icmp(const void *a, const void *b) return strcasecmp(info_a->path, info_b->path); } +static void index_entry_reuc_free(git_index_reuc_entry *reuc) +{ + if (!reuc) + return; + git__free(reuc->path); + git__free(reuc); +} + +static void index_entry_free(git_index_entry *entry) +{ + if (!entry) + return; + git__free(entry->path); + git__free(entry); +} + static unsigned int index_create_mode(unsigned int mode) { if (S_ISLNK(mode)) @@ -367,11 +383,8 @@ static void index_entries_free(git_vector *entries) { size_t i; - for (i = 0; i < entries->length; ++i) { - git_index_entry *e = git_vector_get(entries, i); - git__free(e->path); - git__free(e); - } + for (i = 0; i < entries->length; ++i) + index_entry_free(git__swap(entries->contents[i], NULL)); git_vector_clear(entries); } @@ -670,15 +683,6 @@ static int index_entry_reuc_init(git_index_reuc_entry **reuc_out, return 0; } -static void index_entry_reuc_free(git_index_reuc_entry *reuc) -{ - if (!reuc) - return; - - git__free(reuc->path); - git__free(reuc); -} - static git_index_entry *index_entry_dup(const git_index_entry *source_entry) { git_index_entry *entry; @@ -697,14 +701,6 @@ static git_index_entry *index_entry_dup(const git_index_entry *source_entry) return entry; } -static void index_entry_free(git_index_entry *entry) -{ - if (!entry) - return; - git__free(entry->path); - git__free(entry); -} - static int index_insert(git_index *index, git_index_entry *entry, int replace) { size_t path_length, position; @@ -1357,14 +1353,11 @@ int git_index_reuc_remove(git_index *index, size_t position) void git_index_reuc_clear(git_index *index) { size_t i; - git_index_reuc_entry *reuc; assert(index); - git_vector_foreach(&index->reuc, i, reuc) { - git__free(reuc->path); - git__free(reuc); - } + for (i = 0; i < index->reuc.length; ++i) + index_entry_reuc_free(git__swap(index->reuc.contents[i], NULL)); git_vector_clear(&index->reuc); } @@ -1958,8 +1951,9 @@ int git_index_entry_stage(const git_index_entry *entry) } typedef struct read_tree_data { - git_index *index; git_vector *old_entries; + git_vector *new_entries; + git_vector_cmp entries_search; } read_tree_data; static int read_tree_cb( @@ -1990,7 +1984,7 @@ static int read_tree_cb( skey.stage = 0; if (!git_vector_bsearch2( - &pos, data->old_entries, data->index->entries_search, &skey) && + &pos, data->old_entries, data->entries_search, &skey) && (old_entry = git_vector_get(data->old_entries, pos)) != NULL && entry->mode == old_entry->mode && git_oid_equal(&entry->oid, &old_entry->oid)) @@ -2008,7 +2002,7 @@ static int read_tree_cb( entry->path = git_buf_detach(&path); git_buf_free(&path); - if (git_vector_insert(&data->index->entries, entry) < 0) { + if (git_vector_insert(data->new_entries, entry) < 0) { index_entry_free(entry); return -1; } @@ -2022,22 +2016,22 @@ int git_index_read_tree(git_index *index, const git_tree *tree) git_vector entries = GIT_VECTOR_INIT; read_tree_data data; - git_vector_sort(&index->entries); - - git_vector_set_cmp(&entries, index->entries._cmp); - git_vector_swap(&entries, &index->entries); + git_vector_set_cmp(&entries, index->entries._cmp); /* match sort */ - git_index_clear(index); + data.old_entries = &index->entries; + data.new_entries = &entries; + data.entries_search = index->entries_search; - data.index = index; - data.old_entries = &entries; + git_vector_sort(&index->entries); error = git_tree_walk(tree, GIT_TREEWALK_POST, read_tree_cb, &data); - index_entries_free(&entries); - git_vector_free(&entries); + git_vector_sort(&entries); - git_vector_sort(&index->entries); + git_index_clear(index); + + git_vector_swap(&entries, &index->entries); + git_vector_free(&entries); return error; } -- cgit v1.2.1 From 2a16914c35fe52785959647666da145be354b12f Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 3 Jul 2013 12:20:34 -0700 Subject: Remove GIT_STATUS_SHOW_INDEX_THEN_WORKDIR option This option serves no benefit now that the git_status_list API is available. It was of questionable value before and now it would just be a bad idea to use it rather than the indexed API. --- include/git2/status.h | 15 +++++------ src/diff.c | 2 ++ src/status.c | 17 +++--------- tests-clar/status/status_data.h | 57 ----------------------------------------- tests-clar/status/worktree.c | 6 ----- 5 files changed, 12 insertions(+), 85 deletions(-) diff --git a/include/git2/status.h b/include/git2/status.h index 63aea2f3b..fd0e83104 100644 --- a/include/git2/status.h +++ b/include/git2/status.h @@ -60,25 +60,24 @@ typedef int (*git_status_cb)( const char *path, unsigned int status_flags, void *payload); /** - * For extended status, select the files on which to report status. + * Select the files on which to report status. + * + * With `git_status_foreach_ext`, this will control which changes get + * callbacks. With `git_status_list_new`, these will control which + * changes are included in the list. * * - GIT_STATUS_SHOW_INDEX_AND_WORKDIR is the default. This roughly - * matches `git status --porcelain` where each file gets a callback - * indicating its status in the index and in the working directory. + * matches `git status --porcelain` regarding which files are + * included and in what order. * - GIT_STATUS_SHOW_INDEX_ONLY only gives status based on HEAD to index * comparison, not looking at working directory changes. * - GIT_STATUS_SHOW_WORKDIR_ONLY only gives status based on index to * working directory comparison, not comparing the index to the HEAD. - * - GIT_STATUS_SHOW_INDEX_THEN_WORKDIR runs index-only then workdir-only, - * issuing (up to) two callbacks per file (first index, then workdir). - * This is slightly more efficient than separate calls and can make it - * easier to emulate plain `git status` text output. */ typedef enum { GIT_STATUS_SHOW_INDEX_AND_WORKDIR = 0, GIT_STATUS_SHOW_INDEX_ONLY = 1, GIT_STATUS_SHOW_WORKDIR_ONLY = 2, - GIT_STATUS_SHOW_INDEX_THEN_WORKDIR = 3, } git_status_show_t; /** diff --git a/src/diff.c b/src/diff.c index 9e9528ef9..0980f412a 100644 --- a/src/diff.c +++ b/src/diff.c @@ -1249,6 +1249,8 @@ int git_diff__paired_foreach( i_max = head2idx ? head2idx->deltas.length : 0; j_max = idx2wd ? idx2wd->deltas.length : 0; + if (!i_max && !j_max) + return 0; /* At some point, tree-to-index diffs will probably never ignore case, * even if that isn't true now. Index-to-workdir diffs may or may not diff --git a/src/status.c b/src/status.c index 7da94edc1..ccb8d37da 100644 --- a/src/status.c +++ b/src/status.c @@ -257,9 +257,8 @@ int git_status_list_new( opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR; int error = 0; unsigned int flags = opts ? opts->flags : GIT_STATUS_OPT_DEFAULTS; - git_diff_list *head2idx = NULL; - assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR); + assert(show <= GIT_STATUS_SHOW_WORKDIR_ONLY); *out = NULL; @@ -308,10 +307,8 @@ int git_status_list_new( &status->head2idx, repo, head, NULL, &diffopt)) < 0) goto done; - head2idx = status->head2idx; - if ((flags & GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX) != 0 && - (error = git_diff_find_similar(head2idx, NULL)) < 0) + (error = git_diff_find_similar(status->head2idx, NULL)) < 0) goto done; } @@ -325,16 +322,8 @@ int git_status_list_new( goto done; } - if (show == GIT_STATUS_SHOW_INDEX_THEN_WORKDIR) { - if ((error = git_diff__paired_foreach( - head2idx, NULL, status_collect, status)) < 0) - goto done; - - head2idx = NULL; - } - if ((error = git_diff__paired_foreach( - head2idx, status->idx2wd, status_collect, status)) < 0) + status->head2idx, status->idx2wd, status_collect, status)) < 0) goto done; if (flags & GIT_STATUS_OPT_SORT_CASE_SENSITIVELY) diff --git a/tests-clar/status/status_data.h b/tests-clar/status/status_data.h index 27587843b..3efa934ea 100644 --- a/tests-clar/status/status_data.h +++ b/tests-clar/status/status_data.h @@ -320,60 +320,3 @@ static const unsigned int entry_statuses6[] = { }; static const int entry_count6 = 13; - - -/* entries for a copy of tests/resources/status with options - * passed to the status call in order to get the differences - * between the HEAD and the index and then between the workdir - * and the index. - */ - -static const char *entry_paths7[] = { - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_file_deleted", - "staged_delete_modified_file", - "staged_new_file", - "staged_new_file_deleted_file", - "staged_new_file_modified_file", - "file_deleted", - "ignored_file", - "modified_file", - "new_file", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_modified_file", - "staged_new_file_deleted_file", - "staged_new_file_modified_file", - "subdir/deleted_file", - "subdir/modified_file", - "subdir/new_file", - "\xe8\xbf\x99", -}; - -static const unsigned int entry_statuses7[] = { - GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_IGNORED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, -}; - -static const int entry_count7 = 21; diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index ac993767a..0e315cd60 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -82,12 +82,6 @@ void test_status_worktree__show_workdir_only(void) GIT_STATUS_SHOW_WORKDIR_ONLY); } -void test_status_worktree__show_index_then_workdir_only(void) -{ - assert_show(entry_count7, entry_paths7, entry_statuses7, - GIT_STATUS_SHOW_INDEX_THEN_WORKDIR); -} - /* this test is equivalent to t18-status.c:statuscb1 */ void test_status_worktree__empty_repository(void) { -- cgit v1.2.1 From 219f318c051a37c05dd66687695ebec9f1a90e53 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Wed, 3 Jul 2013 22:02:29 +0200 Subject: Fix a crash if git_remote_set_cred_acquire_cb wasn't called before connecting. Fixes #1700. --- src/transports/ssh.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/transports/ssh.c b/src/transports/ssh.c index a312c8d08..8e3657dde 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -345,14 +345,16 @@ static int _git_ssh_setup_conn( if (user && pass) { if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0) goto on_error; - } else { + } else if (t->owner->cred_acquire_cb) { if (t->owner->cred_acquire_cb(&t->cred, t->owner->url, user, GIT_CREDTYPE_USERPASS_PLAINTEXT | GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE, t->owner->cred_acquire_payload) < 0) return -1; - } + } else { + goto on_error; + } assert(t->cred); if (!user) { -- cgit v1.2.1 From f6bd0863352f70905b3068284f8ccd6beaa9a590 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Wed, 3 Jul 2013 22:02:44 +0200 Subject: Fix a probable leak. --- src/transports/ssh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 8e3657dde..f2480b2cd 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -351,7 +351,7 @@ static int _git_ssh_setup_conn( user, GIT_CREDTYPE_USERPASS_PLAINTEXT | GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE, t->owner->cred_acquire_payload) < 0) - return -1; + goto on_error; } else { goto on_error; } -- cgit v1.2.1 From a5f9b5f8d8c2dbcd1bec92065e5df7bae76d3c7c Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 5 Jul 2013 16:59:38 -0700 Subject: Diff hunk context off by one on long lines The diff hunk context string that is returned to xdiff need not be NUL terminated because the xdiff code just copies the number of bytes that you report directly into the output. There was an off by one in the diff driver code when the header context was longer than the output buffer size, the output buffer length included the NUL byte which was copied into the hunk header. Fixes #1710 --- src/diff_driver.c | 7 ++++--- tests-clar/diff/diff_helpers.c | 5 +++-- tests-clar/diff/drivers.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/diff_driver.c b/src/diff_driver.c index 469be0d14..77b0e9f3e 100644 --- a/src/diff_driver.c +++ b/src/diff_driver.c @@ -373,10 +373,11 @@ static long diff_context_find( !ctxt->match_line(ctxt->driver, ctxt->line.ptr, ctxt->line.size)) return -1; - git_buf_truncate(&ctxt->line, (size_t)out_size); - git_buf_copy_cstr(out, (size_t)out_size, &ctxt->line); + if (out_size > (long)ctxt->line.size) + out_size = ctxt->line.size; + memcpy(out, ctxt->line.ptr, (size_t)out_size); - return (long)ctxt->line.size; + return out_size; } void git_diff_find_context_init( diff --git a/tests-clar/diff/diff_helpers.c b/tests-clar/diff/diff_helpers.c index 4e23792a6..a5c322b4d 100644 --- a/tests-clar/diff/diff_helpers.c +++ b/tests-clar/diff/diff_helpers.c @@ -70,8 +70,9 @@ int diff_hunk_cb( diff_expects *e = payload; GIT_UNUSED(delta); - GIT_UNUSED(header); - GIT_UNUSED(header_len); + + /* confirm no NUL bytes in header text */ + while (header_len--) cl_assert('\0' != *header++); e->hunks++; e->hunk_old_lines += range->old_lines; diff --git a/tests-clar/diff/drivers.c b/tests-clar/diff/drivers.c index 06ab2ff14..e02dd5c68 100644 --- a/tests-clar/diff/drivers.c +++ b/tests-clar/diff/drivers.c @@ -123,3 +123,34 @@ void test_diff_drivers__patterns(void) git_tree_free(one); } +void test_diff_drivers__long_lines(void) +{ + const char *base = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non nisi ligula. Ut viverra enim sed lobortis suscipit.\nPhasellus eget erat odio. Praesent at est iaculis, ultricies augue vel, dignissim risus. Suspendisse at nisi quis turpis fringilla rutrum id sit amet nulla.\nNam eget dolor fermentum, aliquet nisl at, convallis tellus. Pellentesque rhoncus erat enim, id porttitor elit euismod quis.\nMauris sollicitudin magna odio, non egestas libero vehicula ut. Etiam et quam velit. Fusce eget libero rhoncus, ultricies felis sit amet, egestas purus.\nAliquam in semper tellus. Pellentesque adipiscing rutrum velit, quis malesuada lacus consequat eget.\n"; + git_index *idx; + git_diff_list *diff; + git_diff_patch *patch; + char *actual; + const char *expected = "diff --git a/longlines.txt b/longlines.txt\nindex c1ce6ef..0134431 100644\n--- a/longlines.txt\n+++ b/longlines.txt\n@@ -3,3 +3,5 @@ Phasellus eget erat odio. Praesent at est iaculis, ultricies augue vel, dignissi\n Nam eget dolor fermentum, aliquet nisl at, convallis tellus. Pellentesque rhoncus erat enim, id porttitor elit euismod quis.\n Mauris sollicitudin magna odio, non egestas libero vehicula ut. Etiam et quam velit. Fusce eget libero rhoncus, ultricies felis sit amet, egestas purus.\n Aliquam in semper tellus. Pellentesque adipiscing rutrum velit, quis malesuada lacus consequat eget.\n+newline\n+newline\n"; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_mkfile("empty_standard_repo/longlines.txt", base); + cl_git_pass(git_repository_index(&idx, g_repo)); + cl_git_pass(git_index_add_bypath(idx, "longlines.txt")); + cl_git_pass(git_index_write(idx)); + git_index_free(idx); + + cl_git_append2file("empty_standard_repo/longlines.txt", "newline\nnewline\n"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); + cl_assert_equal_sz(1, git_diff_num_deltas(diff)); + cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); + cl_git_pass(git_diff_patch_to_str(&actual, patch)); + + cl_assert_equal_s(expected, actual); + + free(actual); + git_diff_patch_free(patch); + git_diff_list_free(diff); +} + -- cgit v1.2.1 From 2274993be5acf3a9fcf62abbf1f00d06fb513624 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Tue, 9 Jul 2013 12:52:25 +0200 Subject: Make the git_signature const in the stash API. --- include/git2/stash.h | 2 +- src/stash.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/git2/stash.h b/include/git2/stash.h index 68d1b5413..b48d33f5d 100644 --- a/include/git2/stash.h +++ b/include/git2/stash.h @@ -57,7 +57,7 @@ typedef enum { GIT_EXTERN(int) git_stash_save( git_oid *out, git_repository *repo, - git_signature *stasher, + const git_signature *stasher, const char *message, unsigned int flags); diff --git a/src/stash.c b/src/stash.c index 1222634d5..48f19144d 100644 --- a/src/stash.c +++ b/src/stash.c @@ -117,7 +117,7 @@ static int build_tree_from_index(git_tree **out, git_index *index) static int commit_index( git_commit **i_commit, git_index *index, - git_signature *stasher, + const git_signature *stasher, const char *message, const git_commit *parent) { @@ -267,7 +267,7 @@ cleanup: static int commit_untracked( git_commit **u_commit, git_index *index, - git_signature *stasher, + const git_signature *stasher, const char *message, git_commit *i_commit, uint32_t flags) @@ -354,7 +354,7 @@ cleanup: static int commit_worktree( git_oid *w_commit_oid, git_index *index, - git_signature *stasher, + const git_signature *stasher, const char *message, git_commit *i_commit, git_commit *b_commit, @@ -431,7 +431,7 @@ cleanup: static int update_reflog( git_oid *w_commit_oid, git_repository *repo, - git_signature *stasher, + const git_signature *stasher, const char *message) { git_reference *stash = NULL; @@ -510,7 +510,7 @@ static int reset_index_and_workdir( int git_stash_save( git_oid *out, git_repository *repo, - git_signature *stasher, + const git_signature *stasher, const char *message, uint32_t flags) { -- cgit v1.2.1 From a3c062dbf8c8060b9f0cedc2855f506736d25c73 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 9 Jul 2013 09:58:33 -0700 Subject: Make SSH APIs present even without SSH support The SSH APIs will just return an error code and state that the library was built without SSH support if they are called in that case. --- include/git2/transport.h | 87 +++++++++++++---------- src/transport.c | 4 +- src/transports/cred.c | 67 ++++++++++++------ src/transports/ssh.c | 181 +++++++++++++++++++++++++---------------------- 4 files changed, 191 insertions(+), 148 deletions(-) diff --git a/include/git2/transport.h b/include/git2/transport.h index 81bb3abe1..21061fc78 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -36,14 +36,15 @@ typedef enum { } git_credtype_t; /* The base structure for all credential types */ -typedef struct git_cred { +typedef struct git_cred git_cred; + +struct git_cred { git_credtype_t credtype; - void (*free)( - struct git_cred *cred); -} git_cred; + void (*free)(git_cred *cred); +}; /* A plaintext username and password */ -typedef struct git_cred_userpass_plaintext { +typedef struct { git_cred parent; char *username; char *password; @@ -51,6 +52,9 @@ typedef struct git_cred_userpass_plaintext { #ifdef GIT_SSH typedef LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*git_cred_sign_callback)); +#else +typedef int (*git_cred_sign_callback)(void *, ...); +#endif /* A ssh key file and passphrase */ typedef struct git_cred_ssh_keyfile_passphrase { @@ -68,7 +72,6 @@ typedef struct git_cred_ssh_publickey { void *sign_callback; void *sign_data; } git_cred_ssh_publickey; -#endif /** * Creates a new plain-text username and password credential object. @@ -84,7 +87,6 @@ GIT_EXTERN(int) git_cred_userpass_plaintext_new( const char *username, const char *password); -#ifdef GIT_SSH /** * Creates a new ssh key file and passphrase credential object. * The supplied credential parameter will be internally duplicated. @@ -116,9 +118,8 @@ GIT_EXTERN(int) git_cred_ssh_publickey_new( git_cred **out, const char *publickey, size_t publickey_len, - git_cred_sign_callback, + git_cred_sign_callback sign_fn, void *sign_data); -#endif /** * Signature of a function which acquires a credential object. @@ -152,17 +153,21 @@ typedef enum { typedef void (*git_transport_message_cb)(const char *str, int len, void *data); -typedef struct git_transport { +typedef struct git_transport git_transport; + +struct git_transport { unsigned int version; /* Set progress and error callbacks */ - int (*set_callbacks)(struct git_transport *transport, + int (*set_callbacks)( + git_transport *transport, git_transport_message_cb progress_cb, git_transport_message_cb error_cb, void *payload); /* Connect the transport to the remote repository, using the given * direction. */ - int (*connect)(struct git_transport *transport, + int (*connect)( + git_transport *transport, const char *url, git_cred_acquire_cb cred_acquire_cb, void *cred_acquire_payload, @@ -172,17 +177,19 @@ typedef struct git_transport { /* This function may be called after a successful call to connect(). The * provided callback is invoked for each ref discovered on the remote * end. */ - int (*ls)(struct git_transport *transport, + int (*ls)( + git_transport *transport, git_headlist_cb list_cb, void *payload); /* Executes the push whose context is in the git_push object. */ - int (*push)(struct git_transport *transport, git_push *push); + int (*push)(git_transport *transport, git_push *push); /* This function may be called after a successful call to connect(), when * the direction is FETCH. The function performs a negotiation to calculate * the wants list for the fetch. */ - int (*negotiate_fetch)(struct git_transport *transport, + int (*negotiate_fetch)( + git_transport *transport, git_repository *repo, const git_remote_head * const *refs, size_t count); @@ -190,28 +197,29 @@ typedef struct git_transport { /* This function may be called after a successful call to negotiate_fetch(), * when the direction is FETCH. This function retrieves the pack file for * the fetch from the remote end. */ - int (*download_pack)(struct git_transport *transport, + int (*download_pack)( + git_transport *transport, git_repository *repo, git_transfer_progress *stats, git_transfer_progress_callback progress_cb, void *progress_payload); /* Checks to see if the transport is connected */ - int (*is_connected)(struct git_transport *transport); + int (*is_connected)(git_transport *transport); /* Reads the flags value previously passed into connect() */ - int (*read_flags)(struct git_transport *transport, int *flags); + int (*read_flags)(git_transport *transport, int *flags); /* Cancels any outstanding transport operation */ - void (*cancel)(struct git_transport *transport); + void (*cancel)(git_transport *transport); /* This function is the reverse of connect() -- it terminates the * connection to the remote end. */ - int (*close)(struct git_transport *transport); + int (*close)(git_transport *transport); /* Frees/destructs the git_transport object. */ - void (*free)(struct git_transport *transport); -} git_transport; + void (*free)(git_transport *transport); +}; #define GIT_TRANSPORT_VERSION 1 #define GIT_TRANSPORT_INIT {GIT_TRANSPORT_VERSION} @@ -299,35 +307,36 @@ typedef enum { GIT_SERVICE_RECEIVEPACK = 4, } git_smart_service_t; -struct git_smart_subtransport; +typedef struct git_smart_subtransport git_smart_subtransport; +typedef struct git_smart_subtransport_stream git_smart_subtransport_stream; /* A stream used by the smart transport to read and write data * from a subtransport */ -typedef struct git_smart_subtransport_stream { +struct git_smart_subtransport_stream { /* The owning subtransport */ - struct git_smart_subtransport *subtransport; + git_smart_subtransport *subtransport; int (*read)( - struct git_smart_subtransport_stream *stream, - char *buffer, - size_t buf_size, - size_t *bytes_read); + git_smart_subtransport_stream *stream, + char *buffer, + size_t buf_size, + size_t *bytes_read); int (*write)( - struct git_smart_subtransport_stream *stream, - const char *buffer, - size_t len); + git_smart_subtransport_stream *stream, + const char *buffer, + size_t len); void (*free)( - struct git_smart_subtransport_stream *stream); -} git_smart_subtransport_stream; + git_smart_subtransport_stream *stream); +}; /* An implementation of a subtransport which carries data for the * smart transport */ -typedef struct git_smart_subtransport { +struct git_smart_subtransport { int (* action)( git_smart_subtransport_stream **out, - struct git_smart_subtransport *transport, + git_smart_subtransport *transport, const char *url, git_smart_service_t action); @@ -337,10 +346,10 @@ typedef struct git_smart_subtransport { * * 1. UPLOADPACK_LS -> UPLOADPACK * 2. RECEIVEPACK_LS -> RECEIVEPACK */ - int (* close)(struct git_smart_subtransport *transport); + int (*close)(git_smart_subtransport *transport); - void (* free)(struct git_smart_subtransport *transport); -} git_smart_subtransport; + void (*free)(git_smart_subtransport *transport); +}; /* A function which creates a new subtransport for the smart transport */ typedef int (*git_smart_subtransport_cb)( diff --git a/src/transport.c b/src/transport.c index 37c244c97..354789db1 100644 --- a/src/transport.c +++ b/src/transport.c @@ -73,7 +73,7 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void * /* It could be a SSH remote path. Check to see if there's a : * SSH is an unsupported transport mechanism in this version of libgit2 */ if (!definition && strrchr(url, ':')) - definition = &dummy_transport_definition; + definition = &dummy_transport_definition; #else /* For other systems, perform the SSH check first, to avoid going to the * filesystem if it is not necessary */ @@ -97,7 +97,7 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void * *callback = definition->fn; *param = definition->param; - + return 0; } diff --git a/src/transports/cred.c b/src/transports/cred.c index ba5de6e93..cb909fa40 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -68,7 +68,7 @@ static void ssh_keyfile_passphrase_free(struct git_cred *cred) if (c->publickey) { git__free(c->publickey); } - + git__free(c->privatekey); if (c->passphrase) { @@ -82,12 +82,28 @@ static void ssh_keyfile_passphrase_free(struct git_cred *cred) git__free(c); } +static void ssh_publickey_free(struct git_cred *cred) +{ + git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred; + + git__free(c->publickey); + + c->sign_callback = NULL; + c->sign_data = NULL; + + memset(c, 0, sizeof(*c)); + + git__free(c); +} +#endif + int git_cred_ssh_keyfile_passphrase_new( git_cred **cred, const char *publickey, const char *privatekey, const char *passphrase) { +#ifdef GIT_SSH git_cred_ssh_keyfile_passphrase *c; assert(cred && privatekey); @@ -97,15 +113,15 @@ int git_cred_ssh_keyfile_passphrase_new( c->parent.credtype = GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE; c->parent.free = ssh_keyfile_passphrase_free; - + c->privatekey = git__strdup(privatekey); GITERR_CHECK_ALLOC(c->privatekey); - + if (publickey) { c->publickey = git__strdup(publickey); GITERR_CHECK_ALLOC(c->publickey); } - + if (passphrase) { c->passphrase = git__strdup(passphrase); GITERR_CHECK_ALLOC(c->passphrase); @@ -113,29 +129,27 @@ int git_cred_ssh_keyfile_passphrase_new( *cred = &c->parent; return 0; -} - -static void ssh_publickey_free(struct git_cred *cred) -{ - git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred; +#else + GIT_UNUSED(publickey); + GIT_UNUSED(privatekey); + GIT_UNUSED(passphrase); - git__free(c->publickey); - - c->sign_callback = NULL; - c->sign_data = NULL; - - memset(c, 0, sizeof(*c)); + assert(cred); + *cred = NULL; - git__free(c); + giterr_set(GITERR_INVALID, "Cannot create SSH credential. Library was built without SSH support"); + return -1; +#endif } int git_cred_ssh_publickey_new( git_cred **cred, const char *publickey, size_t publickey_len, - LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), + git_cred_sign_callback sign_callback, void *sign_data) { +#ifdef GIT_SSH git_cred_ssh_publickey *c; if (!cred) @@ -146,17 +160,28 @@ int git_cred_ssh_publickey_new( c->parent.credtype = GIT_CREDTYPE_SSH_PUBLICKEY; c->parent.free = ssh_publickey_free; - + c->publickey = git__malloc(publickey_len); GITERR_CHECK_ALLOC(c->publickey); - + memcpy(c->publickey, publickey, publickey_len); - + c->publickey_len = publickey_len; c->sign_callback = sign_callback; c->sign_data = sign_data; *cred = &c->parent; return 0; -} +#else + GIT_UNUSED(publickey); + GIT_UNUSED(publickey_len); + GIT_UNUSED(sign_callback); + GIT_UNUSED(sign_data); + + assert(cred); + *cred = NULL; + + giterr_set(GITERR_INVALID, "Cannot create SSH credential. Library was built without SSH support"); + return -1; #endif +} diff --git a/src/transports/ssh.c b/src/transports/ssh.c index a312c8d08..3ae23cbbf 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -5,13 +5,13 @@ * a Linking Exception. For full terms see the included COPYING file. */ -#ifdef GIT_SSH - #include "git2.h" #include "buffer.h" #include "netops.h" #include "smart.h" +#ifdef GIT_SSH + #include #define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport) @@ -46,27 +46,27 @@ typedef struct { static int gen_proto(git_buf *request, const char *cmd, const char *url) { char *repo; - + if (!git__prefixcmp(url, prefix_ssh)) { url = url + strlen(prefix_ssh); repo = strchr(url, '/'); } else { repo = strchr(url, ':'); } - + if (!repo) { return -1; } - + int len = strlen(cmd) + 1 /* Space */ + 1 /* Quote */ + strlen(repo) + 1 /* Quote */ + 1; - + git_buf_grow(request, len); git_buf_printf(request, "%s '%s'", cmd, repo); git_buf_putc(request, '\0'); - + if (git_buf_oom(request)) return -1; - + return 0; } @@ -74,11 +74,11 @@ static int send_command(ssh_stream *s) { int error; git_buf request = GIT_BUF_INIT; - + error = gen_proto(&request, s->cmd, s->url); if (error < 0) goto cleanup; - + error = libssh2_channel_exec( s->channel, request.ptr @@ -86,9 +86,9 @@ static int send_command(ssh_stream *s) if (0 != error) goto cleanup; - + s->sent_command = 1; - + cleanup: git_buf_free(&request); return error; @@ -101,18 +101,18 @@ static int ssh_stream_read( size_t *bytes_read) { ssh_stream *s = (ssh_stream *)stream; - + *bytes_read = 0; - + if (!s->sent_command && send_command(s) < 0) return -1; - + int rc = libssh2_channel_read(s->channel, buffer, buf_size); if (rc < 0) return -1; - + *bytes_read = rc; - + return 0; } @@ -122,15 +122,15 @@ static int ssh_stream_write( size_t len) { ssh_stream *s = (ssh_stream *)stream; - + if (!s->sent_command && send_command(s) < 0) return -1; - + int rc = libssh2_channel_write(s->channel, buffer, len); if (rc < 0) { return -1; } - + return rc; } @@ -139,26 +139,26 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream) ssh_stream *s = (ssh_stream *)stream; ssh_subtransport *t = OWNING_SUBTRANSPORT(s); int ret; - + GIT_UNUSED(ret); - + t->current_stream = NULL; - + if (s->channel) { libssh2_channel_close(s->channel); libssh2_channel_free(s->channel); s->channel = NULL; } - + if (s->session) { libssh2_session_free(s->session), s->session = NULL; } - + if (s->socket.socket) { ret = gitno_close(&s->socket); assert(!ret); } - + git__free(s->url); git__free(s); } @@ -170,26 +170,26 @@ static int ssh_stream_alloc( git_smart_subtransport_stream **stream) { ssh_stream *s; - + if (!stream) return -1; - + s = git__calloc(sizeof(ssh_stream), 1); GITERR_CHECK_ALLOC(s); - + s->parent.subtransport = &t->parent; s->parent.read = ssh_stream_read; s->parent.write = ssh_stream_write; s->parent.free = ssh_stream_free; - + s->cmd = cmd; s->url = git__strdup(url); - + if (!s->url) { git__free(s); return -1; } - + *stream = &s->parent; return 0; } @@ -201,14 +201,14 @@ static int git_ssh_extract_url_parts( { char *colon, *at; const char *start; - + colon = strchr(url, ':'); - + if (colon == NULL) { giterr_set(GITERR_NET, "Malformed URL: missing :"); return -1; } - + at = strchr(url, '@'); if (at) { start = at+1; @@ -217,9 +217,9 @@ static int git_ssh_extract_url_parts( start = url; *username = git__strdup(default_user); } - + *host = git__substrdup(start, colon - start); - + return 0; } @@ -235,7 +235,7 @@ static int _git_ssh_authenticate_session( case GIT_CREDTYPE_USERPASS_PLAINTEXT: { git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; rc = libssh2_userauth_password( - session, + session, c->username, c->password ); @@ -244,7 +244,7 @@ static int _git_ssh_authenticate_session( case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: { git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred; rc = libssh2_userauth_publickey_fromfile( - session, + session, user, c->publickey, c->privatekey, @@ -268,7 +268,7 @@ static int _git_ssh_authenticate_session( rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED; } } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); - + return rc; } @@ -281,31 +281,31 @@ static int _git_ssh_session_create if (!session) { return -1; } - + LIBSSH2_SESSION* s = libssh2_session_init(); if (!s) return -1; - + int rc = 0; do { rc = libssh2_session_startup(s, socket.socket); } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); - + if (0 != rc) { goto on_error; } - + libssh2_session_set_blocking(s, 1); - + *session = s; - + return 0; - + on_error: if (s) { libssh2_session_free(s), s = NULL; } - + return -1; } @@ -321,13 +321,13 @@ static int _git_ssh_setup_conn( ssh_stream *s; LIBSSH2_SESSION* session=NULL; LIBSSH2_CHANNEL* channel=NULL; - + *stream = NULL; if (ssh_stream_alloc(t, url, cmd, stream) < 0) return -1; - + s = (ssh_stream *)*stream; - + if (!git__prefixcmp(url, prefix_ssh)) { url = url + strlen(prefix_ssh); if (gitno_extract_url_parts(&host, &port, &user, &pass, url, default_port) < 0) @@ -338,10 +338,10 @@ static int _git_ssh_setup_conn( port = git__strdup(default_port); GITERR_CHECK_ALLOC(port); } - + if (gitno_connect(&s->socket, host, port, 0) < 0) goto on_error; - + if (user && pass) { if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0) goto on_error; @@ -354,26 +354,26 @@ static int _git_ssh_setup_conn( return -1; } assert(t->cred); - + if (!user) { user = git__strdup(default_user); } - + if (_git_ssh_session_create(&session, s->socket) < 0) goto on_error; - + if (_git_ssh_authenticate_session(session, user, t->cred) < 0) goto on_error; - + channel = libssh2_channel_open_session(session); if (!channel) goto on_error; - + libssh2_channel_set_blocking(channel, 1); - + s->session = session; s->channel = channel; - + t->current_stream = s; git__free(host); git__free(port); @@ -381,11 +381,11 @@ static int _git_ssh_setup_conn( git__free(pass); return 0; - + on_error: if (*stream) ssh_stream_free(*stream); - + git__free(host); git__free(port); git__free(user); @@ -404,7 +404,7 @@ static int ssh_uploadpack_ls( { if (_git_ssh_setup_conn(t, url, cmd_uploadpack, stream) < 0) return -1; - + return 0; } @@ -414,12 +414,12 @@ static int ssh_uploadpack( git_smart_subtransport_stream **stream) { GIT_UNUSED(url); - + if (t->current_stream) { *stream = &t->current_stream->parent; return 0; } - + giterr_set(GITERR_NET, "Must call UPLOADPACK_LS before UPLOADPACK"); return -1; } @@ -431,7 +431,7 @@ static int ssh_receivepack_ls( { if (_git_ssh_setup_conn(t, url, cmd_receivepack, stream) < 0) return -1; - + return 0; } @@ -441,12 +441,12 @@ static int ssh_receivepack( git_smart_subtransport_stream **stream) { GIT_UNUSED(url); - + if (t->current_stream) { *stream = &t->current_stream->parent; return 0; } - + giterr_set(GITERR_NET, "Must call RECEIVEPACK_LS before RECEIVEPACK"); return -1; } @@ -458,21 +458,21 @@ static int _ssh_action( git_smart_service_t action) { ssh_subtransport *t = (ssh_subtransport *) subtransport; - + switch (action) { case GIT_SERVICE_UPLOADPACK_LS: return ssh_uploadpack_ls(t, url, stream); - + case GIT_SERVICE_UPLOADPACK: return ssh_uploadpack(t, url, stream); - + case GIT_SERVICE_RECEIVEPACK_LS: return ssh_receivepack_ls(t, url, stream); - + case GIT_SERVICE_RECEIVEPACK: return ssh_receivepack(t, url, stream); } - + *stream = NULL; return -1; } @@ -480,40 +480,49 @@ static int _ssh_action( static int _ssh_close(git_smart_subtransport *subtransport) { ssh_subtransport *t = (ssh_subtransport *) subtransport; - + assert(!t->current_stream); - + GIT_UNUSED(t); - + return 0; } static void _ssh_free(git_smart_subtransport *subtransport) { ssh_subtransport *t = (ssh_subtransport *) subtransport; - + assert(!t->current_stream); - + git__free(t); } +#endif -int git_smart_subtransport_ssh(git_smart_subtransport **out, git_transport *owner) +int git_smart_subtransport_ssh( + git_smart_subtransport **out, git_transport *owner) { +#ifdef GIT_SSH ssh_subtransport *t; - - if (!out) - return -1; - + + assert(out); + t = git__calloc(sizeof(ssh_subtransport), 1); GITERR_CHECK_ALLOC(t); - + t->owner = (transport_smart *)owner; t->parent.action = _ssh_action; t->parent.close = _ssh_close; t->parent.free = _ssh_free; - + *out = (git_smart_subtransport *) t; return 0; -} +#else + GIT_UNUSED(owner); + + assert(out); + *out = NULL; + giterr_set(GITERR_INVALID, "Cannot create SSH transport. Library was built without SSH support"); + return -1; #endif +} -- cgit v1.2.1 From 5813bc2194e9adefb2d7a25a5039c36879417c11 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 9 Jul 2013 12:01:16 -0700 Subject: Lots of SSH credential stuff can be left on Much of the SSH credential creation API can be left enabled even on platforms with no SSH support. We really just have to give an error when you attempt to open the SSH connection. --- src/transports/cred.c | 50 +++++++++++--------------------------------------- 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/src/transports/cred.c b/src/transports/cred.c index cb909fa40..6e51c2bf7 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -59,20 +59,17 @@ int git_cred_userpass_plaintext_new( return 0; } -#ifdef GIT_SSH static void ssh_keyfile_passphrase_free(struct git_cred *cred) { - git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred; - size_t pass_len = strlen(c->passphrase); - - if (c->publickey) { - git__free(c->publickey); - } + git_cred_ssh_keyfile_passphrase *c = + (git_cred_ssh_keyfile_passphrase *)cred; + git__free(c->publickey); git__free(c->privatekey); if (c->passphrase) { /* Zero the memory which previously held the passphrase */ + size_t pass_len = strlen(c->passphrase); git__memzero(c->passphrase, pass_len); git__free(c->passphrase); } @@ -95,7 +92,6 @@ static void ssh_publickey_free(struct git_cred *cred) git__free(c); } -#endif int git_cred_ssh_keyfile_passphrase_new( git_cred **cred, @@ -103,7 +99,6 @@ int git_cred_ssh_keyfile_passphrase_new( const char *privatekey, const char *passphrase) { -#ifdef GIT_SSH git_cred_ssh_keyfile_passphrase *c; assert(cred && privatekey); @@ -129,17 +124,6 @@ int git_cred_ssh_keyfile_passphrase_new( *cred = &c->parent; return 0; -#else - GIT_UNUSED(publickey); - GIT_UNUSED(privatekey); - GIT_UNUSED(passphrase); - - assert(cred); - *cred = NULL; - - giterr_set(GITERR_INVALID, "Cannot create SSH credential. Library was built without SSH support"); - return -1; -#endif } int git_cred_ssh_publickey_new( @@ -149,22 +133,22 @@ int git_cred_ssh_publickey_new( git_cred_sign_callback sign_callback, void *sign_data) { -#ifdef GIT_SSH git_cred_ssh_publickey *c; - if (!cred) - return -1; + assert(cred); - c = git__malloc(sizeof(git_cred_ssh_publickey)); + c = git__calloc(1, sizeof(git_cred_ssh_publickey)); GITERR_CHECK_ALLOC(c); c->parent.credtype = GIT_CREDTYPE_SSH_PUBLICKEY; c->parent.free = ssh_publickey_free; - c->publickey = git__malloc(publickey_len); - GITERR_CHECK_ALLOC(c->publickey); + if (publickey_len > 0) { + c->publickey = git__malloc(publickey_len); + GITERR_CHECK_ALLOC(c->publickey); - memcpy(c->publickey, publickey, publickey_len); + memcpy(c->publickey, publickey, publickey_len); + } c->publickey_len = publickey_len; c->sign_callback = sign_callback; @@ -172,16 +156,4 @@ int git_cred_ssh_publickey_new( *cred = &c->parent; return 0; -#else - GIT_UNUSED(publickey); - GIT_UNUSED(publickey_len); - GIT_UNUSED(sign_callback); - GIT_UNUSED(sign_data); - - assert(cred); - *cred = NULL; - - giterr_set(GITERR_INVALID, "Cannot create SSH credential. Library was built without SSH support"); - return -1; -#endif } -- cgit v1.2.1 From 03d9b930ee6b90ab17f031e596ad6d15ee313ca8 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 9 Jul 2013 14:45:58 -0700 Subject: Indent with tabs --- src/transports/cred.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/transports/cred.c b/src/transports/cred.c index 6e51c2bf7..1d8527e39 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -67,12 +67,12 @@ static void ssh_keyfile_passphrase_free(struct git_cred *cred) git__free(c->publickey); git__free(c->privatekey); - if (c->passphrase) { - /* Zero the memory which previously held the passphrase */ + if (c->passphrase) { + /* Zero the memory which previously held the passphrase */ size_t pass_len = strlen(c->passphrase); - git__memzero(c->passphrase, pass_len); - git__free(c->passphrase); - } + git__memzero(c->passphrase, pass_len); + git__free(c->passphrase); + } memset(c, 0, sizeof(*c)); @@ -83,10 +83,10 @@ static void ssh_publickey_free(struct git_cred *cred) { git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred; - git__free(c->publickey); + git__free(c->publickey); - c->sign_callback = NULL; - c->sign_data = NULL; + c->sign_callback = NULL; + c->sign_data = NULL; memset(c, 0, sizeof(*c)); @@ -109,10 +109,10 @@ int git_cred_ssh_keyfile_passphrase_new( c->parent.credtype = GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE; c->parent.free = ssh_keyfile_passphrase_free; - c->privatekey = git__strdup(privatekey); + c->privatekey = git__strdup(privatekey); GITERR_CHECK_ALLOC(c->privatekey); - if (publickey) { + if (publickey) { c->publickey = git__strdup(publickey); GITERR_CHECK_ALLOC(c->publickey); } @@ -129,9 +129,9 @@ int git_cred_ssh_keyfile_passphrase_new( int git_cred_ssh_publickey_new( git_cred **cred, const char *publickey, - size_t publickey_len, + size_t publickey_len, git_cred_sign_callback sign_callback, - void *sign_data) + void *sign_data) { git_cred_ssh_publickey *c; @@ -150,9 +150,9 @@ int git_cred_ssh_publickey_new( memcpy(c->publickey, publickey, publickey_len); } - c->publickey_len = publickey_len; - c->sign_callback = sign_callback; - c->sign_data = sign_data; + c->publickey_len = publickey_len; + c->sign_callback = sign_callback; + c->sign_data = sign_data; *cred = &c->parent; return 0; -- cgit v1.2.1 From a4456929a8890a9ac1441db343c21040665ce253 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 9 Jul 2013 16:16:24 -0700 Subject: Make credential clearing consistent This makes all of the credential objects use the same pattern to clear the contents and call git__memzero when done. Much of this information is probably not sensitive, but it also seems better to just clear consistently. --- src/transports/cred.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/transports/cred.c b/src/transports/cred.c index 1d8527e39..d713f8992 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -12,16 +12,17 @@ static void plaintext_free(struct git_cred *cred) { git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; - size_t pass_len = strlen(c->password); git__free(c->username); /* Zero the memory which previously held the password */ - git__memzero(c->password, pass_len); - git__free(c->password); - - memset(c, 0, sizeof(*c)); + if (c->password) { + size_t pass_len = strlen(c->password); + git__memzero(c->password, pass_len); + git__free(c->password); + } + git__memzero(c, sizeof(*c)); git__free(c); } @@ -74,8 +75,7 @@ static void ssh_keyfile_passphrase_free(struct git_cred *cred) git__free(c->passphrase); } - memset(c, 0, sizeof(*c)); - + git__memzero(c, sizeof(*c)); git__free(c); } @@ -85,11 +85,7 @@ static void ssh_publickey_free(struct git_cred *cred) git__free(c->publickey); - c->sign_callback = NULL; - c->sign_data = NULL; - - memset(c, 0, sizeof(*c)); - + git__memzero(c, sizeof(*c)); git__free(c); } -- cgit v1.2.1 From 290e14798598922fbff7189f64f997bad35c4f84 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 9 Jul 2013 16:17:41 -0700 Subject: Add GIT_CAP_SSH if library was built with SSH This also adds a test that actually calls git_libgit2_capabilities and git_libgit2_version. --- include/git2/common.h | 3 ++- src/util.c | 3 +++ tests-clar/core/caps.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests-clar/core/caps.c diff --git a/include/git2/common.h b/include/git2/common.h index b52e13918..d7df7327e 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -105,7 +105,8 @@ GIT_EXTERN(void) git_libgit2_version(int *major, int *minor, int *rev); */ typedef enum { GIT_CAP_THREADS = ( 1 << 0 ), - GIT_CAP_HTTPS = ( 1 << 1 ) + GIT_CAP_HTTPS = ( 1 << 1 ), + GIT_CAP_SSH = ( 1 << 2 ), } git_cap_t; /** diff --git a/src/util.c b/src/util.c index c543a3d21..ad7603829 100644 --- a/src/util.c +++ b/src/util.c @@ -32,6 +32,9 @@ int git_libgit2_capabilities() #endif #if defined(GIT_SSL) || defined(GIT_WINHTTP) | GIT_CAP_HTTPS +#endif +#if defined(GIT_SSH) + | GIT_CAP_SSH #endif ; } diff --git a/tests-clar/core/caps.c b/tests-clar/core/caps.c new file mode 100644 index 000000000..68a518ed7 --- /dev/null +++ b/tests-clar/core/caps.c @@ -0,0 +1,31 @@ +#include "clar_libgit2.h" + +void test_core_caps__0(void) +{ + int major, minor, rev, caps; + + git_libgit2_version(&major, &minor, &rev); + cl_assert_equal_i(LIBGIT2_VER_MAJOR, major); + cl_assert_equal_i(LIBGIT2_VER_MINOR, minor); + cl_assert_equal_i(LIBGIT2_VER_REVISION, rev); + + caps = git_libgit2_capabilities(); + +#ifdef GIT_THREADS + cl_assert((caps & GIT_CAP_THREADS) != 0); +#else + cl_assert((caps & GIT_CAP_THREADS) == 0); +#endif + +#if defined(GIT_SSL) || defined(GIT_WINHTTP) + cl_assert((caps & GIT_CAP_HTTPS) != 0); +#else + cl_assert((caps & GIT_CAP_HTTPS) == 0); +#endif + +#if defined(GIT_SSH) + cl_assert((caps & GIT_CAP_SSH) != 0); +#else + cl_assert((caps & GIT_CAP_SSH) == 0); +#endif +} -- cgit v1.2.1 From 07fba63e9eda509d1eee13df0b325dbd4be2f3cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20David=20Ib=C3=A1=C3=B1ez?= Date: Sat, 6 Jul 2013 23:51:40 +0200 Subject: Fix return value in git_config_get_multivar If there is not an error, the return value was always the return value of the last call to file->get_multivar With this commit GIT_ENOTFOUND is only returned if all the calls to filge-get_multivar return GIT_ENOTFOUND. --- src/config.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/config.c b/src/config.c index 068c40260..aaad7d87c 100644 --- a/src/config.c +++ b/src/config.c @@ -535,6 +535,7 @@ int git_config_get_multivar( file_internal *internal; git_config_backend *file; int ret = GIT_ENOTFOUND; + int err; size_t i; /* @@ -547,9 +548,15 @@ int git_config_get_multivar( continue; file = internal->file; - ret = file->get_multivar(file, name, regexp, cb, payload); - if (ret < 0 && ret != GIT_ENOTFOUND) - return ret; + err = file->get_multivar(file, name, regexp, cb, payload); + switch (err) { + case GIT_OK: + ret = GIT_OK; + case GIT_ENOTFOUND: + break; + default: + return err; + } } return (ret == GIT_ENOTFOUND) ? config_error_notfound(name) : 0; -- cgit v1.2.1 From 7b5c0d18460b6cb0a65543b92002a29644dbb458 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 9 Jul 2013 16:45:23 -0700 Subject: Add more tests for git_config_get_multivar The old tests didn't try failing lookups or lookups across multiple config files with some having the pattern and some not having it. --- tests-clar/config/multivar.c | 56 ++++++++++++++++++++++++++++++------ tests-clar/resources/config/config11 | 2 +- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/tests-clar/config/multivar.c b/tests-clar/config/multivar.c index 0bda6bcec..efc431502 100644 --- a/tests-clar/config/multivar.c +++ b/tests-clar/config/multivar.c @@ -1,6 +1,6 @@ #include "clar_libgit2.h" -static const char *_name = "remote.fancy.url"; +static const char *_name = "remote.ab.url"; void test_config_multivar__initialize(void) { @@ -46,20 +46,60 @@ static int cb(const git_config_entry *entry, void *data) return 0; } +static void check_get_multivar( + git_config *cfg, int expected, int expected_patterned) +{ + int n = 0; + + if (expected > 0) { + cl_git_pass(git_config_get_multivar(cfg, _name, NULL, cb, &n)); + cl_assert_equal_i(expected, n); + } else { + cl_assert_equal_i(GIT_ENOTFOUND, + git_config_get_multivar(cfg, _name, NULL, cb, &n)); + } + + n = 0; + + if (expected_patterned > 0) { + cl_git_pass(git_config_get_multivar(cfg, _name, "example", cb, &n)); + cl_assert_equal_i(expected_patterned, n); + } else { + cl_assert_equal_i(GIT_ENOTFOUND, + git_config_get_multivar(cfg, _name, "example", cb, &n)); + } +} + void test_config_multivar__get(void) { git_config *cfg; - int n; cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + check_get_multivar(cfg, 2, 1); - n = 0; - cl_git_pass(git_config_get_multivar(cfg, _name, NULL, cb, &n)); - cl_assert(n == 2); + /* add another that has the _name entry */ + cl_git_pass(git_config_add_file_ondisk(cfg, "config/config9", GIT_CONFIG_LEVEL_SYSTEM, 1)); + check_get_multivar(cfg, 3, 2); - n = 0; - cl_git_pass(git_config_get_multivar(cfg, _name, "example", cb, &n)); - cl_assert(n == 1); + /* add another that does not have the _name entry */ + cl_git_pass(git_config_add_file_ondisk(cfg, "config/config0", GIT_CONFIG_LEVEL_GLOBAL, 1)); + check_get_multivar(cfg, 3, 2); + + /* add another that does not have the _name entry at the end */ + cl_git_pass(git_config_add_file_ondisk(cfg, "config/config1", GIT_CONFIG_LEVEL_APP, 1)); + check_get_multivar(cfg, 3, 2); + + /* drop original file */ + cl_git_pass(git_config_add_file_ondisk(cfg, "config/config2", GIT_CONFIG_LEVEL_LOCAL, 1)); + check_get_multivar(cfg, 1, 1); + + /* drop other file with match */ + cl_git_pass(git_config_add_file_ondisk(cfg, "config/config3", GIT_CONFIG_LEVEL_SYSTEM, 1)); + check_get_multivar(cfg, 0, 0); + + /* reload original file (add different place in order) */ + cl_git_pass(git_config_add_file_ondisk(cfg, "config/config11", GIT_CONFIG_LEVEL_SYSTEM, 1)); + check_get_multivar(cfg, 2, 1); git_config_free(cfg); } diff --git a/tests-clar/resources/config/config11 b/tests-clar/resources/config/config11 index 7331862a5..1d8a74470 100644 --- a/tests-clar/resources/config/config11 +++ b/tests-clar/resources/config/config11 @@ -1,4 +1,4 @@ -[remote "fancy"] +[remote "ab"] url = git://github.com/libgit2/libgit2 url = git://git.example.com/libgit2 -- cgit v1.2.1 From e4fda954d6d914609498fc3bcbd27b4e2b5834d3 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 9 Jul 2013 16:46:18 -0700 Subject: A little git_config_get_multivar code cleanup --- src/config.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/config.c b/src/config.c index aaad7d87c..2a058549f 100644 --- a/src/config.c +++ b/src/config.c @@ -534,8 +534,7 @@ int git_config_get_multivar( { file_internal *internal; git_config_backend *file; - int ret = GIT_ENOTFOUND; - int err; + int ret = GIT_ENOTFOUND, err; size_t i; /* @@ -548,15 +547,10 @@ int git_config_get_multivar( continue; file = internal->file; - err = file->get_multivar(file, name, regexp, cb, payload); - switch (err) { - case GIT_OK: - ret = GIT_OK; - case GIT_ENOTFOUND: - break; - default: - return err; - } + if (!(err = file->get_multivar(file, name, regexp, cb, payload))) + ret = 0; + else if (err != GIT_ENOTFOUND) + return err; } return (ret == GIT_ENOTFOUND) ? config_error_notfound(name) : 0; -- cgit v1.2.1 From 367c1903e9aefd07de0d5be98c56640d13e3420d Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Wed, 10 Jul 2013 10:29:09 +0200 Subject: Add some missing error messages. --- src/transports/ssh.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/transports/ssh.c b/src/transports/ssh.c index f2480b2cd..bb3843886 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -353,24 +353,31 @@ static int _git_ssh_setup_conn( t->owner->cred_acquire_payload) < 0) goto on_error; } else { - goto on_error; - } + giterr_set(GITERR_NET, "Cannot set up SSH connection without credentials"); + goto on_error; + } assert(t->cred); if (!user) { user = git__strdup(default_user); } - if (_git_ssh_session_create(&session, s->socket) < 0) + if (_git_ssh_session_create(&session, s->socket) < 0) { + giterr_set(GITERR_NET, "Failed to initialize SSH session"); goto on_error; - - if (_git_ssh_authenticate_session(session, user, t->cred) < 0) + } + + if (_git_ssh_authenticate_session(session, user, t->cred) < 0) { + giterr_set(GITERR_NET, "Failed to authenticate SSH session"); goto on_error; - + } + channel = libssh2_channel_open_session(session); - if (!channel) - goto on_error; - + if (!channel) { + giterr_set(GITERR_NET, "Failed to open SSH channel"); + goto on_error; + } + libssh2_channel_set_blocking(channel, 1); s->session = session; -- cgit v1.2.1 From 08bf80fa2bf95e17af79a1da5832aefb275d9565 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Wed, 10 Jul 2013 10:29:32 +0200 Subject: Tab indent. --- src/transports/ssh.c | 182 ++++++++++++++++++++++++++------------------------- 1 file changed, 92 insertions(+), 90 deletions(-) diff --git a/src/transports/ssh.c b/src/transports/ssh.c index bb3843886..2eaaa45c9 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -46,27 +46,27 @@ typedef struct { static int gen_proto(git_buf *request, const char *cmd, const char *url) { char *repo; - + if (!git__prefixcmp(url, prefix_ssh)) { url = url + strlen(prefix_ssh); repo = strchr(url, '/'); } else { repo = strchr(url, ':'); } - + if (!repo) { return -1; } - + int len = strlen(cmd) + 1 /* Space */ + 1 /* Quote */ + strlen(repo) + 1 /* Quote */ + 1; - + git_buf_grow(request, len); git_buf_printf(request, "%s '%s'", cmd, repo); git_buf_putc(request, '\0'); - + if (git_buf_oom(request)) return -1; - + return 0; } @@ -74,11 +74,11 @@ static int send_command(ssh_stream *s) { int error; git_buf request = GIT_BUF_INIT; - + error = gen_proto(&request, s->cmd, s->url); if (error < 0) goto cleanup; - + error = libssh2_channel_exec( s->channel, request.ptr @@ -86,9 +86,9 @@ static int send_command(ssh_stream *s) if (0 != error) goto cleanup; - + s->sent_command = 1; - + cleanup: git_buf_free(&request); return error; @@ -101,18 +101,18 @@ static int ssh_stream_read( size_t *bytes_read) { ssh_stream *s = (ssh_stream *)stream; - + *bytes_read = 0; - + if (!s->sent_command && send_command(s) < 0) return -1; - + int rc = libssh2_channel_read(s->channel, buffer, buf_size); if (rc < 0) return -1; - + *bytes_read = rc; - + return 0; } @@ -122,15 +122,15 @@ static int ssh_stream_write( size_t len) { ssh_stream *s = (ssh_stream *)stream; - + if (!s->sent_command && send_command(s) < 0) return -1; - + int rc = libssh2_channel_write(s->channel, buffer, len); if (rc < 0) { return -1; } - + return rc; } @@ -139,26 +139,26 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream) ssh_stream *s = (ssh_stream *)stream; ssh_subtransport *t = OWNING_SUBTRANSPORT(s); int ret; - + GIT_UNUSED(ret); - + t->current_stream = NULL; - + if (s->channel) { libssh2_channel_close(s->channel); libssh2_channel_free(s->channel); s->channel = NULL; } - + if (s->session) { libssh2_session_free(s->session), s->session = NULL; } - + if (s->socket.socket) { ret = gitno_close(&s->socket); assert(!ret); } - + git__free(s->url); git__free(s); } @@ -170,26 +170,26 @@ static int ssh_stream_alloc( git_smart_subtransport_stream **stream) { ssh_stream *s; - + if (!stream) return -1; - + s = git__calloc(sizeof(ssh_stream), 1); GITERR_CHECK_ALLOC(s); - + s->parent.subtransport = &t->parent; s->parent.read = ssh_stream_read; s->parent.write = ssh_stream_write; s->parent.free = ssh_stream_free; - + s->cmd = cmd; s->url = git__strdup(url); - + if (!s->url) { git__free(s); return -1; } - + *stream = &s->parent; return 0; } @@ -201,14 +201,14 @@ static int git_ssh_extract_url_parts( { char *colon, *at; const char *start; - + colon = strchr(url, ':'); - + if (colon == NULL) { giterr_set(GITERR_NET, "Malformed URL: missing :"); return -1; } - + at = strchr(url, '@'); if (at) { start = at+1; @@ -217,9 +217,9 @@ static int git_ssh_extract_url_parts( start = url; *username = git__strdup(default_user); } - + *host = git__substrdup(start, colon - start); - + return 0; } @@ -235,7 +235,7 @@ static int _git_ssh_authenticate_session( case GIT_CREDTYPE_USERPASS_PLAINTEXT: { git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; rc = libssh2_userauth_password( - session, + session, c->username, c->password ); @@ -244,7 +244,7 @@ static int _git_ssh_authenticate_session( case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: { git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred; rc = libssh2_userauth_publickey_fromfile( - session, + session, user, c->publickey, c->privatekey, @@ -267,13 +267,12 @@ static int _git_ssh_authenticate_session( default: rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED; } - } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); - - return rc; + } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); + + return rc; } -static int _git_ssh_session_create -( +static int _git_ssh_session_create( LIBSSH2_SESSION** session, gitno_socket socket ) @@ -281,31 +280,30 @@ static int _git_ssh_session_create if (!session) { return -1; } - + LIBSSH2_SESSION* s = libssh2_session_init(); - if (!s) - return -1; - - int rc = 0; - do { - rc = libssh2_session_startup(s, socket.socket); - } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); - - if (0 != rc) { - goto on_error; - } - + if (!s) + return -1; + + int rc = 0; + do { + rc = libssh2_session_startup(s, socket.socket); + } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); + + if (0 != rc) + goto on_error; + libssh2_session_set_blocking(s, 1); - + *session = s; - + return 0; - + on_error: if (s) { libssh2_session_free(s), s = NULL; } - + return -1; } @@ -321,13 +319,13 @@ static int _git_ssh_setup_conn( ssh_stream *s; LIBSSH2_SESSION* session=NULL; LIBSSH2_CHANNEL* channel=NULL; - + *stream = NULL; if (ssh_stream_alloc(t, url, cmd, stream) < 0) return -1; - + s = (ssh_stream *)*stream; - + if (!git__prefixcmp(url, prefix_ssh)) { url = url + strlen(prefix_ssh); if (gitno_extract_url_parts(&host, &port, &user, &pass, url, default_port) < 0) @@ -338,10 +336,10 @@ static int _git_ssh_setup_conn( port = git__strdup(default_port); GITERR_CHECK_ALLOC(port); } - + if (gitno_connect(&s->socket, host, port, 0) < 0) goto on_error; - + if (user && pass) { if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0) goto on_error; @@ -357,11 +355,11 @@ static int _git_ssh_setup_conn( goto on_error; } assert(t->cred); - + if (!user) { user = git__strdup(default_user); } - + if (_git_ssh_session_create(&session, s->socket) < 0) { giterr_set(GITERR_NET, "Failed to initialize SSH session"); goto on_error; @@ -379,10 +377,10 @@ static int _git_ssh_setup_conn( } libssh2_channel_set_blocking(channel, 1); - + s->session = session; s->channel = channel; - + t->current_stream = s; git__free(host); git__free(port); @@ -390,11 +388,15 @@ static int _git_ssh_setup_conn( git__free(pass); return 0; - + on_error: + s->session = NULL; + s->channel = NULL; + t->current_stream = NULL; + if (*stream) ssh_stream_free(*stream); - + git__free(host); git__free(port); git__free(user); @@ -413,7 +415,7 @@ static int ssh_uploadpack_ls( { if (_git_ssh_setup_conn(t, url, cmd_uploadpack, stream) < 0) return -1; - + return 0; } @@ -423,12 +425,12 @@ static int ssh_uploadpack( git_smart_subtransport_stream **stream) { GIT_UNUSED(url); - + if (t->current_stream) { *stream = &t->current_stream->parent; return 0; } - + giterr_set(GITERR_NET, "Must call UPLOADPACK_LS before UPLOADPACK"); return -1; } @@ -440,7 +442,7 @@ static int ssh_receivepack_ls( { if (_git_ssh_setup_conn(t, url, cmd_receivepack, stream) < 0) return -1; - + return 0; } @@ -450,12 +452,12 @@ static int ssh_receivepack( git_smart_subtransport_stream **stream) { GIT_UNUSED(url); - + if (t->current_stream) { *stream = &t->current_stream->parent; return 0; } - + giterr_set(GITERR_NET, "Must call RECEIVEPACK_LS before RECEIVEPACK"); return -1; } @@ -467,21 +469,21 @@ static int _ssh_action( git_smart_service_t action) { ssh_subtransport *t = (ssh_subtransport *) subtransport; - + switch (action) { case GIT_SERVICE_UPLOADPACK_LS: return ssh_uploadpack_ls(t, url, stream); - + case GIT_SERVICE_UPLOADPACK: return ssh_uploadpack(t, url, stream); - + case GIT_SERVICE_RECEIVEPACK_LS: return ssh_receivepack_ls(t, url, stream); - + case GIT_SERVICE_RECEIVEPACK: return ssh_receivepack(t, url, stream); } - + *stream = NULL; return -1; } @@ -489,38 +491,38 @@ static int _ssh_action( static int _ssh_close(git_smart_subtransport *subtransport) { ssh_subtransport *t = (ssh_subtransport *) subtransport; - + assert(!t->current_stream); - + GIT_UNUSED(t); - + return 0; } static void _ssh_free(git_smart_subtransport *subtransport) { ssh_subtransport *t = (ssh_subtransport *) subtransport; - + assert(!t->current_stream); - + git__free(t); } int git_smart_subtransport_ssh(git_smart_subtransport **out, git_transport *owner) { ssh_subtransport *t; - + if (!out) return -1; - + t = git__calloc(sizeof(ssh_subtransport), 1); GITERR_CHECK_ALLOC(t); - + t->owner = (transport_smart *)owner; t->parent.action = _ssh_action; t->parent.close = _ssh_close; t->parent.free = _ssh_free; - + *out = (git_smart_subtransport *) t; return 0; } -- cgit v1.2.1 From c2de6b1adf49f8588dd59188774c96b783181e2f Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 10 Jul 2013 10:21:24 -0700 Subject: Bring SSH error reporting up to base standards The SSH error checking and reporting could still be further improved by using the libssh2 native methods to get error info, but at least this ensures that all error codes are checked and translated into libgit2 error messages. --- src/transports/cred.c | 3 +- src/transports/ssh.c | 151 ++++++++++++++++++++++++-------------------------- 2 files changed, 73 insertions(+), 81 deletions(-) diff --git a/src/transports/cred.c b/src/transports/cred.c index d713f8992..a6727e902 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -33,8 +33,7 @@ int git_cred_userpass_plaintext_new( { git_cred_userpass_plaintext *c; - if (!cred) - return -1; + assert(cred); c = git__malloc(sizeof(git_cred_userpass_plaintext)); GITERR_CHECK_ALLOC(c); diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 0155dd745..7fb53bc3c 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -55,6 +55,7 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url) } if (!repo) { + giterr_set(GITERR_NET, "Malformed git protocol URL"); return -1; } @@ -79,13 +80,11 @@ static int send_command(ssh_stream *s) if (error < 0) goto cleanup; - error = libssh2_channel_exec( - s->channel, - request.ptr - ); - - if (0 != error) + error = libssh2_channel_exec(s->channel, request.ptr); + if (error < 0) { + giterr_set(GITERR_NET, "SSH could not execute request"); goto cleanup; + } s->sent_command = 1; @@ -100,6 +99,7 @@ static int ssh_stream_read( size_t buf_size, size_t *bytes_read) { + int rc; ssh_stream *s = (ssh_stream *)stream; *bytes_read = 0; @@ -107,9 +107,10 @@ static int ssh_stream_read( if (!s->sent_command && send_command(s) < 0) return -1; - int rc = libssh2_channel_read(s->channel, buffer, buf_size); - if (rc < 0) + if ((rc = libssh2_channel_read(s->channel, buffer, buf_size)) < 0) { + giterr_set(GITERR_NET, "SSH could not read data"); return -1; + } *bytes_read = rc; @@ -126,12 +127,12 @@ static int ssh_stream_write( if (!s->sent_command && send_command(s) < 0) return -1; - int rc = libssh2_channel_write(s->channel, buffer, len); - if (rc < 0) { + if (libssh2_channel_write(s->channel, buffer, len) < 0) { + giterr_set(GITERR_NET, "SSH could not write data"); return -1; } - return rc; + return 0; } static void ssh_stream_free(git_smart_subtransport_stream *stream) @@ -151,12 +152,13 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream) } if (s->session) { - libssh2_session_free(s->session), s->session = NULL; + libssh2_session_free(s->session); + s->session = NULL; } if (s->socket.socket) { - ret = gitno_close(&s->socket); - assert(!ret); + (void)gitno_close(&s->socket); + /* can't do anything here with error return value */ } git__free(s->url); @@ -171,8 +173,7 @@ static int ssh_stream_alloc( { ssh_stream *s; - if (!stream) - return -1; + assert(stream); s = git__calloc(sizeof(ssh_stream), 1); GITERR_CHECK_ALLOC(s); @@ -183,8 +184,8 @@ static int ssh_stream_alloc( s->parent.free = ssh_stream_free; s->cmd = cmd; - s->url = git__strdup(url); + s->url = git__strdup(url); if (!s->url) { git__free(s); return -1; @@ -217,8 +218,10 @@ static int git_ssh_extract_url_parts( start = url; *username = git__strdup(default_user); } + GITERR_CHECK_ALLOC(*username); *host = git__substrdup(start, colon - start); + GITERR_CHECK_ALLOC(*host); return 0; } @@ -229,67 +232,63 @@ static int _git_ssh_authenticate_session( git_cred* cred) { int rc; + do { switch (cred->credtype) { - case GIT_CREDTYPE_USERPASS_PLAINTEXT: { - git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; - rc = libssh2_userauth_password( - session, - c->username, - c->password - ); - break; - } - case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: { - git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred; - rc = libssh2_userauth_publickey_fromfile( - session, - user, - c->publickey, - c->privatekey, - c->passphrase - ); - break; - } - case GIT_CREDTYPE_SSH_PUBLICKEY: { - git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred; - rc = libssh2_userauth_publickey( - session, - user, - (const unsigned char *)c->publickey, - c->publickey_len, - c->sign_callback, - &c->sign_data - ); - break; - } - default: - rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED; + case GIT_CREDTYPE_USERPASS_PLAINTEXT: { + git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; + rc = libssh2_userauth_password(session, c->username, c->password); + break; + } + case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: { + git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred; + rc = libssh2_userauth_publickey_fromfile( + session, user, c->publickey, c->privatekey, c->passphrase); + break; + } + case GIT_CREDTYPE_SSH_PUBLICKEY: { + git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred; + rc = libssh2_userauth_publickey( + session, user, (const unsigned char *)c->publickey, + c->publickey_len, c->sign_callback, &c->sign_data); + break; + } + default: + rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED; } } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); - return rc; + if (rc != 0) { + giterr_set(GITERR_NET, "Failed to authenticate SSH session"); + return -1; + } + + return 0; } static int _git_ssh_session_create( LIBSSH2_SESSION** session, gitno_socket socket) { - if (!session) { - return -1; - } + int rc = 0; + LIBSSH2_SESSION* s; - LIBSSH2_SESSION* s = libssh2_session_init(); - if (!s) + assert(session); + + s = libssh2_session_init(); + if (!s) { + giterr_set(GITERR_NET, "Failed to initialize SSH session"); return -1; + } - int rc = 0; do { rc = libssh2_session_startup(s, socket.socket); } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); if (0 != rc) { - goto on_error; + libssh2_session_free(s); + giterr_set(GITERR_NET, "Failed to start SSH session"); + return -1; } libssh2_session_set_blocking(s, 1); @@ -297,21 +296,13 @@ static int _git_ssh_session_create( *session = s; return 0; - -on_error: - if (s) { - libssh2_session_free(s), s = NULL; - } - - return -1; } static int _git_ssh_setup_conn( ssh_subtransport *t, const char *url, const char *cmd, - git_smart_subtransport_stream **stream -) + git_smart_subtransport_stream **stream) { char *host, *port=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; @@ -343,12 +334,17 @@ static int _git_ssh_setup_conn( if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0) goto on_error; } else if (t->owner->cred_acquire_cb) { - if (t->owner->cred_acquire_cb(&t->cred, - t->owner->url, - user, - GIT_CREDTYPE_USERPASS_PLAINTEXT | GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE, + if (t->owner->cred_acquire_cb( + &t->cred, t->owner->url, user, + GIT_CREDTYPE_USERPASS_PLAINTEXT | + GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE, t->owner->cred_acquire_payload) < 0) goto on_error; + + if (!t->cred) { + giterr_set(GITERR_NET, "Callback failed to initialize SSH credentials"); + goto on_error; + } } else { giterr_set(GITERR_NET, "Cannot set up SSH connection without credentials"); goto on_error; @@ -357,17 +353,14 @@ static int _git_ssh_setup_conn( if (!user) { user = git__strdup(default_user); + GITERR_CHECK_ALLOC(user); } - if (_git_ssh_session_create(&session, s->socket) < 0) { - giterr_set(GITERR_NET, "Failed to initialize SSH session"); + if (_git_ssh_session_create(&session, s->socket) < 0) goto on_error; - } - if (_git_ssh_authenticate_session(session, user, t->cred) < 0) { - giterr_set(GITERR_NET, "Failed to authenticate SSH session"); + if (_git_ssh_authenticate_session(session, user, t->cred) < 0) goto on_error; - } channel = libssh2_channel_open_session(session); if (!channel) { @@ -402,7 +395,7 @@ on_error: git__free(pass); if (session) - libssh2_session_free(session), session = NULL; + libssh2_session_free(session); return -1; } -- cgit v1.2.1 From 33c8c6f0b81badadf805d18f39f79384a6494bac Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 10 Jul 2013 10:48:32 -0700 Subject: trivial whitespace fixup --- src/transports/smart_protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 636616717..0cd5e831d 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -372,7 +372,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c return error; if (pkt->type == GIT_PKT_NAK || - (pkt->type == GIT_PKT_ACK && pkt->status != GIT_ACK_CONTINUE)) { + (pkt->type == GIT_PKT_ACK && pkt->status != GIT_ACK_CONTINUE)) { git__free(pkt); break; } -- cgit v1.2.1 From d39fff36484e908438beb17ee043689962182460 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sun, 23 Jun 2013 20:33:57 -0700 Subject: Basic framework for log command --- examples/Makefile | 2 +- examples/log.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 examples/log.c diff --git a/examples/Makefile b/examples/Makefile index 140cc4da9..6288906df 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -3,7 +3,7 @@ CC = gcc CFLAGS = -g -I../include -I../src -Wall -Wextra -Wmissing-prototypes -Wno-missing-field-initializers LFLAGS = -L../build -lgit2 -lz -APPS = general showindex diff rev-list cat-file status +APPS = general showindex diff rev-list cat-file status log all: $(APPS) diff --git a/examples/log.c b/examples/log.c new file mode 100644 index 000000000..f92b66996 --- /dev/null +++ b/examples/log.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include + +static void check(int error, const char *message) +{ + if (error) { + fprintf(stderr, "%s (%d)\n", message, error); + exit(1); + } +} + +static int check_str_param(const char *arg, const char *pat, const char **val) +{ + size_t len = strlen(pat); + if (strncmp(arg, pat, len)) + return 0; + *val = (const char *)(arg + len); + return 1; +} + +static void usage(const char *message, const char *arg) +{ + if (message && arg) + fprintf(stderr, "%s: %s\n", message, arg); + else if (message) + fprintf(stderr, "%s\n", message); + fprintf(stderr, "usage: log []\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + int i; + char *a; + const char *dir = "."; + git_repository *repo; + + git_threads_init(); + + for (i = 1; i < argc; ++i) { + a = argv[i]; + + if (a[0] != '-') { + } + else if (!check_str_param(a, "--git-dir=", &dir)) + usage("Unknown argument", a); + } + + check(git_repository_open_ext(&repo, dir, 0, NULL), + "Could not open repository"); + + git_repository_free(repo); + git_threads_shutdown(); + + return 0; +} -- cgit v1.2.1 From d2ce27dd494b65f54b2d110b4defd69aea976115 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 24 Jun 2013 23:16:06 -0700 Subject: Add public API for pathspec matching This adds a new public API for compiling pathspecs and matching them against the working directory, the index, or a tree from the repository. This also reworks the pathspec internals to allow the sharing of code between the existing internal usage of pathspec matching and the new external API. While this is working and the new API is ready for discussion, I think there is still an incorrect behavior in which patterns are always matched against the full path of an entry without taking the subdirectories into account (so "s*" will match "subdir/file" even though it wouldn't with core Git). Further enhancements are coming, but this was a good place to take a functional snapshot. --- include/git2/index.h | 8 + include/git2/pathspec.h | 202 ++++++++++++++++++++ src/checkout.c | 10 +- src/diff.c | 12 +- src/index.c | 42 +++-- src/index.h | 6 +- src/pathspec.c | 450 ++++++++++++++++++++++++++++++++++++++++----- src/pathspec.h | 43 +++-- tests-clar/repo/pathspec.c | 385 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 1062 insertions(+), 96 deletions(-) create mode 100644 include/git2/pathspec.h create mode 100644 tests-clar/repo/pathspec.c diff --git a/include/git2/index.h b/include/git2/index.h index 51694aded..1fb77efa3 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -138,6 +138,14 @@ typedef enum { GIT_INDEX_ADD_CHECK_PATHSPEC = (1u << 2), } git_index_add_option_t; +/** + * Match any index stage. + * + * Some index APIs take a stage to match; pass this value to match + * any entry matching the path regardless of stage. + */ +#define GIT_INDEX_STAGE_ANY -1 + /** @name Index File Functions * * These functions work on the index file itself. diff --git a/include/git2/pathspec.h b/include/git2/pathspec.h new file mode 100644 index 000000000..8122d9927 --- /dev/null +++ b/include/git2/pathspec.h @@ -0,0 +1,202 @@ +/* + * 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_pathspec_h__ +#define INCLUDE_git_pathspec_h__ + +#include "common.h" +#include "types.h" +#include "strarray.h" + +/** + * Compiled pathspec + */ +typedef struct git_pathspec git_pathspec; + +/** + * List of filenames matching a pathspec + */ +typedef struct git_pathspec_match_list git_pathspec_match_list; + +/** + * Options controlling how pathspec match should be executed + * + * - GIT_PATHSPEC_IGNORE_CASE forces match to ignore case; otherwise + * match will use native case sensitivity of platform + * - GIT_PATHSPEC_USE_CASE forces case sensitive match; otherwise + * match will use native case sensitivity of platform + * - GIT_PATHSPEC_NO_GLOB disables glob patterns and just uses simple + * string comparison for matching + * - GIT_PATHSPEC_NO_MATCH_ERROR means the match function will return + * GIT_ENOTFOUND if no matches are found; otherwise it will return 0 + * for success and `git_pathspec_match_list_entrycount` will be 0. + * - GIT_PATHSPEC_FIND_FAILURES only applies to a git_pathspec_match_list; + * it means to check file names against all unmatched patterns so that + * at the end of a match we can identify patterns that did not match any + * files. + * - GIT_PATHSPEC_FAILURES_ONLY only applies to a git_pathspec_match_list; + * it means to only check for mismatches and not record matched paths. + */ +typedef enum { + GIT_PATHSPEC_DEFAULT = 0, + GIT_PATHSPEC_IGNORE_CASE = (1u << 0), + GIT_PATHSPEC_USE_CASE = (1u << 1), + GIT_PATHSPEC_NO_GLOB = (1u << 2), + GIT_PATHSPEC_NO_MATCH_ERROR = (1u << 3), + GIT_PATHSPEC_FIND_FAILURES = (1u << 4), + GIT_PATHSPEC_FAILURES_ONLY = (1u << 5), +} git_pathspec_flag_t; + +/** + * Compile a pathspec + * + * @param out Output of the compiled pathspec + * @param flags Combination of git_pathspec_flag_t values + * @param pathspec A git_strarray of the paths to match + * @return 0 on success, <0 on failure + */ +GIT_EXTERN(int) git_pathspec_new( + git_pathspec **out, const git_strarray *pathspec); + +/** + * Free a pathspec + * + * @param ps The compiled pathspec + */ +GIT_EXTERN(void) git_pathspec_free(git_pathspec *ps); + +/** + * Try to match a path against a pathspec + * + * Unlike most of the other pathspec matching functions, this will not + * fall back on the native case-sensitivity for your platform. You must + * explicitly pass flags to control case sensitivity or else this will + * fall back on being case sensitive. + * + * @param ps The compiled pathspec + * @param flags Match flags to influence matching behavior + * @param path The pathname to attempt to match + * @return 1 is path matches spec, 0 if it does not + */ +GIT_EXTERN(int) git_pathspec_matches_path( + const git_pathspec *ps, uint32_t flags, const char *path); + +/** + * Match a pathspec against the working directory of a repository. + * + * This returns a `git_patchspec_match` object that contains the list of + * all files matching the given pathspec in the working directory of the + * repository. This handles git ignores (i.e. ignored files will not be + * considered to match the `pathspec` unless the file is tracked in the + * index). + * + * @param out Object with list of matching items + * @param repo The repository in which to match; bare repo is an error + * @param flags Options to control matching behavior + * @param ps Pathspec to be matched + * @return 0 on success, -1 on error, GIT_ENOTFOUND if no matches and + * the GIT_PATHSPEC_NO_MATCH_ERROR flag is used + */ +GIT_EXTERN(int) git_pathspec_match_workdir( + git_pathspec_match_list **out, + git_repository *repo, + uint32_t flags, + git_pathspec *ps); + +/** + * Match a pathspec against entries in an index. + * + * This returns a `git_patchspec_match` object that contains the list of + * all files matching the given pathspec in the index. + * + * NOTE: At the moment, the case sensitivity of this match is controlled + * by the current case-sensitivity of the index object itself and the + * USE_CASE and IGNORE_CASE flags will have no effect. This behavior will + * be corrected in a future release. + * + * @param out Object with list of matching items + * @param inex The index in which to match + * @param flags Options to control matching behavior + * @param ps Pathspec to be matched + * @return 0 on success, -1 on error, GIT_ENOTFOUND if no matches and + * the GIT_PATHSPEC_NO_MATCH_ERROR flag is used + */ +GIT_EXTERN(int) git_pathspec_match_index( + git_pathspec_match_list **out, + git_index *index, + uint32_t flags, + git_pathspec *ps); + +/** + * Match a pathspec against files in a tree. + * + * This returns a `git_patchspec_match` object that contains the list of + * all files matching the given pathspec in the given tree. + * + * @param out Object with list of matching items + * @param inex The index in which to match + * @param flags Options to control matching behavior + * @param ps Pathspec to be matched + * @return 0 on success, -1 on error, GIT_ENOTFOUND if no matches and + * the GIT_PATHSPEC_NO_MATCH_ERROR flag is used + */ +GIT_EXTERN(int) git_pathspec_match_tree( + git_pathspec_match_list **out, + git_tree *tree, + uint32_t flags, + git_pathspec *ps); + +/** + * Free memory associates with a git_pathspec_match_list + * + * @param m The git_pathspec_match_list to be freed + */ +GIT_EXTERN(void) git_pathspec_match_list_free(git_pathspec_match_list *m); + +/** + * Get the number of items in a match list. + * + * @param m The git_pathspec_match_list object + * @return Number of items in match list + */ +GIT_EXTERN(size_t) git_pathspec_match_list_entrycount( + const git_pathspec_match_list *m); + +/** + * Get a matching filename by position. + * + * @param m The git_pathspec_match_list object + * @param pos The index into the list + * @return The filename of the match + */ +GIT_EXTERN(const char *) git_pathspec_match_list_entry( + const git_pathspec_match_list *m, size_t pos); + +/** + * Get the number of pathspec items that did not match. + * + * This will be zero unless you passed GIT_PATHSPEC_FIND_FAILURES when + * generating the git_pathspec_match_list. + * + * @param m The git_pathspec_match_list object + * @return Number of items in original pathspec that had no matches + */ +GIT_EXTERN(size_t) git_pathspec_match_list_failed_entrycount( + const git_pathspec_match_list *m); + +/** + * Get an original pathspec string that had no matches. + * + * This will be return NULL for positions out of range. + * + * @param m The git_pathspec_match_list object + * @param pos The index into the failed items + * @return The pathspec pattern that didn't match anything + */ +GIT_EXTERN(const char *) git_pathspec_match_list_failed_entry( + const git_pathspec_match_list *m, size_t pos); + +#endif diff --git a/src/checkout.c b/src/checkout.c index 8f9ec64e4..ec9da7e2e 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -246,10 +246,10 @@ static int checkout_action_wd_only( bool remove = false; git_checkout_notify_t notify = GIT_CHECKOUT_NOTIFY_NONE; - if (!git_pathspec_match_path( + if (!git_pathspec__match( pathspec, wd->path, (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, - git_iterator_ignore_case(workdir), NULL)) + git_iterator_ignore_case(workdir), NULL, NULL)) return 0; /* check if item is tracked in the index but not in the checkout diff */ @@ -607,7 +607,7 @@ static int checkout_get_actions( uint32_t *actions = NULL; if (data->opts.paths.count > 0 && - git_pathspec_init(&pathspec, &data->opts.paths, &pathpool) < 0) + git_pathspec__vinit(&pathspec, &data->opts.paths, &pathpool) < 0) return -1; if ((error = git_iterator_current(&wditem, workdir)) < 0 && @@ -659,7 +659,7 @@ static int checkout_get_actions( goto fail; } - git_pathspec_free(&pathspec); + git_pathspec__vfree(&pathspec); git_pool_clear(&pathpool); return 0; @@ -670,7 +670,7 @@ fail: *actions_ptr = NULL; git__free(actions); - git_pathspec_free(&pathspec); + git_pathspec__vfree(&pathspec); git_pool_clear(&pathpool); return error; diff --git a/src/diff.c b/src/diff.c index 0980f412a..56232ebf4 100644 --- a/src/diff.c +++ b/src/diff.c @@ -81,11 +81,11 @@ static int diff_delta__from_one( DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_SUBMODULES)) return 0; - if (!git_pathspec_match_path( + if (!git_pathspec__match( &diff->pathspec, entry->path, DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH), DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE), - &matched_pathspec)) + &matched_pathspec, NULL)) return 0; delta = diff_delta__alloc(diff, status, entry->path); @@ -387,7 +387,7 @@ static int diff_list_apply_options( DIFF_FLAG_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE, icase); /* initialize pathspec from options */ - if (git_pathspec_init(&diff->pathspec, &opts->pathspec, pool) < 0) + if (git_pathspec__vinit(&diff->pathspec, &opts->pathspec, pool) < 0) return -1; } @@ -473,7 +473,7 @@ static void diff_list_free(git_diff_list *diff) } git_vector_free(&diff->deltas); - git_pathspec_free(&diff->pathspec); + git_pathspec__vfree(&diff->pathspec); git_pool_clear(&diff->pool); git__memzero(diff, sizeof(*diff)); @@ -634,11 +634,11 @@ static int maybe_modified( bool new_is_workdir = (info->new_iter->type == GIT_ITERATOR_TYPE_WORKDIR); const char *matched_pathspec; - if (!git_pathspec_match_path( + if (!git_pathspec__match( &diff->pathspec, oitem->path, DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH), DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE), - &matched_pathspec)) + &matched_pathspec, NULL)) return 0; memset(&noid, 0, sizeof(noid)); diff --git a/src/index.c b/src/index.c index ffa84e53f..21efd2c63 100644 --- a/src/index.c +++ b/src/index.c @@ -101,8 +101,6 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) static bool is_index_extended(git_index *index); static int write_index(git_index *index, git_filebuf *file); -static int index_find(size_t *at_pos, git_index *index, const char *path, int stage); - static void index_entry_free(git_index_entry *entry); static void index_entry_reuc_free(git_index_reuc_entry *reuc); @@ -114,7 +112,7 @@ static int index_srch(const void *key, const void *array_member) ret = strcmp(srch_key->path, entry->path); - if (ret == 0) + if (ret == 0 && srch_key->stage != GIT_INDEX_STAGE_ANY) ret = srch_key->stage - GIT_IDXENTRY_STAGE(entry); return ret; @@ -128,7 +126,7 @@ static int index_isrch(const void *key, const void *array_member) ret = strcasecmp(srch_key->path, entry->path); - if (ret == 0) + if (ret == 0 && srch_key->stage != GIT_INDEX_STAGE_ANY) ret = srch_key->stage - GIT_IDXENTRY_STAGE(entry); return ret; @@ -562,7 +560,7 @@ const git_index_entry *git_index_get_bypath( git_vector_sort(&index->entries); - if (index_find(&pos, index, path, stage) < 0) { + if (git_index__find(&pos, index, path, stage) < 0) { giterr_set(GITERR_INDEX, "Index does not contain %s", path); return NULL; } @@ -719,7 +717,8 @@ static int index_insert(git_index *index, git_index_entry *entry, int replace) entry->flags |= GIT_IDXENTRY_NAMEMASK; /* look if an entry with this path already exists */ - if (!index_find(&position, index, entry->path, GIT_IDXENTRY_STAGE(entry))) { + if (!git_index__find( + &position, index, entry->path, GIT_IDXENTRY_STAGE(entry))) { existing = (git_index_entry **)&index->entries.contents[position]; /* update filemode to existing values if stat is not trusted */ @@ -831,7 +830,7 @@ int git_index_remove(git_index *index, const char *path, int stage) git_vector_sort(&index->entries); - if (index_find(&position, index, path, stage) < 0) { + if (git_index__find(&position, index, path, stage) < 0) { giterr_set(GITERR_INDEX, "Index does not contain %s at stage %d", path, stage); return GIT_ENOTFOUND; @@ -887,7 +886,8 @@ int git_index_remove_directory(git_index *index, const char *dir, int stage) return error; } -static int index_find(size_t *at_pos, git_index *index, const char *path, int stage) +int git_index__find( + size_t *at_pos, git_index *index, const char *path, int stage) { struct entry_srch_key srch_key; @@ -896,7 +896,8 @@ static int index_find(size_t *at_pos, git_index *index, const char *path, int st srch_key.path = path; srch_key.stage = stage; - return git_vector_bsearch2(at_pos, &index->entries, index->entries_search, &srch_key); + return git_vector_bsearch2( + at_pos, &index->entries, index->entries_search, &srch_key); } int git_index_find(size_t *at_pos, git_index *index, const char *path) @@ -2053,7 +2054,7 @@ int git_index_add_all( git_iterator *wditer = NULL; const git_index_entry *wd = NULL; git_index_entry *entry; - git_pathspec_context ps; + git_pathspec ps; const char *match; size_t existing; bool no_fnmatch = (flags & GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH) != 0; @@ -2074,7 +2075,7 @@ int git_index_add_all( if (git_repository__cvar(&ignorecase, repo, GIT_CVAR_IGNORECASE) < 0) return -1; - if ((error = git_pathspec_context_init(&ps, paths)) < 0) + if ((error = git_pathspec__init(&ps, paths)) < 0) return error; /* optionally check that pathspec doesn't mention any ignored files */ @@ -2091,14 +2092,14 @@ int git_index_add_all( while (!(error = git_iterator_advance(&wd, wditer))) { /* check if path actually matches */ - if (!git_pathspec_match_path( - &ps.pathspec, wd->path, no_fnmatch, ignorecase, &match)) + if (!git_pathspec__match( + &ps.pathspec, wd->path, no_fnmatch, ignorecase, &match, NULL)) continue; /* skip ignored items that are not already in the index */ if ((flags & GIT_INDEX_ADD_FORCE) == 0 && git_iterator_current_is_ignored(wditer) && - index_find(&existing, index, wd->path, 0) < 0) + git_index__find(&existing, index, wd->path, 0) < 0) continue; /* issue notification callback if requested */ @@ -2148,7 +2149,7 @@ int git_index_add_all( cleanup: git_iterator_free(wditer); - git_pathspec_context_free(&ps); + git_pathspec__clear(&ps); return error; } @@ -2168,13 +2169,13 @@ static int index_apply_to_all( { int error = 0; size_t i; - git_pathspec_context ps; + git_pathspec ps; const char *match; git_buf path = GIT_BUF_INIT; assert(index); - if ((error = git_pathspec_context_init(&ps, paths)) < 0) + if ((error = git_pathspec__init(&ps, paths)) < 0) return error; git_vector_sort(&index->entries); @@ -2183,8 +2184,9 @@ static int index_apply_to_all( git_index_entry *entry = git_vector_get(&index->entries, i); /* check if path actually matches */ - if (!git_pathspec_match_path( - &ps.pathspec, entry->path, false, index->ignore_case, &match)) + if (!git_pathspec__match( + &ps.pathspec, entry->path, false, index->ignore_case, + &match, NULL)) continue; /* issue notification callback if requested */ @@ -2231,7 +2233,7 @@ static int index_apply_to_all( } git_buf_free(&path); - git_pathspec_context_free(&ps); + git_pathspec__clear(&ps); return error; } diff --git a/src/index.h b/src/index.h index a59107a7b..40577e105 100644 --- a/src/index.h +++ b/src/index.h @@ -47,13 +47,17 @@ struct git_index_conflict_iterator { size_t cur; }; -extern void git_index_entry__init_from_stat(git_index_entry *entry, struct stat *st); +extern void git_index_entry__init_from_stat( + git_index_entry *entry, struct stat *st); extern size_t git_index__prefix_position(git_index *index, const char *path); extern int git_index_entry__cmp(const void *a, const void *b); extern int git_index_entry__cmp_icase(const void *a, const void *b); +extern int git_index__find( + size_t *at_pos, git_index *index, const char *path, int stage); + extern void git_index__set_ignore_case(git_index *index, bool ignore_case); #endif diff --git a/src/pathspec.c b/src/pathspec.c index f029836d0..35421dbef 100644 --- a/src/pathspec.c +++ b/src/pathspec.c @@ -5,9 +5,13 @@ * a Linking Exception. For full terms see the included COPYING file. */ +#include "git2/pathspec.h" #include "pathspec.h" #include "buf_text.h" #include "attr_file.h" +#include "iterator.h" +#include "repository.h" +#include "index.h" /* what is the common non-wildcard prefix for all items in the pathspec */ char *git_pathspec_prefix(const git_strarray *pathspec) @@ -56,7 +60,7 @@ bool git_pathspec_is_empty(const git_strarray *pathspec) } /* build a vector of fnmatch patterns to evaluate efficiently */ -int git_pathspec_init( +int git_pathspec__vinit( git_vector *vspec, const git_strarray *strspec, git_pool *strpool) { size_t i; @@ -93,7 +97,7 @@ int git_pathspec_init( } /* free data from the pathspec vector */ -void git_pathspec_free(git_vector *vspec) +void git_pathspec__vfree(git_vector *vspec) { git_attr_fnmatch *match; unsigned int i; @@ -106,88 +110,436 @@ void git_pathspec_free(git_vector *vspec) git_vector_free(vspec); } +struct pathspec_match_context { + int fnmatch_flags; + int (*strcomp)(const char *, const char *); + int (*strncomp)(const char *, const char *, size_t); +}; + +static void pathspec_match_context_init( + struct pathspec_match_context *ctxt, + bool disable_fnmatch, + bool casefold) +{ + if (disable_fnmatch) + ctxt->fnmatch_flags = -1; + else if (casefold) + ctxt->fnmatch_flags = FNM_CASEFOLD; + else + ctxt->fnmatch_flags = 0; + + if (casefold) { + ctxt->strcomp = git__strcasecmp; + ctxt->strncomp = git__strncasecmp; + } else { + ctxt->strcomp = git__strcmp; + ctxt->strncomp = git__strncmp; + } +} + +static int pathspec_match_one( + const git_attr_fnmatch *match, + struct pathspec_match_context *ctxt, + const char *path) +{ + int result = (match->flags & GIT_ATTR_FNMATCH_MATCH_ALL) ? 0 : FNM_NOMATCH; + + if (result == FNM_NOMATCH) + result = ctxt->strcomp(match->pattern, path) ? FNM_NOMATCH : 0; + + if (ctxt->fnmatch_flags >= 0 && result == FNM_NOMATCH) + result = p_fnmatch(match->pattern, path, ctxt->fnmatch_flags); + + /* if we didn't match, look for exact dirname prefix match */ + if (result == FNM_NOMATCH && + (match->flags & GIT_ATTR_FNMATCH_HASWILD) == 0 && + ctxt->strncomp(path, match->pattern, match->length) == 0 && + path[match->length] == '/') + result = 0; + + if (result == 0) + return (match->flags & GIT_ATTR_FNMATCH_NEGATIVE) ? 0 : 1; + return -1; +} + /* match a path against the vectorized pathspec */ -bool git_pathspec_match_path( - git_vector *vspec, +bool git_pathspec__match( + const git_vector *vspec, const char *path, bool disable_fnmatch, bool casefold, - const char **matched_pathspec) + const char **matched_pathspec, + size_t *matched_at) { size_t i; - git_attr_fnmatch *match; - int fnmatch_flags = 0; - int (*use_strcmp)(const char *, const char *); - int (*use_strncmp)(const char *, const char *, size_t); + const git_attr_fnmatch *match; + struct pathspec_match_context ctxt; if (matched_pathspec) *matched_pathspec = NULL; + if (matched_at) + *matched_at = GIT_PATHSPEC_NOMATCH; if (!vspec || !vspec->length) return true; - if (disable_fnmatch) - fnmatch_flags = -1; - else if (casefold) - fnmatch_flags = FNM_CASEFOLD; + pathspec_match_context_init(&ctxt, disable_fnmatch, casefold); - if (casefold) { - use_strcmp = git__strcasecmp; - use_strncmp = git__strncasecmp; - } else { - use_strcmp = git__strcmp; - use_strncmp = git__strncmp; + git_vector_foreach(vspec, i, match) { + int result = pathspec_match_one(match, &ctxt, path); + + if (result >= 0) { + if (matched_pathspec) + *matched_pathspec = match->pattern; + if (matched_at) + *matched_at = i; + + return (result != 0); + } } - git_vector_foreach(vspec, i, match) { - int result = (match->flags & GIT_ATTR_FNMATCH_MATCH_ALL) ? 0 : FNM_NOMATCH; + return false; +} - if (result == FNM_NOMATCH) - result = use_strcmp(match->pattern, path) ? FNM_NOMATCH : 0; - if (fnmatch_flags >= 0 && result == FNM_NOMATCH) - result = p_fnmatch(match->pattern, path, fnmatch_flags); +int git_pathspec__init(git_pathspec *ps, const git_strarray *paths) +{ + int error = 0; - /* if we didn't match, look for exact dirname prefix match */ - if (result == FNM_NOMATCH && - (match->flags & GIT_ATTR_FNMATCH_HASWILD) == 0 && - use_strncmp(path, match->pattern, match->length) == 0 && - path[match->length] == '/') - result = 0; + memset(ps, 0, sizeof(*ps)); - if (result == 0) { - if (matched_pathspec) - *matched_pathspec = match->pattern; + ps->prefix = git_pathspec_prefix(paths); + + if ((error = git_pool_init(&ps->pool, 1, 0)) < 0 || + (error = git_pathspec__vinit(&ps->pathspec, paths, &ps->pool)) < 0) + git_pathspec__clear(ps); + + return error; +} + +void git_pathspec__clear(git_pathspec *ps) +{ + git__free(ps->prefix); + git_pathspec__vfree(&ps->pathspec); + git_pool_clear(&ps->pool); + memset(ps, 0, sizeof(*ps)); +} + +int git_pathspec_new(git_pathspec **out, const git_strarray *pathspec) +{ + int error = 0; + git_pathspec *ps = git__malloc(sizeof(git_pathspec)); + GITERR_CHECK_ALLOC(ps); + + if ((error = git_pathspec__init(ps, pathspec)) < 0) { + git__free(ps); + return error; + } + + GIT_REFCOUNT_INC(ps); + *out = ps; + return 0; +} + +static void pathspec_free(git_pathspec *ps) +{ + git_pathspec__clear(ps); + git__free(ps); +} + +void git_pathspec_free(git_pathspec *ps) +{ + if (!ps) + return; + GIT_REFCOUNT_DEC(ps, pathspec_free); +} - return (match->flags & GIT_ATTR_FNMATCH_NEGATIVE) ? false : true; +int git_pathspec_matches_path( + const git_pathspec *ps, uint32_t flags, const char *path) +{ + bool no_fnmatch = (flags & GIT_PATHSPEC_NO_GLOB) != 0; + bool casefold = (flags & GIT_PATHSPEC_IGNORE_CASE) != 0; + + assert(ps && path); + + return (0 != git_pathspec__match( + &ps->pathspec, path, no_fnmatch, casefold, NULL, NULL)); +} + +static void pathspec_match_free(git_pathspec_match_list *m) +{ + git_pathspec_free(m->pathspec); + m->pathspec = NULL; + + git_array_clear(m->matches); + git_array_clear(m->failures); + git_pool_clear(&m->pool); + git__free(m); +} + +static git_pathspec_match_list *pathspec_match_alloc(git_pathspec *ps) +{ + git_pathspec_match_list *m = git__calloc(1, sizeof(git_pathspec_match_list)); + + if (m != NULL && git_pool_init(&m->pool, 1, 0) < 0) { + pathspec_match_free(m); + m = NULL; + } + + /* need to keep reference to pathspec and increment refcount because + * failures array stores pointers to the pattern strings of the + * pathspec that had no matches + */ + GIT_REFCOUNT_INC(ps); + m->pathspec = ps; + + return m; +} + +GIT_INLINE(void) pathspec_mark_pattern(uint8_t *used, size_t pos, size_t *ct) +{ + if (!used[pos]) { + used[pos] = 1; + (*ct)++; + } +} + +static int pathspec_match_from_iterator( + git_pathspec_match_list **out, + git_iterator *iter, + uint32_t flags, + git_pathspec *ps) +{ + int error = 0; + git_pathspec_match_list *m; + const git_index_entry *entry = NULL; + struct pathspec_match_context ctxt; + git_vector *patterns = &ps->pathspec; + bool find_failures = (flags & GIT_PATHSPEC_FIND_FAILURES) != 0; + bool failures_only = (flags & GIT_PATHSPEC_FAILURES_ONLY) != 0; + size_t pos, used_ct = 0, found_files = 0; + git_index *index = NULL; + uint8_t *used_patterns = NULL; + char **file; + + *out = m = pathspec_match_alloc(ps); + GITERR_CHECK_ALLOC(m); + + if ((error = git_iterator_reset(iter, ps->prefix, ps->prefix)) < 0) + goto done; + + if (patterns->length > 0) { + used_patterns = git__calloc(patterns->length, sizeof(uint8_t)); + GITERR_CHECK_ALLOC(used_patterns); + } + + if (git_iterator_type(iter) == GIT_ITERATOR_TYPE_WORKDIR && + (error = git_repository_index__weakptr( + &index, git_iterator_owner(iter))) < 0) + goto done; + + pathspec_match_context_init(&ctxt, + (flags & GIT_PATHSPEC_NO_GLOB) != 0, git_iterator_ignore_case(iter)); + + while (!(error = git_iterator_advance(&entry, iter))) { + int result = -1; + + for (pos = 0; pos < patterns->length; ++pos) { + const git_attr_fnmatch *pat = git_vector_get(patterns, pos); + + result = pathspec_match_one(pat, &ctxt, entry->path); + if (result >= 0) + break; + } + + /* no matches for this path */ + if (result < 0) + continue; + + /* if result was a negative pattern match, then don't list file */ + if (!result) { + pathspec_mark_pattern(used_patterns, pos, &used_ct); + continue; + } + + /* check if path is untracked and ignored */ + if (index != NULL && + git_iterator_current_is_ignored(iter) && + git_index__find(NULL, index, entry->path, GIT_INDEX_STAGE_ANY) < 0) + continue; + + /* mark the matched pattern as used */ + pathspec_mark_pattern(used_patterns, pos, &used_ct); + ++found_files; + + /* if find_failures is on, check if any later patterns also match */ + if (find_failures && used_ct < patterns->length) { + for (++pos; pos < patterns->length; ++pos) { + const git_attr_fnmatch *pat = git_vector_get(patterns, pos); + if (used_patterns[pos]) + continue; + + if (pathspec_match_one(pat, &ctxt, entry->path) > 0) + pathspec_mark_pattern(used_patterns, pos, &used_ct); + } + } + + /* if only looking at failures, exit early or just continue */ + if (failures_only) { + if (used_ct == patterns->length) + break; + continue; + } + + /* insert matched path into matches array */ + if ((file = git_array_alloc(m->matches)) == NULL || + (*file = git_pool_strdup(&m->pool, entry->path)) == NULL) { + error = -1; + goto done; } } - return false; + if (error < 0 && error != GIT_ITEROVER) + goto done; + error = 0; + + /* insert patterns that had no matches into failures array */ + if (find_failures && used_ct < patterns->length) { + for (pos = 0; pos < patterns->length; ++pos) { + const git_attr_fnmatch *pat = git_vector_get(patterns, pos); + if (used_patterns[pos]) + continue; + + if ((file = git_array_alloc(m->failures)) == NULL || + (*file = git_pool_strdup(&m->pool, pat->pattern)) == NULL) { + error = -1; + goto done; + } + } + } + + /* 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"); + error = GIT_ENOTFOUND; + } + +done: + git__free(used_patterns); + + if (error < 0) { + pathspec_match_free(m); + *out = NULL; + } + + return error; } +static git_iterator_flag_t pathspec_match_iter_flags(uint32_t flags) +{ + git_iterator_flag_t f = 0; + + if ((flags & GIT_PATHSPEC_IGNORE_CASE) != 0) + f |= GIT_ITERATOR_IGNORE_CASE; + else if ((flags & GIT_PATHSPEC_USE_CASE) != 0) + f |= GIT_ITERATOR_DONT_IGNORE_CASE; -int git_pathspec_context_init( - git_pathspec_context *ctxt, const git_strarray *paths) + return f; +} + +int git_pathspec_match_workdir( + git_pathspec_match_list **out, + git_repository *repo, + uint32_t flags, + git_pathspec *ps) { int error = 0; + git_iterator *iter; + + assert(out && repo); - memset(ctxt, 0, sizeof(*ctxt)); + if (!(error = git_iterator_for_workdir( + &iter, repo, pathspec_match_iter_flags(flags), NULL, NULL))) { - ctxt->prefix = git_pathspec_prefix(paths); + error = pathspec_match_from_iterator(out, iter, flags, ps); - if ((error = git_pool_init(&ctxt->pool, 1, 0)) < 0 || - (error = git_pathspec_init(&ctxt->pathspec, paths, &ctxt->pool)) < 0) - git_pathspec_context_free(ctxt); + git_iterator_free(iter); + } return error; } -void git_pathspec_context_free( - git_pathspec_context *ctxt) +int git_pathspec_match_index( + git_pathspec_match_list **out, + git_index *index, + uint32_t flags, + git_pathspec *ps) +{ + int error = 0; + git_iterator *iter; + + assert(out && index); + + if (!(error = git_iterator_for_index( + &iter, index, pathspec_match_iter_flags(flags), NULL, NULL))) { + + error = pathspec_match_from_iterator(out, iter, flags, ps); + + git_iterator_free(iter); + } + + return error; +} + +int git_pathspec_match_tree( + git_pathspec_match_list **out, + git_tree *tree, + uint32_t flags, + git_pathspec *ps) +{ + int error = 0; + git_iterator *iter; + + assert(out && tree); + + if (!(error = git_iterator_for_tree( + &iter, tree, pathspec_match_iter_flags(flags), NULL, NULL))) { + + error = pathspec_match_from_iterator(out, iter, flags, ps); + + git_iterator_free(iter); + } + + return error; +} + +void git_pathspec_match_list_free(git_pathspec_match_list *m) +{ + pathspec_match_free(m); +} + +size_t git_pathspec_match_list_entrycount( + const git_pathspec_match_list *m) +{ + return git_array_size(m->matches); +} + +const char *git_pathspec_match_list_entry( + const git_pathspec_match_list *m, size_t pos) +{ + char **entry = git_array_get(m->matches, pos); + return entry ? *entry : NULL; +} + +size_t git_pathspec_match_list_failed_entrycount( + const git_pathspec_match_list *m) +{ + return git_array_size(m->failures); +} + +const char * git_pathspec_match_list_failed_entry( + const git_pathspec_match_list *m, size_t pos) { - git__free(ctxt->prefix); - git_pathspec_free(&ctxt->pathspec); - git_pool_clear(&ctxt->pool); - memset(ctxt, 0, sizeof(*ctxt)); + char **entry = git_array_get(m->failures, pos); + return entry ? *entry : NULL; } diff --git a/src/pathspec.h b/src/pathspec.h index f6509df4c..e7edfea38 100644 --- a/src/pathspec.h +++ b/src/pathspec.h @@ -8,9 +8,27 @@ #define INCLUDE_pathspec_h__ #include "common.h" +#include #include "buffer.h" #include "vector.h" #include "pool.h" +#include "array.h" + +/* public compiled pathspec */ +struct git_pathspec { + git_refcount rc; + char *prefix; + git_vector pathspec; + git_pool pool; +}; + +/* public interface to pathspec matching */ +struct git_pathspec_match_list { + git_pathspec *pathspec; + git_array_t(char *) matches; + git_array_t(char *) failures; + git_pool pool; +}; /* what is the common non-wildcard prefix for all items in the pathspec */ extern char *git_pathspec_prefix(const git_strarray *pathspec); @@ -19,36 +37,31 @@ extern char *git_pathspec_prefix(const git_strarray *pathspec); extern bool git_pathspec_is_empty(const git_strarray *pathspec); /* build a vector of fnmatch patterns to evaluate efficiently */ -extern int git_pathspec_init( +extern int git_pathspec__vinit( git_vector *vspec, const git_strarray *strspec, git_pool *strpool); /* free data from the pathspec vector */ -extern void git_pathspec_free(git_vector *vspec); +extern void git_pathspec__vfree(git_vector *vspec); + +#define GIT_PATHSPEC_NOMATCH ((size_t)-1) /* * Match a path against the vectorized pathspec. * The matched pathspec is passed back into the `matched_pathspec` parameter, * unless it is passed as NULL by the caller. */ -extern bool git_pathspec_match_path( - git_vector *vspec, +extern bool git_pathspec__match( + const git_vector *vspec, const char *path, bool disable_fnmatch, bool casefold, - const char **matched_pathspec); + const char **matched_pathspec, + size_t *matched_at); /* easy pathspec setup */ -typedef struct { - char *prefix; - git_vector pathspec; - git_pool pool; -} git_pathspec_context; - -extern int git_pathspec_context_init( - git_pathspec_context *ctxt, const git_strarray *paths); +extern int git_pathspec__init(git_pathspec *ps, const git_strarray *paths); -extern void git_pathspec_context_free( - git_pathspec_context *ctxt); +extern void git_pathspec__clear(git_pathspec *ps); #endif diff --git a/tests-clar/repo/pathspec.c b/tests-clar/repo/pathspec.c new file mode 100644 index 000000000..334066b67 --- /dev/null +++ b/tests-clar/repo/pathspec.c @@ -0,0 +1,385 @@ +#include "clar_libgit2.h" +#include "git2/pathspec.h" + +static git_repository *g_repo; + +void test_repo_pathspec__initialize(void) +{ + g_repo = cl_git_sandbox_init("status"); +} + +void test_repo_pathspec__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +static char *str0[] = { "*_file", "new_file", "garbage" }; +static char *str1[] = { "*_FILE", "NEW_FILE", "GARBAGE" }; +static char *str2[] = { "staged_*" }; +static char *str3[] = { "!subdir", "*_file", "new_file" }; +static char *str4[] = { "*" }; +static char *str5[] = { "S*" }; + +void test_repo_pathspec__workdir0(void) +{ + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "*_file", "new_file", "garbage" } */ + s.strings = str0; s.count = ARRAY_SIZE(str0); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, 0, ps)); + cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); + cl_assert_equal_s("garbage", git_pathspec_match_list_failed_entry(m, 0)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_FIND_FAILURES | GIT_PATHSPEC_FAILURES_ONLY, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); +} + +void test_repo_pathspec__workdir1(void) +{ + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "*_FILE", "NEW_FILE", "GARBAGE" } */ + s.strings = str1; s.count = ARRAY_SIZE(str1); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_IGNORE_CASE, ps)); + cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_USE_CASE, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_fail(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_USE_CASE | GIT_PATHSPEC_NO_MATCH_ERROR, ps)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_IGNORE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_USE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(3, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); +} + +void test_repo_pathspec__workdir2(void) +{ + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "staged_*" } */ + s.strings = str2; s.count = ARRAY_SIZE(str2); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, 0, ps)); + cl_assert_equal_sz(5, git_pathspec_match_list_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(5, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_fail(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_NO_GLOB | GIT_PATHSPEC_NO_MATCH_ERROR, ps)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_NO_GLOB | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); +} + +void test_repo_pathspec__workdir3(void) +{ + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "!subdir", "*_file", "new_file" } */ + s.strings = str3; s.count = ARRAY_SIZE(str3); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, 0, ps)); + cl_assert_equal_sz(7, git_pathspec_match_list_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(7, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + + cl_assert_equal_s("current_file", git_pathspec_match_list_entry(m, 0)); + cl_assert_equal_s("modified_file", git_pathspec_match_list_entry(m, 1)); + cl_assert_equal_s("new_file", git_pathspec_match_list_entry(m, 2)); + cl_assert_equal_s("staged_changes_modified_file", git_pathspec_match_list_entry(m, 3)); + cl_assert_equal_s("staged_delete_modified_file", git_pathspec_match_list_entry(m, 4)); + cl_assert_equal_s("staged_new_file", git_pathspec_match_list_entry(m, 5)); + cl_assert_equal_s("staged_new_file_modified_file", git_pathspec_match_list_entry(m, 6)); + cl_assert_equal_s(NULL, git_pathspec_match_list_entry(m, 7)); + + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); +} + +void test_repo_pathspec__workdir4(void) +{ + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "*" } */ + s.strings = str4; s.count = ARRAY_SIZE(str4); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, 0, ps)); + cl_assert_equal_sz(13, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_s("这", git_pathspec_match_list_entry(m, 12)); + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); +} + + +void test_repo_pathspec__index0(void) +{ + git_index *idx; + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + cl_git_pass(git_repository_index(&idx, g_repo)); + + /* { "*_file", "new_file", "garbage" } */ + s.strings = str0; s.count = ARRAY_SIZE(str0); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_index(&m, idx, 0, ps)); + cl_assert_equal_sz(9, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + cl_assert_equal_s("current_file", git_pathspec_match_list_entry(m, 0)); + cl_assert_equal_s("modified_file", git_pathspec_match_list_entry(m, 1)); + cl_assert_equal_s("staged_changes_modified_file", git_pathspec_match_list_entry(m, 2)); + cl_assert_equal_s("staged_new_file", git_pathspec_match_list_entry(m, 3)); + cl_assert_equal_s("staged_new_file_deleted_file", git_pathspec_match_list_entry(m, 4)); + cl_assert_equal_s("staged_new_file_modified_file", git_pathspec_match_list_entry(m, 5)); + cl_assert_equal_s("subdir/current_file", git_pathspec_match_list_entry(m, 6)); + cl_assert_equal_s("subdir/deleted_file", git_pathspec_match_list_entry(m, 7)); + cl_assert_equal_s("subdir/modified_file", git_pathspec_match_list_entry(m, 8)); + cl_assert_equal_s(NULL, git_pathspec_match_list_entry(m, 9)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_index(&m, idx, + GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(9, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(2, git_pathspec_match_list_failed_entrycount(m)); + cl_assert_equal_s("new_file", git_pathspec_match_list_failed_entry(m, 0)); + cl_assert_equal_s("garbage", git_pathspec_match_list_failed_entry(m, 1)); + cl_assert_equal_s(NULL, git_pathspec_match_list_failed_entry(m, 2)); + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); + git_index_free(idx); +} + +void test_repo_pathspec__index1(void) +{ + /* Currently the USE_CASE and IGNORE_CASE flags don't work on the + * index because the index sort order for the index iterator is + * set by the index itself. I think the correct fix is for the + * index not to embed a global sort order but to support traversal + * in either case sensitive or insensitive order in a stateless + * manner. + * + * Anyhow, as it is, there is no point in doing this test. + */ +#if 0 + git_index *idx; + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + cl_git_pass(git_repository_index(&idx, g_repo)); + + /* { "*_FILE", "NEW_FILE", "GARBAGE" } */ + s.strings = str1; s.count = ARRAY_SIZE(str1); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_index(&m, idx, + GIT_PATHSPEC_USE_CASE, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_index(&m, idx, + GIT_PATHSPEC_USE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(3, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_index(&m, idx, + GIT_PATHSPEC_IGNORE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(2, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); + git_index_free(idx); +#endif +} + +void test_repo_pathspec__tree0(void) +{ + git_object *tree; + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "*_file", "new_file", "garbage" } */ + s.strings = str0; s.count = ARRAY_SIZE(str0); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_revparse_single(&tree, g_repo, "HEAD~2^{tree}")); + + cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, + GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(4, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_s("current_file", git_pathspec_match_list_entry(m, 0)); + cl_assert_equal_s("modified_file", git_pathspec_match_list_entry(m, 1)); + cl_assert_equal_s("staged_changes_modified_file", git_pathspec_match_list_entry(m, 2)); + cl_assert_equal_s("staged_delete_modified_file", git_pathspec_match_list_entry(m, 3)); + cl_assert_equal_s(NULL, git_pathspec_match_list_entry(m, 4)); + cl_assert_equal_sz(2, git_pathspec_match_list_failed_entrycount(m)); + cl_assert_equal_s("new_file", git_pathspec_match_list_failed_entry(m, 0)); + cl_assert_equal_s("garbage", git_pathspec_match_list_failed_entry(m, 1)); + cl_assert_equal_s(NULL, git_pathspec_match_list_failed_entry(m, 2)); + git_pathspec_match_list_free(m); + + git_object_free(tree); + + cl_git_pass(git_revparse_single(&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, + GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(7, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_s("current_file", git_pathspec_match_list_entry(m, 0)); + cl_assert_equal_s("modified_file", git_pathspec_match_list_entry(m, 1)); + cl_assert_equal_s("staged_changes_modified_file", git_pathspec_match_list_entry(m, 2)); + cl_assert_equal_s("staged_delete_modified_file", git_pathspec_match_list_entry(m, 3)); + cl_assert_equal_s("subdir/current_file", git_pathspec_match_list_entry(m, 4)); + cl_assert_equal_s("subdir/deleted_file", git_pathspec_match_list_entry(m, 5)); + cl_assert_equal_s("subdir/modified_file", git_pathspec_match_list_entry(m, 6)); + cl_assert_equal_s(NULL, git_pathspec_match_list_entry(m, 7)); + cl_assert_equal_sz(2, git_pathspec_match_list_failed_entrycount(m)); + cl_assert_equal_s("new_file", git_pathspec_match_list_failed_entry(m, 0)); + cl_assert_equal_s("garbage", git_pathspec_match_list_failed_entry(m, 1)); + cl_assert_equal_s(NULL, git_pathspec_match_list_failed_entry(m, 2)); + git_pathspec_match_list_free(m); + + git_object_free(tree); + + git_pathspec_free(ps); +} + +void test_repo_pathspec__tree5(void) +{ + git_object *tree; + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "S*" } */ + s.strings = str5; s.count = ARRAY_SIZE(str5); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_revparse_single(&tree, g_repo, "HEAD~2^{tree}")); + + cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, + GIT_PATHSPEC_USE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, + GIT_PATHSPEC_IGNORE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(5, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_s("staged_changes", git_pathspec_match_list_entry(m, 0)); + cl_assert_equal_s("staged_delete_modified_file", git_pathspec_match_list_entry(m, 4)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + git_object_free(tree); + + cl_git_pass(git_revparse_single(&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, + GIT_PATHSPEC_IGNORE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(9, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_s("staged_changes", git_pathspec_match_list_entry(m, 0)); + cl_assert_equal_s("subdir.txt", git_pathspec_match_list_entry(m, 5)); + cl_assert_equal_s("subdir/current_file", git_pathspec_match_list_entry(m, 6)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + git_object_free(tree); + + git_pathspec_free(ps); +} + +void test_repo_pathspec__in_memory(void) +{ + static char *strings[] = { "one", "two*", "!three*", "*four" }; + git_strarray s = { strings, ARRAY_SIZE(strings) }; + git_pathspec *ps; + + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_assert(git_pathspec_matches_path(ps, 0, "one")); + cl_assert(!git_pathspec_matches_path(ps, 0, "ONE")); + cl_assert(git_pathspec_matches_path(ps, GIT_PATHSPEC_IGNORE_CASE, "ONE")); + cl_assert(git_pathspec_matches_path(ps, 0, "two")); + cl_assert(git_pathspec_matches_path(ps, 0, "two.txt")); + cl_assert(!git_pathspec_matches_path(ps, 0, "three.txt")); + cl_assert(git_pathspec_matches_path(ps, 0, "anything.four")); + cl_assert(!git_pathspec_matches_path(ps, 0, "three.four")); + cl_assert(!git_pathspec_matches_path(ps, 0, "nomatch")); + cl_assert(!git_pathspec_matches_path(ps, GIT_PATHSPEC_NO_GLOB, "two")); + cl_assert(git_pathspec_matches_path(ps, GIT_PATHSPEC_NO_GLOB, "two*")); + cl_assert(!git_pathspec_matches_path(ps, GIT_PATHSPEC_NO_GLOB, "anyfour")); + cl_assert(git_pathspec_matches_path(ps, GIT_PATHSPEC_NO_GLOB, "*four")); + + git_pathspec_free(ps); +} -- cgit v1.2.1 From 0d44d3dc84d6996c72d49e6bb8036b9c8edec9e0 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 24 Jun 2013 23:21:23 -0700 Subject: Extending log example code This adds more command line processing to the example version of log. In particular, this adds the funky command line processing that allows an arbitrary series of revisions followed by an arbitrary number of paths and/or glob patterns. The actual logging part still isn't implemented. --- examples/log.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/examples/log.c b/examples/log.c index f92b66996..83e5cbcc0 100644 --- a/examples/log.c +++ b/examples/log.c @@ -32,24 +32,71 @@ static void usage(const char *message, const char *arg) int main(int argc, char *argv[]) { - int i; + int i, j, last_nonoption, force_files = -1; char *a; const char *dir = "."; git_repository *repo; + git_revwalk *walker; + git_revspec revs; git_threads_init(); - for (i = 1; i < argc; ++i) { + for (i = 1, last_nonoption = 1; i < argc; ++i) { a = argv[i]; - if (a[0] != '-') { + if (a[0] != '-' || force_files > 0) { + /* condense args not prefixed with '-' to start of argv */ + if (last_nonoption != i) + argv[last_nonoption] = a; + last_nonoption++; } + else if (!strcmp(a, "--")) + force_files = last_nonoption; /* copy all args as filenames */ else if (!check_str_param(a, "--git-dir=", &dir)) usage("Unknown argument", a); } check(git_repository_open_ext(&repo, dir, 0, NULL), "Could not open repository"); + check(git_revwalk_new(&walker, repo), + "Could not create revision walker"); + + if (force_files < 0) + force_files = last_nonoption; + + for (i = 1; i < force_files; ) { + printf("option '%s'\n", argv[i]); + + if (!git_revparse(&revs, repo, argv[i])) { + char str[GIT_OID_HEXSZ+1]; + + if (revs.from) { + git_oid_tostr(str, sizeof(str), git_object_id(revs.from)); + printf("revwalk from %s\n", str); + } + if (revs.to) { + git_oid_tostr(str, sizeof(str), git_object_id(revs.to)); + printf("revwalk to %s\n", str); + } + + /* push / hide / merge-base in revwalker */ + + ++i; + } else { + /* shift array down */ + for (a = argv[i], j = i + 1; j < force_files; ++j) + argv[j - 1] = argv[j]; + argv[--force_files] = a; + } + } + + if (i == 1) { + /* no revs pushed so push HEAD */ + printf("revwalk HEAD\n"); + } + + for (i = force_files; i < last_nonoption; ++i) + printf("file %s\n", argv[i]); git_repository_free(repo); git_threads_shutdown(); -- cgit v1.2.1 From d0628e2feeaeebf78a6b67fa4ca3fc658aa4744a Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 25 Jun 2013 15:39:13 -0700 Subject: More progress on log example --- examples/log.c | 208 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 146 insertions(+), 62 deletions(-) diff --git a/examples/log.c b/examples/log.c index 83e5cbcc0..5603d743d 100644 --- a/examples/log.c +++ b/examples/log.c @@ -3,21 +3,15 @@ #include #include -static void check(int error, const char *message) +static void check(int error, const char *message, const char *arg) { - if (error) { + if (!error) + return; + if (arg) + fprintf(stderr, "%s '%s' (%d)\n", message, arg, error); + else fprintf(stderr, "%s (%d)\n", message, error); - exit(1); - } -} - -static int check_str_param(const char *arg, const char *pat, const char **val) -{ - size_t len = strlen(pat); - if (strncmp(arg, pat, len)) - return 0; - *val = (const char *)(arg + len); - return 1; + exit(1); } static void usage(const char *message, const char *arg) @@ -30,75 +24,165 @@ static void usage(const char *message, const char *arg) exit(1); } -int main(int argc, char *argv[]) -{ - int i, j, last_nonoption, force_files = -1; - char *a; - const char *dir = "."; +struct log_state { git_repository *repo; + const char *repodir; git_revwalk *walker; - git_revspec revs; + int hide; + int sorting; +}; - git_threads_init(); +static void set_sorting(struct log_state *s, unsigned int sort_mode) +{ + if (!s->repo) { + if (!s->repodir) s->repodir = "."; + check(git_repository_open_ext(&s->repo, s->repodir, 0, NULL), + "Could not open repository", s->repodir); + } - for (i = 1, last_nonoption = 1; i < argc; ++i) { - a = argv[i]; + if (!s->walker) + check(git_revwalk_new(&s->walker, s->repo), + "Could not create revision walker", NULL); + + if (sort_mode == GIT_SORT_REVERSE) + s->sorting = s->sorting ^ GIT_SORT_REVERSE; + else + s->sorting = sort_mode | (s->sorting & GIT_SORT_REVERSE); + + git_revwalk_sorting(s->walker, s->sorting); +} + +static void push_rev(struct log_state *s, git_object *obj, int hide) +{ + hide = s->hide ^ hide; + + if (!s->walker) + check(git_revwalk_new(&s->walker, s->repo), + "Could not create revision walker", NULL); + + if (!obj) + check(git_revwalk_push_head(s->walker), + "Could not find repository HEAD", NULL); + else if (hide) + check(git_revwalk_hide(s->walker, git_object_id(obj)), + "Reference does not refer to a commit", NULL); + else + check(git_revwalk_push(s->walker, git_object_id(obj)), + "Reference does not refer to a commit", NULL); + + git_object_free(obj); +} - if (a[0] != '-' || force_files > 0) { - /* condense args not prefixed with '-' to start of argv */ - if (last_nonoption != i) - argv[last_nonoption] = a; - last_nonoption++; +static int add_revision(struct log_state *s, const char *revstr) +{ + git_revspec revs; + int hide = 0; + + if (!s->repo) { + if (!s->repodir) s->repodir = "."; + check(git_repository_open_ext(&s->repo, s->repodir, 0, NULL), + "Could not open repository", s->repodir); + } + + if (!revstr) + push_rev(s, NULL, hide); + else if (*revstr == '^') { + revs.flags = GIT_REVPARSE_SINGLE; + hide = !hide; + if (!git_revparse_single(&revs.from, s->repo, revstr + 1)) + return -1; + } else + if (!git_revparse(&revs, s->repo, revstr)) + return -1; + + if ((revs.flags & GIT_REVPARSE_SINGLE) != 0) + push_rev(s, revs.from, hide); + else { + push_rev(s, revs.to, hide); + + if ((revs.flags & GIT_REVPARSE_MERGE_BASE) != 0) { + git_oid base; + check(git_merge_base(&base, s->repo, + git_object_id(revs.from), git_object_id(revs.to)), + "Could not find merge base", revstr); + check(git_object_lookup(&revs.to, s->repo, &base, GIT_OBJ_COMMIT), + "Could not find merge base commit", NULL); + + push_rev(s, revs.to, hide); } - else if (!strcmp(a, "--")) - force_files = last_nonoption; /* copy all args as filenames */ - else if (!check_str_param(a, "--git-dir=", &dir)) - usage("Unknown argument", a); + + push_rev(s, revs.from, !hide); } - check(git_repository_open_ext(&repo, dir, 0, NULL), - "Could not open repository"); - check(git_revwalk_new(&walker, repo), - "Could not create revision walker"); + return 0; +} + +struct log_options { + int show_diff; + int skip; + int min_parents, max_parents; + git_time_t before; + git_time_t after; + char *author; + char *committer; - if (force_files < 0) - force_files = last_nonoption; +}; - for (i = 1; i < force_files; ) { - printf("option '%s'\n", argv[i]); +int main(int argc, char *argv[]) +{ + int i, count = 0; + char *a; + struct log_state s; + git_strarray paths; + git_oid oid; + git_commit *commit; + char buf[GIT_OID_HEXSZ + 1]; - if (!git_revparse(&revs, repo, argv[i])) { - char str[GIT_OID_HEXSZ+1]; + git_threads_init(); - if (revs.from) { - git_oid_tostr(str, sizeof(str), git_object_id(revs.from)); - printf("revwalk from %s\n", str); - } - if (revs.to) { - git_oid_tostr(str, sizeof(str), git_object_id(revs.to)); - printf("revwalk to %s\n", str); - } + memset(&s, 0, sizeof(s)); - /* push / hide / merge-base in revwalker */ + for (i = 1; i < argc; ++i) { + a = argv[i]; + if (a[0] != '-') { + if (!add_revision(&s, a)) + ++count; + else /* try failed revision parse as filename */ + break; + } else if (!strcmp(a, "--")) { ++i; - } else { - /* shift array down */ - for (a = argv[i], j = i + 1; j < force_files; ++j) - argv[j - 1] = argv[j]; - argv[--force_files] = a; + break; } + else if (!strcmp(a, "--date-order")) + set_sorting(&s, GIT_SORT_TIME); + else if (!strcmp(a, "--topo-order")) + set_sorting(&s, GIT_SORT_TOPOLOGICAL); + else if (!strcmp(a, "--reverse")) + set_sorting(&s, GIT_SORT_REVERSE); + else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) + s.repodir = a + strlen("--git-dir="); + else + usage("Unsupported argument", a); } - if (i == 1) { - /* no revs pushed so push HEAD */ - printf("revwalk HEAD\n"); - } + if (!count) + add_revision(&s, NULL); + + paths.strings = &argv[i]; + paths.count = argc - i; - for (i = force_files; i < last_nonoption; ++i) - printf("file %s\n", argv[i]); + while (!git_revwalk_next(&oid, s.walker)) { + check(git_commit_lookup(&commit, s.repo, &oid), + "Failed to look up commit", NULL); + git_commit_free(commit); + + git_oid_tostr(buf, sizeof(buf), &oid); + printf("%s\n", buf); + } - git_repository_free(repo); + git_revwalk_free(s.walker); + git_repository_free(s.repo); git_threads_shutdown(); return 0; -- cgit v1.2.1 From 8ba0ff69725251fa375520d9c69c8a053725c4b6 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 25 Jun 2013 15:39:44 -0700 Subject: rev-parse example --- examples/Makefile | 2 +- examples/rev-parse.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 examples/rev-parse.c diff --git a/examples/Makefile b/examples/Makefile index 6288906df..95e46f0c6 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -3,7 +3,7 @@ CC = gcc CFLAGS = -g -I../include -I../src -Wall -Wextra -Wmissing-prototypes -Wno-missing-field-initializers LFLAGS = -L../build -lgit2 -lz -APPS = general showindex diff rev-list cat-file status log +APPS = general showindex diff rev-list cat-file status log rev-parse all: $(APPS) diff --git a/examples/rev-parse.c b/examples/rev-parse.c new file mode 100644 index 000000000..cdbb61e46 --- /dev/null +++ b/examples/rev-parse.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include + +static void check(int error, const char *message, const char *arg) +{ + if (!error) + return; + if (arg) + fprintf(stderr, "%s %s (%d)\n", message, arg, error); + else + fprintf(stderr, "%s(%d)\n", message, error); + exit(1); +} + +static void usage(const char *message, const char *arg) +{ + if (message && arg) + fprintf(stderr, "%s: %s\n", message, arg); + else if (message) + fprintf(stderr, "%s\n", message); + fprintf(stderr, "usage: rev-parse [ --option ] ...\n"); + exit(1); +} + +struct parse_state { + git_repository *repo; + const char *repodir; + int not; +}; + +static int parse_revision(struct parse_state *ps, const char *revstr) +{ + git_revspec rs; + char str[GIT_OID_HEXSZ + 1]; + + if (!ps->repo) { + if (!ps->repodir) + ps->repodir = "."; + check(git_repository_open_ext(&ps->repo, ps->repodir, 0, NULL), + "Could not open repository from", ps->repodir); + } + + check(git_revparse(&rs, ps->repo, revstr), "Could not parse", revstr); + + if ((rs.flags & GIT_REVPARSE_SINGLE) != 0) { + git_oid_tostr(str, sizeof(str), git_object_id(rs.from)); + printf("%s\n", str); + git_object_free(rs.from); + } + else if ((rs.flags & GIT_REVPARSE_RANGE) != 0) { + git_oid_tostr(str, sizeof(str), git_object_id(rs.to)); + printf("%s\n", str); + git_object_free(rs.to); + + if ((rs.flags & GIT_REVPARSE_MERGE_BASE) != 0) { + git_oid base; + check(git_merge_base(&base, ps->repo, + git_object_id(rs.from), git_object_id(rs.to)), + "Could not find merge base", revstr); + + git_oid_tostr(str, sizeof(str), &base); + printf("%s\n", str); + } + + git_oid_tostr(str, sizeof(str), git_object_id(rs.from)); + printf("^%s\n", str); + git_object_free(rs.from); + } + else { + check(0, "Invalid results from git_revparse", revstr); + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + int i; + char *a; + struct parse_state ps; + + git_threads_init(); + + memset(&ps, 0, sizeof(ps)); + + for (i = 1; i < argc; ++i) { + a = argv[i]; + + if (a[0] != '-') { + if (parse_revision(&ps, a) != 0) + break; + } else if (!strcmp(a, "--not")) + ps.not = !ps.not; + else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) + ps.repodir = a + strlen("--git-dir="); + else + usage("Cannot handle argument", a); + } + + git_repository_free(ps.repo); + git_threads_shutdown(); + + return 0; +} -- cgit v1.2.1 From f094f9052fba43707cb5662a362511eeea4c4af5 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 1 Jul 2013 15:41:01 -0700 Subject: Add raw header access to commit API --- include/git2/commit.h | 8 ++++++++ src/commit.c | 47 +++++++++++++++++++++++++++++++++++++---------- src/commit.h | 1 + 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/include/git2/commit.h b/include/git2/commit.h index 544d21d87..fc0551be1 100644 --- a/include/git2/commit.h +++ b/include/git2/commit.h @@ -129,6 +129,14 @@ GIT_EXTERN(const git_signature *) git_commit_committer(const git_commit *commit) */ GIT_EXTERN(const git_signature *) git_commit_author(const git_commit *commit); +/** + * Get the full raw text of the commit header. + * + * @param commit a previously loaded commit + * @return the header text of the commit + */ +GIT_EXTERN(const char *) git_commit_raw_header(const git_commit *commit); + /** * Get the tree pointed to by a commit. * diff --git a/src/commit.c b/src/commit.c index 1ab9b34f7..cf50c2d37 100644 --- a/src/commit.c +++ b/src/commit.c @@ -41,6 +41,7 @@ void git_commit__free(void *_commit) git_signature_free(commit->author); git_signature_free(commit->committer); + git__free(commit->raw_header); git__free(commit->message); git__free(commit->message_encoding); git__free(commit); @@ -171,11 +172,33 @@ int git_commit_create( int git_commit__parse(void *_commit, git_odb_object *odb_obj) { git_commit *commit = _commit; - const char *buffer = git_odb_object_data(odb_obj); - const char *buffer_end = buffer + git_odb_object_size(odb_obj); + const char *buffer_start = git_odb_object_data(odb_obj), *buffer; + const char *buffer_end = buffer_start + git_odb_object_size(odb_obj); git_oid parent_id; + size_t parent_count = 0, header_len; - if (git_vector_init(&commit->parent_ids, 4, NULL) < 0) + /* find end-of-header (counting parents as we go) */ + for (buffer = buffer_start; buffer < buffer_end; ++buffer) { + if (!strncmp("\n\n", buffer, 2)) { + ++buffer; + break; + } + if (!strncmp("\nparent ", buffer, strlen("\nparent "))) + ++parent_count; + } + + header_len = buffer - buffer_start; + commit->raw_header = git__strndup(buffer_start, header_len); + GITERR_CHECK_ALLOC(commit->raw_header); + + /* point "buffer" to header data */ + buffer = commit->raw_header; + buffer_end = commit->raw_header + header_len; + + if (parent_count < 1) + parent_count = 1; + + if (git_vector_init(&commit->parent_ids, parent_count, NULL) < 0) return -1; if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0) @@ -208,8 +231,8 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj) if (git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n') < 0) return -1; - /* Parse add'l header entries until blank line found */ - while (buffer < buffer_end && *buffer != '\n') { + /* Parse add'l header entries */ + while (buffer < buffer_end) { const char *eoln = buffer; while (eoln < buffer_end && *eoln != '\n') ++eoln; @@ -223,15 +246,18 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj) if (eoln < buffer_end && *eoln == '\n') ++eoln; - buffer = eoln; } - /* buffer is now at the end of the header, double-check and move forward into the message */ - if (buffer < buffer_end && *buffer == '\n') - buffer++; + /* point "buffer" to data after header */ + buffer = git_odb_object_data(odb_obj); + buffer_end = buffer + git_odb_object_size(odb_obj); + + buffer += header_len; + if (*buffer == '\n') + ++buffer; - /* parse commit message */ + /* extract commit message */ if (buffer <= buffer_end) { commit->message = git__strndup(buffer, buffer_end - buffer); GITERR_CHECK_ALLOC(commit->message); @@ -255,6 +281,7 @@ GIT_COMMIT_GETTER(const git_signature *, author, commit->author) GIT_COMMIT_GETTER(const git_signature *, committer, commit->committer) GIT_COMMIT_GETTER(const char *, message, commit->message) GIT_COMMIT_GETTER(const char *, message_encoding, commit->message_encoding) +GIT_COMMIT_GETTER(const char *, raw_header, commit->raw_header) GIT_COMMIT_GETTER(git_time_t, time, commit->committer->when.time) GIT_COMMIT_GETTER(int, time_offset, commit->committer->when.offset) GIT_COMMIT_GETTER(unsigned int, parentcount, (unsigned int)commit->parent_ids.length) diff --git a/src/commit.h b/src/commit.h index d0981b125..70d8fc690 100644 --- a/src/commit.h +++ b/src/commit.h @@ -25,6 +25,7 @@ struct git_commit { char *message_encoding; char *message; + char *raw_header; }; void git_commit__free(void *commit); -- cgit v1.2.1 From f44c4fa108ff7e326607812246c3c056c1b901cc Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 1 Jul 2013 15:41:32 -0700 Subject: Add basic commit formatting to log output --- examples/log.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/examples/log.c b/examples/log.c index 5603d743d..12c1d5666 100644 --- a/examples/log.c +++ b/examples/log.c @@ -117,6 +117,32 @@ static int add_revision(struct log_state *s, const char *revstr) return 0; } +static void print_time(const git_time *intime, const char *prefix) +{ + char sign, out[32]; + struct tm intm; + int offset, hours, minutes; + time_t t; + + offset = intime->offset; + if (offset < 0) { + sign = '-'; + offset = -offset; + } else { + sign = '+'; + } + + hours = offset / 60; + minutes = offset % 60; + + t = (time_t)intime->time + (intime->offset * 60); + + gmtime_r(&t, &intm); + strftime(out, sizeof(out), "%a %b %d %T %Y", &intm); + + printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes); +} + struct log_options { int show_diff; int skip; @@ -125,7 +151,6 @@ struct log_options { git_time_t after; char *author; char *committer; - }; int main(int argc, char *argv[]) @@ -173,12 +198,39 @@ int main(int argc, char *argv[]) paths.count = argc - i; while (!git_revwalk_next(&oid, s.walker)) { + const git_signature *sig; + const char *scan, *eol; + check(git_commit_lookup(&commit, s.repo, &oid), "Failed to look up commit", NULL); - git_commit_free(commit); git_oid_tostr(buf, sizeof(buf), &oid); - printf("%s\n", buf); + printf("commit %s\n", buf); + + if ((count = (int)git_commit_parentcount(commit)) > 1) { + printf("Merge:"); + for (i = 0; i < count; ++i) { + git_oid_tostr(buf, 8, git_commit_parent_id(commit, i)); + printf(" %s", buf); + } + printf("\n"); + } + + if ((sig = git_commit_author(commit)) != NULL) { + printf("Author: %s <%s>\n", sig->name, sig->email); + print_time(&sig->when, "Date: "); + } + printf("\n"); + + for (scan = git_commit_message(commit); scan && *scan; ) { + for (eol = scan; *eol && *eol != '\n'; ++eol) /* find eol */; + + printf(" %.*s\n", (int)(eol - scan), scan); + scan = *eol ? eol + 1 : NULL; + } + printf("\n"); + + git_commit_free(commit); } git_revwalk_free(s.walker); -- cgit v1.2.1 From 2b3bd8ecd88a403f9d034aa3a4d1e14c5e904255 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 3 Jul 2013 14:53:39 -0700 Subject: Fix example/log.c minor diffs with git log --- examples/log.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/log.c b/examples/log.c index 12c1d5666..61b789263 100644 --- a/examples/log.c +++ b/examples/log.c @@ -56,9 +56,11 @@ static void push_rev(struct log_state *s, git_object *obj, int hide) { hide = s->hide ^ hide; - if (!s->walker) + if (!s->walker) { check(git_revwalk_new(&s->walker, s->repo), "Could not create revision walker", NULL); + git_revwalk_sorting(s->walker, s->sorting); + } if (!obj) check(git_revwalk_push_head(s->walker), @@ -138,7 +140,7 @@ static void print_time(const git_time *intime, const char *prefix) t = (time_t)intime->time + (intime->offset * 60); gmtime_r(&t, &intm); - strftime(out, sizeof(out), "%a %b %d %T %Y", &intm); + strftime(out, sizeof(out), "%a %b %e %T %Y", &intm); printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes); } @@ -166,6 +168,7 @@ int main(int argc, char *argv[]) git_threads_init(); memset(&s, 0, sizeof(s)); + s.sorting = GIT_SORT_TIME; for (i = 1; i < argc; ++i) { a = argv[i]; -- cgit v1.2.1 From 5a169711fa9875bc98c30c49b5e9ea06ebbbcfeb Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 3 Jul 2013 15:08:54 -0700 Subject: fix bug with order args and no revision --- examples/log.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/log.c b/examples/log.c index 61b789263..f7aabf0b4 100644 --- a/examples/log.c +++ b/examples/log.c @@ -86,9 +86,12 @@ static int add_revision(struct log_state *s, const char *revstr) "Could not open repository", s->repodir); } - if (!revstr) + if (!revstr) { push_rev(s, NULL, hide); - else if (*revstr == '^') { + return 0; + } + + if (*revstr == '^') { revs.flags = GIT_REVPARSE_SINGLE; hide = !hide; if (!git_revparse_single(&revs.from, s->repo, revstr + 1)) -- cgit v1.2.1 From 733c4f3aca212d90459fb21cfbc137f09ff6c951 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 3 Jul 2013 15:12:14 -0700 Subject: more examples/log.c bug fixing --- examples/log.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/log.c b/examples/log.c index f7aabf0b4..ba411d7a4 100644 --- a/examples/log.c +++ b/examples/log.c @@ -94,11 +94,11 @@ static int add_revision(struct log_state *s, const char *revstr) if (*revstr == '^') { revs.flags = GIT_REVPARSE_SINGLE; hide = !hide; - if (!git_revparse_single(&revs.from, s->repo, revstr + 1)) - return -1; - } else - if (!git_revparse(&revs, s->repo, revstr)) + + if (git_revparse_single(&revs.from, s->repo, revstr + 1) < 0) return -1; + } else if (git_revparse(&revs, s->repo, revstr) < 0) + return -1; if ((revs.flags & GIT_REVPARSE_SINGLE) != 0) push_rev(s, revs.from, hide); -- cgit v1.2.1 From a8b5f116bc39f884c8888adae2fd3f9b96d972c0 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 3 Jul 2013 17:00:50 -0700 Subject: Fix example/log.c pathspec handling of merges This fixes the way the example log program decides if a merge commit should be shown when a pathspec is given. Also makes it easier to use the pathspec API to just check "does a tree match anything in the pathspec" without allocating a match list. --- examples/log.c | 124 ++++++++++++++++++++++++++++++++++++++++++--------------- include/git2.h | 1 + src/pathspec.c | 21 ++++++---- 3 files changed, 106 insertions(+), 40 deletions(-) diff --git a/examples/log.c b/examples/log.c index ba411d7a4..50e81efad 100644 --- a/examples/log.c +++ b/examples/log.c @@ -158,15 +158,73 @@ struct log_options { char *committer; }; +static void print_commit(git_commit *commit) +{ + char buf[GIT_OID_HEXSZ + 1]; + int i, count; + const git_signature *sig; + const char *scan, *eol; + + git_oid_tostr(buf, sizeof(buf), git_commit_id(commit)); + printf("commit %s\n", buf); + + if ((count = (int)git_commit_parentcount(commit)) > 1) { + printf("Merge:"); + for (i = 0; i < count; ++i) { + git_oid_tostr(buf, 8, git_commit_parent_id(commit, i)); + printf(" %s", buf); + } + printf("\n"); + } + + if ((sig = git_commit_author(commit)) != NULL) { + printf("Author: %s <%s>\n", sig->name, sig->email); + print_time(&sig->when, "Date: "); + } + printf("\n"); + + for (scan = git_commit_message(commit); scan && *scan; ) { + for (eol = scan; *eol && *eol != '\n'; ++eol) /* find eol */; + + printf(" %.*s\n", (int)(eol - scan), scan); + scan = *eol ? eol + 1 : NULL; + } + printf("\n"); +} + +static int match_with_parent( + git_commit *commit, int i, git_diff_options *opts) +{ + git_commit *parent; + git_tree *a, *b; + git_diff_list *diff; + int ndeltas; + + check(git_commit_parent(&parent, commit, (size_t)i), "Get parent", NULL); + check(git_commit_tree(&a, parent), "Tree for parent", NULL); + check(git_commit_tree(&b, commit), "Tree for commit", NULL); + check(git_diff_tree_to_tree(&diff, git_commit_owner(commit), a, b, opts), + "Checking diff between parent and commit", NULL); + + ndeltas = (int)git_diff_num_deltas(diff); + + git_diff_list_free(diff); + git_tree_free(a); + git_tree_free(b); + git_commit_free(parent); + + return ndeltas > 0; +} + int main(int argc, char *argv[]) { - int i, count = 0; + int i, count = 0, parents; char *a; struct log_state s; - git_strarray paths; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_oid oid; git_commit *commit; - char buf[GIT_OID_HEXSZ + 1]; + git_pathspec *ps = NULL; git_threads_init(); @@ -200,45 +258,47 @@ int main(int argc, char *argv[]) if (!count) add_revision(&s, NULL); - paths.strings = &argv[i]; - paths.count = argc - i; - - while (!git_revwalk_next(&oid, s.walker)) { - const git_signature *sig; - const char *scan, *eol; + diffopts.pathspec.strings = &argv[i]; + diffopts.pathspec.count = argc - i; + count = 0; + if (diffopts.pathspec.count > 0) + check(git_pathspec_new(&ps, &diffopts.pathspec), + "Building pathspec", NULL); + for (; !git_revwalk_next(&oid, s.walker); git_commit_free(commit)) { check(git_commit_lookup(&commit, s.repo, &oid), "Failed to look up commit", NULL); - git_oid_tostr(buf, sizeof(buf), &oid); - printf("commit %s\n", buf); - - if ((count = (int)git_commit_parentcount(commit)) > 1) { - printf("Merge:"); - for (i = 0; i < count; ++i) { - git_oid_tostr(buf, 8, git_commit_parent_id(commit, i)); - printf(" %s", buf); + parents = (int)git_commit_parentcount(commit); + + if (diffopts.pathspec.count > 0) { + int unmatched = parents; + + if (parents == 0) { + git_tree *tree; + check(git_commit_tree(&tree, commit), "Get tree", NULL); + if (git_pathspec_match_tree( + NULL, tree, GIT_PATHSPEC_NO_MATCH_ERROR, ps) != 0) + unmatched = 1; + git_tree_free(tree); + } else if (parents == 1) { + unmatched = match_with_parent(commit, 0, &diffopts) ? 0 : 1; + } else { + for (i = 0; i < parents; ++i) { + if (match_with_parent(commit, i, &diffopts)) + unmatched--; + } } - printf("\n"); - } - if ((sig = git_commit_author(commit)) != NULL) { - printf("Author: %s <%s>\n", sig->name, sig->email); - print_time(&sig->when, "Date: "); + if (unmatched > 0) + continue; } - printf("\n"); - - for (scan = git_commit_message(commit); scan && *scan; ) { - for (eol = scan; *eol && *eol != '\n'; ++eol) /* find eol */; - - printf(" %.*s\n", (int)(eol - scan), scan); - scan = *eol ? eol + 1 : NULL; - } - printf("\n"); - git_commit_free(commit); + print_commit(commit); + ++count; } + git_pathspec_free(ps); git_revwalk_free(s.walker); git_repository_free(s.repo); git_threads_shutdown(); diff --git a/include/git2.h b/include/git2.h index 5f9fc4824..e8638a830 100644 --- a/include/git2.h +++ b/include/git2.h @@ -56,5 +56,6 @@ #include "git2/message.h" #include "git2/pack.h" #include "git2/stash.h" +#include "git2/pathspec.h" #endif diff --git a/src/pathspec.c b/src/pathspec.c index 35421dbef..021f38f1c 100644 --- a/src/pathspec.c +++ b/src/pathspec.c @@ -311,7 +311,7 @@ static int pathspec_match_from_iterator( git_pathspec *ps) { int error = 0; - git_pathspec_match_list *m; + git_pathspec_match_list *m = NULL; const git_index_entry *entry = NULL; struct pathspec_match_context ctxt; git_vector *patterns = &ps->pathspec; @@ -322,8 +322,13 @@ static int pathspec_match_from_iterator( uint8_t *used_patterns = NULL; char **file; - *out = m = pathspec_match_alloc(ps); - GITERR_CHECK_ALLOC(m); + if (out) { + *out = m = pathspec_match_alloc(ps); + GITERR_CHECK_ALLOC(m); + } else { + failures_only = true; + find_failures = false; + } if ((error = git_iterator_reset(iter, ps->prefix, ps->prefix)) < 0) goto done; @@ -385,7 +390,7 @@ static int pathspec_match_from_iterator( } /* if only looking at failures, exit early or just continue */ - if (failures_only) { + if (failures_only || !out) { if (used_ct == patterns->length) break; continue; @@ -429,7 +434,7 @@ done: if (error < 0) { pathspec_match_free(m); - *out = NULL; + if (out) *out = NULL; } return error; @@ -456,7 +461,7 @@ int git_pathspec_match_workdir( int error = 0; git_iterator *iter; - assert(out && repo); + assert(repo); if (!(error = git_iterator_for_workdir( &iter, repo, pathspec_match_iter_flags(flags), NULL, NULL))) { @@ -478,7 +483,7 @@ int git_pathspec_match_index( int error = 0; git_iterator *iter; - assert(out && index); + assert(index); if (!(error = git_iterator_for_index( &iter, index, pathspec_match_iter_flags(flags), NULL, NULL))) { @@ -500,7 +505,7 @@ int git_pathspec_match_tree( int error = 0; git_iterator *iter; - assert(out && tree); + assert(tree); if (!(error = git_iterator_for_tree( &iter, tree, pathspec_match_iter_flags(flags), NULL, NULL))) { -- cgit v1.2.1 From bc6f0839ebd5794c99d5b488d431188a162a064d Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 5 Jul 2013 15:22:21 -0700 Subject: Add a bunch more features to log example --- examples/log.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 112 insertions(+), 14 deletions(-) diff --git a/examples/log.c b/examples/log.c index 50e81efad..dbbc42914 100644 --- a/examples/log.c +++ b/examples/log.c @@ -148,16 +148,6 @@ static void print_time(const git_time *intime, const char *prefix) printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes); } -struct log_options { - int show_diff; - int skip; - int min_parents, max_parents; - git_time_t before; - git_time_t after; - char *author; - char *committer; -}; - static void print_commit(git_commit *commit) { char buf[GIT_OID_HEXSZ + 1]; @@ -192,6 +182,37 @@ static void print_commit(git_commit *commit) printf("\n"); } +static int print_diff( + const git_diff_delta *delta, + const git_diff_range *range, + char usage, + const char *line, + size_t line_len, + void *data) +{ + (void)delta; (void)range; (void)usage; (void)line_len; (void)data; + fputs(line, stdout); + return 0; +} + +static int match_int(int *value, const char *arg, int allow_negative) +{ + char *found; + *value = (int)strtol(arg, &found, 10); + return (found && *found == '\0' && (allow_negative || *value >= 0)); +} + +static int match_int_arg( + int *value, const char *arg, const char *pfx, int allow_negative) +{ + size_t pfxlen = strlen(pfx); + if (strncmp(arg, pfx, pfxlen) != 0) + return 0; + if (!match_int(value, arg + pfxlen, allow_negative)) + usage("Invalid value after argument", arg); + return 1; +} + static int match_with_parent( git_commit *commit, int i, git_diff_options *opts) { @@ -216,14 +237,25 @@ static int match_with_parent( return ndeltas > 0; } +struct log_options { + int show_diff; + int skip, limit; + int min_parents, max_parents; + git_time_t before; + git_time_t after; + char *author; + char *committer; +}; + int main(int argc, char *argv[]) { - int i, count = 0, parents; + int i, count = 0, printed = 0, parents; char *a; struct log_state s; + struct log_options opt; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_oid oid; - git_commit *commit; + git_commit *commit = NULL; git_pathspec *ps = NULL; git_threads_init(); @@ -231,6 +263,9 @@ int main(int argc, char *argv[]) memset(&s, 0, sizeof(s)); s.sorting = GIT_SORT_TIME; + memset(&opt, 0, sizeof(opt)); + opt.max_parents = -1; + for (i = 1; i < argc; ++i) { a = argv[i]; @@ -251,6 +286,33 @@ int main(int argc, char *argv[]) set_sorting(&s, GIT_SORT_REVERSE); else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) s.repodir = a + strlen("--git-dir="); + else if (match_int_arg(&opt.skip, a, "--skip=", 0)) + /* found valid --skip */; + else if (match_int_arg(&opt.limit, a, "--max-count=", 0)) + /* found valid --max-count */; + else if (a[1] >= '0' && a[1] <= '9') { + if (!match_int(&opt.limit, a + 1, 0)) + usage("Invalid limit on number of commits", a); + } else if (!strcmp(a, "-n")) { + if (i + 1 == argc || !match_int(&opt.limit, argv[i], 0)) + usage("Argument -n not followed by valid count", argv[i]); + else + ++i; + } + else if (!strcmp(a, "--merges")) + opt.min_parents = 2; + else if (!strcmp(a, "--no-merges")) + opt.max_parents = 1; + else if (!strcmp(a, "--no-min-parents")) + opt.min_parents = 0; + else if (!strcmp(a, "--no-max-parents")) + opt.max_parents = -1; + else if (match_int_arg(&opt.max_parents, a, "--max-parents=", 1)) + /* found valid --max-parents */; + else if (match_int_arg(&opt.min_parents, a, "--min-parents=", 0)) + /* found valid --min_parents */; + else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) + opt.show_diff = 1; else usage("Unsupported argument", a); } @@ -260,16 +322,21 @@ int main(int argc, char *argv[]) diffopts.pathspec.strings = &argv[i]; diffopts.pathspec.count = argc - i; - count = 0; if (diffopts.pathspec.count > 0) check(git_pathspec_new(&ps, &diffopts.pathspec), "Building pathspec", NULL); + printed = count = 0; + for (; !git_revwalk_next(&oid, s.walker); git_commit_free(commit)) { check(git_commit_lookup(&commit, s.repo, &oid), "Failed to look up commit", NULL); parents = (int)git_commit_parentcount(commit); + if (parents < opt.min_parents) + continue; + if (opt.max_parents > 0 && parents > opt.max_parents) + continue; if (diffopts.pathspec.count > 0) { int unmatched = parents; @@ -294,8 +361,39 @@ int main(int argc, char *argv[]) continue; } + if (count++ < opt.skip) + continue; + if (printed++ >= opt.limit) { + git_commit_free(commit); + break; + } + print_commit(commit); - ++count; + + if (opt.show_diff) { + git_tree *a = NULL, *b = NULL; + git_diff_list *diff = NULL; + + if (parents > 1) + continue; + check(git_commit_tree(&b, commit), "Get tree", NULL); + if (parents == 1) { + git_commit *parent; + check(git_commit_parent(&parent, commit, 0), "Get parent", NULL); + check(git_commit_tree(&a, parent), "Tree for parent", NULL); + git_commit_free(parent); + } + + check(git_diff_tree_to_tree( + &diff, git_commit_owner(commit), a, b, &diffopts), + "Diff commit with parent", NULL); + check(git_diff_print_patch(diff, print_diff, NULL), + "Displaying diff", NULL); + + git_diff_list_free(diff); + git_tree_free(a); + git_tree_free(b); + } } git_pathspec_free(ps); -- cgit v1.2.1 From 9abc78ae6157167682f061b4f73eea51ab7d7342 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sun, 7 Jul 2013 21:56:11 -0700 Subject: Convert commit->parent_ids to git_array_t This converts the array of parent SHAs from a git_vector where each SHA has to be separately allocated to a git_array_t where all the SHAs can be kept in one block. Since the two collections have almost identical APIs, there isn't much involved in making the change. I did add an API to git_array_t so that it could be allocated at a precise initial size. --- src/array.h | 3 +++ src/commit.c | 29 +++++++---------------------- src/commit.h | 4 ++-- 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/array.h b/src/array.h index 2d77c71a0..707570624 100644 --- a/src/array.h +++ b/src/array.h @@ -30,6 +30,9 @@ #define git_array_init(a) \ do { (a).size = (a).asize = 0; (a).ptr = NULL; } while (0) +#define git_array_init_to_size(a, desired) \ + do { (a).size = 0; (a).asize = desired; (a).ptr = git__calloc(desired, sizeof(*(a).ptr)); } while (0) + #define git_array_clear(a) \ do { git__free((a).ptr); git_array_init(a); } while (0) diff --git a/src/commit.c b/src/commit.c index cf50c2d37..cc912a7be 100644 --- a/src/commit.c +++ b/src/commit.c @@ -19,24 +19,11 @@ #include -static void clear_parents(git_commit *commit) -{ - size_t i; - - for (i = 0; i < commit->parent_ids.length; ++i) { - git_oid *parent = git_vector_get(&commit->parent_ids, i); - git__free(parent); - } - - git_vector_clear(&commit->parent_ids); -} - void git_commit__free(void *_commit) { git_commit *commit = _commit; - clear_parents(commit); - git_vector_free(&commit->parent_ids); + git_array_clear(commit->parent_ids); git_signature_free(commit->author); git_signature_free(commit->committer); @@ -44,6 +31,7 @@ void git_commit__free(void *_commit) git__free(commit->raw_header); git__free(commit->message); git__free(commit->message_encoding); + git__free(commit); } @@ -198,8 +186,8 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj) if (parent_count < 1) parent_count = 1; - if (git_vector_init(&commit->parent_ids, parent_count, NULL) < 0) - return -1; + git_array_init_to_size(commit->parent_ids, parent_count); + GITERR_CHECK_ARRAY(commit->parent_ids); if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0) goto bad_buffer; @@ -209,13 +197,10 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj) */ while (git_oid__parse(&parent_id, &buffer, buffer_end, "parent ") == 0) { - git_oid *new_id = git__malloc(sizeof(git_oid)); + git_oid *new_id = git_array_alloc(commit->parent_ids); GITERR_CHECK_ALLOC(new_id); git_oid_cpy(new_id, &parent_id); - - if (git_vector_insert(&commit->parent_ids, new_id) < 0) - return -1; } commit->author = git__malloc(sizeof(git_signature)); @@ -284,7 +269,7 @@ GIT_COMMIT_GETTER(const char *, message_encoding, commit->message_encoding) GIT_COMMIT_GETTER(const char *, raw_header, commit->raw_header) GIT_COMMIT_GETTER(git_time_t, time, commit->committer->when.time) GIT_COMMIT_GETTER(int, time_offset, commit->committer->when.offset) -GIT_COMMIT_GETTER(unsigned int, parentcount, (unsigned int)commit->parent_ids.length) +GIT_COMMIT_GETTER(unsigned int, parentcount, (unsigned int)git_array_size(commit->parent_ids)) GIT_COMMIT_GETTER(const git_oid *, tree_id, &commit->tree_id); int git_commit_tree(git_tree **tree_out, const git_commit *commit) @@ -298,7 +283,7 @@ const git_oid *git_commit_parent_id( { assert(commit); - return git_vector_get(&commit->parent_ids, n); + return git_array_get(commit->parent_ids, n); } int git_commit_parent( diff --git a/src/commit.h b/src/commit.h index 70d8fc690..22fc898a1 100644 --- a/src/commit.h +++ b/src/commit.h @@ -10,14 +10,14 @@ #include "git2/commit.h" #include "tree.h" #include "repository.h" -#include "vector.h" +#include "array.h" #include struct git_commit { git_object object; - git_vector parent_ids; + git_array_t(git_oid) parent_ids; git_oid tree_id; git_signature *author; -- cgit v1.2.1 From 3e96ecf219bd9b84c3a7faec61e818766f60e0d9 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 8 Jul 2013 09:53:24 -0700 Subject: Improve include/git2/pathspec.h docs --- include/git2/pathspec.h | 75 ++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/include/git2/pathspec.h b/include/git2/pathspec.h index 8122d9927..6d97bb326 100644 --- a/include/git2/pathspec.h +++ b/include/git2/pathspec.h @@ -25,20 +25,22 @@ typedef struct git_pathspec_match_list git_pathspec_match_list; * Options controlling how pathspec match should be executed * * - GIT_PATHSPEC_IGNORE_CASE forces match to ignore case; otherwise - * match will use native case sensitivity of platform + * match will use native case sensitivity of platform filesystem * - GIT_PATHSPEC_USE_CASE forces case sensitive match; otherwise - * match will use native case sensitivity of platform + * match will use native case sensitivity of platform filesystem * - GIT_PATHSPEC_NO_GLOB disables glob patterns and just uses simple * string comparison for matching - * - GIT_PATHSPEC_NO_MATCH_ERROR means the match function will return - * GIT_ENOTFOUND if no matches are found; otherwise it will return 0 - * for success and `git_pathspec_match_list_entrycount` will be 0. - * - GIT_PATHSPEC_FIND_FAILURES only applies to a git_pathspec_match_list; - * it means to check file names against all unmatched patterns so that - * at the end of a match we can identify patterns that did not match any - * files. - * - GIT_PATHSPEC_FAILURES_ONLY only applies to a git_pathspec_match_list; - * it means to only check for mismatches and not record matched paths. + * - GIT_PATHSPEC_NO_MATCH_ERROR means the match functions return error + * code GIT_ENOTFOUND if no matches are found; otherwise no matches is + * still success (return 0) but `git_pathspec_match_list_entrycount` + * will indicate 0 matches. + * - GIT_PATHSPEC_FIND_FAILURES means that the `git_pathspec_match_list` + * should track which patterns matched which files so that at the end of + * the match we can identify patterns that did not match any files. + * - GIT_PATHSPEC_FAILURES_ONLY means that the `git_pathspec_match_list` + * does not need to keep the actual matching filenames. Use this to + * just test if there were any matches at all or in combination with + * GIT_PATHSPEC_FIND_FAILURES to validate a pathspec. */ typedef enum { GIT_PATHSPEC_DEFAULT = 0, @@ -54,7 +56,6 @@ typedef enum { * Compile a pathspec * * @param out Output of the compiled pathspec - * @param flags Combination of git_pathspec_flag_t values * @param pathspec A git_strarray of the paths to match * @return 0 on success, <0 on failure */ @@ -77,7 +78,7 @@ GIT_EXTERN(void) git_pathspec_free(git_pathspec *ps); * fall back on being case sensitive. * * @param ps The compiled pathspec - * @param flags Match flags to influence matching behavior + * @param flags Combination of git_pathspec_flag_t options to control match * @param path The pathname to attempt to match * @return 1 is path matches spec, 0 if it does not */ @@ -87,18 +88,24 @@ GIT_EXTERN(int) git_pathspec_matches_path( /** * Match a pathspec against the working directory of a repository. * - * This returns a `git_patchspec_match` object that contains the list of - * all files matching the given pathspec in the working directory of the - * repository. This handles git ignores (i.e. ignored files will not be + * This matches the pathspec against the current files in the working + * directory of the repository. It is an error to invoke this on a bare + * repo. This handles git ignores (i.e. ignored files will not be * considered to match the `pathspec` unless the file is tracked in the * index). * - * @param out Object with list of matching items + * If `out` is not NULL, this returns a `git_patchspec_match_list`. That + * contains the list of all matched filenames (unless you pass the + * `GIT_PATHSPEC_FAILURES_ONLY` flag) and may also contain the list of + * pathspecs with no match (if you used the `GIT_PATHSPEC_FIND_FAILURES` + * flag). You must call `git_pathspec_match_list_free()` on this object. + * + * @param out Output list of matches; pass NULL to just get return value * @param repo The repository in which to match; bare repo is an error - * @param flags Options to control matching behavior + * @param flags Combination of git_pathspec_flag_t options to control match * @param ps Pathspec to be matched * @return 0 on success, -1 on error, GIT_ENOTFOUND if no matches and - * the GIT_PATHSPEC_NO_MATCH_ERROR flag is used + * the GIT_PATHSPEC_NO_MATCH_ERROR flag was given */ GIT_EXTERN(int) git_pathspec_match_workdir( git_pathspec_match_list **out, @@ -109,17 +116,22 @@ GIT_EXTERN(int) git_pathspec_match_workdir( /** * Match a pathspec against entries in an index. * - * This returns a `git_patchspec_match` object that contains the list of - * all files matching the given pathspec in the index. + * This matches the pathspec against the files in the repository index. * * NOTE: At the moment, the case sensitivity of this match is controlled * by the current case-sensitivity of the index object itself and the * USE_CASE and IGNORE_CASE flags will have no effect. This behavior will * be corrected in a future release. * - * @param out Object with list of matching items - * @param inex The index in which to match - * @param flags Options to control matching behavior + * If `out` is not NULL, this returns a `git_patchspec_match_list`. That + * contains the list of all matched filenames (unless you pass the + * `GIT_PATHSPEC_FAILURES_ONLY` flag) and may also contain the list of + * pathspecs with no match (if you used the `GIT_PATHSPEC_FIND_FAILURES` + * flag). You must call `git_pathspec_match_list_free()` on this object. + * + * @param out Output list of matches; pass NULL to just get return value + * @param index The index to match against + * @param flags Combination of git_pathspec_flag_t options to control match * @param ps Pathspec to be matched * @return 0 on success, -1 on error, GIT_ENOTFOUND if no matches and * the GIT_PATHSPEC_NO_MATCH_ERROR flag is used @@ -133,12 +145,17 @@ GIT_EXTERN(int) git_pathspec_match_index( /** * Match a pathspec against files in a tree. * - * This returns a `git_patchspec_match` object that contains the list of - * all files matching the given pathspec in the given tree. + * This matches the pathspec against the files in the given tree. + * + * If `out` is not NULL, this returns a `git_patchspec_match_list`. That + * contains the list of all matched filenames (unless you pass the + * `GIT_PATHSPEC_FAILURES_ONLY` flag) and may also contain the list of + * pathspecs with no match (if you used the `GIT_PATHSPEC_FIND_FAILURES` + * flag). You must call `git_pathspec_match_list_free()` on this object. * - * @param out Object with list of matching items - * @param inex The index in which to match - * @param flags Options to control matching behavior + * @param out Output list of matches; pass NULL to just get return value + * @param tree The root-level tree to match against + * @param flags Combination of git_pathspec_flag_t options to control match * @param ps Pathspec to be matched * @return 0 on success, -1 on error, GIT_ENOTFOUND if no matches and * the GIT_PATHSPEC_NO_MATCH_ERROR flag is used -- cgit v1.2.1 From 6fc5a58197bf04e1b5c6ca1bdb5765e90d3eb106 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 8 Jul 2013 22:42:02 -0700 Subject: Basic bit vector This is a simple bit vector object that is not resizable after the initial allocation but can be of arbitrary size. It will keep the bti vector entirely on the stack for vectors 64 bits or less, and will allocate the vector on the heap for larger sizes. The API is uniform regardless of storage location. This is very basic right now and all the APIs are inline functions, but it is useful for storing an array of boolean values. --- src/bitvec.h | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ tests-clar/core/bitvec.c | 64 +++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 src/bitvec.h create mode 100644 tests-clar/core/bitvec.c diff --git a/src/bitvec.h b/src/bitvec.h new file mode 100644 index 000000000..a033f534f --- /dev/null +++ b/src/bitvec.h @@ -0,0 +1,92 @@ +/* + * 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_bitvec_h__ +#define INCLUDE_bitvec_h__ + +#include "util.h" + +/* + * This is a silly little fixed length bit vector type that will store + * vectors of 64 bits or less directly in the structure and allocate + * memory for vectors longer than 64 bits. You can use the two versions + * transparently through the API and avoid heap allocation completely when + * using a short bit vector as a result. + */ +typedef struct { + size_t length; + union { + uint8_t *ptr; + uint64_t bits; + } u; +} git_bitvec; + +GIT_INLINE(int) git_bitvec_init(git_bitvec *bv, size_t capacity) +{ + if (capacity < 64) { + bv->length = 0; + bv->u.bits = 0; + return 0; + } + + bv->length = (capacity + 7) / 8; + bv->u.ptr = git__calloc(bv->length, 1); + return bv->u.ptr ? 0 : -1; +} + +#define GIT_BITVEC_MASK_INLINE(BIT) (((uint64_t)1) << BIT) + +#define GIT_BITVEC_MASK_BYTE(BIT) (((uint8_t)1) << ((BIT) & 0x07)) +#define GIT_BITVEC_INDEX_BYTE(BIT) ((BIT) >> 3) + +GIT_INLINE(void) git_bitvec_set(git_bitvec *bv, size_t bit, bool on) +{ + if (!bv->length) { + assert(bit < 64); + + if (on) + bv->u.bits |= GIT_BITVEC_MASK_INLINE(bit); + else + bv->u.bits &= ~GIT_BITVEC_MASK_INLINE(bit); + } else { + assert(bit < bv->length * 8); + + if (on) + bv->u.ptr[GIT_BITVEC_INDEX_BYTE(bit)] |= GIT_BITVEC_MASK_BYTE(bit); + else + bv->u.ptr[GIT_BITVEC_INDEX_BYTE(bit)] &= ~GIT_BITVEC_MASK_BYTE(bit); + } +} + +GIT_INLINE(bool) git_bitvec_get(git_bitvec *bv, size_t bit) +{ + if (!bv->length) { + assert(bit < 64); + return (bv->u.bits & GIT_BITVEC_MASK_INLINE(bit)) != 0; + } else { + assert(bit < bv->length * 8); + return (bv->u.ptr[GIT_BITVEC_INDEX_BYTE(bit)] & + GIT_BITVEC_MASK_BYTE(bit)) != 0; + } +} + +GIT_INLINE(void) git_bitvec_clear(git_bitvec *bv) +{ + if (!bv->length) + bv->u.bits = 0; + else + memset(bv->u.ptr, 0, bv->length); +} + +GIT_INLINE(void) git_bitvec_free(git_bitvec *bv) +{ + if (bv->length) { + git__free(bv->u.ptr); + memset(bv, 0, sizeof(*bv)); + } +} + +#endif diff --git a/tests-clar/core/bitvec.c b/tests-clar/core/bitvec.c new file mode 100644 index 000000000..48d7b99f0 --- /dev/null +++ b/tests-clar/core/bitvec.c @@ -0,0 +1,64 @@ +#include "clar_libgit2.h" +#include "bitvec.h" + +#if 0 +static void print_bitvec(git_bitvec *bv) +{ + int b; + + if (!bv->length) { + for (b = 63; b >= 0; --b) + fprintf(stderr, "%d", (bv->u.bits & (1ul << b)) ? 1 : 0); + } else { + for (b = bv->length * 8; b >= 0; --b) + fprintf(stderr, "%d", (bv->u.ptr[b >> 3] & (b & 0x0ff)) ? 1 : 0); + } + fprintf(stderr, "\n"); +} +#endif + +static void set_some_bits(git_bitvec *bv, size_t length) +{ + size_t i; + + for (i = 0; i < length; ++i) { + if (i % 3 == 0 || i % 7 == 0) + git_bitvec_set(bv, i, true); + } +} + +static void check_some_bits(git_bitvec *bv, size_t length) +{ + size_t i; + + for (i = 0; i < length; ++i) + cl_assert_equal_b(i % 3 == 0 || i % 7 == 0, git_bitvec_get(bv, i)); +} + +void test_core_bitvec__0(void) +{ + git_bitvec bv; + + cl_git_pass(git_bitvec_init(&bv, 32)); + set_some_bits(&bv, 16); + check_some_bits(&bv, 16); + git_bitvec_clear(&bv); + set_some_bits(&bv, 32); + check_some_bits(&bv, 32); + git_bitvec_clear(&bv); + set_some_bits(&bv, 64); + check_some_bits(&bv, 64); + git_bitvec_free(&bv); + + cl_git_pass(git_bitvec_init(&bv, 128)); + set_some_bits(&bv, 32); + check_some_bits(&bv, 32); + set_some_bits(&bv, 128); + check_some_bits(&bv, 128); + git_bitvec_free(&bv); + + cl_git_pass(git_bitvec_init(&bv, 4000)); + set_some_bits(&bv, 4000); + check_some_bits(&bv, 4000); + git_bitvec_free(&bv); +} -- cgit v1.2.1 From 2b672d5b646edf94ae315a9f968611ff65508c90 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 8 Jul 2013 22:46:36 -0700 Subject: Add git_pathspec_match_diff API This adds an additional pathspec API that will match a pathspec against a diff object. This is convenient if you want to handle renames (so you need the whole diff and can't use the pathspec constraint built into the diff API) but still want to tell if the diff had any files that matched the pathspec. When the pathspec is matched against a diff, instead of keeping a list of filenames that matched, instead the API keeps the list of git_diff_deltas that matched and they can be retrieved via a new API git_pathspec_match_list_diff_entry. There are a couple of other minor API extensions here that were mostly for the sake of convenience and to reduce dependencies on knowing the internal data structure between files inside the library. --- include/git2/diff.h | 8 ++ include/git2/pathspec.h | 41 ++++++ src/array.h | 2 + src/diff.c | 10 ++ src/diff.h | 2 + src/pathspec.c | 314 ++++++++++++++++++++++++++++++++++----------- src/pathspec.h | 12 +- tests-clar/diff/pathspec.c | 92 +++++++++++++ 8 files changed, 404 insertions(+), 77 deletions(-) create mode 100644 tests-clar/diff/pathspec.c diff --git a/include/git2/diff.h b/include/git2/diff.h index 43029c49c..121c9df5c 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -797,6 +797,14 @@ GIT_EXTERN(size_t) git_diff_num_deltas_of_type( git_diff_list *diff, git_delta_t type); +/** + * Check if deltas are sorted case sensitively or insensitively. + * + * @param diff Diff list to check + * @return 0 if case sensitive, 1 if case is ignored + */ +GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff_list *diff); + /** * Return the diff delta and patch for an entry in the diff list. * diff --git a/include/git2/pathspec.h b/include/git2/pathspec.h index 6d97bb326..a835f8e52 100644 --- a/include/git2/pathspec.h +++ b/include/git2/pathspec.h @@ -10,6 +10,7 @@ #include "common.h" #include "types.h" #include "strarray.h" +#include "diff.h" /** * Compiled pathspec @@ -166,6 +167,30 @@ GIT_EXTERN(int) git_pathspec_match_tree( uint32_t flags, git_pathspec *ps); +/** + * Match a pathspec against files in a diff list. + * + * This matches the pathspec against the files in the given diff list. + * + * If `out` is not NULL, this returns a `git_patchspec_match_list`. That + * contains the list of all matched filenames (unless you pass the + * `GIT_PATHSPEC_FAILURES_ONLY` flag) and may also contain the list of + * pathspecs with no match (if you used the `GIT_PATHSPEC_FIND_FAILURES` + * flag). You must call `git_pathspec_match_list_free()` on this object. + * + * @param out Output list of matches; pass NULL to just get return value + * @param diff A generated diff list + * @param flags Combination of git_pathspec_flag_t options to control match + * @param ps Pathspec to be matched + * @return 0 on success, -1 on error, GIT_ENOTFOUND if no matches and + * the GIT_PATHSPEC_NO_MATCH_ERROR flag is used + */ +GIT_EXTERN(int) git_pathspec_match_diff( + git_pathspec_match_list **out, + git_diff_list *diff, + uint32_t flags, + git_pathspec *ps); + /** * Free memory associates with a git_pathspec_match_list * @@ -185,6 +210,9 @@ GIT_EXTERN(size_t) git_pathspec_match_list_entrycount( /** * Get a matching filename by position. * + * This routine cannot be used if the match list was generated by + * `git_pathspec_match_diff`. If so, it will always return NULL. + * * @param m The git_pathspec_match_list object * @param pos The index into the list * @return The filename of the match @@ -192,6 +220,19 @@ GIT_EXTERN(size_t) git_pathspec_match_list_entrycount( GIT_EXTERN(const char *) git_pathspec_match_list_entry( const git_pathspec_match_list *m, size_t pos); +/** + * Get a matching diff delta by position. + * + * This routine can only be used if the match list was generated by + * `git_pathspec_match_diff`. Otherwise it will always return NULL. + * + * @param m The git_pathspec_match_list object + * @param pos The index into the list + * @return The filename of the match + */ +GIT_EXTERN(const git_diff_delta *) git_pathspec_match_list_diff_entry( + const git_pathspec_match_list *m, size_t pos); + /** * Get the number of pathspec items that did not match. * diff --git a/src/array.h b/src/array.h index 707570624..248010425 100644 --- a/src/array.h +++ b/src/array.h @@ -66,4 +66,6 @@ GIT_INLINE(void *) git_array_grow(git_array_generic_t *a, size_t item_size) #define git_array_size(a) (a).size +#define git_array_valid_index(a, i) ((i) < (a).size) + #endif diff --git a/src/diff.c b/src/diff.c index 56232ebf4..cc7be451f 100644 --- a/src/diff.c +++ b/src/diff.c @@ -247,6 +247,11 @@ GIT_INLINE(const char *) diff_delta__path(const git_diff_delta *delta) return str; } +const char *git_diff_delta__path(const git_diff_delta *delta) +{ + return diff_delta__path(delta); +} + int git_diff_delta__cmp(const void *a, const void *b) { const git_diff_delta *da = a, *db = b; @@ -1235,6 +1240,11 @@ size_t git_diff_num_deltas_of_type(git_diff_list *diff, git_delta_t type) return count; } +int git_diff_is_sorted_icase(const git_diff_list *diff) +{ + return (diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0; +} + int git_diff__paired_foreach( git_diff_list *head2idx, git_diff_list *idx2wd, diff --git a/src/diff.h b/src/diff.h index 6ef03ee7c..d09a130bc 100644 --- a/src/diff.h +++ b/src/diff.h @@ -76,6 +76,8 @@ extern void git_diff_list_addref(git_diff_list *diff); extern int git_diff_delta__cmp(const void *a, const void *b); extern int git_diff_delta__casecmp(const void *a, const void *b); +extern const char *git_diff_delta__path(const git_diff_delta *delta); + extern bool git_diff_delta__should_skip( const git_diff_options *opts, const git_diff_delta *delta); diff --git a/src/pathspec.c b/src/pathspec.c index 021f38f1c..625726e0b 100644 --- a/src/pathspec.c +++ b/src/pathspec.c @@ -6,12 +6,15 @@ */ #include "git2/pathspec.h" +#include "git2/diff.h" #include "pathspec.h" #include "buf_text.h" #include "attr_file.h" #include "iterator.h" #include "repository.h" #include "index.h" +#include "bitvec.h" +#include "diff.h" /* what is the common non-wildcard prefix for all items in the pathspec */ char *git_pathspec_prefix(const git_strarray *pathspec) @@ -162,6 +165,28 @@ static int pathspec_match_one( return -1; } +static int git_pathspec__match_at( + size_t *matched_at, + const git_vector *vspec, + struct pathspec_match_context *ctxt, + const char *path0, + const char *path1) +{ + int result = GIT_ENOTFOUND; + size_t i = 0; + const git_attr_fnmatch *match; + + git_vector_foreach(vspec, i, match) { + if (path0 && (result = pathspec_match_one(match, ctxt, path0)) >= 0) + break; + if (path1 && (result = pathspec_match_one(match, ctxt, path1)) >= 0) + break; + } + + *matched_at = i; + return result; +} + /* match a path against the vectorized pathspec */ bool git_pathspec__match( const git_vector *vspec, @@ -171,8 +196,8 @@ bool git_pathspec__match( const char **matched_pathspec, size_t *matched_at) { - size_t i; - const git_attr_fnmatch *match; + int result; + size_t pos; struct pathspec_match_context ctxt; if (matched_pathspec) @@ -185,20 +210,18 @@ bool git_pathspec__match( pathspec_match_context_init(&ctxt, disable_fnmatch, casefold); - git_vector_foreach(vspec, i, match) { - int result = pathspec_match_one(match, &ctxt, path); - - if (result >= 0) { - if (matched_pathspec) - *matched_pathspec = match->pattern; - if (matched_at) - *matched_at = i; - - return (result != 0); + result = git_pathspec__match_at(&pos, vspec, &ctxt, path, NULL); + if (result >= 0) { + if (matched_pathspec) { + const git_attr_fnmatch *match = git_vector_get(vspec, pos); + *matched_pathspec = match->pattern; } + + if (matched_at) + *matched_at = pos; } - return false; + return (result > 0); } @@ -277,7 +300,8 @@ static void pathspec_match_free(git_pathspec_match_list *m) git__free(m); } -static git_pathspec_match_list *pathspec_match_alloc(git_pathspec *ps) +static git_pathspec_match_list *pathspec_match_alloc( + git_pathspec *ps, int datatype) { git_pathspec_match_list *m = git__calloc(1, sizeof(git_pathspec_match_list)); @@ -292,16 +316,73 @@ static git_pathspec_match_list *pathspec_match_alloc(git_pathspec *ps) */ GIT_REFCOUNT_INC(ps); m->pathspec = ps; + m->datatype = datatype; return m; } -GIT_INLINE(void) pathspec_mark_pattern(uint8_t *used, size_t pos, size_t *ct) +GIT_INLINE(size_t) pathspec_mark_pattern(git_bitvec *used, size_t pos) +{ + if (!git_bitvec_get(used, pos)) { + git_bitvec_set(used, pos, true); + return 1; + } + + return 0; +} + +static size_t pathspec_mark_remaining( + git_bitvec *used, + git_vector *patterns, + struct pathspec_match_context *ctxt, + size_t start, + const char *path0, + const char *path1) +{ + size_t count = 0; + + if (path1 == path0) + path1 = NULL; + + for (; start < patterns->length; ++start) { + const git_attr_fnmatch *pat = git_vector_get(patterns, start); + + if (git_bitvec_get(used, start)) + continue; + + if (path0 && pathspec_match_one(pat, ctxt, path0) > 0) + count += pathspec_mark_pattern(used, start); + else if (path1 && pathspec_match_one(pat, ctxt, path1) > 0) + count += pathspec_mark_pattern(used, start); + } + + return count; +} + +static int pathspec_build_failure_array( + git_pathspec_string_array_t *failures, + git_vector *patterns, + git_bitvec *used, + git_pool *pool) { - if (!used[pos]) { - used[pos] = 1; - (*ct)++; + size_t pos; + char **failed; + const git_attr_fnmatch *pat; + + for (pos = 0; pos < patterns->length; ++pos) { + if (git_bitvec_get(used, pos)) + continue; + + if ((failed = git_array_alloc(*failures)) == NULL) + return -1; + + pat = git_vector_get(patterns, pos); + + if ((*failed = git_pool_strdup(pool, pat->pattern)) == NULL) + return -1; } + + return 0; } static int pathspec_match_from_iterator( @@ -315,47 +396,37 @@ static int pathspec_match_from_iterator( const git_index_entry *entry = NULL; struct pathspec_match_context ctxt; git_vector *patterns = &ps->pathspec; - bool find_failures = (flags & GIT_PATHSPEC_FIND_FAILURES) != 0; - bool failures_only = (flags & GIT_PATHSPEC_FAILURES_ONLY) != 0; + bool find_failures = out && (flags & GIT_PATHSPEC_FIND_FAILURES) != 0; + bool failures_only = !out || (flags & GIT_PATHSPEC_FAILURES_ONLY) != 0; size_t pos, used_ct = 0, found_files = 0; git_index *index = NULL; - uint8_t *used_patterns = NULL; + git_bitvec used_patterns; char **file; + if (git_bitvec_init(&used_patterns, patterns->length) < 0) + return -1; + if (out) { - *out = m = pathspec_match_alloc(ps); + *out = m = pathspec_match_alloc(ps, PATHSPEC_DATATYPE_STRINGS); GITERR_CHECK_ALLOC(m); - } else { - failures_only = true; - find_failures = false; } if ((error = git_iterator_reset(iter, ps->prefix, ps->prefix)) < 0) goto done; - if (patterns->length > 0) { - used_patterns = git__calloc(patterns->length, sizeof(uint8_t)); - GITERR_CHECK_ALLOC(used_patterns); - } - if (git_iterator_type(iter) == GIT_ITERATOR_TYPE_WORKDIR && (error = git_repository_index__weakptr( &index, git_iterator_owner(iter))) < 0) goto done; - pathspec_match_context_init(&ctxt, - (flags & GIT_PATHSPEC_NO_GLOB) != 0, git_iterator_ignore_case(iter)); + pathspec_match_context_init( + &ctxt, (flags & GIT_PATHSPEC_NO_GLOB) != 0, + git_iterator_ignore_case(iter)); while (!(error = git_iterator_advance(&entry, iter))) { - int result = -1; - - for (pos = 0; pos < patterns->length; ++pos) { - const git_attr_fnmatch *pat = git_vector_get(patterns, pos); - - result = pathspec_match_one(pat, &ctxt, entry->path); - if (result >= 0) - break; - } + /* search for match with entry->path */ + int result = git_pathspec__match_at( + &pos, patterns, &ctxt, entry->path, NULL); /* no matches for this path */ if (result < 0) @@ -363,31 +434,24 @@ static int pathspec_match_from_iterator( /* if result was a negative pattern match, then don't list file */ if (!result) { - pathspec_mark_pattern(used_patterns, pos, &used_ct); + used_ct += pathspec_mark_pattern(&used_patterns, pos); continue; } - /* check if path is untracked and ignored */ + /* check if path is ignored and untracked */ if (index != NULL && git_iterator_current_is_ignored(iter) && git_index__find(NULL, index, entry->path, GIT_INDEX_STAGE_ANY) < 0) continue; /* mark the matched pattern as used */ - pathspec_mark_pattern(used_patterns, pos, &used_ct); + used_ct += pathspec_mark_pattern(&used_patterns, pos); ++found_files; /* if find_failures is on, check if any later patterns also match */ - if (find_failures && used_ct < patterns->length) { - for (++pos; pos < patterns->length; ++pos) { - const git_attr_fnmatch *pat = git_vector_get(patterns, pos); - if (used_patterns[pos]) - continue; - - if (pathspec_match_one(pat, &ctxt, entry->path) > 0) - pathspec_mark_pattern(used_patterns, pos, &used_ct); - } - } + if (find_failures && used_ct < patterns->length) + used_ct += pathspec_mark_remaining( + &used_patterns, patterns, &ctxt, pos + 1, entry->path, NULL); /* if only looking at failures, exit early or just continue */ if (failures_only || !out) { @@ -397,7 +461,7 @@ static int pathspec_match_from_iterator( } /* insert matched path into matches array */ - if ((file = git_array_alloc(m->matches)) == NULL || + if ((file = (char **)git_array_alloc(m->matches)) == NULL || (*file = git_pool_strdup(&m->pool, entry->path)) == NULL) { error = -1; goto done; @@ -409,19 +473,10 @@ static int pathspec_match_from_iterator( error = 0; /* insert patterns that had no matches into failures array */ - if (find_failures && used_ct < patterns->length) { - for (pos = 0; pos < patterns->length; ++pos) { - const git_attr_fnmatch *pat = git_vector_get(patterns, pos); - if (used_patterns[pos]) - continue; - - if ((file = git_array_alloc(m->failures)) == NULL || - (*file = git_pool_strdup(&m->pool, pat->pattern)) == NULL) { - error = -1; - goto done; - } - } - } + if (find_failures && used_ct < patterns->length && + (error = pathspec_build_failure_array( + &m->failures, patterns, &used_patterns, &m->pool)) < 0) + goto done; /* if every pattern failed to match, then we have failed */ if ((flags & GIT_PATHSPEC_NO_MATCH_ERROR) != 0 && !found_files) { @@ -430,7 +485,7 @@ static int pathspec_match_from_iterator( } done: - git__free(used_patterns); + git_bitvec_free(&used_patterns); if (error < 0) { pathspec_match_free(m); @@ -518,33 +573,142 @@ int git_pathspec_match_tree( return error; } +int git_pathspec_match_diff( + git_pathspec_match_list **out, + git_diff_list *diff, + uint32_t flags, + git_pathspec *ps) +{ + int error = 0; + git_pathspec_match_list *m = NULL; + struct pathspec_match_context ctxt; + git_vector *patterns = &ps->pathspec; + bool find_failures = out && (flags & GIT_PATHSPEC_FIND_FAILURES) != 0; + bool failures_only = !out || (flags & GIT_PATHSPEC_FAILURES_ONLY) != 0; + size_t i, pos, used_ct = 0, found_deltas = 0; + const git_diff_delta *delta, **match; + git_bitvec used_patterns; + + assert(diff); + + if (git_bitvec_init(&used_patterns, patterns->length) < 0) + return -1; + + if (out) { + *out = m = pathspec_match_alloc(ps, PATHSPEC_DATATYPE_DIFF); + GITERR_CHECK_ALLOC(m); + } + + pathspec_match_context_init( + &ctxt, (flags & GIT_PATHSPEC_NO_GLOB) != 0, + git_diff_is_sorted_icase(diff)); + + git_vector_foreach(&diff->deltas, i, delta) { + /* search for match with delta */ + int result = git_pathspec__match_at( + &pos, patterns, &ctxt, delta->old_file.path, delta->new_file.path); + + /* no matches for this path */ + if (result < 0) + continue; + + /* mark the matched pattern as used */ + used_ct += pathspec_mark_pattern(&used_patterns, pos); + + /* if result was a negative pattern match, then don't list file */ + if (!result) + continue; + + ++found_deltas; + + /* if find_failures is on, check if any later patterns also match */ + if (find_failures && used_ct < patterns->length) + used_ct += pathspec_mark_remaining( + &used_patterns, patterns, &ctxt, pos + 1, + delta->old_file.path, delta->new_file.path); + + /* if only looking at failures, exit early or just continue */ + if (failures_only || !out) { + if (used_ct == patterns->length) + break; + continue; + } + + /* insert matched delta into matches array */ + if (!(match = (const git_diff_delta **)git_array_alloc(m->matches))) { + error = -1; + goto done; + } else { + *match = delta; + } + } + + /* insert patterns that had no matches into failures array */ + if (find_failures && used_ct < patterns->length && + (error = pathspec_build_failure_array( + &m->failures, patterns, &used_patterns, &m->pool)) < 0) + goto done; + + /* 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"); + error = GIT_ENOTFOUND; + } + +done: + git_bitvec_free(&used_patterns); + + if (error < 0) { + pathspec_match_free(m); + if (out) *out = NULL; + } + + return error; +} + void git_pathspec_match_list_free(git_pathspec_match_list *m) { - pathspec_match_free(m); + if (m) + pathspec_match_free(m); } size_t git_pathspec_match_list_entrycount( const git_pathspec_match_list *m) { - return git_array_size(m->matches); + return m ? git_array_size(m->matches) : 0; } const char *git_pathspec_match_list_entry( const git_pathspec_match_list *m, size_t pos) { - char **entry = git_array_get(m->matches, pos); - return entry ? *entry : NULL; + if (!m || m->datatype != PATHSPEC_DATATYPE_STRINGS || + !git_array_valid_index(m->matches, pos)) + return NULL; + + return *((const char **)git_array_get(m->matches, pos)); +} + +const git_diff_delta *git_pathspec_match_list_diff_entry( + const git_pathspec_match_list *m, size_t pos) +{ + if (!m || m->datatype != PATHSPEC_DATATYPE_DIFF || + !git_array_valid_index(m->matches, pos)) + return NULL; + + return *((const git_diff_delta **)git_array_get(m->matches, pos)); } size_t git_pathspec_match_list_failed_entrycount( const git_pathspec_match_list *m) { - return git_array_size(m->failures); + return m ? git_array_size(m->failures) : 0; } const char * git_pathspec_match_list_failed_entry( const git_pathspec_match_list *m, size_t pos) { - char **entry = git_array_get(m->failures, pos); + char **entry = m ? git_array_get(m->failures, pos) : NULL; + return entry ? *entry : NULL; } + diff --git a/src/pathspec.h b/src/pathspec.h index e7edfea38..40cd21c3f 100644 --- a/src/pathspec.h +++ b/src/pathspec.h @@ -22,12 +22,20 @@ struct git_pathspec { git_pool pool; }; +enum { + PATHSPEC_DATATYPE_STRINGS = 0, + PATHSPEC_DATATYPE_DIFF = 1, +}; + +typedef git_array_t(char *) git_pathspec_string_array_t; + /* public interface to pathspec matching */ struct git_pathspec_match_list { git_pathspec *pathspec; - git_array_t(char *) matches; - git_array_t(char *) failures; + git_array_t(void *) matches; + git_pathspec_string_array_t failures; git_pool pool; + int datatype; }; /* what is the common non-wildcard prefix for all items in the pathspec */ diff --git a/tests-clar/diff/pathspec.c b/tests-clar/diff/pathspec.c new file mode 100644 index 000000000..332b513b3 --- /dev/null +++ b/tests-clar/diff/pathspec.c @@ -0,0 +1,92 @@ +#include "clar_libgit2.h" +#include "diff_helpers.h" + +static git_repository *g_repo = NULL; + +void test_diff_pathspec__initialize(void) +{ + g_repo = cl_git_sandbox_init("status"); +} + +void test_diff_pathspec__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_diff_pathspec__0(void) +{ + const char *a_commit = "26a125ee"; /* the current HEAD */ + const char *b_commit = "0017bd4a"; /* the start */ + git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); + git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit); + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff_list *diff = NULL; + git_strarray paths = { NULL, 1 }; + char *path; + git_pathspec *ps; + git_pathspec_match_list *matches; + + cl_assert(a); + cl_assert(b); + + path = "*_file"; + paths.strings = &path; + cl_git_pass(git_pathspec_new(&ps, &paths)); + + cl_git_pass(git_pathspec_match_tree(&matches, a, GIT_PATHSPEC_DEFAULT, ps)); + cl_assert_equal_i(7, git_pathspec_match_list_entrycount(matches)); + cl_assert_equal_s("current_file", git_pathspec_match_list_entry(matches,0)); + cl_assert(git_pathspec_match_list_diff_entry(matches,0) == NULL); + git_pathspec_match_list_free(matches); + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, NULL, a, &opts)); + + cl_git_pass(git_pathspec_match_diff( + &matches, diff, GIT_PATHSPEC_DEFAULT, ps)); + cl_assert_equal_i(7, git_pathspec_match_list_entrycount(matches)); + cl_assert(git_pathspec_match_list_diff_entry(matches, 0) != NULL); + cl_assert(git_pathspec_match_list_entry(matches, 0) == NULL); + cl_assert_equal_s("current_file", + git_pathspec_match_list_diff_entry(matches,0)->new_file.path); + cl_assert_equal_i(GIT_DELTA_ADDED, + git_pathspec_match_list_diff_entry(matches,0)->status); + git_pathspec_match_list_free(matches); + + git_diff_list_free(diff); + diff = NULL; + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); + + cl_git_pass(git_pathspec_match_diff( + &matches, diff, GIT_PATHSPEC_DEFAULT, ps)); + cl_assert_equal_i(3, git_pathspec_match_list_entrycount(matches)); + cl_assert(git_pathspec_match_list_diff_entry(matches, 0) != NULL); + cl_assert(git_pathspec_match_list_entry(matches, 0) == NULL); + cl_assert_equal_s("subdir/current_file", + git_pathspec_match_list_diff_entry(matches,0)->new_file.path); + cl_assert_equal_i(GIT_DELTA_DELETED, + git_pathspec_match_list_diff_entry(matches,0)->status); + git_pathspec_match_list_free(matches); + + git_diff_list_free(diff); + diff = NULL; + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); + + cl_git_pass(git_pathspec_match_diff( + &matches, diff, GIT_PATHSPEC_DEFAULT, ps)); + cl_assert_equal_i(4, git_pathspec_match_list_entrycount(matches)); + cl_assert(git_pathspec_match_list_diff_entry(matches, 0) != NULL); + cl_assert(git_pathspec_match_list_entry(matches, 0) == NULL); + cl_assert_equal_s("modified_file", + git_pathspec_match_list_diff_entry(matches,0)->new_file.path); + cl_assert_equal_i(GIT_DELTA_MODIFIED, + git_pathspec_match_list_diff_entry(matches,0)->status); + git_pathspec_match_list_free(matches); + + git_diff_list_free(diff); + diff = NULL; + + git_tree_free(a); + git_tree_free(b); +} -- cgit v1.2.1 From 406dd556e20117b3cc2e5c53410d65314fd14056 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 10 Jul 2013 21:05:47 +0200 Subject: bitvec: Simplify the bit vector code --- src/bitvec.h | 61 ++++++++++++++++++++++-------------------------------------- 1 file changed, 22 insertions(+), 39 deletions(-) diff --git a/src/bitvec.h b/src/bitvec.h index a033f534f..fd6f0ccf8 100644 --- a/src/bitvec.h +++ b/src/bitvec.h @@ -19,58 +19,43 @@ typedef struct { size_t length; union { - uint8_t *ptr; + uint64_t *words; uint64_t bits; } u; } git_bitvec; GIT_INLINE(int) git_bitvec_init(git_bitvec *bv, size_t capacity) { - if (capacity < 64) { - bv->length = 0; - bv->u.bits = 0; - return 0; + memset(bv, 0x0, sizeof(*bv)); + + if (capacity >= 64) { + bv->length = (capacity / 64) + 1; + bv->u.words = git__calloc(bv->length, sizeof(uint64_t)); + if (!bv->u.words) + return -1; } - bv->length = (capacity + 7) / 8; - bv->u.ptr = git__calloc(bv->length, 1); - return bv->u.ptr ? 0 : -1; + return 0; } -#define GIT_BITVEC_MASK_INLINE(BIT) (((uint64_t)1) << BIT) - -#define GIT_BITVEC_MASK_BYTE(BIT) (((uint8_t)1) << ((BIT) & 0x07)) -#define GIT_BITVEC_INDEX_BYTE(BIT) ((BIT) >> 3) +#define GIT_BITVEC_MASK(BIT) ((uint64_t)1 << (BIT % 64)) +#define GIT_BITVEC_WORD(BV, BIT) (BV->length ? &BV->u.words[BIT / 64] : &BV->u.bits) GIT_INLINE(void) git_bitvec_set(git_bitvec *bv, size_t bit, bool on) { - if (!bv->length) { - assert(bit < 64); - - if (on) - bv->u.bits |= GIT_BITVEC_MASK_INLINE(bit); - else - bv->u.bits &= ~GIT_BITVEC_MASK_INLINE(bit); - } else { - assert(bit < bv->length * 8); + uint64_t *word = GIT_BITVEC_WORD(bv, bit); + uint64_t mask = GIT_BITVEC_MASK(bit); - if (on) - bv->u.ptr[GIT_BITVEC_INDEX_BYTE(bit)] |= GIT_BITVEC_MASK_BYTE(bit); - else - bv->u.ptr[GIT_BITVEC_INDEX_BYTE(bit)] &= ~GIT_BITVEC_MASK_BYTE(bit); - } + if (on) + *word |= mask; + else + *word &= ~mask; } GIT_INLINE(bool) git_bitvec_get(git_bitvec *bv, size_t bit) { - if (!bv->length) { - assert(bit < 64); - return (bv->u.bits & GIT_BITVEC_MASK_INLINE(bit)) != 0; - } else { - assert(bit < bv->length * 8); - return (bv->u.ptr[GIT_BITVEC_INDEX_BYTE(bit)] & - GIT_BITVEC_MASK_BYTE(bit)) != 0; - } + uint64_t *word = GIT_BITVEC_WORD(bv, bit); + return (*word & GIT_BITVEC_MASK(bit)) != 0; } GIT_INLINE(void) git_bitvec_clear(git_bitvec *bv) @@ -78,15 +63,13 @@ GIT_INLINE(void) git_bitvec_clear(git_bitvec *bv) if (!bv->length) bv->u.bits = 0; else - memset(bv->u.ptr, 0, bv->length); + memset(bv->u.words, 0x0, bv->length * sizeof(uint64_t)); } GIT_INLINE(void) git_bitvec_free(git_bitvec *bv) { - if (bv->length) { - git__free(bv->u.ptr); - memset(bv, 0, sizeof(*bv)); - } + if (bv->length) + git__free(bv->u.words); } #endif -- cgit v1.2.1 From 0105b55e8f7e4d8194400b341b6e0425182ff636 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 27 Jun 2013 15:26:31 -0700 Subject: Add another submodule test of dirty wd --- tests-clar/diff/submodules.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index 5de46732b..1c9940cc5 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -121,6 +121,45 @@ void test_diff_submodules__dirty_submodule(void) git_diff_list_free(diff); } +void test_diff_submodules__dirty_submodule_2(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff_list *diff = NULL; + char *smpath = "testrepo"; + static const char *expected_none[] = { NULL, "" }; + static const char *expected_dirty[] = { + "diff --git a/testrepo b/testrepo\nindex a65fedf..a65fedf 160000\n--- a/testrepo\n+++ b/testrepo\n@@ -1 +1 @@\n-Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750\n+Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750-dirty\n", /* testrepo.git */ + "" + }; + + setup_submodules(); + + cl_git_pass(git_submodule_reload_all(g_repo)); + + opts.flags = GIT_DIFF_INCLUDE_IGNORED | + GIT_DIFF_INCLUDE_UNTRACKED | + GIT_DIFF_INCLUDE_UNMODIFIED; + opts.pathspec.count = 1; + opts.pathspec.strings = &smpath; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_none); + git_diff_list_free(diff); + + cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); + cl_git_mkfile("submodules/testrepo/all_new.txt", "never seen before"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_dirty); + git_diff_list_free(diff); + + cl_git_pass(git_submodule_reload_all(g_repo)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_dirty); + git_diff_list_free(diff); +} + void test_diff_submodules__submod2_index_to_wd(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; -- cgit v1.2.1 From 12f8fe0054505d6c3228a5186516f7c5f28d5165 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 27 Jun 2013 15:43:12 -0700 Subject: More improvements to submodule diff tests This controls for the diff.mnemonicprefix setting so that can't break the tests. Also, this expands one test to emulate an ObjectiveGit test more closely. --- tests-clar/diff/submodules.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index 1c9940cc5..e3c4e66a3 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -86,6 +86,7 @@ void test_diff_submodules__unmodified_submodule(void) opts.flags = GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_INCLUDE_UNMODIFIED; + opts.old_prefix = "a"; opts.new_prefix = "b"; cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected); @@ -115,6 +116,7 @@ void test_diff_submodules__dirty_submodule(void) opts.flags = GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_INCLUDE_UNMODIFIED; + opts.old_prefix = "a"; opts.new_prefix = "b"; cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected); @@ -124,9 +126,9 @@ void test_diff_submodules__dirty_submodule(void) void test_diff_submodules__dirty_submodule_2(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff_list *diff = NULL, *diff2 = NULL; char *smpath = "testrepo"; - static const char *expected_none[] = { NULL, "" }; + static const char *expected_none[] = { "" }; static const char *expected_dirty[] = { "diff --git a/testrepo b/testrepo\nindex a65fedf..a65fedf 160000\n--- a/testrepo\n+++ b/testrepo\n@@ -1 +1 @@\n-Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750\n+Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750-dirty\n", /* testrepo.git */ "" @@ -136,9 +138,11 @@ void test_diff_submodules__dirty_submodule_2(void) cl_git_pass(git_submodule_reload_all(g_repo)); - opts.flags = GIT_DIFF_INCLUDE_IGNORED | - GIT_DIFF_INCLUDE_UNTRACKED | - GIT_DIFF_INCLUDE_UNMODIFIED; + opts.flags = GIT_DIFF_INCLUDE_UNTRACKED | + GIT_DIFF_INCLUDE_UNTRACKED_CONTENT | + GIT_DIFF_RECURSE_UNTRACKED_DIRS | + GIT_DIFF_DISABLE_PATHSPEC_MATCH; + opts.old_prefix = "a"; opts.new_prefix = "b"; opts.pathspec.count = 1; opts.pathspec.strings = &smpath; @@ -151,6 +155,18 @@ void test_diff_submodules__dirty_submodule_2(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_dirty); + + { + git_tree *head; + + cl_git_pass(git_repository_head_tree(&head, g_repo)); + cl_git_pass(git_diff_tree_to_index(&diff2, g_repo, head, NULL, &opts)); + cl_git_pass(git_diff_merge(diff, diff2)); + git_diff_list_free(diff2); + + check_diff_patches(diff, expected_dirty); + } + git_diff_list_free(diff); cl_git_pass(git_submodule_reload_all(g_repo)); @@ -179,6 +195,7 @@ void test_diff_submodules__submod2_index_to_wd(void) setup_submodules2(); opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + opts.old_prefix = "a"; opts.new_prefix = "b"; cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected); @@ -201,6 +218,7 @@ void test_diff_submodules__submod2_head_to_index(void) cl_git_pass(git_repository_head_tree(&head, g_repo)); opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + opts.old_prefix = "a"; opts.new_prefix = "b"; cl_git_pass(git_diff_tree_to_index(&diff, g_repo, head, NULL, &opts)); check_diff_patches(diff, expected); -- cgit v1.2.1 From 49621a34af7160d4afbf08a5be15e0e4f3a47791 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 27 Jun 2013 15:46:46 -0700 Subject: Fix memory leak in test --- tests-clar/diff/submodules.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index e3c4e66a3..ffaae3ce4 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -163,6 +163,7 @@ void test_diff_submodules__dirty_submodule_2(void) cl_git_pass(git_diff_tree_to_index(&diff2, g_repo, head, NULL, &opts)); cl_git_pass(git_diff_merge(diff, diff2)); git_diff_list_free(diff2); + git_tree_free(head); check_diff_patches(diff, expected_dirty); } -- cgit v1.2.1 From 3e7d7100e2be8f6c1fe290842ee9a19b854a7046 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 27 Jun 2013 16:12:00 -0700 Subject: Fix diff test helper to show parent file/line --- tests-clar/diff/submodules.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index ffaae3ce4..c7bdf6d75 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -37,7 +37,8 @@ void test_diff_submodules__cleanup(void) cl_fixture_cleanup("submod2_target"); } -static void check_diff_patches(git_diff_list *diff, const char **expected) +static void check_diff_patches_at_line( + git_diff_list *diff, const char **expected, const char *file, int line) { const git_diff_delta *delta; git_diff_patch *patch = NULL; @@ -48,24 +49,30 @@ static void check_diff_patches(git_diff_list *diff, const char **expected) cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d)); if (delta->status == GIT_DELTA_UNMODIFIED) { - cl_assert(expected[d] == NULL); + clar__assert(expected[d] == NULL, file, line, "found UNMODIFIED delta where modified was expected", NULL, 1); continue; } if (expected[d] && !strcmp(expected[d], "")) continue; - if (expected[d] && !strcmp(expected[d], "")) - cl_assert(0); + if (expected[d] && !strcmp(expected[d], "")) { + cl_git_pass(git_diff_patch_to_str(&patch_text, patch)); + clar__assert(0, file, line, "expected end of deltas, but found more", patch_text, 1); + } cl_git_pass(git_diff_patch_to_str(&patch_text, patch)); - cl_assert_equal_s(expected[d], patch_text); + clar__assert_equal_s(expected[d], patch_text, file, line, + "expected diff did not match actual diff", 1); git__free(patch_text); } - cl_assert(expected[d] && !strcmp(expected[d], "")); + clar__assert(expected[d] && !strcmp(expected[d], ""), file, line, "found fewer deltas than expected", expected[d], 1); } +#define check_diff_patches(diff, exp) \ + check_diff_patches_at_line(diff, exp, __FILE__, __LINE__) + void test_diff_submodules__unmodified_submodule(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; -- cgit v1.2.1 From 4535f04409a9379ace7cdda0b53a62d3cdf20676 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 27 Jun 2013 16:12:44 -0700 Subject: More diff submodule tests for cache issues The submodules code caches data about submodules in a way that can cause problems. This adds some tests that try making various modifications to the state of a submodule to see where we can catch out problems in the submodule caching. Right now, I've put in an extra git_submodule_reload_all so that the test will pass, but with that commented out, the test fails. I'm working on fixing the broken version of the test at which point I'll commit the fix and delete the extra reload that makes the test pass. --- tests-clar/diff/submodules.c | 150 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index c7bdf6d75..9b77897b7 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -234,3 +234,153 @@ void test_diff_submodules__submod2_head_to_index(void) git_tree_free(head); } + +void test_diff_submodules__invalid_cache(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff_list *diff = NULL; + git_submodule *sm; + char *smpath = "sm_changed_head"; + git_repository *smrepo; + git_index *smindex; + static const char *expected_baseline[] = { + "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ + "" + }; + static const char *expected_unchanged[] = { "" }; + static const char *expected_dirty[] = { + "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247-dirty\n", + "" + }; + static const char *expected_moved[] = { + "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..0910a13 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 0910a13dfa2210496f6c590d75bc360dd11b2a1b\n", + "" + }; + static const char *expected_moved_dirty[] = { + "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..0910a13 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 0910a13dfa2210496f6c590d75bc360dd11b2a1b-dirty\n", + "" + }; + + setup_submodules2(); + + opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + opts.old_prefix = "a"; opts.new_prefix = "b"; + opts.pathspec.count = 1; + opts.pathspec.strings = &smpath; + + /* baseline */ + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_baseline); + git_diff_list_free(diff); + + /* update index with new HEAD */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath)); + cl_git_pass(git_submodule_add_to_index(sm, 1)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_unchanged); + git_diff_list_free(diff); + + /* create untracked file in submodule working directory */ + cl_git_mkfile("submod2/sm_changed_head/new_around_here", "hello"); + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_NONE); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_dirty); + git_diff_list_free(diff); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_UNTRACKED); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_unchanged); + git_diff_list_free(diff); + + /* modify tracked file in submodule working directory */ + cl_git_append2file( + "submod2/sm_changed_head/file_to_modify", "\nmore stuff\n"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_dirty); + git_diff_list_free(diff); + + cl_git_pass(git_submodule_reload_all(g_repo)); + cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_dirty); + git_diff_list_free(diff); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_unchanged); + git_diff_list_free(diff); + + /* add file to index in submodule */ + cl_git_pass(git_submodule_open(&smrepo, sm)); + cl_git_pass(git_repository_index(&smindex, smrepo)); + cl_git_pass(git_index_add_bypath(smindex, "file_to_modify")); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_UNTRACKED); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_dirty); + git_diff_list_free(diff); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_unchanged); + git_diff_list_free(diff); + + /* commit changed index of submodule */ + { + git_object *parent; + git_oid tree_id, commit_id; + git_tree *tree; + git_signature *sig; + + cl_git_pass(git_revparse_single(&parent, smrepo, "HEAD")); + cl_git_pass(git_index_write_tree(&tree_id, smindex)); + cl_git_pass(git_index_write(smindex)); + cl_git_pass(git_tree_lookup(&tree, smrepo, &tree_id)); + cl_git_pass(git_signature_new(&sig, "Sm Test", "sm@tester.test", 1372350000, 480)); + cl_git_pass(git_commit_create_v( + &commit_id, smrepo, "HEAD", sig, sig, NULL, + "Move it", tree, 1, parent)); + git_object_free(parent); + git_tree_free(tree); + git_signature_free(sig); + } + + /* THIS RELOAD SHOULD NOT BE REQUIRED */ + cl_git_pass(git_submodule_reload_all(g_repo)); + cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath)); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_moved); + git_diff_list_free(diff); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_ALL); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_unchanged); + git_diff_list_free(diff); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_NONE); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_moved_dirty); + git_diff_list_free(diff); + + p_unlink("submod2/sm_changed_head/new_around_here"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_moved); + git_diff_list_free(diff); + + git_index_free(smindex); + git_repository_free(smrepo); +} -- cgit v1.2.1 From 41f1f9d732a7cdd50d58948224ca0693a68995dc Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 27 Jun 2013 16:52:00 -0700 Subject: Add API to get path to index file --- include/git2/index.h | 8 ++++++++ src/index.c | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/include/git2/index.h b/include/git2/index.h index 1fb77efa3..b44535601 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -239,6 +239,14 @@ GIT_EXTERN(int) git_index_read(git_index *index); */ GIT_EXTERN(int) git_index_write(git_index *index); +/** + * Get the full path to the index file on disk. + * + * @param index an existing index object + * @return path to index file or NULL for in-memory index + */ +GIT_EXTERN(const char *) git_index_path(git_index *index); + /** * Read a tree into the index file with stats * diff --git a/src/index.c b/src/index.c index 21efd2c63..bd5e192f3 100644 --- a/src/index.c +++ b/src/index.c @@ -516,6 +516,12 @@ int git_index_write(git_index *index) return 0; } +const char * git_index_path(git_index *index) +{ + assert(index); + return index->index_file_path; +} + int git_index_write_tree(git_oid *oid, git_index *index) { git_repository *repo; -- cgit v1.2.1 From e807860fa9b5278932a0ba25f84b4035b0ebda84 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 27 Jun 2013 16:52:38 -0700 Subject: Add timestamp check to submodule status This is probably not the final form of this change, but this is a preliminary version of checking a timestamp to see if the cached working directory HEAD OID matches the current. Right now, this uses the timestamp on the index and is, like most of our timestamp checking, subject to having only second accuracy. --- src/submodule.c | 42 +++++++++++++++++++++++++++++++++----- src/submodule.h | 48 ++++++++++++++++++++++++++++---------------- tests-clar/diff/submodules.c | 13 ++++++++---- 3 files changed, 77 insertions(+), 26 deletions(-) diff --git a/src/submodule.c b/src/submodule.c index dcd58d016..e6ed7e33e 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -9,9 +9,7 @@ #include "git2/config.h" #include "git2/sys/config.h" #include "git2/types.h" -#include "git2/repository.h" #include "git2/index.h" -#include "git2/submodule.h" #include "buffer.h" #include "buf_text.h" #include "vector.h" @@ -544,6 +542,15 @@ const git_oid *git_submodule_wd_id(git_submodule *submodule) { assert(submodule); + /* if we know the submodule index timestamp and it has moved, then + * let's reload the working directory information for the submodule + */ + if (submodule->wd_head_path != NULL && + git_futils_filestamp_check( + &submodule->wd_stamp, submodule->wd_head_path)) + submodule->flags &= ~GIT_SUBMODULE_STATUS__WD_OID_VALID; + + /* load unless we think we have a valid oid */ if (!(submodule->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID)) { git_repository *subrepo; @@ -702,11 +709,36 @@ int git_submodule_open( /* if we have opened the submodule successfully, let's grab the HEAD OID */ if (!error) { + git_buf buf = GIT_BUF_INIT; + + /* For now, let's just the index timestamp... + * + * git_buf_joinpath(&buf, git_repository_path(*subrepo), GIT_HEAD_FILE); + * if (!git_path_exists(buf.ptr)) { + */ + git_index *index; + if (!git_repository_index__weakptr(&index, *subrepo)) + git_buf_sets(&buf, git_index_path(index)); + else + git_buf_free(&buf); + /* } */ + + if (git_buf_len(&buf) > 0) { + git__free(submodule->wd_head_path); + submodule->wd_head_path = git_buf_detach(&buf); + } + if (!git_reference_name_to_id( - &submodule->wd_oid, *subrepo, GIT_HEAD_FILE)) + &submodule->wd_oid, *subrepo, GIT_HEAD_FILE)) { + submodule->flags |= GIT_SUBMODULE_STATUS__WD_OID_VALID; - else - giterr_clear(); + + if (submodule->wd_head_path) + git_futils_filestamp_check( + &submodule->wd_stamp, submodule->wd_head_path); + } + + giterr_clear(); } return error; diff --git a/src/submodule.h b/src/submodule.h index ba8e2518e..88d4f97c7 100644 --- a/src/submodule.h +++ b/src/submodule.h @@ -7,6 +7,10 @@ #ifndef INCLUDE_submodule_h__ #define INCLUDE_submodule_h__ +#include "git2/submodule.h" +#include "git2/repository.h" +#include "fileops.h" + /* Notes: * * Submodule information can be in four places: the index, the config files @@ -44,43 +48,53 @@ * an entry for every submodule found in the HEAD and index, and for every * submodule described in .gitmodules. The fields are as follows: * - * - `owner` is the git_repository containing this submodule * - `name` is the name of the submodule from .gitmodules. * - `path` is the path to the submodule from the repo root. It is almost * always the same as `name`. * - `url` is the url for the submodule. - * - `tree_oid` is the SHA1 for the submodule path in the repo HEAD. - * - `index_oid` is the SHA1 for the submodule recorded in the index. - * - `workdir_oid` is the SHA1 for the HEAD of the checked out submodule. * - `update` is a git_submodule_update_t value - see gitmodules(5) update. + * - `update_default` is the update value from the config * - `ignore` is a git_submodule_ignore_t value - see gitmodules(5) ignore. + * - `ignore_default` is the ignore value from the config * - `fetch_recurse` is 0 or 1 - see gitmodules(5) fetchRecurseSubmodules. - * - `refcount` tracks how many hashmap entries there are for this submodule. - * It only comes into play if the name and path of the submodule differ. - * - `flags` is for internal use, tracking where this submodule has been - * found (head, index, config, workdir) and other misc info about it. + * + * - `owner` is the git_repository containing this submodule + * - `flags` after for internal use, tracking where this submodule has been + * found (head, index, config, workdir) and known status info, etc. + * - `head_oid` is the SHA1 for the submodule path in the repo HEAD. + * - `index_oid` is the SHA1 for the submodule recorded in the index. + * - `wd_oid` is the SHA1 for the HEAD of the checked out submodule. + * - `wd_index_path` is the path to the index of the checked out submodule + * - `wd_last_index` is a timestamp of that submodule index so we can + * quickly check if the `wd_oid` should be rechecked + * - `refcount` tracks how many hash table entries in the + * git_submodule_cache there are for this submodule. It only comes into + * play if the name and path of the submodule differ. * * If the submodule has been added to .gitmodules but not yet git added, - * then the `index_oid` will be valid and zero. If the submodule has been - * deleted, but the delete has not been committed yet, then the `index_oid` - * will be set, but the `url` will be NULL. + * then the `index_oid` will be zero but still marked valid. If the + * submodule has been deleted, but the delete has not been committed yet, + * then the `index_oid` will be set, but the `url` will be NULL. */ struct git_submodule { - git_repository *owner; + /* information from config */ char *name; char *path; /* important: may point to same string data as "name" */ char *url; - uint32_t flags; - git_oid head_oid; - git_oid index_oid; - git_oid wd_oid; - /* information from config */ git_submodule_update_t update; git_submodule_update_t update_default; git_submodule_ignore_t ignore; git_submodule_ignore_t ignore_default; int fetch_recurse; + /* internal information */ + git_repository *owner; + uint32_t flags; + git_oid head_oid; + git_oid index_oid; + git_oid wd_oid; + char *wd_head_path; + git_futils_filestamp wd_stamp; int refcount; }; diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index 9b77897b7..c94fd57c6 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -333,29 +333,34 @@ void test_diff_submodules__invalid_cache(void) check_diff_patches(diff, expected_unchanged); git_diff_list_free(diff); + sleep(2); + /* commit changed index of submodule */ { git_object *parent; git_oid tree_id, commit_id; git_tree *tree; git_signature *sig; + git_reference *ref; - cl_git_pass(git_revparse_single(&parent, smrepo, "HEAD")); + cl_git_pass(git_revparse_ext(&parent, &ref, smrepo, "HEAD")); cl_git_pass(git_index_write_tree(&tree_id, smindex)); cl_git_pass(git_index_write(smindex)); cl_git_pass(git_tree_lookup(&tree, smrepo, &tree_id)); cl_git_pass(git_signature_new(&sig, "Sm Test", "sm@tester.test", 1372350000, 480)); cl_git_pass(git_commit_create_v( - &commit_id, smrepo, "HEAD", sig, sig, NULL, - "Move it", tree, 1, parent)); + &commit_id, smrepo, git_reference_name(ref), sig, sig, + NULL, "Move it", tree, 1, parent)); git_object_free(parent); git_tree_free(tree); + git_reference_free(ref); git_signature_free(sig); } - /* THIS RELOAD SHOULD NOT BE REQUIRED */ + /* THIS RELOAD SHOULD NOT BE REQUIRED cl_git_pass(git_submodule_reload_all(g_repo)); cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath)); + */ git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); -- cgit v1.2.1 From 302a04b09ca706eeda9b8cceb50694f37973e348 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sat, 29 Jun 2013 12:41:39 -0700 Subject: Add accessors for refcount value --- src/thread-utils.h | 5 +++++ src/util.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/thread-utils.h b/src/thread-utils.h index f19a2ba2c..f8c4dc66d 100644 --- a/src/thread-utils.h +++ b/src/thread-utils.h @@ -43,6 +43,11 @@ GIT_INLINE(void) git_atomic_set(git_atomic *a, int val) a->val = val; } +GIT_INLINE(int) git_atomic_get(git_atomic *a) +{ + return (int)a->val; +} + #ifdef GIT_THREADS #define git_thread pthread_t diff --git a/src/util.h b/src/util.h index e0088399c..a97c9bf39 100644 --- a/src/util.h +++ b/src/util.h @@ -221,6 +221,9 @@ typedef void (*git_refcount_freeptr)(void *r); #define GIT_REFCOUNT_OWNER(r) (((git_refcount *)(r))->owner) +#define GIT_REFCOUNT_VAL(r) git_atomic_get(&((git_refcount *)(r))->refcount) + + static signed char from_hex[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ -- cgit v1.2.1 From 3fe046cfdba414f69b09e76da2a550be96eeab7e Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sat, 29 Jun 2013 13:13:38 -0700 Subject: Add BARE option to git_repository_open_ext This adds a BARE option to git_repository_open_ext which allows a fast open path that still knows how to read gitlinks and to search for the actual .git directory from a subdirectory. `git_repository_open_bare` is still simpler and faster, but having a gitlink aware fast open is very useful for submodules where we want to quickly be able to peek at the HEAD and index data without doing any other meaningful repo operations. --- include/git2/repository.h | 4 +++ src/repository.c | 15 ++++++----- tests-clar/repo/open.c | 65 ++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 74 insertions(+), 10 deletions(-) diff --git a/include/git2/repository.h b/include/git2/repository.h index c81051969..807d834fe 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -94,10 +94,14 @@ GIT_EXTERN(int) git_repository_discover( * changes from the `stat` system call). (E.g. Searching in a user's home * directory "/home/user/source/" will not return "/.git/" as the found * repo if "/" is a different filesystem than "/home".) + * * GIT_REPOSITORY_OPEN_BARE - Open repository as a bare repo regardless + * of core.bare config, and defer loading config file for faster setup. + * Unlike `git_repository_open_bare`, this can follow gitlinks. */ typedef enum { GIT_REPOSITORY_OPEN_NO_SEARCH = (1 << 0), GIT_REPOSITORY_OPEN_CROSS_FS = (1 << 1), + GIT_REPOSITORY_OPEN_BARE = (1 << 2), } git_repository_open_flag_t; /** diff --git a/src/repository.c b/src/repository.c index ed9469c59..bd7ef5476 100644 --- a/src/repository.c +++ b/src/repository.c @@ -266,7 +266,7 @@ static int find_ceiling_dir_offset( buf[--len] = '\0'; if (!strncmp(path, buf2, len) && - path[len] == '/' && + (path[len] == '/' || !path[len]) && len > max_len) { max_len = len; @@ -322,17 +322,18 @@ static int find_repo( git_buf path = GIT_BUF_INIT; struct stat st; dev_t initial_device = 0; - bool try_with_dot_git = false; + bool try_with_dot_git = ((flags & GIT_REPOSITORY_OPEN_BARE) != 0); int ceiling_offset; git_buf_free(repo_path); - if ((error = git_path_prettify_dir(&path, start_path, NULL)) < 0) + if ((error = git_path_prettify(&path, start_path, NULL)) < 0) return error; ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs); - if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0) + if (!try_with_dot_git && + (error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0) return error; while (!error && !git_buf_len(repo_path)) { @@ -384,7 +385,7 @@ static int find_repo( try_with_dot_git = !try_with_dot_git; } - if (!error && parent_path != NULL) { + if (!error && parent_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) { if (!git_buf_len(repo_path)) git_buf_clear(parent_path); else { @@ -460,7 +461,9 @@ int git_repository_open_ext( repo->path_repository = git_buf_detach(&path); GITERR_CHECK_ALLOC(repo->path_repository); - if ((error = load_config_data(repo)) < 0 || + if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) + repo->is_bare = 1; + else if ((error = load_config_data(repo)) < 0 || (error = load_workdir(repo, &parent)) < 0) { git_repository_free(repo); diff --git a/tests-clar/repo/open.c b/tests-clar/repo/open.c index 840858586..f386612a7 100644 --- a/tests-clar/repo/open.c +++ b/tests-clar/repo/open.c @@ -69,14 +69,23 @@ void test_repo_open__open_with_discover(void) cl_fixture_cleanup("attr"); } +static void make_gitlink_dir(const char *dir, const char *linktext) +{ + git_buf path = GIT_BUF_INIT; + + cl_git_pass(git_futils_mkdir(dir, NULL, 0777, GIT_MKDIR_VERIFY_DIR)); + cl_git_pass(git_buf_joinpath(&path, dir, ".git")); + cl_git_rewritefile(path.ptr, linktext); + git_buf_free(&path); +} + void test_repo_open__gitlinked(void) { /* need to have both repo dir and workdir set up correctly */ git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); git_repository *repo2; - cl_must_pass(p_mkdir("alternate", 0777)); - cl_git_mkfile("alternate/.git", "gitdir: ../empty_standard_repo/.git"); + make_gitlink_dir("alternate", "gitdir: ../empty_standard_repo/.git"); cl_git_pass(git_repository_open(&repo2, "alternate")); @@ -193,12 +202,11 @@ void test_repo_open__bad_gitlinks(void) cl_git_sandbox_init("attr"); - cl_git_pass(p_mkdir("alternate", 0777)); cl_git_pass(p_mkdir("invalid", 0777)); cl_git_pass(git_futils_mkdir_r("invalid2/.git", NULL, 0777)); for (scan = bad_links; *scan != NULL; scan++) { - cl_git_rewritefile("alternate/.git", *scan); + make_gitlink_dir("alternate", *scan); cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL)); } @@ -315,3 +323,52 @@ void test_repo_open__no_config(void) git_repository_free(repo); cl_fixture_cleanup("empty_standard_repo"); } + +void test_repo_open__force_bare(void) +{ + /* need to have both repo dir and workdir set up correctly */ + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + git_repository *barerepo; + + make_gitlink_dir("alternate", "gitdir: ../empty_standard_repo/.git"); + + cl_assert(!git_repository_is_bare(repo)); + + cl_git_pass(git_repository_open(&barerepo, "alternate")); + cl_assert(!git_repository_is_bare(barerepo)); + git_repository_free(barerepo); + + cl_git_pass(git_repository_open_bare( + &barerepo, "empty_standard_repo/.git")); + cl_assert(git_repository_is_bare(barerepo)); + git_repository_free(barerepo); + + cl_git_fail(git_repository_open_bare(&barerepo, "alternate/.git")); + + cl_git_pass(git_repository_open_ext( + &barerepo, "alternate/.git", GIT_REPOSITORY_OPEN_BARE, NULL)); + cl_assert(git_repository_is_bare(barerepo)); + git_repository_free(barerepo); + + cl_git_pass(p_mkdir("empty_standard_repo/subdir", 0777)); + cl_git_mkfile("empty_standard_repo/subdir/something.txt", "something"); + + cl_git_fail(git_repository_open_bare( + &barerepo, "empty_standard_repo/subdir")); + + cl_git_pass(git_repository_open_ext( + &barerepo, "empty_standard_repo/subdir", GIT_REPOSITORY_OPEN_BARE, NULL)); + cl_assert(git_repository_is_bare(barerepo)); + git_repository_free(barerepo); + + cl_git_pass(p_mkdir("alternate/subdir", 0777)); + cl_git_pass(p_mkdir("alternate/subdir/sub2", 0777)); + cl_git_mkfile("alternate/subdir/sub2/something.txt", "something"); + + cl_git_fail(git_repository_open_bare(&barerepo, "alternate/subdir/sub2")); + + cl_git_pass(git_repository_open_ext( + &barerepo, "alternate/subdir/sub2", GIT_REPOSITORY_OPEN_BARE, NULL)); + cl_assert(git_repository_is_bare(barerepo)); + git_repository_free(barerepo); +} -- cgit v1.2.1 From 1aad6137d218830bc280c4327595182019164515 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sat, 29 Jun 2013 13:16:33 -0700 Subject: Submodule status improvements This fixes the way that submodule status is checked to bypass just about all of the caching in the submodule object. Based on the ignore value, it will try to do the minimum work necessary to find the current status of the submodule - but it will actually go to disk to get all of the current values. This also removes the custom refcounting stuff in favor of the common git_refcount style. Right now, it is still for internal purposes only, but it should make it easier to add true submodule refcounting in the future with a public git_submodule_free call that will allow bindings not to worry about the submodule object getting freed from underneath them. --- include/git2/submodule.h | 16 +- src/submodule.c | 616 +++++++++++++++++++++++------------------------ src/submodule.h | 38 ++- 3 files changed, 336 insertions(+), 334 deletions(-) diff --git a/include/git2/submodule.h b/include/git2/submodule.h index 91b5300ae..3267bcd0f 100644 --- a/include/git2/submodule.h +++ b/include/git2/submodule.h @@ -119,19 +119,9 @@ typedef enum { GIT_SUBMODULE_STATUS_WD_UNTRACKED = (1u << 13), } git_submodule_status_t; -#define GIT_SUBMODULE_STATUS__IN_FLAGS \ - (GIT_SUBMODULE_STATUS_IN_HEAD | \ - GIT_SUBMODULE_STATUS_IN_INDEX | \ - GIT_SUBMODULE_STATUS_IN_CONFIG | \ - GIT_SUBMODULE_STATUS_IN_WD) - -#define GIT_SUBMODULE_STATUS__INDEX_FLAGS \ - (GIT_SUBMODULE_STATUS_INDEX_ADDED | \ - GIT_SUBMODULE_STATUS_INDEX_DELETED | \ - GIT_SUBMODULE_STATUS_INDEX_MODIFIED) - -#define GIT_SUBMODULE_STATUS__WD_FLAGS \ - ~(GIT_SUBMODULE_STATUS__IN_FLAGS | GIT_SUBMODULE_STATUS__INDEX_FLAGS) +#define GIT_SUBMODULE_STATUS__IN_FLAGS 0x000Fu +#define GIT_SUBMODULE_STATUS__INDEX_FLAGS 0x0070u +#define GIT_SUBMODULE_STATUS__WD_FLAGS 0x3F80u #define GIT_SUBMODULE_STATUS_IS_UNMODIFIED(S) \ (((S) & ~GIT_SUBMODULE_STATUS__IN_FLAGS) == 0) diff --git a/src/submodule.c b/src/submodule.c index e6ed7e33e..0beedeb42 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -71,15 +71,11 @@ static int load_submodule_config(git_repository *repo); static git_config_backend *open_gitmodules(git_repository *, bool, const git_oid *); static int lookup_head_remote(git_buf *url, git_repository *repo); static int submodule_get(git_submodule **, git_repository *, const char *, const char *); -static void submodule_release(git_submodule *sm, int decr); -static int submodule_load_from_index(git_repository *, const git_index_entry *); -static int submodule_load_from_head(git_repository*, const char*, const git_oid*); static int submodule_load_from_config(const git_config_entry *, void *); static int submodule_load_from_wd_lite(git_submodule *, const char *, void *); static int submodule_update_config(git_submodule *, const char *, const char *, bool, bool); -static void submodule_mode_mismatch(git_repository *, const char *, unsigned int); -static int submodule_index_status(unsigned int *status, git_submodule *sm); -static int submodule_wd_status(unsigned int *status, git_submodule *sm); +static void submodule_get_index_status(unsigned int *, git_submodule *); +static void submodule_get_wd_status(unsigned int *, git_submodule *, git_repository *, git_submodule_ignore_t); static int submodule_cmp(const void *a, const void *b) { @@ -161,7 +157,7 @@ int git_submodule_foreach( * us from issuing a callback twice for a submodule where the name * and path are not the same. */ - if (sm->refcount > 1) { + if (GIT_REFCOUNT_VAL(sm) > 1) { if (git_vector_bsearch(NULL, &seen, sm) != GIT_ENOTFOUND) continue; if ((error = git_vector_insert(&seen, sm)) < 0) @@ -193,9 +189,7 @@ void git_submodule_config_free(git_repository *repo) if (smcfg == NULL) return; - git_strmap_foreach_value(smcfg, sm, { - submodule_release(sm,1); - }); + git_strmap_foreach_value(smcfg, sm, { git_submodule_free(sm); }); git_strmap_free(smcfg); } @@ -336,7 +330,7 @@ int git_submodule_add_finalize(git_submodule *sm) assert(sm); - if ((error = git_repository_index__weakptr(&index, sm->owner)) < 0 || + if ((error = git_repository_index__weakptr(&index, sm->repo)) < 0 || (error = git_index_add_bypath(index, GIT_MODULES_FILE)) < 0) return error; @@ -346,7 +340,7 @@ int git_submodule_add_finalize(git_submodule *sm) int git_submodule_add_to_index(git_submodule *sm, int write_index) { int error; - git_repository *repo, *sm_repo = NULL; + git_repository *sm_repo = NULL; git_index *index; git_buf path = GIT_BUF_INIT; git_commit *head; @@ -355,14 +349,12 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index) assert(sm); - repo = sm->owner; - /* force reload of wd OID by git_submodule_open */ sm->flags = sm->flags & ~GIT_SUBMODULE_STATUS__WD_OID_VALID; - if ((error = git_repository_index__weakptr(&index, repo)) < 0 || + if ((error = git_repository_index__weakptr(&index, sm->repo)) < 0 || (error = git_buf_joinpath( - &path, git_repository_workdir(repo), sm->path)) < 0 || + &path, git_repository_workdir(sm->repo), sm->path)) < 0 || (error = git_submodule_open(&sm_repo, sm)) < 0) goto cleanup; @@ -422,7 +414,7 @@ int git_submodule_save(git_submodule *submodule) assert(submodule); - mods = open_gitmodules(submodule->owner, true, NULL); + mods = open_gitmodules(submodule->repo, true, NULL); if (!mods) { giterr_set(GITERR_SUBMODULE, "Adding submodules to a bare repository is not supported (for now)"); @@ -485,7 +477,7 @@ cleanup: git_repository *git_submodule_owner(git_submodule *submodule) { assert(submodule); - return submodule->owner; + return submodule->repo; } const char *git_submodule_name(git_submodule *submodule) @@ -542,20 +534,12 @@ const git_oid *git_submodule_wd_id(git_submodule *submodule) { assert(submodule); - /* if we know the submodule index timestamp and it has moved, then - * let's reload the working directory information for the submodule - */ - if (submodule->wd_head_path != NULL && - git_futils_filestamp_check( - &submodule->wd_stamp, submodule->wd_head_path)) - submodule->flags &= ~GIT_SUBMODULE_STATUS__WD_OID_VALID; - /* load unless we think we have a valid oid */ if (!(submodule->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID)) { git_repository *subrepo; /* calling submodule open grabs the HEAD OID if possible */ - if (!git_submodule_open(&subrepo, submodule)) + if (!git_submodule_open_bare(&subrepo, submodule)) git_repository_free(subrepo); else giterr_clear(); @@ -674,74 +658,68 @@ int git_submodule_sync(git_submodule *submodule) submodule, "url", submodule->url, true, true); } -int git_submodule_open( - git_repository **subrepo, - git_submodule *submodule) +static int git_submodule__open( + git_repository **subrepo, git_submodule *sm, bool bare) { int error; git_buf path = GIT_BUF_INIT; - git_repository *repo; - const char *workdir; + unsigned int flags = GIT_REPOSITORY_OPEN_NO_SEARCH; + const char *wd; - assert(submodule && subrepo); + assert(sm && subrepo); - repo = submodule->owner; - workdir = git_repository_workdir(repo); + if (git_repository__ensure_not_bare( + sm->repo, "open submodule repository") < 0) + return GIT_EBAREREPO; - if (!workdir) { - giterr_set(GITERR_REPOSITORY, - "Cannot open submodule repository in a bare repo"); - return GIT_ENOTFOUND; - } - - if ((submodule->flags & GIT_SUBMODULE_STATUS_IN_WD) == 0) { - giterr_set(GITERR_REPOSITORY, - "Cannot open submodule repository that is not checked out"); - return GIT_ENOTFOUND; - } + wd = git_repository_workdir(sm->repo); - if (git_buf_joinpath(&path, workdir, submodule->path) < 0) + if (git_buf_joinpath(&path, wd, sm->path) < 0 || + git_buf_joinpath(&path, path.ptr, DOT_GIT) < 0) return -1; - error = git_repository_open(subrepo, path.ptr); + sm->flags = sm->flags & + ~(GIT_SUBMODULE_STATUS_IN_WD | + GIT_SUBMODULE_STATUS__WD_OID_VALID | + GIT_SUBMODULE_STATUS__WD_SCANNED); - git_buf_free(&path); + if (bare) + flags |= GIT_REPOSITORY_OPEN_BARE; - /* if we have opened the submodule successfully, let's grab the HEAD OID */ - if (!error) { - git_buf buf = GIT_BUF_INIT; + error = git_repository_open_ext(subrepo, path.ptr, flags, wd); - /* For now, let's just the index timestamp... - * - * git_buf_joinpath(&buf, git_repository_path(*subrepo), GIT_HEAD_FILE); - * if (!git_path_exists(buf.ptr)) { - */ - git_index *index; - if (!git_repository_index__weakptr(&index, *subrepo)) - git_buf_sets(&buf, git_index_path(index)); - else - git_buf_free(&buf); - /* } */ + /* if we opened the submodule successfully, grab HEAD OID, etc. */ + if (!error) { + sm->flags |= GIT_SUBMODULE_STATUS_IN_WD | + GIT_SUBMODULE_STATUS__WD_SCANNED; - if (git_buf_len(&buf) > 0) { - git__free(submodule->wd_head_path); - submodule->wd_head_path = git_buf_detach(&buf); - } + if (!git_reference_name_to_id(&sm->wd_oid, *subrepo, GIT_HEAD_FILE)) + sm->flags |= GIT_SUBMODULE_STATUS__WD_OID_VALID; + else + giterr_clear(); + } else if (git_path_exists(path.ptr)) { + sm->flags |= GIT_SUBMODULE_STATUS__WD_SCANNED | + GIT_SUBMODULE_STATUS_IN_WD; + } else { + git_buf_rtruncate_at_char(&path, '/'); /* remove "/.git" */ - if (!git_reference_name_to_id( - &submodule->wd_oid, *subrepo, GIT_HEAD_FILE)) { + if (git_path_isdir(path.ptr)) + sm->flags |= GIT_SUBMODULE_STATUS__WD_SCANNED; + } - submodule->flags |= GIT_SUBMODULE_STATUS__WD_OID_VALID; + git_buf_free(&path); - if (submodule->wd_head_path) - git_futils_filestamp_check( - &submodule->wd_stamp, submodule->wd_head_path); - } + return error; +} - giterr_clear(); - } +int git_submodule_open_bare(git_repository **subrepo, git_submodule *sm) +{ + return git_submodule__open(subrepo, sm, true); +} - return error; +int git_submodule_open(git_repository **subrepo, git_submodule *sm) +{ + return git_submodule__open(subrepo, sm, false); } int git_submodule_reload_all(git_repository *repo) @@ -751,74 +729,99 @@ int git_submodule_reload_all(git_repository *repo) return load_submodule_config(repo); } -int git_submodule_reload(git_submodule *submodule) +static void submodule_update_from_index_entry( + git_submodule *sm, const git_index_entry *ie) { - git_repository *repo; - git_index *index; - int error; - size_t pos; - git_tree *head; - git_config_backend *mods; + bool already_found = (sm->flags & GIT_SUBMODULE_STATUS_IN_INDEX) != 0; - assert(submodule); + if (!S_ISGITLINK(ie->mode)) { + if (!already_found) + sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE; + } else { + if (already_found) + sm->flags |= GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES; + else + git_oid_cpy(&sm->index_oid, &ie->oid); - /* refresh index data */ + sm->flags |= GIT_SUBMODULE_STATUS_IN_INDEX | + GIT_SUBMODULE_STATUS__INDEX_OID_VALID; + } +} + +static int submodule_update_index(git_submodule *sm) +{ + git_index *index; + const git_index_entry *ie; - repo = submodule->owner; - if (git_repository_index__weakptr(&index, repo) < 0) + if (git_repository_index__weakptr(&index, sm->repo) < 0) return -1; - submodule->flags = submodule->flags & + sm->flags = sm->flags & ~(GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS__INDEX_OID_VALID); - if (!git_index_find(&pos, index, submodule->path)) { - const git_index_entry *entry = git_index_get_byindex(index, pos); + if (!(ie = git_index_get_bypath(index, sm->path, 0))) + return 0; - if (S_ISGITLINK(entry->mode)) { - if ((error = submodule_load_from_index(repo, entry)) < 0) - return error; - } else { - submodule_mode_mismatch( - repo, entry->path, GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE); - } + submodule_update_from_index_entry(sm, ie); + + return 0; +} + +static void submodule_update_from_head_data( + git_submodule *sm, mode_t mode, const git_oid *id) +{ + if (!S_ISGITLINK(mode)) + sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE; + else { + git_oid_cpy(&sm->head_oid, id); + + sm->flags |= GIT_SUBMODULE_STATUS_IN_HEAD | + GIT_SUBMODULE_STATUS__HEAD_OID_VALID; } +} - /* refresh HEAD tree data */ +static int submodule_update_head(git_submodule *submodule) +{ + git_tree *head = NULL; + git_tree_entry *te; - if (!(error = git_repository_head_tree(&head, repo))) { - git_tree_entry *te; + submodule->flags = submodule->flags & + ~(GIT_SUBMODULE_STATUS_IN_HEAD | + GIT_SUBMODULE_STATUS__HEAD_OID_VALID); - submodule->flags = submodule->flags & - ~(GIT_SUBMODULE_STATUS_IN_HEAD | - GIT_SUBMODULE_STATUS__HEAD_OID_VALID); + /* if we can't look up file in current head, then done */ + if (git_repository_head_tree(&head, submodule->repo) < 0 || + git_tree_entry_bypath(&te, head, submodule->path) < 0) + giterr_clear(); + else + submodule_update_from_head_data(submodule, te->attr, &te->oid); - if (!(error = git_tree_entry_bypath(&te, head, submodule->path))) { + git_tree_free(head); + return 0; +} - if (S_ISGITLINK(te->attr)) { - error = submodule_load_from_head(repo, submodule->path, &te->oid); - } else { - submodule_mode_mismatch( - repo, submodule->path, - GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE); - } +int git_submodule_reload(git_submodule *submodule) +{ + int error = 0; + git_config_backend *mods; - git_tree_entry_free(te); - } - else if (error == GIT_ENOTFOUND) { - giterr_clear(); - error = 0; - } + assert(submodule); - git_tree_free(head); - } + /* refresh index data */ - if (error < 0) - return error; + if (submodule_update_index(submodule) < 0) + return -1; + + /* refresh HEAD tree data */ + + if (submodule_update_head(submodule) < 0) + return -1; /* refresh config data */ - if ((mods = open_gitmodules(repo, false, NULL)) != NULL) { + mods = open_gitmodules(submodule->repo, false, NULL); + if (mods != NULL) { git_buf path = GIT_BUF_INIT; git_buf_sets(&path, "submodule\\."); @@ -829,7 +832,7 @@ int git_submodule_reload(git_submodule *submodule) error = -1; else error = git_config_file_foreach_match( - mods, path.ptr, submodule_load_from_config, repo); + mods, path.ptr, submodule_load_from_config, submodule->repo); git_buf_free(&path); git_config_file_free(mods); @@ -848,38 +851,91 @@ int git_submodule_reload(git_submodule *submodule) return error; } -int git_submodule_status( - unsigned int *status, - git_submodule *submodule) +static void submodule_copy_oid_maybe( + git_oid *tgt, const git_oid *src, bool valid) { - int error = 0; - unsigned int status_val; + if (tgt) { + if (valid) + memcpy(tgt, src, sizeof(*tgt)); + else + memset(tgt, 0, sizeof(*tgt)); + } +} - assert(status && submodule); +int git_submodule__status( + unsigned int *out_status, + git_oid *out_head_id, + git_oid *out_index_id, + git_oid *out_wd_id, + git_submodule *sm, + git_submodule_ignore_t ign) +{ + unsigned int status; + git_repository *smrepo = NULL; - status_val = GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(submodule->flags); + if (ign == GIT_SUBMODULE_IGNORE_DEFAULT) + ign = sm->ignore; - if (submodule->ignore != GIT_SUBMODULE_IGNORE_ALL) { - if (!(error = submodule_index_status(&status_val, submodule))) - error = submodule_wd_status(&status_val, submodule); + /* only return location info if ignore == all */ + if (ign == GIT_SUBMODULE_IGNORE_ALL) { + *out_status = (sm->flags & GIT_SUBMODULE_STATUS__IN_FLAGS); + return 0; } - *status = status_val; + /* refresh the index OID */ + if (submodule_update_index(sm) < 0) + return -1; + + /* refresh the HEAD OID */ + if (submodule_update_head(sm) < 0) + return -1; - return error; + /* for ignore == dirty, don't scan the working directory */ + if (ign == GIT_SUBMODULE_IGNORE_DIRTY) { + /* git_submodule_open_bare will load WD OID data */ + if (git_submodule_open_bare(&smrepo, sm) < 0) + giterr_clear(); + else + git_repository_free(smrepo); + smrepo = NULL; + } else if (git_submodule_open(&smrepo, sm) < 0) { + giterr_clear(); + smrepo = NULL; + } + + status = GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(sm->flags); + + submodule_get_index_status(&status, sm); + submodule_get_wd_status(&status, sm, smrepo, ign); + + git_repository_free(smrepo); + + *out_status = status; + + submodule_copy_oid_maybe(out_head_id, &sm->head_oid, + (sm->flags & GIT_SUBMODULE_STATUS__HEAD_OID_VALID) != 0); + submodule_copy_oid_maybe(out_index_id, &sm->index_oid, + (sm->flags & GIT_SUBMODULE_STATUS__INDEX_OID_VALID) != 0); + submodule_copy_oid_maybe(out_wd_id, &sm->wd_oid, + (sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) != 0); + + return 0; } -int git_submodule_location( - unsigned int *location_status, - git_submodule *submodule) +int git_submodule_status(unsigned int *status, git_submodule *sm) { - assert(location_status && submodule); + assert(status && sm); - *location_status = submodule->flags & - (GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX | - GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_IN_WD); + return git_submodule__status( + status, NULL, NULL, NULL, sm, GIT_SUBMODULE_IGNORE_DEFAULT); +} - return 0; +int git_submodule_location(unsigned int *location, git_submodule *sm) +{ + assert(location && sm); + + return git_submodule__status( + location, NULL, NULL, NULL, sm, GIT_SUBMODULE_IGNORE_ALL); } @@ -889,54 +945,47 @@ int git_submodule_location( static git_submodule *submodule_alloc(git_repository *repo, const char *name) { + size_t namelen; git_submodule *sm; - if (!name || !strlen(name)) { + if (!name || !(namelen = strlen(name))) { giterr_set(GITERR_SUBMODULE, "Invalid submodule name"); return NULL; } - sm = git__calloc(1, sizeof(git_submodule)); + sm = git__calloc(1, sizeof(git_submodule) + namelen + 1); if (sm == NULL) - goto fail; - - sm->path = sm->name = git__strdup(name); - if (!sm->name) - goto fail; + return NULL; - sm->owner = repo; - sm->refcount = 1; + sm->name = sm->path = git__strdup(name); + if (!sm->name) { + git__free(sm); + return NULL; + } + GIT_REFCOUNT_INC(sm); + sm->repo = repo; return sm; - -fail: - submodule_release(sm, 0); - return NULL; } -static void submodule_release(git_submodule *sm, int decr) +static void submodule_release(git_submodule *sm) { if (!sm) return; - sm->refcount -= decr; - - if (sm->refcount == 0) { - if (sm->name != sm->path) { - git__free(sm->path); - sm->path = NULL; - } - - git__free(sm->name); - sm->name = NULL; - - git__free(sm->url); - sm->url = NULL; - - sm->owner = NULL; + if (sm->path != sm->name) + git__free(sm->path); + git__free(sm->name); + git__free(sm->url); + git__memzero(sm, sizeof(*sm)); + git__free(sm); +} - git__free(sm); - } +void git_submodule_free(git_submodule *sm) +{ + if (!sm) + return; + GIT_REFCOUNT_DEC(sm, submodule_release); } static int submodule_get( @@ -966,10 +1015,10 @@ static int submodule_get( pos = kh_put(str, smcfg, sm->name, &error); if (error < 0) { - submodule_release(sm, 1); + git_submodule_free(sm); sm = NULL; } else if (error == 0) { - submodule_release(sm, 1); + git_submodule_free(sm); sm = git_strmap_value_at(smcfg, pos); } else { git_strmap_set_value_at(smcfg, pos, sm); @@ -983,43 +1032,6 @@ static int submodule_get( return (sm != NULL) ? 0 : -1; } -static int submodule_load_from_index( - git_repository *repo, const git_index_entry *entry) -{ - git_submodule *sm; - - if (submodule_get(&sm, repo, entry->path, NULL) < 0) - return -1; - - if (sm->flags & GIT_SUBMODULE_STATUS_IN_INDEX) { - sm->flags |= GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES; - return 0; - } - - sm->flags |= GIT_SUBMODULE_STATUS_IN_INDEX; - - git_oid_cpy(&sm->index_oid, &entry->oid); - sm->flags |= GIT_SUBMODULE_STATUS__INDEX_OID_VALID; - - return 0; -} - -static int submodule_load_from_head( - git_repository *repo, const char *path, const git_oid *oid) -{ - git_submodule *sm; - - if (submodule_get(&sm, repo, path, NULL) < 0) - return -1; - - sm->flags |= GIT_SUBMODULE_STATUS_IN_HEAD; - - git_oid_cpy(&sm->head_oid, oid); - sm->flags |= GIT_SUBMODULE_STATUS__HEAD_OID_VALID; - - return 0; -} - static int submodule_config_error(const char *property, const char *value) { giterr_set(GITERR_INVALID, @@ -1079,11 +1091,11 @@ static int submodule_load_from_config( git_strmap_insert2(smcfg, alternate, sm, old_sm, error); if (error >= 0) - sm->refcount++; /* inserted under a new key */ + GIT_REFCOUNT_INC(sm); /* inserted under a new key */ /* if we replaced an old module under this key, release the old one */ if (old_sm && ((git_submodule *)old_sm) != sm) { - submodule_release(old_sm, 1); + git_submodule_free(old_sm); /* TODO: log warning about multiple submodules with same path */ } } @@ -1133,13 +1145,15 @@ static int submodule_load_from_config( static int submodule_load_from_wd_lite( git_submodule *sm, const char *name, void *payload) { - git_repository *repo = git_submodule_owner(sm); git_buf path = GIT_BUF_INIT; GIT_UNUSED(name); GIT_UNUSED(payload); - if (git_buf_joinpath(&path, git_repository_workdir(repo), sm->path) < 0) + if (git_repository_is_bare(sm->repo)) + return 0; + + if (git_buf_joinpath(&path, git_repository_workdir(sm->repo), sm->path) < 0) return -1; if (git_path_isdir(path.ptr)) @@ -1153,18 +1167,6 @@ static int submodule_load_from_wd_lite( return 0; } -static void submodule_mode_mismatch( - git_repository *repo, const char *path, unsigned int flag) -{ - khiter_t pos = git_strmap_lookup_index(repo->submodules, path); - - if (git_strmap_valid_index(repo->submodules, pos)) { - git_submodule *sm = git_strmap_value_at(repo->submodules, pos); - - sm->flags |= flag; - } -} - static int load_submodule_config_from_index( git_repository *repo, git_oid *gitmodules_oid) { @@ -1178,18 +1180,21 @@ static int load_submodule_config_from_index( return error; while (!(error = git_iterator_advance(&entry, i))) { + khiter_t pos = git_strmap_lookup_index(repo->submodules, entry->path); + git_submodule *sm; - if (S_ISGITLINK(entry->mode)) { - error = submodule_load_from_index(repo, entry); - if (error < 0) - break; - } else { - submodule_mode_mismatch( - repo, entry->path, GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE); + if (git_strmap_valid_index(repo->submodules, pos)) { + sm = git_strmap_value_at(repo->submodules, pos); - if (strcmp(entry->path, GIT_MODULES_FILE) == 0) - git_oid_cpy(gitmodules_oid, &entry->oid); - } + 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(&sm, repo, entry->path, NULL)) + submodule_update_from_index_entry(sm, entry); + } else if (strcmp(entry->path, GIT_MODULES_FILE) == 0) + git_oid_cpy(gitmodules_oid, &entry->oid); } if (error == GIT_ITEROVER) @@ -1220,18 +1225,24 @@ static int load_submodule_config_from_head( } while (!(error = git_iterator_advance(&entry, i))) { + khiter_t pos = git_strmap_lookup_index(repo->submodules, entry->path); + git_submodule *sm; - if (S_ISGITLINK(entry->mode)) { - error = submodule_load_from_head(repo, entry->path, &entry->oid); - if (error < 0) - break; - } else { - submodule_mode_mismatch( - repo, entry->path, GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE); + if (git_strmap_valid_index(repo->submodules, pos)) { + sm = git_strmap_value_at(repo->submodules, pos); - if (strcmp(entry->path, GIT_MODULES_FILE) == 0 && - git_oid_iszero(gitmodules_oid)) - git_oid_cpy(gitmodules_oid, &entry->oid); + if (S_ISGITLINK(entry->mode)) + submodule_update_from_head_data( + sm, entry->mode, &entry->oid); + else + sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE; + } else if (S_ISGITLINK(entry->mode)) { + if (!submodule_get(&sm, repo, entry->path, NULL)) + submodule_update_from_head_data( + sm, entry->mode, &entry->oid); + } else if (strcmp(entry->path, GIT_MODULES_FILE) == 0 && + git_oid_iszero(gitmodules_oid)) { + git_oid_cpy(gitmodules_oid, &entry->oid); } } @@ -1416,7 +1427,7 @@ static int submodule_update_config( assert(submodule); - error = git_repository_config__weakptr(&config, submodule->owner); + error = git_repository_config__weakptr(&config, submodule->repo); if (error < 0) return error; @@ -1444,11 +1455,13 @@ cleanup: return error; } -static int submodule_index_status(unsigned int *status, git_submodule *sm) +static void submodule_get_index_status(unsigned int *status, git_submodule *sm) { const git_oid *head_oid = git_submodule_head_id(sm); const git_oid *index_oid = git_submodule_index_id(sm); + *status = *status & ~GIT_SUBMODULE_STATUS__INDEX_FLAGS; + if (!head_oid) { if (index_oid) *status |= GIT_SUBMODULE_STATUS_INDEX_ADDED; @@ -1457,27 +1470,22 @@ static int submodule_index_status(unsigned int *status, git_submodule *sm) *status |= GIT_SUBMODULE_STATUS_INDEX_DELETED; else if (!git_oid_equal(head_oid, index_oid)) *status |= GIT_SUBMODULE_STATUS_INDEX_MODIFIED; - - return 0; } -static int submodule_wd_status(unsigned int *status, git_submodule *sm) +static void submodule_get_wd_status( + unsigned int *status, + git_submodule *sm, + git_repository *sm_repo, + git_submodule_ignore_t ign) { - int error = 0; - const git_oid *wd_oid, *index_oid; - git_repository *sm_repo = NULL; - - /* open repo now if we need it (so wd_id() call won't reopen) */ - if ((sm->ignore == GIT_SUBMODULE_IGNORE_NONE || - sm->ignore == GIT_SUBMODULE_IGNORE_UNTRACKED) && - (sm->flags & GIT_SUBMODULE_STATUS_IN_WD) != 0) - { - if ((error = git_submodule_open(&sm_repo, sm)) < 0) - return error; - } + const git_oid *index_oid = git_submodule_index_id(sm); + const git_oid *wd_oid = + (sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) ? &sm->wd_oid : NULL; + git_tree *sm_head = NULL; + git_diff_options opt = GIT_DIFF_OPTIONS_INIT; + git_diff_list *diff; - index_oid = git_submodule_index_id(sm); - wd_oid = git_submodule_wd_id(sm); + *status = *status & ~GIT_SUBMODULE_STATUS__WD_FLAGS; if (!index_oid) { if (wd_oid) @@ -1493,59 +1501,49 @@ static int submodule_wd_status(unsigned int *status, git_submodule *sm) else if (!git_oid_equal(index_oid, wd_oid)) *status |= GIT_SUBMODULE_STATUS_WD_MODIFIED; - if (sm_repo != NULL) { - git_tree *sm_head; - git_diff_options opt = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff; - - /* the diffs below could be optimized with an early termination - * option to the git_diff functions, but for now this is sufficient - * (and certainly no worse that what core git does). - */ - - /* perform head-to-index diff on submodule */ - - if ((error = git_repository_head_tree(&sm_head, sm_repo)) < 0) - return error; + /* if we have no repo, then we're done */ + if (!sm_repo) + return; - if (sm->ignore == GIT_SUBMODULE_IGNORE_NONE) - opt.flags |= GIT_DIFF_INCLUDE_UNTRACKED; + /* the diffs below could be optimized with an early termination + * option to the git_diff functions, but for now this is sufficient + * (and certainly no worse that what core git does). + */ - error = git_diff_tree_to_index(&diff, sm_repo, sm_head, NULL, &opt); + if (ign == GIT_SUBMODULE_IGNORE_NONE) + opt.flags |= GIT_DIFF_INCLUDE_UNTRACKED; - if (!error) { + /* if we don't have an orphaned head, check diff with index */ + if (git_repository_head_tree(&sm_head, sm_repo) < 0) + giterr_clear(); + else { + /* perform head to index diff on submodule */ + if (git_diff_tree_to_index(&diff, sm_repo, sm_head, NULL, &opt) < 0) + giterr_clear(); + else { if (git_diff_num_deltas(diff) > 0) *status |= GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED; - git_diff_list_free(diff); diff = NULL; } git_tree_free(sm_head); + } - if (error < 0) - return error; - - /* perform index-to-workdir diff on submodule */ - - error = git_diff_index_to_workdir(&diff, sm_repo, NULL, &opt); - - if (!error) { - size_t untracked = - git_diff_num_deltas_of_type(diff, GIT_DELTA_UNTRACKED); - - if (untracked > 0) - *status |= GIT_SUBMODULE_STATUS_WD_UNTRACKED; + /* perform index-to-workdir diff on submodule */ + if (git_diff_index_to_workdir(&diff, sm_repo, NULL, &opt) < 0) + giterr_clear(); + else { + size_t untracked = + git_diff_num_deltas_of_type(diff, GIT_DELTA_UNTRACKED); - if (git_diff_num_deltas(diff) != untracked) - *status |= GIT_SUBMODULE_STATUS_WD_WD_MODIFIED; + if (untracked > 0) + *status |= GIT_SUBMODULE_STATUS_WD_UNTRACKED; - git_diff_list_free(diff); - diff = NULL; - } + if (git_diff_num_deltas(diff) != untracked) + *status |= GIT_SUBMODULE_STATUS_WD_WD_MODIFIED; - git_repository_free(sm_repo); + git_diff_list_free(diff); + diff = NULL; } - - return error; } diff --git a/src/submodule.h b/src/submodule.h index 88d4f97c7..8db2fff29 100644 --- a/src/submodule.h +++ b/src/submodule.h @@ -48,6 +48,10 @@ * an entry for every submodule found in the HEAD and index, and for every * submodule described in .gitmodules. The fields are as follows: * + * - `rc` tracks the refcount of how many hash table entries in the + * git_submodule_cache there are for this submodule. It only comes into + * play if the name and path of the submodule differ. + * * - `name` is the name of the submodule from .gitmodules. * - `path` is the path to the submodule from the repo root. It is almost * always the same as `name`. @@ -58,18 +62,12 @@ * - `ignore_default` is the ignore value from the config * - `fetch_recurse` is 0 or 1 - see gitmodules(5) fetchRecurseSubmodules. * - * - `owner` is the git_repository containing this submodule + * - `repo` is the parent repository that contains this submodule. * - `flags` after for internal use, tracking where this submodule has been * found (head, index, config, workdir) and known status info, etc. * - `head_oid` is the SHA1 for the submodule path in the repo HEAD. * - `index_oid` is the SHA1 for the submodule recorded in the index. * - `wd_oid` is the SHA1 for the HEAD of the checked out submodule. - * - `wd_index_path` is the path to the index of the checked out submodule - * - `wd_last_index` is a timestamp of that submodule index so we can - * quickly check if the `wd_oid` should be rechecked - * - `refcount` tracks how many hash table entries in the - * git_submodule_cache there are for this submodule. It only comes into - * play if the name and path of the submodule differ. * * If the submodule has been added to .gitmodules but not yet git added, * then the `index_oid` will be zero but still marked valid. If the @@ -77,9 +75,11 @@ * then the `index_oid` will be set, but the `url` will be NULL. */ struct git_submodule { + git_refcount rc; + /* information from config */ char *name; - char *path; /* important: may point to same string data as "name" */ + char *path; /* important: may just point to "name" string */ char *url; git_submodule_update_t update; git_submodule_update_t update_default; @@ -88,14 +88,11 @@ struct git_submodule { int fetch_recurse; /* internal information */ - git_repository *owner; + git_repository *repo; uint32_t flags; git_oid head_oid; git_oid index_oid; git_oid wd_oid; - char *wd_head_path; - git_futils_filestamp wd_stamp; - int refcount; }; /* Additional flags on top of public GIT_SUBMODULE_STATUS values */ @@ -113,4 +110,21 @@ enum { #define GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(S) \ ((S) & ~(0xFFFFFFFFu << 20)) +/* Internal status fn returns status and optionally the various OIDs */ +extern int git_submodule__status( + unsigned int *out_status, + git_oid *out_head_id, + git_oid *out_index_id, + git_oid *out_wd_id, + git_submodule *sm, + git_submodule_ignore_t ign); + +/* Open submodule repository as bare repo for quick HEAD check, etc. */ +extern int git_submodule_open_bare( + git_repository **repo, + git_submodule *submodule); + +/* Release reference to submodule object - not currently for external use */ +extern void git_submodule_free(git_submodule *sm); + #endif -- cgit v1.2.1 From 2e3e273e33894bc1089cfc09d89bd2cb144b108d Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sat, 29 Jun 2013 13:20:45 -0700 Subject: Update diff to new internal submodule status API Submodules now expose an internal status API that allows diff to get back the OID values from the submodule very easily and also to avoiding caching issues and to override the ignore setting for the submodule. --- src/diff.c | 14 ++++++++------ tests-clar/diff/submodules.c | 7 ------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/diff.c b/src/diff.c index cc7be451f..2b018188e 100644 --- a/src/diff.c +++ b/src/diff.c @@ -13,6 +13,7 @@ #include "pathspec.h" #include "index.h" #include "odb.h" +#include "submodule.h" #define DIFF_FLAG_IS_SET(DIFF,FLAG) (((DIFF)->opts.flags & (FLAG)) != 0) #define DIFF_FLAG_ISNT_SET(DIFF,FLAG) (((DIFF)->opts.flags & (FLAG)) == 0) @@ -595,7 +596,6 @@ static int maybe_modified_submodule( int error = 0; git_submodule *sub; unsigned int sm_status = 0; - const git_oid *sm_oid; *status = GIT_DELTA_UNMODIFIED; @@ -603,7 +603,9 @@ static int maybe_modified_submodule( !(error = git_submodule_lookup( &sub, diff->repo, info->nitem->path)) && git_submodule_ignore(sub) != GIT_SUBMODULE_IGNORE_ALL && - !(error = git_submodule_status(&sm_status, sub))) + !(error = git_submodule__status( + &sm_status, NULL, NULL, found_oid, sub, + GIT_SUBMODULE_IGNORE_DEFAULT))) { /* check IS_WD_UNMODIFIED because this case is only used * when the new side of the diff is the working directory @@ -611,10 +613,10 @@ static int maybe_modified_submodule( if (!GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED(sm_status)) *status = GIT_DELTA_MODIFIED; - /* grab OID while we are here */ - if (git_oid_iszero(&info->nitem->oid) && - (sm_oid = git_submodule_wd_id(sub)) != NULL) - git_oid_cpy(found_oid, sm_oid); + /* now that we have a HEAD OID, check if HEAD moved */ + if ((sm_status & GIT_SUBMODULE_STATUS_IN_WD) != 0 && + !git_oid_equal(&info->oitem->oid, found_oid)) + *status = GIT_DELTA_MODIFIED; } /* GIT_EEXISTS means a dir with .git in it was found - ignore it */ diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index c94fd57c6..4a40affb2 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -333,8 +333,6 @@ void test_diff_submodules__invalid_cache(void) check_diff_patches(diff, expected_unchanged); git_diff_list_free(diff); - sleep(2); - /* commit changed index of submodule */ { git_object *parent; @@ -357,11 +355,6 @@ void test_diff_submodules__invalid_cache(void) git_signature_free(sig); } - /* THIS RELOAD SHOULD NOT BE REQUIRED - cl_git_pass(git_submodule_reload_all(g_repo)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath)); - */ - git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); -- cgit v1.2.1 From f9775a37aa4ed042839a6b2f9d8e0dfbd73a2f09 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sat, 29 Jun 2013 23:22:31 -0700 Subject: Add ignore_submodules to diff options This adds correct support for an equivalent to --ignore-submodules in diff, where an actual ignore value can be passed to diff to override the per submodule settings in the configuration. This required tweaking the constants for ignore values so that zero would not be used and could represent an unset option to the diff. This was an opportunity to move the submodule values into include/git2/types.h and to rename the poorly named DEFAULT values for ignore and update constants to RESET instead. Now the GIT_DIFF_IGNORE_SUBMODULES flag is exactly the same as setting the ignore_submodules option to GIT_SUBMODULE_IGNORE_ALL (which is actually a minor change from the old behavior in that submodules will now be treated as UNMODIFIED deltas instead of being left out totally - if you set GIT_DIFF_INCLUDE_UNMODIFIED). This includes tests for the various new settings. --- include/git2/diff.h | 5 +- include/git2/submodule.h | 53 ++++---------------- include/git2/types.h | 34 +++++++++++++ src/diff.c | 77 ++++++++++++++++------------- src/submodule.c | 112 ++++++++++++++++++++++++++++-------------- src/submodule.h | 8 +++ tests-clar/clar_libgit2.h | 3 ++ tests-clar/diff/submodules.c | 65 ++++++++++++++++++++++-- tests-clar/submodule/modify.c | 10 ++-- 9 files changed, 245 insertions(+), 122 deletions(-) diff --git a/include/git2/diff.h b/include/git2/diff.h index 121c9df5c..71a8b72bf 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -78,7 +78,7 @@ typedef enum { GIT_DIFF_IGNORE_WHITESPACE_CHANGE = (1 << 3), /** Ignore whitespace at end of line */ GIT_DIFF_IGNORE_WHITESPACE_EOL = (1 << 4), - /** Exclude submodules from the diff completely */ + /** Treat all submodules as unmodified */ GIT_DIFF_IGNORE_SUBMODULES = (1 << 5), /** Use the "patience diff" algorithm (currently unimplemented) */ GIT_DIFF_PATIENCE = (1 << 6), @@ -314,6 +314,8 @@ typedef int (*git_diff_notify_cb)( * - `notify_cb` is an optional callback function, notifying the consumer of * which files are being examined as the diff is generated * - `notify_payload` is the payload data to pass to the `notify_cb` function + * - `ignore_submodules` overrides the submodule ignore setting for all + * submodules in the diff. */ typedef struct { unsigned int version; /**< version for the struct */ @@ -326,6 +328,7 @@ typedef struct { git_off_t max_size; /**< defaults to 512MB */ git_diff_notify_cb notify_cb; void *notify_payload; + git_submodule_ignore_t ignore_submodules; /** << submodule ignore rule */ } git_diff_options; #define GIT_DIFF_OPTIONS_VERSION 1 diff --git a/include/git2/submodule.h b/include/git2/submodule.h index 3267bcd0f..ba7a558d0 100644 --- a/include/git2/submodule.h +++ b/include/git2/submodule.h @@ -14,51 +14,18 @@ /** * @file git2/submodule.h * @brief Git submodule management utilities - * @defgroup git_submodule Git submodule management routines - * @ingroup Git - * @{ - */ -GIT_BEGIN_DECL - -/** - * Opaque structure representing a submodule. * * Submodule support in libgit2 builds a list of known submodules and keeps * it in the repository. The list is built from the .gitmodules file, the * .git/config file, the index, and the HEAD tree. Items in the working * directory that look like submodules (i.e. a git repo) but are not * mentioned in those places won't be tracked. - */ -typedef struct git_submodule git_submodule; - -/** - * Values that could be specified for the update rule of a submodule. * - * Use the DEFAULT value if you have altered the update value via - * `git_submodule_set_update()` and wish to reset to the original default. - */ -typedef enum { - GIT_SUBMODULE_UPDATE_DEFAULT = -1, - GIT_SUBMODULE_UPDATE_CHECKOUT = 0, - GIT_SUBMODULE_UPDATE_REBASE = 1, - GIT_SUBMODULE_UPDATE_MERGE = 2, - GIT_SUBMODULE_UPDATE_NONE = 3 -} git_submodule_update_t; - -/** - * Values that could be specified for how closely to examine the - * working directory when getting submodule status. - * - * Use the DEFUALT value if you have altered the ignore value via - * `git_submodule_set_ignore()` and wish to reset to the original value. + * @defgroup git_submodule Git submodule management routines + * @ingroup Git + * @{ */ -typedef enum { - GIT_SUBMODULE_IGNORE_DEFAULT = -1, /* reset to default */ - GIT_SUBMODULE_IGNORE_NONE = 0, /* any change or untracked == dirty */ - GIT_SUBMODULE_IGNORE_UNTRACKED = 1, /* dirty if tracked files change */ - GIT_SUBMODULE_IGNORE_DIRTY = 2, /* only dirty if HEAD moved */ - GIT_SUBMODULE_IGNORE_ALL = 3 /* never dirty */ -} git_submodule_ignore_t; +GIT_BEGIN_DECL /** * Return codes for submodule status. @@ -377,9 +344,9 @@ GIT_EXTERN(git_submodule_ignore_t) git_submodule_ignore( * submodule is in memory. You should call `git_submodule_save()` if you * want to persist the new ignore role. * - * Calling this again with GIT_SUBMODULE_IGNORE_DEFAULT or calling - * `git_submodule_reload()` will revert the rule to the value that was in the - * original config. + * Calling this again with GIT_SUBMODULE_IGNORE_RESET or calling + * `git_submodule_reload()` will revert the rule to the value that was in + * the original config. * * @return old value for ignore */ @@ -399,9 +366,9 @@ GIT_EXTERN(git_submodule_update_t) git_submodule_update( * This sets the update rule in memory for the submodule. You should call * `git_submodule_save()` if you want to persist the new update rule. * - * Calling this again with GIT_SUBMODULE_UPDATE_DEFAULT or calling - * `git_submodule_reload()` will revert the rule to the value that was in the - * original config. + * Calling this again with GIT_SUBMODULE_UPDATE_RESET or calling + * `git_submodule_reload()` will revert the rule to the value that was in + * the original config. * * @return old value for update */ diff --git a/include/git2/types.h b/include/git2/types.h index dc344075c..1da0d3ed2 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -229,6 +229,40 @@ typedef struct git_transfer_progress { */ typedef int (*git_transfer_progress_callback)(const git_transfer_progress *stats, void *payload); +/** + * Opaque structure representing a submodule. + */ +typedef struct git_submodule git_submodule; + +/** + * Values that could be specified for the update rule of a submodule. + * + * Use the RESET value if you have altered the in-memory update value via + * `git_submodule_set_update()` and wish to reset to the original default. + */ +typedef enum { + GIT_SUBMODULE_UPDATE_RESET = -1, + GIT_SUBMODULE_UPDATE_CHECKOUT = 1, + GIT_SUBMODULE_UPDATE_REBASE = 2, + GIT_SUBMODULE_UPDATE_MERGE = 3, + GIT_SUBMODULE_UPDATE_NONE = 4 +} git_submodule_update_t; + +/** + * Values that could be specified for how closely to examine the + * working directory when getting submodule status. + * + * Use the RESET value if you have altered the in-memory ignore value via + * `git_submodule_set_ignore()` and wish to reset to the original value. + */ +typedef enum { + GIT_SUBMODULE_IGNORE_RESET = -1, /* reset to on-disk value */ + GIT_SUBMODULE_IGNORE_NONE = 1, /* any change or untracked == dirty */ + GIT_SUBMODULE_IGNORE_UNTRACKED = 2, /* dirty if tracked files change */ + GIT_SUBMODULE_IGNORE_DIRTY = 3, /* only dirty if HEAD moved */ + GIT_SUBMODULE_IGNORE_ALL = 4 /* never dirty */ +} git_submodule_ignore_t; + /** @} */ GIT_END_DECL diff --git a/src/diff.c b/src/diff.c index 2b018188e..5fa635f05 100644 --- a/src/diff.c +++ b/src/diff.c @@ -78,10 +78,6 @@ static int diff_delta__from_one( DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNTRACKED)) return 0; - if (entry->mode == GIT_FILEMODE_COMMIT && - DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_SUBMODULES)) - return 0; - if (!git_pathspec__match( &diff->pathspec, entry->path, DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH), @@ -141,11 +137,6 @@ static int diff_delta__from_two( DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNMODIFIED)) return 0; - if (old_entry->mode == GIT_FILEMODE_COMMIT && - new_entry->mode == GIT_FILEMODE_COMMIT && - DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_SUBMODULES)) - return 0; - if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) { uint32_t temp_mode = old_mode; const git_index_entry *temp_entry = old_entry; @@ -431,8 +422,18 @@ static int diff_list_apply_options( if (!opts) { diff->opts.context_lines = config_int(cfg, "diff.context", 3); - if (config_bool(cfg, "diff.ignoreSubmodules", 0)) - diff->opts.flags |= GIT_DIFF_IGNORE_SUBMODULES; + /* add other defaults here */ + } + + /* if ignore_submodules not explicitly set, check diff config */ + if (diff->opts.ignore_submodules <= 0) { + const char *str; + + if (git_config_get_string(&str , cfg, "diff.ignoreSubmodules") < 0) + giterr_clear(); + else if (str != NULL && + git_submodule_parse_ignore(&diff->opts.ignore_submodules, str) < 0) + giterr_clear(); } /* if either prefix is not set, figure out appropriate value */ @@ -596,36 +597,44 @@ static int maybe_modified_submodule( int error = 0; git_submodule *sub; unsigned int sm_status = 0; + git_submodule_ignore_t ign = diff->opts.ignore_submodules; *status = GIT_DELTA_UNMODIFIED; - if (!DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_SUBMODULES) && - !(error = git_submodule_lookup( - &sub, diff->repo, info->nitem->path)) && - git_submodule_ignore(sub) != GIT_SUBMODULE_IGNORE_ALL && - !(error = git_submodule__status( - &sm_status, NULL, NULL, found_oid, sub, - GIT_SUBMODULE_IGNORE_DEFAULT))) - { - /* check IS_WD_UNMODIFIED because this case is only used - * when the new side of the diff is the working directory - */ - if (!GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED(sm_status)) - *status = GIT_DELTA_MODIFIED; + if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_SUBMODULES) || + ign == GIT_SUBMODULE_IGNORE_ALL) + return 0; - /* now that we have a HEAD OID, check if HEAD moved */ - if ((sm_status & GIT_SUBMODULE_STATUS_IN_WD) != 0 && - !git_oid_equal(&info->oitem->oid, found_oid)) - *status = GIT_DELTA_MODIFIED; - } + if ((error = git_submodule_lookup( + &sub, diff->repo, info->nitem->path)) < 0) { - /* GIT_EEXISTS means a dir with .git in it was found - ignore it */ - if (error == GIT_EEXISTS) { - giterr_clear(); - error = 0; + /* GIT_EEXISTS means dir with .git in it was found - ignore it */ + if (error == GIT_EEXISTS) { + giterr_clear(); + error = 0; + } + return error; } - return error; + if (ign <= 0 && git_submodule_ignore(sub) == GIT_SUBMODULE_IGNORE_ALL) + return 0; + + if ((error = git_submodule__status( + &sm_status, NULL, NULL, found_oid, sub, ign)) < 0) + return error; + + /* check IS_WD_UNMODIFIED because this case is only used + * when the new side of the diff is the working directory + */ + if (!GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED(sm_status)) + *status = GIT_DELTA_MODIFIED; + + /* now that we have a HEAD OID, check if HEAD moved */ + if ((sm_status & GIT_SUBMODULE_STATUS_IN_WD) != 0 && + !git_oid_equal(&info->oitem->oid, found_oid)) + *status = GIT_DELTA_MODIFIED; + + return 0; } static int maybe_modified( diff --git a/src/submodule.c b/src/submodule.c index 0beedeb42..685906332 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -30,6 +30,8 @@ static git_cvar_map _sm_update_map[] = { {GIT_CVAR_STRING, "rebase", GIT_SUBMODULE_UPDATE_REBASE}, {GIT_CVAR_STRING, "merge", GIT_SUBMODULE_UPDATE_MERGE}, {GIT_CVAR_STRING, "none", GIT_SUBMODULE_UPDATE_NONE}, + {GIT_CVAR_FALSE, NULL, GIT_SUBMODULE_UPDATE_NONE}, + {GIT_CVAR_TRUE, NULL, GIT_SUBMODULE_UPDATE_CHECKOUT}, }; static git_cvar_map _sm_ignore_map[] = { @@ -37,6 +39,8 @@ static git_cvar_map _sm_ignore_map[] = { {GIT_CVAR_STRING, "untracked", GIT_SUBMODULE_IGNORE_UNTRACKED}, {GIT_CVAR_STRING, "dirty", GIT_SUBMODULE_IGNORE_DIRTY}, {GIT_CVAR_STRING, "all", GIT_SUBMODULE_IGNORE_ALL}, + {GIT_CVAR_FALSE, NULL, GIT_SUBMODULE_IGNORE_NONE}, + {GIT_CVAR_TRUE, NULL, GIT_SUBMODULE_IGNORE_ALL}, }; static kh_inline khint_t str_hash_no_trailing_slash(const char *s) @@ -406,11 +410,30 @@ cleanup: return error; } +const char *git_submodule_ignore_to_str(git_submodule_ignore_t ignore) +{ + int i; + for (i = 0; i < (int)ARRAY_SIZE(_sm_ignore_map); ++i) + if (_sm_ignore_map[i].map_value == ignore) + return _sm_ignore_map[i].str_match; + return NULL; +} + +const char *git_submodule_update_to_str(git_submodule_update_t update) +{ + int i; + for (i = 0; i < (int)ARRAY_SIZE(_sm_update_map); ++i) + if (_sm_update_map[i].map_value == update) + return _sm_update_map[i].str_match; + return NULL; +} + int git_submodule_save(git_submodule *submodule) { int error = 0; git_config_backend *mods; git_buf key = GIT_BUF_INIT; + const char *val; assert(submodule); @@ -435,22 +458,14 @@ int git_submodule_save(git_submodule *submodule) goto cleanup; if (!(error = submodule_config_key_trunc_puts(&key, "update")) && - submodule->update != GIT_SUBMODULE_UPDATE_DEFAULT) - { - const char *val = (submodule->update == GIT_SUBMODULE_UPDATE_CHECKOUT) ? - NULL : _sm_update_map[submodule->update].str_match; + (val = git_submodule_update_to_str(submodule->update)) != NULL) error = git_config_file_set_string(mods, key.ptr, val); - } if (error < 0) goto cleanup; if (!(error = submodule_config_key_trunc_puts(&key, "ignore")) && - submodule->ignore != GIT_SUBMODULE_IGNORE_DEFAULT) - { - const char *val = (submodule->ignore == GIT_SUBMODULE_IGNORE_NONE) ? - NULL : _sm_ignore_map[submodule->ignore].str_match; + (val = git_submodule_ignore_to_str(submodule->ignore)) != NULL) error = git_config_file_set_string(mods, key.ptr, val); - } if (error < 0) goto cleanup; @@ -554,7 +569,8 @@ const git_oid *git_submodule_wd_id(git_submodule *submodule) git_submodule_ignore_t git_submodule_ignore(git_submodule *submodule) { assert(submodule); - return submodule->ignore; + return (submodule->ignore < GIT_SUBMODULE_IGNORE_NONE) ? + GIT_SUBMODULE_IGNORE_NONE : submodule->ignore; } git_submodule_ignore_t git_submodule_set_ignore( @@ -564,7 +580,7 @@ git_submodule_ignore_t git_submodule_set_ignore( assert(submodule); - if (ignore == GIT_SUBMODULE_IGNORE_DEFAULT) + if (ignore == GIT_SUBMODULE_IGNORE_RESET) ignore = submodule->ignore_default; old = submodule->ignore; @@ -575,7 +591,8 @@ git_submodule_ignore_t git_submodule_set_ignore( git_submodule_update_t git_submodule_update(git_submodule *submodule) { assert(submodule); - return submodule->update; + return (submodule->update < GIT_SUBMODULE_UPDATE_CHECKOUT) ? + GIT_SUBMODULE_UPDATE_CHECKOUT : submodule->update; } git_submodule_update_t git_submodule_set_update( @@ -585,7 +602,7 @@ git_submodule_update_t git_submodule_set_update( assert(submodule); - if (update == GIT_SUBMODULE_UPDATE_DEFAULT) + if (update == GIT_SUBMODULE_UPDATE_RESET) update = submodule->update_default; old = submodule->update; @@ -616,6 +633,7 @@ int git_submodule_set_fetch_recurse_submodules( int git_submodule_init(git_submodule *submodule, int overwrite) { int error; + const char *val; /* write "submodule.NAME.url" */ @@ -632,14 +650,10 @@ int git_submodule_init(git_submodule *submodule, int overwrite) /* write "submodule.NAME.update" if not default */ - if (submodule->update == GIT_SUBMODULE_UPDATE_CHECKOUT) - error = submodule_update_config( - submodule, "update", NULL, (overwrite != 0), false); - else if (submodule->update != GIT_SUBMODULE_UPDATE_DEFAULT) - error = submodule_update_config( - submodule, "update", - _sm_update_map[submodule->update].str_match, - (overwrite != 0), false); + val = (submodule->update == GIT_SUBMODULE_UPDATE_CHECKOUT) ? + NULL : git_submodule_update_to_str(submodule->update); + error = submodule_update_config( + submodule, "update", val, (overwrite != 0), false); return error; } @@ -873,7 +887,7 @@ int git_submodule__status( unsigned int status; git_repository *smrepo = NULL; - if (ign == GIT_SUBMODULE_IGNORE_DEFAULT) + if (ign < GIT_SUBMODULE_IGNORE_NONE) ign = sm->ignore; /* only return location info if ignore == all */ @@ -926,8 +940,7 @@ int git_submodule_status(unsigned int *status, git_submodule *sm) { assert(status && sm); - return git_submodule__status( - status, NULL, NULL, NULL, sm, GIT_SUBMODULE_IGNORE_DEFAULT); + return git_submodule__status(status, NULL, NULL, NULL, sm, 0); } int git_submodule_location(unsigned int *location, git_submodule *sm) @@ -964,7 +977,10 @@ static git_submodule *submodule_alloc(git_repository *repo, const char *name) } GIT_REFCOUNT_INC(sm); - sm->repo = repo; + sm->ignore = sm->ignore_default = GIT_SUBMODULE_IGNORE_NONE; + sm->update = sm->update_default = GIT_SUBMODULE_UPDATE_CHECKOUT; + sm->repo = repo; + return sm; } @@ -1039,6 +1055,34 @@ static int submodule_config_error(const char *property, const char *value) return -1; } +int git_submodule_parse_ignore(git_submodule_ignore_t *out, const char *value) +{ + int val; + + if (git_config_lookup_map_value( + &val, _sm_ignore_map, ARRAY_SIZE(_sm_ignore_map), value) < 0) { + *out = GIT_SUBMODULE_IGNORE_NONE; + return submodule_config_error("ignore", value); + } + + *out = (git_submodule_ignore_t)val; + return 0; +} + +int git_submodule_parse_update(git_submodule_update_t *out, const char *value) +{ + int val; + + if (git_config_lookup_map_value( + &val, _sm_update_map, ARRAY_SIZE(_sm_update_map), value) < 0) { + *out = GIT_SUBMODULE_UPDATE_CHECKOUT; + return submodule_config_error("update", value); + } + + *out = (git_submodule_update_t)val; + return 0; +} + static int submodule_load_from_config( const git_config_entry *entry, void *data) { @@ -1120,22 +1164,18 @@ static int submodule_load_from_config( return -1; } else if (strcasecmp(property, "update") == 0) { - int val; - if (git_config_lookup_map_value( - &val, _sm_update_map, ARRAY_SIZE(_sm_update_map), value) < 0) - return submodule_config_error("update", value); - sm->update_default = sm->update = (git_submodule_update_t)val; + if (git_submodule_parse_update(&sm->update, value) < 0) + return -1; + sm->update_default = sm->update; } else if (strcasecmp(property, "fetchRecurseSubmodules") == 0) { if (git__parse_bool(&sm->fetch_recurse, value) < 0) return submodule_config_error("fetchRecurseSubmodules", value); } else if (strcasecmp(property, "ignore") == 0) { - int val; - if (git_config_lookup_map_value( - &val, _sm_ignore_map, ARRAY_SIZE(_sm_ignore_map), value) < 0) - return submodule_config_error("ignore", value); - sm->ignore_default = sm->ignore = (git_submodule_ignore_t)val; + if (git_submodule_parse_ignore(&sm->ignore, value) < 0) + return -1; + sm->ignore_default = sm->ignore; } /* ignore other unknown submodule properties */ diff --git a/src/submodule.h b/src/submodule.h index 8db2fff29..b05937503 100644 --- a/src/submodule.h +++ b/src/submodule.h @@ -127,4 +127,12 @@ extern int git_submodule_open_bare( /* Release reference to submodule object - not currently for external use */ extern void git_submodule_free(git_submodule *sm); +extern int git_submodule_parse_ignore( + git_submodule_ignore_t *out, const char *value); +extern int git_submodule_parse_update( + git_submodule_update_t *out, const char *value); + +extern const char *git_submodule_ignore_to_str(git_submodule_ignore_t); +extern const char *git_submodule_update_to_str(git_submodule_update_t); + #endif diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index 3fcf45a37..5371b2864 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -29,6 +29,9 @@ void cl_git_report_failure(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) + #define cl_assert_equal_sz(sz1,sz2) cl_assert_equal_i((int)sz1, (int)(sz2)) /* diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index 4a40affb2..2e425bb11 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -49,7 +49,7 @@ static void check_diff_patches_at_line( cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d)); if (delta->status == GIT_DELTA_UNMODIFIED) { - clar__assert(expected[d] == NULL, file, line, "found UNMODIFIED delta where modified was expected", NULL, 1); + cl_assert_at_line(expected[d] == NULL, file, line); continue; } @@ -57,7 +57,7 @@ static void check_diff_patches_at_line( continue; if (expected[d] && !strcmp(expected[d], "")) { cl_git_pass(git_diff_patch_to_str(&patch_text, patch)); - clar__assert(0, file, line, "expected end of deltas, but found more", patch_text, 1); + cl_assert_at_line(!strcmp(expected[d], ""), file, line); } cl_git_pass(git_diff_patch_to_str(&patch_text, patch)); @@ -67,7 +67,7 @@ static void check_diff_patches_at_line( git__free(patch_text); } - clar__assert(expected[d] && !strcmp(expected[d], ""), file, line, "found fewer deltas than expected", expected[d], 1); + cl_assert_at_line(expected[d] && !strcmp(expected[d], ""), file, line); } #define check_diff_patches(diff, exp) \ @@ -382,3 +382,62 @@ void test_diff_submodules__invalid_cache(void) git_index_free(smindex); git_repository_free(smrepo); } + +void test_diff_submodules__diff_ignore_options(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff_list *diff = NULL; + static const char *expected_normal[] = { + "", /* .gitmodules */ + NULL, /* not-submodule */ + NULL, /* not */ + "diff --git a/sm_changed_file b/sm_changed_file\nindex 4800958..4800958 160000\n--- a/sm_changed_file\n+++ b/sm_changed_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_file */ + "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ + "diff --git a/sm_changed_index b/sm_changed_index\nindex 4800958..4800958 160000\n--- a/sm_changed_index\n+++ b/sm_changed_index\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_index */ + "diff --git a/sm_changed_untracked_file b/sm_changed_untracked_file\nindex 4800958..4800958 160000\n--- a/sm_changed_untracked_file\n+++ b/sm_changed_untracked_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_untracked_file */ + "diff --git a/sm_missing_commits b/sm_missing_commits\nindex 4800958..5e49635 160000\n--- a/sm_missing_commits\n+++ b/sm_missing_commits\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 5e4963595a9774b90524d35a807169049de8ccad\n", /* sm_missing_commits */ + "" + }; + static const char *expected_ignore_all[] = { + "", /* .gitmodules */ + NULL, /* not-submodule */ + NULL, /* not */ + "" + }; + static const char *expected_ignore_dirty[] = { + "", /* .gitmodules */ + NULL, /* not-submodule */ + NULL, /* not */ + "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ + "diff --git a/sm_missing_commits b/sm_missing_commits\nindex 4800958..5e49635 160000\n--- a/sm_missing_commits\n+++ b/sm_missing_commits\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 5e4963595a9774b90524d35a807169049de8ccad\n", /* sm_missing_commits */ + "" + }; + + setup_submodules2(); + + opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + opts.old_prefix = "a"; opts.new_prefix = "b"; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_normal); + git_diff_list_free(diff); + + opts.flags |= GIT_DIFF_IGNORE_SUBMODULES; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_ignore_all); + git_diff_list_free(diff); + + opts.flags &= ~GIT_DIFF_IGNORE_SUBMODULES; + opts.ignore_submodules = GIT_SUBMODULE_IGNORE_ALL; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_ignore_all); + git_diff_list_free(diff); + + opts.ignore_submodules = GIT_SUBMODULE_IGNORE_DIRTY; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_ignore_dirty); + git_diff_list_free(diff); +} diff --git a/tests-clar/submodule/modify.c b/tests-clar/submodule/modify.c index 94eb3738a..c0498ce6e 100644 --- a/tests-clar/submodule/modify.c +++ b/tests-clar/submodule/modify.c @@ -204,10 +204,10 @@ void test_submodule_modify__edit_and_save(void) cl_git_pass(git_submodule_set_url(sm1, old_url)); cl_assert_equal_i( (int)GIT_SUBMODULE_IGNORE_UNTRACKED, - (int)git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_DEFAULT)); + (int)git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_RESET)); cl_assert_equal_i( (int)GIT_SUBMODULE_UPDATE_REBASE, - (int)git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_DEFAULT)); + (int)git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_RESET)); cl_assert_equal_i( 1, git_submodule_set_fetch_recurse_submodules(sm1, old_fetchrecurse)); @@ -228,10 +228,10 @@ void test_submodule_modify__edit_and_save(void) cl_git_pass(git_submodule_save(sm1)); /* attempt to "revert" values */ - git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_DEFAULT); - git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_DEFAULT); + git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_RESET); + git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_RESET); - /* but ignore and update should NOT revert because the DEFAULT + /* but ignore and update should NOT revert because the RESET * should now be the newly saved value... */ cl_assert_equal_i( -- cgit v1.2.1 From b8df28a5dae65b617ce85e1937066093600880af Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sun, 30 Jun 2013 08:38:10 -0700 Subject: Clean up left over alloc change --- src/submodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/submodule.c b/src/submodule.c index 685906332..b5dacc42e 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -966,7 +966,7 @@ static git_submodule *submodule_alloc(git_repository *repo, const char *name) return NULL; } - sm = git__calloc(1, sizeof(git_submodule) + namelen + 1); + sm = git__calloc(1, sizeof(git_submodule)); if (sm == NULL) return NULL; -- cgit v1.2.1 From 9564229af42b68d205376853410c55b957546a14 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sun, 30 Jun 2013 08:43:07 -0700 Subject: Add tests for diff.ignoreSubmdules config --- tests-clar/diff/submodules.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index 2e425bb11..fe9cf1d98 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -387,6 +387,7 @@ void test_diff_submodules__diff_ignore_options(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_list *diff = NULL; + git_config *cfg; static const char *expected_normal[] = { "", /* .gitmodules */ NULL, /* not-submodule */ @@ -440,4 +441,32 @@ void test_diff_submodules__diff_ignore_options(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_ignore_dirty); git_diff_list_free(diff); + + opts.ignore_submodules = 0; + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_bool(cfg, "diff.ignoreSubmodules", false)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_normal); + git_diff_list_free(diff); + + cl_git_pass(git_config_set_bool(cfg, "diff.ignoreSubmodules", true)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_ignore_all); + git_diff_list_free(diff); + + cl_git_pass(git_config_set_string(cfg, "diff.ignoreSubmodules", "none")); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_normal); + git_diff_list_free(diff); + + cl_git_pass(git_config_set_string(cfg, "diff.ignoreSubmodules", "dirty")); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_ignore_dirty); + git_diff_list_free(diff); + + git_config_free(cfg); } -- cgit v1.2.1 From 125655fe3f0caf8b3d9fff2ec45ec694b34eed04 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 2 Jul 2013 16:49:57 -0700 Subject: Untracked directories with .git should be ignored This restores a behavior that was accidentally lost during some diff refactoring where an untracked directory that contains a .git item should be treated as IGNORED, not as UNTRACKED. The submodule code already detects this, but the diff code was not handling the scenario right. This also updates a number of existing tests that were actually exercising the behavior but did not have the right expectations in place. It actually makes the new `test_diff_submodules__diff_ignore_options` test feel much better because the "not-a-submodule" entries are now ignored instead of showing up as untracked items. Fixes #1697 --- src/diff.c | 14 ++++++++-- tests-clar/diff/submodules.c | 47 ++++++-------------------------- tests-clar/diff/workdir.c | 7 +++-- tests-clar/status/submodules.c | 21 ++++++++------ tests-clar/submodule/status.c | 35 ++++++++++++++++-------- tests-clar/submodule/submodule_helpers.c | 35 ++++++++++++++++++++++++ tests-clar/submodule/submodule_helpers.h | 3 ++ 7 files changed, 97 insertions(+), 65 deletions(-) diff --git a/src/diff.c b/src/diff.c index 5fa635f05..e875d09b3 100644 --- a/src/diff.c +++ b/src/diff.c @@ -735,7 +735,7 @@ static int maybe_modified( /* if we got here and decided that the files are modified, but we * haven't calculated the OID of the new item, then calculate it now */ - if (status != GIT_DELTA_UNMODIFIED && git_oid_iszero(&nitem->oid)) { + if (status == GIT_DELTA_MODIFIED && git_oid_iszero(&nitem->oid)) { if (git_oid_iszero(&noid)) { if (git_diff__oid_for_file(diff->repo, nitem->path, nitem->mode, nitem->file_size, &noid) < 0) @@ -858,7 +858,7 @@ static int handle_unmatched_new_item( git_buf_clear(&info->ignore_prefix); } - if (S_ISDIR(nitem->mode)) { + if (nitem->mode == GIT_FILEMODE_TREE) { bool recurse_into_dir = contains_oitem; /* if not already inside an ignored dir, check if this is ignored */ @@ -962,6 +962,16 @@ static int handle_unmatched_new_item( else if (info->new_iter->type != GIT_ITERATOR_TYPE_WORKDIR) delta_type = GIT_DELTA_ADDED; + else if (nitem->mode == GIT_FILEMODE_COMMIT) { + git_submodule *sm; + + /* ignore things that are not actual submodules */ + if (git_submodule_lookup(&sm, info->repo, nitem->path) != 0) { + giterr_clear(); + delta_type = GIT_DELTA_IGNORED; + } + } + /* Actually create the record for this item if necessary */ if ((error = diff_delta__from_one(diff, delta_type, nitem)) < 0) return error; diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index fe9cf1d98..94804db22 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -5,36 +5,13 @@ static git_repository *g_repo = NULL; -static void setup_submodules(void) -{ - g_repo = cl_git_sandbox_init("submodules"); - cl_fixture_sandbox("testrepo.git"); - rewrite_gitmodules(git_repository_workdir(g_repo)); - p_rename("submodules/testrepo/.gitted", "submodules/testrepo/.git"); -} - -static void setup_submodules2(void) -{ - g_repo = cl_git_sandbox_init("submod2"); - - cl_fixture_sandbox("submod2_target"); - p_rename("submod2_target/.gitted", "submod2_target/.git"); - - rewrite_gitmodules(git_repository_workdir(g_repo)); - p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git"); - p_rename("submod2/not/.gitted", "submod2/not/.git"); -} - void test_diff_submodules__initialize(void) { } void test_diff_submodules__cleanup(void) { - cl_git_sandbox_cleanup(); - - cl_fixture_cleanup("testrepo.git"); - cl_fixture_cleanup("submod2_target"); + cleanup_fixture_submodules(); } static void check_diff_patches_at_line( @@ -88,7 +65,7 @@ void test_diff_submodules__unmodified_submodule(void) "" }; - setup_submodules(); + g_repo = setup_fixture_submodules(); opts.flags = GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED | @@ -115,7 +92,7 @@ void test_diff_submodules__dirty_submodule(void) "" }; - setup_submodules(); + g_repo = setup_fixture_submodules(); cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); cl_git_mkfile("submodules/testrepo/all_new.txt", "never seen before"); @@ -141,7 +118,7 @@ void test_diff_submodules__dirty_submodule_2(void) "" }; - setup_submodules(); + g_repo = setup_fixture_submodules(); cl_git_pass(git_submodule_reload_all(g_repo)); @@ -190,8 +167,6 @@ void test_diff_submodules__submod2_index_to_wd(void) git_diff_list *diff = NULL; static const char *expected[] = { "", /* .gitmodules */ - NULL, /* not-submodule */ - NULL, /* not */ "diff --git a/sm_changed_file b/sm_changed_file\nindex 4800958..4800958 160000\n--- a/sm_changed_file\n+++ b/sm_changed_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_file */ "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ "diff --git a/sm_changed_index b/sm_changed_index\nindex 4800958..4800958 160000\n--- a/sm_changed_index\n+++ b/sm_changed_index\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_index */ @@ -200,7 +175,7 @@ void test_diff_submodules__submod2_index_to_wd(void) "" }; - setup_submodules2(); + g_repo = setup_fixture_submod2(); opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; opts.old_prefix = "a"; opts.new_prefix = "b"; @@ -221,7 +196,7 @@ void test_diff_submodules__submod2_head_to_index(void) "" }; - setup_submodules2(); + g_repo = setup_fixture_submod2(); cl_git_pass(git_repository_head_tree(&head, g_repo)); @@ -261,7 +236,7 @@ void test_diff_submodules__invalid_cache(void) "" }; - setup_submodules2(); + g_repo = setup_fixture_submod2(); opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; opts.old_prefix = "a"; opts.new_prefix = "b"; @@ -390,8 +365,6 @@ void test_diff_submodules__diff_ignore_options(void) git_config *cfg; static const char *expected_normal[] = { "", /* .gitmodules */ - NULL, /* not-submodule */ - NULL, /* not */ "diff --git a/sm_changed_file b/sm_changed_file\nindex 4800958..4800958 160000\n--- a/sm_changed_file\n+++ b/sm_changed_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_file */ "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ "diff --git a/sm_changed_index b/sm_changed_index\nindex 4800958..4800958 160000\n--- a/sm_changed_index\n+++ b/sm_changed_index\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_index */ @@ -401,20 +374,16 @@ void test_diff_submodules__diff_ignore_options(void) }; static const char *expected_ignore_all[] = { "", /* .gitmodules */ - NULL, /* not-submodule */ - NULL, /* not */ "" }; static const char *expected_ignore_dirty[] = { "", /* .gitmodules */ - NULL, /* not-submodule */ - NULL, /* not */ "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ "diff --git a/sm_missing_commits b/sm_missing_commits\nindex 4800958..5e49635 160000\n--- a/sm_missing_commits\n+++ b/sm_missing_commits\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 5e4963595a9774b90524d35a807169049de8ccad\n", /* sm_missing_commits */ "" }; - setup_submodules2(); + g_repo = setup_fixture_submod2(); opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; opts.old_prefix = "a"; opts.new_prefix = "b"; diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index 6a2504d09..c7fac1e48 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -776,6 +776,7 @@ void test_diff_workdir__submodules(void) opts.flags = GIT_DIFF_INCLUDE_UNTRACKED | + GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_RECURSE_UNTRACKED_DIRS | GIT_DIFF_INCLUDE_UNTRACKED_CONTENT; @@ -806,7 +807,7 @@ void test_diff_workdir__submodules(void) * only significant difference is that those Added items will show up * as Untracked items in the pure libgit2 diff. * - * Then add in the two extra untracked items "not" and "not-submodule" + * Then add in the two extra ignored items "not" and "not-submodule" * to get the 12 files reported here. */ @@ -815,8 +816,8 @@ void test_diff_workdir__submodules(void) cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(10, exp.file_status[GIT_DELTA_UNTRACKED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(8, exp.file_status[GIT_DELTA_UNTRACKED]); /* the following numbers match "git diff 873585" exactly */ diff --git a/tests-clar/status/submodules.c b/tests-clar/status/submodules.c index af8707721..7bfef503f 100644 --- a/tests-clar/status/submodules.c +++ b/tests-clar/status/submodules.c @@ -9,25 +9,19 @@ static git_repository *g_repo = NULL; void test_status_submodules__initialize(void) { - g_repo = cl_git_sandbox_init("submodules"); - - cl_fixture_sandbox("testrepo.git"); - - rewrite_gitmodules(git_repository_workdir(g_repo)); - - p_rename("submodules/testrepo/.gitted", "submodules/testrepo/.git"); } void test_status_submodules__cleanup(void) { - cl_git_sandbox_cleanup(); - cl_fixture_cleanup("testrepo.git"); + cleanup_fixture_submodules(); } void test_status_submodules__api(void) { git_submodule *sm; + g_repo = setup_fixture_submodules(); + cl_assert(git_submodule_lookup(NULL, g_repo, "nonexistent") == GIT_ENOTFOUND); cl_assert(git_submodule_lookup(NULL, g_repo, "modified") == GIT_ENOTFOUND); @@ -42,6 +36,8 @@ void test_status_submodules__0(void) { int counts = 0; + g_repo = setup_fixture_submodules(); + cl_assert(git_path_isdir("submodules/.git")); cl_assert(git_path_isdir("submodules/testrepo/.git")); cl_assert(git_path_isfile("submodules/.gitmodules")); @@ -86,6 +82,8 @@ void test_status_submodules__1(void) { status_entry_counts counts; + g_repo = setup_fixture_submodules(); + cl_assert(git_path_isdir("submodules/.git")); cl_assert(git_path_isdir("submodules/testrepo/.git")); cl_assert(git_path_isfile("submodules/.gitmodules")); @@ -104,6 +102,7 @@ void test_status_submodules__1(void) void test_status_submodules__single_file(void) { unsigned int status = 0; + g_repo = setup_fixture_submodules(); cl_git_pass( git_status_file(&status, g_repo, "testrepo") ); cl_assert(!status); } @@ -134,6 +133,8 @@ void test_status_submodules__moved_head(void) GIT_STATUS_WT_NEW }; + g_repo = setup_fixture_submodules(); + cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo")); cl_git_pass(git_submodule_open(&smrepo, sm)); @@ -192,6 +193,8 @@ void test_status_submodules__dirty_workdir_only(void) GIT_STATUS_WT_NEW }; + g_repo = setup_fixture_submodules(); + cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); cl_git_mkfile("submodules/testrepo/all_new.txt", "never seen before"); diff --git a/tests-clar/submodule/status.c b/tests-clar/submodule/status.c index 68110bdd5..7b29ac288 100644 --- a/tests-clar/submodule/status.c +++ b/tests-clar/submodule/status.c @@ -9,21 +9,12 @@ static git_repository *g_repo = NULL; void test_submodule_status__initialize(void) { - g_repo = cl_git_sandbox_init("submod2"); - - cl_fixture_sandbox("submod2_target"); - p_rename("submod2_target/.gitted", "submod2_target/.git"); - - /* must create submod2_target before rewrite so prettify will work */ - rewrite_gitmodules(git_repository_workdir(g_repo)); - p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git"); - p_rename("submod2/not/.gitted", "submod2/not/.git"); + g_repo = setup_fixture_submod2(); } void test_submodule_status__cleanup(void) { - cl_git_sandbox_cleanup(); - cl_fixture_cleanup("submod2_target"); + cleanup_fixture_submodules(); } void test_submodule_status__unchanged(void) @@ -326,6 +317,7 @@ void test_submodule_status__ignore_all(void) typedef struct { size_t counter; const char **paths; + int *statuses; } submodule_expectations; static int confirm_submodule_status( @@ -336,6 +328,7 @@ static int confirm_submodule_status( while (git__suffixcmp(exp->paths[exp->counter], "/") == 0) exp->counter++; + cl_assert_equal_i(exp->statuses[exp->counter], (int)status_flags); cl_assert_equal_s(exp->paths[exp->counter++], path); GIT_UNUSED(status_flags); @@ -365,7 +358,24 @@ void test_submodule_status__iterator(void) "sm_unchanged", NULL }; - submodule_expectations exp = { 0, expected }; + static int expected_flags[] = { + GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_MODIFIED, /* ".gitmodules" */ + 0, /* "just_a_dir/" will be skipped */ + GIT_STATUS_CURRENT, /* "just_a_dir/contents" */ + GIT_STATUS_CURRENT, /* "just_a_file" */ + GIT_STATUS_IGNORED, /* "not" (contains .git) */ + GIT_STATUS_IGNORED, /* "not-submodule" (contains .git) */ + GIT_STATUS_CURRENT, /* "README.txt */ + GIT_STATUS_INDEX_NEW, /* "sm_added_and_uncommited" */ + GIT_STATUS_WT_MODIFIED, /* "sm_changed_file" */ + GIT_STATUS_WT_MODIFIED, /* "sm_changed_head" */ + GIT_STATUS_WT_MODIFIED, /* "sm_changed_index" */ + GIT_STATUS_WT_MODIFIED, /* "sm_changed_untracked_file" */ + GIT_STATUS_WT_MODIFIED, /* "sm_missing_commits" */ + GIT_STATUS_CURRENT, /* "sm_unchanged" */ + 0 + }; + submodule_expectations exp = { 0, expected, expected_flags }; git_status_options opts = GIT_STATUS_OPTIONS_INIT; cl_git_pass(git_iterator_for_workdir(&iter, g_repo, @@ -378,6 +388,7 @@ void test_submodule_status__iterator(void) opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_INCLUDE_UNMODIFIED | + GIT_STATUS_OPT_INCLUDE_IGNORED | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; cl_git_pass(git_status_foreach_ext( diff --git a/tests-clar/submodule/submodule_helpers.c b/tests-clar/submodule/submodule_helpers.c index 0c3e79f71..a7807522b 100644 --- a/tests-clar/submodule/submodule_helpers.c +++ b/tests-clar/submodule/submodule_helpers.c @@ -82,3 +82,38 @@ void rewrite_gitmodules(const char *workdir) git_buf_free(&out_f); git_buf_free(&path); } + +git_repository *setup_fixture_submodules(void) +{ + git_repository *repo = cl_git_sandbox_init("submodules"); + + cl_fixture_sandbox("testrepo.git"); + + rewrite_gitmodules(git_repository_workdir(repo)); + p_rename("submodules/testrepo/.gitted", "submodules/testrepo/.git"); + + return repo; +} + +git_repository *setup_fixture_submod2(void) +{ + git_repository *repo = cl_git_sandbox_init("submod2"); + + cl_fixture_sandbox("submod2_target"); + p_rename("submod2_target/.gitted", "submod2_target/.git"); + + rewrite_gitmodules(git_repository_workdir(repo)); + p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git"); + p_rename("submod2/not/.gitted", "submod2/not/.git"); + + return repo; +} + +void cleanup_fixture_submodules(void) +{ + cl_git_sandbox_cleanup(); + + /* just try to clean up both possible extras */ + cl_fixture_cleanup("testrepo.git"); + cl_fixture_cleanup("submod2_target"); +} diff --git a/tests-clar/submodule/submodule_helpers.h b/tests-clar/submodule/submodule_helpers.h index 6b76a832e..1de15ca17 100644 --- a/tests-clar/submodule/submodule_helpers.h +++ b/tests-clar/submodule/submodule_helpers.h @@ -1,2 +1,5 @@ extern void rewrite_gitmodules(const char *workdir); +extern git_repository *setup_fixture_submodules(void); +extern git_repository *setup_fixture_submod2(void); +extern void cleanup_fixture_submodules(void); -- cgit v1.2.1 From d70ce9bd7a1acec34b283d3bc92da84fbbf79860 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 10 Jul 2013 15:38:57 -0700 Subject: Clarify docs for git_status_file --- include/git2/status.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/git2/status.h b/include/git2/status.h index fd0e83104..2f7c06726 100644 --- a/include/git2/status.h +++ b/include/git2/status.h @@ -234,12 +234,12 @@ GIT_EXTERN(int) git_status_foreach_ext( * This is not quite the same as calling `git_status_foreach_ext()` with * the pathspec set to the specified path. * - * @param status_flags The status value for the file + * @param status_flags Output combination of git_status_t values for file * @param repo A repository object - * @param path The file to retrieve status for, rooted at the repo's workdir + * @param path The file to retrieve status for relative to the repo workdir * @return 0 on success, GIT_ENOTFOUND if the file is not found in the HEAD, - * index, and work tree, GIT_EINVALIDPATH if `path` points at a folder, - * GIT_EAMBIGUOUS if "path" matches multiple files, -1 on other error. + * index, and work tree, GIT_EAMBIGUOUS if `path` matches multiple files + * or if it refers to a folder, and -1 on other errors. */ GIT_EXTERN(int) git_status_file( unsigned int *status_flags, -- cgit v1.2.1 From 814de0bcab99f82dc637ba7ae34df5a0e9e1138c Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 11 Jul 2013 11:00:41 -0700 Subject: Update git__swap thread helper This makes git__swap use the __sync_lock_test_and_set primitive with GCC and the InterlockedExchangePointer primitive with MSVC. Previously is used compare_and_swap in a way that was probably unintuitive for most thinking (i.e. it could fail to swap in the value if another thread raced in). Now it will always succeed and the last thread to run in a race will win instead of the first thread. This also fixes up a little confusion between volatile void ** and void * volatile * that came up with the Win32 compiler. --- src/thread-utils.h | 57 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/src/thread-utils.h b/src/thread-utils.h index f8c4dc66d..04e02959f 100644 --- a/src/thread-utils.h +++ b/src/thread-utils.h @@ -38,16 +38,6 @@ typedef git_atomic git_atomic_ssize; #endif -GIT_INLINE(void) git_atomic_set(git_atomic *a, int val) -{ - a->val = val; -} - -GIT_INLINE(int) git_atomic_get(git_atomic *a) -{ - return (int)a->val; -} - #ifdef GIT_THREADS #define git_thread pthread_t @@ -71,6 +61,17 @@ GIT_INLINE(int) git_atomic_get(git_atomic *a) #define git_cond_signal(c) pthread_cond_signal(c) #define git_cond_broadcast(c) pthread_cond_broadcast(c) +GIT_INLINE(void) git_atomic_set(git_atomic *a, int val) +{ +#if defined(GIT_WIN32) + InterlockedExchange(&a->val, (LONG)val); +#elif defined(__GNUC__) + __sync_lock_test_and_set(&a->val, val); +#else +# error "Unsupported architecture for atomic operations" +#endif +} + GIT_INLINE(int) git_atomic_inc(git_atomic *a) { #if defined(GIT_WIN32) @@ -105,7 +106,7 @@ GIT_INLINE(int) git_atomic_dec(git_atomic *a) } GIT_INLINE(void *) git___compare_and_swap( - volatile void **ptr, void *oldval, void *newval) + void * volatile *ptr, void *oldval, void *newval) { volatile void *foundval; #if defined(GIT_WIN32) @@ -118,6 +119,16 @@ GIT_INLINE(void *) git___compare_and_swap( return (foundval == oldval) ? oldval : newval; } +GIT_INLINE(volatile void *) git___swap( + void * volatile *ptr, void *newval) +{ +#if defined(GIT_WIN32) + return InterlockedExchangePointer(ptr, newval); +#else + return __sync_lock_test_and_set(ptr, newval); +#endif +} + #ifdef GIT_ARCH_64 GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend) @@ -156,6 +167,11 @@ GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend) #define git_cond_signal(c) (void)0 #define git_cond_broadcast(c) (void)0 +GIT_INLINE(void) git_atomic_set(git_atomic *a, int val) +{ + a->val = val; +} + GIT_INLINE(int) git_atomic_inc(git_atomic *a) { return ++a->val; @@ -173,7 +189,7 @@ GIT_INLINE(int) git_atomic_dec(git_atomic *a) } GIT_INLINE(void *) git___compare_and_swap( - volatile void **ptr, void *oldval, void *newval) + void * volatile *ptr, void *oldval, void *newval) { if (*ptr == oldval) *ptr = newval; @@ -182,6 +198,14 @@ GIT_INLINE(void *) git___compare_and_swap( return oldval; } +GIT_INLINE(volatile void *) git___swap( + void * volatile *ptr, void *newval) +{ + volatile void *old = *ptr; + *ptr = newval; + return old; +} + #ifdef GIT_ARCH_64 GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend) @@ -194,13 +218,18 @@ GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend) #endif +GIT_INLINE(int) git_atomic_get(git_atomic *a) +{ + return (int)a->val; +} + /* Atomically replace oldval with newval * @return oldval if it was replaced or newval if it was not */ #define git__compare_and_swap(P,O,N) \ - git___compare_and_swap((volatile void **)P, O, N) + git___compare_and_swap((void * volatile *)P, O, N) -#define git__swap(ptr, val) git__compare_and_swap(&ptr, ptr, val) +#define git__swap(ptr, val) (void *)git___swap((void * volatile *)&ptr, val) extern int git_online_cpus(void); -- cgit v1.2.1 From 584f2d3013df6744fa7b5c5398a78b96f31e25f4 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 11 Jul 2013 11:04:42 -0700 Subject: Fix warnings on Win64 --- src/commit.c | 3 ++- src/diff_driver.c | 2 +- tests-clar/diff/pathspec.c | 14 +++++++------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/commit.c b/src/commit.c index cc912a7be..15a195fe5 100644 --- a/src/commit.c +++ b/src/commit.c @@ -163,7 +163,8 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj) const char *buffer_start = git_odb_object_data(odb_obj), *buffer; const char *buffer_end = buffer_start + git_odb_object_size(odb_obj); git_oid parent_id; - size_t parent_count = 0, header_len; + uint32_t parent_count = 0; + size_t header_len; /* find end-of-header (counting parents as we go) */ for (buffer = buffer_start; buffer < buffer_end; ++buffer) { diff --git a/src/diff_driver.c b/src/diff_driver.c index 77b0e9f3e..e82dfa50d 100644 --- a/src/diff_driver.c +++ b/src/diff_driver.c @@ -374,7 +374,7 @@ static long diff_context_find( return -1; if (out_size > (long)ctxt->line.size) - out_size = ctxt->line.size; + out_size = (long)ctxt->line.size; memcpy(out, ctxt->line.ptr, (size_t)out_size); return out_size; diff --git a/tests-clar/diff/pathspec.c b/tests-clar/diff/pathspec.c index 332b513b3..4334a8901 100644 --- a/tests-clar/diff/pathspec.c +++ b/tests-clar/diff/pathspec.c @@ -34,7 +34,7 @@ void test_diff_pathspec__0(void) cl_git_pass(git_pathspec_new(&ps, &paths)); cl_git_pass(git_pathspec_match_tree(&matches, a, GIT_PATHSPEC_DEFAULT, ps)); - cl_assert_equal_i(7, git_pathspec_match_list_entrycount(matches)); + cl_assert_equal_i(7, (int)git_pathspec_match_list_entrycount(matches)); cl_assert_equal_s("current_file", git_pathspec_match_list_entry(matches,0)); cl_assert(git_pathspec_match_list_diff_entry(matches,0) == NULL); git_pathspec_match_list_free(matches); @@ -43,13 +43,13 @@ void test_diff_pathspec__0(void) cl_git_pass(git_pathspec_match_diff( &matches, diff, GIT_PATHSPEC_DEFAULT, ps)); - cl_assert_equal_i(7, git_pathspec_match_list_entrycount(matches)); + cl_assert_equal_i(7, (int)git_pathspec_match_list_entrycount(matches)); cl_assert(git_pathspec_match_list_diff_entry(matches, 0) != NULL); cl_assert(git_pathspec_match_list_entry(matches, 0) == NULL); cl_assert_equal_s("current_file", git_pathspec_match_list_diff_entry(matches,0)->new_file.path); cl_assert_equal_i(GIT_DELTA_ADDED, - git_pathspec_match_list_diff_entry(matches,0)->status); + (int)git_pathspec_match_list_diff_entry(matches,0)->status); git_pathspec_match_list_free(matches); git_diff_list_free(diff); @@ -59,13 +59,13 @@ void test_diff_pathspec__0(void) cl_git_pass(git_pathspec_match_diff( &matches, diff, GIT_PATHSPEC_DEFAULT, ps)); - cl_assert_equal_i(3, git_pathspec_match_list_entrycount(matches)); + cl_assert_equal_i(3, (int)git_pathspec_match_list_entrycount(matches)); cl_assert(git_pathspec_match_list_diff_entry(matches, 0) != NULL); cl_assert(git_pathspec_match_list_entry(matches, 0) == NULL); cl_assert_equal_s("subdir/current_file", git_pathspec_match_list_diff_entry(matches,0)->new_file.path); cl_assert_equal_i(GIT_DELTA_DELETED, - git_pathspec_match_list_diff_entry(matches,0)->status); + (int)git_pathspec_match_list_diff_entry(matches,0)->status); git_pathspec_match_list_free(matches); git_diff_list_free(diff); @@ -75,13 +75,13 @@ void test_diff_pathspec__0(void) cl_git_pass(git_pathspec_match_diff( &matches, diff, GIT_PATHSPEC_DEFAULT, ps)); - cl_assert_equal_i(4, git_pathspec_match_list_entrycount(matches)); + cl_assert_equal_i(4, (int)git_pathspec_match_list_entrycount(matches)); cl_assert(git_pathspec_match_list_diff_entry(matches, 0) != NULL); cl_assert(git_pathspec_match_list_entry(matches, 0) == NULL); cl_assert_equal_s("modified_file", git_pathspec_match_list_diff_entry(matches,0)->new_file.path); cl_assert_equal_i(GIT_DELTA_MODIFIED, - git_pathspec_match_list_diff_entry(matches,0)->status); + (int)git_pathspec_match_list_diff_entry(matches,0)->status); git_pathspec_match_list_free(matches); git_diff_list_free(diff); -- cgit v1.2.1 From 0a1c8f55b35ebd35a7d267099257634483268ffd Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 11 Jul 2013 17:09:15 -0500 Subject: preload configuration paths --- src/fileops.c | 14 ++++++++++++++ src/fileops.h | 7 +++++++ src/global.c | 9 ++++----- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 1f58fa5cd..db53d4fce 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -627,6 +627,20 @@ static git_futils_dirs_guess_cb git_futils__dir_guess[GIT_FUTILS_DIR__MAX] = { git_futils_guess_xdg_dirs, }; +int git_futils_dirs_global_init(void) +{ + git_futils_dir_t i; + git_buf *path; + int error = 0; + + for (i = 0; i < GIT_FUTILS_DIR__MAX; i++) { + if ((error = git_futils_dirs_get(&path, i)) < 0) + break; + } + + return error; +} + static int git_futils_check_selector(git_futils_dir_t which) { if (which < GIT_FUTILS_DIR__MAX) diff --git a/src/fileops.h b/src/fileops.h index f4e059c83..d23ebaffb 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -309,6 +309,13 @@ typedef enum { GIT_FUTILS_DIR__MAX = 3, } git_futils_dir_t; +/** + * Configures global data for configuration file search paths. + * + * @return 0 on success, <0 on failure + */ +extern int git_futils_dirs_global_init(void); + /** * Get the search path for global/system/xdg files * diff --git a/src/global.c b/src/global.c index 2d40ca2fc..a06d0c81f 100644 --- a/src/global.c +++ b/src/global.c @@ -65,10 +65,8 @@ int git_threads_init(void) return -1; /* Initialize any other subsystems that have global state */ - if ((error = git_hash_global_init()) >= 0) - _tls_init = 1; - - if (error == 0) + if ((error = git_hash_global_init()) >= 0 && + (error = git_futils_dirs_global_init()) >= 0) _tls_init = 1; GIT_MEMORY_BARRIER; @@ -127,7 +125,8 @@ int git_threads_init(void) pthread_key_create(&_tls_key, &cb__free_status); /* Initialize any other subsystems that have global state */ - if ((error = git_hash_global_init()) >= 0) + if ((error = git_hash_global_init()) >= 0 && + (error = git_futils_dirs_global_init()) >= 0) _tls_init = 1; GIT_MEMORY_BARRIER; -- cgit v1.2.1 From 1c13b0bfdcfb510863a6e5e3238f8a461551aa0f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 12 Jul 2013 15:30:05 -0500 Subject: test that suggests tags arent fully peeled during push --- tests-clar/online/push.c | 12 ++++++++++++ .../objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 | 2 ++ .../objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 | Bin 0 -> 141 bytes .../resources/push_src/.gitted/refs/tags/tag-commit-two | 1 + tests-clar/resources/push_src/.gitted/refs/tags/tag-tag | 1 + 5 files changed, 16 insertions(+) create mode 100644 tests-clar/resources/push_src/.gitted/objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 create mode 100644 tests-clar/resources/push_src/.gitted/objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 create mode 100644 tests-clar/resources/push_src/.gitted/refs/tags/tag-commit-two create mode 100644 tests-clar/resources/push_src/.gitted/refs/tags/tag-tag diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 5dc7974c7..321180781 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -29,6 +29,7 @@ static git_oid _tag_commit; static git_oid _tag_tree; static git_oid _tag_blob; static git_oid _tag_lightweight; +static git_oid _tag_tag; static int cred_acquire_cb( git_cred **cred, @@ -272,6 +273,7 @@ void test_online_push__initialize(void) git_oid_fromstr(&_tag_tree, "ff83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e"); git_oid_fromstr(&_tag_blob, "b483ae7ba66decee9aee971f501221dea84b1498"); git_oid_fromstr(&_tag_lightweight, "951bbbb90e2259a4c8950db78946784fb53fcbce"); + git_oid_fromstr(&_tag_tag, "eea4f2705eeec2db3813f2430829afce99cd00b5"); /* Remote URL environment variable must be set. User and password are optional. */ _remote_url = cl_getenv("GITTEST_REMOTE_URL"); @@ -569,6 +571,16 @@ void test_online_push__tag_lightweight(void) exp_refs, ARRAY_SIZE(exp_refs), 0); } +void test_online_push__tag_to_tag(void) +{ + const char *specs[] = { "refs/tags/tag-tag:refs/tags/tag-tag" }; + push_status exp_stats[] = { { "refs/tags/tag-tag", NULL } }; + expected_ref exp_refs[] = { { "refs/tags/tag-tag", &_tag_tag } }; + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0); +} + void test_online_push__force(void) { const char *specs1[] = {"refs/heads/b3:refs/heads/tgt"}; diff --git a/tests-clar/resources/push_src/.gitted/objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 b/tests-clar/resources/push_src/.gitted/objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 new file mode 100644 index 000000000..0bc57f266 --- /dev/null +++ b/tests-clar/resources/push_src/.gitted/objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 @@ -0,0 +1,2 @@ +x%] +0S͏B)} @bnf`f`>3(nibC0hQ6BMv2&-M0Q)+ tNsE*;}JϲN픹(th@#B˺C?TÅoyk7 \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 b/tests-clar/resources/push_src/.gitted/objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 new file mode 100644 index 000000000..b7b81d5e3 Binary files /dev/null and b/tests-clar/resources/push_src/.gitted/objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 differ diff --git a/tests-clar/resources/push_src/.gitted/refs/tags/tag-commit-two b/tests-clar/resources/push_src/.gitted/refs/tags/tag-commit-two new file mode 100644 index 000000000..abb365080 --- /dev/null +++ b/tests-clar/resources/push_src/.gitted/refs/tags/tag-commit-two @@ -0,0 +1 @@ +36f79b2846017d3761e0a02d0bccd573e0f90c57 diff --git a/tests-clar/resources/push_src/.gitted/refs/tags/tag-tag b/tests-clar/resources/push_src/.gitted/refs/tags/tag-tag new file mode 100644 index 000000000..d6cd74804 --- /dev/null +++ b/tests-clar/resources/push_src/.gitted/refs/tags/tag-tag @@ -0,0 +1 @@ +eea4f2705eeec2db3813f2430829afce99cd00b5 -- cgit v1.2.1 From cdacd3d931a95068b6ef3410e240c73f305835a1 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 12 Jul 2013 16:53:00 -0500 Subject: header files show up in vs --- CMakeLists.txt | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 34d56b3fa..1086005c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,7 @@ ELSE () ELSE() MESSAGE("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) + FILE(GLOB SRC_HTTP deps/http-parser/*.c deps/http-parser/*.h) ENDIF() ENDIF() @@ -148,7 +148,7 @@ ELSE() MESSAGE( "zlib was not found; using bundled 3rd-party sources." ) INCLUDE_DIRECTORIES(deps/zlib) ADD_DEFINITIONS(-DNO_VIZ -DSTDC -DNO_GZIP) - FILE(GLOB SRC_ZLIB deps/zlib/*.c) + FILE(GLOB SRC_ZLIB deps/zlib/*.c deps/zlib/*.h) ENDIF() IF(NOT LIBSSH2_LIBRARY) @@ -285,19 +285,19 @@ ENDIF() ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64) # Collect sourcefiles -FILE(GLOB SRC_H include/git2/*.h) +FILE(GLOB SRC_H include/git2.h include/git2/*.h include/git2/sys/*.h) # On Windows use specific platform sources IF (WIN32 AND NOT CYGWIN) ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0501) - FILE(GLOB SRC_OS src/win32/*.c) + FILE(GLOB SRC_OS src/win32/*.c src/win32/*.h) ELSEIF (AMIGA) ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R) - FILE(GLOB SRC_OS src/amiga/*.c) + FILE(GLOB SRC_OS src/amiga/*.c src/amiga/*.h) ELSE() - FILE(GLOB SRC_OS src/unix/*.c) + FILE(GLOB SRC_OS src/unix/*.c src/unix/*.h) ENDIF() -FILE(GLOB SRC_GIT2 src/*.c src/transports/*.c src/xdiff/*.c) +FILE(GLOB SRC_GIT2 src/*.c src/*.h src/transports/*.c src/transports/*.h src/xdiff/*.c src/xdiff/*.h) # Determine architecture of the machine IF (CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -309,7 +309,7 @@ ELSE() ENDIF() # Compile and link libgit2 -ADD_LIBRARY(git2 ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1} ${WIN_RC}) +ADD_LIBRARY(git2 ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1} ${WIN_RC}) TARGET_LINK_LIBRARIES(git2 ${SSL_LIBRARIES}) TARGET_LINK_LIBRARIES(git2 ${SSH_LIBRARIES}) TARGET_OS_LIBRARIES(git2) @@ -359,7 +359,7 @@ IF (BUILD_CLAR) ADD_DEFINITIONS(-DCLAR_RESOURCES=\"${TEST_RESOURCES}\") INCLUDE_DIRECTORIES(${CLAR_PATH}) - FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c) + FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c ${CLAR_PATH}/*/*.h) SET(SRC_CLAR "${CLAR_PATH}/main.c" "${CLAR_PATH}/clar_libgit2.c" "${CLAR_PATH}/clar.c") ADD_CUSTOM_COMMAND( @@ -373,7 +373,7 @@ IF (BUILD_CLAR) ${CLAR_PATH}/clar.c PROPERTIES OBJECT_DEPENDS ${CLAR_PATH}/clar.suite) - ADD_EXECUTABLE(libgit2_clar ${SRC_GIT2} ${SRC_OS} ${SRC_CLAR} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1}) + ADD_EXECUTABLE(libgit2_clar ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_CLAR} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1}) TARGET_LINK_LIBRARIES(libgit2_clar ${SSL_LIBRARIES}) TARGET_LINK_LIBRARIES(libgit2_clar ${SSH_LIBRARIES}) @@ -409,7 +409,7 @@ IF (TAGS) ENDIF () IF (BUILD_EXAMPLES) - FILE(GLOB_RECURSE EXAMPLE_SRC examples/network/*.c) + FILE(GLOB_RECURSE EXAMPLE_SRC examples/network/*.c examples/network/*.h) ADD_EXECUTABLE(cgit2 ${EXAMPLE_SRC}) IF(WIN32) TARGET_LINK_LIBRARIES(cgit2 git2) -- cgit v1.2.1 From b3a559ddce5e23d7084546ca771fc16e96d24ed8 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 13 Jul 2013 13:55:03 +0200 Subject: submodule: Fix memory leaks --- src/submodule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/submodule.c b/src/submodule.c index b5dacc42e..b4e917561 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -798,7 +798,7 @@ static void submodule_update_from_head_data( static int submodule_update_head(git_submodule *submodule) { git_tree *head = NULL; - git_tree_entry *te; + git_tree_entry *te = NULL; submodule->flags = submodule->flags & ~(GIT_SUBMODULE_STATUS_IN_HEAD | @@ -811,6 +811,7 @@ static int submodule_update_head(git_submodule *submodule) else submodule_update_from_head_data(submodule, te->attr, &te->oid); + git_tree_entry_free(te); git_tree_free(head); return 0; } -- cgit v1.2.1 From d6cb13d7436793718f103687fe95d0f881487ad0 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 13 Jul 2013 14:00:05 +0200 Subject: tests: Fix memory leak --- tests-clar/diff/pathspec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests-clar/diff/pathspec.c b/tests-clar/diff/pathspec.c index 4334a8901..7b15ea04c 100644 --- a/tests-clar/diff/pathspec.c +++ b/tests-clar/diff/pathspec.c @@ -89,4 +89,5 @@ void test_diff_pathspec__0(void) git_tree_free(a); git_tree_free(b); + git_pathspec_free(ps); } -- cgit v1.2.1 From 80fd31faf773f3f50e2b5547b7171063f38dac17 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 13 Jul 2013 13:30:23 +0200 Subject: revparse: Don't return a reference when asked for a git object Fix #1722 --- src/revparse.c | 13 +++++++++++++ tests-clar/refs/revparse.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/src/revparse.c b/src/revparse.c index bcfb0843f..d21f08b53 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -685,6 +685,8 @@ int revparse__ext( git_reference *reference = NULL; git_object *base_rev = NULL; + bool should_return_reference = true; + assert(object_out && reference_out && repo && spec); *object_out = NULL; @@ -693,6 +695,8 @@ int revparse__ext( while (spec[pos]) { switch (spec[pos]) { case '^': + should_return_reference = false; + if ((error = ensure_base_rev_loaded(&base_rev, &reference, spec, identifier_len, repo, false)) < 0) goto cleanup; @@ -725,6 +729,8 @@ int revparse__ext( { git_object *temp_object = NULL; + should_return_reference = false; + if ((error = extract_how_many(&n, spec, &pos)) < 0) goto cleanup; @@ -743,6 +749,8 @@ int revparse__ext( { git_object *temp_object = NULL; + should_return_reference = false; + if ((error = extract_path(&buf, spec, &pos)) < 0) goto cleanup; @@ -807,6 +815,11 @@ int revparse__ext( if ((error = ensure_base_rev_loaded(&base_rev, &reference, spec, identifier_len, repo, false)) < 0) goto cleanup; + if (!should_return_reference) { + git_reference_free(reference); + reference = NULL; + } + *object_out = base_rev; *reference_out = reference; *identifier_len_out = identifier_len; diff --git a/tests-clar/refs/revparse.c b/tests-clar/refs/revparse.c index 69d92745c..9657054de 100644 --- a/tests-clar/refs/revparse.c +++ b/tests-clar/refs/revparse.c @@ -738,4 +738,45 @@ void test_refs_revparse__ext_can_expand_short_reference_names(void) "master", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "refs/heads/master"); + + test_object_and_ref( + "HEAD", + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", + "refs/heads/master"); + + test_object_and_ref( + "tags/test", + "b25fa35b38051e4ae45d4222e795f9df2e43f1d1", + "refs/tags/test"); +} + +void test_refs_revparse__ext_returns_NULL_reference_when_expression_points_at_a_revision(void) +{ + test_object_and_ref( + "HEAD~3", + "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", + NULL); + + test_object_and_ref( + "HEAD~0", + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", + NULL); + + test_object_and_ref( + "HEAD^0", + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", + NULL); + + test_object_and_ref( + "@{-1}@{0}", + "a4a7dce85cf63874e984719f4fdd239f5145052f", + NULL); +} + +void test_refs_revparse__ext_returns_NULL_reference_when_expression_points_at_a_tree_content(void) +{ + test_object_and_ref( + "tags/test:readme.txt", + "0266163a49e280c4f5ed1e08facd36a2bd716bcf", + NULL); } -- cgit v1.2.1 From d6d34cd0f49621c6f5ea992820c4564f5e968b73 Mon Sep 17 00:00:00 2001 From: crazymaster Date: Sat, 13 Jul 2013 02:10:16 +0900 Subject: Add test for multi-byte characters --- tests-clar/object/blob/filter.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests-clar/object/blob/filter.c b/tests-clar/object/blob/filter.c index 042bddab7..50b4af4f4 100644 --- a/tests-clar/object/blob/filter.c +++ b/tests-clar/object/blob/filter.c @@ -5,7 +5,7 @@ #include "buf_text.h" static git_repository *g_repo = NULL; -#define NUM_TEST_OBJECTS 8 +#define NUM_TEST_OBJECTS 9 static git_oid g_oids[NUM_TEST_OBJECTS]; static const char *g_raw[NUM_TEST_OBJECTS] = { "", @@ -15,9 +15,10 @@ static const char *g_raw[NUM_TEST_OBJECTS] = { "foo\nbar\rboth\r\nreversed\n\ragain\nproblems\r", "123\n\000\001\002\003\004abc\255\254\253\r\n", "\xEF\xBB\xBFThis is UTF-8\n", + "\xEF\xBB\xBFほげほげ\r\nほげほげ\r\n", "\xFE\xFF\x00T\x00h\x00i\x00s\x00!" }; -static git_off_t g_len[NUM_TEST_OBJECTS] = { -1, -1, -1, -1, -1, 17, -1, 12 }; +static git_off_t g_len[NUM_TEST_OBJECTS] = { -1, -1, -1, -1, -1, 17, -1, -1, 12 }; static git_buf_text_stats g_stats[NUM_TEST_OBJECTS] = { { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 2, 0, 6, 0 }, @@ -26,6 +27,7 @@ static git_buf_text_stats g_stats[NUM_TEST_OBJECTS] = { { 0, 0, 4, 4, 1, 31, 0 }, { 0, 1, 1, 2, 1, 9, 5 }, { GIT_BOM_UTF8, 0, 0, 1, 0, 16, 0 }, + { GIT_BOM_UTF8, 0, 2, 2, 2, 27, 0 }, { GIT_BOM_UTF16_BE, 5, 0, 0, 0, 7, 5 }, }; static git_buf g_crlf_filtered[NUM_TEST_OBJECTS] = { @@ -36,6 +38,7 @@ static git_buf g_crlf_filtered[NUM_TEST_OBJECTS] = { { "foo\nbar\rboth\nreversed\n\ragain\nproblems\r", 0, 38 }, { "123\n\000\001\002\003\004abc\255\254\253\n", 0, 16 }, { "\xEF\xBB\xBFThis is UTF-8\n", 0, 17 }, + { "\xEF\xBB\xBFほげほげ\nほげほげ\n", 0, 29 }, { "\xFE\xFF\x00T\x00h\x00i\x00s\x00!", 0, 12 } }; -- cgit v1.2.1 From 6550565af387119b080a65d71f77f1261752595b Mon Sep 17 00:00:00 2001 From: crazymaster Date: Sat, 13 Jul 2013 03:02:00 +0900 Subject: Fix gather_stats --- src/buf_text.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/buf_text.c b/src/buf_text.c index 443454b5f..bc8d04680 100644 --- a/src/buf_text.c +++ b/src/buf_text.c @@ -261,29 +261,34 @@ bool git_buf_text_gather_stats( /* Counting loop */ while (scan < end) { unsigned char c = *scan++; - - if ((c > 0x1F && c < 0x7F) || c > 0x9f) - stats->printable++; - else switch (c) { - case '\0': - stats->nul++; - stats->nonprintable++; - break; - case '\n': - stats->lf++; - break; - case '\r': - stats->cr++; - if (scan < end && *scan == '\n') - stats->crlf++; - break; - case '\t': case '\f': case '\v': case '\b': case 0x1b: /*ESC*/ + if (c == '\r') { + stats->cr++; + if (scan < end && *scan == '\n') + stats->crlf++; + continue; + } + if (c == '\n') { + stats->lf++; + continue; + } + if (c == 127) + /* DEL */ + stats->nonprintable++; + else if (c < 32) { + switch (c) { + /* BS, HT, ESC and FF */ + case '\b': case '\t': case '\033': case '\014': stats->printable++; break; + case 0: + stats->nul++; + /* fall through */ default: stats->nonprintable++; - break; } + } + else + stats->printable++; } return (stats->nul > 0 || -- cgit v1.2.1 From 960431c3808a98333aa9642424bcc7fef581b78c Mon Sep 17 00:00:00 2001 From: Andy Lindeman Date: Sun, 14 Jul 2013 17:26:24 -0400 Subject: Fixes return type documentation --- include/git2/object.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/git2/object.h b/include/git2/object.h index b91b04dba..f74f3dfd1 100644 --- a/include/git2/object.h +++ b/include/git2/object.h @@ -36,7 +36,7 @@ GIT_BEGIN_DECL * @param repo the repository to look up the object * @param id the unique identifier for the object * @param type the type of the object - * @return a reference to the object + * @return 0 or an error code */ GIT_EXTERN(int) git_object_lookup( git_object **object, -- cgit v1.2.1 From a91e4d6b21e141c2abc76b65b2d4c91d5d3e03cc Mon Sep 17 00:00:00 2001 From: crazymaster Date: Mon, 15 Jul 2013 07:19:42 +0900 Subject: Replace Japanese characters with the encoded hexadecimal values --- tests-clar/object/blob/filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests-clar/object/blob/filter.c b/tests-clar/object/blob/filter.c index 50b4af4f4..b5e9bb298 100644 --- a/tests-clar/object/blob/filter.c +++ b/tests-clar/object/blob/filter.c @@ -15,7 +15,7 @@ static const char *g_raw[NUM_TEST_OBJECTS] = { "foo\nbar\rboth\r\nreversed\n\ragain\nproblems\r", "123\n\000\001\002\003\004abc\255\254\253\r\n", "\xEF\xBB\xBFThis is UTF-8\n", - "\xEF\xBB\xBFほげほげ\r\nほげほげ\r\n", + "\xEF\xBB\xBF0xE30x810x0xBB0xE30x810x920xE30x810x0xBB0xE30x810x92\r\n0xE30x810x0xBB0xE30x810x920xE30x810x0xBB0xE30x810x92\r\n", "\xFE\xFF\x00T\x00h\x00i\x00s\x00!" }; static git_off_t g_len[NUM_TEST_OBJECTS] = { -1, -1, -1, -1, -1, 17, -1, -1, 12 }; @@ -38,7 +38,7 @@ static git_buf g_crlf_filtered[NUM_TEST_OBJECTS] = { { "foo\nbar\rboth\nreversed\n\ragain\nproblems\r", 0, 38 }, { "123\n\000\001\002\003\004abc\255\254\253\n", 0, 16 }, { "\xEF\xBB\xBFThis is UTF-8\n", 0, 17 }, - { "\xEF\xBB\xBFほげほげ\nほげほげ\n", 0, 29 }, + { "\xEF\xBB\xBF0xE30x810x0xBB0xE30x810x920xE30x810x0xBB0xE30x810x92\n0xE30x810x0xBB0xE30x810x920xE30x810x0xBB0xE30x810x92\n", 0, 29 }, { "\xFE\xFF\x00T\x00h\x00i\x00s\x00!", 0, 12 } }; -- cgit v1.2.1 From 19bee769d49467704f4d8ee36965c548cb40e3c6 Mon Sep 17 00:00:00 2001 From: crazymaster Date: Mon, 15 Jul 2013 07:39:16 +0900 Subject: Revert "Replace Japanese characters with the encoded hexadecimal values" This reverts commit a91e4d6b21e141c2abc76b65b2d4c91d5d3e03cc. --- tests-clar/object/blob/filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests-clar/object/blob/filter.c b/tests-clar/object/blob/filter.c index b5e9bb298..50b4af4f4 100644 --- a/tests-clar/object/blob/filter.c +++ b/tests-clar/object/blob/filter.c @@ -15,7 +15,7 @@ static const char *g_raw[NUM_TEST_OBJECTS] = { "foo\nbar\rboth\r\nreversed\n\ragain\nproblems\r", "123\n\000\001\002\003\004abc\255\254\253\r\n", "\xEF\xBB\xBFThis is UTF-8\n", - "\xEF\xBB\xBF0xE30x810x0xBB0xE30x810x920xE30x810x0xBB0xE30x810x92\r\n0xE30x810x0xBB0xE30x810x920xE30x810x0xBB0xE30x810x92\r\n", + "\xEF\xBB\xBFほげほげ\r\nほげほげ\r\n", "\xFE\xFF\x00T\x00h\x00i\x00s\x00!" }; static git_off_t g_len[NUM_TEST_OBJECTS] = { -1, -1, -1, -1, -1, 17, -1, -1, 12 }; @@ -38,7 +38,7 @@ static git_buf g_crlf_filtered[NUM_TEST_OBJECTS] = { { "foo\nbar\rboth\nreversed\n\ragain\nproblems\r", 0, 38 }, { "123\n\000\001\002\003\004abc\255\254\253\n", 0, 16 }, { "\xEF\xBB\xBFThis is UTF-8\n", 0, 17 }, - { "\xEF\xBB\xBF0xE30x810x0xBB0xE30x810x920xE30x810x0xBB0xE30x810x92\n0xE30x810x0xBB0xE30x810x920xE30x810x0xBB0xE30x810x92\n", 0, 29 }, + { "\xEF\xBB\xBFほげほげ\nほげほげ\n", 0, 29 }, { "\xFE\xFF\x00T\x00h\x00i\x00s\x00!", 0, 12 } }; -- cgit v1.2.1 From b74d4478df8c6d62c96b3bd067ae1987209583a6 Mon Sep 17 00:00:00 2001 From: crazymaster Date: Mon, 15 Jul 2013 07:41:39 +0900 Subject: Fix the initial line --- src/buf_text.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/buf_text.c b/src/buf_text.c index bc8d04680..472339def 100644 --- a/src/buf_text.c +++ b/src/buf_text.c @@ -261,34 +261,29 @@ bool git_buf_text_gather_stats( /* Counting loop */ while (scan < end) { unsigned char c = *scan++; - if (c == '\r') { - stats->cr++; - if (scan < end && *scan == '\n') - stats->crlf++; - continue; - } - if (c == '\n') { - stats->lf++; - continue; - } - if (c == 127) - /* DEL */ - stats->nonprintable++; - else if (c < 32) { - switch (c) { - /* BS, HT, ESC and FF */ - case '\b': case '\t': case '\033': case '\014': + + if (c > 0x1F && c != 0x7F) + stats->printable++; + else switch (c) { + case '\0': + stats->nul++; + stats->nonprintable++; + break; + case '\n': + stats->lf++; + break; + case '\r': + stats->cr++; + if (scan < end && *scan == '\n') + stats->crlf++; + break; + case '\t': case '\f': case '\v': case '\b': case 0x1b: /*ESC*/ stats->printable++; break; - case 0: - stats->nul++; - /* fall through */ default: stats->nonprintable++; + break; } - } - else - stats->printable++; } return (stats->nul > 0 || -- cgit v1.2.1 From 2185dd6f99474b69287e6f3cd2e4a24c3a75155b Mon Sep 17 00:00:00 2001 From: crazymaster Date: Mon, 15 Jul 2013 07:59:04 +0900 Subject: Fix typo --- tests-clar/object/blob/filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests-clar/object/blob/filter.c b/tests-clar/object/blob/filter.c index 50b4af4f4..6293046d3 100644 --- a/tests-clar/object/blob/filter.c +++ b/tests-clar/object/blob/filter.c @@ -15,7 +15,7 @@ static const char *g_raw[NUM_TEST_OBJECTS] = { "foo\nbar\rboth\r\nreversed\n\ragain\nproblems\r", "123\n\000\001\002\003\004abc\255\254\253\r\n", "\xEF\xBB\xBFThis is UTF-8\n", - "\xEF\xBB\xBFほげほげ\r\nほげほげ\r\n", + "\xEF\xBB\xBF0xE30x810xBB0xE30x810x920xE30x810xBB0xE30x810x92\r\n0xE30x810xBB0xE30x810x920xE30x810xBB0xE30x810x92\r\n", "\xFE\xFF\x00T\x00h\x00i\x00s\x00!" }; static git_off_t g_len[NUM_TEST_OBJECTS] = { -1, -1, -1, -1, -1, 17, -1, -1, 12 }; @@ -38,7 +38,7 @@ static git_buf g_crlf_filtered[NUM_TEST_OBJECTS] = { { "foo\nbar\rboth\nreversed\n\ragain\nproblems\r", 0, 38 }, { "123\n\000\001\002\003\004abc\255\254\253\n", 0, 16 }, { "\xEF\xBB\xBFThis is UTF-8\n", 0, 17 }, - { "\xEF\xBB\xBFほげほげ\nほげほげ\n", 0, 29 }, + { "\xEF\xBB\xBF0xE30x810xBB0xE30x810x920xE30x810xBB0xE30x810x92\n0xE30x810xBB0xE30x810x920xE30x810xBB0xE30x810x92\n", 0, 29 }, { "\xFE\xFF\x00T\x00h\x00i\x00s\x00!", 0, 12 } }; -- cgit v1.2.1 From d0b25d9dff363976eea92509c359ca8e08aaebb5 Mon Sep 17 00:00:00 2001 From: crazymaster Date: Mon, 15 Jul 2013 08:14:00 +0900 Subject: Fix --- tests-clar/object/blob/filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests-clar/object/blob/filter.c b/tests-clar/object/blob/filter.c index 6293046d3..2b3954d9c 100644 --- a/tests-clar/object/blob/filter.c +++ b/tests-clar/object/blob/filter.c @@ -15,7 +15,7 @@ static const char *g_raw[NUM_TEST_OBJECTS] = { "foo\nbar\rboth\r\nreversed\n\ragain\nproblems\r", "123\n\000\001\002\003\004abc\255\254\253\r\n", "\xEF\xBB\xBFThis is UTF-8\n", - "\xEF\xBB\xBF0xE30x810xBB0xE30x810x920xE30x810xBB0xE30x810x92\r\n0xE30x810xBB0xE30x810x920xE30x810xBB0xE30x810x92\r\n", + "\xEF\xBB\xBF\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\r\n\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\r\n", "\xFE\xFF\x00T\x00h\x00i\x00s\x00!" }; static git_off_t g_len[NUM_TEST_OBJECTS] = { -1, -1, -1, -1, -1, 17, -1, -1, 12 }; @@ -38,7 +38,7 @@ static git_buf g_crlf_filtered[NUM_TEST_OBJECTS] = { { "foo\nbar\rboth\nreversed\n\ragain\nproblems\r", 0, 38 }, { "123\n\000\001\002\003\004abc\255\254\253\n", 0, 16 }, { "\xEF\xBB\xBFThis is UTF-8\n", 0, 17 }, - { "\xEF\xBB\xBF0xE30x810xBB0xE30x810x920xE30x810xBB0xE30x810x92\n0xE30x810xBB0xE30x810x920xE30x810xBB0xE30x810x92\n", 0, 29 }, + { "\xEF\xBB\xBF\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\n\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\n", 0, 29 }, { "\xFE\xFF\x00T\x00h\x00i\x00s\x00!", 0, 12 } }; -- cgit v1.2.1 From 9146f1e57ec4f2b6fa293c78d54f1383464ff5be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Duraffort?= Date: Mon, 15 Jul 2013 15:59:18 +0200 Subject: repository: clarify assignment and test order --- src/repository.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/repository.c b/src/repository.c index bd7ef5476..99ac56ef9 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1500,12 +1500,12 @@ int git_repository_is_empty(git_repository *repo) if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0) return -1; - if (!(error = git_reference_type(head) == GIT_REF_SYMBOLIC)) + if (!((error = git_reference_type(head)) == GIT_REF_SYMBOLIC)) goto cleanup; - if (!(error = strcmp( + if (!(error = (strcmp( git_reference_symbolic_target(head), - GIT_REFS_HEADS_DIR "master") == 0)) + GIT_REFS_HEADS_DIR "master") == 0))) goto cleanup; error = repo_contains_no_reference(repo); -- cgit v1.2.1 From 8d6ef4bf78cc5d3a3cb277ecc4fcf0fdcdbc9f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Duraffort?= Date: Mon, 15 Jul 2013 15:59:35 +0200 Subject: index: fix potential memory leaks --- src/index.c | 12 +++++++++--- src/indexer.c | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/index.c b/src/index.c index bd5e192f3..0610eb5b9 100644 --- a/src/index.c +++ b/src/index.c @@ -1409,14 +1409,18 @@ static int read_reuc(git_index *index, const char *buffer, size_t size) if (git__strtol32(&tmp, buffer, &endptr, 8) < 0 || !endptr || endptr == buffer || *endptr || - (unsigned)tmp > UINT_MAX) + (unsigned)tmp > UINT_MAX) { + index_entry_reuc_free(lost); return index_error_invalid("reading reuc entry stage"); + } lost->mode[i] = tmp; len = (endptr + 1) - buffer; - if (size <= len) + if (size <= len) { + index_entry_reuc_free(lost); return index_error_invalid("reading reuc entry stage"); + } size -= len; buffer += len; @@ -1426,8 +1430,10 @@ static int read_reuc(git_index *index, const char *buffer, size_t size) for (i = 0; i < 3; i++) { if (!lost->mode[i]) continue; - if (size < 20) + if (size < 20) { + index_entry_reuc_free(lost); return index_error_invalid("reading reuc entry oid"); + } git_oid_fromraw(&lost->oid[i], (const unsigned char *) buffer); size -= 20; diff --git a/src/indexer.c b/src/indexer.c index 1b638cd8a..09f962934 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -325,7 +325,7 @@ static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t ent /* FIXME: Parse the object instead of hashing it */ if (git_odb__hashobj(&oid, obj) < 0) { giterr_set(GITERR_INDEXER, "Failed to hash object"); - return -1; + goto on_error; } pentry = git__calloc(1, sizeof(struct git_pack_entry)); -- cgit v1.2.1 From 050af8bbe08b7cab7bfce044dcb51fb61ff1dc41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Duraffort?= Date: Mon, 15 Jul 2013 16:00:00 +0200 Subject: pack: fix memory leak in error path --- src/pack-objects.c | 4 +++- src/pack.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pack-objects.c b/src/pack-objects.c index 500104c55..7f427e3bd 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -505,8 +505,10 @@ static git_pobject **compute_write_order(git_packbuilder *pb) /* * Mark objects that are at the tip of tags. */ - if (git_tag_foreach(pb->repo, &cb_tag_foreach, pb) < 0) + if (git_tag_foreach(pb->repo, &cb_tag_foreach, pb) < 0) { + git__free(wo); return NULL; + } /* * Give the objects in the original recency order until diff --git a/src/pack.c b/src/pack.c index 7ce7099e0..497db38e8 100644 --- a/src/pack.c +++ b/src/pack.c @@ -329,8 +329,10 @@ static int pack_index_open(struct git_pack_file *p) memcpy(idx_name, p->pack_name, base_len); memcpy(idx_name + base_len, ".idx", sizeof(".idx")); - if ((error = git_mutex_lock(&p->lock)) < 0) + if ((error = git_mutex_lock(&p->lock)) < 0) { + git__free(idx_name); return error; + } if (p->index_version == -1) error = pack_index_check(idx_name, p); -- cgit v1.2.1 From c6451624c4631ccf039d0f3d5af6fbf4364f001c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Duraffort?= Date: Mon, 15 Jul 2013 16:00:07 +0200 Subject: Fix some more memory leaks in error path --- src/merge.c | 4 +++- src/odb.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/merge.c b/src/merge.c index 82d2e6f37..2e94ce1cd 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1902,8 +1902,10 @@ static int write_merge_msg( entries = git__calloc(heads_len, sizeof(struct merge_msg_entry)); GITERR_CHECK_ALLOC(entries); - if (git_vector_init(&matching, heads_len, NULL) < 0) + if (git_vector_init(&matching, heads_len, NULL) < 0) { + git__free(entries); return -1; + } for (i = 0; i < heads_len; i++) entries[i].merge_head = heads[i]; diff --git a/src/odb.c b/src/odb.c index 8e62efd00..23eb4e12e 100644 --- a/src/odb.c +++ b/src/odb.c @@ -232,6 +232,7 @@ int git_odb__hashlink(git_oid *out, const char *path) link_data[size] = '\0'; if (read_len != (ssize_t)size) { giterr_set(GITERR_OS, "Failed to read symlink data for '%s'", path); + git__free(link_data); return -1; } -- cgit v1.2.1 From 85e1eded6a5302b25c339988a6828aa45fbc23d8 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 15 Jul 2013 16:31:25 +0200 Subject: Add `git_remote_owner` --- include/git2/remote.h | 8 ++++++++ src/remote.c | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/include/git2/remote.h b/include/git2/remote.h index 45d15d0a3..13b04367c 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -95,6 +95,14 @@ GIT_EXTERN(int) git_remote_load(git_remote **out, git_repository *repo, const ch */ GIT_EXTERN(int) git_remote_save(const git_remote *remote); +/** + * Get the remote's repository + * + * @param remote the remote + * @return a pointer to the repository + */ +GIT_EXTERN(git_repository *) git_remote_owner(const git_remote *remote); + /** * Get the remote's name * diff --git a/src/remote.c b/src/remote.c index 0e8354a11..158f3e938 100644 --- a/src/remote.c +++ b/src/remote.c @@ -467,6 +467,12 @@ const char *git_remote_name(const git_remote *remote) return remote->name; } +git_repository *git_remote_owner(const git_remote *remote) +{ + assert(remote); + return remote->repo; +} + const char *git_remote_url(const git_remote *remote) { assert(remote); -- cgit v1.2.1 From 51b0397a66336cd9b45f5562c0fb147052c2e086 Mon Sep 17 00:00:00 2001 From: Andy Lindeman Date: Mon, 15 Jul 2013 23:40:57 -0400 Subject: Small grammar fix in docs --- 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 65d8cc16e..f1e7d0899 100644 --- a/include/git2/tree.h +++ b/include/git2/tree.h @@ -208,7 +208,7 @@ GIT_EXTERN(git_filemode_t) git_tree_entry_filemode(const git_tree_entry *entry); GIT_EXTERN(int) git_tree_entry_cmp(const git_tree_entry *e1, const git_tree_entry *e2); /** - * Convert a tree entry to the git_object it points too. + * Convert a tree entry to the git_object it points to. * * You must call `git_object_free()` on the object when you are done with it. * -- cgit v1.2.1 From e49dc6872d53dfa09d8a93dc5733328f2bd3204d Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 17 Jul 2013 14:06:31 -0700 Subject: Switch default calling convention to cdecl. --- CMakeLists.txt | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1086005c3..2afa1e03d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,16 +30,13 @@ OPTION( ENABLE_TRACE "Enables tracing support" OFF ) OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF ) IF(MSVC) - # This option is only availalbe when building with MSVC. By default, - # libgit2 is build using the stdcall calling convention, as that's what - # the CLR expects by default and how the Windows API is built. + # This option is only availalbe when building with MSVC. By default, libgit2 + # is build using the cdecl calling convention, which is useful if you're + # writing C. However, the CLR and Win32 API both expect stdcall. # - # If you are writing a C or C++ program and want to link to libgit2, you - # have to either: - # - Add /Gz to the compiler options of _your_ program / library. - # - Turn this off by invoking CMake with the "-DSTDCALL=Off" argument. - # - OPTION( STDCALL "Build libgit2 with the __stdcall convention" ON ) + # If you are writing a CLR program and want to link to libgit2, you'll want + # to turn this on by invoking CMake with the "-DSTDCALL=ON" argument. + OPTION( STDCALL "Build libgit2 with the __stdcall convention" OFF ) # This option must match the settings used in your program, in particular if you # are linking statically -- cgit v1.2.1 From d55bed1a253a9f914521c29b9a2d2517a79c034d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 17 Jul 2013 16:55:00 -0500 Subject: don't include ignored as rename candidates --- src/diff_tform.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/diff_tform.c b/src/diff_tform.c index b137bd319..ac5356a8c 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -590,11 +590,13 @@ static bool is_rename_target( return false; case GIT_DELTA_UNTRACKED: - case GIT_DELTA_IGNORED: if (!FLAG_SET(opts, GIT_DIFF_FIND_FOR_UNTRACKED)) return false; break; + case GIT_DELTA_IGNORED: + return false; + default: /* all other status values should be checked */ break; } -- cgit v1.2.1 From 275d8d55b29c83bd8c165f5eeaafd76c7e0d966b Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 18 Jul 2013 09:37:59 -0700 Subject: Typo --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2afa1e03d..c937ba93c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ OPTION( ENABLE_TRACE "Enables tracing support" OFF ) OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF ) IF(MSVC) - # This option is only availalbe when building with MSVC. By default, libgit2 + # This option is only available when building with MSVC. By default, libgit2 # is build using the cdecl calling convention, which is useful if you're # writing C. However, the CLR and Win32 API both expect stdcall. # -- cgit v1.2.1 From 3e3d332b4c3642ecd33d83f234f97be6c8aee449 Mon Sep 17 00:00:00 2001 From: Martin Woodward Date: Fri, 19 Jul 2013 18:04:11 +0100 Subject: Tidy up the methods of contacting the project Updated the methods of getting involved with the project and asking questions. --- README.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a2a18765a..3e08ac3ea 100644 --- a/README.md +++ b/README.md @@ -11,20 +11,23 @@ libgit2 is licensed under a **very permissive license** (GPLv2 with a special Li This basically means that you can link it (unmodified) with any kind of software without having to release its source code. -* Mailing list: ~~~~ - The libgit2 mailing list has - traditionally been hosted in Librelist, but Librelist is and has always - been a shitshow. We encourage you to [open an issue](https://github.com/libgit2/libgit2/issues) - on GitHub instead for any questions regarding the library. - * Archives: * Website: +* StackOverflow Tag: [libgit2](http://stackoverflow.com/questions/tagged/libgit2) +* Issues: * API documentation: * IRC: #libgit2 on irc.freenode.net. +* Mailing list: The libgit2 mailing list was + traditionally hosted in Librelist but has been deprecated. We encourage you to + [use StackOverflow](http://stackoverflow.com/questions/tagged/libgit2) or [open an issue](https://github.com/libgit2/libgit2/issues) + on GitHub instead for any questions regarding the library. The mailing list archives are still available at + . + What It Can Do ================================== -libgit2 is already very usable. +libgit2 is already very usable and is being used in production for many applications including the GitHub.com site, in Plastic SCM +and also powering Microsoft's Visual Studio tools for Git. The library provides: * SHA conversions, formatting and shortening * abstracted ODB backend system @@ -128,8 +131,8 @@ Here are the bindings to libgit2 that are currently available: * Lua * luagit2 * .NET - * libgit2net, low level bindings * libgit2sharp + * libgit2net, low level bindings superceeded by libgit2sharp * Node.js * node-gitteh * nodegit -- cgit v1.2.1 From 6ca83665c77599f10914ae48e3f1952333d72827 Mon Sep 17 00:00:00 2001 From: Martin Woodward Date: Fri, 19 Jul 2013 18:20:58 +0100 Subject: Update contributing guidance to explain PR flow Updating the contributing guidance to explain a bit more about how we use PR's --- CONTRIBUTING.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 28ef27f42..5c2eaec5e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,6 +48,12 @@ Please include a nice description of your changes with your PR; if we have to read the whole diff to figure out why you're contributing in the first place, you're less likely to get feedback and have your change merged in. +If you are working on a particular area then feel free to submit a PR that +highlights your work in progress (and flag in the PR title that it's not +ready to merge). This will help in getting visibility for your fix, allow +others to comment early on the changes and also let others know that you +are currently working on something. + ## Porting Code From Other Open-Source Projects `libgit2` is licensed under the terms of the GPL v2 with a linking @@ -57,14 +63,17 @@ The most common case is porting code from core Git. Git is a pure GPL project, which means that in order to port code to this project, we need the explicit permission of the author. Check the [`git.git-authors`](https://github.com/libgit2/libgit2/blob/development/git.git-authors) -file for authors who have already consented; feel free to add someone if -you've obtained their consent. +file for authors who have already consented. Other licenses have other requirements; check the license of the library you're porting code *from* to see what you need to do. As a general rule, MIT and BSD (3-clause) licenses are typically no problem. Apache 2.0 license typically doesn't work due to GPL incompatibility. +If you are pulling in code from core Git, another project or code you've pulled from +a forum / Stack Overflow then please flag this in your PR and also make sure you've +given proper credit to the original author in the code snippet. + ## Style Guide `libgit2` is written in [ANSI C](http://en.wikipedia.org/wiki/ANSI_C) -- cgit v1.2.1 From 41a93cc6e5adb17cab0281ac49996d02f94baa9d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 19 Jul 2013 12:43:08 -0500 Subject: Clarify when to use github issues Suggest that github issues are to be used for bug reports, while questions about usage should be directed to StackOverflow. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3e08ac3ea..611d6f579 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,9 @@ release its source code. * IRC: #libgit2 on irc.freenode.net. * Mailing list: The libgit2 mailing list was traditionally hosted in Librelist but has been deprecated. We encourage you to - [use StackOverflow](http://stackoverflow.com/questions/tagged/libgit2) or [open an issue](https://github.com/libgit2/libgit2/issues) - on GitHub instead for any questions regarding the library. The mailing list archives are still available at + [use StackOverflow](http://stackoverflow.com/questions/tagged/libgit2) instead for any questions regarding + the library, and to or [open an issue](https://github.com/libgit2/libgit2/issues) + on GitHub for bug reports. The mailing list archives are still available at . -- cgit v1.2.1 From bef59b1be4ec9754959423d36138731577a4f413 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 19 Jul 2013 12:56:47 -0500 Subject: Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 611d6f579..a89463b7c 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ release its source code. * Mailing list: The libgit2 mailing list was traditionally hosted in Librelist but has been deprecated. We encourage you to [use StackOverflow](http://stackoverflow.com/questions/tagged/libgit2) instead for any questions regarding - the library, and to or [open an issue](https://github.com/libgit2/libgit2/issues) + the library, or [open an issue](https://github.com/libgit2/libgit2/issues) on GitHub for bug reports. The mailing list archives are still available at . -- cgit v1.2.1 From b71071313f4800840ecc48cb18e5cedec8ef250e Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 22 Jul 2013 11:01:19 -0700 Subject: git_reference_next_name must match git_reference_next The git_reference_next API silently skips invalid references when scanning the loose refs. The git_reference_next_name API should skip the same ones even though it isn't creating the reference object. This adds a test with a an invalid loose reference and makes sure that both APIs skip the same entries and generate the same results. --- src/refdb_fs.c | 16 +++++++++++++--- tests-clar/revwalk/basic.c | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/refdb_fs.c b/src/refdb_fs.c index b9e283ac5..2f1a5b26c 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -452,6 +452,9 @@ static int loose_lookup( git_buf ref_file = GIT_BUF_INIT; int error = 0; + if (out) + *out = NULL; + error = reference_read(&ref_file, NULL, backend->path, ref_name, NULL); if (error < 0) @@ -465,15 +468,17 @@ static int loose_lookup( goto done; } - *out = git_reference__alloc_symbolic(ref_name, target); + if (out) + *out = git_reference__alloc_symbolic(ref_name, target); } else { if ((error = loose_parse_oid(&oid, ref_name, &ref_file)) < 0) goto done; - *out = git_reference__alloc(ref_name, &oid, NULL); + if (out) + *out = git_reference__alloc(ref_name, &oid, NULL); } - if (*out == NULL) + if (out && *out == NULL) error = -1; done: @@ -679,6 +684,11 @@ static int refdb_fs_backend__iterator_next_name( if (git_strmap_exists(packfile, path)) continue; + if (loose_lookup(NULL, backend, path) != 0) { + giterr_clear(); + continue; + } + *out = path; return 0; } diff --git a/tests-clar/revwalk/basic.c b/tests-clar/revwalk/basic.c index e82776260..7c2fc000d 100644 --- a/tests-clar/revwalk/basic.c +++ b/tests-clar/revwalk/basic.c @@ -142,6 +142,28 @@ void test_revwalk_basic__glob_heads(void) cl_assert(i == 14); } +void test_revwalk_basic__glob_heads_with_invalid(void) +{ + int i; + git_oid oid; + + test_revwalk_basic__cleanup(); + + _repo = cl_git_sandbox_init("testrepo"); + cl_git_mkfile("testrepo/.git/refs/heads/garbage", "not-a-ref"); + + cl_git_pass(git_revwalk_new(&_walk, _repo)); + cl_git_pass(git_revwalk_push_glob(_walk, "heads")); + + for (i = 0; !git_revwalk_next(&oid, _walk); ++i) + /* walking */; + + /* git log --branches --oneline | wc -l => 16 */ + cl_assert_equal_i(16, i); + + cl_fixture_cleanup("testrepo"); +} + void test_revwalk_basic__push_head(void) { int i = 0; -- cgit v1.2.1 From c77342ef1c956f99f84f217359c73e8de65cdd1c Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 22 Jul 2013 11:20:34 -0700 Subject: Use pool for loose refdb string allocations Instead of using lots of strdup calls, this adds a memory pool to the loose refs iteration code and uses it for keeping track of the loose refs array. Memory usage could probably be reduced even further by eliminating the vector and just scanning by adding the strlen of each ref, but that would be a more intrusive changes. This also updates the error handling to be more thorough about checking for failed allocations, etc. --- src/refdb_fs.c | 55 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 2f1a5b26c..acd82594b 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -560,7 +560,10 @@ typedef struct { git_reference_iterator parent; char *glob; + + git_pool pool; git_vector loose; + unsigned int loose_pos; khiter_t packed_pos; } refdb_fs_iter; @@ -568,24 +571,18 @@ typedef struct { static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter) { refdb_fs_iter *iter = (refdb_fs_iter *) _iter; - char *loose_path; - size_t i; - - git_vector_foreach(&iter->loose, i, loose_path) { - git__free(loose_path); - } git_vector_free(&iter->loose); - - git__free(iter->glob); + git_pool_clear(&iter->pool); git__free(iter); } static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) { + int error = 0; git_strmap *packfile = backend->refcache.packfile; git_buf path = GIT_BUF_INIT; - git_iterator *fsit; + git_iterator *fsit = NULL; const git_index_entry *entry = NULL; if (!backend->path) /* do nothing if no path for loose refs */ @@ -594,15 +591,16 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) if (git_buf_printf(&path, "%s/refs", backend->path) < 0) return -1; - if (git_iterator_for_filesystem(&fsit, git_buf_cstr(&path), 0, NULL, NULL) < 0) - return -1; - - git_vector_init(&iter->loose, 8, NULL); - git_buf_sets(&path, GIT_REFS_DIR); + if ((error = git_iterator_for_filesystem( + &fsit, git_buf_cstr(&path), 0, NULL, NULL)) < 0 || + (error = git_vector_init(&iter->loose, 8, NULL)) < 0 || + (error = git_buf_sets(&path, GIT_REFS_DIR)) < 0) + goto cleanup; while (!git_iterator_advance(&entry, fsit)) { const char *ref_name; khiter_t pos; + char *ref_dup; git_buf_truncate(&path, strlen(GIT_REFS_DIR)); git_buf_puts(&path, entry->path); @@ -618,9 +616,16 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) ref->flags |= PACKREF_SHADOWED; } - git_vector_insert(&iter->loose, git__strdup(ref_name)); + if (!(ref_dup = git_pool_strdup(&iter->pool, ref_name))) { + error = -1; + goto cleanup; + } + + if ((error = git_vector_insert(&iter->loose, ref_dup)) < 0) + goto cleanup; } +cleanup: git_iterator_free(fsit); git_buf_free(&path); @@ -727,20 +732,26 @@ static int refdb_fs_backend__iterator( iter = git__calloc(1, sizeof(refdb_fs_iter)); GITERR_CHECK_ALLOC(iter); - if (glob != NULL) - iter->glob = git__strdup(glob); + if (git_pool_init(&iter->pool, 1, 0) < 0) + goto fail; + + if (glob != NULL && + (iter->glob = git_pool_strdup(&iter->pool, glob)) == NULL) + goto fail; iter->parent.next = refdb_fs_backend__iterator_next; iter->parent.next_name = refdb_fs_backend__iterator_next_name; iter->parent.free = refdb_fs_backend__iterator_free; - if (iter_load_loose_paths(backend, iter) < 0) { - refdb_fs_backend__iterator_free((git_reference_iterator *)iter); - return -1; - } + if (iter_load_loose_paths(backend, iter) < 0) + goto fail; *out = (git_reference_iterator *)iter; return 0; + +fail: + refdb_fs_backend__iterator_free((git_reference_iterator *)iter); + return -1; } static bool ref_is_available( @@ -792,7 +803,7 @@ static int reference_path_available( return -1; } }); - + return 0; } -- cgit v1.2.1 From 989710d9828ef0f90b494903bd1e1bd8b20a8914 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 22 Jul 2013 11:22:55 -0700 Subject: Fix warning message about mismatched types --- src/fileops.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index db53d4fce..c01ff64db 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -630,13 +630,11 @@ static git_futils_dirs_guess_cb git_futils__dir_guess[GIT_FUTILS_DIR__MAX] = { int git_futils_dirs_global_init(void) { git_futils_dir_t i; - git_buf *path; + const git_buf *path; int error = 0; - for (i = 0; i < GIT_FUTILS_DIR__MAX; i++) { - if ((error = git_futils_dirs_get(&path, i)) < 0) - break; - } + for (i = 0; !error && i < GIT_FUTILS_DIR__MAX; i++) + error = git_futils_dirs_get(&path, i); return error; } -- cgit v1.2.1 From 4cee9b8618b949f55233f2350654d771a0dc2ece Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 22 Jul 2013 11:41:23 -0700 Subject: Update init and clean for revwalk::basic tests The new tests don't always want to use the same fixture data as the old ones so this makes it configurable on a per-test basis. --- tests-clar/revwalk/basic.c | 50 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/tests-clar/revwalk/basic.c b/tests-clar/revwalk/basic.c index 7c2fc000d..cb8fcb9c7 100644 --- a/tests-clar/revwalk/basic.c +++ b/tests-clar/revwalk/basic.c @@ -98,27 +98,46 @@ static int test_walk(git_revwalk *walk, const git_oid *root, return test_walk_only(walk, possible_results, results_count); } -static git_repository *_repo; -static git_revwalk *_walk; +static git_repository *_repo = NULL; +static git_revwalk *_walk = NULL; +static const char *_fixture = NULL; void test_revwalk_basic__initialize(void) { - cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_revwalk_new(&_walk, _repo)); } void test_revwalk_basic__cleanup(void) { git_revwalk_free(_walk); - _walk = NULL; - git_repository_free(_repo); + + if (_fixture) + cl_git_sandbox_cleanup(); + else + git_repository_free(_repo); + + _fixture = NULL; _repo = NULL; + _walk = NULL; +} + +static void revwalk_basic_setup_walk(const char *fixture) +{ + if (fixture) { + _fixture = fixture; + _repo = cl_git_sandbox_init(fixture); + } else { + cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); + } + + cl_git_pass(git_revwalk_new(&_walk, _repo)); } void test_revwalk_basic__sorting_modes(void) { git_oid id; + revwalk_basic_setup_walk(NULL); + git_oid_fromstr(&id, commit_head); cl_git_pass(test_walk(_walk, &id, GIT_SORT_TIME, commit_sorting_time, 1)); @@ -132,6 +151,8 @@ void test_revwalk_basic__glob_heads(void) int i = 0; git_oid oid; + revwalk_basic_setup_walk(NULL); + cl_git_pass(git_revwalk_push_glob(_walk, "heads")); while (git_revwalk_next(&oid, _walk) == 0) { @@ -147,12 +168,9 @@ void test_revwalk_basic__glob_heads_with_invalid(void) int i; git_oid oid; - test_revwalk_basic__cleanup(); + revwalk_basic_setup_walk("testrepo"); - _repo = cl_git_sandbox_init("testrepo"); cl_git_mkfile("testrepo/.git/refs/heads/garbage", "not-a-ref"); - - cl_git_pass(git_revwalk_new(&_walk, _repo)); cl_git_pass(git_revwalk_push_glob(_walk, "heads")); for (i = 0; !git_revwalk_next(&oid, _walk); ++i) @@ -160,8 +178,6 @@ void test_revwalk_basic__glob_heads_with_invalid(void) /* git log --branches --oneline | wc -l => 16 */ cl_assert_equal_i(16, i); - - cl_fixture_cleanup("testrepo"); } void test_revwalk_basic__push_head(void) @@ -169,6 +185,8 @@ void test_revwalk_basic__push_head(void) int i = 0; git_oid oid; + revwalk_basic_setup_walk(NULL); + cl_git_pass(git_revwalk_push_head(_walk)); while (git_revwalk_next(&oid, _walk) == 0) { @@ -184,6 +202,8 @@ void test_revwalk_basic__push_head_hide_ref(void) int i = 0; git_oid oid; + revwalk_basic_setup_walk(NULL); + cl_git_pass(git_revwalk_push_head(_walk)); cl_git_pass(git_revwalk_hide_ref(_walk, "refs/heads/packed-test")); @@ -200,6 +220,8 @@ void test_revwalk_basic__push_head_hide_ref_nobase(void) int i = 0; git_oid oid; + revwalk_basic_setup_walk(NULL); + cl_git_pass(git_revwalk_push_head(_walk)); cl_git_pass(git_revwalk_hide_ref(_walk, "refs/heads/packed")); @@ -215,12 +237,16 @@ void test_revwalk_basic__disallow_non_commit(void) { git_oid oid; + revwalk_basic_setup_walk(NULL); + cl_git_pass(git_oid_fromstr(&oid, "521d87c1ec3aef9824daf6d96cc0ae3710766d91")); cl_git_fail(git_revwalk_push(_walk, &oid)); } void test_revwalk_basic__push_range(void) { + revwalk_basic_setup_walk(NULL); + git_revwalk_reset(_walk); git_revwalk_sorting(_walk, 0); cl_git_pass(git_revwalk_push_range(_walk, "9fd738e~2..9fd738e")); -- cgit v1.2.1 From b4a4cf24a539ce07d86fed6835c98154fb40e723 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 22 Jul 2013 16:07:56 -0700 Subject: Add git_diff_patch_size() API This adds a new API to get the size in bytes of the diffs in a git_diff_patch object. --- include/git2/diff.h | 18 ++++++++++++++++++ src/diff_patch.c | 22 ++++++++++++++++++++-- tests-clar/diff/patch.c | 19 +++++++++++++++---- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/include/git2/diff.h b/include/git2/diff.h index 71a8b72bf..711967501 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -942,6 +942,24 @@ GIT_EXTERN(int) git_diff_patch_get_line_in_hunk( size_t hunk_idx, size_t line_of_hunk); +/** + * Look up size of patch diff data in bytes + * + * This returns the raw size of the patch data. This only includes the + * actual data from the lines of the diff, not the file or hunk headers. + * + * If you pass `include_context` as true (non-zero), this will be the size + * of all of the diff output; if you pass it as false (zero), this will + * only include the actual changed lines (as if `context_lines` was 0). + * + * @param patch A git_diff_patch representing changes to one file + * @param include_context Include context lines in size if non-zero + * @return The number of bytes of data + */ +GIT_EXTERN(size_t) git_diff_patch_size( + git_diff_patch *patch, + int include_context); + /** * Serialize the patch to text via callback. * diff --git a/src/diff_patch.c b/src/diff_patch.c index 1b4adac03..5febc883c 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -42,7 +42,7 @@ struct git_diff_patch { git_array_t(diff_patch_hunk) hunks; git_array_t(diff_patch_line) lines; size_t oldno, newno; - size_t content_size; + size_t content_size, context_size; git_pool flattened; }; @@ -806,6 +806,20 @@ notfound: return diff_error_outofrange(thing); } +size_t git_diff_patch_size(git_diff_patch *patch, int include_context) +{ + size_t out; + + assert(patch); + + out = patch->content_size; + + if (!include_context) + out -= patch->context_size; + + return out; +} + git_diff_list *git_diff_patch__diff(git_diff_patch *patch) { return patch->diff; @@ -934,7 +948,11 @@ static int diff_patch_line_cb( line->len = content_len; line->origin = line_origin; - patch->content_size += content_len; + patch->content_size += content_len + 1; /* +1 for line_origin */ + + if (line_origin == GIT_DIFF_LINE_CONTEXT || + line_origin == GIT_DIFF_LINE_CONTEXT_EOFNL) + patch->context_size += content_len + 1; /* do some bookkeeping so we can provide old/new line numbers */ diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c index 3f14a0de7..51baadf2e 100644 --- a/tests-clar/diff/patch.c +++ b/tests-clar/diff/patch.c @@ -128,6 +128,9 @@ void test_diff_patch__to_string(void) cl_assert_equal_s(expected, text); + cl_assert_equal_sz(31, git_diff_patch_size(patch, 0)); + cl_assert_equal_sz(31, git_diff_patch_size(patch, 1)); + git__free(text); git_diff_patch_free(patch); git_diff_list_free(diff); @@ -409,6 +412,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) static void check_single_patch_stats( git_repository *repo, size_t hunks, size_t adds, size_t dels, size_t ctxt, + size_t size_with_context, size_t size_without_context, const char *expected) { git_diff_list *diff; @@ -439,6 +443,13 @@ static void check_single_patch_stats( git__free(text); } + if (size_with_context) + cl_assert_equal_sz( + size_with_context, git_diff_patch_size(patch, 1)); + if (size_without_context) + cl_assert_equal_sz( + size_without_context, git_diff_patch_size(patch, 0)); + /* walk lines in hunk with basic sanity checks */ for (; hunks > 0; --hunks) { size_t i, max_i; @@ -495,14 +506,14 @@ void test_diff_patch__line_counts_with_eofnl(void) git_buf_consume(&content, end); cl_git_rewritefile("renames/songof7cities.txt", content.ptr); - check_single_patch_stats(g_repo, 1, 0, 1, 3, NULL); + check_single_patch_stats(g_repo, 1, 0, 1, 3, 0, 0, NULL); /* remove trailing whitespace */ git_buf_rtrim(&content); cl_git_rewritefile("renames/songof7cities.txt", content.ptr); - check_single_patch_stats(g_repo, 2, 1, 2, 6, NULL); + check_single_patch_stats(g_repo, 2, 1, 2, 6, 0, 0, NULL); /* add trailing whitespace */ @@ -514,7 +525,7 @@ void test_diff_patch__line_counts_with_eofnl(void) cl_git_pass(git_buf_putc(&content, '\n')); cl_git_rewritefile("renames/songof7cities.txt", content.ptr); - check_single_patch_stats(g_repo, 1, 1, 1, 3, NULL); + check_single_patch_stats(g_repo, 1, 1, 1, 3, 0, 0, NULL); /* no trailing whitespace as context line */ @@ -537,7 +548,7 @@ void test_diff_patch__line_counts_with_eofnl(void) cl_git_rewritefile("renames/songof7cities.txt", content.ptr); check_single_patch_stats( - g_repo, 1, 1, 1, 6, + g_repo, 1, 1, 1, 6, 349, 115, /* below is pasted output of 'git diff' with fn context removed */ "diff --git a/songof7cities.txt b/songof7cities.txt\n" "index 378a7d9..3d0154e 100644\n" -- cgit v1.2.1 From c05a55b056509d1146ab55ab1351298789f00751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 23 Jul 2013 09:40:19 +0200 Subject: Clean up some documentation clang's docparser highlighted these. --- include/git2/notes.h | 4 ++-- include/git2/pack.h | 4 ++-- include/git2/sys/index.h | 2 -- include/git2/sys/refs.h | 4 ++-- include/git2/transport.h | 2 +- src/fileops.h | 8 ++++---- src/path.h | 2 -- src/pqueue.h | 6 ++---- 8 files changed, 13 insertions(+), 19 deletions(-) diff --git a/include/git2/notes.h b/include/git2/notes.h index 7382904ad..76361633b 100644 --- a/include/git2/notes.h +++ b/include/git2/notes.h @@ -99,7 +99,7 @@ GIT_EXTERN(int) git_note_read( /** * Get the note message * - * @param note + * @param note the note * @return the note message */ GIT_EXTERN(const char *) git_note_message(const git_note *note); @@ -108,7 +108,7 @@ GIT_EXTERN(const char *) git_note_message(const git_note *note); /** * Get the note object OID * - * @param note + * @param note the note * @return the note object OID */ GIT_EXTERN(const git_oid *) git_note_oid(const git_note *note); diff --git a/include/git2/pack.h b/include/git2/pack.h index cc1f48add..976e39cb4 100644 --- a/include/git2/pack.h +++ b/include/git2/pack.h @@ -137,7 +137,7 @@ GIT_EXTERN(int) git_packbuilder_foreach(git_packbuilder *pb, git_packbuilder_for * Get the total number of objects the packbuilder will write out * * @param pb the packbuilder - * @return + * @return the number of objects in the packfile */ GIT_EXTERN(uint32_t) git_packbuilder_object_count(git_packbuilder *pb); @@ -145,7 +145,7 @@ GIT_EXTERN(uint32_t) git_packbuilder_object_count(git_packbuilder *pb); * Get the number of objects the packbuilder has already written out * * @param pb the packbuilder - * @return + * @return the number of objects which have already been written */ GIT_EXTERN(uint32_t) git_packbuilder_written(git_packbuilder *pb); diff --git a/include/git2/sys/index.h b/include/git2/sys/index.h index a32e07036..1a06a4df1 100644 --- a/include/git2/sys/index.h +++ b/include/git2/sys/index.h @@ -72,7 +72,6 @@ GIT_EXTERN(int) git_index_name_add(git_index *index, * Remove all filename conflict entries. * * @param index an existing index object - * @return 0 or an error code */ GIT_EXTERN(void) git_index_name_clear(git_index *index); @@ -168,7 +167,6 @@ GIT_EXTERN(int) git_index_reuc_remove(git_index *index, size_t n); * Remove all resolve undo entries from the index * * @param index an existing index object - * @return 0 or an error code */ GIT_EXTERN(void) git_index_reuc_clear(git_index *index); diff --git a/include/git2/sys/refs.h b/include/git2/sys/refs.h index 85963258c..dd95ca12c 100644 --- a/include/git2/sys/refs.h +++ b/include/git2/sys/refs.h @@ -16,7 +16,7 @@ * * @param name the reference name * @param oid the object id for a direct reference - * @param symbolic the target for a symbolic reference + * @param peel the first non-tag object's OID, or NULL * @return the created git_reference or NULL on error */ GIT_EXTERN(git_reference *) git_reference__alloc( @@ -28,7 +28,7 @@ GIT_EXTERN(git_reference *) git_reference__alloc( * Create a new symbolic reference. * * @param name the reference name - * @param symbolic the target for a symbolic reference + * @param target the target for a symbolic reference * @return the created git_reference or NULL on error */ GIT_EXTERN(git_reference *) git_reference__alloc_symbolic( diff --git a/include/git2/transport.h b/include/git2/transport.h index 21061fc78..1cc200eb4 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -110,7 +110,7 @@ GIT_EXTERN(int) git_cred_ssh_keyfile_passphrase_new( * @param out The newly created credential object. * @param publickey The bytes of the public key. * @param publickey_len The length of the public key in bytes. - * @param sign_callback The callback method for authenticating. + * @param sign_fn The callback method for authenticating. * @param sign_data The abstract data sent to the sign_callback method. * @return 0 for success or an error code for failure */ diff --git a/src/fileops.h b/src/fileops.h index d23ebaffb..5adedfc57 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -244,7 +244,7 @@ extern mode_t git_futils_canonical_mode(mode_t raw_mode); * @param out buffer to populate with the mapping information. * @param fd open descriptor to configure the mapping from. * @param begin first byte to map, this should be page aligned. - * @param end number of bytes to map. + * @param len number of bytes to map. * @return * - 0 on success; * - -1 on error. @@ -278,7 +278,7 @@ extern void git_futils_mmap_free(git_map *map); /** * Find a "global" file (i.e. one in a user's home directory). * - * @param pathbuf buffer to write the full path into + * @param path buffer to write the full path into * @param filename name of file to find in the home directory * @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error */ @@ -287,7 +287,7 @@ extern int git_futils_find_global_file(git_buf *path, const char *filename); /** * Find an "XDG" file (i.e. one in user's XDG config path). * - * @param pathbuf buffer to write the full path into + * @param path buffer to write the full path into * @param filename name of file to find in the home directory * @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error */ @@ -296,7 +296,7 @@ extern int git_futils_find_xdg_file(git_buf *path, const char *filename); /** * Find a "system" file (i.e. one shared for all users of the system). * - * @param pathbuf buffer to write the full path into + * @param path buffer to write the full path into * @param filename name of file to find in the home directory * @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error */ diff --git a/src/path.h b/src/path.h index ead4fa338..b2899e97f 100644 --- a/src/path.h +++ b/src/path.h @@ -175,7 +175,6 @@ extern bool git_path_contains(git_buf *dir, const char *item); * * @param parent Directory path that might contain subdir * @param subdir Subdirectory name to look for in parent - * @param append_if_exists If true, then subdir will be appended to the parent path if it does exist * @return true if subdirectory exists, false otherwise. */ extern bool git_path_contains_dir(git_buf *parent, const char *subdir); @@ -185,7 +184,6 @@ extern bool git_path_contains_dir(git_buf *parent, const char *subdir); * * @param dir Directory path that might contain file * @param file File name to look for in parent - * @param append_if_exists If true, then file will be appended to the path if it does exist * @return true if file exists, false otherwise. */ extern bool git_path_contains_file(git_buf *dir, const char *file); diff --git a/src/pqueue.h b/src/pqueue.h index ed7139285..9061f8279 100644 --- a/src/pqueue.h +++ b/src/pqueue.h @@ -48,7 +48,7 @@ typedef struct { * should be preallocated * @param cmppri the callback function to compare two nodes of the queue * - * @Return the handle or NULL for insufficent memory + * @return the handle or NULL for insufficent memory */ int git_pqueue_init(git_pqueue *q, size_t n, git_pqueue_cmp cmppri); @@ -83,8 +83,7 @@ int git_pqueue_insert(git_pqueue *q, void *d); /** * pop the highest-ranking item from the queue. - * @param p the queue - * @param d where to copy the entry to + * @param q the queue * @return NULL on error, otherwise the entry */ void *git_pqueue_pop(git_pqueue *q); @@ -93,7 +92,6 @@ void *git_pqueue_pop(git_pqueue *q); /** * access highest-ranking item without removing it. * @param q the queue - * @param d the entry * @return NULL on error, otherwise the entry */ void *git_pqueue_peek(git_pqueue *q); -- cgit v1.2.1 From 64061d4a14f77fdcf6ecc038ea6e9b02f14e03a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 23 Jul 2013 10:51:14 +0200 Subject: remote: fix git_remote_download() documentation The description of what the function does hasn't been true for quite a while. Change it to reflect the way it currently works. While here, remove an even older comment about missing features that have been implemented. --- include/git2/remote.h | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 13b04367c..fa8b378c6 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -25,13 +25,6 @@ GIT_BEGIN_DECL typedef int (*git_remote_rename_problem_cb)(const char *problematic_refspec, void *payload); -/* - * TODO: This functions still need to be implemented: - * - _listcb/_foreach - * - _add - * - _rename - * - _del (needs support from config) - */ /** * Add a remote with the default fetch refspec to the repository's configuration. This @@ -255,13 +248,14 @@ GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction); GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload); /** - * Download the packfile + * Download and index the packfile + * + * Connect to the remote if it hasn't been done yet, negotiate with + * the remote git which objects are missing, download and index the + * packfile. * - * Negotiate what objects should be downloaded and download the - * packfile with those objects. The packfile is downloaded with a - * temporary filename, as it's final name is not known yet. If there - * was no packfile needed (all the objects were available locally), - * filename will be NULL and the function will return success. + * The .idx file will be created and both it and the packfile with be + * renamed to their final name. * * @param remote the remote to download from * @param progress_cb function to call with progress information. Be aware that -- cgit v1.2.1 From 197b8966dba18770e4b77a17173c8f354ac175e3 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 23 Jul 2013 14:34:31 -0700 Subject: Add hunk/file headers to git_diff_patch_size This allows git_diff_patch_size to account for hunk headers and file headers in the returned size. This required some refactoring of the code that is used to print file headers so that it could be invoked by the git_diff_patch_size API. Also this increases the test coverage and fixes an off-by-one bug in the size calculation when newline changes happen at the end of the file. --- include/git2/diff.h | 8 +++-- src/diff.h | 7 +++++ src/diff_patch.c | 49 +++++++++++++++++++++++------- src/diff_print.c | 79 ++++++++++++++++++++++++++----------------------- tests-clar/diff/patch.c | 66 +++++++++++++++++++++++------------------ 5 files changed, 130 insertions(+), 79 deletions(-) diff --git a/include/git2/diff.h b/include/git2/diff.h index 711967501..269eb773d 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -391,7 +391,7 @@ typedef enum { */ GIT_DIFF_LINE_FILE_HDR = 'F', GIT_DIFF_LINE_HUNK_HDR = 'H', - GIT_DIFF_LINE_BINARY = 'B' + GIT_DIFF_LINE_BINARY = 'B' /**< Deprecated, will not be returned */ } git_diff_line_t; /** @@ -954,11 +954,15 @@ GIT_EXTERN(int) git_diff_patch_get_line_in_hunk( * * @param patch A git_diff_patch representing changes to one file * @param include_context Include context lines in size if non-zero + * @param include_hunk_headers Include hunk header lines if non-zero + * @param include_file_headers Include file header lines if non-zero * @return The number of bytes of data */ GIT_EXTERN(size_t) git_diff_patch_size( git_diff_patch *patch, - int include_context); + int include_context, + int include_hunk_headers, + int include_file_headers); /** * Serialize the patch to text via callback. diff --git a/src/diff.h b/src/diff.h index d09a130bc..ff480324f 100644 --- a/src/diff.h +++ b/src/diff.h @@ -81,6 +81,13 @@ extern const char *git_diff_delta__path(const git_diff_delta *delta); extern bool git_diff_delta__should_skip( const git_diff_options *opts, const git_diff_delta *delta); +extern int git_diff_delta__format_file_header( + git_buf *out, + const git_diff_delta *delta, + const char *oldpfx, + const char *newpfx, + int oid_strlen); + extern int git_diff__oid_for_file( git_repository *, const char *, uint16_t, git_off_t, git_oid *); diff --git a/src/diff_patch.c b/src/diff_patch.c index 5febc883c..6f8ea2d3d 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -42,7 +42,7 @@ struct git_diff_patch { git_array_t(diff_patch_hunk) hunks; git_array_t(diff_patch_line) lines; size_t oldno, newno; - size_t content_size, context_size; + size_t content_size, context_size, header_size; git_pool flattened; }; @@ -806,7 +806,11 @@ notfound: return diff_error_outofrange(thing); } -size_t git_diff_patch_size(git_diff_patch *patch, int include_context) +size_t git_diff_patch_size( + git_diff_patch *patch, + int include_context, + int include_hunk_headers, + int include_file_headers) { size_t out; @@ -817,6 +821,21 @@ size_t git_diff_patch_size(git_diff_patch *patch, int include_context) if (!include_context) out -= patch->context_size; + if (include_hunk_headers) + out += patch->header_size; + + if (include_file_headers) { + git_buf file_header = GIT_BUF_INIT; + + if (git_diff_delta__format_file_header( + &file_header, patch->delta, NULL, NULL, 0) < 0) + giterr_clear(); + else + out += git_buf_len(&file_header); + + git_buf_free(&file_header); + } + return out; } @@ -914,6 +933,8 @@ static int diff_patch_hunk_cb( hunk->header[header_len] = '\0'; hunk->header_len = header_len; + patch->header_size += header_len; + hunk->line_start = git_array_size(patch->lines); hunk->line_count = 0; @@ -934,6 +955,7 @@ static int diff_patch_line_cb( git_diff_patch *patch = payload; diff_patch_hunk *hunk; diff_patch_line *line; + const char *content_end = content + content_len; GIT_UNUSED(delta); GIT_UNUSED(range); @@ -948,38 +970,43 @@ static int diff_patch_line_cb( line->len = content_len; line->origin = line_origin; - patch->content_size += content_len + 1; /* +1 for line_origin */ - - if (line_origin == GIT_DIFF_LINE_CONTEXT || - line_origin == GIT_DIFF_LINE_CONTEXT_EOFNL) - patch->context_size += content_len + 1; - /* do some bookkeeping so we can provide old/new line numbers */ - for (line->lines = 0; content_len > 0; --content_len) { + line->lines = 0; + while (content < content_end) if (*content++ == '\n') ++line->lines; - } + + patch->content_size += content_len; switch (line_origin) { case GIT_DIFF_LINE_ADDITION: + patch->content_size += 1; case GIT_DIFF_LINE_DEL_EOFNL: line->oldno = -1; line->newno = patch->newno; patch->newno += line->lines; break; case GIT_DIFF_LINE_DELETION: + patch->content_size += 1; case GIT_DIFF_LINE_ADD_EOFNL: line->oldno = patch->oldno; line->newno = -1; patch->oldno += line->lines; break; - default: + case GIT_DIFF_LINE_CONTEXT: + patch->content_size += 1; + patch->context_size += 1; + case GIT_DIFF_LINE_CONTEXT_EOFNL: + patch->context_size += content_len; line->oldno = patch->oldno; line->newno = patch->newno; patch->oldno += line->lines; patch->newno += line->lines; break; + default: + assert(false); + break; } hunk->line_count++; diff --git a/src/diff_print.c b/src/diff_print.c index 0de548813..cdb813176 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -198,13 +198,13 @@ int git_diff_print_raw( return error; } -static int diff_print_oid_range(diff_print_info *pi, const git_diff_delta *delta) +static int diff_print_oid_range( + git_buf *out, const git_diff_delta *delta, int oid_strlen) { - git_buf *out = pi->buf; char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1]; - git_oid_tostr(start_oid, pi->oid_strlen, &delta->old_file.oid); - git_oid_tostr(end_oid, pi->oid_strlen, &delta->new_file.oid); + git_oid_tostr(start_oid, oid_strlen, &delta->old_file.oid); + git_oid_tostr(end_oid, oid_strlen, &delta->new_file.oid); /* TODO: Match git diff more closely */ if (delta->old_file.mode == delta->new_file.mode) { @@ -228,35 +228,29 @@ static int diff_print_oid_range(diff_print_info *pi, const git_diff_delta *delta return 0; } -static int diff_print_patch_file( - const git_diff_delta *delta, float progress, void *data) +int git_diff_delta__format_file_header( + git_buf *out, + const git_diff_delta *delta, + const char *oldpfx, + const char *newpfx, + int oid_strlen) { - diff_print_info *pi = data; - const char *oldpfx = pi->diff ? pi->diff->opts.old_prefix : NULL; const char *oldpath = delta->old_file.path; - const char *newpfx = pi->diff ? pi->diff->opts.new_prefix : NULL; const char *newpath = delta->new_file.path; - uint32_t opts_flags = pi->diff ? pi->diff->opts.flags : GIT_DIFF_NORMAL; - - GIT_UNUSED(progress); - - if (S_ISDIR(delta->new_file.mode) || - delta->status == GIT_DELTA_UNMODIFIED || - delta->status == GIT_DELTA_IGNORED || - (delta->status == GIT_DELTA_UNTRACKED && - (opts_flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) == 0)) - return 0; if (!oldpfx) oldpfx = DIFF_OLD_PREFIX_DEFAULT; if (!newpfx) newpfx = DIFF_NEW_PREFIX_DEFAULT; + if (!oid_strlen) + oid_strlen = GIT_ABBREV_DEFAULT + 1; - git_buf_clear(pi->buf); - git_buf_printf(pi->buf, "diff --git %s%s %s%s\n", - oldpfx, delta->old_file.path, newpfx, delta->new_file.path); + git_buf_clear(out); + + git_buf_printf(out, "diff --git %s%s %s%s\n", + oldpfx, oldpath, newpfx, newpath); - if (diff_print_oid_range(pi, delta) < 0) + if (diff_print_oid_range(out, delta, oid_strlen) < 0) return -1; if (git_oid_iszero(&delta->old_file.oid)) { @@ -269,28 +263,39 @@ static int diff_print_patch_file( } if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) { - git_buf_printf(pi->buf, "--- %s%s\n", oldpfx, oldpath); - git_buf_printf(pi->buf, "+++ %s%s\n", newpfx, newpath); + git_buf_printf(out, "--- %s%s\n", oldpfx, oldpath); + git_buf_printf(out, "+++ %s%s\n", newpfx, newpath); + } else { + git_buf_printf( + out, "Binary files %s%s and %s%s differ\n", + oldpfx, oldpath, newpfx, newpath); } - if (git_buf_oom(pi->buf)) - return -1; + return git_buf_oom(out) ? -1 : 0; +} - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR, - git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) - return callback_error(); +static int diff_print_patch_file( + const git_diff_delta *delta, float progress, void *data) +{ + diff_print_info *pi = data; + const char *oldpfx = pi->diff ? pi->diff->opts.old_prefix : NULL; + const char *newpfx = pi->diff ? pi->diff->opts.new_prefix : NULL; + uint32_t opts_flags = pi->diff ? pi->diff->opts.flags : GIT_DIFF_NORMAL; - if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) + GIT_UNUSED(progress); + + if (S_ISDIR(delta->new_file.mode) || + delta->status == GIT_DELTA_UNMODIFIED || + delta->status == GIT_DELTA_IGNORED || + (delta->status == GIT_DELTA_UNTRACKED && + (opts_flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) == 0)) return 0; - git_buf_clear(pi->buf); - git_buf_printf( - pi->buf, "Binary files %s%s and %s%s differ\n", - oldpfx, oldpath, newpfx, newpath); - if (git_buf_oom(pi->buf)) + if (git_diff_delta__format_file_header( + pi->buf, delta, oldpfx, newpfx, pi->oid_strlen) < 0) return -1; - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_BINARY, + if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR, git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) return callback_error(); diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c index 51baadf2e..6a33fa990 100644 --- a/tests-clar/diff/patch.c +++ b/tests-clar/diff/patch.c @@ -128,8 +128,10 @@ void test_diff_patch__to_string(void) cl_assert_equal_s(expected, text); - cl_assert_equal_sz(31, git_diff_patch_size(patch, 0)); - cl_assert_equal_sz(31, git_diff_patch_size(patch, 1)); + cl_assert_equal_sz(31, git_diff_patch_size(patch, 0, 0, 0)); + cl_assert_equal_sz(31, git_diff_patch_size(patch, 1, 0, 0)); + cl_assert_equal_sz(31 + 16, git_diff_patch_size(patch, 1, 1, 0)); + cl_assert_equal_sz(strlen(expected), git_diff_patch_size(patch, 1, 1, 1)); git__free(text); git_diff_patch_free(patch); @@ -411,8 +413,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) static void check_single_patch_stats( git_repository *repo, size_t hunks, - size_t adds, size_t dels, size_t ctxt, - size_t size_with_context, size_t size_without_context, + size_t adds, size_t dels, size_t ctxt, size_t *sizes, const char *expected) { git_diff_list *diff; @@ -441,14 +442,19 @@ static void check_single_patch_stats( cl_git_pass(git_diff_patch_to_str(&text, patch)); cl_assert_equal_s(expected, text); git__free(text); - } - if (size_with_context) - cl_assert_equal_sz( - size_with_context, git_diff_patch_size(patch, 1)); - if (size_without_context) cl_assert_equal_sz( - size_without_context, git_diff_patch_size(patch, 0)); + strlen(expected), git_diff_patch_size(patch, 1, 1, 1)); + } + + if (sizes) { + if (sizes[0]) + cl_assert_equal_sz(sizes[0], git_diff_patch_size(patch, 0, 0, 0)); + if (sizes[1]) + cl_assert_equal_sz(sizes[1], git_diff_patch_size(patch, 1, 0, 0)); + if (sizes[2]) + cl_assert_equal_sz(sizes[2], git_diff_patch_size(patch, 1, 1, 0)); + } /* walk lines in hunk with basic sanity checks */ for (; hunks > 0; --hunks) { @@ -492,6 +498,23 @@ void test_diff_patch__line_counts_with_eofnl(void) git_buf content = GIT_BUF_INIT; const char *end; git_index *index; + const char *expected = + /* below is pasted output of 'git diff' with fn context removed */ + "diff --git a/songof7cities.txt b/songof7cities.txt\n" + "index 378a7d9..3d0154e 100644\n" + "--- a/songof7cities.txt\n" + "+++ b/songof7cities.txt\n" + "@@ -42,7 +42,7 @@ With peoples undefeated of the dark, enduring blood.\n" + " \n" + " To the sound of trumpets shall their seed restore my Cities\n" + " Wealthy and well-weaponed, that once more may I behold\n" + "-All the world go softly when it walks before my Cities,\n" + "+#All the world go softly when it walks before my Cities,\n" + " And the horses and the chariots fleeing from them as of old!\n" + " \n" + " -- Rudyard Kipling\n" + "\\ No newline at end of file\n"; + size_t expected_sizes[3] = { 115, 119 + 115 + 114, 119 + 115 + 114 + 71 }; g_repo = cl_git_sandbox_init("renames"); @@ -506,14 +529,14 @@ void test_diff_patch__line_counts_with_eofnl(void) git_buf_consume(&content, end); cl_git_rewritefile("renames/songof7cities.txt", content.ptr); - check_single_patch_stats(g_repo, 1, 0, 1, 3, 0, 0, NULL); + check_single_patch_stats(g_repo, 1, 0, 1, 3, NULL, NULL); /* remove trailing whitespace */ git_buf_rtrim(&content); cl_git_rewritefile("renames/songof7cities.txt", content.ptr); - check_single_patch_stats(g_repo, 2, 1, 2, 6, 0, 0, NULL); + check_single_patch_stats(g_repo, 2, 1, 2, 6, NULL, NULL); /* add trailing whitespace */ @@ -525,7 +548,7 @@ void test_diff_patch__line_counts_with_eofnl(void) cl_git_pass(git_buf_putc(&content, '\n')); cl_git_rewritefile("renames/songof7cities.txt", content.ptr); - check_single_patch_stats(g_repo, 1, 1, 1, 3, 0, 0, NULL); + check_single_patch_stats(g_repo, 1, 1, 1, 3, NULL, NULL); /* no trailing whitespace as context line */ @@ -548,22 +571,7 @@ void test_diff_patch__line_counts_with_eofnl(void) cl_git_rewritefile("renames/songof7cities.txt", content.ptr); check_single_patch_stats( - g_repo, 1, 1, 1, 6, 349, 115, - /* below is pasted output of 'git diff' with fn context removed */ - "diff --git a/songof7cities.txt b/songof7cities.txt\n" - "index 378a7d9..3d0154e 100644\n" - "--- a/songof7cities.txt\n" - "+++ b/songof7cities.txt\n" - "@@ -42,7 +42,7 @@ With peoples undefeated of the dark, enduring blood.\n" - " \n" - " To the sound of trumpets shall their seed restore my Cities\n" - " Wealthy and well-weaponed, that once more may I behold\n" - "-All the world go softly when it walks before my Cities,\n" - "+#All the world go softly when it walks before my Cities,\n" - " And the horses and the chariots fleeing from them as of old!\n" - " \n" - " -- Rudyard Kipling\n" - "\\ No newline at end of file\n"); + g_repo, 1, 1, 1, 6, expected_sizes, expected); git_buf_free(&content); git_config_free(cfg); -- cgit v1.2.1 From df40f3981c312b03415e388663176b2a8315221a Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 23 Jul 2013 15:18:28 -0700 Subject: Make compact output more like core Git --- src/diff_print.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/diff_print.c b/src/diff_print.c index cdb813176..f427baa36 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -98,12 +98,12 @@ static int diff_print_one_compact( if (delta->old_file.path != delta->new_file.path && strcomp(delta->old_file.path,delta->new_file.path) != 0) - git_buf_printf(out, "%c\t%s%c -> %s%c\n", code, + git_buf_printf(out, "%c\t%s%c %s%c\n", code, delta->old_file.path, old_suffix, delta->new_file.path, new_suffix); else if (delta->old_file.mode != delta->new_file.mode && delta->old_file.mode != 0 && delta->new_file.mode != 0) - git_buf_printf(out, "%c\t%s%c (%o -> %o)\n", code, - delta->old_file.path, new_suffix, delta->old_file.mode, delta->new_file.mode); + git_buf_printf(out, "%c\t%s%c %s%c\n", code, + delta->old_file.path, old_suffix, delta->new_file.path, new_suffix); else if (old_suffix != ' ') git_buf_printf(out, "%c\t%s%c\n", code, delta->old_file.path, old_suffix); else -- cgit v1.2.1 From eb1c1707ab6a399734d9083152c05516af052412 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 23 Jul 2013 15:45:58 -0700 Subject: Restore GIT_DIFF_LINE_BINARY usage This restores the usage of GIT_DIFF_LINE_BINARY for the diff output line that reads "Binary files x and y differ" so that it can be optionally colorized independently of the file header. --- include/git2/diff.h | 2 +- src/diff_print.c | 65 +++++++++++++++++++++++++++++++++++------------------ 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/include/git2/diff.h b/include/git2/diff.h index 269eb773d..c989ba4ee 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -391,7 +391,7 @@ typedef enum { */ GIT_DIFF_LINE_FILE_HDR = 'F', GIT_DIFF_LINE_HUNK_HDR = 'H', - GIT_DIFF_LINE_BINARY = 'B' /**< Deprecated, will not be returned */ + GIT_DIFF_LINE_BINARY = 'B' /**< For "Binary files x and y differ" */ } git_diff_line_t; /** diff --git a/src/diff_print.c b/src/diff_print.c index f427baa36..4ddd72443 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -228,16 +228,35 @@ static int diff_print_oid_range( return 0; } -int git_diff_delta__format_file_header( +static int diff_delta_format_with_paths( git_buf *out, const git_diff_delta *delta, const char *oldpfx, const char *newpfx, - int oid_strlen) + const char *template) { const char *oldpath = delta->old_file.path; const char *newpath = delta->new_file.path; + if (git_oid_iszero(&delta->old_file.oid)) { + oldpfx = ""; + oldpath = "/dev/null"; + } + if (git_oid_iszero(&delta->new_file.oid)) { + newpfx = ""; + newpath = "/dev/null"; + } + + return git_buf_printf(out, template, oldpfx, oldpath, newpfx, newpath); +} + +int git_diff_delta__format_file_header( + git_buf *out, + const git_diff_delta *delta, + const char *oldpfx, + const char *newpfx, + int oid_strlen) +{ if (!oldpfx) oldpfx = DIFF_OLD_PREFIX_DEFAULT; if (!newpfx) @@ -248,28 +267,14 @@ int git_diff_delta__format_file_header( git_buf_clear(out); git_buf_printf(out, "diff --git %s%s %s%s\n", - oldpfx, oldpath, newpfx, newpath); + oldpfx, delta->old_file.path, newpfx, delta->new_file.path); if (diff_print_oid_range(out, delta, oid_strlen) < 0) return -1; - if (git_oid_iszero(&delta->old_file.oid)) { - oldpfx = ""; - oldpath = "/dev/null"; - } - if (git_oid_iszero(&delta->new_file.oid)) { - newpfx = ""; - newpath = "/dev/null"; - } - - if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) { - git_buf_printf(out, "--- %s%s\n", oldpfx, oldpath); - git_buf_printf(out, "+++ %s%s\n", newpfx, newpath); - } else { - git_buf_printf( - out, "Binary files %s%s and %s%s differ\n", - oldpfx, oldpath, newpfx, newpath); - } + if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) + diff_delta_format_with_paths( + out, delta, oldpfx, newpfx, "--- %s%s\n+++ %s%s\n"); return git_buf_oom(out) ? -1 : 0; } @@ -278,8 +283,10 @@ static int diff_print_patch_file( const git_diff_delta *delta, float progress, void *data) { diff_print_info *pi = data; - const char *oldpfx = pi->diff ? pi->diff->opts.old_prefix : NULL; - const char *newpfx = pi->diff ? pi->diff->opts.new_prefix : NULL; + const char *oldpfx = + pi->diff ? pi->diff->opts.old_prefix : DIFF_OLD_PREFIX_DEFAULT; + const char *newpfx = + pi->diff ? pi->diff->opts.new_prefix : DIFF_NEW_PREFIX_DEFAULT; uint32_t opts_flags = pi->diff ? pi->diff->opts.flags : GIT_DIFF_NORMAL; GIT_UNUSED(progress); @@ -299,6 +306,20 @@ static int diff_print_patch_file( git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) return callback_error(); + if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) + return 0; + + git_buf_clear(pi->buf); + + if (diff_delta_format_with_paths( + pi->buf, delta, oldpfx, newpfx, + "Binary files %s%s and %s%s differ\n") < 0) + return -1; + + if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_BINARY, + git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) + return callback_error(); + return 0; } -- cgit v1.2.1 From 39a1a66242a480b880032f5a6a4e31ee77414d4c Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 24 Jul 2013 13:09:07 -0700 Subject: Don't unload diff data unless loaded --- src/diff_file.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/diff_file.c b/src/diff_file.c index 9d06daafa..19bcf2d45 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -417,6 +417,9 @@ int git_diff_file_content__load(git_diff_file_content *fc) void git_diff_file_content__unload(git_diff_file_content *fc) { + if ((fc->flags & GIT_DIFF_FLAG__LOADED) == 0) + return; + if (fc->flags & GIT_DIFF_FLAG__FREE_DATA) { git__free(fc->map.data); fc->map.data = ""; -- cgit v1.2.1 From 69c66b554e1072d8b6c63366834e15310fecaea7 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 24 Jul 2013 13:09:33 -0700 Subject: Don't do text diff unless content will be used --- src/diff_patch.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/diff_patch.c b/src/diff_patch.c index 1b4adac03..02a45cb1a 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -230,6 +230,10 @@ static int diff_patch_generate(git_diff_patch *patch, git_diff_output *output) if ((patch->flags & GIT_DIFF_PATCH_DIFFED) != 0) return 0; + /* if we are not looking at the hunks and lines, don't do the diff */ + if (!output->hunk_cb && !output->data_cb) + return 0; + if ((patch->flags & GIT_DIFF_PATCH_LOADED) == 0 && (error = diff_patch_load(patch, output)) < 0) return error; -- cgit v1.2.1 From 18e9efc425bd617655782188056fe43ecdc673e4 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 24 Jul 2013 13:10:16 -0700 Subject: Don't check rename if file size difference is huge --- src/diff_tform.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/diff_tform.c b/src/diff_tform.c index ac5356a8c..ab43a3a14 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -446,6 +446,8 @@ static int similarity_calc( } blobsize = git_blob_rawsize(blob); + if (!file->size) + file->size = blobsize; if (!git__is_sizet(blobsize)) /* ? what to do ? */ blobsize = (size_t)-1; @@ -510,6 +512,13 @@ static int similarity_measure( return 0; } + /* check if file sizes too small or nowhere near each other */ + if (a_file->size > 127 && + b_file->size > 127 && + (a_file->size > (b_file->size << 4) || + b_file->size > (a_file->size << 4))) + return 0; + /* update signature cache if needed */ if (!cache[a_idx] && similarity_calc(diff, opts, a_idx, cache) < 0) return -1; -- cgit v1.2.1 From 427cc255dffc1a44f1e9a289067012370f3cc38d Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 24 Jul 2013 13:11:11 -0700 Subject: Use local variables in hash calc to avoid aliasing --- src/hashsig.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/hashsig.c b/src/hashsig.c index ab8d8b3f0..a11c4bee7 100644 --- a/src/hashsig.c +++ b/src/hashsig.c @@ -43,8 +43,8 @@ struct git_hashsig { int considered; }; -#define HEAP_LCHILD_OF(I) (((I)*2)+1) -#define HEAP_RCHILD_OF(I) (((I)*2)+2) +#define HEAP_LCHILD_OF(I) (((I)<<1)+1) +#define HEAP_RCHILD_OF(I) (((I)<<1)+2) #define HEAP_PARENT_OF(I) (((I)-1)>>1) static void hashsig_heap_init(hashsig_heap *h, hashsig_cmp cmp) @@ -152,8 +152,9 @@ static void hashsig_initial_window( hashsig_in_progress *prog) { hashsig_state state, shift_n; - int win_len; + int win_len, saw_lf = prog->saw_lf; const char *scan, *end; + char *window = &prog->window[0]; /* init until we have processed at least HASHSIG_HASH_WINDOW data */ @@ -170,7 +171,7 @@ static void hashsig_initial_window( while (scan < end && win_len < HASHSIG_HASH_WINDOW) { char ch = *scan++; - if (!hashsig_include_char(ch, sig->opt, &prog->saw_lf)) + if (!hashsig_include_char(ch, sig->opt, &saw_lf)) continue; state = (state * HASHSIG_HASH_SHIFT + ch) & HASHSIG_HASH_MASK; @@ -180,7 +181,7 @@ static void hashsig_initial_window( else shift_n = (shift_n * HASHSIG_HASH_SHIFT) & HASHSIG_HASH_MASK; - prog->window[win_len++] = ch; + window[win_len++] = ch; } /* insert initial hash if we just finished */ @@ -194,6 +195,7 @@ static void hashsig_initial_window( prog->state = state; prog->win_len = win_len; prog->shift_n = shift_n; + prog->saw_lf = saw_lf; *data = scan; } @@ -206,22 +208,26 @@ static int hashsig_add_hashes( { const char *scan = data, *end = data + size; hashsig_state state, shift_n, rmv; + int win_pos, saw_lf; + char *window = &prog->window[0]; if (prog->win_len < HASHSIG_HASH_WINDOW) hashsig_initial_window(sig, &scan, size, prog); state = prog->state; shift_n = prog->shift_n; + saw_lf = prog->saw_lf; + win_pos = prog->win_pos; /* advance window, adding new chars and removing old */ for (; scan < end; ++scan) { char ch = *scan; - if (!hashsig_include_char(ch, sig->opt, &prog->saw_lf)) + if (!hashsig_include_char(ch, sig->opt, &saw_lf)) continue; - rmv = shift_n * prog->window[prog->win_pos]; + rmv = shift_n * window[win_pos]; state = (state - rmv) & HASHSIG_HASH_MASK; state = (state * HASHSIG_HASH_SHIFT) & HASHSIG_HASH_MASK; @@ -231,11 +237,13 @@ static int hashsig_add_hashes( hashsig_heap_insert(&sig->maxs, (hashsig_t)state); sig->considered++; - prog->window[prog->win_pos] = ch; - prog->win_pos = (prog->win_pos + 1) % HASHSIG_HASH_WINDOW; + window[win_pos] = ch; + win_pos = (win_pos + 1) % HASHSIG_HASH_WINDOW; } - prog->state = state; + prog->state = state; + prog->saw_lf = saw_lf; + prog->win_pos = win_pos; return 0; } @@ -296,7 +304,7 @@ int git_hashsig_create_fromfile( const char *path, git_hashsig_option_t opts) { - char buf[4096]; + char buf[0x1000]; ssize_t buflen = 0; int error = 0, fd; hashsig_in_progress prog = HASHSIG_IN_PROGRESS_INIT; -- cgit v1.2.1 From 397357a0480b341fce5e93d3f485504f2ae94082 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 24 Jul 2013 13:12:00 -0700 Subject: Add rename test that used to be really slow Before the optimization commits, this test used to take about 20 seconds to run on my machine. Afterwards, there is still a couple seconds of data setup, but the actual diff and rename detection runs in a fraction of a second. --- tests-clar/diff/rename.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index 9efd9281c..ed58b7aa9 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -1122,3 +1122,60 @@ void test_diff_rename__unmodified_can_be_renamed(void) git_index_free(index); git_tree_free(tree); } + +void test_diff_rename__many_files(void) +{ + git_index *index; + git_tree *tree; + git_diff_list *diff = NULL; + diff_expects exp; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + git_buf b = GIT_BUF_INIT; + int i, j; + char tmp[64]; + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/ikeepsix2.txt")); + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "ikeepsix2.txt")); + + for (i = 0; i < 100; i += 2) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + + for (j = 0; j < i * 128; ++j) + git_buf_printf(&b, "more content %d\n", i); + + cl_git_mkfile(tmp, b.ptr); + cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/"))); + } + git_buf_free(&b); + + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &exp)); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(51, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(52, exp.files); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &exp)); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + cl_assert_equal_i(50, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(51, exp.files); + + git_diff_list_free(diff); + git_index_free(index); + git_tree_free(tree); +} -- cgit v1.2.1 From f5c4d0225157a6e15fc08f07aa77b5e8f52cdac5 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 24 Jul 2013 13:44:35 -0700 Subject: Fix incorrect comment --- src/diff_tform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diff_tform.c b/src/diff_tform.c index ab43a3a14..cabcd1f80 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -512,7 +512,7 @@ static int similarity_measure( return 0; } - /* check if file sizes too small or nowhere near each other */ + /* check if file sizes are nowhere near each other */ if (a_file->size > 127 && b_file->size > 127 && (a_file->size > (b_file->size << 4) || -- cgit v1.2.1 From 847c679309378748d2a3ac1c5a49331d2e64d4cf Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Thu, 25 Jul 2013 00:26:51 +0200 Subject: Allow Makefile.embed to be used when cross-compiling This allows libgit2 to be cross-compiled (e.g. when building native rugged binaries for windows from Linux or OS X). ``` CROSS_COMPILE=i686-w64-mingw32 make -f Makefile.embed ``` --- Makefile.embed | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Makefile.embed b/Makefile.embed index 76b4d3cda..8b8970d76 100644 --- a/Makefile.embed +++ b/Makefile.embed @@ -1,15 +1,33 @@ -PLATFORM=$(shell uname -o) +PLATFORM=$(shell uname -s) + +ifneq (,$(CROSS_COMPILE)) + PREFIX=$(CROSS_COMPILE)- +else + PREFIX= +endif + +WIN32=0 +ifneq (,$(findstring MINGW32,$(PLATFORM))) + WIN32=1 +endif +ifneq (,$(findstring mingw,$(CROSS_COMPILE))) + WIN32=1 +endif rm=rm -f -AR=ar cq -RANLIB=ranlib +AR=$(PREFIX)ar cq +RANLIB=$(PREFIX)ranlib + LIBNAME=libgit2.a -ifeq ($(PLATFORM),Msys) + +ifeq ($(WIN32),1) CC=gcc else CC=cc endif +CC:=$(PREFIX)$(CC) + INCLUDES= -I. -Isrc -Iinclude -Ideps/http-parser -Ideps/zlib DEFINES= $(INCLUDES) -DNO_VIZ -DSTDC -DNO_GZIP -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE $(EXTRA_DEFINES) @@ -17,7 +35,7 @@ CFLAGS= -g $(DEFINES) -Wall -Wextra -O2 $(EXTRA_CFLAGS) SRCS = $(wildcard src/*.c) $(wildcard src/transports/*.c) $(wildcard src/xdiff/*.c) $(wildcard deps/http-parser/*.c) $(wildcard deps/zlib/*.c) src/hash/hash_generic.c -ifeq ($(PLATFORM),Msys) +ifeq ($(WIN32),1) SRCS += $(wildcard src/win32/*.c) $(wildcard src/compat/*.c) deps/regex/regex.c INCLUDES += -Ideps/regex DEFINES += -DWIN32 -D_WIN32_WINNT=0x0501 -- cgit v1.2.1 From a5140f4dda66263a34080b11cfc34a49c9743100 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 24 Jul 2013 17:11:49 -0700 Subject: Fix rename detection for tree-to-tree diffs The performance improvements I introduced for rename detection were not able to run successfully for tree-to-tree diffs because the blob size was not known early enough and so the file signature always had to be calculated nonetheless. This change separates loading blobs into memory from calculating the signature. I can't avoid having to load the large blobs into memory, but by moving it forward, I'm able to avoid the signature calculation if the blob won't come into play for renames. --- src/diff_tform.c | 145 ++++++++++++++++++++++++++++++++--------------- tests-clar/diff/rename.c | 50 +++++++++++++++- 2 files changed, 146 insertions(+), 49 deletions(-) diff --git a/src/diff_tform.c b/src/diff_tform.c index cabcd1f80..08b0d5c38 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -408,54 +408,90 @@ GIT_INLINE(git_diff_file *) similarity_get_file(git_diff_list *diff, size_t idx) return (idx & 1) ? &delta->new_file : &delta->old_file; } -static int similarity_calc( - git_diff_list *diff, - const git_diff_find_options *opts, - size_t file_idx, - void **cache) +typedef struct { + size_t idx; + git_iterator_type_t src; + git_repository *repo; + git_diff_file *file; + git_buf data; + git_blob *blob; + int loaded; +} similarity_info; + +static void similarity_init( + similarity_info *info, git_diff_list *diff, size_t file_idx) +{ + info->idx = file_idx; + info->src = (file_idx & 1) ? diff->new_src : diff->old_src; + info->repo = diff->repo; + info->file = similarity_get_file(diff, file_idx); + info->blob = NULL; + info->loaded = 0; + git_buf_init(&info->data, 0); +} + +static int similarity_load(similarity_info *info) { int error = 0; - git_diff_file *file = similarity_get_file(diff, file_idx); - git_iterator_type_t src = (file_idx & 1) ? diff->new_src : diff->old_src; + git_diff_file *file = info->file; - if (src == GIT_ITERATOR_TYPE_WORKDIR) { /* compute hashsig from file */ - git_buf path = GIT_BUF_INIT; + if (info->src == GIT_ITERATOR_TYPE_WORKDIR) { + error = git_buf_joinpath( + &info->data, git_repository_workdir(info->repo), file->path); - /* TODO: apply wd-to-odb filters to file data if necessary */ + /* if path is not a regular file, just skip this item */ + if (!error && !git_path_isfile(info->data.ptr)) + git_buf_free(&info->data); + } else if (git_blob_lookup(&info->blob, info->repo, &file->oid) < 0) { + /* if lookup fails, just skip this item in similarity calc */ + giterr_clear(); + } else { + if (!file->size) + file->size = git_blob_rawsize(info->blob); + assert(file->size == git_blob_rawsize(info->blob)); - if ((error = git_buf_joinpath( - &path, git_repository_workdir(diff->repo), file->path)) < 0) - return error; + info->data.size = (size_t)(git__is_sizet(file->size) ? file->size : -1); + info->data.ptr = (char *)git_blob_rawcontent(info->blob); + } - /* if path is not a regular file, just skip this item */ - if (git_path_isfile(path.ptr)) - error = opts->metric->file_signature( - &cache[file_idx], file, path.ptr, opts->metric->payload); + info->loaded = 1; - git_buf_free(&path); - } else { /* compute hashsig from blob buffer */ - git_blob *blob = NULL; - git_off_t blobsize; + return error; +} - /* TODO: add max size threshold a la diff? */ +static void similarity_unload(similarity_info *info) +{ + if (info->blob) + git_blob_free(info->blob); + else + git_buf_free(&info->data); - if (git_blob_lookup(&blob, diff->repo, &file->oid) < 0) { - /* if lookup fails, just skip this item in similarity calc */ - giterr_clear(); - return 0; - } + info->loaded = 0; +} - blobsize = git_blob_rawsize(blob); - if (!file->size) - file->size = blobsize; - if (!git__is_sizet(blobsize)) /* ? what to do ? */ - blobsize = (size_t)-1; +static int similarity_calc( + similarity_info *info, + const git_diff_find_options *opts, + void **cache) +{ + int error = 0; - error = opts->metric->buffer_signature( - &cache[file_idx], file, git_blob_rawcontent(blob), - (size_t)blobsize, opts->metric->payload); + if (!info->loaded && (error = similarity_load(info)) < 0) + return error; - git_blob_free(blob); + if (!info->data.size) + return 0; + + if (info->src == GIT_ITERATOR_TYPE_WORKDIR) { + /* TODO: apply wd-to-odb filters to file data if necessary */ + + error = opts->metric->file_signature( + &cache[info->idx], info->file, + info->data.ptr, opts->metric->payload); + } else { + error = opts->metric->buffer_signature( + &cache[info->idx], info->file, + info->data.ptr, info->data.size, opts->metric->payload); } return error; @@ -478,6 +514,8 @@ static int similarity_measure( git_diff_file *a_file = similarity_get_file(diff, a_idx); git_diff_file *b_file = similarity_get_file(diff, b_idx); bool exact_match = FLAG_SET(opts, GIT_DIFF_FIND_EXACT_MATCH_ONLY); + int error = 0; + similarity_info a_info, b_info; *score = -1; @@ -512,26 +550,39 @@ static int similarity_measure( return 0; } + similarity_init(&a_info, diff, a_idx); + similarity_init(&b_info, diff, b_idx); + + if (!a_file->size && (error = similarity_load(&a_info)) < 0) + goto done; + if (!b_file->size && (error = similarity_load(&b_info)) < 0) + goto done; + /* check if file sizes are nowhere near each other */ if (a_file->size > 127 && b_file->size > 127 && (a_file->size > (b_file->size << 4) || b_file->size > (a_file->size << 4))) - return 0; + goto done; /* update signature cache if needed */ - if (!cache[a_idx] && similarity_calc(diff, opts, a_idx, cache) < 0) - return -1; - if (!cache[b_idx] && similarity_calc(diff, opts, b_idx, cache) < 0) - return -1; + if (!cache[a_idx] && (error = similarity_calc(&a_info, opts, cache)) < 0) + goto done; + if (!cache[b_idx] && (error = similarity_calc(&b_info, opts, cache)) < 0) + goto done; - /* some metrics may not wish to process this file (too big / too small) */ - if (!cache[a_idx] || !cache[b_idx]) - return 0; + /* calculate similarity provided that the metric choose to process + * both the a and b files (some may not if file is too big, etc). + */ + if (cache[a_idx] && cache[b_idx]) + error = opts->metric->similarity( + score, cache[a_idx], cache[b_idx], opts->metric->payload); - /* compare signatures */ - return opts->metric->similarity( - score, cache[a_idx], cache[b_idx], opts->metric->payload); +done: + similarity_unload(&a_info); + similarity_unload(&b_info); + + return error; } static int calc_self_similarity( diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index ed58b7aa9..79c89e362 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -1126,7 +1126,7 @@ void test_diff_rename__unmodified_can_be_renamed(void) void test_diff_rename__many_files(void) { git_index *index; - git_tree *tree; + git_tree *tree, *new_tree; git_diff_list *diff = NULL; diff_expects exp; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; @@ -1176,6 +1176,52 @@ void test_diff_rename__many_files(void) cl_assert_equal_i(51, exp.files); git_diff_list_free(diff); - git_index_free(index); + + { + git_object *parent; + git_signature *sig; + git_oid tree_id, commit_id; + git_reference *ref; + + cl_git_pass(git_index_write_tree(&tree_id, index)); + cl_git_pass(git_tree_lookup(&new_tree, g_repo, &tree_id)); + + cl_git_pass(git_revparse_ext(&parent, &ref, g_repo, "HEAD")); + cl_git_pass(git_signature_new( + &sig, "Sm Test", "sm@tester.test", 1372350000, 480)); + + cl_git_pass(git_commit_create_v( + &commit_id, g_repo, git_reference_name(ref), sig, sig, + NULL, "yoyoyo", new_tree, 1, parent)); + + git_object_free(parent); + git_reference_free(ref); + git_signature_free(sig); + } + + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, tree, new_tree, &diffopts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &exp)); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(51, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(52, exp.files); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &exp)); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + cl_assert_equal_i(50, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(51, exp.files); + + git_diff_list_free(diff); + + git_tree_free(new_tree); git_tree_free(tree); + git_index_free(index); } -- cgit v1.2.1 From effdbeb3239b777e2b19fc4944643fc7f2a768c3 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 24 Jul 2013 17:48:37 -0700 Subject: Make rename detection file size fix better The previous fix for checking file sizes with rename detection always loads the blob. In this version, if the odb backend can get the object header without loading the whole thing into memory, then we'll just use that, so that we can eliminate possible rename sources & targets without loading them. --- src/diff.h | 29 ++++++++++++++ src/diff_file.c | 14 +------ src/diff_tform.c | 116 +++++++++++++++++++++++++++---------------------------- 3 files changed, 89 insertions(+), 70 deletions(-) diff --git a/src/diff.h b/src/diff.h index d09a130bc..d1bec00c6 100644 --- a/src/diff.h +++ b/src/diff.h @@ -16,6 +16,7 @@ #include "iterator.h" #include "repository.h" #include "pool.h" +#include "odb.h" #define DIFF_OLD_PREFIX_DEFAULT "a/" #define DIFF_NEW_PREFIX_DEFAULT "b/" @@ -108,5 +109,33 @@ extern void git_diff_find_similar__hashsig_free(void *sig, void *payload); extern int git_diff_find_similar__calc_similarity( int *score, void *siga, void *sigb, void *payload); +/* + * Sometimes a git_diff_file will have a zero size; this attempts to + * fill in the size without loading the blob if possible. If that is + * not possible, then it will return the git_odb_object that had to be + * loaded and the caller can use it or dispose of it as needed. + */ +GIT_INLINE(int) git_diff_file__resolve_zero_size( + git_diff_file *file, git_odb_object **odb_obj, git_repository *repo) +{ + int error; + git_odb *odb; + size_t len; + git_otype type; + + if ((error = git_repository_odb(&odb, repo)) < 0) + return error; + + error = git_odb__read_header_or_object( + odb_obj, &len, &type, odb, &file->oid); + + git_odb_free(odb); + + if (!error) + file->size = (git_off_t)len; + + return error; +} + #endif diff --git a/src/diff_file.c b/src/diff_file.c index 19bcf2d45..bcfef13cd 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -241,19 +241,9 @@ static int diff_file_content_load_blob(git_diff_file_content *fc) /* if we don't know size, try to peek at object header first */ if (!fc->file->size) { - git_odb *odb; - size_t len; - git_otype type; - - if (!(error = git_repository_odb__weakptr(&odb, fc->repo))) { - error = git_odb__read_header_or_object( - &odb_obj, &len, &type, odb, &fc->file->oid); - git_odb_free(odb); - } - if (error) + if ((error = git_diff_file__resolve_zero_size( + fc->file, &odb_obj, fc->repo)) < 0) return error; - - fc->file->size = len; } if (diff_file_content_binary_by_size(fc)) diff --git a/src/diff_tform.c b/src/diff_tform.c index 08b0d5c38..8fd2a4fe9 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -414,59 +414,26 @@ typedef struct { git_repository *repo; git_diff_file *file; git_buf data; + git_odb_object *odb_obj; git_blob *blob; - int loaded; } similarity_info; -static void similarity_init( +static int similarity_init( similarity_info *info, git_diff_list *diff, size_t file_idx) { info->idx = file_idx; info->src = (file_idx & 1) ? diff->new_src : diff->old_src; info->repo = diff->repo; info->file = similarity_get_file(diff, file_idx); + info->odb_obj = NULL; info->blob = NULL; - info->loaded = 0; git_buf_init(&info->data, 0); -} - -static int similarity_load(similarity_info *info) -{ - int error = 0; - git_diff_file *file = info->file; - - if (info->src == GIT_ITERATOR_TYPE_WORKDIR) { - error = git_buf_joinpath( - &info->data, git_repository_workdir(info->repo), file->path); - - /* if path is not a regular file, just skip this item */ - if (!error && !git_path_isfile(info->data.ptr)) - git_buf_free(&info->data); - } else if (git_blob_lookup(&info->blob, info->repo, &file->oid) < 0) { - /* if lookup fails, just skip this item in similarity calc */ - giterr_clear(); - } else { - if (!file->size) - file->size = git_blob_rawsize(info->blob); - assert(file->size == git_blob_rawsize(info->blob)); - - info->data.size = (size_t)(git__is_sizet(file->size) ? file->size : -1); - info->data.ptr = (char *)git_blob_rawcontent(info->blob); - } - - info->loaded = 1; - return error; -} - -static void similarity_unload(similarity_info *info) -{ - if (info->blob) - git_blob_free(info->blob); - else - git_buf_free(&info->data); + if (info->file->size > 0) + return 0; - info->loaded = 0; + return git_diff_file__resolve_zero_size( + info->file, &info->odb_obj, info->repo); } static int similarity_calc( @@ -475,28 +442,59 @@ static int similarity_calc( void **cache) { int error = 0; + git_diff_file *file = info->file; - if (!info->loaded && (error = similarity_load(info)) < 0) - return error; + if (info->src == GIT_ITERATOR_TYPE_WORKDIR) { + if ((error = git_buf_joinpath( + &info->data, git_repository_workdir(info->repo), file->path)) < 0) + return error; - if (!info->data.size) - return 0; + /* if path is not a regular file, just skip this item */ + if (!git_path_isfile(info->data.ptr)) + return 0; - if (info->src == GIT_ITERATOR_TYPE_WORKDIR) { /* TODO: apply wd-to-odb filters to file data if necessary */ error = opts->metric->file_signature( &cache[info->idx], info->file, info->data.ptr, opts->metric->payload); } else { - error = opts->metric->buffer_signature( - &cache[info->idx], info->file, - info->data.ptr, info->data.size, opts->metric->payload); + /* if we didn't initially know the size, we might have an odb_obj + * around from earlier, so convert that, otherwise load the blob now + */ + if (info->odb_obj != NULL) + error = git_object__from_odb_object( + (git_object **)&info->blob, info->repo, + info->odb_obj, GIT_OBJ_BLOB); + else + error = git_blob_lookup(&info->blob, info->repo, &file->oid); + + if (error < 0) { + /* if lookup fails, just skip this item in similarity calc */ + giterr_clear(); + } else { + size_t sz = (size_t)(git__is_sizet(file->size) ? file->size : -1); + + error = opts->metric->buffer_signature( + &cache[info->idx], info->file, + git_blob_rawcontent(info->blob), sz, opts->metric->payload); + } } return error; } +static void similarity_unload(similarity_info *info) +{ + if (info->odb_obj) + git_odb_object_free(info->odb_obj); + + if (info->blob) + git_blob_free(info->blob); + else + git_buf_free(&info->data); +} + #define FLAG_SET(opts,flag_name) (((opts)->flags & flag_name) != 0) /* - score < 0 means files cannot be compared @@ -550,26 +548,28 @@ static int similarity_measure( return 0; } - similarity_init(&a_info, diff, a_idx); - similarity_init(&b_info, diff, b_idx); + memset(&a_info, 0, sizeof(a_info)); + memset(&b_info, 0, sizeof(b_info)); - if (!a_file->size && (error = similarity_load(&a_info)) < 0) - goto done; - if (!b_file->size && (error = similarity_load(&b_info)) < 0) - goto done; + /* set up similarity data (will try to update missing file sizes) */ + if (!cache[a_idx] && (error = similarity_init(&a_info, diff, a_idx)) < 0) + return error; + if (!cache[b_idx] && (error = similarity_init(&b_info, diff, b_idx)) < 0) + goto cleanup; /* check if file sizes are nowhere near each other */ if (a_file->size > 127 && b_file->size > 127 && (a_file->size > (b_file->size << 4) || b_file->size > (a_file->size << 4))) - goto done; + goto cleanup; /* update signature cache if needed */ if (!cache[a_idx] && (error = similarity_calc(&a_info, opts, cache)) < 0) - goto done; + goto cleanup; + if (!cache[b_idx] && (error = similarity_calc(&b_info, opts, cache)) < 0) - goto done; + goto cleanup; /* calculate similarity provided that the metric choose to process * both the a and b files (some may not if file is too big, etc). @@ -578,7 +578,7 @@ static int similarity_measure( error = opts->metric->similarity( score, cache[a_idx], cache[b_idx], opts->metric->payload); -done: +cleanup: similarity_unload(&a_info); similarity_unload(&b_info); -- cgit v1.2.1 From 3a2d48d5ee48c520fdc6b0cd65e1982db7751352 Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Thu, 25 Jul 2013 14:54:19 +0200 Subject: Close p->mwf.fd only if necessary This fixes a regression introduced in revision 9d2f841a5d39fc25ce722a3904f6ebc9aa112222. Signed-off-by: Sven Strickroth --- src/pack.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pack.c b/src/pack.c index 497db38e8..d7e6a1e94 100644 --- a/src/pack.c +++ b/src/pack.c @@ -822,7 +822,7 @@ void git_packfile_free(struct git_pack_file *p) git_mwindow_free_all(&p->mwf); - if (p->mwf.fd != -1) + if (p->mwf.fd >= 0) p_close(p->mwf.fd); pack_index_free(p); @@ -905,7 +905,8 @@ static int packfile_open(struct git_pack_file *p) cleanup: giterr_set(GITERR_OS, "Invalid packfile '%s'", p->pack_name); - p_close(p->mwf.fd); + if (p->mwf.fd >= 0) + p_close(p->mwf.fd); p->mwf.fd = -1; git_mutex_unlock(&p->lock); -- cgit v1.2.1 From a16e41729d5dec4acd30302c4a217622de00d290 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 25 Jul 2013 12:27:39 -0700 Subject: Fix rename detection to use actual blob size The size data in the index may not reflect the actual size of the blob data from the ODB when content filtering comes into play. This commit fixes rename detection to use the actual blob size when calculating data signatures instead of the value from the index. Because of a misunderstanding on my part, I first converted the git_index_add_bypath API to use the post-filtered blob data size in creating the index entry. I backed that change out, but I kept the overall refactoring of that routine and the new internal git_blob__create_from_paths API because it eliminates an extra stat() call from the code that adds a file to the index. The existing tests actually cover this code path, at least when running on Windows, so at this point I'm not adding new tests to cover the changes. --- src/blob.c | 89 +++++++++++++++++++++++++++++++++----------------------- src/blob.h | 9 ++++++ src/diff_tform.c | 8 ++++- src/index.c | 34 +++++----------------- 4 files changed, 76 insertions(+), 64 deletions(-) diff --git a/src/blob.c b/src/blob.c index 2e4d5f479..0f1c97003 100644 --- a/src/blob.c +++ b/src/blob.c @@ -105,6 +105,7 @@ static int write_file_stream( static int write_file_filtered( git_oid *oid, + git_off_t *size, git_odb *odb, const char *full_path, git_vector *filters) @@ -123,8 +124,11 @@ static int write_file_filtered( git_buf_free(&source); /* Write the file to disk if it was properly filtered */ - if (!error) + if (!error) { + *size = dest.size; + error = git_odb_write(oid, odb, dest.ptr, dest.size, GIT_OBJ_BLOB); + } git_buf_free(&dest); return error; @@ -152,21 +156,46 @@ static int write_symlink( return error; } -static int blob_create_internal(git_oid *oid, git_repository *repo, const char *content_path, const char *hint_path, bool try_load_filters) +int git_blob__create_from_paths( + git_oid *oid, + struct stat *out_st, + git_repository *repo, + const char *content_path, + const char *hint_path, + mode_t hint_mode, + bool try_load_filters) { int error; struct stat st; git_odb *odb = NULL; git_off_t size; + mode_t mode; + git_buf path = GIT_BUF_INIT; assert(hint_path || !try_load_filters); - if ((error = git_path_lstat(content_path, &st)) < 0 || (error = git_repository_odb__weakptr(&odb, repo)) < 0) - return error; + if (!content_path) { + if (git_repository__ensure_not_bare(repo, "create blob from file") < 0) + return GIT_EBAREREPO; + + if (git_buf_joinpath( + &path, git_repository_workdir(repo), hint_path) < 0) + return -1; + + content_path = path.ptr; + } + + if ((error = git_path_lstat(content_path, &st)) < 0 || + (error = git_repository_odb(&odb, repo)) < 0) + goto done; + + if (out_st) + memcpy(out_st, &st, sizeof(st)); size = st.st_size; + mode = hint_mode ? hint_mode : st.st_mode; - if (S_ISLNK(st.st_mode)) { + if (S_ISLNK(hint_mode)) { error = write_symlink(oid, odb, content_path, (size_t)size); } else { git_vector write_filters = GIT_VECTOR_INIT; @@ -187,7 +216,8 @@ static int blob_create_internal(git_oid *oid, git_repository *repo, const char * error = write_file_stream(oid, odb, content_path, size); } else { /* We need to apply one or more filters */ - error = write_file_filtered(oid, odb, content_path, &write_filters); + error = write_file_filtered( + oid, &size, odb, content_path, &write_filters); } git_filters_free(&write_filters); @@ -207,34 +237,21 @@ static int blob_create_internal(git_oid *oid, git_repository *repo, const char * */ } +done: + git_odb_free(odb); + git_buf_free(&path); + return error; } -int git_blob_create_fromworkdir(git_oid *oid, git_repository *repo, const char *path) +int git_blob_create_fromworkdir( + git_oid *oid, git_repository *repo, const char *path) { - git_buf full_path = GIT_BUF_INIT; - const char *workdir; - int error; - - if ((error = git_repository__ensure_not_bare(repo, "create blob from file")) < 0) - return error; - - workdir = git_repository_workdir(repo); - - if (git_buf_joinpath(&full_path, workdir, path) < 0) { - git_buf_free(&full_path); - return -1; - } - - error = blob_create_internal( - oid, repo, git_buf_cstr(&full_path), - git_buf_cstr(&full_path) + strlen(workdir), true); - - git_buf_free(&full_path); - return error; + return git_blob__create_from_paths(oid, NULL, repo, NULL, path, 0, true); } -int git_blob_create_fromdisk(git_oid *oid, git_repository *repo, const char *path) +int git_blob_create_fromdisk( + git_oid *oid, git_repository *repo, const char *path) { int error; git_buf full_path = GIT_BUF_INIT; @@ -251,8 +268,8 @@ int git_blob_create_fromdisk(git_oid *oid, git_repository *repo, const char *pat if (workdir && !git__prefixcmp(hintpath, workdir)) hintpath += strlen(workdir); - error = blob_create_internal( - oid, repo, git_buf_cstr(&full_path), hintpath, true); + error = git_blob__create_from_paths( + oid, NULL, repo, git_buf_cstr(&full_path), hintpath, 0, true); git_buf_free(&full_path); return error; @@ -272,12 +289,9 @@ int git_blob_create_fromchunks( git_filebuf file = GIT_FILEBUF_INIT; git_buf path = GIT_BUF_INIT; - if (git_buf_join_n( - &path, '/', 3, - git_repository_path(repo), - GIT_OBJECTS_DIR, - "streamed") < 0) - goto cleanup; + if (git_buf_joinpath( + &path, git_repository_path(repo), GIT_OBJECTS_DIR "streamed") < 0) + goto cleanup; content = git__malloc(BUFFER_SIZE); GITERR_CHECK_ALLOC(content); @@ -303,7 +317,8 @@ int git_blob_create_fromchunks( if (git_filebuf_flush(&file) < 0) goto cleanup; - error = blob_create_internal(oid, repo, file.path_lock, hintpath, hintpath != NULL); + error = git_blob__create_from_paths( + oid, NULL, repo, file.path_lock, hintpath, 0, hintpath != NULL); cleanup: git_buf_free(&path); diff --git a/src/blob.h b/src/blob.h index 22e37cc3a..4cd9f1e0c 100644 --- a/src/blob.h +++ b/src/blob.h @@ -21,4 +21,13 @@ void git_blob__free(void *blob); int git_blob__parse(void *blob, git_odb_object *obj); int git_blob__getbuf(git_buf *buffer, git_blob *blob); +extern int git_blob__create_from_paths( + git_oid *out_oid, + struct stat *out_st, + git_repository *repo, + const char *full_path, + const char *hint_path, + mode_t hint_mode, + bool apply_filters); + #endif diff --git a/src/diff_tform.c b/src/diff_tform.c index 8fd2a4fe9..d4b8cf30a 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -473,7 +473,13 @@ static int similarity_calc( /* if lookup fails, just skip this item in similarity calc */ giterr_clear(); } else { - size_t sz = (size_t)(git__is_sizet(file->size) ? file->size : -1); + size_t sz; + + /* index size may not be actual blob size if filtered */ + if (file->size != git_blob_rawsize(info->blob)) + file->size = git_blob_rawsize(info->blob); + + sz = (size_t)(git__is_sizet(file->size) ? file->size : -1); error = opts->metric->buffer_signature( &cache[info->idx], info->file, diff --git a/src/index.c b/src/index.c index 0610eb5b9..cbdd43bdc 100644 --- a/src/index.c +++ b/src/index.c @@ -16,6 +16,7 @@ #include "iterator.h" #include "pathspec.h" #include "ignore.h" +#include "blob.h" #include "git2/odb.h" #include "git2/oid.h" @@ -604,42 +605,23 @@ int git_index_entry__cmp_icase(const void *a, const void *b) return strcasecmp(entry_a->path, entry_b->path); } -static int index_entry_init(git_index_entry **entry_out, git_index *index, const char *rel_path) +static int index_entry_init( + git_index_entry **entry_out, git_index *index, const char *rel_path) { + int error = 0; git_index_entry *entry = NULL; struct stat st; git_oid oid; - const char *workdir; - git_buf full_path = GIT_BUF_INIT; - int error; if (INDEX_OWNER(index) == NULL) return create_index_error(-1, "Could not initialize index entry. " "Index is not backed up by an existing repository."); - workdir = git_repository_workdir(INDEX_OWNER(index)); - - if (!workdir) - return create_index_error(GIT_EBAREREPO, - "Could not initialize index entry. Repository is bare"); - - if ((error = git_buf_joinpath(&full_path, workdir, rel_path)) < 0) - return error; - - if ((error = git_path_lstat(full_path.ptr, &st)) < 0) { - git_buf_free(&full_path); - return error; - } - - git_buf_free(&full_path); /* done with full path */ - - /* There is no need to validate the rel_path here, since it will be - * immediately validated by the call to git_blob_create_fromfile. - */ - - /* write the blob to disk and get the oid */ - if ((error = git_blob_create_fromworkdir(&oid, INDEX_OWNER(index), rel_path)) < 0) + /* write the blob to disk and get the oid and stat info */ + error = git_blob__create_from_paths( + &oid, &st, INDEX_OWNER(index), NULL, rel_path, 0, true); + if (error < 0) return error; entry = git__calloc(1, sizeof(git_index_entry)); -- cgit v1.2.1 From 8dd8aa480ba46863e9c7df40bb9695e88a0286ee Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 26 Jul 2013 10:28:57 -0700 Subject: Fix some warnings --- src/array.h | 11 ++++++----- src/blob.c | 2 +- src/diff_patch.c | 26 +++++++++++++------------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/array.h b/src/array.h index 248010425..c25a1b29e 100644 --- a/src/array.h +++ b/src/array.h @@ -39,25 +39,26 @@ #define GITERR_CHECK_ARRAY(a) GITERR_CHECK_ALLOC((a).ptr) -typedef git_array_t(void) git_array_generic_t; +typedef git_array_t(char) git_array_generic_t; /* use a generic array for growth so this can return the new item */ -GIT_INLINE(void *) git_array_grow(git_array_generic_t *a, size_t item_size) +GIT_INLINE(void *) git_array_grow(void *_a, size_t item_size) { + git_array_generic_t *a = _a; uint32_t new_size = (a->size < 8) ? 8 : a->asize * 3 / 2; - void *new_array = git__realloc(a->ptr, new_size * item_size); + char *new_array = git__realloc(a->ptr, new_size * item_size); if (!new_array) { git_array_clear(*a); return NULL; } else { a->ptr = new_array; a->asize = new_size; a->size++; - return (((char *)a->ptr) + (a->size - 1) * item_size); + return a->ptr + (a->size - 1) * item_size; } } #define git_array_alloc(a) \ ((a).size >= (a).asize) ? \ - git_array_grow((git_array_generic_t *)&(a), sizeof(*(a).ptr)) : \ + git_array_grow(&(a), sizeof(*(a).ptr)) : \ (a).ptr ? &(a).ptr[(a).size++] : NULL #define git_array_last(a) ((a).size ? &(a).ptr[(a).size - 1] : NULL) diff --git a/src/blob.c b/src/blob.c index 0f1c97003..5bb51f7cf 100644 --- a/src/blob.c +++ b/src/blob.c @@ -195,7 +195,7 @@ int git_blob__create_from_paths( size = st.st_size; mode = hint_mode ? hint_mode : st.st_mode; - if (S_ISLNK(hint_mode)) { + if (S_ISLNK(mode)) { error = write_symlink(oid, odb, content_path, (size_t)size); } else { git_vector write_filters = GIT_VECTOR_INIT; diff --git a/src/diff_patch.c b/src/diff_patch.c index 02a45cb1a..69bb08198 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -288,8 +288,8 @@ int git_diff_foreach( if (diff_required(diff, "git_diff_foreach") < 0) return -1; - diff_output_init((git_diff_output *)&xo, - &diff->opts, file_cb, hunk_cb, data_cb, payload); + diff_output_init( + &xo.output, &diff->opts, file_cb, hunk_cb, data_cb, payload); git_xdiff_init(&xo, &diff->opts); git_vector_foreach(&diff->deltas, idx, patch.delta) { @@ -300,10 +300,10 @@ int git_diff_foreach( if (!(error = diff_patch_init_from_diff(&patch, diff, idx))) { - error = diff_patch_file_callback(&patch, (git_diff_output *)&xo); + error = diff_patch_file_callback(&patch, &xo.output); if (!error) - error = diff_patch_generate(&patch, (git_diff_output *)&xo); + error = diff_patch_generate(&patch, &xo.output); git_diff_patch_free(&patch); } @@ -441,7 +441,7 @@ int git_diff_blobs( memset(&xo, 0, sizeof(xo)); diff_output_init( - (git_diff_output *)&xo, opts, file_cb, hunk_cb, data_cb, payload); + &xo.output, opts, file_cb, hunk_cb, data_cb, payload); git_xdiff_init(&xo, opts); if (!old_path && new_path) @@ -452,7 +452,7 @@ int git_diff_blobs( error = diff_patch_from_blobs( &pd, &xo, old_blob, old_path, new_blob, new_path, opts); - git_diff_patch_free((git_diff_patch *)&pd); + git_diff_patch_free(&pd.patch); return error; } @@ -477,7 +477,7 @@ int git_diff_patch_from_blobs( memset(&xo, 0, sizeof(xo)); - diff_output_to_patch((git_diff_output *)&xo, &pd->patch); + diff_output_to_patch(&xo.output, &pd->patch); git_xdiff_init(&xo, opts); error = diff_patch_from_blobs( @@ -553,7 +553,7 @@ int git_diff_blob_to_buffer( memset(&xo, 0, sizeof(xo)); diff_output_init( - (git_diff_output *)&xo, opts, file_cb, hunk_cb, data_cb, payload); + &xo.output, opts, file_cb, hunk_cb, data_cb, payload); git_xdiff_init(&xo, opts); if (!old_path && buf_path) @@ -564,7 +564,7 @@ int git_diff_blob_to_buffer( error = diff_patch_from_blob_and_buffer( &pd, &xo, old_blob, old_path, buf, buflen, buf_path, opts); - git_diff_patch_free((git_diff_patch *)&pd); + git_diff_patch_free(&pd.patch); return error; } @@ -590,7 +590,7 @@ int git_diff_patch_from_blob_and_buffer( memset(&xo, 0, sizeof(xo)); - diff_output_to_patch((git_diff_output *)&xo, &pd->patch); + diff_output_to_patch(&xo.output, &pd->patch); git_xdiff_init(&xo, opts); error = diff_patch_from_blob_and_buffer( @@ -642,13 +642,13 @@ int git_diff_get_patch( if ((error = diff_patch_alloc_from_diff(&patch, diff, idx)) < 0) return error; - diff_output_to_patch((git_diff_output *)&xo, patch); + diff_output_to_patch(&xo.output, patch); git_xdiff_init(&xo, &diff->opts); - error = diff_patch_file_callback(patch, (git_diff_output *)&xo); + error = diff_patch_file_callback(patch, &xo.output); if (!error) - error = diff_patch_generate(patch, (git_diff_output *)&xo); + error = diff_patch_generate(patch, &xo.output); if (!error) { /* if cumulative diff size is < 0.5 total size, flatten the patch */ -- cgit v1.2.1 From c3ae047361c0412ed371ef899b018e9c13d6ecf8 Mon Sep 17 00:00:00 2001 From: Brendan Macmillan Date: Sat, 27 Jul 2013 05:31:28 +1000 Subject: Fix -n bug; default to all ancestors --- examples/log.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/log.c b/examples/log.c index dbbc42914..413c211e4 100644 --- a/examples/log.c +++ b/examples/log.c @@ -265,6 +265,7 @@ int main(int argc, char *argv[]) memset(&opt, 0, sizeof(opt)); opt.max_parents = -1; + opt.limit = -1; for (i = 1; i < argc; ++i) { a = argv[i]; @@ -294,8 +295,8 @@ int main(int argc, char *argv[]) if (!match_int(&opt.limit, a + 1, 0)) usage("Invalid limit on number of commits", a); } else if (!strcmp(a, "-n")) { - if (i + 1 == argc || !match_int(&opt.limit, argv[i], 0)) - usage("Argument -n not followed by valid count", argv[i]); + if (i + 1 == argc || !match_int(&opt.limit, argv[i + 1], 0)) + usage("Argument -n not followed by valid count", argv[i + 1]); else ++i; } @@ -363,7 +364,7 @@ int main(int argc, char *argv[]) if (count++ < opt.skip) continue; - if (printed++ >= opt.limit) { + if (opt.limit != -1 && printed++ >= opt.limit) { git_commit_free(commit); break; } -- cgit v1.2.1 From f5254d78441f7fa1067a1c34d3925b72afcb024c Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Sat, 27 Jul 2013 20:15:06 +0200 Subject: Fix possible double close Signed-off-by: Sven Strickroth --- src/fileops.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fileops.c b/src/fileops.c index c01ff64db..7f8418d7a 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -222,6 +222,7 @@ int git_futils_writebuffer( if ((error = p_write(fd, git_buf_cstr(buf), git_buf_len(buf))) < 0) { giterr_set(GITERR_OS, "Could not write to '%s'", path); (void)p_close(fd); + return error; } if ((error = p_close(fd)) < 0) -- cgit v1.2.1 From a6837b5fc9465e0f271ccd2c0bb71aae78a10a64 Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Wed, 31 Jul 2013 19:13:35 +0200 Subject: When building with MINGW, specify `__USE_MINGW_ANSI_STDIO`. This option is already present in the CMake config, but was missing from `Makefile.embed` and would cause all kinds of weird failures when compiling rugged on windows with the ruby devkit. --- Makefile.embed | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile.embed b/Makefile.embed index 8b8970d76..2f3b057c7 100644 --- a/Makefile.embed +++ b/Makefile.embed @@ -6,12 +6,12 @@ else PREFIX= endif -WIN32=0 +MINGW=0 ifneq (,$(findstring MINGW32,$(PLATFORM))) - WIN32=1 + MINGW=1 endif ifneq (,$(findstring mingw,$(CROSS_COMPILE))) - WIN32=1 + MINGW=1 endif rm=rm -f @@ -20,7 +20,7 @@ RANLIB=$(PREFIX)ranlib LIBNAME=libgit2.a -ifeq ($(WIN32),1) +ifeq ($(MINGW),1) CC=gcc else CC=cc @@ -35,10 +35,10 @@ CFLAGS= -g $(DEFINES) -Wall -Wextra -O2 $(EXTRA_CFLAGS) SRCS = $(wildcard src/*.c) $(wildcard src/transports/*.c) $(wildcard src/xdiff/*.c) $(wildcard deps/http-parser/*.c) $(wildcard deps/zlib/*.c) src/hash/hash_generic.c -ifeq ($(WIN32),1) +ifeq ($(MINGW),1) SRCS += $(wildcard src/win32/*.c) $(wildcard src/compat/*.c) deps/regex/regex.c INCLUDES += -Ideps/regex - DEFINES += -DWIN32 -D_WIN32_WINNT=0x0501 + DEFINES += -DWIN32 -D_WIN32_WINNT=0x0501 -D__USE_MINGW_ANSI_STDIO=1 else SRCS += $(wildcard src/unix/*.c) CFLAGS += -fPIC -- cgit v1.2.1 From d730d3f4f0efb269dd760a3100ae86c460b8ba36 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 31 Jul 2013 16:40:42 -0700 Subject: Major rename detection changes After doing further profiling, I found that a lot of time was being spent attempting to insert hashes into the file hash signature when using the rolling hash because the rolling hash approach generates a hash per byte of the file instead of one per run/line of data. To optimize this, I decided to convert back to a run-based file signature algorithm which would be more like core Git. After changing this, a number of the existing tests started to fail. In some cases, this appears to have been because the test was coded to be too specific to the particular results of the file similarity metric and in some cases there appear to have been bugs in the core rename detection code where only by the coincidence of the file similarity scoring were the expected results being generated. This renames all the variables in the core rename detection code to be more consistent and hopefully easier to follow which made it a bit easier to reason about the behavior of that code and fix the problems that I was seeing. I think it's in better shape now. There are a couple of tests now that attempt to stress test the rename detection code and they are quite slow. Most of the time is spent setting up the test data on disk and in the index. When we roll out performance improvements for index insertion, it should also speed up these tests I hope. --- src/diff_tform.c | 219 +++++++++++++++++++++++++++------------------- src/hashsig.c | 218 ++++++++++++++++++++------------------------- src/util.h | 5 ++ tests-clar/clar_libgit2.h | 14 +++ tests-clar/core/buffer.c | 42 +++++---- tests-clar/diff/rename.c | 99 +++++++++++++++------ 6 files changed, 340 insertions(+), 257 deletions(-) diff --git a/src/diff_tform.c b/src/diff_tform.c index d4b8cf30a..92c4036fb 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -436,7 +436,7 @@ static int similarity_init( info->file, &info->odb_obj, info->repo); } -static int similarity_calc( +static int similarity_sig( similarity_info *info, const git_diff_find_options *opts, void **cache) @@ -566,16 +566,19 @@ static int similarity_measure( /* check if file sizes are nowhere near each other */ if (a_file->size > 127 && b_file->size > 127 && - (a_file->size > (b_file->size << 4) || - b_file->size > (a_file->size << 4))) + (a_file->size > (b_file->size << 3) || + b_file->size > (a_file->size << 3))) goto cleanup; /* update signature cache if needed */ - if (!cache[a_idx] && (error = similarity_calc(&a_info, opts, cache)) < 0) - goto cleanup; - - if (!cache[b_idx] && (error = similarity_calc(&b_info, opts, cache)) < 0) - goto cleanup; + if (!cache[a_idx]) { + if ((error = similarity_sig(&a_info, opts, cache)) < 0) + goto cleanup; + } + if (!cache[b_idx]) { + if ((error = similarity_sig(&b_info, opts, cache)) < 0) + goto cleanup; + } /* calculate similarity provided that the metric choose to process * both the a and b files (some may not if file is too big, etc). @@ -759,25 +762,30 @@ int git_diff_find_similar( git_diff_list *diff, git_diff_find_options *given_opts) { - size_t i, j, sigcache_size; + size_t s, t; int error = 0, similarity; - git_diff_delta *from, *to; + git_diff_delta *src, *tgt; git_diff_find_options opts; - size_t num_srcs = 0, num_tgts = 0, tried_srcs = 0, tried_tgts = 0; + size_t num_deltas, num_srcs = 0, num_tgts = 0; + size_t tried_srcs = 0, tried_tgts = 0; size_t num_rewrites = 0, num_updates = 0, num_bumped = 0; void **sigcache; /* cache of similarity metric file signatures */ - diff_find_match *match_srcs = NULL, *match_tgts = NULL, *best_match; + diff_find_match *tgt2src = NULL; + diff_find_match *src2tgt = NULL; + diff_find_match *tgt2src_copy = NULL; + diff_find_match *best_match; git_diff_file swap; if ((error = normalize_find_opts(diff, &opts, given_opts)) < 0) return error; + num_deltas = diff->deltas.length; + /* TODO: maybe abort if deltas.length > rename_limit ??? */ - if (!git__is_uint32(diff->deltas.length)) + if (!git__is_uint32(num_deltas)) return 0; - sigcache_size = diff->deltas.length * 2; /* keep size b/c diff may change */ - sigcache = git__calloc(sigcache_size, sizeof(void *)); + sigcache = git__calloc(num_deltas * 2, sizeof(void *)); GITERR_CHECK_ALLOC(sigcache); /* Label rename sources and targets @@ -785,11 +793,11 @@ int git_diff_find_similar( * This will also set self-similarity scores for MODIFIED files and * mark them for splitting if break-rewrites is enabled */ - git_vector_foreach(&diff->deltas, i, to) { - if (is_rename_source(diff, &opts, i, sigcache)) + git_vector_foreach(&diff->deltas, t, tgt) { + if (is_rename_source(diff, &opts, t, sigcache)) ++num_srcs; - if (is_rename_target(diff, &opts, i, sigcache)) + if (is_rename_target(diff, &opts, t, sigcache)) ++num_tgts; } @@ -797,10 +805,15 @@ int git_diff_find_similar( if (!num_srcs || !num_tgts) goto cleanup; - match_tgts = git__calloc(diff->deltas.length, sizeof(diff_find_match)); - GITERR_CHECK_ALLOC(match_tgts); - match_srcs = git__calloc(diff->deltas.length, sizeof(diff_find_match)); - GITERR_CHECK_ALLOC(match_srcs); + src2tgt = git__calloc(num_deltas, sizeof(diff_find_match)); + GITERR_CHECK_ALLOC(src2tgt); + tgt2src = git__calloc(num_deltas, sizeof(diff_find_match)); + GITERR_CHECK_ALLOC(tgt2src); + + if (FLAG_SET(&opts, GIT_DIFF_FIND_COPIES)) { + tgt2src_copy = git__calloc(num_deltas, sizeof(diff_find_match)); + GITERR_CHECK_ALLOC(tgt2src_copy); + } /* * Find best-fit matches for rename / copy candidates @@ -809,47 +822,61 @@ int git_diff_find_similar( find_best_matches: tried_tgts = num_bumped = 0; - git_vector_foreach(&diff->deltas, i, to) { + git_vector_foreach(&diff->deltas, t, tgt) { /* skip things that are not rename targets */ - if ((to->flags & GIT_DIFF_FLAG__IS_RENAME_TARGET) == 0) + if ((tgt->flags & GIT_DIFF_FLAG__IS_RENAME_TARGET) == 0) continue; tried_srcs = 0; - git_vector_foreach(&diff->deltas, j, from) { + git_vector_foreach(&diff->deltas, s, src) { /* skip things that are not rename sources */ - if ((from->flags & GIT_DIFF_FLAG__IS_RENAME_SOURCE) == 0) + if ((src->flags & GIT_DIFF_FLAG__IS_RENAME_SOURCE) == 0) continue; /* calculate similarity for this pair and find best match */ - if (i == j) + if (s == t) similarity = -1; /* don't measure self-similarity here */ else if ((error = similarity_measure( - &similarity, diff, &opts, sigcache, 2 * j, 2 * i + 1)) < 0) + &similarity, diff, &opts, sigcache, 2 * s, 2 * t + 1)) < 0) goto cleanup; - /* if this pairing is better for the src and the tgt, keep it */ - if (similarity > 0 && - match_tgts[i].similarity < (uint32_t)similarity && - match_srcs[j].similarity < (uint32_t)similarity) + if (similarity < 0) + continue; + + /* is this a better rename? */ + if (tgt2src[t].similarity < (uint32_t)similarity && + src2tgt[s].similarity < (uint32_t)similarity) { - if (match_tgts[i].similarity > 0) { - match_tgts[match_srcs[j].idx].similarity = 0; - match_srcs[match_tgts[i].idx].similarity = 0; - ++num_bumped; + /* eject old mapping */ + if (src2tgt[s].similarity > 0) { + tgt2src[src2tgt[s].idx].similarity = 0; + num_bumped++; + } + if (tgt2src[t].similarity > 0) { + src2tgt[tgt2src[t].idx].similarity = 0; + num_bumped++; } - match_tgts[i].similarity = (uint32_t)similarity; - match_tgts[i].idx = (uint32_t)j; + /* write new mapping */ + tgt2src[t].idx = s; + tgt2src[t].similarity = (uint32_t)similarity; + src2tgt[s].idx = t; + src2tgt[s].similarity = (uint32_t)similarity; + } - match_srcs[j].similarity = (uint32_t)similarity; - match_srcs[j].idx = (uint32_t)i; + /* keep best absolute match for copies */ + if (tgt2src_copy != NULL && + tgt2src_copy[t].similarity < (uint32_t)similarity) + { + tgt2src_copy[t].idx = s; + tgt2src_copy[t].similarity = (uint32_t)similarity; } if (++tried_srcs >= num_srcs) break; - /* cap on maximum targets we'll examine (per "to" file) */ + /* cap on maximum targets we'll examine (per "tgt" file) */ if (tried_srcs > opts.rename_limit) break; } @@ -867,18 +894,21 @@ find_best_matches: tried_tgts = 0; - git_vector_foreach(&diff->deltas, i, to) { + git_vector_foreach(&diff->deltas, t, tgt) { /* skip things that are not rename targets */ - if ((to->flags & GIT_DIFF_FLAG__IS_RENAME_TARGET) == 0) + if ((tgt->flags & GIT_DIFF_FLAG__IS_RENAME_TARGET) == 0) continue; /* check if this delta was the target of a similarity */ - best_match = &match_tgts[i]; - if (!best_match->similarity) + if (tgt2src[t].similarity) + best_match = &tgt2src[t]; + else if (tgt2src_copy && tgt2src_copy[t].similarity) + best_match = &tgt2src_copy[t]; + else continue; - j = best_match->idx; - from = GIT_VECTOR_GET(&diff->deltas, j); + s = best_match->idx; + src = GIT_VECTOR_GET(&diff->deltas, s); /* possible scenarios: * 1. from DELETE to ADD/UNTRACK/IGNORE = RENAME @@ -888,101 +918,107 @@ find_best_matches: * 5. from OTHER to ADD/UNTRACK/IGNORE = OTHER + COPY */ - if (from->status == GIT_DELTA_DELETED) { + if (src->status == GIT_DELTA_DELETED) { - if (delta_is_new_only(to)) { + if (delta_is_new_only(tgt)) { if (best_match->similarity < opts.rename_threshold) continue; - delta_make_rename(to, from, best_match->similarity); + delta_make_rename(tgt, src, best_match->similarity); - from->flags |= GIT_DIFF_FLAG__TO_DELETE; + src->flags |= GIT_DIFF_FLAG__TO_DELETE; num_rewrites++; } else { - assert(delta_is_split(to)); + assert(delta_is_split(tgt)); if (best_match->similarity < opts.rename_from_rewrite_threshold) continue; - memcpy(&swap, &to->old_file, sizeof(swap)); + memcpy(&swap, &tgt->old_file, sizeof(swap)); - delta_make_rename(to, from, best_match->similarity); + delta_make_rename(tgt, src, best_match->similarity); num_rewrites--; - from->status = GIT_DELTA_DELETED; - memcpy(&from->old_file, &swap, sizeof(from->old_file)); - memset(&from->new_file, 0, sizeof(from->new_file)); - from->new_file.path = from->old_file.path; - from->new_file.flags |= GIT_DIFF_FLAG_VALID_OID; + src->status = GIT_DELTA_DELETED; + memcpy(&src->old_file, &swap, sizeof(src->old_file)); + memset(&src->new_file, 0, sizeof(src->new_file)); + src->new_file.path = src->old_file.path; + src->new_file.flags |= GIT_DIFF_FLAG_VALID_OID; num_updates++; } } - else if (delta_is_split(from)) { + else if (delta_is_split(src)) { - if (delta_is_new_only(to)) { + if (delta_is_new_only(tgt)) { if (best_match->similarity < opts.rename_threshold) continue; - delta_make_rename(to, from, best_match->similarity); + delta_make_rename(tgt, src, best_match->similarity); - from->status = (diff->new_src == GIT_ITERATOR_TYPE_WORKDIR) ? + src->status = (diff->new_src == GIT_ITERATOR_TYPE_WORKDIR) ? GIT_DELTA_UNTRACKED : GIT_DELTA_ADDED; - memset(&from->old_file, 0, sizeof(from->old_file)); - from->old_file.path = from->new_file.path; - from->old_file.flags |= GIT_DIFF_FLAG_VALID_OID; + memset(&src->old_file, 0, sizeof(src->old_file)); + src->old_file.path = src->new_file.path; + src->old_file.flags |= GIT_DIFF_FLAG_VALID_OID; - from->flags &= ~GIT_DIFF_FLAG__TO_SPLIT; + src->flags &= ~GIT_DIFF_FLAG__TO_SPLIT; num_rewrites--; num_updates++; } else { - assert(delta_is_split(from)); + assert(delta_is_split(src)); if (best_match->similarity < opts.rename_from_rewrite_threshold) continue; - memcpy(&swap, &to->old_file, sizeof(swap)); + memcpy(&swap, &tgt->old_file, sizeof(swap)); - delta_make_rename(to, from, best_match->similarity); + delta_make_rename(tgt, src, best_match->similarity); num_rewrites--; num_updates++; - memcpy(&from->old_file, &swap, sizeof(from->old_file)); + memcpy(&src->old_file, &swap, sizeof(src->old_file)); /* if we've just swapped the new element into the correct * place, clear the SPLIT flag */ - if (match_tgts[j].idx == i && - match_tgts[j].similarity > + if (tgt2src[s].idx == t && + tgt2src[s].similarity > opts.rename_from_rewrite_threshold) { - - from->status = GIT_DELTA_RENAMED; - from->similarity = match_tgts[j].similarity; - match_tgts[j].similarity = 0; - from->flags &= ~GIT_DIFF_FLAG__TO_SPLIT; + src->status = GIT_DELTA_RENAMED; + src->similarity = tgt2src[s].similarity; + tgt2src[s].similarity = 0; + src->flags &= ~GIT_DIFF_FLAG__TO_SPLIT; num_rewrites--; } /* otherwise, if we just overwrote a source, update mapping */ - else if (j > i && match_srcs[i].similarity > 0) { - match_tgts[match_srcs[i].idx].idx = (uint32_t)j; + else if (s > t && src2tgt[t].similarity > 0) { + /* what used to be at src t is now at src s */ + tgt2src[src2tgt[t].idx].idx = (uint32_t)s; } num_updates++; } } - else if (delta_is_new_only(to)) { - if (!FLAG_SET(&opts, GIT_DIFF_FIND_COPIES) || - best_match->similarity < opts.copy_threshold) + else if (delta_is_new_only(tgt)) { + if (!FLAG_SET(&opts, GIT_DIFF_FIND_COPIES)) + continue; + + if (tgt2src_copy[t].similarity < opts.copy_threshold) continue; - to->status = GIT_DELTA_COPIED; - to->similarity = best_match->similarity; - memcpy(&to->old_file, &from->old_file, sizeof(to->old_file)); + /* always use best possible source for copy */ + best_match = &tgt2src_copy[t]; + src = GIT_VECTOR_GET(&diff->deltas, best_match->idx); + + tgt->status = GIT_DELTA_COPIED; + tgt->similarity = best_match->similarity; + memcpy(&tgt->old_file, &src->old_file, sizeof(tgt->old_file)); num_updates++; } @@ -998,12 +1034,13 @@ find_best_matches: FLAG_SET(&opts, GIT_DIFF_BREAK_REWRITES)); cleanup: - git__free(match_srcs); - git__free(match_tgts); + git__free(tgt2src); + git__free(src2tgt); + git__free(tgt2src_copy); - for (i = 0; i < sigcache_size; ++i) { - if (sigcache[i] != NULL) - opts.metric->free_signature(sigcache[i], opts.metric->payload); + for (t = 0; t < num_deltas * 2; ++t) { + if (sigcache[t] != NULL) + opts.metric->free_signature(sigcache[t], opts.metric->payload); } git__free(sigcache); diff --git a/src/hashsig.c b/src/hashsig.c index a11c4bee7..109f966ba 100644 --- a/src/hashsig.c +++ b/src/hashsig.c @@ -13,12 +13,15 @@ typedef uint64_t hashsig_state; #define HASHSIG_SCALE 100 -#define HASHSIG_HASH_WINDOW 32 -#define HASHSIG_HASH_START 0 +#define HASHSIG_MAX_RUN 80 +#define HASHSIG_HASH_START 0x012345678ABCDEF0LL #define HASHSIG_HASH_SHIFT 5 -#define HASHSIG_HASH_MASK 0x7FFFFFFF + +#define HASHSIG_HASH_MIX(S,CH) \ + (S) = ((S) << HASHSIG_HASH_SHIFT) - (S) + (hashsig_state)(CH) #define HASHSIG_HEAP_SIZE ((1 << 7) - 1) +#define HASHSIG_HEAP_MIN_SIZE 4 typedef int (*hashsig_cmp)(const void *a, const void *b, void *); @@ -28,14 +31,6 @@ typedef struct { hashsig_t values[HASHSIG_HEAP_SIZE]; } hashsig_heap; -typedef struct { - hashsig_state state, shift_n; - char window[HASHSIG_HASH_WINDOW]; - int win_len, win_pos, saw_lf; -} hashsig_in_progress; - -#define HASHSIG_IN_PROGRESS_INIT { HASHSIG_HASH_START, 1, {0}, 0, 0, 1 } - struct git_hashsig { hashsig_heap mins; hashsig_heap maxs; @@ -115,142 +110,109 @@ static void hashsig_heap_sort(hashsig_heap *h) static void hashsig_heap_insert(hashsig_heap *h, hashsig_t val) { - /* if heap is full, pop top if new element should replace it */ - if (h->size == h->asize && h->cmp(&val, &h->values[0], NULL) > 0) { - h->size--; - h->values[0] = h->values[h->size]; - hashsig_heap_down(h, 0); - } - /* if heap is not full, insert new element */ if (h->size < h->asize) { h->values[h->size++] = val; hashsig_heap_up(h, h->size - 1); } -} - -GIT_INLINE(bool) hashsig_include_char( - char ch, git_hashsig_option_t opt, int *saw_lf) -{ - if ((opt & GIT_HASHSIG_IGNORE_WHITESPACE) && git__isspace(ch)) - return false; - - if (opt & GIT_HASHSIG_SMART_WHITESPACE) { - if (ch == '\r' || (*saw_lf && git__isspace(ch))) - return false; - *saw_lf = (ch == '\n'); + /* if heap is full, pop top if new element should replace it */ + else if (h->cmp(&val, &h->values[0], NULL) > 0) { + h->size--; + h->values[0] = h->values[h->size]; + hashsig_heap_down(h, 0); } - return true; } -static void hashsig_initial_window( - git_hashsig *sig, - const char **data, - size_t size, - hashsig_in_progress *prog) -{ - hashsig_state state, shift_n; - int win_len, saw_lf = prog->saw_lf; - const char *scan, *end; - char *window = &prog->window[0]; - - /* init until we have processed at least HASHSIG_HASH_WINDOW data */ - - if (prog->win_len >= HASHSIG_HASH_WINDOW) - return; - - state = prog->state; - win_len = prog->win_len; - shift_n = prog->shift_n; - - scan = *data; - end = scan + size; - - while (scan < end && win_len < HASHSIG_HASH_WINDOW) { - char ch = *scan++; - - if (!hashsig_include_char(ch, sig->opt, &saw_lf)) - continue; - - state = (state * HASHSIG_HASH_SHIFT + ch) & HASHSIG_HASH_MASK; - - if (!win_len) - shift_n = 1; - else - shift_n = (shift_n * HASHSIG_HASH_SHIFT) & HASHSIG_HASH_MASK; - - window[win_len++] = ch; - } - - /* insert initial hash if we just finished */ +typedef struct { + int use_ignores; + uint8_t ignore_ch[256]; +} hashsig_in_progress; - if (win_len == HASHSIG_HASH_WINDOW) { - hashsig_heap_insert(&sig->mins, (hashsig_t)state); - hashsig_heap_insert(&sig->maxs, (hashsig_t)state); - sig->considered = 1; +static void hashsig_in_progress_init( + hashsig_in_progress *prog, git_hashsig *sig) +{ + int i; + + switch (sig->opt) { + case GIT_HASHSIG_IGNORE_WHITESPACE: + for (i = 0; i < 256; ++i) + prog->ignore_ch[i] = git__isspace_nonlf(i); + prog->use_ignores = 1; + break; + case GIT_HASHSIG_SMART_WHITESPACE: + for (i = 0; i < 256; ++i) + prog->ignore_ch[i] = git__isspace(i); + prog->use_ignores = 1; + break; + default: + memset(prog, 0, sizeof(*prog)); + break; } - - prog->state = state; - prog->win_len = win_len; - prog->shift_n = shift_n; - prog->saw_lf = saw_lf; - - *data = scan; } +#define HASHSIG_IN_PROGRESS_INIT { 1 } + static int hashsig_add_hashes( git_hashsig *sig, - const char *data, + const uint8_t *data, size_t size, hashsig_in_progress *prog) { - const char *scan = data, *end = data + size; - hashsig_state state, shift_n, rmv; - int win_pos, saw_lf; - char *window = &prog->window[0]; - - if (prog->win_len < HASHSIG_HASH_WINDOW) - hashsig_initial_window(sig, &scan, size, prog); - - state = prog->state; - shift_n = prog->shift_n; - saw_lf = prog->saw_lf; - win_pos = prog->win_pos; - - /* advance window, adding new chars and removing old */ - - for (; scan < end; ++scan) { - char ch = *scan; - - if (!hashsig_include_char(ch, sig->opt, &saw_lf)) - continue; - - rmv = shift_n * window[win_pos]; + const uint8_t *scan = data, *end = data + size; + hashsig_state state = HASHSIG_HASH_START; + int use_ignores = prog->use_ignores, len; + uint8_t ch; + + while (scan < end) { + state = HASHSIG_HASH_START; + + for (len = 0; scan < end && len < HASHSIG_MAX_RUN; ) { + ch = *scan; + + if (use_ignores) + for (; scan < end && git__isspace_nonlf(ch); ch = *scan) + ++scan; + else if (sig->opt != GIT_HASHSIG_NORMAL) + for (; scan < end && ch == '\r'; ch = *scan) + ++scan; + + /* peek at next character to decide what to do next */ + if (sig->opt == GIT_HASHSIG_SMART_WHITESPACE) + use_ignores = (ch == '\n'); + + if (scan >= end) + break; + ++scan; + + /* check run terminator */ + if (ch == '\n' || ch == '\0') + break; + + ++len; + HASHSIG_HASH_MIX(state, ch); + } - state = (state - rmv) & HASHSIG_HASH_MASK; - state = (state * HASHSIG_HASH_SHIFT) & HASHSIG_HASH_MASK; - state = (state + ch) & HASHSIG_HASH_MASK; + if (len > 0) { + hashsig_heap_insert(&sig->mins, (hashsig_t)state); + hashsig_heap_insert(&sig->maxs, (hashsig_t)state); - hashsig_heap_insert(&sig->mins, (hashsig_t)state); - hashsig_heap_insert(&sig->maxs, (hashsig_t)state); - sig->considered++; + sig->considered++; - window[win_pos] = ch; - win_pos = (win_pos + 1) % HASHSIG_HASH_WINDOW; + while (scan < end && (*scan == '\n' || !*scan)) + ++scan; + } } - prog->state = state; - prog->saw_lf = saw_lf; - prog->win_pos = win_pos; + prog->use_ignores = use_ignores; return 0; } static int hashsig_finalize_hashes(git_hashsig *sig) { - if (sig->mins.size < HASHSIG_HEAP_SIZE) { + if (sig->mins.size < HASHSIG_HEAP_MIN_SIZE) { giterr_set(GITERR_INVALID, "File too small for similarity signature calculation"); return GIT_EBUFS; @@ -282,11 +244,13 @@ int git_hashsig_create( git_hashsig_option_t opts) { int error; - hashsig_in_progress prog = HASHSIG_IN_PROGRESS_INIT; + hashsig_in_progress prog; git_hashsig *sig = hashsig_alloc(opts); GITERR_CHECK_ALLOC(sig); - error = hashsig_add_hashes(sig, buf, buflen, &prog); + hashsig_in_progress_init(&prog, sig); + + error = hashsig_add_hashes(sig, (const uint8_t *)buf, buflen, &prog); if (!error) error = hashsig_finalize_hashes(sig); @@ -304,10 +268,10 @@ int git_hashsig_create_fromfile( const char *path, git_hashsig_option_t opts) { - char buf[0x1000]; + uint8_t buf[0x1000]; ssize_t buflen = 0; int error = 0, fd; - hashsig_in_progress prog = HASHSIG_IN_PROGRESS_INIT; + hashsig_in_progress prog; git_hashsig *sig = hashsig_alloc(opts); GITERR_CHECK_ALLOC(sig); @@ -316,6 +280,8 @@ int git_hashsig_create_fromfile( return fd; } + hashsig_in_progress_init(&prog, sig); + while (!error) { if ((buflen = p_read(fd, buf, sizeof(buf))) <= 0) { if ((error = (int)buflen) < 0) @@ -370,6 +336,12 @@ static int hashsig_heap_compare(const hashsig_heap *a, const hashsig_heap *b) int git_hashsig_compare(const git_hashsig *a, const git_hashsig *b) { - return (hashsig_heap_compare(&a->mins, &b->mins) + - hashsig_heap_compare(&a->maxs, &b->maxs)) / 2; + /* if we have fewer than the maximum number of elements, then just use + * one array since the two arrays will be the same + */ + if (a->mins.size < HASHSIG_HEAP_SIZE) + return hashsig_heap_compare(&a->mins, &b->mins); + else + return (hashsig_heap_compare(&a->mins, &b->mins) + + hashsig_heap_compare(&a->maxs, &b->maxs)) / 2; } diff --git a/src/util.h b/src/util.h index a97c9bf39..ed9624770 100644 --- a/src/util.h +++ b/src/util.h @@ -294,6 +294,11 @@ GIT_INLINE(bool) git__isspace(int c) return (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r' || c == '\v' || c == 0x85 /* Unicode CR+LF */); } +GIT_INLINE(bool) git__isspace_nonlf(int c) +{ + return (c == ' ' || c == '\t' || c == '\f' || c == '\r' || c == '\v' || c == 0x85 /* Unicode CR+LF */); +} + GIT_INLINE(bool) git__iswildcard(int c) { return (c == '*' || c == '?' || c == '['); diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index 5371b2864..8c8357e40 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -34,6 +34,20 @@ void cl_git_report_failure(int, const char *, int, const char *); #define cl_assert_equal_sz(sz1,sz2) cl_assert_equal_i((int)sz1, (int)(sz2)) +GIT_INLINE(void) clar__assert_in_range( + int lo, int val, int hi, + const char *file, int line, const char *err, int should_abort) +{ + if (lo > val || hi < val) { + char buf[128]; + snprintf(buf, sizeof(buf), "%d not in [%d,%d]", val, lo, hi); + clar__fail(file, line, err, buf, should_abort); + } +} + +#define cl_assert_in_range(L,V,H) \ + clar__assert_in_range((L),(V),(H),__FILE__,__LINE__,"Range check: " #V " in [" #L "," #H "]", 1) + /* * Some utility macros for building long strings */ diff --git a/tests-clar/core/buffer.c b/tests-clar/core/buffer.c index 3d8221e04..9d9628cfd 100644 --- a/tests-clar/core/buffer.c +++ b/tests-clar/core/buffer.c @@ -734,10 +734,11 @@ void test_core_buffer__classify_with_utf8(void) } #define SIMILARITY_TEST_DATA_1 \ - "test data\nright here\ninline\ntada\nneeds more data\nlots of data\n" \ - "is this enough?\nthere has to be enough data to fill the hash array!\n" \ - "Apparently 191 bytes is the minimum amount of data needed.\nHere goes!\n" \ - "Let's make sure we've got plenty to go with here.\n smile \n" + "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \ + "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \ + "020\n021\n022\n023\n024\n025\n026\n027\n028\n029\n" \ + "030\n031\n032\n033\n034\n035\n036\n037\n038\n039\n" \ + "040\n041\n042\n043\n044\n045\n046\n047\n048\n049\n" void test_core_buffer__similarity_metric(void) { @@ -761,15 +762,17 @@ void test_core_buffer__similarity_metric(void) cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); cl_git_pass(git_buf_sets(&buf, - "Test data\nright here\ninline\ntada\nneeds more data\nlots of data\n" - "is this enough?\nthere has to be enough data to fill the hash array!\n" - "Apparently 191 bytes is the minimum amount of data needed.\nHere goes!\n" - "Let's make sure we've got plenty to go with here.\n smile \n")); + "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \ + "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \ + "x020x\n021\n022\n023\n024\n025\n026\n027\n028\n029\n" \ + "030\n031\n032\n033\n034\n035\n036\n037\n038\n039\n" \ + "040\n041\n042\n043\n044\n045\n046\n047\n048\n049\n" + )); cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); sim = git_hashsig_compare(a, b); - cl_assert(95 < sim && sim < 100); /* expect >95% similarity */ + cl_assert_in_range(95, sim, 100); /* expect >95% similarity */ git_hashsig_free(a); git_hashsig_free(b); @@ -779,12 +782,13 @@ void test_core_buffer__similarity_metric(void) cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1 - "and if I add some more, it should still be pretty similar, yes?\n")); + "050\n051\n052\n053\n054\n055\n056\n057\n058\n059\n")); cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); sim = git_hashsig_compare(a, b); + /* 20% lines added ~= 10% lines changed */ - cl_assert(70 < sim && sim < 80); /* expect in the 70-80% similarity range */ + cl_assert_in_range(85, sim, 95); /* expect similarity around 90% */ git_hashsig_free(a); git_hashsig_free(b); @@ -794,15 +798,19 @@ void test_core_buffer__similarity_metric(void) cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); cl_git_pass(git_buf_sets(&buf, - "test data\nright here\ninline\ntada\nneeds more data\nlots of data\n" - "is this enough?\nthere has to be enough data to fill the hash array!\n" - "okay, that's half the original\nwhat else can we add?\nmore data\n" - "one more line will complete this\nshort\nlines\ndon't\nmatter\n")); + "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \ + "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \ + "020x\n021\n022\n023\n024\n" \ + "x25\nx26\nx27\nx28\nx29\n" \ + "x30\nx31\nx32\nx33\nx34\nx35\nx36\nx37\nx38\nx39\n" \ + "x40\nx41\nx42\nx43\nx44\nx45\nx46\nx47\nx48\nx49\n" + )); cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); sim = git_hashsig_compare(a, b); + /* 50% lines changed */ - cl_assert(40 < sim && sim < 60); /* expect in the 40-60% similarity range */ + cl_assert_in_range(40, sim, 60); /* expect in the 40-60% similarity range */ git_hashsig_free(a); git_hashsig_free(b); @@ -891,7 +899,7 @@ void test_core_buffer__similarity_metric_whitespace(void) if (i == j) cl_assert_equal_i(100, sim); else - cl_assert(sim < 30); /* expect pretty different */ + cl_assert_in_range(0, sim, 30); /* pretty different */ } else { cl_assert_equal_i(100, sim); } diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index 79c89e362..20ee66288 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -236,6 +236,8 @@ void test_diff_rename__not_exact_match(void) &diff, g_repo, old_tree, new_tree, &diffopts)); opts.flags = GIT_DIFF_FIND_ALL; + opts.break_rewrite_threshold = 70; + cl_git_pass(git_diff_find_similar(diff, &opts)); memset(&exp, 0, sizeof(exp)); @@ -312,8 +314,8 @@ void test_diff_rename__not_exact_match(void) /* the default match algorithm is going to find the internal * whitespace differences in the lines of sixserving.txt to be - * significant enough that this will decide to split it into - * an ADD and a DELETE + * significant enough that this will decide to split it into an ADD + * and a DELETE */ memset(&exp, 0, sizeof(exp)); @@ -480,6 +482,7 @@ void test_diff_rename__working_directory_changes(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &diffopts)); opts.flags = GIT_DIFF_FIND_ALL | GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE; + opts.rename_threshold = 70; cl_git_pass(git_diff_find_similar(diff, &opts)); memset(&exp, 0, sizeof(exp)); @@ -1123,7 +1126,10 @@ void test_diff_rename__unmodified_can_be_renamed(void) git_tree_free(tree); } -void test_diff_rename__many_files(void) +#define ANOTHER_POEM \ +"OH, glorious are the guarded heights\nWhere guardian souls abide—\nSelf-exiled from our gross delights—\nAbove, beyond, outside:\nAn ampler arc their spirit swings—\nCommands a juster view—\nWe have their word for all these things,\nNo doubt their words are true.\n\nYet we, the bond slaves of our day,\nWhom dirt and danger press—\nCo-heirs of insolence, delay,\nAnd leagued unfaithfulness—\nSuch is our need must seek indeed\nAnd, having found, engage\nThe men who merely do the work\nFor which they draw the wage.\n\nFrom forge and farm and mine and bench,\nDeck, altar, outpost lone—\nMill, school, battalion, counter, trench,\nRail, senate, sheepfold, throne—\nCreation's cry goes up on high\nFrom age to cheated age:\n\"Send us the men who do the work\n\"For which they draw the wage!\"\n" + +static void test_with_many(size_t expected_new) { git_index *index; git_tree *tree, *new_tree; @@ -1131,9 +1137,6 @@ void test_diff_rename__many_files(void) diff_expects exp; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - git_buf b = GIT_BUF_INIT; - int i, j; - char tmp[64]; cl_git_pass(git_repository_index(&index, g_repo)); cl_git_pass( @@ -1142,18 +1145,6 @@ void test_diff_rename__many_files(void) cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/ikeepsix2.txt")); cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); cl_git_pass(git_index_add_bypath(index, "ikeepsix2.txt")); - - for (i = 0; i < 100; i += 2) { - snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); - - for (j = 0; j < i * 128; ++j) - git_buf_printf(&b, "more content %d\n", i); - - cl_git_mkfile(tmp, b.ptr); - cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/"))); - } - git_buf_free(&b); - cl_git_pass(git_index_write(index)); cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); @@ -1162,8 +1153,8 @@ void test_diff_rename__many_files(void) cl_git_pass(git_diff_foreach( diff, diff_file_cb, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(51, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(52, exp.files); + cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(expected_new + 2, exp.files); opts.flags = GIT_DIFF_FIND_ALL; cl_git_pass(git_diff_find_similar(diff, &opts)); @@ -1172,8 +1163,8 @@ void test_diff_rename__many_files(void) cl_git_pass(git_diff_foreach( diff, diff_file_cb, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - cl_assert_equal_i(50, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(51, exp.files); + cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(expected_new + 1, exp.files); git_diff_list_free(diff); @@ -1206,8 +1197,8 @@ void test_diff_rename__many_files(void) cl_git_pass(git_diff_foreach( diff, diff_file_cb, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(51, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(52, exp.files); + cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(expected_new + 2, exp.files); opts.flags = GIT_DIFF_FIND_ALL; cl_git_pass(git_diff_find_similar(diff, &opts)); @@ -1216,8 +1207,8 @@ void test_diff_rename__many_files(void) cl_git_pass(git_diff_foreach( diff, diff_file_cb, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - cl_assert_equal_i(50, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(51, exp.files); + cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(expected_new + 1, exp.files); git_diff_list_free(diff); @@ -1225,3 +1216,59 @@ void test_diff_rename__many_files(void) git_tree_free(tree); git_index_free(index); } + +void test_diff_rename__many_files(void) +{ + git_index *index; + char tmp[64]; + int i, j; + git_buf b = GIT_BUF_INIT; + + cl_git_pass(git_repository_index(&index, g_repo)); + + for (i = 0; i < 100; i += 1) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + for (j = i * 256; j > 0; --j) + git_buf_printf(&b, "more content %d\n", i); + cl_git_mkfile(tmp, b.ptr); + } + + for (i = 0; i < 100; i += 1) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/"))); + } + + git_buf_free(&b); + git_index_free(index); + + test_with_many(100); +} + +void test_diff_rename__again_many_files(void) +{ + git_index *index; + char tmp[64]; + int i; + git_buf b = GIT_BUF_INIT; + + cl_git_pass(git_repository_index(&index, g_repo)); + + git_buf_printf(&b, "%08d\n" ANOTHER_POEM "%08d\n" ANOTHER_POEM ANOTHER_POEM, 0, 0); + + for (i = 0; i < 2500; i += 1) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + snprintf(b.ptr, 9, "%08d", i); + b.ptr[8] = '\n'; + cl_git_mkfile(tmp, b.ptr); + } + git_buf_free(&b); + + for (i = 0; i < 2500; i += 1) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/"))); + } + + git_index_free(index); + + test_with_many(2500); +} -- cgit v1.2.1 From a42c2a8c89189afbcfccbc17f798971c18c15de6 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 31 Jul 2013 21:51:50 -0500 Subject: Rename test for multiple similar matches A rename test that illustrates a source matching multiple targets. --- tests-clar/diff/rename.c | 66 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index 20ee66288..108b34621 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -871,6 +871,8 @@ void test_diff_rename__from_deleted_to_split(void) struct rename_expected { size_t len; + + unsigned int *status; const char **sources; const char **targets; @@ -885,7 +887,7 @@ int test_names_expected(const git_diff_delta *delta, float progress, void *p) cl_assert(expected->idx < expected->len); - cl_assert_equal_i(delta->status, GIT_DELTA_RENAMED); + cl_assert_equal_i(delta->status, expected->status[expected->idx]); cl_assert(git__strcmp(expected->sources[expected->idx], delta->old_file.path) == 0); @@ -907,9 +909,10 @@ void test_diff_rename__rejected_match_can_match_others(void) git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; git_buf one = GIT_BUF_INIT, two = GIT_BUF_INIT; + unsigned int status[] = { GIT_DELTA_RENAMED, GIT_DELTA_RENAMED }; const char *sources[] = { "Class1.cs", "Class2.cs" }; const char *targets[] = { "ClassA.cs", "ClassB.cs" }; - struct rename_expected expect = { 2, sources, targets }; + struct rename_expected expect = { 2, status, sources, targets }; char *ptr; opts.checkout_strategy = GIT_CHECKOUT_FORCE; @@ -991,9 +994,10 @@ void test_diff_rename__rejected_match_can_match_others_two(void) git_diff_list *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + unsigned int status[] = { GIT_DELTA_RENAMED, GIT_DELTA_RENAMED }; const char *sources[] = { "a.txt", "b.txt" }; const char *targets[] = { "c.txt", "d.txt" }; - struct rename_expected expect = { 2, sources, targets }; + struct rename_expected expect = { 2, status, sources, targets }; opts.checkout_strategy = GIT_CHECKOUT_FORCE; @@ -1036,6 +1040,62 @@ void test_diff_rename__rejected_match_can_match_others_two(void) git_reference_free(selfsimilar); } +void test_diff_rename__rejected_match_can_match_others_three(void) +{ + git_reference *head, *selfsimilar; + git_index *index; + git_tree *tree; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_diff_list *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + + /* Both cannot be renames from a.txt */ + unsigned int status[] = { GIT_DELTA_ADDED, GIT_DELTA_RENAMED }; + const char *sources[] = { "0001.txt", "a.txt" }; + const char *targets[] = { "0001.txt", "0002.txt" }; + struct rename_expected expect = { 2, status, sources, targets }; + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); + cl_git_pass(git_reference_symbolic_set_target( + &selfsimilar, head, "refs/heads/renames_similar_two")); + cl_git_pass(git_checkout_head(g_repo, &opts)); + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_pass(p_unlink("renames/a.txt")); + + cl_git_pass(git_index_remove_bypath(index, "a.txt")); + + write_similarity_file_two("renames/0001.txt", 7); + write_similarity_file_two("renames/0002.txt", 0); + + cl_git_pass(git_index_add_bypath(index, "0001.txt")); + cl_git_pass(git_index_add_bypath(index, "0002.txt")); + + cl_git_pass(git_index_write(index)); + + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass( + git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + cl_git_pass(git_diff_find_similar(diff, &findopts)); + + cl_git_pass( + git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); + + cl_assert(expect.idx == expect.len); + + git_diff_list_free(diff); + git_tree_free(tree); + git_index_free(index); + git_reference_free(head); + git_reference_free(selfsimilar); +} + void test_diff_rename__case_changes_are_split(void) { git_index *index; -- cgit v1.2.1 From 7edb74d374f401cea50be143b63c7d2d141d18be Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sun, 4 Aug 2013 14:06:13 -0700 Subject: Update rename src map for any split src When using a rename source that is actually a to-be-split record, we have to update the best-fit mapping data in both the case where the target is also a split record and the case where the target is a simple added record. Before this commit, we were only doing the update when the target was itself a split record (and even in that case, the test was slightly wrong). --- src/diff_tform.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/diff_tform.c b/src/diff_tform.c index 92c4036fb..ba35d3c14 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -947,6 +947,11 @@ find_best_matches: src->new_file.flags |= GIT_DIFF_FLAG_VALID_OID; num_updates++; + + if (src2tgt[t].similarity > 0 && src2tgt[t].idx > t) { + /* what used to be at src t is now at src s */ + tgt2src[src2tgt[t].idx].idx = (uint32_t)s; + } } } @@ -996,7 +1001,7 @@ find_best_matches: num_rewrites--; } /* otherwise, if we just overwrote a source, update mapping */ - else if (s > t && src2tgt[t].similarity > 0) { + else if (src2tgt[t].similarity > 0 && src2tgt[t].idx > t) { /* what used to be at src t is now at src s */ tgt2src[src2tgt[t].idx].idx = (uint32_t)s; } -- cgit v1.2.1 From 0a38eb42ca207f7aeb9e48a172fdbbc587201eb1 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 31 Jul 2013 22:36:50 -0500 Subject: Rename test for rename from rewrite A rename test that illustrates a rename from a rewrite. --- tests-clar/diff/rename.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index 108b34621..b78122c7e 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -1096,6 +1096,56 @@ void test_diff_rename__rejected_match_can_match_others_three(void) git_reference_free(selfsimilar); } +void test_diff_rename__can_rename_from_rewrite(void) +{ + git_index *index; + git_tree *tree; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_diff_list *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + + unsigned int status[] = { GIT_DELTA_RENAMED, GIT_DELTA_RENAMED }; + const char *sources[] = { "ikeepsix.txt", "songof7cities.txt" }; + const char *targets[] = { "songof7cities.txt", "this-is-a-rename.txt" }; + struct rename_expected expect = { 2, status, sources, targets }; + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_pass(p_rename("renames/songof7cities.txt", "renames/this-is-a-rename.txt")); + cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/songof7cities.txt")); + + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + + cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); + cl_git_pass(git_index_add_bypath(index, "this-is-a-rename.txt")); + + cl_git_pass(git_index_write(index)); + + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass( + git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + findopts.flags |= GIT_DIFF_FIND_AND_BREAK_REWRITES | + GIT_DIFF_FIND_REWRITES | + GIT_DIFF_FIND_RENAMES_FROM_REWRITES; + + cl_git_pass(git_diff_find_similar(diff, &findopts)); + + cl_git_pass( + git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); + + cl_assert(expect.idx == expect.len); + + git_diff_list_free(diff); + git_tree_free(tree); + git_index_free(index); +} + void test_diff_rename__case_changes_are_split(void) { git_index *index; @@ -1284,6 +1334,8 @@ void test_diff_rename__many_files(void) int i, j; git_buf b = GIT_BUF_INIT; +/* + cl_git_pass(git_repository_index(&index, g_repo)); for (i = 0; i < 100; i += 1) { @@ -1302,6 +1354,7 @@ void test_diff_rename__many_files(void) git_index_free(index); test_with_many(100); +*/ } void test_diff_rename__again_many_files(void) @@ -1311,6 +1364,8 @@ void test_diff_rename__again_many_files(void) int i; git_buf b = GIT_BUF_INIT; +/* + cl_git_pass(git_repository_index(&index, g_repo)); git_buf_printf(&b, "%08d\n" ANOTHER_POEM "%08d\n" ANOTHER_POEM ANOTHER_POEM, 0, 0); @@ -1331,4 +1386,5 @@ void test_diff_rename__again_many_files(void) git_index_free(index); test_with_many(2500); +*/ } -- cgit v1.2.1 From 31b42eacce29defe07bdc1fa50a21aa11b23ea83 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sun, 4 Aug 2013 14:09:44 -0700 Subject: Restore commented out tests This restores the commented out tests (even though they're slow) and fixes some trailing whitespace. --- tests-clar/diff/rename.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index b78122c7e..55555012a 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -871,7 +871,7 @@ void test_diff_rename__from_deleted_to_split(void) struct rename_expected { size_t len; - + unsigned int *status; const char **sources; const char **targets; @@ -1129,7 +1129,7 @@ void test_diff_rename__can_rename_from_rewrite(void) cl_git_pass( git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - + findopts.flags |= GIT_DIFF_FIND_AND_BREAK_REWRITES | GIT_DIFF_FIND_REWRITES | GIT_DIFF_FIND_RENAMES_FROM_REWRITES; @@ -1334,8 +1334,6 @@ void test_diff_rename__many_files(void) int i, j; git_buf b = GIT_BUF_INIT; -/* - cl_git_pass(git_repository_index(&index, g_repo)); for (i = 0; i < 100; i += 1) { @@ -1354,7 +1352,6 @@ void test_diff_rename__many_files(void) git_index_free(index); test_with_many(100); -*/ } void test_diff_rename__again_many_files(void) @@ -1364,8 +1361,6 @@ void test_diff_rename__again_many_files(void) int i; git_buf b = GIT_BUF_INIT; -/* - cl_git_pass(git_repository_index(&index, g_repo)); git_buf_printf(&b, "%08d\n" ANOTHER_POEM "%08d\n" ANOTHER_POEM ANOTHER_POEM, 0, 0); @@ -1386,5 +1381,4 @@ void test_diff_rename__again_many_files(void) git_index_free(index); test_with_many(2500); -*/ } -- cgit v1.2.1 From e8242022bc409b3cb7e234eabdd9bda05ae3a158 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 5 Aug 2013 09:59:02 -0700 Subject: Move slow tests to "stress" clar module Create a new section of clar tests "stress" that will default to being off where we can put slow tests that push the library for performance testing purposes. --- CMakeLists.txt | 2 +- tests-clar/diff/rename.c | 147 ------------------------------------------ tests-clar/stress/diff.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 148 deletions(-) create mode 100644 tests-clar/stress/diff.c diff --git a/CMakeLists.txt b/CMakeLists.txt index c937ba93c..53f568ed3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -361,7 +361,7 @@ IF (BUILD_CLAR) ADD_CUSTOM_COMMAND( OUTPUT ${CLAR_PATH}/clar.suite - COMMAND ${PYTHON_EXECUTABLE} generate.py -f -xonline . + COMMAND ${PYTHON_EXECUTABLE} generate.py -f -xonline -xstress . DEPENDS ${SRC_TEST} WORKING_DIRECTORY ${CLAR_PATH} ) diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index 55555012a..5a35495f7 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -1235,150 +1235,3 @@ void test_diff_rename__unmodified_can_be_renamed(void) git_index_free(index); git_tree_free(tree); } - -#define ANOTHER_POEM \ -"OH, glorious are the guarded heights\nWhere guardian souls abide—\nSelf-exiled from our gross delights—\nAbove, beyond, outside:\nAn ampler arc their spirit swings—\nCommands a juster view—\nWe have their word for all these things,\nNo doubt their words are true.\n\nYet we, the bond slaves of our day,\nWhom dirt and danger press—\nCo-heirs of insolence, delay,\nAnd leagued unfaithfulness—\nSuch is our need must seek indeed\nAnd, having found, engage\nThe men who merely do the work\nFor which they draw the wage.\n\nFrom forge and farm and mine and bench,\nDeck, altar, outpost lone—\nMill, school, battalion, counter, trench,\nRail, senate, sheepfold, throne—\nCreation's cry goes up on high\nFrom age to cheated age:\n\"Send us the men who do the work\n\"For which they draw the wage!\"\n" - -static void test_with_many(size_t expected_new) -{ - git_index *index; - git_tree *tree, *new_tree; - git_diff_list *diff = NULL; - diff_expects exp; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/ikeepsix2.txt")); - cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_add_bypath(index, "ikeepsix2.txt")); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &exp)); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(expected_new + 2, exp.files); - - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &exp)); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(expected_new + 1, exp.files); - - git_diff_list_free(diff); - - { - git_object *parent; - git_signature *sig; - git_oid tree_id, commit_id; - git_reference *ref; - - cl_git_pass(git_index_write_tree(&tree_id, index)); - cl_git_pass(git_tree_lookup(&new_tree, g_repo, &tree_id)); - - cl_git_pass(git_revparse_ext(&parent, &ref, g_repo, "HEAD")); - cl_git_pass(git_signature_new( - &sig, "Sm Test", "sm@tester.test", 1372350000, 480)); - - cl_git_pass(git_commit_create_v( - &commit_id, g_repo, git_reference_name(ref), sig, sig, - NULL, "yoyoyo", new_tree, 1, parent)); - - git_object_free(parent); - git_reference_free(ref); - git_signature_free(sig); - } - - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, tree, new_tree, &diffopts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &exp)); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(expected_new + 2, exp.files); - - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &exp)); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(expected_new + 1, exp.files); - - git_diff_list_free(diff); - - git_tree_free(new_tree); - git_tree_free(tree); - git_index_free(index); -} - -void test_diff_rename__many_files(void) -{ - git_index *index; - char tmp[64]; - int i, j; - git_buf b = GIT_BUF_INIT; - - cl_git_pass(git_repository_index(&index, g_repo)); - - for (i = 0; i < 100; i += 1) { - snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); - for (j = i * 256; j > 0; --j) - git_buf_printf(&b, "more content %d\n", i); - cl_git_mkfile(tmp, b.ptr); - } - - for (i = 0; i < 100; i += 1) { - snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); - cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/"))); - } - - git_buf_free(&b); - git_index_free(index); - - test_with_many(100); -} - -void test_diff_rename__again_many_files(void) -{ - git_index *index; - char tmp[64]; - int i; - git_buf b = GIT_BUF_INIT; - - cl_git_pass(git_repository_index(&index, g_repo)); - - git_buf_printf(&b, "%08d\n" ANOTHER_POEM "%08d\n" ANOTHER_POEM ANOTHER_POEM, 0, 0); - - for (i = 0; i < 2500; i += 1) { - snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); - snprintf(b.ptr, 9, "%08d", i); - b.ptr[8] = '\n'; - cl_git_mkfile(tmp, b.ptr); - } - git_buf_free(&b); - - for (i = 0; i < 2500; i += 1) { - snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); - cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/"))); - } - - git_index_free(index); - - test_with_many(2500); -} diff --git a/tests-clar/stress/diff.c b/tests-clar/stress/diff.c new file mode 100644 index 000000000..62ccd5ec7 --- /dev/null +++ b/tests-clar/stress/diff.c @@ -0,0 +1,164 @@ +#include "clar_libgit2.h" +#include "../diff/diff_helpers.h" + +static git_repository *g_repo = NULL; + +void test_stress_diff__initialize(void) +{ +} + +void test_stress_diff__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +#define ANOTHER_POEM \ +"OH, glorious are the guarded heights\nWhere guardian souls abide—\nSelf-exiled from our gross delights—\nAbove, beyond, outside:\nAn ampler arc their spirit swings—\nCommands a juster view—\nWe have their word for all these things,\nNo doubt their words are true.\n\nYet we, the bond slaves of our day,\nWhom dirt and danger press—\nCo-heirs of insolence, delay,\nAnd leagued unfaithfulness—\nSuch is our need must seek indeed\nAnd, having found, engage\nThe men who merely do the work\nFor which they draw the wage.\n\nFrom forge and farm and mine and bench,\nDeck, altar, outpost lone—\nMill, school, battalion, counter, trench,\nRail, senate, sheepfold, throne—\nCreation's cry goes up on high\nFrom age to cheated age:\n\"Send us the men who do the work\n\"For which they draw the wage!\"\n" + +static void test_with_many(size_t expected_new) +{ + git_index *index; + git_tree *tree, *new_tree; + git_diff_list *diff = NULL; + diff_expects exp; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/ikeepsix2.txt")); + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "ikeepsix2.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &exp)); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(expected_new + 2, exp.files); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &exp)); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(expected_new + 1, exp.files); + + git_diff_list_free(diff); + + { + git_object *parent; + git_signature *sig; + git_oid tree_id, commit_id; + git_reference *ref; + + cl_git_pass(git_index_write_tree(&tree_id, index)); + cl_git_pass(git_tree_lookup(&new_tree, g_repo, &tree_id)); + + cl_git_pass(git_revparse_ext(&parent, &ref, g_repo, "HEAD")); + cl_git_pass(git_signature_new( + &sig, "Sm Test", "sm@tester.test", 1372350000, 480)); + + cl_git_pass(git_commit_create_v( + &commit_id, g_repo, git_reference_name(ref), sig, sig, + NULL, "yoyoyo", new_tree, 1, parent)); + + git_object_free(parent); + git_reference_free(ref); + git_signature_free(sig); + } + + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, tree, new_tree, &diffopts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &exp)); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(expected_new + 2, exp.files); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &exp)); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(expected_new + 1, exp.files); + + git_diff_list_free(diff); + + git_tree_free(new_tree); + git_tree_free(tree); + git_index_free(index); +} + +void test_stress_diff__rename_big_files(void) +{ + git_index *index; + char tmp[64]; + int i, j; + git_buf b = GIT_BUF_INIT; + + g_repo = cl_git_sandbox_init("renames"); + + cl_git_pass(git_repository_index(&index, g_repo)); + + for (i = 0; i < 100; i += 1) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + for (j = i * 256; j > 0; --j) + git_buf_printf(&b, "more content %d\n", i); + cl_git_mkfile(tmp, b.ptr); + } + + for (i = 0; i < 100; i += 1) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/"))); + } + + git_buf_free(&b); + git_index_free(index); + + test_with_many(100); +} + +void test_stress_diff__rename_many_files(void) +{ + git_index *index; + char tmp[64]; + int i; + git_buf b = GIT_BUF_INIT; + + g_repo = cl_git_sandbox_init("renames"); + + cl_git_pass(git_repository_index(&index, g_repo)); + + git_buf_printf(&b, "%08d\n" ANOTHER_POEM "%08d\n" ANOTHER_POEM ANOTHER_POEM, 0, 0); + + for (i = 0; i < 2500; i += 1) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + snprintf(b.ptr, 9, "%08d", i); + b.ptr[8] = '\n'; + cl_git_mkfile(tmp, b.ptr); + } + git_buf_free(&b); + + for (i = 0; i < 2500; i += 1) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/"))); + } + + git_index_free(index); + + test_with_many(2500); +} -- cgit v1.2.1 From 9b7d02ff2d9b87d61778ee7ef5e2d43bf4c561f0 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 5 Aug 2013 10:53:39 -0700 Subject: Update submodule documentation Fixes #1762 --- include/git2/submodule.h | 51 +++++++++++++++++++++++++++++++++++------------- include/git2/types.h | 51 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 81 insertions(+), 21 deletions(-) diff --git a/include/git2/submodule.h b/include/git2/submodule.h index ba7a558d0..186f263f5 100644 --- a/include/git2/submodule.h +++ b/include/git2/submodule.h @@ -316,9 +316,10 @@ GIT_EXTERN(const git_oid *) git_submodule_head_id(git_submodule *submodule); GIT_EXTERN(const git_oid *) git_submodule_wd_id(git_submodule *submodule); /** - * Get the ignore rule for the submodule. + * Get the ignore rule that will be used for the submodule. * - * There are four ignore values: + * These values control the behavior of `git_submodule_status()` for this + * submodule. There are four ignore values: * * - **GIT_SUBMODULE_IGNORE_NONE** will consider any change to the contents * of the submodule from a clean checkout to be dirty, including the @@ -332,6 +333,13 @@ GIT_EXTERN(const git_oid *) git_submodule_wd_id(git_submodule *submodule); * - **GIT_SUBMODULE_IGNORE_ALL** means not to open the submodule repo. * The working directory will be consider clean so long as there is a * checked out version present. + * + * plus the special **GIT_SUBMODULE_IGNORE_RESET** which can be used with + * `git_submodule_set_ignore()` to revert to the on-disk setting. + * + * @param submodule The submodule to check + * @return The current git_submodule_ignore_t valyue what will be used for + * this submodule. */ GIT_EXTERN(git_submodule_ignore_t) git_submodule_ignore( git_submodule *submodule); @@ -339,15 +347,17 @@ GIT_EXTERN(git_submodule_ignore_t) git_submodule_ignore( /** * Set the ignore rule for the submodule. * - * This sets the ignore rule in memory for the submodule. This will be used - * for any following actions (such as `git_submodule_status()`) while the - * submodule is in memory. You should call `git_submodule_save()` if you - * want to persist the new ignore role. + * This sets the in-memory ignore rule for the submodule which will + * control the behavior of `git_submodule_status()`. + * + * To make changes persistent, call `git_submodule_save()` to write the + * value to disk (in the ".gitmodules" and ".git/config" files). * - * Calling this again with GIT_SUBMODULE_IGNORE_RESET or calling - * `git_submodule_reload()` will revert the rule to the value that was in - * the original config. + * Call with `GIT_SUBMODULE_IGNORE_RESET` or call `git_submodule_reload()` + * to revert the in-memory rule to the value that is on disk. * + * @param submodule The submodule to update + * @param ignore The new value for the ignore rule * @return old value for ignore */ GIT_EXTERN(git_submodule_ignore_t) git_submodule_set_ignore( @@ -355,7 +365,16 @@ GIT_EXTERN(git_submodule_ignore_t) git_submodule_set_ignore( git_submodule_ignore_t ignore); /** - * Get the update rule for the submodule. + * Get the update rule that will be used for the submodule. + * + * This value controls the behavior of the `git submodule update` command. + * There are four useful values documented with `git_submodule_update_t` + * plus the `GIT_SUBMODULE_UPDATE_RESET` which can be used to revert to + * the on-disk setting. + * + * @param submodule The submodule to check + * @return The current git_submodule_update_t value that will be used + * for this submodule. */ GIT_EXTERN(git_submodule_update_t) git_submodule_update( git_submodule *submodule); @@ -363,13 +382,17 @@ GIT_EXTERN(git_submodule_update_t) git_submodule_update( /** * Set the update rule for the submodule. * - * This sets the update rule in memory for the submodule. You should call - * `git_submodule_save()` if you want to persist the new update rule. + * The initial value comes from the ".git/config" setting of + * `submodule.$name.update` for this submodule (which is initialized from + * the ".gitmodules" file). Using this function sets the update rule in + * memory for the submodule. Call `git_submodule_save()` to write out the + * new update rule. * * Calling this again with GIT_SUBMODULE_UPDATE_RESET or calling - * `git_submodule_reload()` will revert the rule to the value that was in - * the original config. + * `git_submodule_reload()` will revert the rule to the on disk value. * + * @param submodule The submodule to update + * @param update The new value to use * @return old value for update */ GIT_EXTERN(git_submodule_update_t) git_submodule_set_update( diff --git a/include/git2/types.h b/include/git2/types.h index 1da0d3ed2..b500c986d 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -235,10 +235,29 @@ typedef int (*git_transfer_progress_callback)(const git_transfer_progress *stats typedef struct git_submodule git_submodule; /** - * Values that could be specified for the update rule of a submodule. + * Submodule update values * - * Use the RESET value if you have altered the in-memory update value via - * `git_submodule_set_update()` and wish to reset to the original default. + * These values represent settings for the `submodule.$name.update` + * configuration value which says how to handle `git submodule update` for + * this submodule. The value is usually set in the ".gitmodules" file and + * copied to ".git/config" when the submodule is initialized. + * + * You can override this setting on a per-submodule basis with + * `git_submodule_set_update()` and write the changed value to disk using + * `git_submodule_save()`. If you have overwritten the value, you can + * revert it by passing `GIT_SUBMODULE_UPDATE_RESET` to the set function. + * + * The values are: + * + * - GIT_SUBMODULE_UPDATE_RESET: reset to the on-disk value. + * - GIT_SUBMODULE_UPDATE_CHECKOUT: the default; when a submodule is + * updated, checkout the new detached HEAD to the submodule directory. + * - GIT_SUBMODULE_UPDATE_REBASE: update by rebasing the current checked + * out branch onto the commit from the superproject. + * - GIT_SUBMODULE_UPDATE_MERGE: update by merging the commit in the + * superproject into the current checkout out branch of the submodule. + * - GIT_SUBMODULE_UPDATE_NONE: do not update this submodule even when + * the commit in the superproject is updated. */ typedef enum { GIT_SUBMODULE_UPDATE_RESET = -1, @@ -249,11 +268,29 @@ typedef enum { } git_submodule_update_t; /** - * Values that could be specified for how closely to examine the - * working directory when getting submodule status. + * Submodule ignore values + * + * These values represent settings for the `submodule.$name.ignore` + * configuration value which says how deeply to look at the working + * directory when getting submodule status. + * + * You can override this value in memory on a per-submodule basis with + * `git_submodule_set_ignore()` and can write the changed value to disk + * with `git_submodule_save()`. If you have overwritten the value, you + * can revert to the on disk value by using `GIT_SUBMODULE_IGNORE_RESET`. + * + * The values are: * - * Use the RESET value if you have altered the in-memory ignore value via - * `git_submodule_set_ignore()` and wish to reset to the original value. + * - GIT_SUBMODULE_IGNORE_RESET: reset to the on-disk value. + * - GIT_SUBMODULE_IGNORE_NONE: don't ignore any change - i.e. even an + * untracked file, will mark the submodule as dirty. Ignored files are + * still ignored, of course. + * - GIT_SUBMODULE_IGNORE_UNTRACKED: ignore untracked files; only changes + * to tracked files, or the index or the HEAD commit will matter. + * - GIT_SUBMODULE_IGNORE_DIRTY: ignore changes in the working directory, + * only considering changes if the HEAD of submodule has moved from the + * value in the superproject. + * - GIT_SUBMODULE_IGNORE_ALL: never check if the submodule is dirty */ typedef enum { GIT_SUBMODULE_IGNORE_RESET = -1, /* reset to on-disk value */ -- cgit v1.2.1 From d85636190f127efa2ec4a6593124c037dfec0ba9 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 5 Aug 2013 11:41:39 -0700 Subject: Split UTF-16 and UTF-8 buffer sizes for win32 Also fixed up call-sites to use the correct buffer sizes, especially when converting to utf-8. --- src/fileops.c | 4 +-- src/path.c | 4 +-- src/transports/winhttp.c | 4 +-- src/win32/dir.c | 12 ++++----- src/win32/dir.h | 2 +- src/win32/posix.h | 4 +-- src/win32/posix_w32.c | 66 +++++++++++++++++++++++------------------------ src/win32/utf-conv.c | 2 +- src/win32/utf-conv.h | 3 ++- tests-clar/clar_libgit2.c | 22 ++++++++-------- 10 files changed, 62 insertions(+), 61 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 7f8418d7a..36fcc73df 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -58,9 +58,9 @@ int git_futils_creat_locked(const char *path, const mode_t mode) int fd; #ifdef GIT_WIN32 - wchar_t buf[GIT_WIN_PATH]; + wchar_t buf[GIT_WIN_PATH_UTF16]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); fd = _wopen(buf, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY | O_CLOEXEC, mode); #else diff --git a/src/path.c b/src/path.c index 6437979d5..ca0cc8c7c 100644 --- a/src/path.c +++ b/src/path.c @@ -486,14 +486,14 @@ bool git_path_is_empty_dir(const char *path) { git_buf pathbuf = GIT_BUF_INIT; HANDLE hFind = INVALID_HANDLE_VALUE; - wchar_t wbuf[GIT_WIN_PATH]; + wchar_t wbuf[GIT_WIN_PATH_UTF16]; WIN32_FIND_DATAW ffd; bool retval = true; if (!git_path_isdir(path)) return false; git_buf_printf(&pathbuf, "%s\\*", path); - git__utf8_to_16(wbuf, GIT_WIN_PATH, git_buf_cstr(&pathbuf)); + git__utf8_to_16(wbuf, GIT_WIN_PATH_UTF16, git_buf_cstr(&pathbuf)); hFind = FindFirstFileW(wbuf, &ffd); if (INVALID_HANDLE_VALUE == hFind) { diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 95e422dc0..6064f90d8 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -893,7 +893,7 @@ static int winhttp_connect( const char *url) { wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")"; - wchar_t host[GIT_WIN_PATH]; + wchar_t host[GIT_WIN_PATH_UTF16]; int32_t port; const char *default_port = "80"; int ret; @@ -920,7 +920,7 @@ static int winhttp_connect( return -1; /* Prepare host */ - git__utf8_to_16(host, GIT_WIN_PATH, t->host); + git__utf8_to_16(host, GIT_WIN_PATH_UTF16, t->host); /* Establish session */ t->session = WinHttpOpen( diff --git a/src/win32/dir.c b/src/win32/dir.c index 8c51d8378..b18c603f7 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -25,8 +25,8 @@ static int init_filter(char *filter, size_t n, const char *dir) git__DIR *git__opendir(const char *dir) { - char filter[GIT_WIN_PATH]; - wchar_t filter_w[GIT_WIN_PATH]; + char filter[GIT_WIN_PATH_UTF8]; + wchar_t filter_w[GIT_WIN_PATH_UTF16]; git__DIR *new = NULL; if (!dir || !init_filter(filter, sizeof(filter), dir)) @@ -40,7 +40,7 @@ git__DIR *git__opendir(const char *dir) if (!new->dir) goto fail; - git__utf8_to_16(filter_w, GIT_WIN_PATH, filter); + git__utf8_to_16(filter_w, GIT_WIN_PATH_UTF16, filter); new->h = FindFirstFileW(filter_w, &new->f); if (new->h == INVALID_HANDLE_VALUE) { @@ -101,8 +101,8 @@ struct git__dirent *git__readdir(git__DIR *d) void git__rewinddir(git__DIR *d) { - char filter[GIT_WIN_PATH]; - wchar_t filter_w[GIT_WIN_PATH]; + char filter[GIT_WIN_PATH_UTF8]; + wchar_t filter_w[GIT_WIN_PATH_UTF16]; if (!d) return; @@ -116,7 +116,7 @@ void git__rewinddir(git__DIR *d) if (!init_filter(filter, sizeof(filter), d->dir)) return; - git__utf8_to_16(filter_w, GIT_WIN_PATH, filter); + git__utf8_to_16(filter_w, GIT_WIN_PATH_UTF16, filter); d->h = FindFirstFileW(filter_w, &d->f); if (d->h == INVALID_HANDLE_VALUE) diff --git a/src/win32/dir.h b/src/win32/dir.h index 7696d468e..a3e154972 100644 --- a/src/win32/dir.h +++ b/src/win32/dir.h @@ -11,7 +11,7 @@ struct git__dirent { int d_ino; - char d_name[261]; + char d_name[260*4+1]; }; typedef struct { diff --git a/src/win32/posix.h b/src/win32/posix.h index c49c2175c..753f35a2d 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -20,9 +20,9 @@ GIT_INLINE(int) p_link(const char *old, const char *new) GIT_INLINE(int) p_mkdir(const char *path, mode_t mode) { - wchar_t buf[GIT_WIN_PATH]; + wchar_t buf[GIT_WIN_PATH_UTF16]; GIT_UNUSED(mode); - git__utf8_to_16(buf, GIT_WIN_PATH, path); + git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); return _wmkdir(buf); } diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 036632e2a..a96741d1c 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -16,8 +16,8 @@ int p_unlink(const char *path) { - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + wchar_t buf[GIT_WIN_PATH_UTF16]; + git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); _wchmod(buf, 0666); return _wunlink(buf); } @@ -59,10 +59,10 @@ static int do_lstat( const char *file_name, struct stat *buf, int posix_enotdir) { WIN32_FILE_ATTRIBUTE_DATA fdata; - wchar_t fbuf[GIT_WIN_PATH], lastch; + wchar_t fbuf[GIT_WIN_PATH_UTF16], lastch; int flen; - flen = git__utf8_to_16(fbuf, GIT_WIN_PATH, file_name); + flen = git__utf8_to_16(fbuf, GIT_WIN_PATH_UTF16, file_name); /* truncate trailing slashes */ for (; flen > 0; --flen) { @@ -108,10 +108,10 @@ static int do_lstat( * the length of the path pointed to, which we expect everywhere else */ if (S_ISLNK(fMode)) { - char target[GIT_WIN_PATH]; + char target[GIT_WIN_PATH_UTF8]; int readlink_result; - readlink_result = p_readlink(file_name, target, GIT_WIN_PATH); + readlink_result = p_readlink(file_name, target, GIT_WIN_PATH_UTF8); if (readlink_result == -1) return -1; @@ -165,7 +165,7 @@ int p_readlink(const char *link, char *target, size_t target_len) static fpath_func pGetFinalPath = NULL; HANDLE hFile; DWORD dwRet; - wchar_t link_w[GIT_WIN_PATH]; + wchar_t link_w[GIT_WIN_PATH_UTF16]; wchar_t* target_w; int error = 0; @@ -188,7 +188,7 @@ int p_readlink(const char *link, char *target, size_t target_len) } } - git__utf8_to_16(link_w, GIT_WIN_PATH, link); + git__utf8_to_16(link_w, GIT_WIN_PATH_UTF16, link); hFile = CreateFileW(link_w, // file to open GENERIC_READ, // open for reading @@ -254,10 +254,10 @@ int p_symlink(const char *old, const char *new) int p_open(const char *path, int flags, ...) { - wchar_t buf[GIT_WIN_PATH]; + wchar_t buf[GIT_WIN_PATH_UTF16]; mode_t mode = 0; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); if (flags & O_CREAT) { va_list arg_list; @@ -272,8 +272,8 @@ int p_open(const char *path, int flags, ...) int p_creat(const char *path, mode_t mode) { - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + wchar_t buf[GIT_WIN_PATH_UTF16]; + git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); return _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode); } @@ -299,7 +299,7 @@ int p_getcwd(char *buffer_out, size_t size) int p_stat(const char* path, struct stat* buf) { - char target[GIT_WIN_PATH]; + char target[GIT_WIN_PATH_UTF8]; int error = 0; error = do_lstat(path, buf, 0); @@ -307,7 +307,7 @@ int p_stat(const char* path, struct stat* buf) /* We need not do this in a loop to unwind chains of symlinks since * p_readlink calls GetFinalPathNameByHandle which does it for us. */ if (error >= 0 && S_ISLNK(buf->st_mode) && - (error = p_readlink(path, target, GIT_WIN_PATH)) >= 0) + (error = p_readlink(path, target, GIT_WIN_PATH_UTF8)) >= 0) error = do_lstat(target, buf, 0); return error; @@ -315,23 +315,23 @@ int p_stat(const char* path, struct stat* buf) int p_chdir(const char* path) { - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + wchar_t buf[GIT_WIN_PATH_UTF16]; + git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); return _wchdir(buf); } int p_chmod(const char* path, mode_t mode) { - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + wchar_t buf[GIT_WIN_PATH_UTF16]; + git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); return _wchmod(buf, mode); } int p_rmdir(const char* path) { int error; - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + wchar_t buf[GIT_WIN_PATH_UTF16]; + git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); error = _wrmdir(buf); @@ -347,24 +347,24 @@ int p_rmdir(const char* path) int p_hide_directory__w32(const char *path) { - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + wchar_t buf[GIT_WIN_PATH_UTF16]; + git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); return (SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0) ? 0 : -1; } char *p_realpath(const char *orig_path, char *buffer) { int ret; - wchar_t orig_path_w[GIT_WIN_PATH]; - wchar_t buffer_w[GIT_WIN_PATH]; + wchar_t orig_path_w[GIT_WIN_PATH_UTF16]; + wchar_t buffer_w[GIT_WIN_PATH_UTF16]; - git__utf8_to_16(orig_path_w, GIT_WIN_PATH, orig_path); + git__utf8_to_16(orig_path_w, GIT_WIN_PATH_UTF16, orig_path); /* Implicitly use GetCurrentDirectory which can be a threading issue */ - ret = GetFullPathNameW(orig_path_w, GIT_WIN_PATH, buffer_w, NULL); + ret = GetFullPathNameW(orig_path_w, GIT_WIN_PATH_UTF16, buffer_w, NULL); /* According to MSDN, a return value equals to zero means a failure. */ - if (ret == 0 || ret > GIT_WIN_PATH) + if (ret == 0 || ret > GIT_WIN_PATH_UTF16) buffer = NULL; else if (GetFileAttributesW(buffer_w) == INVALID_FILE_ATTRIBUTES) { @@ -448,18 +448,18 @@ int p_setenv(const char* name, const char* value, int overwrite) int p_access(const char* path, mode_t mode) { - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + wchar_t buf[GIT_WIN_PATH_UTF16]; + git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); return _waccess(buf, mode); } int p_rename(const char *from, const char *to) { - wchar_t wfrom[GIT_WIN_PATH]; - wchar_t wto[GIT_WIN_PATH]; + wchar_t wfrom[GIT_WIN_PATH_UTF16]; + wchar_t wto[GIT_WIN_PATH_UTF16]; - git__utf8_to_16(wfrom, GIT_WIN_PATH, from); - git__utf8_to_16(wto, GIT_WIN_PATH, to); + git__utf8_to_16(wfrom, GIT_WIN_PATH_UTF16, from); + git__utf8_to_16(wto, GIT_WIN_PATH_UTF16, to); return MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? 0 : -1; } diff --git a/src/win32/utf-conv.c b/src/win32/utf-conv.c index c06f3a8c2..78d277494 100644 --- a/src/win32/utf-conv.c +++ b/src/win32/utf-conv.c @@ -77,5 +77,5 @@ int git__utf8_to_16(wchar_t *dest, size_t length, const char *src) int git__utf16_to_8(char *out, const wchar_t *input) { - return WideCharToMultiByte(CP_UTF8, 0, input, -1, out, GIT_WIN_PATH, NULL, NULL); + return WideCharToMultiByte(CP_UTF8, 0, input, -1, out, GIT_WIN_PATH_UTF8, NULL, NULL); } diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h index 6cc9205f7..9922e2969 100644 --- a/src/win32/utf-conv.h +++ b/src/win32/utf-conv.h @@ -10,7 +10,8 @@ #ifndef INCLUDE_git_utfconv_h__ #define INCLUDE_git_utfconv_h__ -#define GIT_WIN_PATH (260 + 1) +#define GIT_WIN_PATH_UTF16 (260 + 1) +#define GIT_WIN_PATH_UTF8 (260 * 4 + 1) int git__utf8_to_16(wchar_t *dest, size_t length, const char *src); int git__utf16_to_8(char *dest, const wchar_t *src); diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index de0e41bf7..34d54cd94 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -56,17 +56,17 @@ void cl_git_rewritefile(const char *filename, const char *new_content) char *cl_getenv(const char *name) { - wchar_t name_utf16[GIT_WIN_PATH]; + wchar_t name_utf16[GIT_WIN_PATH_UTF16]; DWORD alloc_len; wchar_t *value_utf16; char *value_utf8; - git__utf8_to_16(name_utf16, GIT_WIN_PATH, name); + git__utf8_to_16(name_utf16, GIT_WIN_PATH_UTF16, name); alloc_len = GetEnvironmentVariableW(name_utf16, NULL, 0); if (alloc_len <= 0) return NULL; - alloc_len = GIT_WIN_PATH; + alloc_len = GIT_WIN_PATH_UTF8; cl_assert(value_utf16 = git__calloc(alloc_len, sizeof(wchar_t))); GetEnvironmentVariableW(name_utf16, value_utf16, alloc_len); @@ -81,13 +81,13 @@ char *cl_getenv(const char *name) int cl_setenv(const char *name, const char *value) { - wchar_t name_utf16[GIT_WIN_PATH]; - wchar_t value_utf16[GIT_WIN_PATH]; + wchar_t name_utf16[GIT_WIN_PATH_UTF16]; + wchar_t value_utf16[GIT_WIN_PATH_UTF16]; - git__utf8_to_16(name_utf16, GIT_WIN_PATH, name); + git__utf8_to_16(name_utf16, GIT_WIN_PATH_UTF16, name); if (value) { - git__utf8_to_16(value_utf16, GIT_WIN_PATH, value); + git__utf8_to_16(value_utf16, GIT_WIN_PATH_UTF16, value); cl_assert(SetEnvironmentVariableW(name_utf16, value_utf16)); } else { /* Windows XP returns 0 (failed) when passing NULL for lpValue when @@ -107,12 +107,12 @@ int cl_setenv(const char *name, const char *value) * the source is a directory, a child of the source). */ int cl_rename(const char *source, const char *dest) { - wchar_t source_utf16[GIT_WIN_PATH]; - wchar_t dest_utf16[GIT_WIN_PATH]; + wchar_t source_utf16[GIT_WIN_PATH_UTF16]; + wchar_t dest_utf16[GIT_WIN_PATH_UTF16]; unsigned retries = 1; - git__utf8_to_16(source_utf16, GIT_WIN_PATH, source); - git__utf8_to_16(dest_utf16, GIT_WIN_PATH, dest); + git__utf8_to_16(source_utf16, GIT_WIN_PATH_UTF16, source); + git__utf8_to_16(dest_utf16, GIT_WIN_PATH_UTF16, dest); while (!MoveFileW(source_utf16, dest_utf16)) { /* Only retry if the error is ERROR_ACCESS_DENIED; -- cgit v1.2.1 From f1af935b8918e9f9eae63219a434a7dedbff1c38 Mon Sep 17 00:00:00 2001 From: Nikolai Vladimirov Date: Mon, 5 Aug 2013 21:53:09 +0300 Subject: submodule: check alloc and name presense --- src/submodule.c | 5 ++++- tests-clar/resources/submodules/gitmodules | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/submodule.c b/src/submodule.c index b4e917561..40bda9a41 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -1025,6 +1025,7 @@ static int submodule_get( if (!git_strmap_valid_index(smcfg, pos)) { sm = submodule_alloc(repo, name); + GITERR_CHECK_ALLOC(sm); /* insert value at name - if another thread beats us to it, then use * their record and release our own. @@ -1101,8 +1102,10 @@ static int submodule_load_from_config( namestart = key + strlen("submodule."); property = strrchr(namestart, '.'); - if (property == NULL) + + if (!property || (property == namestart)) return 0; + property++; is_path = (strcasecmp(property, "path") == 0); diff --git a/tests-clar/resources/submodules/gitmodules b/tests-clar/resources/submodules/gitmodules index 1262f8bb0..2798b696c 100644 --- a/tests-clar/resources/submodules/gitmodules +++ b/tests-clar/resources/submodules/gitmodules @@ -1,3 +1,6 @@ [submodule "testrepo"] + path = testrepo + url = +[submodule ""] path = testrepo url = \ No newline at end of file -- cgit v1.2.1 From e38f0d69aba011d02ba5cabc648fee6c6f4dcc29 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 5 Aug 2013 14:06:41 -0500 Subject: Add rename from rewrites to status In git_diff_paired_foreach, temporarily resort the index->workdir diff list by index path so that we can track a rename in the workdir from head->index->workdir. --- include/git2/status.h | 5 +- src/diff.c | 77 ++++++++++++++++++-------- src/status.c | 29 +++------- tests-clar/status/renames.c | 129 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 45 deletions(-) diff --git a/include/git2/status.h b/include/git2/status.h index 2f7c06726..aa934d96b 100644 --- a/include/git2/status.h +++ b/include/git2/status.h @@ -107,7 +107,7 @@ typedef enum { * - GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX indicates that rename detection * should be processed between the head and the index and enables * the GIT_STATUS_INDEX_RENAMED as a possible status flag. - * - GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR indicates tha rename + * - GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR indicates that rename * detection should be run between the index and the working directory * and enabled GIT_STATUS_WT_RENAMED as a possible status flag. * - GIT_STATUS_OPT_SORT_CASE_SENSITIVELY overrides the native case @@ -116,6 +116,8 @@ typedef enum { * - GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY overrides the native case * sensitivity for the file system and forces the output to be in * case-insensitive order + * - GIT_STATUS_OPT_RENAMES_FROM_REWRITES indicates that rename detection + * should include rewritten files * * Calling `git_status_foreach()` is like calling the extended version * with: GIT_STATUS_OPT_INCLUDE_IGNORED, GIT_STATUS_OPT_INCLUDE_UNTRACKED, @@ -134,6 +136,7 @@ typedef enum { GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR = (1u << 8), GIT_STATUS_OPT_SORT_CASE_SENSITIVELY = (1u << 9), GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY = (1u << 10), + GIT_STATUS_OPT_RENAMES_FROM_REWRITES = (1u << 11), } git_status_opt_t; #define GIT_STATUS_OPT_DEFAULTS \ diff --git a/src/diff.c b/src/diff.c index e875d09b3..77dbbd8bc 100644 --- a/src/diff.c +++ b/src/diff.c @@ -258,6 +258,26 @@ int git_diff_delta__casecmp(const void *a, const void *b) return val ? val : ((int)da->status - (int)db->status); } +GIT_INLINE(const char *) diff_delta__i2w_path(const git_diff_delta *delta) +{ + return delta->old_file.path ? + delta->old_file.path : delta->new_file.path; +} + +int git_diff_delta__i2w_cmp(const void *a, const void *b) +{ + const git_diff_delta *da = a, *db = b; + int val = strcmp(diff_delta__i2w_path(da), diff_delta__i2w_path(db)); + return val ? val : ((int)da->status - (int)db->status); +} + +int git_diff_delta__i2w_casecmp(const void *a, const void *b) +{ + const git_diff_delta *da = a, *db = b; + int val = strcasecmp(diff_delta__i2w_path(da), diff_delta__i2w_path(db)); + return val ? val : ((int)da->status - (int)db->status); +} + bool git_diff_delta__should_skip( const git_diff_options *opts, const git_diff_delta *delta) { @@ -1276,7 +1296,7 @@ int git_diff__paired_foreach( git_diff_delta *h2i, *i2w; size_t i, j, i_max, j_max; int (*strcomp)(const char *, const char *) = git__strcmp; - bool icase_mismatch; + bool h2i_icase, i2w_icase, icase_mismatch; i_max = head2idx ? head2idx->deltas.length : 0; j_max = idx2wd ? idx2wd->deltas.length : 0; @@ -1291,24 +1311,35 @@ int git_diff__paired_foreach( * Therefore the main thing we need to do here is make sure the diffs * are traversed in a compatible order. To do this, we temporarily * resort a mismatched diff to get the order correct. + * + * In order to traverse renames in the index->workdir, we need to + * ensure that we compare the index name on both sides, so we + * always sort by the old name in the i2w list. */ + h2i_icase = head2idx != NULL && + (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0; + + i2w_icase = idx2wd != NULL && + (idx2wd->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0; + icase_mismatch = - (head2idx != NULL && idx2wd != NULL && - ((head2idx->opts.flags ^ idx2wd->opts.flags) & GIT_DIFF_DELTAS_ARE_ICASE)); - - /* force case-sensitive delta sort */ - if (icase_mismatch) { - if (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) { - git_vector_set_cmp(&head2idx->deltas, git_diff_delta__cmp); - git_vector_sort(&head2idx->deltas); - } else { - git_vector_set_cmp(&idx2wd->deltas, git_diff_delta__cmp); - git_vector_sort(&idx2wd->deltas); - } + (head2idx != NULL && idx2wd != NULL && h2i_icase != i2w_icase); + + if (icase_mismatch && h2i_icase) { + git_vector_set_cmp(&head2idx->deltas, git_diff_delta__cmp); + git_vector_sort(&head2idx->deltas); } - else if (head2idx != NULL && head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) + + if (i2w_icase && !icase_mismatch) { strcomp = git__strcasecmp; + git_vector_set_cmp(&idx2wd->deltas, git_diff_delta__i2w_casecmp); + git_vector_sort(&idx2wd->deltas); + } else if (idx2wd != NULL) { + git_vector_set_cmp(&idx2wd->deltas, git_diff_delta__i2w_cmp); + git_vector_sort(&idx2wd->deltas); + } + for (i = 0, j = 0; i < i_max || j < j_max; ) { h2i = head2idx ? GIT_VECTOR_GET(&head2idx->deltas, i) : NULL; i2w = idx2wd ? GIT_VECTOR_GET(&idx2wd->deltas, j) : NULL; @@ -1332,14 +1363,16 @@ int git_diff__paired_foreach( } /* restore case-insensitive delta sort */ - if (icase_mismatch) { - if (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) { - git_vector_set_cmp(&head2idx->deltas, git_diff_delta__casecmp); - git_vector_sort(&head2idx->deltas); - } else { - git_vector_set_cmp(&idx2wd->deltas, git_diff_delta__casecmp); - git_vector_sort(&idx2wd->deltas); - } + if (icase_mismatch && h2i_icase) { + git_vector_set_cmp(&head2idx->deltas, git_diff_delta__casecmp); + git_vector_sort(&head2idx->deltas); + } + + /* restore idx2wd sort by new path */ + if (idx2wd != NULL) { + git_vector_set_cmp(&idx2wd->deltas, + i2w_icase ? git_diff_delta__casecmp : git_diff_delta__cmp); + git_vector_sort(&idx2wd->deltas); } return 0; diff --git a/src/status.c b/src/status.c index ccb8d37da..b2353258b 100644 --- a/src/status.c +++ b/src/status.c @@ -225,24 +225,6 @@ static git_status_list *git_status_list_alloc(git_index *index) return status; } -/* -static int newfile_cmp(const void *a, const void *b) -{ - const git_diff_delta *delta_a = a; - const git_diff_delta *delta_b = b; - - return git__strcmp(delta_a->new_file.path, delta_b->new_file.path); -} - -static int newfile_casecmp(const void *a, const void *b) -{ - const git_diff_delta *delta_a = a; - const git_diff_delta *delta_b = b; - - return git__strcasecmp(delta_a->new_file.path, delta_b->new_file.path); -} -*/ - int git_status_list_new( git_status_list **out, git_repository *repo, @@ -251,7 +233,7 @@ int git_status_list_new( git_index *index = NULL; git_status_list *status = NULL; git_diff_options diffopt = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options findopts_i2w = GIT_DIFF_FIND_OPTIONS_INIT; + git_diff_find_options findopt = GIT_DIFF_FIND_OPTIONS_INIT; git_tree *head = NULL; git_status_show_t show = opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR; @@ -284,6 +266,7 @@ int git_status_list_new( } diffopt.flags = GIT_DIFF_INCLUDE_TYPECHANGE; + findopt.flags = GIT_DIFF_FIND_FOR_UNTRACKED; if ((flags & GIT_STATUS_OPT_INCLUDE_UNTRACKED) != 0) diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNTRACKED; @@ -300,7 +283,9 @@ int git_status_list_new( if ((flags & GIT_STATUS_OPT_EXCLUDE_SUBMODULES) != 0) diffopt.flags = diffopt.flags | GIT_DIFF_IGNORE_SUBMODULES; - findopts_i2w.flags |= GIT_DIFF_FIND_FOR_UNTRACKED; + if ((flags & GIT_STATUS_OPT_RENAMES_FROM_REWRITES) != 0) + findopt.flags = findopt.flags | GIT_DIFF_FIND_AND_BREAK_REWRITES | + GIT_DIFF_FIND_RENAMES_FROM_REWRITES; if (show != GIT_STATUS_SHOW_WORKDIR_ONLY) { if ((error = git_diff_tree_to_index( @@ -308,7 +293,7 @@ int git_status_list_new( goto done; if ((flags & GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX) != 0 && - (error = git_diff_find_similar(status->head2idx, NULL)) < 0) + (error = git_diff_find_similar(status->head2idx, &findopt)) < 0) goto done; } @@ -318,7 +303,7 @@ int git_status_list_new( goto done; if ((flags & GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR) != 0 && - (error = git_diff_find_similar(status->idx2wd, &findopts_i2w)) < 0) + (error = git_diff_find_similar(status->idx2wd, &findopt)) < 0) goto done; } diff --git a/tests-clar/status/renames.c b/tests-clar/status/renames.c index 80ff26020..836e65c88 100644 --- a/tests-clar/status/renames.c +++ b/tests-clar/status/renames.c @@ -153,6 +153,65 @@ void test_status_renames__head2index_two(void) git_index_free(index); } +void test_status_renames__head2index_no_rename_from_rewrite(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_INDEX_MODIFIED, "ikeepsix.txt", "ikeepsix.txt" }, + { GIT_STATUS_INDEX_MODIFIED, "sixserving.txt", "sixserving.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + + cl_git_pass(git_repository_index(&index, g_repo)); + + rename_file(g_repo, "ikeepsix.txt", "_temp_.txt"); + rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); + rename_file(g_repo, "_temp_.txt", "sixserving.txt"); + + cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "sixserving.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 2); + git_status_list_free(statuslist); + + git_index_free(index); +} + +void test_status_renames__head2index_rename_from_rewrite(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_INDEX_RENAMED, "sixserving.txt", "ikeepsix.txt" }, + { GIT_STATUS_INDEX_RENAMED, "ikeepsix.txt", "sixserving.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES; + + cl_git_pass(git_repository_index(&index, g_repo)); + + rename_file(g_repo, "ikeepsix.txt", "_temp_.txt"); + rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); + rename_file(g_repo, "_temp_.txt", "sixserving.txt"); + + cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "sixserving.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 2); + git_status_list_free(statuslist); + + git_index_free(index); +} + void test_status_renames__index2workdir_one(void) { git_status_list *statuslist; @@ -197,6 +256,32 @@ void test_status_renames__index2workdir_two(void) git_status_list_free(statuslist); } +void test_status_renames__index2workdir_rename_from_rewrite(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_WT_RENAMED, "sixserving.txt", "ikeepsix.txt" }, + { GIT_STATUS_WT_RENAMED, "ikeepsix.txt", "sixserving.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES; + + cl_git_pass(git_repository_index(&index, g_repo)); + + rename_file(g_repo, "ikeepsix.txt", "_temp_.txt"); + rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); + rename_file(g_repo, "_temp_.txt", "sixserving.txt"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 2); + git_status_list_free(statuslist); + + git_index_free(index); +} + void test_status_renames__both_one(void) { git_index *index; @@ -274,6 +359,50 @@ void test_status_renames__both_two(void) git_index_free(index); } + +void test_status_renames__both_rename_from_rewrite(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, + "songof7cities.txt", "ikeepsix.txt" }, + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, + "ikeepsix.txt", "sixserving.txt" }, + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, + "sixserving.txt", "songof7cities.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES; + + cl_git_pass(git_repository_index(&index, g_repo)); + + rename_file(g_repo, "ikeepsix.txt", "_temp_.txt"); + rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); + rename_file(g_repo, "songof7cities.txt", "sixserving.txt"); + rename_file(g_repo, "_temp_.txt", "songof7cities.txt"); + + cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "sixserving.txt")); + cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); + cl_git_pass(git_index_write(index)); + + rename_file(g_repo, "songof7cities.txt", "_temp_.txt"); + rename_file(g_repo, "ikeepsix.txt", "songof7cities.txt"); + rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); + rename_file(g_repo, "_temp_.txt", "sixserving.txt"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 3); + git_status_list_free(statuslist); + + git_index_free(index); +} + void test_status_renames__both_casechange_one(void) { git_index *index; -- cgit v1.2.1 From 437224b4b912176ac0992aa56790142e3ba5bb8f Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 5 Aug 2013 21:46:32 -0700 Subject: More tests for ambiguous OIDs across packs The test coverage for ambiguous OIDs was pretty thin. This adds a bunch of new objects both in packs, across packs, and loose that match to 8 characters so that we can test various cases of ambiguous lookups. --- include/git2/odb.h | 2 +- tests-clar/odb/mixed.c | 64 +++++++++++++++++++++ tests-clar/resources/duplicate.git/config | 2 +- .../0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea | Bin 0 -> 22 bytes ...ck-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx | Bin 0 -> 1184 bytes ...k-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack | Bin 0 -> 249 bytes ...ck-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx | Bin 0 -> 1268 bytes ...k-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack | Bin 0 -> 369 bytes .../duplicate.git/refs/heads/dummy-marker.txt | 1 + 9 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 tests-clar/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea create mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx create mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack create mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx create mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack create mode 100644 tests-clar/resources/duplicate.git/refs/heads/dummy-marker.txt diff --git a/include/git2/odb.h b/include/git2/odb.h index b64436c4d..b3e9a57a6 100644 --- a/include/git2/odb.h +++ b/include/git2/odb.h @@ -120,7 +120,7 @@ GIT_EXTERN(int) git_odb_read(git_odb_object **out, git_odb *db, const git_oid *i * @param db database to search for the object in. * @param short_id a prefix of the id of the object to read. * @param len the length of the prefix - * @return + * @return * - 0 if the object was read; * - GIT_ENOTFOUND if the object is not in the database. * - GIT_EAMBIGUOUS if the prefix is ambiguous (several objects match the prefix) diff --git a/tests-clar/odb/mixed.c b/tests-clar/odb/mixed.c index da0ed97d7..7f7120a6e 100644 --- a/tests-clar/odb/mixed.c +++ b/tests-clar/odb/mixed.c @@ -18,8 +18,72 @@ void test_odb_mixed__dup_oid(void) { const char hex[] = "ce013625030ba8dba906f756967f9e9ca394464a"; git_oid oid; git_odb_object *obj; + cl_git_pass(git_oid_fromstr(&oid, hex)); cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, GIT_OID_HEXSZ)); git_odb_object_free(obj); } +/* some known sha collisions of file content: + * 'aabqhq' and 'aaazvc' with prefix 'dea509d0' (+ '9' and + 'b') + * 'aaeufo' and 'aaaohs' with prefix '81b5bff5' (+ 'f' and + 'b') + * 'aafewy' and 'aaepta' with prefix '739e3c4c' + * 'aahsyn' and 'aadrjg' with prefix '0ddeaded' (+ '9' and + 'e') + */ + +void test_odb_mixed__dup_oid_prefix_0(void) { + char hex[10]; + git_oid oid; + git_odb_object *obj; + + /* ambiguous in the same pack file */ + + strncpy(hex, "dea509d0", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_assert_equal_i( + GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + + strncpy(hex, "dea509d09", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + git_odb_object_free(obj); + + strncpy(hex, "dea509d0b", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + git_odb_object_free(obj); + + /* ambiguous in different pack files */ + + strncpy(hex, "81b5bff5", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_assert_equal_i( + GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + + strncpy(hex, "81b5bff5b", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + git_odb_object_free(obj); + + strncpy(hex, "81b5bff5f", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + git_odb_object_free(obj); + + /* ambiguous in pack file and loose */ + + strncpy(hex, "0ddeaded", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_assert_equal_i( + GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + + strncpy(hex, "0ddeaded9", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + git_odb_object_free(obj); + + strncpy(hex, "0ddeadede", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + git_odb_object_free(obj); +} diff --git a/tests-clar/resources/duplicate.git/config b/tests-clar/resources/duplicate.git/config index 515f48362..a4ef456cb 100644 --- a/tests-clar/resources/duplicate.git/config +++ b/tests-clar/resources/duplicate.git/config @@ -1,5 +1,5 @@ [core] repositoryformatversion = 0 filemode = true - bare = false + bare = true logallrefupdates = true diff --git a/tests-clar/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea b/tests-clar/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea new file mode 100644 index 000000000..47c2a631a Binary files /dev/null and b/tests-clar/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea differ diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx b/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx new file mode 100644 index 000000000..acbed82b6 Binary files /dev/null and b/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx differ diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack b/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack new file mode 100644 index 000000000..652b0c91f Binary files /dev/null and b/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack differ diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx b/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx new file mode 100644 index 000000000..fff685554 Binary files /dev/null and b/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx differ diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack b/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack new file mode 100644 index 000000000..e3e5f0e09 Binary files /dev/null and b/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack differ diff --git a/tests-clar/resources/duplicate.git/refs/heads/dummy-marker.txt b/tests-clar/resources/duplicate.git/refs/heads/dummy-marker.txt new file mode 100644 index 000000000..421376db9 --- /dev/null +++ b/tests-clar/resources/duplicate.git/refs/heads/dummy-marker.txt @@ -0,0 +1 @@ +dummy -- cgit v1.2.1 From 2d9f5b9f13107a4f59ea1c055620efeb603f2bab Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 7 Aug 2013 11:11:55 -0500 Subject: Parse config headers with quoted quotes Parse config headers that have the last quote on the line quoted instead of walking off the end. --- src/config_file.c | 11 +++++++++++ tests-clar/config/read.c | 21 ++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 2b0732a13..570f286c8 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -792,6 +792,11 @@ static int parse_section_header_ext(diskfile_backend *cfg, const char *line, con } switch (c) { + case 0: + set_parse_error(cfg, 0, "Unexpected end-of-line in section header"); + git_buf_free(&buf); + return -1; + case '"': ++quote_marks; continue; @@ -801,6 +806,12 @@ static int parse_section_header_ext(diskfile_backend *cfg, const char *line, con switch (c) { case '"': + if (&line[rpos-1] == last_quote) { + set_parse_error(cfg, 0, "Missing closing quotation mark in section header"); + git_buf_free(&buf); + return -1; + } + case '\\': break; diff --git a/tests-clar/config/read.c b/tests-clar/config/read.c index 9f943d0f6..a18dca89b 100644 --- a/tests-clar/config/read.c +++ b/tests-clar/config/read.c @@ -431,10 +431,10 @@ void test_config_read__simple_read_from_specific_level(void) git_config_free(cfg); } -static void clean_empty_config(void *unused) +static void clean_test_config(void *unused) { GIT_UNUSED(unused); - cl_fixture_cleanup("./empty"); + cl_fixture_cleanup("./testconfig"); } void test_config_read__can_load_and_parse_an_empty_config_file(void) @@ -442,10 +442,21 @@ void test_config_read__can_load_and_parse_an_empty_config_file(void) git_config *cfg; int i; - cl_set_cleanup(&clean_empty_config, NULL); - cl_git_mkfile("./empty", ""); - cl_git_pass(git_config_open_ondisk(&cfg, "./empty")); + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", ""); + cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig")); cl_assert_equal_i(GIT_ENOTFOUND, git_config_get_int32(&i, cfg, "nope.neither")); git_config_free(cfg); } + +void test_config_read__corrupt_header(void) +{ + git_config *cfg; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "[sneaky ] \"quoted closing quote mark\\\""); + cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); + + git_config_free(cfg); +} -- cgit v1.2.1 From 8c8a54901071f7d8372ce901b098507d5a4a5804 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 6 Aug 2013 20:35:51 -0700 Subject: Add status test for long paths --- tests-clar/status/status_data.h | 4 ++++ tests-clar/status/worktree.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/tests-clar/status/status_data.h b/tests-clar/status/status_data.h index 3efa934ea..652fe4378 100644 --- a/tests-clar/status/status_data.h +++ b/tests-clar/status/status_data.h @@ -1,5 +1,9 @@ #include "status_helpers.h" +// A utf-8 string with 89 characters, but 267 bytes. +static const char *longname = "\xE5\x8F\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97"; + + /* entries for a plain copy of tests/resources/status */ static const char *entry_paths0[] = { diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index 0e315cd60..10efd7473 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -865,3 +865,35 @@ void test_status_worktree__sorting_by_case(void) cl_assert_equal_i(0, counts.wrong_status_flags_count); cl_assert_equal_i(0, counts.wrong_sorted_path); } + +void test_status_worktree__long_filenames(void) +{ + char path[GIT_WIN_PATH_UTF8]; + const char *expected_paths[] = {path}; + const unsigned int expected_statuses[] = {GIT_STATUS_WT_NEW}; + + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts = {0}; + + // Create directory with amazingly long filename + sprintf(path, "empty_standard_repo/%s", longname); + cl_git_pass(git_futils_mkdir_r(path, NULL, 0777)); + sprintf(path, "empty_standard_repo/%s/foo", longname); + cl_git_mkfile(path, "dummy"); + + sprintf(path, "%s/foo", longname); + counts.expected_entry_count = 1; + counts.expected_paths = expected_paths; + counts.expected_statuses = expected_statuses; + + opts.show = GIT_STATUS_SHOW_WORKDIR_ONLY; + opts.flags = GIT_STATUS_OPT_DEFAULTS; + + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) ); + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + -- cgit v1.2.1 From 2984f3190e350099662b944dc45579bc194c65be Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 7 Aug 2013 05:55:12 -0700 Subject: Don't use win32-only macro in test code --- tests-clar/status/worktree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index 10efd7473..be7398cb6 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -868,7 +868,7 @@ void test_status_worktree__sorting_by_case(void) void test_status_worktree__long_filenames(void) { - char path[GIT_WIN_PATH_UTF8]; + char path[260*4+1]; const char *expected_paths[] = {path}; const unsigned int expected_statuses[] = {GIT_STATUS_WT_NEW}; -- cgit v1.2.1 From c0c516935292732e56cd2f2ca1c0c471743f4adc Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 6 Aug 2013 21:05:03 -0700 Subject: Add long-file-name branch to test repo --- tests-clar/refs/list.c | 4 ++-- tests-clar/repo/iterator.c | 3 ++- .../objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 | Bin 0 -> 167 bytes .../objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e | Bin 0 -> 41 bytes .../objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a | Bin 0 -> 187 bytes .../resources/testrepo/.gitted/refs/heads/long-file-name | 1 + tests-clar/revwalk/basic.c | 2 +- 7 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 tests-clar/resources/testrepo/.gitted/objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 create mode 100644 tests-clar/resources/testrepo/.gitted/objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e create mode 100644 tests-clar/resources/testrepo/.gitted/objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a create mode 100644 tests-clar/resources/testrepo/.gitted/refs/heads/long-file-name diff --git a/tests-clar/refs/list.c b/tests-clar/refs/list.c index c9c2af4a7..de5c0fd3d 100644 --- a/tests-clar/refs/list.c +++ b/tests-clar/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, 13); + cl_assert_equal_i((int)ref_list.count, 14); 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, 13); + cl_assert_equal_i((int)ref_list.count, 14); git_strarray_free(&ref_list); } diff --git a/tests-clar/repo/iterator.c b/tests-clar/repo/iterator.c index 11a7d2a23..1c513e9e7 100644 --- a/tests-clar/repo/iterator.c +++ b/tests-clar/repo/iterator.c @@ -906,6 +906,7 @@ void test_repo_iterator__fs2(void) static const char *expect_base[] = { "heads/br2", "heads/dir", + "heads/long-file-name", "heads/master", "heads/packed-test", "heads/subtrees", @@ -922,6 +923,6 @@ void test_repo_iterator__fs2(void) cl_git_pass(git_iterator_for_filesystem( &i, "testrepo/.git/refs", 0, NULL, NULL)); - expect_iterator_items(i, 11, expect_base, 11, expect_base); + expect_iterator_items(i, 12, expect_base, 12, expect_base); git_iterator_free(i); } diff --git a/tests-clar/resources/testrepo/.gitted/objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 b/tests-clar/resources/testrepo/.gitted/objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 new file mode 100644 index 000000000..ee7c78174 Binary files /dev/null and b/tests-clar/resources/testrepo/.gitted/objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e b/tests-clar/resources/testrepo/.gitted/objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e new file mode 100644 index 000000000..197685b86 Binary files /dev/null and b/tests-clar/resources/testrepo/.gitted/objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a b/tests-clar/resources/testrepo/.gitted/objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a new file mode 100644 index 000000000..db778aaae Binary files /dev/null and b/tests-clar/resources/testrepo/.gitted/objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a differ diff --git a/tests-clar/resources/testrepo/.gitted/refs/heads/long-file-name b/tests-clar/resources/testrepo/.gitted/refs/heads/long-file-name new file mode 100644 index 000000000..1f942a746 --- /dev/null +++ b/tests-clar/resources/testrepo/.gitted/refs/heads/long-file-name @@ -0,0 +1 @@ +6b377958d8c6a4906e8573b53672a1a23a4e8ce6 diff --git a/tests-clar/revwalk/basic.c b/tests-clar/revwalk/basic.c index cb8fcb9c7..6d55aed54 100644 --- a/tests-clar/revwalk/basic.c +++ b/tests-clar/revwalk/basic.c @@ -177,7 +177,7 @@ void test_revwalk_basic__glob_heads_with_invalid(void) /* walking */; /* git log --branches --oneline | wc -l => 16 */ - cl_assert_equal_i(16, i); + cl_assert_equal_i(17, i); } void test_revwalk_basic__push_head(void) -- cgit v1.2.1 From 75f98a95eee8a0efe8f9649ddc8a81c64d863ced Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 7 Aug 2013 06:12:27 -0700 Subject: Add checkout test for long file name --- tests-clar/checkout/tree.c | 19 +++++++++++++++++++ tests-clar/status/status_data.h | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c index e4bfbce06..fff530cdd 100644 --- a/tests-clar/checkout/tree.c +++ b/tests-clar/checkout/tree.c @@ -677,3 +677,22 @@ void test_checkout_tree__target_directory_from_bare(void) cl_git_pass(git_futils_rmdir_r( "alternative", NULL, GIT_RMDIR_REMOVE_FILES)); } + +void test_checkout_tree__extremely_long_file_name(void) +{ + // A utf-8 string with 83 characters, but 249 bytes. + const char *longname = "\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97"; + char path[1024]; + + g_opts.checkout_strategy = GIT_CHECKOUT_FORCE; + cl_git_pass(git_revparse_single(&g_object, g_repo, "long-file-name")); + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + + sprintf(path, "testrepo/%s.txt", longname); + cl_assert(git_path_exists(path)); + + git_object_free(g_object); + cl_git_pass(git_revparse_single(&g_object, g_repo, "master")); + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + cl_assert(!git_path_exists(path)); +} diff --git a/tests-clar/status/status_data.h b/tests-clar/status/status_data.h index 652fe4378..8ad4235fd 100644 --- a/tests-clar/status/status_data.h +++ b/tests-clar/status/status_data.h @@ -1,7 +1,7 @@ #include "status_helpers.h" -// A utf-8 string with 89 characters, but 267 bytes. -static const char *longname = "\xE5\x8F\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97"; +// A utf-8 string with 83 characters, but 249 bytes. +static const char *longname = "\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97"; /* entries for a plain copy of tests/resources/status */ -- cgit v1.2.1 From 9c38f7a6523cdc87a897eccb6d83439987f99a4e Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 7 Aug 2013 13:22:41 -0700 Subject: Add typedefs for win32 utf-8 and utf-16 buffers ...and normalize the signatures of the two conversion functions. --- src/fileops.c | 4 ++-- src/path.c | 4 ++-- src/transports/winhttp.c | 8 +++---- src/win32/dir.c | 8 +++---- src/win32/findfile.c | 2 +- src/win32/posix.h | 4 ++-- src/win32/posix_w32.c | 55 ++++++++++++++++++++++++----------------------- src/win32/utf-conv.c | 8 +++---- src/win32/utf-conv.h | 7 ++++-- tests-clar/clar_libgit2.c | 20 ++++++++--------- 10 files changed, 62 insertions(+), 58 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 36fcc73df..5e86d1a91 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -58,9 +58,9 @@ int git_futils_creat_locked(const char *path, const mode_t mode) int fd; #ifdef GIT_WIN32 - wchar_t buf[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 buf; - git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); + git__utf8_to_16(buf, path); fd = _wopen(buf, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY | O_CLOEXEC, mode); #else diff --git a/src/path.c b/src/path.c index ca0cc8c7c..da7bd90a0 100644 --- a/src/path.c +++ b/src/path.c @@ -486,14 +486,14 @@ bool git_path_is_empty_dir(const char *path) { git_buf pathbuf = GIT_BUF_INIT; HANDLE hFind = INVALID_HANDLE_VALUE; - wchar_t wbuf[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 wbuf; WIN32_FIND_DATAW ffd; bool retval = true; if (!git_path_isdir(path)) return false; git_buf_printf(&pathbuf, "%s\\*", path); - git__utf8_to_16(wbuf, GIT_WIN_PATH_UTF16, git_buf_cstr(&pathbuf)); + git__utf8_to_16(wbuf, git_buf_cstr(&pathbuf)); hFind = FindFirstFileW(wbuf, &ffd); if (INVALID_HANDLE_VALUE == hFind) { diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 6064f90d8..fbf9b2f48 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -264,7 +264,7 @@ static int winhttp_stream_connect(winhttp_stream *s) if (git_buf_printf(&buf, "Content-Type: application/x-git-%s-request", s->service) < 0) goto on_error; - git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)); + git__utf8_to_16(ct, git_buf_cstr(&buf)); if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) { giterr_set(GITERR_OS, "Failed to add a header to the request"); @@ -593,7 +593,7 @@ replay: else snprintf(expected_content_type_8, MAX_CONTENT_TYPE_LEN, "application/x-git-%s-advertisement", s->service); - git__utf8_to_16(expected_content_type, MAX_CONTENT_TYPE_LEN, expected_content_type_8); + git__utf8_to_16(expected_content_type, expected_content_type_8); content_type_length = sizeof(content_type); if (!WinHttpQueryHeaders(s->request, @@ -893,7 +893,7 @@ static int winhttp_connect( const char *url) { wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")"; - wchar_t host[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 host; int32_t port; const char *default_port = "80"; int ret; @@ -920,7 +920,7 @@ static int winhttp_connect( return -1; /* Prepare host */ - git__utf8_to_16(host, GIT_WIN_PATH_UTF16, t->host); + git__utf8_to_16(host, t->host); /* Establish session */ t->session = WinHttpOpen( diff --git a/src/win32/dir.c b/src/win32/dir.c index b18c603f7..a638fce96 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -26,7 +26,7 @@ static int init_filter(char *filter, size_t n, const char *dir) git__DIR *git__opendir(const char *dir) { char filter[GIT_WIN_PATH_UTF8]; - wchar_t filter_w[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 filter_w; git__DIR *new = NULL; if (!dir || !init_filter(filter, sizeof(filter), dir)) @@ -40,7 +40,7 @@ git__DIR *git__opendir(const char *dir) if (!new->dir) goto fail; - git__utf8_to_16(filter_w, GIT_WIN_PATH_UTF16, filter); + git__utf8_to_16(filter_w, filter); new->h = FindFirstFileW(filter_w, &new->f); if (new->h == INVALID_HANDLE_VALUE) { @@ -102,7 +102,7 @@ struct git__dirent *git__readdir(git__DIR *d) void git__rewinddir(git__DIR *d) { char filter[GIT_WIN_PATH_UTF8]; - wchar_t filter_w[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 filter_w; if (!d) return; @@ -116,7 +116,7 @@ void git__rewinddir(git__DIR *d) if (!init_filter(filter, sizeof(filter), d->dir)) return; - git__utf8_to_16(filter_w, GIT_WIN_PATH_UTF16, filter); + git__utf8_to_16(filter_w, filter); d->h = FindFirstFileW(filter_w, &d->f); if (d->h == INVALID_HANDLE_VALUE) diff --git a/src/win32/findfile.c b/src/win32/findfile.c index 9d9051bff..248173563 100644 --- a/src/win32/findfile.c +++ b/src/win32/findfile.c @@ -53,7 +53,7 @@ int git_win32__find_file( if (*filename == '/' || *filename == '\\') filename++; - git__utf8_to_16(file_utf16 + root->len - 1, alloc_len, filename); + git__utf8_to_16(file_utf16 + root->len - 1, filename); /* check access */ if (_waccess(file_utf16, F_OK) < 0) { diff --git a/src/win32/posix.h b/src/win32/posix.h index 753f35a2d..259ad572c 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -20,9 +20,9 @@ GIT_INLINE(int) p_link(const char *old, const char *new) GIT_INLINE(int) p_mkdir(const char *path, mode_t mode) { - wchar_t buf[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 buf; GIT_UNUSED(mode); - git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); + git__utf8_to_16(buf, path); return _wmkdir(buf); } diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index a96741d1c..4c696d0cd 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -16,8 +16,8 @@ int p_unlink(const char *path) { - wchar_t buf[GIT_WIN_PATH_UTF16]; - git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); + git_win_str_utf16 buf; + git__utf8_to_16(buf, path); _wchmod(buf, 0666); return _wunlink(buf); } @@ -59,10 +59,11 @@ static int do_lstat( const char *file_name, struct stat *buf, int posix_enotdir) { WIN32_FILE_ATTRIBUTE_DATA fdata; - wchar_t fbuf[GIT_WIN_PATH_UTF16], lastch; + git_win_str_utf16 fbuf; + wchar_t lastch; int flen; - flen = git__utf8_to_16(fbuf, GIT_WIN_PATH_UTF16, file_name); + flen = git__utf8_to_16(fbuf, file_name); /* truncate trailing slashes */ for (; flen > 0; --flen) { @@ -165,7 +166,7 @@ int p_readlink(const char *link, char *target, size_t target_len) static fpath_func pGetFinalPath = NULL; HANDLE hFile; DWORD dwRet; - wchar_t link_w[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 link_w; wchar_t* target_w; int error = 0; @@ -188,7 +189,7 @@ int p_readlink(const char *link, char *target, size_t target_len) } } - git__utf8_to_16(link_w, GIT_WIN_PATH_UTF16, link); + git__utf8_to_16(link_w, link); hFile = CreateFileW(link_w, // file to open GENERIC_READ, // open for reading @@ -254,10 +255,10 @@ int p_symlink(const char *old, const char *new) int p_open(const char *path, int flags, ...) { - wchar_t buf[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 buf; mode_t mode = 0; - git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); + git__utf8_to_16(buf, path); if (flags & O_CREAT) { va_list arg_list; @@ -272,8 +273,8 @@ int p_open(const char *path, int flags, ...) int p_creat(const char *path, mode_t mode) { - wchar_t buf[GIT_WIN_PATH_UTF16]; - git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); + git_win_str_utf16 buf; + git__utf8_to_16(buf, path); return _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode); } @@ -315,23 +316,23 @@ int p_stat(const char* path, struct stat* buf) int p_chdir(const char* path) { - wchar_t buf[GIT_WIN_PATH_UTF16]; - git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); + git_win_str_utf16 buf; + git__utf8_to_16(buf, path); return _wchdir(buf); } int p_chmod(const char* path, mode_t mode) { - wchar_t buf[GIT_WIN_PATH_UTF16]; - git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); + git_win_str_utf16 buf; + git__utf8_to_16(buf, path); return _wchmod(buf, mode); } int p_rmdir(const char* path) { int error; - wchar_t buf[GIT_WIN_PATH_UTF16]; - git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); + git_win_str_utf16 buf; + git__utf8_to_16(buf, path); error = _wrmdir(buf); @@ -347,18 +348,18 @@ int p_rmdir(const char* path) int p_hide_directory__w32(const char *path) { - wchar_t buf[GIT_WIN_PATH_UTF16]; - git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); + git_win_str_utf16 buf; + git__utf8_to_16(buf, path); return (SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0) ? 0 : -1; } char *p_realpath(const char *orig_path, char *buffer) { int ret; - wchar_t orig_path_w[GIT_WIN_PATH_UTF16]; - wchar_t buffer_w[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 orig_path_w; + git_win_str_utf16 buffer_w; - git__utf8_to_16(orig_path_w, GIT_WIN_PATH_UTF16, orig_path); + git__utf8_to_16(orig_path_w, orig_path); /* Implicitly use GetCurrentDirectory which can be a threading issue */ ret = GetFullPathNameW(orig_path_w, GIT_WIN_PATH_UTF16, buffer_w, NULL); @@ -448,18 +449,18 @@ int p_setenv(const char* name, const char* value, int overwrite) int p_access(const char* path, mode_t mode) { - wchar_t buf[GIT_WIN_PATH_UTF16]; - git__utf8_to_16(buf, GIT_WIN_PATH_UTF16, path); + git_win_str_utf16 buf; + git__utf8_to_16(buf, path); return _waccess(buf, mode); } int p_rename(const char *from, const char *to) { - wchar_t wfrom[GIT_WIN_PATH_UTF16]; - wchar_t wto[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 wfrom; + git_win_str_utf16 wto; - git__utf8_to_16(wfrom, GIT_WIN_PATH_UTF16, from); - git__utf8_to_16(wto, GIT_WIN_PATH_UTF16, to); + git__utf8_to_16(wfrom, from); + git__utf8_to_16(wto, to); return MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? 0 : -1; } diff --git a/src/win32/utf-conv.c b/src/win32/utf-conv.c index 78d277494..9c9686147 100644 --- a/src/win32/utf-conv.c +++ b/src/win32/utf-conv.c @@ -70,12 +70,12 @@ void git__utf8_to_16(wchar_t *dest, size_t length, const char *src) } #endif -int git__utf8_to_16(wchar_t *dest, size_t length, const char *src) +int git__utf8_to_16(git_win_str_utf16 dest, const git_win_str_utf8 src) { - return MultiByteToWideChar(CP_UTF8, 0, src, -1, dest, (int)length); + return MultiByteToWideChar(CP_UTF8, 0, src, -1, dest, GIT_WIN_PATH_UTF16); } -int git__utf16_to_8(char *out, const wchar_t *input) +int git__utf16_to_8(git_win_str_utf8 dest, const git_win_str_utf16 src) { - return WideCharToMultiByte(CP_UTF8, 0, input, -1, out, GIT_WIN_PATH_UTF8, NULL, NULL); + return WideCharToMultiByte(CP_UTF8, 0, src, -1, dest, GIT_WIN_PATH_UTF8, NULL, NULL); } diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h index 9922e2969..d0b6fc825 100644 --- a/src/win32/utf-conv.h +++ b/src/win32/utf-conv.h @@ -13,8 +13,11 @@ #define GIT_WIN_PATH_UTF16 (260 + 1) #define GIT_WIN_PATH_UTF8 (260 * 4 + 1) -int git__utf8_to_16(wchar_t *dest, size_t length, const char *src); -int git__utf16_to_8(char *dest, const wchar_t *src); +typedef wchar_t git_win_str_utf16[GIT_WIN_PATH_UTF16]; +typedef char git_win_str_utf8[GIT_WIN_PATH_UTF8]; + +int git__utf8_to_16(git_win_str_utf16 dest, const git_win_str_utf8 src); +int git__utf16_to_8(git_win_str_utf8 dest, const git_win_str_utf16 src); #endif diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 34d54cd94..869acd613 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -56,12 +56,12 @@ void cl_git_rewritefile(const char *filename, const char *new_content) char *cl_getenv(const char *name) { - wchar_t name_utf16[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 name_utf16; DWORD alloc_len; wchar_t *value_utf16; char *value_utf8; - git__utf8_to_16(name_utf16, GIT_WIN_PATH_UTF16, name); + git__utf8_to_16(name_utf16, name); alloc_len = GetEnvironmentVariableW(name_utf16, NULL, 0); if (alloc_len <= 0) return NULL; @@ -81,13 +81,13 @@ char *cl_getenv(const char *name) int cl_setenv(const char *name, const char *value) { - wchar_t name_utf16[GIT_WIN_PATH_UTF16]; - wchar_t value_utf16[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 name_utf16; + git_win_str_utf16 value_utf16; - git__utf8_to_16(name_utf16, GIT_WIN_PATH_UTF16, name); + git__utf8_to_16(name_utf16, name); if (value) { - git__utf8_to_16(value_utf16, GIT_WIN_PATH_UTF16, value); + git__utf8_to_16(value_utf16, value); cl_assert(SetEnvironmentVariableW(name_utf16, value_utf16)); } else { /* Windows XP returns 0 (failed) when passing NULL for lpValue when @@ -107,12 +107,12 @@ int cl_setenv(const char *name, const char *value) * the source is a directory, a child of the source). */ int cl_rename(const char *source, const char *dest) { - wchar_t source_utf16[GIT_WIN_PATH_UTF16]; - wchar_t dest_utf16[GIT_WIN_PATH_UTF16]; + git_win_str_utf16 source_utf16; + git_win_str_utf16 dest_utf16; unsigned retries = 1; - git__utf8_to_16(source_utf16, GIT_WIN_PATH_UTF16, source); - git__utf8_to_16(dest_utf16, GIT_WIN_PATH_UTF16, dest); + git__utf8_to_16(source_utf16, source); + git__utf8_to_16(dest_utf16, dest); while (!MoveFileW(source_utf16, dest_utf16)) { /* Only retry if the error is ERROR_ACCESS_DENIED; -- cgit v1.2.1 From 2c0128ee79243d32e60f19e60acc2e297c1761d6 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 7 Aug 2013 19:29:33 -0700 Subject: Rename git_win_str_utf* to git_win32_path_utf* --- src/fileops.c | 2 +- src/path.c | 2 +- src/transports/winhttp.c | 2 +- src/win32/dir.c | 4 ++-- src/win32/posix.h | 2 +- src/win32/posix_w32.c | 28 ++++++++++++++-------------- src/win32/utf-conv.c | 4 ++-- src/win32/utf-conv.h | 8 ++++---- tests-clar/clar_libgit2.c | 10 +++++----- 9 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 5e86d1a91..25323d0c9 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -58,7 +58,7 @@ int git_futils_creat_locked(const char *path, const mode_t mode) int fd; #ifdef GIT_WIN32 - git_win_str_utf16 buf; + git_win32_path_utf16 buf; git__utf8_to_16(buf, path); fd = _wopen(buf, O_WRONLY | O_CREAT | O_TRUNC | diff --git a/src/path.c b/src/path.c index da7bd90a0..72831c736 100644 --- a/src/path.c +++ b/src/path.c @@ -486,7 +486,7 @@ bool git_path_is_empty_dir(const char *path) { git_buf pathbuf = GIT_BUF_INIT; HANDLE hFind = INVALID_HANDLE_VALUE; - git_win_str_utf16 wbuf; + git_win32_path_utf16 wbuf; WIN32_FIND_DATAW ffd; bool retval = true; diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index fbf9b2f48..359ab5f5e 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -893,7 +893,7 @@ static int winhttp_connect( const char *url) { wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")"; - git_win_str_utf16 host; + git_win32_path_utf16 host; int32_t port; const char *default_port = "80"; int ret; diff --git a/src/win32/dir.c b/src/win32/dir.c index a638fce96..b1cb47c9b 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -26,7 +26,7 @@ static int init_filter(char *filter, size_t n, const char *dir) git__DIR *git__opendir(const char *dir) { char filter[GIT_WIN_PATH_UTF8]; - git_win_str_utf16 filter_w; + git_win32_path_utf16 filter_w; git__DIR *new = NULL; if (!dir || !init_filter(filter, sizeof(filter), dir)) @@ -102,7 +102,7 @@ struct git__dirent *git__readdir(git__DIR *d) void git__rewinddir(git__DIR *d) { char filter[GIT_WIN_PATH_UTF8]; - git_win_str_utf16 filter_w; + git_win32_path_utf16 filter_w; if (!d) return; diff --git a/src/win32/posix.h b/src/win32/posix.h index 259ad572c..47f6ddeb0 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -20,7 +20,7 @@ GIT_INLINE(int) p_link(const char *old, const char *new) GIT_INLINE(int) p_mkdir(const char *path, mode_t mode) { - git_win_str_utf16 buf; + git_win32_path_utf16 buf; GIT_UNUSED(mode); git__utf8_to_16(buf, path); return _wmkdir(buf); diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 4c696d0cd..a7df424df 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -16,7 +16,7 @@ int p_unlink(const char *path) { - git_win_str_utf16 buf; + git_win32_path_utf16 buf; git__utf8_to_16(buf, path); _wchmod(buf, 0666); return _wunlink(buf); @@ -59,7 +59,7 @@ static int do_lstat( const char *file_name, struct stat *buf, int posix_enotdir) { WIN32_FILE_ATTRIBUTE_DATA fdata; - git_win_str_utf16 fbuf; + git_win32_path_utf16 fbuf; wchar_t lastch; int flen; @@ -166,7 +166,7 @@ int p_readlink(const char *link, char *target, size_t target_len) static fpath_func pGetFinalPath = NULL; HANDLE hFile; DWORD dwRet; - git_win_str_utf16 link_w; + git_win32_path_utf16 link_w; wchar_t* target_w; int error = 0; @@ -255,7 +255,7 @@ int p_symlink(const char *old, const char *new) int p_open(const char *path, int flags, ...) { - git_win_str_utf16 buf; + git_win32_path_utf16 buf; mode_t mode = 0; git__utf8_to_16(buf, path); @@ -273,7 +273,7 @@ int p_open(const char *path, int flags, ...) int p_creat(const char *path, mode_t mode) { - git_win_str_utf16 buf; + git_win32_path_utf16 buf; git__utf8_to_16(buf, path); return _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode); } @@ -316,14 +316,14 @@ int p_stat(const char* path, struct stat* buf) int p_chdir(const char* path) { - git_win_str_utf16 buf; + git_win32_path_utf16 buf; git__utf8_to_16(buf, path); return _wchdir(buf); } int p_chmod(const char* path, mode_t mode) { - git_win_str_utf16 buf; + git_win32_path_utf16 buf; git__utf8_to_16(buf, path); return _wchmod(buf, mode); } @@ -331,7 +331,7 @@ int p_chmod(const char* path, mode_t mode) int p_rmdir(const char* path) { int error; - git_win_str_utf16 buf; + git_win32_path_utf16 buf; git__utf8_to_16(buf, path); error = _wrmdir(buf); @@ -348,7 +348,7 @@ int p_rmdir(const char* path) int p_hide_directory__w32(const char *path) { - git_win_str_utf16 buf; + git_win32_path_utf16 buf; git__utf8_to_16(buf, path); return (SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0) ? 0 : -1; } @@ -356,8 +356,8 @@ int p_hide_directory__w32(const char *path) char *p_realpath(const char *orig_path, char *buffer) { int ret; - git_win_str_utf16 orig_path_w; - git_win_str_utf16 buffer_w; + git_win32_path_utf16 orig_path_w; + git_win32_path_utf16 buffer_w; git__utf8_to_16(orig_path_w, orig_path); @@ -449,15 +449,15 @@ int p_setenv(const char* name, const char* value, int overwrite) int p_access(const char* path, mode_t mode) { - git_win_str_utf16 buf; + git_win32_path_utf16 buf; git__utf8_to_16(buf, path); return _waccess(buf, mode); } int p_rename(const char *from, const char *to) { - git_win_str_utf16 wfrom; - git_win_str_utf16 wto; + git_win32_path_utf16 wfrom; + git_win32_path_utf16 wto; git__utf8_to_16(wfrom, from); git__utf8_to_16(wto, to); diff --git a/src/win32/utf-conv.c b/src/win32/utf-conv.c index 9c9686147..bb63b0f8d 100644 --- a/src/win32/utf-conv.c +++ b/src/win32/utf-conv.c @@ -70,12 +70,12 @@ void git__utf8_to_16(wchar_t *dest, size_t length, const char *src) } #endif -int git__utf8_to_16(git_win_str_utf16 dest, const git_win_str_utf8 src) +int git__utf8_to_16(git_win32_path_utf16 dest, const git_win32_path_utf8 src) { return MultiByteToWideChar(CP_UTF8, 0, src, -1, dest, GIT_WIN_PATH_UTF16); } -int git__utf16_to_8(git_win_str_utf8 dest, const git_win_str_utf16 src) +int git__utf16_to_8(git_win32_path_utf8 dest, const git_win32_path_utf16 src) { return WideCharToMultiByte(CP_UTF8, 0, src, -1, dest, GIT_WIN_PATH_UTF8, NULL, NULL); } diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h index d0b6fc825..4e602291e 100644 --- a/src/win32/utf-conv.h +++ b/src/win32/utf-conv.h @@ -13,11 +13,11 @@ #define GIT_WIN_PATH_UTF16 (260 + 1) #define GIT_WIN_PATH_UTF8 (260 * 4 + 1) -typedef wchar_t git_win_str_utf16[GIT_WIN_PATH_UTF16]; -typedef char git_win_str_utf8[GIT_WIN_PATH_UTF8]; +typedef wchar_t git_win32_path_utf16[GIT_WIN_PATH_UTF16]; +typedef char git_win32_path_utf8[GIT_WIN_PATH_UTF8]; -int git__utf8_to_16(git_win_str_utf16 dest, const git_win_str_utf8 src); -int git__utf16_to_8(git_win_str_utf8 dest, const git_win_str_utf16 src); +int git__utf8_to_16(git_win32_path_utf16 dest, const git_win32_path_utf8 src); +int git__utf16_to_8(git_win32_path_utf8 dest, const git_win32_path_utf16 src); #endif diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 869acd613..ebd034a08 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -56,7 +56,7 @@ void cl_git_rewritefile(const char *filename, const char *new_content) char *cl_getenv(const char *name) { - git_win_str_utf16 name_utf16; + git_win32_path_utf16 name_utf16; DWORD alloc_len; wchar_t *value_utf16; char *value_utf8; @@ -81,8 +81,8 @@ char *cl_getenv(const char *name) int cl_setenv(const char *name, const char *value) { - git_win_str_utf16 name_utf16; - git_win_str_utf16 value_utf16; + git_win32_path_utf16 name_utf16; + git_win32_path_utf16 value_utf16; git__utf8_to_16(name_utf16, name); @@ -107,8 +107,8 @@ int cl_setenv(const char *name, const char *value) * the source is a directory, a child of the source). */ int cl_rename(const char *source, const char *dest) { - git_win_str_utf16 source_utf16; - git_win_str_utf16 dest_utf16; + git_win32_path_utf16 source_utf16; + git_win32_path_utf16 dest_utf16; unsigned retries = 1; git__utf8_to_16(source_utf16, source); -- cgit v1.2.1 From d19bcb335256fddc5dd1289f1772d4d864b54ec0 Mon Sep 17 00:00:00 2001 From: Brodie Rao Date: Thu, 6 Jun 2013 14:49:14 -0700 Subject: odb_pack: handle duplicate objects from different packs This is based on 24634c6fd02b2240e4a93fad70a08220f8fb793a. This also corrects an issue with error codes being mixed up with the number of found objects. --- src/odb_pack.c | 41 ++++++++------------- tests-clar/odb/mixed.c | 3 ++ .../resources/duplicate.git/objects/info/packs | 1 + ...ck-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx | Bin 0 -> 1100 bytes ...k-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack | Bin 0 -> 47 bytes 5 files changed, 20 insertions(+), 25 deletions(-) create mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx create mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack diff --git a/src/odb_pack.c b/src/odb_pack.c index eec79259b..43880612a 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -259,23 +259,26 @@ static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backen return git_odb__error_notfound("failed to find pack entry", oid); } -static unsigned pack_entry_find_prefix_inner( - struct git_pack_entry *e, - struct pack_backend *backend, - const git_oid *short_oid, - size_t len, - struct git_pack_file *last_found) +static int pack_entry_find_prefix( + struct git_pack_entry *e, + struct pack_backend *backend, + const git_oid *short_oid, + size_t len) { int error; size_t i; - unsigned found = 0; + git_oid found_full_oid = {{0}}; + bool found = false; + struct git_pack_file *last_found = backend->last_found; if (last_found) { error = git_pack_entry_find(e, last_found, short_oid, len); if (error == GIT_EAMBIGUOUS) return error; - if (!error) - found = 1; + if (!error) { + git_oid_cpy(&found_full_oid, &e->sha1); + found = true; + } } for (i = 0; i < backend->packs.length; ++i) { @@ -289,28 +292,16 @@ static unsigned pack_entry_find_prefix_inner( if (error == GIT_EAMBIGUOUS) return error; if (!error) { - if (++found > 1) - break; + if (found && git_oid_cmp(&e->sha1, &found_full_oid)) + return git_odb__error_ambiguous("found multiple pack entries"); + git_oid_cpy(&found_full_oid, &e->sha1); + found = true; backend->last_found = p; } } - return found; -} - -static int pack_entry_find_prefix( - struct git_pack_entry *e, - struct pack_backend *backend, - const git_oid *short_oid, - size_t len) -{ - struct git_pack_file *last_found = backend->last_found; - unsigned int found = pack_entry_find_prefix_inner(e, backend, short_oid, len, last_found); - if (!found) return git_odb__error_notfound("no matching pack entry for prefix", short_oid); - else if (found > 1) - return git_odb__error_ambiguous("found multiple pack entries"); else return 0; } diff --git a/tests-clar/odb/mixed.c b/tests-clar/odb/mixed.c index 7f7120a6e..dd4587831 100644 --- a/tests-clar/odb/mixed.c +++ b/tests-clar/odb/mixed.c @@ -16,11 +16,14 @@ void test_odb_mixed__cleanup(void) void test_odb_mixed__dup_oid(void) { const char hex[] = "ce013625030ba8dba906f756967f9e9ca394464a"; + const char short_hex[] = "ce01362"; git_oid oid; git_odb_object *obj; cl_git_pass(git_oid_fromstr(&oid, hex)); cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, GIT_OID_HEXSZ)); + cl_git_pass(git_oid_fromstrn(&oid, short_hex, sizeof(short_hex) - 1)); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, sizeof(short_hex) - 1)); git_odb_object_free(obj); } diff --git a/tests-clar/resources/duplicate.git/objects/info/packs b/tests-clar/resources/duplicate.git/objects/info/packs index 3696a7d36..d0fdf905e 100644 --- a/tests-clar/resources/duplicate.git/objects/info/packs +++ b/tests-clar/resources/duplicate.git/objects/info/packs @@ -1,2 +1,3 @@ P pack-e87994ad581c9af946de0eb890175c08cd005f38.pack +P pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx b/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx new file mode 100644 index 000000000..9f78f6e0f Binary files /dev/null and b/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx differ diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack b/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack new file mode 100644 index 000000000..d1dd3b61a Binary files /dev/null and b/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack differ -- cgit v1.2.1 From 6385fc5ff5d669d3ec99d89f19c5860cf53011ba Mon Sep 17 00:00:00 2001 From: Nico von Geyso Date: Sun, 17 Mar 2013 20:39:01 +0100 Subject: added new type and several functions to git_strmap This step is needed to easily add iterators to git_config_backend As well use these new git_strmap functions to implement foreach * git_strmap_iter * git_strmap_has_data(...) * git_strmap_begin(...) * git_strmap_end(...) * git_strmap_next(...) --- src/config_file.c | 5 +++-- src/strmap.c | 34 ++++++++++++++++++++++++++++++++++ src/strmap.h | 12 ++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/strmap.c diff --git a/src/config_file.c b/src/config_file.c index 570f286c8..088f6190d 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -270,7 +270,8 @@ static int file_foreach( } } - git_strmap_foreach(b->values, key, var, + git_strmap_iter iter = git_strmap_begin(b->values); + while (!(git_strmap_next(&key, (void**) &var, &iter, b->values) < 0)) { for (; var != NULL; var = next_var) { next_var = CVAR_LIST_NEXT(var); @@ -285,7 +286,7 @@ static int file_foreach( goto cleanup; } } - ); + } cleanup: if (regexp != NULL) diff --git a/src/strmap.c b/src/strmap.c new file mode 100644 index 000000000..1b07359d1 --- /dev/null +++ b/src/strmap.c @@ -0,0 +1,34 @@ +/* + * 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 "strmap.h" + +int git_strmap_next( + const char **key, + void **data, + git_strmap_iter* iter, + git_strmap *map) +{ + if (!map) + return GIT_ERROR; + + while (*iter != git_strmap_end(map)) { + if (!(git_strmap_has_data(map, *iter))) { + ++(*iter); + continue; + } + + *key = git_strmap_key(map, *iter); + *data = git_strmap_value_at(map, *iter); + + ++(*iter); + + return GIT_OK; + } + + return GIT_ITEROVER; +} diff --git a/src/strmap.h b/src/strmap.h index 44176a0fc..cb079b500 100644 --- a/src/strmap.h +++ b/src/strmap.h @@ -17,6 +17,7 @@ __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) @@ -31,7 +32,9 @@ typedef khash_t(str) git_strmap; #define git_strmap_valid_index(h, idx) (idx != kh_end(h)) #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) +#define git_strmap_key(h, idx) kh_key(h, idx) #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) @@ -61,4 +64,13 @@ typedef khash_t(str) git_strmap; #define git_strmap_foreach kh_foreach #define git_strmap_foreach_value kh_foreach_value +#define git_strmap_begin kh_begin +#define git_strmap_end kh_end + +int git_strmap_next( + const char **key, + void **data, + git_strmap_iter* iter, + git_strmap *map); + #endif -- cgit v1.2.1 From a603c191578f7b33720e36e95421fcd58bc7abe4 Mon Sep 17 00:00:00 2001 From: Nico von Geyso Date: Mon, 18 Mar 2013 21:02:36 +0100 Subject: replaced foreach() with non callback based iterations in git_config_backend new functions in struct git_config_backend: * iterator_new(...) * iterator_free(...) * next(...) The old callback based foreach style can still be used with `git_config_backend_foreach_match` --- include/git2/config.h | 20 +++++++++++ include/git2/sys/config.h | 4 ++- src/config.c | 46 +++++++++++++++++++++++- src/config_file.c | 90 ++++++++++++++++++++++++++++------------------- src/config_file.h | 4 +-- 5 files changed, 123 insertions(+), 41 deletions(-) diff --git a/include/git2/config.h b/include/git2/config.h index 827d43544..f6fc74ee1 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -61,6 +61,7 @@ typedef struct { } git_config_entry; typedef int (*git_config_foreach_cb)(const git_config_entry *, void *); +typedef struct git_config_backend_iter* git_config_backend_iter; typedef enum { GIT_CVAR_FALSE = 0, @@ -535,6 +536,25 @@ GIT_EXTERN(int) git_config_parse_int32(int32_t *out, const char *value); GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value); +/** + * Perform an operation on each config variable in given config backend + * matching a regular expression. + * + * This behaviors like `git_config_foreach_match` except instead of all config + * entries it just enumerates through the given backend entry. + * + * @param backend where to get the variables from + * @param regexp regular expression to match against config names (can be NULL) + * @param callback the function to call on each variable + * @param payload the data to pass to the callback + */ +GIT_EXTERN(int) git_config_backend_foreach_match( + git_config_backend *backend, + const char *regexp, + int (*fn)(const git_config_entry *, void *), + void *data); + + /** @} */ GIT_END_DECL #endif diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 11e59cf03..61dcce544 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -35,7 +35,9 @@ struct git_config_backend { int (*set)(struct git_config_backend *, const char *key, const char *value); int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value); int (*del)(struct git_config_backend *, const char *key); - int (*foreach)(struct git_config_backend *, const char *, git_config_foreach_cb callback, void *payload); + int (*iterator_new)(git_config_backend_iter **, struct git_config_backend *); + void (*iterator_free)(git_config_backend_iter *); + int (*next)(git_config_backend_iter *, git_config_entry *, struct git_config_backend *); int (*refresh)(struct git_config_backend *); void (*free)(struct git_config_backend *); }; diff --git a/src/config.c b/src/config.c index 2a058549f..b421b3be1 100644 --- a/src/config.c +++ b/src/config.c @@ -321,6 +321,50 @@ int git_config_foreach( return git_config_foreach_match(cfg, NULL, cb, payload); } +int git_config_backend_foreach_match( + git_config_backend *backend, + const char *regexp, + int (*fn)(const git_config_entry *, void *), + void *data) +{ + git_config_entry entry; + git_config_backend_iter iter; + regex_t regex; + int result = 0; + + if (regexp != NULL) { + if ((result = regcomp(®ex, regexp, REG_EXTENDED)) < 0) { + giterr_set_regex(®ex, result); + regfree(®ex); + return -1; + } + } + + if (backend->iterator_new(&iter, backend) < 0) + return 0; + + while(!(backend->next(&iter, &entry, backend) < 0)) { + /* skip non-matching keys if regexp was provided */ + if (regexp && regexec(®ex, entry.name, 0, NULL, 0) != 0) + continue; + + /* abort iterator on non-zero return value */ + if (fn(&entry, data)) { + giterr_clear(); + result = GIT_EUSER; + goto cleanup; + } + } + +cleanup: + if (regexp != NULL) + regfree(®ex); + + backend->iterator_free(iter); + + return result; +} + int git_config_foreach_match( const git_config *cfg, const char *regexp, @@ -335,7 +379,7 @@ int git_config_foreach_match( for (i = 0; i < cfg->files.length && ret == 0; ++i) { internal = git_vector_get(&cfg->files, i); file = internal->file; - ret = file->foreach(file, regexp, cb, payload); + ret = git_config_backend_foreach_match(file, regexp, cb, payload); } return ret; diff --git a/src/config_file.c b/src/config_file.c index 088f6190d..ff8f8fc15 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -27,6 +27,12 @@ typedef struct cvar_t { git_config_entry *entry; } cvar_t; +typedef struct git_config_file_iter { + git_strmap_iter iter; + cvar_t* next; +} git_config_file_iter; + + #define CVAR_LIST_HEAD(list) ((list)->head) #define CVAR_LIST_TAIL(list) ((list)->tail) @@ -247,52 +253,60 @@ static void backend_free(git_config_backend *_backend) git__free(backend); } -static int file_foreach( - git_config_backend *backend, - const char *regexp, - int (*fn)(const git_config_entry *, void *), - void *data) +static int config_iterator_new( + git_config_backend_iter *iter, + struct git_config_backend* backend) { diskfile_backend *b = (diskfile_backend *)backend; - cvar_t *var, *next_var; - const char *key; - regex_t regex; - int result = 0; + git_config_file_iter **it= ((git_config_file_iter**) iter); - if (!b->values) - return 0; + if (!b->values || git_strmap_num_entries(b->values) < 1) + return -1; - if (regexp != NULL) { - if ((result = regcomp(®ex, regexp, REG_EXTENDED)) < 0) { - giterr_set_regex(®ex, result); - regfree(®ex); - return -1; - } - } + *it = git__calloc(1, sizeof(git_config_file_iter)); + GITERR_CHECK_ALLOC(it); - git_strmap_iter iter = git_strmap_begin(b->values); - while (!(git_strmap_next(&key, (void**) &var, &iter, b->values) < 0)) { - for (; var != NULL; var = next_var) { - next_var = CVAR_LIST_NEXT(var); + (*it)->iter = git_strmap_begin(b->values); + (*it)->next = NULL; - /* skip non-matching keys if regexp was provided */ - if (regexp && regexec(®ex, key, 0, NULL, 0) != 0) - continue; + return 0; +} - /* abort iterator on non-zero return value */ - if (fn(var->entry, data)) { - giterr_clear(); - result = GIT_EUSER; - goto cleanup; - } - } +static void config_iterator_free( + git_config_backend_iter iter) +{ + git__free(iter); +} + +static int config_next( + git_config_backend_iter *iter, + git_config_entry* entry, + struct git_config_backend* backend) +{ + diskfile_backend *b = (diskfile_backend *)backend; + git_config_file_iter *it = *((git_config_file_iter**) iter); + int err; + cvar_t * var; + const char* key; + + if (it->next == NULL) { + err = git_strmap_next(&key, (void**) &var, &(it->iter), b->values); + } else { + key = it->next->entry->name; + var = it->next; } -cleanup: - if (regexp != NULL) - regfree(®ex); + if (err < 0) { + it->next = NULL; + return -1; + } - return result; + entry->name = key; + entry->value = var->entry->value; + entry->level = var->entry->level; + it->next = CVAR_LIST_NEXT(var); + + return 0; } static int config_set(git_config_backend *cfg, const char *name, const char *value) @@ -595,7 +609,9 @@ int git_config_file__ondisk(git_config_backend **out, const char *path) backend->parent.set = config_set; backend->parent.set_multivar = config_set_multivar; backend->parent.del = config_delete; - backend->parent.foreach = file_foreach; + backend->parent.iterator_new = config_iterator_new; + backend->parent.iterator_free = config_iterator_free; + backend->parent.next = config_next; backend->parent.refresh = config_refresh; backend->parent.free = backend_free; diff --git a/src/config_file.h b/src/config_file.h index 7445859c4..d4a1a4061 100644 --- a/src/config_file.h +++ b/src/config_file.h @@ -42,7 +42,7 @@ GIT_INLINE(int) git_config_file_foreach( int (*fn)(const git_config_entry *entry, void *data), void *data) { - return cfg->foreach(cfg, NULL, fn, data); + return git_config_backend_foreach_match(cfg, NULL, fn, data); } GIT_INLINE(int) git_config_file_foreach_match( @@ -51,7 +51,7 @@ GIT_INLINE(int) git_config_file_foreach_match( int (*fn)(const git_config_entry *entry, void *data), void *data) { - return cfg->foreach(cfg, regexp, fn, data); + return git_config_backend_foreach_match(cfg, regexp, fn, data); } extern int git_config_file_normalize_section(char *start, char *end); -- cgit v1.2.1 From 4d588d9713bb558e45a8bdf6c41d232bb592b814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 8 Aug 2013 11:24:47 +0200 Subject: Don't typedef a pointer Make the iterator structure opaque and make sure it compiles. --- include/git2/config.h | 2 +- include/git2/sys/config.h | 2 +- src/config.c | 4 ++-- src/config.h | 5 +++++ src/config_file.c | 18 ++++++++++-------- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/include/git2/config.h b/include/git2/config.h index f6fc74ee1..43bc19412 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -61,7 +61,7 @@ typedef struct { } git_config_entry; typedef int (*git_config_foreach_cb)(const git_config_entry *, void *); -typedef struct git_config_backend_iter* git_config_backend_iter; +typedef struct git_config_backend_iter git_config_backend_iter; typedef enum { GIT_CVAR_FALSE = 0, diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 61dcce544..f617623a9 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -37,7 +37,7 @@ struct git_config_backend { int (*del)(struct git_config_backend *, const char *key); int (*iterator_new)(git_config_backend_iter **, struct git_config_backend *); void (*iterator_free)(git_config_backend_iter *); - int (*next)(git_config_backend_iter *, git_config_entry *, struct git_config_backend *); + int (*next)(git_config_entry *, git_config_backend_iter *); int (*refresh)(struct git_config_backend *); void (*free)(struct git_config_backend *); }; diff --git a/src/config.c b/src/config.c index b421b3be1..2f800a896 100644 --- a/src/config.c +++ b/src/config.c @@ -328,7 +328,7 @@ int git_config_backend_foreach_match( void *data) { git_config_entry entry; - git_config_backend_iter iter; + git_config_backend_iter* iter; regex_t regex; int result = 0; @@ -343,7 +343,7 @@ int git_config_backend_foreach_match( if (backend->iterator_new(&iter, backend) < 0) return 0; - while(!(backend->next(&iter, &entry, backend) < 0)) { + while(!(backend->next(&entry, iter) < 0)) { /* skip non-matching keys if regexp was provided */ if (regexp && regexec(®ex, entry.name, 0, NULL, 0) != 0) continue; diff --git a/src/config.h b/src/config.h index c5c11ae14..ea150e968 100644 --- a/src/config.h +++ b/src/config.h @@ -24,6 +24,11 @@ struct git_config { git_vector files; }; +typedef struct { + git_config_backend *backend; + unsigned int flags; +} git_config_backend_iter; + extern int git_config_find_global_r(git_buf *global_config_path); extern int git_config_find_xdg_r(git_buf *system_config_path); extern int git_config_find_system_r(git_buf *system_config_path); diff --git a/src/config_file.c b/src/config_file.c index ff8f8fc15..ea571e9f8 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -28,6 +28,8 @@ typedef struct cvar_t { } cvar_t; typedef struct git_config_file_iter { + git_config_backend *backend; + unsigned int flags; git_strmap_iter iter; cvar_t* next; } git_config_file_iter; @@ -254,7 +256,7 @@ static void backend_free(git_config_backend *_backend) } static int config_iterator_new( - git_config_backend_iter *iter, + git_config_backend_iter **iter, struct git_config_backend* backend) { diskfile_backend *b = (diskfile_backend *)backend; @@ -266,6 +268,7 @@ static int config_iterator_new( *it = git__calloc(1, sizeof(git_config_file_iter)); GITERR_CHECK_ALLOC(it); + (*it)->backend = backend; (*it)->iter = git_strmap_begin(b->values); (*it)->next = NULL; @@ -273,18 +276,17 @@ static int config_iterator_new( } static void config_iterator_free( - git_config_backend_iter iter) + git_config_backend_iter* iter) { git__free(iter); } -static int config_next( - git_config_backend_iter *iter, - git_config_entry* entry, - struct git_config_backend* backend) +static int config_iterator_next( + git_config_entry *entry, + git_config_backend_iter *iter) { - diskfile_backend *b = (diskfile_backend *)backend; git_config_file_iter *it = *((git_config_file_iter**) iter); + diskfile_backend *b = (diskfile_backend *)it->backend; int err; cvar_t * var; const char* key; @@ -611,7 +613,7 @@ int git_config_file__ondisk(git_config_backend **out, const char *path) backend->parent.del = config_delete; backend->parent.iterator_new = config_iterator_new; backend->parent.iterator_free = config_iterator_free; - backend->parent.next = config_next; + backend->parent.next = config_iterator_next; backend->parent.refresh = config_refresh; backend->parent.free = backend_free; -- cgit v1.2.1 From 82ae6fcdba2aa0fb21f49b127b5f5f7a637ffc76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 8 Aug 2013 11:55:47 +0200 Subject: config: compilation fixes --- src/config.h | 4 ++-- src/config_file.c | 19 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/config.h b/src/config.h index ea150e968..2f7c96d7f 100644 --- a/src/config.h +++ b/src/config.h @@ -24,10 +24,10 @@ struct git_config { git_vector files; }; -typedef struct { +struct git_config_backend_iter { git_config_backend *backend; unsigned int flags; -} git_config_backend_iter; +}; extern int git_config_find_global_r(git_buf *global_config_path); extern int git_config_find_xdg_r(git_buf *system_config_path); diff --git a/src/config_file.c b/src/config_file.c index ea571e9f8..849ef0f6f 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -28,8 +28,7 @@ typedef struct cvar_t { } cvar_t; typedef struct git_config_file_iter { - git_config_backend *backend; - unsigned int flags; + git_config_backend_iter parent; git_strmap_iter iter; cvar_t* next; } git_config_file_iter; @@ -260,17 +259,17 @@ static int config_iterator_new( struct git_config_backend* backend) { diskfile_backend *b = (diskfile_backend *)backend; - git_config_file_iter **it= ((git_config_file_iter**) iter); + git_config_file_iter *it = git__calloc(1, sizeof(git_config_file_iter)); if (!b->values || git_strmap_num_entries(b->values) < 1) return -1; - *it = git__calloc(1, sizeof(git_config_file_iter)); GITERR_CHECK_ALLOC(it); - (*it)->backend = backend; - (*it)->iter = git_strmap_begin(b->values); - (*it)->next = NULL; + it->parent.backend = backend; + it->iter = git_strmap_begin(b->values); + it->next = NULL; + *iter = (git_config_backend_iter *) it; return 0; } @@ -285,9 +284,9 @@ static int config_iterator_next( git_config_entry *entry, git_config_backend_iter *iter) { - git_config_file_iter *it = *((git_config_file_iter**) iter); - diskfile_backend *b = (diskfile_backend *)it->backend; - int err; + git_config_file_iter *it = (git_config_file_iter *) iter; + diskfile_backend *b = (diskfile_backend *) it->parent.backend; + int err = 0; cvar_t * var; const char* key; -- cgit v1.2.1 From 84fec6f628b8c82a70c0aff5dc6a47d1cdb6fbf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 8 Aug 2013 13:14:35 +0200 Subject: config: saner iterator errors Really report an error in foreach if we fail to allocate the iterator, and don't fail if the config is emtpy. --- src/config.c | 6 ++++-- src/config_file.c | 3 --- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/config.c b/src/config.c index 2f800a896..6c055e0e6 100644 --- a/src/config.c +++ b/src/config.c @@ -340,8 +340,10 @@ int git_config_backend_foreach_match( } } - if (backend->iterator_new(&iter, backend) < 0) - return 0; + if ((result = backend->iterator_new(&iter, backend)) < 0) { + iter = NULL; + return -1; + } while(!(backend->next(&entry, iter) < 0)) { /* skip non-matching keys if regexp was provided */ diff --git a/src/config_file.c b/src/config_file.c index 849ef0f6f..6eb51ac25 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -261,9 +261,6 @@ static int config_iterator_new( diskfile_backend *b = (diskfile_backend *)backend; git_config_file_iter *it = git__calloc(1, sizeof(git_config_file_iter)); - if (!b->values || git_strmap_num_entries(b->values) < 1) - return -1; - GITERR_CHECK_ALLOC(it); it->parent.backend = backend; -- cgit v1.2.1 From 4efa32903adf131631d283c914e0a5bf29c49e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 8 Aug 2013 13:41:18 +0200 Subject: config: get_multivar -> get_multivar_foreach The plain function will return an iterator, so move this one out of the way. --- include/git2/config.h | 4 ++-- include/git2/sys/config.h | 2 +- src/config.c | 4 ++-- src/config_file.c | 4 ++-- src/diff_driver.c | 4 ++-- src/remote.c | 2 +- tests-clar/config/multivar.c | 44 ++++++++++++++++++++-------------------- tests-clar/config/validkeyname.c | 2 +- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/include/git2/config.h b/include/git2/config.h index 43bc19412..a0dc11bb1 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -328,7 +328,7 @@ GIT_EXTERN(int) git_config_get_bool(int *out, const git_config *cfg, const char GIT_EXTERN(int) git_config_get_string(const char **out, const git_config *cfg, const char *name); /** - * Get each value of a multivar. + * Get each value of a multivar in a foreach callback * * The callback will be called on each variable found * @@ -339,7 +339,7 @@ GIT_EXTERN(int) git_config_get_string(const char **out, const git_config *cfg, c * @param callback the function to be called on each value of the variable * @param payload opaque pointer to pass to the callback */ -GIT_EXTERN(int) git_config_get_multivar(const git_config *cfg, const char *name, const char *regexp, git_config_foreach_cb callback, void *payload); +GIT_EXTERN(int) git_config_get_multivar_foreach(const git_config *cfg, const char *name, const char *regexp, git_config_foreach_cb callback, void *payload); /** * Set the value of an integer config variable in the config file diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index f617623a9..09c79638a 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -31,7 +31,7 @@ struct git_config_backend { /* Open means open the file/database and parse if necessary */ int (*open)(struct git_config_backend *, git_config_level_t level); int (*get)(const struct git_config_backend *, const char *key, const git_config_entry **entry); - int (*get_multivar)(struct git_config_backend *, const char *key, const char *regexp, git_config_foreach_cb callback, void *payload); + int (*get_multivar_foreach)(struct git_config_backend *, const char *key, const char *regexp, git_config_foreach_cb callback, void *payload); int (*set)(struct git_config_backend *, const char *key, const char *value); int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value); int (*del)(struct git_config_backend *, const char *key); diff --git a/src/config.c b/src/config.c index 6c055e0e6..a4627c9ad 100644 --- a/src/config.c +++ b/src/config.c @@ -574,7 +574,7 @@ int git_config_get_entry(const git_config_entry **out, const git_config *cfg, co return config_error_notfound(name); } -int git_config_get_multivar( +int git_config_get_multivar_foreach( const git_config *cfg, const char *name, const char *regexp, git_config_foreach_cb cb, void *payload) { @@ -593,7 +593,7 @@ int git_config_get_multivar( continue; file = internal->file; - if (!(err = file->get_multivar(file, name, regexp, cb, payload))) + if (!(err = file->get_multivar_foreach(file, name, regexp, cb, payload))) ret = 0; else if (err != GIT_ENOTFOUND) return err; diff --git a/src/config_file.c b/src/config_file.c index 6eb51ac25..ed79624eb 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -413,7 +413,7 @@ static int config_get(const git_config_backend *cfg, const char *name, const git return 0; } -static int config_get_multivar( +static int config_get_multivar_foreach( git_config_backend *cfg, const char *name, const char *regex_str, @@ -603,7 +603,7 @@ int git_config_file__ondisk(git_config_backend **out, const char *path) backend->parent.open = config_open; backend->parent.get = config_get; - backend->parent.get_multivar = config_get_multivar; + backend->parent.get_multivar_foreach = config_get_multivar_foreach; backend->parent.set = config_set; backend->parent.set_multivar = config_set_multivar; backend->parent.del = config_delete; diff --git a/src/diff_driver.c b/src/diff_driver.c index e82dfa50d..bd5a8fbd9 100644 --- a/src/diff_driver.c +++ b/src/diff_driver.c @@ -187,7 +187,7 @@ static int git_diff_driver_load( git_buf_truncate(&name, namelen + strlen("diff..")); git_buf_put(&name, "xfuncname", strlen("xfuncname")); - if ((error = git_config_get_multivar( + if ((error = git_config_get_multivar_foreach( cfg, name.ptr, NULL, diff_driver_xfuncname, drv)) < 0) { if (error != GIT_ENOTFOUND) goto done; @@ -196,7 +196,7 @@ static int git_diff_driver_load( git_buf_truncate(&name, namelen + strlen("diff..")); git_buf_put(&name, "funcname", strlen("funcname")); - if ((error = git_config_get_multivar( + if ((error = git_config_get_multivar_foreach( cfg, name.ptr, NULL, diff_driver_funcname, drv)) < 0) { if (error != GIT_ENOTFOUND) goto done; diff --git a/src/remote.c b/src/remote.c index 158f3e938..003fadaa3 100644 --- a/src/remote.c +++ b/src/remote.c @@ -217,7 +217,7 @@ static int get_optional_config( return -1; if (cb != NULL) - error = git_config_get_multivar(config, key, NULL, cb, payload); + error = git_config_get_multivar_foreach(config, key, NULL, cb, payload); else error = git_config_get_string(payload, config, key); diff --git a/tests-clar/config/multivar.c b/tests-clar/config/multivar.c index efc431502..390b24c6b 100644 --- a/tests-clar/config/multivar.c +++ b/tests-clar/config/multivar.c @@ -46,27 +46,27 @@ static int cb(const git_config_entry *entry, void *data) return 0; } -static void check_get_multivar( +static void check_get_multivar_foreach( git_config *cfg, int expected, int expected_patterned) { int n = 0; if (expected > 0) { - cl_git_pass(git_config_get_multivar(cfg, _name, NULL, cb, &n)); + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); cl_assert_equal_i(expected, n); } else { cl_assert_equal_i(GIT_ENOTFOUND, - git_config_get_multivar(cfg, _name, NULL, cb, &n)); + git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); } n = 0; if (expected_patterned > 0) { - cl_git_pass(git_config_get_multivar(cfg, _name, "example", cb, &n)); + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "example", cb, &n)); cl_assert_equal_i(expected_patterned, n); } else { cl_assert_equal_i(GIT_ENOTFOUND, - git_config_get_multivar(cfg, _name, "example", cb, &n)); + git_config_get_multivar_foreach(cfg, _name, "example", cb, &n)); } } @@ -75,31 +75,31 @@ void test_config_multivar__get(void) git_config *cfg; cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - check_get_multivar(cfg, 2, 1); + check_get_multivar_foreach(cfg, 2, 1); /* add another that has the _name entry */ cl_git_pass(git_config_add_file_ondisk(cfg, "config/config9", GIT_CONFIG_LEVEL_SYSTEM, 1)); - check_get_multivar(cfg, 3, 2); + check_get_multivar_foreach(cfg, 3, 2); /* add another that does not have the _name entry */ cl_git_pass(git_config_add_file_ondisk(cfg, "config/config0", GIT_CONFIG_LEVEL_GLOBAL, 1)); - check_get_multivar(cfg, 3, 2); + check_get_multivar_foreach(cfg, 3, 2); /* add another that does not have the _name entry at the end */ cl_git_pass(git_config_add_file_ondisk(cfg, "config/config1", GIT_CONFIG_LEVEL_APP, 1)); - check_get_multivar(cfg, 3, 2); + check_get_multivar_foreach(cfg, 3, 2); /* drop original file */ cl_git_pass(git_config_add_file_ondisk(cfg, "config/config2", GIT_CONFIG_LEVEL_LOCAL, 1)); - check_get_multivar(cfg, 1, 1); + check_get_multivar_foreach(cfg, 1, 1); /* drop other file with match */ cl_git_pass(git_config_add_file_ondisk(cfg, "config/config3", GIT_CONFIG_LEVEL_SYSTEM, 1)); - check_get_multivar(cfg, 0, 0); + check_get_multivar_foreach(cfg, 0, 0); /* reload original file (add different place in order) */ cl_git_pass(git_config_add_file_ondisk(cfg, "config/config11", GIT_CONFIG_LEVEL_SYSTEM, 1)); - check_get_multivar(cfg, 2, 1); + check_get_multivar_foreach(cfg, 2, 1); git_config_free(cfg); } @@ -113,11 +113,11 @@ void test_config_multivar__add(void) cl_git_pass(git_config_set_multivar(cfg, _name, "nonexistant", "git://git.otherplace.org/libgit2")); n = 0; - cl_git_pass(git_config_get_multivar(cfg, _name, NULL, cb, &n)); + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); cl_assert(n == 3); n = 0; - cl_git_pass(git_config_get_multivar(cfg, _name, "otherplace", cb, &n)); + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); cl_assert(n == 1); git_config_free(cfg); @@ -127,11 +127,11 @@ void test_config_multivar__add(void) cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); n = 0; - cl_git_pass(git_config_get_multivar(cfg, _name, NULL, cb, &n)); + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); cl_assert(n == 3); n = 0; - cl_git_pass(git_config_get_multivar(cfg, _name, "otherplace", cb, &n)); + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); cl_assert(n == 1); git_config_free(cfg); @@ -147,7 +147,7 @@ void test_config_multivar__add_new(void) cl_git_pass(git_config_set_multivar(cfg, var, "", "variable")); n = 0; - cl_git_pass(git_config_get_multivar(cfg, var, NULL, cb, &n)); + cl_git_pass(git_config_get_multivar_foreach(cfg, var, NULL, cb, &n)); cl_assert(n == 1); git_config_free(cfg); @@ -161,13 +161,13 @@ void test_config_multivar__replace(void) cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); n = 0; - cl_git_pass(git_config_get_multivar(cfg, _name, NULL, cb, &n)); + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); cl_assert(n == 2); cl_git_pass(git_config_set_multivar(cfg, _name, "github", "git://git.otherplace.org/libgit2")); n = 0; - cl_git_pass(git_config_get_multivar(cfg, _name, NULL, cb, &n)); + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); cl_assert(n == 2); git_config_free(cfg); @@ -175,7 +175,7 @@ void test_config_multivar__replace(void) cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); n = 0; - cl_git_pass(git_config_get_multivar(cfg, _name, NULL, cb, &n)); + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); cl_assert(n == 2); git_config_free(cfg); @@ -190,7 +190,7 @@ void test_config_multivar__replace_multiple(void) cl_git_pass(git_config_set_multivar(cfg, _name, "git://", "git://git.otherplace.org/libgit2")); n = 0; - cl_git_pass(git_config_get_multivar(cfg, _name, "otherplace", cb, &n)); + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); cl_assert(n == 2); git_config_free(cfg); @@ -198,7 +198,7 @@ void test_config_multivar__replace_multiple(void) cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); n = 0; - cl_git_pass(git_config_get_multivar(cfg, _name, "otherplace", cb, &n)); + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); cl_assert(n == 2); git_config_free(cfg); diff --git a/tests-clar/config/validkeyname.c b/tests-clar/config/validkeyname.c index 03c13d723..33699737b 100644 --- a/tests-clar/config/validkeyname.c +++ b/tests-clar/config/validkeyname.c @@ -28,7 +28,7 @@ static void assert_invalid_config_key_name(const char *name) GIT_EINVALIDSPEC); cl_git_fail_with(git_config_delete_entry(cfg, name), GIT_EINVALIDSPEC); - cl_git_fail_with(git_config_get_multivar(cfg, name, "*", NULL, NULL), + cl_git_fail_with(git_config_get_multivar_foreach(cfg, name, "*", NULL, NULL), GIT_EINVALIDSPEC); cl_git_fail_with(git_config_set_multivar(cfg, name, "*", "42"), GIT_EINVALIDSPEC); -- cgit v1.2.1 From eba7399251cfa95d9346b9b41ca78dc5d43a840d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 8 Aug 2013 14:39:32 +0200 Subject: config: move next() and free() into the iterator Like we have in the references iterator, next and free belong in the iterator itself. --- include/git2/config.h | 2 +- include/git2/sys/config.h | 30 +++++++++++++++++++++--- src/config.c | 8 +++---- src/config.h | 5 ---- src/config_file.c | 59 ++++++++++++++++++++++++----------------------- 5 files changed, 62 insertions(+), 42 deletions(-) diff --git a/include/git2/config.h b/include/git2/config.h index a0dc11bb1..950312548 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -61,7 +61,7 @@ typedef struct { } git_config_entry; typedef int (*git_config_foreach_cb)(const git_config_entry *, void *); -typedef struct git_config_backend_iter git_config_backend_iter; +typedef struct git_config_iterator git_config_iterator; typedef enum { GIT_CVAR_FALSE = 0, diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 09c79638a..45599dc69 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -20,6 +20,32 @@ */ GIT_BEGIN_DECL +/** + * Every iterator must have this struct as its first element, so the + * API can talk to it. You'd define your iterator as + * + * struct my_iterator { + * git_config_iterator parent; + * ... + * } + * + * and assign `iter->parent.backend` to your `git_config_backend`. + */ +struct git_config_iterator { + git_config_backend *backend; + unsigned int flags; + + /** + * Return the current entry and advance the iterator + */ + int (*next)(git_config_entry *entry, git_config_iterator *iter); + + /** + * Free the iterator + */ + void (*free)(git_config_iterator *iter); +}; + /** * Generic backend that implements the interface to * access a configuration file @@ -35,9 +61,7 @@ struct git_config_backend { int (*set)(struct git_config_backend *, const char *key, const char *value); int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value); int (*del)(struct git_config_backend *, const char *key); - int (*iterator_new)(git_config_backend_iter **, struct git_config_backend *); - void (*iterator_free)(git_config_backend_iter *); - int (*next)(git_config_entry *, git_config_backend_iter *); + int (*iterator)(git_config_iterator **, struct git_config_backend *); int (*refresh)(struct git_config_backend *); void (*free)(struct git_config_backend *); }; diff --git a/src/config.c b/src/config.c index a4627c9ad..5bec0f040 100644 --- a/src/config.c +++ b/src/config.c @@ -328,7 +328,7 @@ int git_config_backend_foreach_match( void *data) { git_config_entry entry; - git_config_backend_iter* iter; + git_config_iterator* iter; regex_t regex; int result = 0; @@ -340,12 +340,12 @@ int git_config_backend_foreach_match( } } - if ((result = backend->iterator_new(&iter, backend)) < 0) { + if ((result = backend->iterator(&iter, backend)) < 0) { iter = NULL; return -1; } - while(!(backend->next(&entry, iter) < 0)) { + while(!(iter->next(&entry, iter) < 0)) { /* skip non-matching keys if regexp was provided */ if (regexp && regexec(®ex, entry.name, 0, NULL, 0) != 0) continue; @@ -362,7 +362,7 @@ cleanup: if (regexp != NULL) regfree(®ex); - backend->iterator_free(iter); + iter->free(iter); return result; } diff --git a/src/config.h b/src/config.h index 2f7c96d7f..c5c11ae14 100644 --- a/src/config.h +++ b/src/config.h @@ -24,11 +24,6 @@ struct git_config { git_vector files; }; -struct git_config_backend_iter { - git_config_backend *backend; - unsigned int flags; -}; - extern int git_config_find_global_r(git_buf *global_config_path); extern int git_config_find_xdg_r(git_buf *system_config_path); extern int git_config_find_system_r(git_buf *system_config_path); diff --git a/src/config_file.c b/src/config_file.c index ed79624eb..3e0c6cc0b 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -28,9 +28,9 @@ typedef struct cvar_t { } cvar_t; typedef struct git_config_file_iter { - git_config_backend_iter parent; + git_config_iterator parent; git_strmap_iter iter; - cvar_t* next; + cvar_t* next_var; } git_config_file_iter; @@ -254,32 +254,15 @@ static void backend_free(git_config_backend *_backend) git__free(backend); } -static int config_iterator_new( - git_config_backend_iter **iter, - struct git_config_backend* backend) -{ - diskfile_backend *b = (diskfile_backend *)backend; - git_config_file_iter *it = git__calloc(1, sizeof(git_config_file_iter)); - - GITERR_CHECK_ALLOC(it); - - it->parent.backend = backend; - it->iter = git_strmap_begin(b->values); - it->next = NULL; - *iter = (git_config_backend_iter *) it; - - return 0; -} - static void config_iterator_free( - git_config_backend_iter* iter) + git_config_iterator* iter) { git__free(iter); } static int config_iterator_next( git_config_entry *entry, - git_config_backend_iter *iter) + git_config_iterator *iter) { git_config_file_iter *it = (git_config_file_iter *) iter; diskfile_backend *b = (diskfile_backend *) it->parent.backend; @@ -287,22 +270,42 @@ static int config_iterator_next( cvar_t * var; const char* key; - if (it->next == NULL) { + if (it->next_var == NULL) { err = git_strmap_next(&key, (void**) &var, &(it->iter), b->values); } else { - key = it->next->entry->name; - var = it->next; + key = it->next_var->entry->name; + var = it->next_var; } if (err < 0) { - it->next = NULL; + it->next_var = NULL; return -1; } entry->name = key; entry->value = var->entry->value; entry->level = var->entry->level; - it->next = CVAR_LIST_NEXT(var); + it->next_var = CVAR_LIST_NEXT(var); + + return 0; +} + +static int config_iterator_new( + git_config_iterator **iter, + struct git_config_backend* backend) +{ + diskfile_backend *b = (diskfile_backend *)backend; + git_config_file_iter *it = git__calloc(1, sizeof(git_config_file_iter)); + + GITERR_CHECK_ALLOC(it); + + it->parent.backend = backend; + it->iter = git_strmap_begin(b->values); + it->next_var = NULL; + + it->parent.next = config_iterator_next; + it->parent.free = config_iterator_free; + *iter = (git_config_iterator *) it; return 0; } @@ -607,9 +610,7 @@ int git_config_file__ondisk(git_config_backend **out, const char *path) backend->parent.set = config_set; backend->parent.set_multivar = config_set_multivar; backend->parent.del = config_delete; - backend->parent.iterator_new = config_iterator_new; - backend->parent.iterator_free = config_iterator_free; - backend->parent.next = config_iterator_next; + backend->parent.iterator = config_iterator_new; backend->parent.refresh = config_refresh; backend->parent.free = backend_free; -- cgit v1.2.1 From 3a7ffc29c9416c5d182835c7f18c04437366f218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 8 Aug 2013 16:18:07 +0200 Subject: config: initial multivar iterator --- include/git2/sys/config.h | 6 ++-- src/config.c | 18 ++++++++++ src/config_file.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 2 deletions(-) diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 45599dc69..477d47271 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -36,9 +36,10 @@ struct git_config_iterator { unsigned int flags; /** - * Return the current entry and advance the iterator + * Return the current entry and advance the iterator. The + * memory belongs to the library. */ - int (*next)(git_config_entry *entry, git_config_iterator *iter); + int (*next)(const git_config_entry *entry, git_config_iterator *iter); /** * Free the iterator @@ -58,6 +59,7 @@ struct git_config_backend { int (*open)(struct git_config_backend *, git_config_level_t level); int (*get)(const struct git_config_backend *, const char *key, const git_config_entry **entry); int (*get_multivar_foreach)(struct git_config_backend *, const char *key, const char *regexp, git_config_foreach_cb callback, void *payload); + int (*get_multivar)(git_config_iterator **, struct git_config_backend *, const char *name, const char *regexp); int (*set)(struct git_config_backend *, const char *key, const char *value); int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value); int (*del)(struct git_config_backend *, const char *key); diff --git a/src/config.c b/src/config.c index 5bec0f040..77c558022 100644 --- a/src/config.c +++ b/src/config.c @@ -602,6 +602,24 @@ int git_config_get_multivar_foreach( return (ret == GIT_ENOTFOUND) ? config_error_notfound(name) : 0; } +struct config_multivar_iter { + git_config_iterator parent; +}; + +int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp) +{ + struct config_multivar_iter *iter; + + iter = git__calloc(1, sizeof(struct config_multivar_iter)); + GITERR_CHECK_ALLOC(iter); + + /* get multivar from each */ + + *out = (git_config_iterator *) iter; + + return 0; +} + int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value) { git_config_backend *file; diff --git a/src/config_file.c b/src/config_file.c index 3e0c6cc0b..5559bd406 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -416,6 +416,95 @@ static int config_get(const git_config_backend *cfg, const char *name, const git return 0; } +typedef struct { + git_config_iterator parent; + cvar_t *var; + regex_t regex; + int have_regex; +} foreach_iter; + +static void foreach_iter_free(git_config_iterator *_iter) +{ + foreach_iter *iter = (foreach_iter *) _iter; + + if (iter->have_regex) + regfree(&iter->regex); + + git__free(iter); +} + +static int foreach_iter_next(git_config_entry **out, git_config_iterator *_iter) +{ + foreach_iter *iter = (foreach_iter *) _iter; + + cvar_t* var = iter->var; + + if (var == NULL) + return GIT_ITEROVER; + + if (!iter->have_regex) { + *out = var->entry; + iter->var = var->next; + return 0; + } + + /* For the regex case, we must loop until we find something we like */ + do { + git_config_entry *entry = var->entry; + regex_t *regex = &iter->regex;; + if (regexec(regex, entry->value, 0, NULL, 0) == 0) { + *out = entry; + return 0; + } + } while(var != NULL); + + return GIT_ITEROVER; +} + +static int config_get_multivar(git_config_iterator **out, git_config_backend *_backend, + const char *name, const char *regexp) +{ + foreach_iter *iter; + diskfile_backend *b = (diskfile_backend *) _backend; + + char *key; + khiter_t pos; + int error = 0; + + if ((error = normalize_name(name, &key)) < 0) + return error; + + pos = git_strmap_lookup_index(b->values, key); + git__free(key); + + if (!git_strmap_valid_index(b->values, pos)) + return GIT_ENOTFOUND; + + iter = git__calloc(1, sizeof(foreach_iter)); + GITERR_CHECK_ALLOC(iter); + + iter->var = git_strmap_value_at(b->values, pos); + + if (regexp != NULL) { + int result; + + result = regcomp(&iter->regex, regexp, REG_EXTENDED); + if (result < 0) { + giterr_set_regex(&iter->regex, result); + regfree(&iter->regex); + return -1; + } + iter->have_regex = 1; + } + + iter->parent.free = foreach_iter_free; + iter->parent.next = foreach_iter_next; + + *out = (git_config_iterator *) iter; + + return 0; + } + static int config_get_multivar_foreach( git_config_backend *cfg, const char *name, @@ -607,6 +696,7 @@ int git_config_file__ondisk(git_config_backend **out, const char *path) backend->parent.open = config_open; backend->parent.get = config_get; backend->parent.get_multivar_foreach = config_get_multivar_foreach; + backend->parent.get_multivar = config_get_multivar; backend->parent.set = config_set; backend->parent.set_multivar = config_set_multivar; backend->parent.del = config_delete; -- cgit v1.2.1 From cca5df6376fd41fb4fbbb9f8a9ff87c38079dfd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 8 Aug 2013 16:59:39 +0200 Subject: config: hopefully get the iterator to work on multivars --- include/git2/sys/config.h | 2 +- src/config.c | 81 ++++++++++++++++++++++++++++++++++++++++++++--- src/config_file.c | 9 ++++-- 3 files changed, 83 insertions(+), 9 deletions(-) diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 477d47271..d5b450a6c 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -39,7 +39,7 @@ struct git_config_iterator { * Return the current entry and advance the iterator. The * memory belongs to the library. */ - int (*next)(const git_config_entry *entry, git_config_iterator *iter); + int (*next)(git_config_entry *entry, git_config_iterator *iter); /** * Free the iterator diff --git a/src/config.c b/src/config.c index 77c558022..f34d5dd29 100644 --- a/src/config.c +++ b/src/config.c @@ -602,18 +602,89 @@ int git_config_get_multivar_foreach( return (ret == GIT_ENOTFOUND) ? config_error_notfound(name) : 0; } -struct config_multivar_iter { +typedef struct { git_config_iterator parent; -}; + git_config_iterator *current; + const char *name; + const char *regexp; + const git_config *cfg; + size_t i; +} multivar_iter; + +static int find_next_backend(size_t *out, const git_config *cfg, size_t i) +{ + file_internal *internal; + + for (; i > 0; --i) { + internal = git_vector_get(&cfg->files, i - 1); + if (!internal || !internal->file) + continue; + + *out = i; + return 0; + } + + return -1; +} + +static int multivar_iter_next_empty(git_config_entry *entry, git_config_iterator *_iter) +{ + GIT_UNUSED(entry); + GIT_UNUSED(_iter); + + return GIT_ITEROVER; +} + +static int multivar_iter_next(git_config_entry *entry, git_config_iterator *_iter) +{ + multivar_iter *iter = (multivar_iter *) _iter; + git_config_iterator *current = iter->current; + file_internal *internal; + git_config_backend *backend; + size_t i; + int error; + + if (current != NULL && + (error = current->next(entry, current)) == 0) + return 0; + + if (error != GIT_ITEROVER) + return error; + + do { + if (find_next_backend(&i, iter->cfg, iter->i) < 0) + return GIT_ITEROVER; + + internal = git_vector_get(&iter->cfg->files, i - 1); + backend = internal->file; + if ((error = backend->get_multivar(&iter->current, backend, iter->name, iter->regexp)) < 0) + return -1; + + iter->i = i; + return iter->current->next(entry, iter->current); + + } while(1); + + return GIT_ITEROVER; +} int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp) { - struct config_multivar_iter *iter; + multivar_iter *iter; + size_t i; - iter = git__calloc(1, sizeof(struct config_multivar_iter)); + iter = git__calloc(1, sizeof(multivar_iter)); GITERR_CHECK_ALLOC(iter); - /* get multivar from each */ + if (find_next_backend(&i, cfg, cfg->files.length) < 0) + iter->parent.next = multivar_iter_next_empty; + else + iter->parent.next = multivar_iter_next; + + iter->i = cfg->files.length; + iter->cfg = cfg; + iter->name = name; + iter->regexp = regexp; *out = (git_config_iterator *) iter; diff --git a/src/config_file.c b/src/config_file.c index 5559bd406..74b200073 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -433,7 +433,7 @@ static void foreach_iter_free(git_config_iterator *_iter) git__free(iter); } -static int foreach_iter_next(git_config_entry **out, git_config_iterator *_iter) +static int foreach_iter_next(git_config_entry *out, git_config_iterator *_iter) { foreach_iter *iter = (foreach_iter *) _iter; @@ -443,7 +443,9 @@ static int foreach_iter_next(git_config_entry **out, git_config_iterator *_iter) return GIT_ITEROVER; if (!iter->have_regex) { - *out = var->entry; + out->name = var->entry->name; + out->value = var->entry->value; + iter->var = var->next; return 0; } @@ -453,7 +455,8 @@ static int foreach_iter_next(git_config_entry **out, git_config_iterator *_iter) git_config_entry *entry = var->entry; regex_t *regex = &iter->regex;; if (regexec(regex, entry->value, 0, NULL, 0) == 0) { - *out = entry; + out->name = entry->name; + out->value = entry->value; return 0; } } while(var != NULL); -- cgit v1.2.1 From aaefbdeea205fbea2005113a9743c81721a42b36 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 8 Aug 2013 08:48:57 -0700 Subject: Discriminate path-specific and general UTF-X conversions --- src/fileops.c | 2 +- src/path.c | 2 +- src/transports/winhttp.c | 6 +++--- src/win32/dir.c | 6 +++--- src/win32/findfile.c | 4 ++-- src/win32/posix.h | 2 +- src/win32/posix_w32.c | 26 +++++++++++++------------- src/win32/utf-conv.c | 8 ++++---- src/win32/utf-conv.h | 17 ++++++++++++++--- tests-clar/clar_libgit2.c | 12 ++++++------ 10 files changed, 48 insertions(+), 37 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 25323d0c9..d62158db7 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -60,7 +60,7 @@ int git_futils_creat_locked(const char *path, const mode_t mode) #ifdef GIT_WIN32 git_win32_path_utf16 buf; - git__utf8_to_16(buf, path); + git__win32_path_utf8_to_16(buf, path); fd = _wopen(buf, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY | O_CLOEXEC, mode); #else diff --git a/src/path.c b/src/path.c index 72831c736..d0cecc070 100644 --- a/src/path.c +++ b/src/path.c @@ -493,7 +493,7 @@ bool git_path_is_empty_dir(const char *path) if (!git_path_isdir(path)) return false; git_buf_printf(&pathbuf, "%s\\*", path); - git__utf8_to_16(wbuf, git_buf_cstr(&pathbuf)); + git__win32_path_utf8_to_16(wbuf, git_buf_cstr(&pathbuf)); hFind = FindFirstFileW(wbuf, &ffd); if (INVALID_HANDLE_VALUE == hFind) { diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 359ab5f5e..5c55c10f1 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -264,7 +264,7 @@ static int winhttp_stream_connect(winhttp_stream *s) if (git_buf_printf(&buf, "Content-Type: application/x-git-%s-request", s->service) < 0) goto on_error; - git__utf8_to_16(ct, git_buf_cstr(&buf)); + git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)); if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) { giterr_set(GITERR_OS, "Failed to add a header to the request"); @@ -593,7 +593,7 @@ replay: else snprintf(expected_content_type_8, MAX_CONTENT_TYPE_LEN, "application/x-git-%s-advertisement", s->service); - git__utf8_to_16(expected_content_type, expected_content_type_8); + git__utf8_to_16(expected_content_type, MAX_CONTENT_TYPE_LEN, expected_content_type_8); content_type_length = sizeof(content_type); if (!WinHttpQueryHeaders(s->request, @@ -920,7 +920,7 @@ static int winhttp_connect( return -1; /* Prepare host */ - git__utf8_to_16(host, t->host); + git__win32_path_utf8_to_16(host, t->host); /* Establish session */ t->session = WinHttpOpen( diff --git a/src/win32/dir.c b/src/win32/dir.c index b1cb47c9b..85f793d62 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -40,7 +40,7 @@ git__DIR *git__opendir(const char *dir) if (!new->dir) goto fail; - git__utf8_to_16(filter_w, filter); + git__win32_path_utf8_to_16(filter_w, filter); new->h = FindFirstFileW(filter_w, &new->f); if (new->h == INVALID_HANDLE_VALUE) { @@ -80,7 +80,7 @@ int git__readdir_ext( if (wcslen(d->f.cFileName) >= sizeof(entry->d_name)) return -1; - git__utf16_to_8(entry->d_name, d->f.cFileName); + git__win32_path_utf16_to_8(entry->d_name, d->f.cFileName); entry->d_ino = 0; *result = entry; @@ -116,7 +116,7 @@ void git__rewinddir(git__DIR *d) if (!init_filter(filter, sizeof(filter), d->dir)) return; - git__utf8_to_16(filter_w, filter); + git__win32_path_utf8_to_16(filter_w, filter); d->h = FindFirstFileW(filter_w, &d->f); if (d->h == INVALID_HANDLE_VALUE) diff --git a/src/win32/findfile.c b/src/win32/findfile.c index 248173563..64b9bb537 100644 --- a/src/win32/findfile.c +++ b/src/win32/findfile.c @@ -27,7 +27,7 @@ static int win32_path_utf16_to_8(git_buf *path_utf8, const wchar_t *path_utf16) { char temp_utf8[GIT_PATH_MAX]; - git__utf16_to_8(temp_utf8, path_utf16); + git__utf16_to_8(temp_utf8, GIT_PATH_MAX, path_utf16); git_path_mkposix(temp_utf8); return git_buf_sets(path_utf8, temp_utf8); @@ -53,7 +53,7 @@ int git_win32__find_file( if (*filename == '/' || *filename == '\\') filename++; - git__utf8_to_16(file_utf16 + root->len - 1, filename); + git__utf8_to_16(file_utf16 + root->len - 1, alloc_len - root->len, filename); /* check access */ if (_waccess(file_utf16, F_OK) < 0) { diff --git a/src/win32/posix.h b/src/win32/posix.h index 47f6ddeb0..7803c9c84 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -22,7 +22,7 @@ GIT_INLINE(int) p_mkdir(const char *path, mode_t mode) { git_win32_path_utf16 buf; GIT_UNUSED(mode); - git__utf8_to_16(buf, path); + git__win32_path_utf8_to_16(buf, path); return _wmkdir(buf); } diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index a7df424df..d9a68f284 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -17,7 +17,7 @@ int p_unlink(const char *path) { git_win32_path_utf16 buf; - git__utf8_to_16(buf, path); + git__win32_path_utf8_to_16(buf, path); _wchmod(buf, 0666); return _wunlink(buf); } @@ -63,7 +63,7 @@ static int do_lstat( wchar_t lastch; int flen; - flen = git__utf8_to_16(fbuf, file_name); + flen = git__win32_path_utf8_to_16(fbuf, file_name); /* truncate trailing slashes */ for (; flen > 0; --flen) { @@ -189,7 +189,7 @@ int p_readlink(const char *link, char *target, size_t target_len) } } - git__utf8_to_16(link_w, link); + git__win32_path_utf8_to_16(link_w, link); hFile = CreateFileW(link_w, // file to open GENERIC_READ, // open for reading @@ -258,7 +258,7 @@ int p_open(const char *path, int flags, ...) git_win32_path_utf16 buf; mode_t mode = 0; - git__utf8_to_16(buf, path); + git__win32_path_utf8_to_16(buf, path); if (flags & O_CREAT) { va_list arg_list; @@ -274,7 +274,7 @@ int p_open(const char *path, int flags, ...) int p_creat(const char *path, mode_t mode) { git_win32_path_utf16 buf; - git__utf8_to_16(buf, path); + git__win32_path_utf8_to_16(buf, path); return _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode); } @@ -317,14 +317,14 @@ int p_stat(const char* path, struct stat* buf) int p_chdir(const char* path) { git_win32_path_utf16 buf; - git__utf8_to_16(buf, path); + git__win32_path_utf8_to_16(buf, path); return _wchdir(buf); } int p_chmod(const char* path, mode_t mode) { git_win32_path_utf16 buf; - git__utf8_to_16(buf, path); + git__win32_path_utf8_to_16(buf, path); return _wchmod(buf, mode); } @@ -332,7 +332,7 @@ int p_rmdir(const char* path) { int error; git_win32_path_utf16 buf; - git__utf8_to_16(buf, path); + git__win32_path_utf8_to_16(buf, path); error = _wrmdir(buf); @@ -349,7 +349,7 @@ int p_rmdir(const char* path) int p_hide_directory__w32(const char *path) { git_win32_path_utf16 buf; - git__utf8_to_16(buf, path); + git__win32_path_utf8_to_16(buf, path); return (SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0) ? 0 : -1; } @@ -359,7 +359,7 @@ char *p_realpath(const char *orig_path, char *buffer) git_win32_path_utf16 orig_path_w; git_win32_path_utf16 buffer_w; - git__utf8_to_16(orig_path_w, orig_path); + git__win32_path_utf8_to_16(orig_path_w, orig_path); /* Implicitly use GetCurrentDirectory which can be a threading issue */ ret = GetFullPathNameW(orig_path_w, GIT_WIN_PATH_UTF16, buffer_w, NULL); @@ -450,7 +450,7 @@ int p_setenv(const char* name, const char* value, int overwrite) int p_access(const char* path, mode_t mode) { git_win32_path_utf16 buf; - git__utf8_to_16(buf, path); + git__win32_path_utf8_to_16(buf, path); return _waccess(buf, mode); } @@ -459,8 +459,8 @@ int p_rename(const char *from, const char *to) git_win32_path_utf16 wfrom; git_win32_path_utf16 wto; - git__utf8_to_16(wfrom, from); - git__utf8_to_16(wto, to); + git__win32_path_utf8_to_16(wfrom, from); + git__win32_path_utf8_to_16(wto, to); return MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? 0 : -1; } diff --git a/src/win32/utf-conv.c b/src/win32/utf-conv.c index bb63b0f8d..623b0517a 100644 --- a/src/win32/utf-conv.c +++ b/src/win32/utf-conv.c @@ -70,12 +70,12 @@ void git__utf8_to_16(wchar_t *dest, size_t length, const char *src) } #endif -int git__utf8_to_16(git_win32_path_utf16 dest, const git_win32_path_utf8 src) +int git__utf8_to_16(wchar_t * dest, size_t dest_size, const char *src) { - return MultiByteToWideChar(CP_UTF8, 0, src, -1, dest, GIT_WIN_PATH_UTF16); + return MultiByteToWideChar(CP_UTF8, 0, src, -1, dest, dest_size); } -int git__utf16_to_8(git_win32_path_utf8 dest, const git_win32_path_utf16 src) +int git__utf16_to_8(char *dest, size_t dest_size, const wchar_t *src) { - return WideCharToMultiByte(CP_UTF8, 0, src, -1, dest, GIT_WIN_PATH_UTF8, NULL, NULL); + return WideCharToMultiByte(CP_UTF8, 0, src, -1, dest, dest_size, NULL, NULL); } diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h index 4e602291e..7290f1d1a 100644 --- a/src/win32/utf-conv.h +++ b/src/win32/utf-conv.h @@ -16,8 +16,19 @@ typedef wchar_t git_win32_path_utf16[GIT_WIN_PATH_UTF16]; typedef char git_win32_path_utf8[GIT_WIN_PATH_UTF8]; -int git__utf8_to_16(git_win32_path_utf16 dest, const git_win32_path_utf8 src); -int git__utf16_to_8(git_win32_path_utf8 dest, const git_win32_path_utf16 src); +// dest_size is the size of dest in wchar_t's +int git__utf8_to_16(wchar_t * dest, size_t dest_size, const char *src); +// dest_size is the size of dest in char's +int git__utf16_to_8(char *dest, size_t dest_size, const wchar_t *src); -#endif +GIT_INLINE(int) git__win32_path_utf8_to_16(git_win32_path_utf16 dest, const git_win32_path_utf8 src) +{ + return git__utf8_to_16(dest, GIT_WIN_PATH_UTF16, src); +} + +GIT_INLINE(int) git__win32_path_utf16_to_8(git_win32_path_utf8 dest, const git_win32_path_utf16 src) +{ + return git__utf16_to_8(dest, GIT_WIN_PATH_UTF8, src); +} +#endif diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index ebd034a08..6c741accd 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -61,7 +61,7 @@ char *cl_getenv(const char *name) wchar_t *value_utf16; char *value_utf8; - git__utf8_to_16(name_utf16, name); + git__win32_path_utf8_to_16(name_utf16, name); alloc_len = GetEnvironmentVariableW(name_utf16, NULL, 0); if (alloc_len <= 0) return NULL; @@ -72,7 +72,7 @@ char *cl_getenv(const char *name) GetEnvironmentVariableW(name_utf16, value_utf16, alloc_len); cl_assert(value_utf8 = git__malloc(alloc_len)); - git__utf16_to_8(value_utf8, value_utf16); + git__win32_path_utf16_to_8(value_utf8, value_utf16); git__free(value_utf16); @@ -84,10 +84,10 @@ int cl_setenv(const char *name, const char *value) git_win32_path_utf16 name_utf16; git_win32_path_utf16 value_utf16; - git__utf8_to_16(name_utf16, name); + git__win32_path_utf8_to_16(name_utf16, name); if (value) { - git__utf8_to_16(value_utf16, value); + git__win32_path_utf8_to_16(value_utf16, value); cl_assert(SetEnvironmentVariableW(name_utf16, value_utf16)); } else { /* Windows XP returns 0 (failed) when passing NULL for lpValue when @@ -111,8 +111,8 @@ int cl_rename(const char *source, const char *dest) git_win32_path_utf16 dest_utf16; unsigned retries = 1; - git__utf8_to_16(source_utf16, source); - git__utf8_to_16(dest_utf16, dest); + git__win32_path_utf8_to_16(source_utf16, source); + git__win32_path_utf8_to_16(dest_utf16, dest); while (!MoveFileW(source_utf16, dest_utf16)) { /* Only retry if the error is ERROR_ACCESS_DENIED; -- cgit v1.2.1 From 57f31f058c29edfd7d6d810fcd4a964875e9d463 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 8 Aug 2013 11:05:00 -0500 Subject: Fixes to safely reading the index Avoid wrapping around extension size when reading, avoid walking off the end of the buffer when reading names. --- src/index.c | 7 ++++--- src/posix.h | 4 ++++ src/win32/mingw-compat.h | 5 +++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/index.c b/src/index.c index cbdd43bdc..5f53f1e2f 100644 --- a/src/index.c +++ b/src/index.c @@ -1371,7 +1371,7 @@ static int read_reuc(git_index *index, const char *buffer, size_t size) while (size) { git_index_reuc_entry *lost; - len = strlen(buffer) + 1; + len = p_strnlen(buffer, size) + 1; if (size <= len) return index_error_invalid("reading reuc entries"); @@ -1444,7 +1444,7 @@ static int read_conflict_names(git_index *index, const char *buffer, size_t size return -1; #define read_conflict_name(ptr) \ - len = strlen(buffer) + 1; \ + len = p_strnlen(buffer, size) + 1; \ if (size < len) \ return index_error_invalid("reading conflict name entries"); \ \ @@ -1571,7 +1571,8 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer total_size = dest.extension_size + sizeof(struct index_extension); - if (buffer_size < total_size || + if (dest.extension_size > total_size || + buffer_size < total_size || buffer_size - total_size < INDEX_FOOTER_SIZE) return 0; diff --git a/src/posix.h b/src/posix.h index 40bcc1ab0..ea97a1349 100644 --- a/src/posix.h +++ b/src/posix.h @@ -93,6 +93,10 @@ extern int p_gettimeofday(struct timeval *tv, struct timezone *tz); # include "unix/posix.h" #endif +#ifndef __MINGW32__ +# define p_strnlen strnlen +#endif + #ifdef NO_READDIR_R # include GIT_INLINE(int) p_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) diff --git a/src/win32/mingw-compat.h b/src/win32/mingw-compat.h index 7b97b48db..97b1cb71b 100644 --- a/src/win32/mingw-compat.h +++ b/src/win32/mingw-compat.h @@ -19,6 +19,11 @@ # define S_IFLNK _S_IFLNK # define S_ISLNK(m) (((m) & _S_IFMT) == _S_IFLNK) +GIT_INLINE(size_t) p_strnlen(const char *s, size_t maxlen) { + const char *end = memchr(s, 0, maxlen); + return end ? (end - s) : maxlen; +} + #endif #endif /* INCLUDE_mingw_compat__ */ -- cgit v1.2.1 From a1f69452a22689ca2eede7669e79a3e7ab849cdd Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 8 Aug 2013 12:36:11 -0500 Subject: git_strndup fix when OOM --- src/util.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/util.h b/src/util.h index ed9624770..a784390c1 100644 --- a/src/util.h +++ b/src/util.h @@ -55,6 +55,9 @@ GIT_INLINE(char *) git__strndup(const char *str, size_t n) ptr = (char*)git__malloc(length + 1); + if (!ptr) + return NULL; + if (length) memcpy(ptr, str, length); -- cgit v1.2.1 From 99dfb538addc06c2f40d29371c52dd43f0d6ceb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 8 Aug 2013 17:57:59 +0200 Subject: config: working multivar iterator Implement the foreach version as a wrapper around the iterator. --- include/git2/config.h | 10 +++++ include/git2/sys/config.h | 2 +- src/config.c | 91 +++++++++++++++++++++++++++----------------- src/config_file.c | 20 +++++----- tests-clar/config/multivar.c | 14 +++---- 5 files changed, 84 insertions(+), 53 deletions(-) diff --git a/include/git2/config.h b/include/git2/config.h index 950312548..e1d34b997 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -341,6 +341,16 @@ GIT_EXTERN(int) git_config_get_string(const char **out, const git_config *cfg, c */ GIT_EXTERN(int) git_config_get_multivar_foreach(const git_config *cfg, const char *name, const char *regexp, git_config_foreach_cb callback, void *payload); +/** + * Get each value of a multivar + * + * @param out pointer to store the iterator + * @param cfg where to look for the variable + * @param name the variable's name + * @param regexp regular expression to filter which variables we're + * interested in. Use NULL to indicate all + */ +GIT_EXTERN(int) git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp); /** * Set the value of an integer config variable in the config file * with the highest level (usually the local one). diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index d5b450a6c..e369fb8ab 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -39,7 +39,7 @@ struct git_config_iterator { * Return the current entry and advance the iterator. The * memory belongs to the library. */ - int (*next)(git_config_entry *entry, git_config_iterator *iter); + int (*next)(git_config_entry **entry, git_config_iterator *iter); /** * Free the iterator diff --git a/src/config.c b/src/config.c index f34d5dd29..63a386de3 100644 --- a/src/config.c +++ b/src/config.c @@ -327,7 +327,7 @@ int git_config_backend_foreach_match( int (*fn)(const git_config_entry *, void *), void *data) { - git_config_entry entry; + git_config_entry *entry; git_config_iterator* iter; regex_t regex; int result = 0; @@ -347,11 +347,11 @@ int git_config_backend_foreach_match( while(!(iter->next(&entry, iter) < 0)) { /* skip non-matching keys if regexp was provided */ - if (regexp && regexec(®ex, entry.name, 0, NULL, 0) != 0) + if (regexp && regexec(®ex, entry->name, 0, NULL, 0) != 0) continue; /* abort iterator on non-zero return value */ - if (fn(&entry, data)) { + if (fn(entry, data)) { giterr_clear(); result = GIT_EUSER; goto cleanup; @@ -578,35 +578,36 @@ int git_config_get_multivar_foreach( const git_config *cfg, const char *name, const char *regexp, git_config_foreach_cb cb, void *payload) { - file_internal *internal; - git_config_backend *file; - int ret = GIT_ENOTFOUND, err; - size_t i; + int err, found; + git_config_iterator *iter; + git_config_entry *entry; + + if ((err = git_config_get_multivar(&iter, cfg, name, regexp)) < 0) + return err; + + found = 0; + while ((err = iter->next(&entry, iter)) == 0) { + found = 1; + if(cb(entry, payload)) { + iter->free(iter); + return GIT_EUSER; + } + } - /* - * This loop runs the "wrong" way 'round because we need to - * look at every value from the most general to most specific - */ - for (i = cfg->files.length; i > 0; --i) { - internal = git_vector_get(&cfg->files, i - 1); - if (!internal || !internal->file) - continue; - file = internal->file; + if (err == GIT_ITEROVER) + err = 0; - if (!(err = file->get_multivar_foreach(file, name, regexp, cb, payload))) - ret = 0; - else if (err != GIT_ENOTFOUND) - return err; - } + if (found == 0 && err == 0) + err = config_error_notfound(name); - return (ret == GIT_ENOTFOUND) ? config_error_notfound(name) : 0; + return err; } typedef struct { git_config_iterator parent; git_config_iterator *current; - const char *name; - const char *regexp; + char *name; + char *regexp; const git_config *cfg; size_t i; } multivar_iter; @@ -627,7 +628,7 @@ static int find_next_backend(size_t *out, const git_config *cfg, size_t i) return -1; } -static int multivar_iter_next_empty(git_config_entry *entry, git_config_iterator *_iter) +static int multivar_iter_next_empty(git_config_entry **entry, git_config_iterator *_iter) { GIT_UNUSED(entry); GIT_UNUSED(_iter); @@ -635,20 +636,21 @@ static int multivar_iter_next_empty(git_config_entry *entry, git_config_iterator return GIT_ITEROVER; } -static int multivar_iter_next(git_config_entry *entry, git_config_iterator *_iter) +static int multivar_iter_next(git_config_entry **entry, git_config_iterator *_iter) { multivar_iter *iter = (multivar_iter *) _iter; git_config_iterator *current = iter->current; file_internal *internal; git_config_backend *backend; size_t i; - int error; + int error = 0; if (current != NULL && - (error = current->next(entry, current)) == 0) + (error = current->next(entry, current)) == 0) { return 0; + } - if (error != GIT_ITEROVER) + if (error < 0 && error != GIT_ITEROVER) return error; do { @@ -657,10 +659,15 @@ static int multivar_iter_next(git_config_entry *entry, git_config_iterator *_ite internal = git_vector_get(&iter->cfg->files, i - 1); backend = internal->file; - if ((error = backend->get_multivar(&iter->current, backend, iter->name, iter->regexp)) < 0) - return -1; + iter->i = i - 1; + + error = backend->get_multivar(&iter->current, backend, iter->name, iter->regexp); + if (error == GIT_ENOTFOUND) + continue; + + if (error < 0) + return error; - iter->i = i; return iter->current->next(entry, iter->current); } while(1); @@ -668,6 +675,15 @@ static int multivar_iter_next(git_config_entry *entry, git_config_iterator *_ite return GIT_ITEROVER; } +void multivar_iter_free(git_config_iterator *_iter) +{ + multivar_iter *iter = (multivar_iter *) _iter; + + git__free(iter->name); + git__free(iter->regexp); + git__free(iter); +} + int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp) { multivar_iter *iter; @@ -676,6 +692,15 @@ int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, co iter = git__calloc(1, sizeof(multivar_iter)); GITERR_CHECK_ALLOC(iter); + iter->name = git__strdup(name); + GITERR_CHECK_ALLOC(iter->name); + + if (regexp != NULL) { + iter->regexp = git__strdup(regexp); + GITERR_CHECK_ALLOC(iter->regexp); + } + + iter->parent.free = multivar_iter_free; if (find_next_backend(&i, cfg, cfg->files.length) < 0) iter->parent.next = multivar_iter_next_empty; else @@ -683,8 +708,6 @@ int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, co iter->i = cfg->files.length; iter->cfg = cfg; - iter->name = name; - iter->regexp = regexp; *out = (git_config_iterator *) iter; diff --git a/src/config_file.c b/src/config_file.c index 74b200073..38cb9f8b8 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -261,7 +261,7 @@ static void config_iterator_free( } static int config_iterator_next( - git_config_entry *entry, + git_config_entry **entry, git_config_iterator *iter) { git_config_file_iter *it = (git_config_file_iter *) iter; @@ -282,9 +282,7 @@ static int config_iterator_next( return -1; } - entry->name = key; - entry->value = var->entry->value; - entry->level = var->entry->level; + *entry = var->entry; it->next_var = CVAR_LIST_NEXT(var); return 0; @@ -433,19 +431,18 @@ static void foreach_iter_free(git_config_iterator *_iter) git__free(iter); } -static int foreach_iter_next(git_config_entry *out, git_config_iterator *_iter) +static int foreach_iter_next(git_config_entry **out, git_config_iterator *_iter) { foreach_iter *iter = (foreach_iter *) _iter; cvar_t* var = iter->var; + if (var == NULL) return GIT_ITEROVER; if (!iter->have_regex) { - out->name = var->entry->name; - out->value = var->entry->value; - + *out = var->entry; iter->var = var->next; return 0; } @@ -455,10 +452,11 @@ static int foreach_iter_next(git_config_entry *out, git_config_iterator *_iter) git_config_entry *entry = var->entry; regex_t *regex = &iter->regex;; if (regexec(regex, entry->value, 0, NULL, 0) == 0) { - out->name = entry->name; - out->value = entry->value; + *out = entry; + iter->var = var->next; return 0; } + var = var->next; } while(var != NULL); return GIT_ITEROVER; @@ -550,7 +548,7 @@ static int config_get_multivar_foreach( if (regexec(®ex, var->entry->value, 0, NULL, 0) == 0) { /* early termination by the user is not an error; * just break and return successfully */ - if (fn(var->entry, data) < 0) + if (fn(var->entry, data)) break; } diff --git a/tests-clar/config/multivar.c b/tests-clar/config/multivar.c index 390b24c6b..b7283b32f 100644 --- a/tests-clar/config/multivar.c +++ b/tests-clar/config/multivar.c @@ -114,11 +114,11 @@ void test_config_multivar__add(void) n = 0; cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - cl_assert(n == 3); + cl_assert_equal_i(n, 3); n = 0; cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); - cl_assert(n == 1); + cl_assert_equal_i(n, 1); git_config_free(cfg); @@ -128,11 +128,11 @@ void test_config_multivar__add(void) n = 0; cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - cl_assert(n == 3); + cl_assert_equal_i(n, 3); n = 0; cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); - cl_assert(n == 1); + cl_assert_equal_i(n, 1); git_config_free(cfg); } @@ -148,7 +148,7 @@ void test_config_multivar__add_new(void) cl_git_pass(git_config_set_multivar(cfg, var, "", "variable")); n = 0; cl_git_pass(git_config_get_multivar_foreach(cfg, var, NULL, cb, &n)); - cl_assert(n == 1); + cl_assert_equal_i(n, 1); git_config_free(cfg); } @@ -191,7 +191,7 @@ void test_config_multivar__replace_multiple(void) n = 0; cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); - cl_assert(n == 2); + cl_assert_equal_i(n, 2); git_config_free(cfg); @@ -199,7 +199,7 @@ void test_config_multivar__replace_multiple(void) n = 0; cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); - cl_assert(n == 2); + cl_assert_equal_i(n, 2); git_config_free(cfg); } -- cgit v1.2.1 From 1e96c9d5341e5f2b0e1af9a1088cc30d3ffb9a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 8 Aug 2013 20:47:06 +0200 Subject: config: add _next() and _iterator_free() Make it look like the refs iterator API. --- include/git2/config.h | 17 +++++++++++++++++ src/config.c | 10 ++++++++++ tests-clar/config/multivar.c | 18 ++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/include/git2/config.h b/include/git2/config.h index e1d34b997..b338e0c81 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -351,6 +351,23 @@ GIT_EXTERN(int) git_config_get_multivar_foreach(const git_config *cfg, const cha * interested in. Use NULL to indicate all */ GIT_EXTERN(int) git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp); + +/** + * Return the current entry and advance the iterator + * + * @param entry pointer to store the entry + * @param iter the iterator + * @return 0 or an error code. GIT_ITEROVER if the iteration has completed + */ +GIT_EXTERN(int) git_config_next(git_config_entry **entry, git_config_iterator *iter); + +/** + * Free a config iterator + * + * @param iter the iterator to free + */ +GIT_EXTERN(void) git_config_iterator_free(git_config_iterator *iter); + /** * Set the value of an integer config variable in the config file * with the highest level (usually the local one). diff --git a/src/config.c b/src/config.c index 63a386de3..83b101ded 100644 --- a/src/config.c +++ b/src/config.c @@ -727,6 +727,16 @@ int git_config_set_multivar(git_config *cfg, const char *name, const char *regex return file->set_multivar(file, name, regexp, value); } +int git_config_next(git_config_entry **entry, git_config_iterator *iter) +{ + return iter->next(entry, iter); +} + +void git_config_iterator_free(git_config_iterator *iter) +{ + iter->free(iter); +} + static int git_config__find_file_to_path( char *out, size_t outlen, int (*find)(git_buf *buf)) { diff --git a/tests-clar/config/multivar.c b/tests-clar/config/multivar.c index b7283b32f..afb993c18 100644 --- a/tests-clar/config/multivar.c +++ b/tests-clar/config/multivar.c @@ -70,6 +70,22 @@ static void check_get_multivar_foreach( } } +static void check_get_multivar(git_config *cfg, int expected) +{ + git_config_iterator *iter; + git_config_entry *entry; + int n = 0; + + cl_git_pass(git_config_get_multivar(&iter, cfg, _name, NULL)); + + while (git_config_next(&entry, iter) == 0) + n++; + + cl_assert_equal_i(expected, n); + git_config_iterator_free(iter); + +} + void test_config_multivar__get(void) { git_config *cfg; @@ -101,6 +117,8 @@ void test_config_multivar__get(void) cl_git_pass(git_config_add_file_ondisk(cfg, "config/config11", GIT_CONFIG_LEVEL_SYSTEM, 1)); check_get_multivar_foreach(cfg, 2, 1); + check_get_multivar(cfg, 2); + git_config_free(cfg); } -- cgit v1.2.1 From a319ffaead9290bfe35a0f105ff17dacaf7b6e7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 8 Aug 2013 21:00:33 +0200 Subject: config: fix leaks in the iterators --- src/config.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/config.c b/src/config.c index 83b101ded..42273cde8 100644 --- a/src/config.c +++ b/src/config.c @@ -594,6 +594,7 @@ int git_config_get_multivar_foreach( } } + iter->free(iter); if (err == GIT_ITEROVER) err = 0; @@ -661,6 +662,10 @@ static int multivar_iter_next(git_config_entry **entry, git_config_iterator *_it backend = internal->file; iter->i = i - 1; + if (iter->current) + iter->current->free(current); + + iter->current = NULL; error = backend->get_multivar(&iter->current, backend, iter->name, iter->regexp); if (error == GIT_ENOTFOUND) continue; @@ -679,6 +684,9 @@ void multivar_iter_free(git_config_iterator *_iter) { multivar_iter *iter = (multivar_iter *) _iter; + if (iter->current) + iter->current->free(iter->current); + git__free(iter->name); git__free(iter->regexp); git__free(iter); -- cgit v1.2.1 From c57f668268744cbccb13c30095a0c1649fb18a63 Mon Sep 17 00:00:00 2001 From: Nikolai Vladimirov Date: Thu, 8 Aug 2013 21:17:32 +0300 Subject: config: allow empty string as value `git_config_set_string(config, "config.section", "")` fails when escaping the value. The buffer in `escape_value` is allocated without NULL-termination. And in case of empty string 0 is passed for buffer size in `git_buf_grow`. `git_buf_detach` returns NULL when the allocated size is 0 and that leads to an error return in `GITERR_CHECK_ALLOC` called after `escape_value` The change in `config_file.c` was suggested by Russell Belfer --- src/config_file.c | 3 +++ tests-clar/config/write.c | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/config_file.c b/src/config_file.c index 2b0732a13..605e2e99c 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -1293,6 +1293,9 @@ static char *escape_value(const char *ptr) assert(ptr); len = strlen(ptr); + if (!len) + return git__calloc(1, sizeof(char)); + git_buf_grow(&buf, len); while (*ptr != '\0') { diff --git a/tests-clar/config/write.c b/tests-clar/config/write.c index d70612a97..57b02a7d9 100644 --- a/tests-clar/config/write.c +++ b/tests-clar/config/write.c @@ -242,3 +242,20 @@ void test_config_write__can_set_a_value_to_NULL(void) cl_git_sandbox_cleanup(); } + +void test_config_write__can_set_an_empty_value(void) +{ + git_repository *repository; + git_config *config; + const char * str; + + repository = cl_git_sandbox_init("testrepo.git"); + cl_git_pass(git_repository_config(&config, repository)); + + cl_git_pass(git_config_set_string(config, "core.somevar", "")); + cl_git_pass(git_config_get_string(&str, config, "core.somevar")); + cl_assert_equal_s(str, ""); + + git_config_free(config); + cl_git_sandbox_cleanup(); +} -- cgit v1.2.1 From 4ba64794aee983483eef659623a765d61311ded1 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 9 Aug 2013 10:52:35 -0700 Subject: Revert PR #1462 and provide alternative fix This rolls back the changes to fnmatch parsing from commit 2e40a60e847d6c128af23e24ea7a8efebd2427da except for the tests that were added. Instead this adds couple of new flags that can be passed in when attempting to parse an fnmatch pattern. Also, this changes the pathspec match logic to special case matching a filename with a '!' prefix against a negative pattern. This fixes the build. --- src/attr_file.c | 61 ++++++++++++++++---------------------------------- src/attr_file.h | 14 ++++++------ src/ignore.c | 4 ++-- src/pathspec.c | 13 +++++++++-- tests-clar/attr/file.c | 8 +++---- 5 files changed, 42 insertions(+), 58 deletions(-) diff --git a/src/attr_file.c b/src/attr_file.c index ca5f2137c..92702df98 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -79,13 +79,17 @@ int git_attr_file__parse_buffer( while (!error && *scan) { /* allocate rule if needed */ - if (!rule && !(rule = git__calloc(1, sizeof(git_attr_rule)))) { - error = -1; - break; + if (!rule) { + if (!(rule = git__calloc(1, sizeof(git_attr_rule)))) { + error = -1; + break; + } + rule->match.flags = GIT_ATTR_FNMATCH_ALLOWNEG | + GIT_ATTR_FNMATCH_ALLOWMACRO; } /* parse the next "pattern attr attr attr" line */ - if (!(error = git_attr_fnmatch__parse_gitattr_format( + if (!(error = git_attr_fnmatch__parse( &rule->match, attrs->pool, context, &scan)) && !(error = git_attr_assignment__parse( repo, attrs->pool, &rule->assigns, &scan))) @@ -337,16 +341,23 @@ void git_attr_path__free(git_attr_path *info) * GIT_ENOTFOUND if the fnmatch does not require matching, or * another error code there was an actual problem. */ -int git_attr_fnmatch__parse_gitattr_format( +int git_attr_fnmatch__parse( git_attr_fnmatch *spec, git_pool *pool, const char *source, const char **base) { - const char *pattern; + const char *pattern, *scan; + int slash_count, allow_space; assert(spec && base && *base); + if (parse_optimized_patterns(spec, pool, *base)) + return 0; + + spec->flags = (spec->flags & GIT_ATTR_FNMATCH__INCOMING); + allow_space = ((spec->flags & GIT_ATTR_FNMATCH_ALLOWSPACE) != 0); + pattern = *base; while (git__isspace(*pattern)) pattern++; @@ -355,7 +366,7 @@ int git_attr_fnmatch__parse_gitattr_format( return GIT_ENOTFOUND; } - if (*pattern == '[') { + if (*pattern == '[' && (spec->flags & GIT_ATTR_FNMATCH_ALLOWMACRO) != 0) { if (strncmp(pattern, "[attr]", 6) == 0) { spec->flags = spec->flags | GIT_ATTR_FNMATCH_MACRO; pattern += 6; @@ -363,44 +374,11 @@ int git_attr_fnmatch__parse_gitattr_format( /* else a character range like [a-e]* which is accepted */ } - if (*pattern == '!') { + if (*pattern == '!' && (spec->flags & GIT_ATTR_FNMATCH_ALLOWNEG) != 0) { spec->flags = spec->flags | GIT_ATTR_FNMATCH_NEGATIVE; pattern++; } - if (git_attr_fnmatch__parse_shellglob_format(spec, pool, - source, &pattern) < 0) - return -1; - - *base = pattern; - - return 0; -} - -/* - * Fills a spec for the purpose of pure pathspec matching, not - * related to a gitattribute file parsing. - * - * This will return 0 if the spec was filled out, or - * another error code there was an actual problem. - */ -int git_attr_fnmatch__parse_shellglob_format( - git_attr_fnmatch *spec, - git_pool *pool, - const char *source, - const char **base) -{ - const char *pattern, *scan; - int slash_count, allow_space; - - assert(spec && base && *base); - - if (parse_optimized_patterns(spec, pool, *base)) - return 0; - - allow_space = (spec->flags & GIT_ATTR_FNMATCH_ALLOWSPACE) != 0; - pattern = *base; - slash_count = 0; for (scan = pattern; *scan != '\0'; ++scan) { /* scan until (non-escaped) white space */ @@ -636,7 +614,6 @@ static void git_attr_rule__clear(git_attr_rule *rule) /* match.pattern is stored in a git_pool, so no need to free */ rule->match.pattern = NULL; rule->match.length = 0; - rule->match.flags = 0; } void git_attr_rule__free(git_attr_rule *rule) diff --git a/src/attr_file.h b/src/attr_file.h index afea1e115..3bc7c6cb8 100644 --- a/src/attr_file.h +++ b/src/attr_file.h @@ -28,6 +28,12 @@ #define GIT_ATTR_FNMATCH_ALLOWSPACE (1U << 6) #define GIT_ATTR_FNMATCH_ICASE (1U << 7) #define GIT_ATTR_FNMATCH_MATCH_ALL (1U << 8) +#define GIT_ATTR_FNMATCH_ALLOWNEG (1U << 9) +#define GIT_ATTR_FNMATCH_ALLOWMACRO (1U << 10) + +#define GIT_ATTR_FNMATCH__INCOMING \ + (GIT_ATTR_FNMATCH_ALLOWSPACE | \ + GIT_ATTR_FNMATCH_ALLOWNEG | GIT_ATTR_FNMATCH_ALLOWMACRO) extern const char *git_attr__true; extern const char *git_attr__false; @@ -115,13 +121,7 @@ extern uint32_t git_attr_file__name_hash(const char *name); * other utilities */ -extern int git_attr_fnmatch__parse_gitattr_format( - git_attr_fnmatch *spec, - git_pool *pool, - const char *source, - const char **base); - -extern int git_attr_fnmatch__parse_shellglob_format( +extern int git_attr_fnmatch__parse( git_attr_fnmatch *spec, git_pool *pool, const char *source, diff --git a/src/ignore.c b/src/ignore.c index 7d8280403..3c23158c2 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -37,9 +37,9 @@ static int parse_ignore_file( GITERR_CHECK_ALLOC(match); } - match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE; + match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE | GIT_ATTR_FNMATCH_ALLOWNEG; - if (!(error = git_attr_fnmatch__parse_gitattr_format( + if (!(error = git_attr_fnmatch__parse( match, ignores->pool, context, &scan))) { match->flags |= GIT_ATTR_FNMATCH_IGNORE; diff --git a/src/pathspec.c b/src/pathspec.c index 4266bb99e..1d7b71a74 100644 --- a/src/pathspec.c +++ b/src/pathspec.c @@ -83,9 +83,9 @@ int git_pathspec__vinit( if (!match) return -1; - match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE; + match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE | GIT_ATTR_FNMATCH_ALLOWNEG; - ret = git_attr_fnmatch__parse_shellglob_format(match, strpool, NULL, &pattern); + ret = git_attr_fnmatch__parse(match, strpool, NULL, &pattern); if (ret == GIT_ENOTFOUND) { git__free(match); continue; @@ -160,6 +160,15 @@ static int pathspec_match_one( path[match->length] == '/') result = 0; + /* if we didn't match and this is a negative match, check for exact + * match of filename with leading '!' + */ + if (result == FNM_NOMATCH && + (match->flags & GIT_ATTR_FNMATCH_NEGATIVE) != 0 && + *path == '!' && + ctxt->strncomp(path + 1, match->pattern, match->length) == 0) + return 1; + if (result == 0) return (match->flags & GIT_ATTR_FNMATCH_NEGATIVE) ? 0 : 1; return -1; diff --git a/tests-clar/attr/file.c b/tests-clar/attr/file.c index 8866fd9bd..4eb1d22fe 100644 --- a/tests-clar/attr/file.c +++ b/tests-clar/attr/file.c @@ -49,7 +49,6 @@ void test_attr_file__match_variants(void) cl_assert(rule); cl_assert_equal_s("pat0", rule->match.pattern); cl_assert(rule->match.length == strlen("pat0")); - cl_assert(rule->match.flags == 0); cl_assert(rule->assigns.length == 1); assign = get_assign(rule,0); cl_assert_equal_s("attr0", assign->name); @@ -59,16 +58,16 @@ void test_attr_file__match_variants(void) rule = get_rule(1); cl_assert_equal_s("pat1", rule->match.pattern); cl_assert(rule->match.length == strlen("pat1")); - cl_assert(rule->match.flags == GIT_ATTR_FNMATCH_NEGATIVE); + cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_NEGATIVE) != 0); rule = get_rule(2); cl_assert_equal_s("pat2", rule->match.pattern); cl_assert(rule->match.length == strlen("pat2")); - cl_assert(rule->match.flags == GIT_ATTR_FNMATCH_DIRECTORY); + cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_DIRECTORY) != 0); rule = get_rule(3); cl_assert_equal_s("pat3dir/pat3file", rule->match.pattern); - cl_assert(rule->match.flags == GIT_ATTR_FNMATCH_FULLPATH); + cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_FULLPATH) != 0); rule = get_rule(4); cl_assert_equal_s("pat4.*", rule->match.pattern); @@ -89,7 +88,6 @@ void test_attr_file__match_variants(void) rule = get_rule(8); cl_assert_equal_s("pat8 with spaces", rule->match.pattern); cl_assert(rule->match.length == strlen("pat8 with spaces")); - cl_assert(rule->match.flags == 0); rule = get_rule(9); cl_assert_equal_s("pat9", rule->match.pattern); -- cgit v1.2.1 From b7b77def931be50777884ddd35a8689df0ecbebd Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 9 Aug 2013 11:20:49 -0700 Subject: Match against file with leading ! was too broad --- src/pathspec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pathspec.c b/src/pathspec.c index 1d7b71a74..d56d03918 100644 --- a/src/pathspec.c +++ b/src/pathspec.c @@ -166,7 +166,8 @@ static int pathspec_match_one( if (result == FNM_NOMATCH && (match->flags & GIT_ATTR_FNMATCH_NEGATIVE) != 0 && *path == '!' && - ctxt->strncomp(path + 1, match->pattern, match->length) == 0) + ctxt->strncomp(path + 1, match->pattern, match->length) == 0 && + (!path[match->length + 1] || path[match->length + 1] == '/')) return 1; if (result == 0) -- cgit v1.2.1 From ba8b8c040744edb9bc832a67646e0126636753bb Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 7 Aug 2013 09:17:20 -0700 Subject: Improve building ignore file lists The routines to push and pop ignore files while traversing a directory had some issues. In particular, setting up the initial list would sometimes push an ignore file before it ought to be applied if the starting path was a directory containing an ignore file. Also, the pop function was not always matching the right part of the path and would fail to pop ignores from the list in some cases. This adds some tests that exercise a particular problematic case and then fixes the problems that I could find related to this. At some point, I'd like to isolate this ignore rule management code and rewrite it, but that's a larger project and right now, I'll opt to just try to fix the broken behaviors. --- src/ignore.c | 30 ++++++++++------ src/ignore.h | 5 +-- src/iterator.c | 2 +- src/path.c | 2 +- tests-clar/status/ignore.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 112 insertions(+), 14 deletions(-) diff --git a/src/ignore.c b/src/ignore.c index 3c23158c2..ca63f0bd9 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -159,17 +159,26 @@ int git_ignore__push_dir(git_ignores *ign, const char *dir) { if (git_buf_joinpath(&ign->dir, ign->dir.ptr, dir) < 0) return -1; - else - return push_ignore_file( - ign->repo, ign, &ign->ign_path, ign->dir.ptr, GIT_IGNORE_FILE); + + return push_ignore_file( + ign->repo, ign, &ign->ign_path, ign->dir.ptr, GIT_IGNORE_FILE); } int git_ignore__pop_dir(git_ignores *ign) { if (ign->ign_path.length > 0) { git_attr_file *file = git_vector_last(&ign->ign_path); - if (git__suffixcmp(ign->dir.ptr, file->key + 2) == 0) + size_t keylen = strlen(file->key); + + while (keylen && file->key[keylen] != '/') + keylen--; + keylen -= 1; /* because we will skip "0#" prefix */ + + if (ign->dir.size > keylen && + !memcmp(ign->dir.ptr + ign->dir.size - keylen, + file->key + 2, keylen)) git_vector_pop(&ign->ign_path); + git_buf_rtruncate_at_char(&ign->dir, '/'); } return 0; @@ -298,12 +307,9 @@ int git_ignore_path_is_ignored( path.full.size = (tail - path.full.ptr); path.is_dir = (tail == end) ? full_is_dir : true; - /* update ignores for new path fragment */ - if (path.basename == path.path) - error = git_ignore__for_path(repo, path.path, &ignores); - else - error = git_ignore__push_dir(&ignores, path.basename); - if (error < 0) + /* initialize ignores the first time through */ + if (path.basename == path.path && + (error = git_ignore__for_path(repo, path.path, &ignores)) < 0) break; /* first process builtins - success means path was found */ @@ -327,6 +333,10 @@ int git_ignore_path_is_ignored( if (tail == end) break; + /* now add this directory to list of ignores */ + if ((error = git_ignore__push_dir(&ignores, path.path)) < 0) + break; + /* reinstate divider in path */ *tail = '/'; while (*tail == '/') tail++; diff --git a/src/ignore.h b/src/ignore.h index cc114b001..851c824bf 100644 --- a/src/ignore.h +++ b/src/ignore.h @@ -24,14 +24,15 @@ */ typedef struct { git_repository *repo; - git_buf dir; + git_buf dir; /* current directory reflected in ign_path */ git_attr_file *ign_internal; git_vector ign_path; git_vector ign_global; int ignore_case; } git_ignores; -extern int git_ignore__for_path(git_repository *repo, const char *path, git_ignores *ign); +extern int git_ignore__for_path( + git_repository *repo, const char *path, git_ignores *ign); extern int git_ignore__push_dir(git_ignores *ign, const char *dir); diff --git a/src/iterator.c b/src/iterator.c index 5917f63fd..bdc98d22b 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -1350,7 +1350,7 @@ int git_iterator_for_workdir_ext( wi->fi.update_entry_cb = workdir_iterator__update_entry; if ((error = iterator__update_ignore_case((git_iterator *)wi, flags)) < 0 || - (error = git_ignore__for_path(repo, "", &wi->ignores)) < 0) + (error = git_ignore__for_path(repo, ".gitignore", &wi->ignores)) < 0) { git_iterator_free((git_iterator *)wi); return error; diff --git a/src/path.c b/src/path.c index 6437979d5..b81675b49 100644 --- a/src/path.c +++ b/src/path.c @@ -603,7 +603,7 @@ int git_path_find_dir(git_buf *dir, const char *path, const char *base) } /* call dirname if this is not a directory */ - if (!error && git_path_isdir(dir->ptr) == false) + if (!error) /* && git_path_isdir(dir->ptr) == false) */ error = git_path_dirname_r(dir, dir->ptr); if (!error) diff --git a/tests-clar/status/ignore.c b/tests-clar/status/ignore.c index 1b41fed1a..acdc8fb58 100644 --- a/tests-clar/status/ignore.c +++ b/tests-clar/status/ignore.c @@ -493,3 +493,90 @@ void test_status_ignore__filenames_with_special_prefixes_do_not_interfere_with_s git_buf_free(&file); } } + +void test_status_ignore__issue_1766_negated_ignores(void) +{ + int ignored = 0; + unsigned int status; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_futils_mkdir_r( + "empty_standard_repo/a", NULL, 0775)); + cl_git_mkfile( + "empty_standard_repo/a/.gitignore", "*\n!.gitignore\n"); + cl_git_mkfile( + "empty_standard_repo/a/ignoreme", "I should be ignored\n"); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "a/.gitignore")); + cl_assert(!ignored); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "a/ignoreme")); + cl_assert(ignored); + + cl_git_pass(git_futils_mkdir_r( + "empty_standard_repo/b", NULL, 0775)); + cl_git_mkfile( + "empty_standard_repo/b/.gitignore", "*\n!.gitignore\n"); + cl_git_mkfile( + "empty_standard_repo/b/ignoreme", "I should be ignored\n"); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "b/.gitignore")); + cl_assert(!ignored); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "b/ignoreme")); + cl_assert(ignored); + + /* shouldn't have changed results from first couple either */ + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "a/.gitignore")); + cl_assert(!ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "a/ignoreme")); + cl_assert(ignored); + + /* status should find the two ignore files and nothing else */ + + cl_git_pass(git_status_file(&status, g_repo, "a/.gitignore")); + cl_assert_equal_i(GIT_STATUS_WT_NEW, (int)status); + + cl_git_pass(git_status_file(&status, g_repo, "a/ignoreme")); + cl_assert_equal_i(GIT_STATUS_IGNORED, (int)status); + + cl_git_pass(git_status_file(&status, g_repo, "b/.gitignore")); + cl_assert_equal_i(GIT_STATUS_WT_NEW, (int)status); + + cl_git_pass(git_status_file(&status, g_repo, "b/ignoreme")); + cl_assert_equal_i(GIT_STATUS_IGNORED, (int)status); + + { + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts; + static const char *paths[] = { + "a/.gitignore", + "a/ignoreme", + "b/.gitignore", + "b/ignoreme", + }; + static const unsigned int statuses[] = { + GIT_STATUS_WT_NEW, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_NEW, + GIT_STATUS_IGNORED, + }; + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = 4; + counts.expected_paths = paths; + counts.expected_statuses = statuses; + + opts.flags = GIT_STATUS_OPT_DEFAULTS; + + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, cb_status__normal, &counts)); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); + } +} + -- cgit v1.2.1 From 3bc3ed80f476bcef24a508cadd45d4c341ef60c7 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 9 Aug 2013 10:06:23 -0700 Subject: Improve and comment git_ignore__pop_dir This just cleans up the improved logic for popping ignore dirs and documents why the complex behavior is needed. --- src/ignore.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/ignore.c b/src/ignore.c index ca63f0bd9..0c35d0431 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -168,15 +168,25 @@ int git_ignore__pop_dir(git_ignores *ign) { if (ign->ign_path.length > 0) { git_attr_file *file = git_vector_last(&ign->ign_path); - size_t keylen = strlen(file->key); - - while (keylen && file->key[keylen] != '/') - keylen--; - keylen -= 1; /* because we will skip "0#" prefix */ - - if (ign->dir.size > keylen && - !memcmp(ign->dir.ptr + ign->dir.size - keylen, - file->key + 2, keylen)) + const char *start, *end, *scan; + size_t keylen; + + /* - ign->dir looks something like "a/b" (or "a/b/c/d") + * - file->key looks something like "0#a/b/.gitignore + * + * We are popping the last directory off ign->dir. We also want to + * remove the file from the vector if the directory part of the key + * matches the ign->dir path. We need to test if the "a/b" part of + * the file key matches the path we are about to pop. + */ + + for (start = end = scan = &file->key[2]; *scan; ++scan) + if (*scan == '/') + end = scan; /* point 'end' to last '/' in key */ + keylen = (end - start) + 1; + + if (ign->dir.size >= keylen && + !memcmp(ign->dir.ptr + ign->dir.size - keylen, start, keylen)) git_vector_pop(&ign->ign_path); git_buf_rtruncate_at_char(&ign->dir, '/'); -- cgit v1.2.1 From aa0af72933424bcf778db29c63c3727b25052c27 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Sat, 10 Aug 2013 14:56:58 -0700 Subject: Fix 64-bit MSVC warnings --- src/win32/utf-conv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/win32/utf-conv.c b/src/win32/utf-conv.c index 623b0517a..d4dbfbab9 100644 --- a/src/win32/utf-conv.c +++ b/src/win32/utf-conv.c @@ -72,10 +72,10 @@ void git__utf8_to_16(wchar_t *dest, size_t length, const char *src) int git__utf8_to_16(wchar_t * dest, size_t dest_size, const char *src) { - return MultiByteToWideChar(CP_UTF8, 0, src, -1, dest, dest_size); + return MultiByteToWideChar(CP_UTF8, 0, src, -1, dest, (int)dest_size); } int git__utf16_to_8(char *dest, size_t dest_size, const wchar_t *src) { - return WideCharToMultiByte(CP_UTF8, 0, src, -1, dest, dest_size, NULL, NULL); + return WideCharToMultiByte(CP_UTF8, 0, src, -1, dest, (int)dest_size, NULL, NULL); } -- cgit v1.2.1 From 0e26fca1daa11a3108960dee3cb555b4c482ad81 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Sat, 10 Aug 2013 15:11:19 -0700 Subject: Make utf-8 source strings unlimited --- src/win32/utf-conv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h index 7290f1d1a..66422e17c 100644 --- a/src/win32/utf-conv.h +++ b/src/win32/utf-conv.h @@ -21,12 +21,12 @@ int git__utf8_to_16(wchar_t * dest, size_t dest_size, const char *src); // dest_size is the size of dest in char's int git__utf16_to_8(char *dest, size_t dest_size, const wchar_t *src); -GIT_INLINE(int) git__win32_path_utf8_to_16(git_win32_path_utf16 dest, const git_win32_path_utf8 src) +GIT_INLINE(int) git__win32_path_utf8_to_16(git_win32_path_utf16 dest, const char *src) { return git__utf8_to_16(dest, GIT_WIN_PATH_UTF16, src); } -GIT_INLINE(int) git__win32_path_utf16_to_8(git_win32_path_utf8 dest, const git_win32_path_utf16 src) +GIT_INLINE(int) git__win32_path_utf16_to_8(git_win32_path_utf8 dest, const wchar_t *src) { return git__utf16_to_8(dest, GIT_WIN_PATH_UTF8, src); } -- cgit v1.2.1 From 5880962d90958bc37c08c21d37c9da480ef20e7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 9 Aug 2013 09:05:19 +0200 Subject: config: introduce _iterator_new() As the name suggests, it iterates over all the entries --- include/git2/config.h | 11 +++++ src/config.c | 123 ++++++++++++++++++++++++++++++++++++----------- src/config_file.c | 2 +- tests-clar/config/read.c | 30 ++++++++++++ 4 files changed, 136 insertions(+), 30 deletions(-) diff --git a/include/git2/config.h b/include/git2/config.h index b338e0c81..aed720fc8 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -452,6 +452,17 @@ GIT_EXTERN(int) git_config_foreach( git_config_foreach_cb callback, void *payload); +/** + * Iterate over all the config variables + * + * Use `git_config_next` to advance the iteration and + * `git_config_iterator_free` when done. + * + * @param out pointer to store the iterator + * @param cfg where to ge the variables from + */ +GIT_EXTERN(int) git_config_iterator_new(git_config_iterator **out, const git_config *cfg); + /** * Perform an operation on each config variable matching a regular expression. * diff --git a/src/config.c b/src/config.c index 42273cde8..f7ea6f795 100644 --- a/src/config.c +++ b/src/config.c @@ -315,6 +315,99 @@ int git_config_refresh(git_config *cfg) * Loop over all the variables */ +typedef struct { + git_config_iterator parent; + git_config_iterator *current; + const git_config *cfg; + size_t i; +} all_iter; + +static int find_next_backend(size_t *out, const git_config *cfg, size_t i) +{ + file_internal *internal; + + for (; i > 0; --i) { + internal = git_vector_get(&cfg->files, i - 1); + if (!internal || !internal->file) + continue; + + *out = i; + return 0; + } + + return -1; +} + +static int all_iter_next(git_config_entry **entry, git_config_iterator *_iter) +{ + all_iter *iter = (all_iter *) _iter; + file_internal *internal; + git_config_backend *backend; + size_t i; + int error = 0; + + if (iter->current != NULL && + (error = iter->current->next(entry, iter->current)) == 0) { + return 0; + } + + if (error < 0 && error != GIT_ITEROVER) + return error; + + do { + if (find_next_backend(&i, iter->cfg, iter->i) < 0) + return GIT_ITEROVER; + + internal = git_vector_get(&iter->cfg->files, i - 1); + backend = internal->file; + iter->i = i - 1; + + if (iter->current) + iter->current->free(iter->current); + + iter->current = NULL; + error = backend->iterator(&iter->current, backend); + if (error == GIT_ENOTFOUND) + continue; + + if (error < 0) + return error; + + return iter->current->next(entry, iter->current); + + } while(1); + + return GIT_ITEROVER; +} + +static void all_iter_free(git_config_iterator *_iter) +{ + all_iter *iter = (all_iter *) _iter; + + if (iter->current) + iter->current->free(iter->current); + + git__free(iter); +} + +int git_config_iterator_new(git_config_iterator **out, const git_config *cfg) +{ + all_iter *iter; + + iter = git__calloc(1, sizeof(all_iter)); + GITERR_CHECK_ALLOC(iter); + + iter->parent.free = all_iter_free; + iter->parent.next = all_iter_next; + + iter->i = cfg->files.length; + iter->cfg = cfg; + + *out = (git_config_iterator *) iter; + + return 0; +} + int git_config_foreach( const git_config *cfg, git_config_foreach_cb cb, void *payload) { @@ -613,30 +706,6 @@ typedef struct { size_t i; } multivar_iter; -static int find_next_backend(size_t *out, const git_config *cfg, size_t i) -{ - file_internal *internal; - - for (; i > 0; --i) { - internal = git_vector_get(&cfg->files, i - 1); - if (!internal || !internal->file) - continue; - - *out = i; - return 0; - } - - return -1; -} - -static int multivar_iter_next_empty(git_config_entry **entry, git_config_iterator *_iter) -{ - GIT_UNUSED(entry); - GIT_UNUSED(_iter); - - return GIT_ITEROVER; -} - static int multivar_iter_next(git_config_entry **entry, git_config_iterator *_iter) { multivar_iter *iter = (multivar_iter *) _iter; @@ -695,7 +764,6 @@ void multivar_iter_free(git_config_iterator *_iter) int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp) { multivar_iter *iter; - size_t i; iter = git__calloc(1, sizeof(multivar_iter)); GITERR_CHECK_ALLOC(iter); @@ -709,10 +777,7 @@ int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, co } iter->parent.free = multivar_iter_free; - if (find_next_backend(&i, cfg, cfg->files.length) < 0) - iter->parent.next = multivar_iter_next_empty; - else - iter->parent.next = multivar_iter_next; + iter->parent.next = multivar_iter_next; iter->i = cfg->files.length; iter->cfg = cfg; diff --git a/src/config_file.c b/src/config_file.c index 38cb9f8b8..4e564a51d 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -279,7 +279,7 @@ static int config_iterator_next( if (err < 0) { it->next_var = NULL; - return -1; + return err; } *entry = var->entry; diff --git a/tests-clar/config/read.c b/tests-clar/config/read.c index a18dca89b..2fb511d9d 100644 --- a/tests-clar/config/read.c +++ b/tests-clar/config/read.c @@ -245,6 +245,36 @@ void test_config_read__foreach(void) git_config_free(cfg); } +void test_config_read__iterator(void) +{ + git_config *cfg; + git_config_iterator *iter; + git_config_entry *entry; + int count, ret; + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), + GIT_CONFIG_LEVEL_SYSTEM, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), + GIT_CONFIG_LEVEL_GLOBAL, 0)); + + count = 0; + cl_git_pass(git_config_iterator_new(&iter, cfg)); + + while ((ret = git_config_next(&entry, iter)) == 0) { + count++; + } + + cl_assert_equal_i(GIT_ITEROVER, ret); + cl_assert_equal_i(7, count); + + count = 3; + cl_git_pass(git_config_iterator_new(&iter, cfg)); + + git_config_iterator_free(iter); + git_config_free(cfg); +} + static int count_cfg_entries(const git_config_entry *entry, void *payload) { int *count = payload; -- cgit v1.2.1 From 54f3a572b4fac419008afa83da56c1b0daee1257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 9 Aug 2013 10:29:11 +0200 Subject: config: introduce a regex-filtering iterator --- include/git2/config.h | 12 ++++++++++ src/config.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ tests-clar/config/read.c | 33 ++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/include/git2/config.h b/include/git2/config.h index aed720fc8..28216467b 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -463,6 +463,18 @@ GIT_EXTERN(int) git_config_foreach( */ GIT_EXTERN(int) git_config_iterator_new(git_config_iterator **out, const git_config *cfg); +/** + * Iterate over all the config variables whose name matches a pattern + * + * Use `git_config_next` to advance the iteration and + * `git_config_iterator_free` when done. + * + * @param out pointer to store the iterator + * @param cfg where to ge the variables from + * @param regexp regular expression to match the names + */ +GIT_EXTERN(int) git_config_iterator_glob_new(git_config_iterator **out, const git_config *cfg, const char *regexp); + /** * Perform an operation on each config variable matching a regular expression. * diff --git a/src/config.c b/src/config.c index f7ea6f795..9d809f8f1 100644 --- a/src/config.c +++ b/src/config.c @@ -319,6 +319,8 @@ typedef struct { git_config_iterator parent; git_config_iterator *current; const git_config *cfg; + regex_t regex; + int has_regex; size_t i; } all_iter; @@ -380,6 +382,27 @@ static int all_iter_next(git_config_entry **entry, git_config_iterator *_iter) return GIT_ITEROVER; } +static int all_iter_glob_next(git_config_entry **entry, git_config_iterator *_iter) +{ + int error; + all_iter *iter = (all_iter *) _iter; + + /* + * We use the "normal" function to grab the next one across + * backends and then apply the regex + */ + while ((error = all_iter_next(entry, _iter)) == 0) { + /* skip non-matching keys if regexp was provided */ + if (regexec(&iter->regex, (*entry)->name, 0, NULL, 0) != 0) + continue; + + /* and simply return if we like the entry's name */ + return 0; + } + + return error; +} + static void all_iter_free(git_config_iterator *_iter) { all_iter *iter = (all_iter *) _iter; @@ -390,6 +413,14 @@ static void all_iter_free(git_config_iterator *_iter) git__free(iter); } +static void all_iter_glob_free(git_config_iterator *_iter) +{ + all_iter *iter = (all_iter *) _iter; + + regfree(&iter->regex); + all_iter_free(_iter); +} + int git_config_iterator_new(git_config_iterator **out, const git_config *cfg) { all_iter *iter; @@ -408,6 +439,36 @@ int git_config_iterator_new(git_config_iterator **out, const git_config *cfg) return 0; } +int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cfg, const char *regexp) +{ + all_iter *iter; + int result; + + iter = git__calloc(1, sizeof(all_iter)); + GITERR_CHECK_ALLOC(iter); + + if (regexp != NULL) { + if ((result = regcomp(&iter->regex, regexp, REG_EXTENDED)) < 0) { + giterr_set_regex(&iter->regex, result); + regfree(&iter->regex); + return -1; + } + + iter->parent.next = all_iter_glob_next; + } else { + iter->parent.next = all_iter_next; + } + + iter->parent.free = all_iter_glob_free; + + iter->i = cfg->files.length; + iter->cfg = cfg; + + *out = (git_config_iterator *) iter; + + return 0; +} + int git_config_foreach( const git_config *cfg, git_config_foreach_cb cb, void *payload) { diff --git a/tests-clar/config/read.c b/tests-clar/config/read.c index 2fb511d9d..395f1cfdb 100644 --- a/tests-clar/config/read.c +++ b/tests-clar/config/read.c @@ -265,6 +265,7 @@ void test_config_read__iterator(void) count++; } + git_config_iterator_free(iter); cl_assert_equal_i(GIT_ITEROVER, ret); cl_assert_equal_i(7, count); @@ -318,6 +319,38 @@ void test_config_read__foreach_match(void) git_config_free(cfg); } +static void check_glob_iter(git_config *cfg, const char *regexp, int expected) +{ + git_config_iterator *iter; + git_config_entry *entry; + int count, error; + + cl_git_pass(git_config_iterator_glob_new(&iter, cfg, regexp)); + + count = 0; + while ((error = git_config_next(&entry, iter)) == 0) + count++; + + cl_assert_equal_i(GIT_ITEROVER, error); + cl_assert_equal_i(expected, count); + git_config_iterator_free(iter); +} + +void test_config_read__iterator_glob(void) +{ + git_config *cfg; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9"))); + + check_glob_iter(cfg, "core.*", 3); + check_glob_iter(cfg, "remote\\.ab.*", 2); + check_glob_iter(cfg, ".*url$", 2); + check_glob_iter(cfg, ".*dummy.*", 2); + check_glob_iter(cfg, ".*nomatch.*", 0); + + git_config_free(cfg); +} + void test_config_read__whitespace_not_required_around_assignment(void) { git_config *cfg; -- cgit v1.2.1 From d8488b981c1410dd2de2f9fe99764bdae33ca607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 9 Aug 2013 10:37:35 +0200 Subject: config: implement _foreach and _foreach_match on top of the iterator directly Use a glob iterator instead of going through git_config_backend_foreach_match. This function is left as it's exposed in the API. --- src/config.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/config.c b/src/config.c index 9d809f8f1..3881d73dd 100644 --- a/src/config.c +++ b/src/config.c @@ -455,12 +455,12 @@ int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cf } iter->parent.next = all_iter_glob_next; + iter->parent.free = all_iter_glob_free; } else { iter->parent.next = all_iter_next; + iter->parent.free = all_iter_free; } - iter->parent.free = all_iter_glob_free; - iter->i = cfg->files.length; iter->cfg = cfg; @@ -527,18 +527,27 @@ int git_config_foreach_match( git_config_foreach_cb cb, void *payload) { - int ret = 0; - size_t i; - file_internal *internal; - git_config_backend *file; + int error; + git_config_iterator *iter; + git_config_entry *entry; - for (i = 0; i < cfg->files.length && ret == 0; ++i) { - internal = git_vector_get(&cfg->files, i); - file = internal->file; - ret = git_config_backend_foreach_match(file, regexp, cb, payload); + if ((error = git_config_iterator_glob_new(&iter, cfg, regexp)) < 0) + return error; + + while ((error = git_config_next(&entry, iter)) == 0) { + if(cb(entry, payload)) { + giterr_clear(); + error = GIT_EUSER; + break; + } } - return ret; + git_config_iterator_free(iter); + + if (error == GIT_ITEROVER) + error = 0; + + return error; } /************** -- cgit v1.2.1 From d8289b9fb416cfe4f83eeb38fe324c077bada3e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 9 Aug 2013 11:03:13 +0200 Subject: config: handle empty backends when iterating --- src/config.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 3881d73dd..061765ac0 100644 --- a/src/config.c +++ b/src/config.c @@ -375,7 +375,12 @@ static int all_iter_next(git_config_entry **entry, git_config_iterator *_iter) if (error < 0) return error; - return iter->current->next(entry, iter->current); + error = iter->current->next(entry, iter->current); + /* If this backend is empty, then keep going */ + if (error == GIT_ITEROVER) + continue; + + return error; } while(1); -- cgit v1.2.1 From 86c02614608eb7e9e78c09cdec69aeba689edae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 9 Aug 2013 11:05:02 +0200 Subject: config: deduplicate iterator creation When the glob iterator is passed NULL regexp, call the non-globbing iterator so we don't have to special-case which functions to call. --- src/config.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/config.c b/src/config.c index 061765ac0..ae4e4816a 100644 --- a/src/config.c +++ b/src/config.c @@ -449,23 +449,20 @@ int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cf all_iter *iter; int result; + if (regexp == NULL) + return git_config_iterator_new(out, cfg); + iter = git__calloc(1, sizeof(all_iter)); GITERR_CHECK_ALLOC(iter); - if (regexp != NULL) { - if ((result = regcomp(&iter->regex, regexp, REG_EXTENDED)) < 0) { - giterr_set_regex(&iter->regex, result); - regfree(&iter->regex); - return -1; - } - - iter->parent.next = all_iter_glob_next; - iter->parent.free = all_iter_glob_free; - } else { - iter->parent.next = all_iter_next; - iter->parent.free = all_iter_free; + if ((result = regcomp(&iter->regex, regexp, REG_EXTENDED)) < 0) { + giterr_set_regex(&iter->regex, result); + regfree(&iter->regex); + return -1; } + iter->parent.next = all_iter_glob_next; + iter->parent.free = all_iter_glob_free; iter->i = cfg->files.length; iter->cfg = cfg; -- cgit v1.2.1 From 43e5dda70249ede020a57f3888356a0dcb96da48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 12 Aug 2013 11:21:57 +0200 Subject: config: get rid of a useless asignment --- src/config_file.c | 4 +--- src/strmap.c | 2 -- src/strmap.h | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 4e564a51d..7c22be424 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -268,12 +268,10 @@ static int config_iterator_next( diskfile_backend *b = (diskfile_backend *) it->parent.backend; int err = 0; cvar_t * var; - const char* key; if (it->next_var == NULL) { - err = git_strmap_next(&key, (void**) &var, &(it->iter), b->values); + err = git_strmap_next((void**) &var, &(it->iter), b->values); } else { - key = it->next_var->entry->name; var = it->next_var; } diff --git a/src/strmap.c b/src/strmap.c index 1b07359d1..b26a13d1f 100644 --- a/src/strmap.c +++ b/src/strmap.c @@ -8,7 +8,6 @@ #include "strmap.h" int git_strmap_next( - const char **key, void **data, git_strmap_iter* iter, git_strmap *map) @@ -22,7 +21,6 @@ int git_strmap_next( continue; } - *key = git_strmap_key(map, *iter); *data = git_strmap_value_at(map, *iter); ++(*iter); diff --git a/src/strmap.h b/src/strmap.h index cb079b500..8276ab468 100644 --- a/src/strmap.h +++ b/src/strmap.h @@ -68,7 +68,6 @@ typedef khiter_t git_strmap_iter; #define git_strmap_end kh_end int git_strmap_next( - const char **key, void **data, git_strmap_iter* iter, git_strmap *map); -- cgit v1.2.1 From e54cfb9b544eeac2924f45fc7752c2a7be709a03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 12 Aug 2013 11:50:27 +0200 Subject: odb: free object data when id is ambiguous By the time we recognise this as an ambiguous id, the object's data has been loaded into memory. Free it when returning EABMIGUOUS. --- src/odb.c | 4 +++- tests-clar/odb/mixed.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/odb.c b/src/odb.c index 23eb4e12e..6969cf772 100644 --- a/src/odb.c +++ b/src/odb.c @@ -786,8 +786,10 @@ attempt_lookup: git__free(data); data = raw.data; - if (found && git_oid__cmp(&full_oid, &found_full_oid)) + if (found && git_oid__cmp(&full_oid, &found_full_oid)) { + git__free(raw.data); return git_odb__error_ambiguous("multiple matches for prefix"); + } found_full_oid = full_oid; found = true; diff --git a/tests-clar/odb/mixed.c b/tests-clar/odb/mixed.c index dd4587831..51970ceec 100644 --- a/tests-clar/odb/mixed.c +++ b/tests-clar/odb/mixed.c @@ -22,6 +22,7 @@ void test_odb_mixed__dup_oid(void) { cl_git_pass(git_oid_fromstr(&oid, hex)); cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, GIT_OID_HEXSZ)); + git_odb_object_free(obj); cl_git_pass(git_oid_fromstrn(&oid, short_hex, sizeof(short_hex) - 1)); cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, sizeof(short_hex) - 1)); git_odb_object_free(obj); -- cgit v1.2.1 From 7affc2f7dec48dc886e9838b102bdd42d06b1d2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sun, 11 Aug 2013 23:30:47 +0200 Subject: Include username in each credential type Key-based authentication also needs an username, so include it in each one. Also stop assuming a default username of "git" in the ssh transport which has no business making such a decision. --- include/git2/transport.h | 16 +++++++++++++++- src/transports/cred.c | 39 +++++++++++++++++++++++++++++++++++++++ src/transports/ssh.c | 22 ++++++++++++---------- 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/include/git2/transport.h b/include/git2/transport.h index 1cc200eb4..e61b10423 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -59,6 +59,7 @@ typedef int (*git_cred_sign_callback)(void *, ...); /* A ssh key file and passphrase */ typedef struct git_cred_ssh_keyfile_passphrase { git_cred parent; + char *username; char *publickey; char *privatekey; char *passphrase; @@ -67,12 +68,21 @@ typedef struct git_cred_ssh_keyfile_passphrase { /* A ssh public key and authentication callback */ typedef struct git_cred_ssh_publickey { git_cred parent; + char *username; char *publickey; - size_t publickey_len; + size_t publickey_len; void *sign_callback; void *sign_data; } git_cred_ssh_publickey; +/** + * Check whether a credential object contains username information. + * + * @param cred object to check + * @return 1 if the credential object has non-NULL username, 0 otherwise + */ +GIT_EXTERN(int) git_cred_has_username(git_cred *cred); + /** * Creates a new plain-text username and password credential object. * The supplied credential parameter will be internally duplicated. @@ -92,6 +102,7 @@ GIT_EXTERN(int) git_cred_userpass_plaintext_new( * The supplied credential parameter will be internally duplicated. * * @param out The newly created credential object. + * @param username username to use to authenticate * @param publickey The path to the public key of the credential. * @param privatekey The path to the private key of the credential. * @param passphrase The passphrase of the credential. @@ -99,6 +110,7 @@ GIT_EXTERN(int) git_cred_userpass_plaintext_new( */ GIT_EXTERN(int) git_cred_ssh_keyfile_passphrase_new( git_cred **out, + const char *username, const char *publickey, const char *privatekey, const char *passphrase); @@ -108,6 +120,7 @@ GIT_EXTERN(int) git_cred_ssh_keyfile_passphrase_new( * The supplied credential parameter will be internally duplicated. * * @param out The newly created credential object. + * @param username username to use to authenticate * @param publickey The bytes of the public key. * @param publickey_len The length of the public key in bytes. * @param sign_fn The callback method for authenticating. @@ -116,6 +129,7 @@ GIT_EXTERN(int) git_cred_ssh_keyfile_passphrase_new( */ GIT_EXTERN(int) git_cred_ssh_publickey_new( git_cred **out, + const char *username, const char *publickey, size_t publickey_len, git_cred_sign_callback sign_fn, diff --git a/src/transports/cred.c b/src/transports/cred.c index a6727e902..35aaf4f91 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -9,6 +9,31 @@ #include "smart.h" #include "git2/cred_helpers.h" +int git_cred_has_username(git_cred *cred) +{ + int ret = 0; + + switch (cred->credtype) { + case GIT_CREDTYPE_USERPASS_PLAINTEXT: { + git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; + ret = !!c->username; + break; + } + case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: { + git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred; + ret = !!c->username; + break; + } + case GIT_CREDTYPE_SSH_PUBLICKEY: { + git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred; + ret = !!c->username; + break; + } + } + + return ret; +} + static void plaintext_free(struct git_cred *cred) { git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; @@ -64,6 +89,7 @@ static void ssh_keyfile_passphrase_free(struct git_cred *cred) git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred; + git__free(c->username); git__free(c->publickey); git__free(c->privatekey); @@ -82,6 +108,7 @@ static void ssh_publickey_free(struct git_cred *cred) { git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred; + git__free(c->username); git__free(c->publickey); git__memzero(c, sizeof(*c)); @@ -90,6 +117,7 @@ static void ssh_publickey_free(struct git_cred *cred) int git_cred_ssh_keyfile_passphrase_new( git_cred **cred, + const char *username, const char *publickey, const char *privatekey, const char *passphrase) @@ -104,6 +132,11 @@ int git_cred_ssh_keyfile_passphrase_new( c->parent.credtype = GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE; c->parent.free = ssh_keyfile_passphrase_free; + if (username) { + c->username = git__strdup(username); + GITERR_CHECK_ALLOC(c->username); + } + c->privatekey = git__strdup(privatekey); GITERR_CHECK_ALLOC(c->privatekey); @@ -123,6 +156,7 @@ int git_cred_ssh_keyfile_passphrase_new( int git_cred_ssh_publickey_new( git_cred **cred, + const char *username, const char *publickey, size_t publickey_len, git_cred_sign_callback sign_callback, @@ -138,6 +172,11 @@ int git_cred_ssh_publickey_new( c->parent.credtype = GIT_CREDTYPE_SSH_PUBLICKEY; c->parent.free = ssh_publickey_free; + if (username) { + c->username = git__strdup(username); + GITERR_CHECK_ALLOC(c->username); + } + if (publickey_len > 0) { c->publickey = git__malloc(publickey_len); GITERR_CHECK_ALLOC(c->publickey); diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 7fb53bc3c..1258a8e68 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -17,7 +17,6 @@ #define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport) static const char prefix_ssh[] = "ssh://"; -static const char default_user[] = "git"; static const char cmd_uploadpack[] = "git-upload-pack"; static const char cmd_receivepack[] = "git-receive-pack"; @@ -214,11 +213,10 @@ static int git_ssh_extract_url_parts( if (at) { start = at+1; *username = git__substrdup(url, at - url); + GITERR_CHECK_ALLOC(*username); } else { - start = url; - *username = git__strdup(default_user); + *username = NULL; } - GITERR_CHECK_ALLOC(*username); *host = git__substrdup(start, colon - start); GITERR_CHECK_ALLOC(*host); @@ -237,19 +235,23 @@ static int _git_ssh_authenticate_session( switch (cred->credtype) { case GIT_CREDTYPE_USERPASS_PLAINTEXT: { git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; - rc = libssh2_userauth_password(session, c->username, c->password); + user = c->username ? c->username : user; + rc = libssh2_userauth_password(session, user, c->password); break; } case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: { git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred; + user = c->username ? c->username : user; rc = libssh2_userauth_publickey_fromfile( - session, user, c->publickey, c->privatekey, c->passphrase); + session, c->username, c->publickey, c->privatekey, c->passphrase); break; } case GIT_CREDTYPE_SSH_PUBLICKEY: { git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred; + + user = c->username ? c->username : user; rc = libssh2_userauth_publickey( - session, user, (const unsigned char *)c->publickey, + session, c->username, (const unsigned char *)c->publickey, c->publickey_len, c->sign_callback, &c->sign_data); break; } @@ -351,9 +353,9 @@ static int _git_ssh_setup_conn( } assert(t->cred); - if (!user) { - user = git__strdup(default_user); - GITERR_CHECK_ALLOC(user); + if (!user && !git_cred_has_username(t->cred)) { + giterr_set_str(GITERR_NET, "Cannot authenticate without a username"); + goto on_error; } if (_git_ssh_session_create(&session, s->socket) < 0) -- cgit v1.2.1 From d10de8bd8dff0ebbb7d6684f5a7b9d3e1ec04667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 12 Aug 2013 12:07:33 +0200 Subject: CMake: finding libssh2 should be idempotent With the current code, running 'cmake .' in an already-configured directory causes the removal of ssh flags passed to the compiler, making it impossible to build with ssh support but by removing CMake's cache. Remove the check for LIBSSH2_LIBRARY and let CMake do the right thing wrt finding the library. --- CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 53f568ed3..1500a3a68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,15 +148,14 @@ ELSE() FILE(GLOB SRC_ZLIB deps/zlib/*.c deps/zlib/*.h) ENDIF() -IF(NOT LIBSSH2_LIBRARY) - FIND_PACKAGE(LIBSSH2 QUIET) -ENDIF() +FIND_PACKAGE(LIBSSH2 QUIET) IF (LIBSSH2_FOUND) ADD_DEFINITIONS(-DGIT_SSH) INCLUDE_DIRECTORIES(${LIBSSH2_INCLUDE_DIR}) SET(SSH_LIBRARIES ${LIBSSH2_LIBRARIES}) ENDIF() + # Platform specific compilation flags IF (MSVC) -- cgit v1.2.1 From 423e3b0c4838537608bede2c166abd3b589dd23c Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 12 Aug 2013 11:02:53 -0700 Subject: Update to clar 7bf638b80 --- tests-clar/clar.c | 2 +- tests-clar/clar/sandbox.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests-clar/clar.c b/tests-clar/clar.c index fb10dd397..585af8a74 100644 --- a/tests-clar/clar.c +++ b/tests-clar/clar.c @@ -36,7 +36,7 @@ # define strncpy(to, from, to_size) strncpy_s(to, to_size, from, _TRUNCATE) # define W_OK 02 # define S_ISDIR(x) ((x & _S_IFDIR) != 0) -# define snprint_eq(buf,sz,fmt,a,b) _snprintf_s(buf,sz,_TRUNCATE,fmt,a,b) +# define snprint_eq(buf,sz,fmt,...) _snprintf_s(buf,sz,_TRUNCATE,fmt,__VA_ARGS__) # else # define snprint_eq snprintf # endif diff --git a/tests-clar/clar/sandbox.h b/tests-clar/clar/sandbox.h index 5622bfab7..1ca6fcae8 100644 --- a/tests-clar/clar/sandbox.h +++ b/tests-clar/clar/sandbox.h @@ -45,7 +45,7 @@ find_tmp_path(char *buffer, size_t length) #else DWORD env_len; - if ((env_len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length)) > 0 && + if ((env_len = GetEnvironmentVariable("CLAR_TMP", buffer, length)) > 0 && env_len < length) return 0; -- cgit v1.2.1 From abf3732728d0af42ed7217c7148509c8aa30a7e5 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 13 Aug 2013 09:15:39 +0200 Subject: windows: Path conversion with better semantics --- src/fileops.c | 4 ++-- src/path.c | 4 ++-- src/transports/winhttp.c | 4 ++-- src/win32/dir.c | 10 ++++----- src/win32/dir.h | 2 +- src/win32/findfile.c | 12 +++++------ src/win32/posix_w32.c | 54 +++++++++++++++++++++++------------------------ src/win32/utf-conv.h | 7 +++--- tests-clar/clar_libgit2.c | 22 +++++++++---------- 9 files changed, 59 insertions(+), 60 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index d62158db7..cf77ad164 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -58,9 +58,9 @@ int git_futils_creat_locked(const char *path, const mode_t mode) int fd; #ifdef GIT_WIN32 - git_win32_path_utf16 buf; + git_win32_path buf; - git__win32_path_utf8_to_16(buf, path); + git__win32_path_from_c(buf, path); fd = _wopen(buf, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY | O_CLOEXEC, mode); #else diff --git a/src/path.c b/src/path.c index d0cecc070..cf9a3776a 100644 --- a/src/path.c +++ b/src/path.c @@ -486,14 +486,14 @@ bool git_path_is_empty_dir(const char *path) { git_buf pathbuf = GIT_BUF_INIT; HANDLE hFind = INVALID_HANDLE_VALUE; - git_win32_path_utf16 wbuf; + git_win32_path wbuf; WIN32_FIND_DATAW ffd; bool retval = true; if (!git_path_isdir(path)) return false; git_buf_printf(&pathbuf, "%s\\*", path); - git__win32_path_utf8_to_16(wbuf, git_buf_cstr(&pathbuf)); + git__win32_path_from_c(wbuf, git_buf_cstr(&pathbuf)); hFind = FindFirstFileW(wbuf, &ffd); if (INVALID_HANDLE_VALUE == hFind) { diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 5c55c10f1..6f182c94c 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -893,7 +893,7 @@ static int winhttp_connect( const char *url) { wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")"; - git_win32_path_utf16 host; + git_win32_path host; int32_t port; const char *default_port = "80"; int ret; @@ -920,7 +920,7 @@ static int winhttp_connect( return -1; /* Prepare host */ - git__win32_path_utf8_to_16(host, t->host); + git__win32_path_from_c(host, t->host); /* Establish session */ t->session = WinHttpOpen( diff --git a/src/win32/dir.c b/src/win32/dir.c index 85f793d62..f75b8d57e 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -26,7 +26,7 @@ static int init_filter(char *filter, size_t n, const char *dir) git__DIR *git__opendir(const char *dir) { char filter[GIT_WIN_PATH_UTF8]; - git_win32_path_utf16 filter_w; + git_win32_path filter_w; git__DIR *new = NULL; if (!dir || !init_filter(filter, sizeof(filter), dir)) @@ -40,7 +40,7 @@ git__DIR *git__opendir(const char *dir) if (!new->dir) goto fail; - git__win32_path_utf8_to_16(filter_w, filter); + git__win32_path_from_c(filter_w, filter); new->h = FindFirstFileW(filter_w, &new->f); if (new->h == INVALID_HANDLE_VALUE) { @@ -80,7 +80,7 @@ int git__readdir_ext( if (wcslen(d->f.cFileName) >= sizeof(entry->d_name)) return -1; - git__win32_path_utf16_to_8(entry->d_name, d->f.cFileName); + git__win32_path_from_c(entry->d_name, d->f.cFileName); entry->d_ino = 0; *result = entry; @@ -102,7 +102,7 @@ struct git__dirent *git__readdir(git__DIR *d) void git__rewinddir(git__DIR *d) { char filter[GIT_WIN_PATH_UTF8]; - git_win32_path_utf16 filter_w; + git_win32_path filter_w; if (!d) return; @@ -116,7 +116,7 @@ void git__rewinddir(git__DIR *d) if (!init_filter(filter, sizeof(filter), d->dir)) return; - git__win32_path_utf8_to_16(filter_w, filter); + git__win32_path_from_c(filter_w, filter); d->h = FindFirstFileW(filter_w, &d->f); if (d->h == INVALID_HANDLE_VALUE) diff --git a/src/win32/dir.h b/src/win32/dir.h index a3e154972..3875ab159 100644 --- a/src/win32/dir.h +++ b/src/win32/dir.h @@ -11,7 +11,7 @@ struct git__dirent { int d_ino; - char d_name[260*4+1]; + char d_name[GIT_WIN_PATH_UTF8]; }; typedef struct { diff --git a/src/win32/findfile.c b/src/win32/findfile.c index 64b9bb537..a1c11fcfb 100644 --- a/src/win32/findfile.c +++ b/src/win32/findfile.c @@ -23,11 +23,11 @@ int git_win32__expand_path(struct git_win32__path *s_root, const wchar_t *templ) return s_root->len ? 0 : -1; } -static int win32_path_utf16_to_8(git_buf *path_utf8, const wchar_t *path_utf16) +static int win32_path_to_8(git_buf *path_utf8, const wchar_t *path) { char temp_utf8[GIT_PATH_MAX]; - git__utf16_to_8(temp_utf8, GIT_PATH_MAX, path_utf16); + git__utf16_to_8(temp_utf8, GIT_PATH_MAX, path); git_path_mkposix(temp_utf8); return git_buf_sets(path_utf8, temp_utf8); @@ -61,7 +61,7 @@ int git_win32__find_file( return GIT_ENOTFOUND; } - win32_path_utf16_to_8(path, file_utf16); + win32_path_to_8(path, file_utf16); git__free(file_utf16); return 0; @@ -113,7 +113,7 @@ static int win32_find_git_in_path(git_buf *buf, const wchar_t *gitexe) /* replace "bin\\" or "cmd\\" with "etc\\" */ wcscpy(&root.path[root.len - 4], L"etc\\"); - win32_path_utf16_to_8(buf, root.path); + win32_path_to_8(buf, root.path); return 0; } } @@ -146,7 +146,7 @@ static int win32_find_git_in_registry( wcscat(path16.path, L"etc\\"); path16.len += 4; - win32_path_utf16_to_8(buf, path16.path); + win32_path_to_8(buf, path16.path); } RegCloseKey(hKey); @@ -168,7 +168,7 @@ static int win32_find_existing_dirs( path16.path[0] != L'%' && !_waccess(path16.path, F_OK)) { - win32_path_utf16_to_8(&buf, path16.path); + win32_path_to_8(&buf, path16.path); if (buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index d9a68f284..437ded284 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -16,8 +16,8 @@ int p_unlink(const char *path) { - git_win32_path_utf16 buf; - git__win32_path_utf8_to_16(buf, path); + git_win32_path buf; + git__win32_path_from_c(buf, path); _wchmod(buf, 0666); return _wunlink(buf); } @@ -59,11 +59,11 @@ static int do_lstat( const char *file_name, struct stat *buf, int posix_enotdir) { WIN32_FILE_ATTRIBUTE_DATA fdata; - git_win32_path_utf16 fbuf; + git_win32_path fbuf; wchar_t lastch; int flen; - flen = git__win32_path_utf8_to_16(fbuf, file_name); + flen = git__win32_path_from_c(fbuf, file_name); /* truncate trailing slashes */ for (; flen > 0; --flen) { @@ -166,7 +166,7 @@ int p_readlink(const char *link, char *target, size_t target_len) static fpath_func pGetFinalPath = NULL; HANDLE hFile; DWORD dwRet; - git_win32_path_utf16 link_w; + git_win32_path link_w; wchar_t* target_w; int error = 0; @@ -189,7 +189,7 @@ int p_readlink(const char *link, char *target, size_t target_len) } } - git__win32_path_utf8_to_16(link_w, link); + git__win32_path_from_c(link_w, link); hFile = CreateFileW(link_w, // file to open GENERIC_READ, // open for reading @@ -255,10 +255,10 @@ int p_symlink(const char *old, const char *new) int p_open(const char *path, int flags, ...) { - git_win32_path_utf16 buf; + git_win32_path buf; mode_t mode = 0; - git__win32_path_utf8_to_16(buf, path); + git__win32_path_from_c(buf, path); if (flags & O_CREAT) { va_list arg_list; @@ -273,8 +273,8 @@ int p_open(const char *path, int flags, ...) int p_creat(const char *path, mode_t mode) { - git_win32_path_utf16 buf; - git__win32_path_utf8_to_16(buf, path); + git_win32_path buf; + git__win32_path_from_c(buf, path); return _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode); } @@ -316,23 +316,23 @@ int p_stat(const char* path, struct stat* buf) int p_chdir(const char* path) { - git_win32_path_utf16 buf; - git__win32_path_utf8_to_16(buf, path); + git_win32_path buf; + git__win32_path_from_c(buf, path); return _wchdir(buf); } int p_chmod(const char* path, mode_t mode) { - git_win32_path_utf16 buf; - git__win32_path_utf8_to_16(buf, path); + git_win32_path buf; + git__win32_path_from_c(buf, path); return _wchmod(buf, mode); } int p_rmdir(const char* path) { int error; - git_win32_path_utf16 buf; - git__win32_path_utf8_to_16(buf, path); + git_win32_path buf; + git__win32_path_from_c(buf, path); error = _wrmdir(buf); @@ -348,18 +348,18 @@ int p_rmdir(const char* path) int p_hide_directory__w32(const char *path) { - git_win32_path_utf16 buf; - git__win32_path_utf8_to_16(buf, path); + git_win32_path buf; + git__win32_path_from_c(buf, path); return (SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0) ? 0 : -1; } char *p_realpath(const char *orig_path, char *buffer) { int ret; - git_win32_path_utf16 orig_path_w; - git_win32_path_utf16 buffer_w; + git_win32_path orig_path_w; + git_win32_path buffer_w; - git__win32_path_utf8_to_16(orig_path_w, orig_path); + git__win32_path_from_c(orig_path_w, orig_path); /* Implicitly use GetCurrentDirectory which can be a threading issue */ ret = GetFullPathNameW(orig_path_w, GIT_WIN_PATH_UTF16, buffer_w, NULL); @@ -449,18 +449,18 @@ int p_setenv(const char* name, const char* value, int overwrite) int p_access(const char* path, mode_t mode) { - git_win32_path_utf16 buf; - git__win32_path_utf8_to_16(buf, path); + git_win32_path buf; + git__win32_path_from_c(buf, path); return _waccess(buf, mode); } int p_rename(const char *from, const char *to) { - git_win32_path_utf16 wfrom; - git_win32_path_utf16 wto; + git_win32_path wfrom; + git_win32_path wto; - git__win32_path_utf8_to_16(wfrom, from); - git__win32_path_utf8_to_16(wto, to); + git__win32_path_from_c(wfrom, from); + git__win32_path_from_c(wto, to); return MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? 0 : -1; } diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h index 66422e17c..3cfb3514e 100644 --- a/src/win32/utf-conv.h +++ b/src/win32/utf-conv.h @@ -13,20 +13,19 @@ #define GIT_WIN_PATH_UTF16 (260 + 1) #define GIT_WIN_PATH_UTF8 (260 * 4 + 1) -typedef wchar_t git_win32_path_utf16[GIT_WIN_PATH_UTF16]; -typedef char git_win32_path_utf8[GIT_WIN_PATH_UTF8]; +typedef wchar_t git_win32_path[GIT_WIN_PATH_UTF16]; // dest_size is the size of dest in wchar_t's int git__utf8_to_16(wchar_t * dest, size_t dest_size, const char *src); // dest_size is the size of dest in char's int git__utf16_to_8(char *dest, size_t dest_size, const wchar_t *src); -GIT_INLINE(int) git__win32_path_utf8_to_16(git_win32_path_utf16 dest, const char *src) +GIT_INLINE(int) git__win32_path_from_c(git_win32_path dest, const char *src) { return git__utf8_to_16(dest, GIT_WIN_PATH_UTF16, src); } -GIT_INLINE(int) git__win32_path_utf16_to_8(git_win32_path_utf8 dest, const wchar_t *src) +GIT_INLINE(int) git__win32_path_to_c(char *dest, const git_win32_path *src) { return git__utf16_to_8(dest, GIT_WIN_PATH_UTF8, src); } diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 6c741accd..9e0fbfbac 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -56,12 +56,12 @@ void cl_git_rewritefile(const char *filename, const char *new_content) char *cl_getenv(const char *name) { - git_win32_path_utf16 name_utf16; + git_win32_path name_utf16; DWORD alloc_len; wchar_t *value_utf16; char *value_utf8; - git__win32_path_utf8_to_16(name_utf16, name); + git__win32_path_from_c(name_utf16, name); alloc_len = GetEnvironmentVariableW(name_utf16, NULL, 0); if (alloc_len <= 0) return NULL; @@ -72,7 +72,7 @@ char *cl_getenv(const char *name) GetEnvironmentVariableW(name_utf16, value_utf16, alloc_len); cl_assert(value_utf8 = git__malloc(alloc_len)); - git__win32_path_utf16_to_8(value_utf8, value_utf16); + git__utf16_to_8(value_utf8, alloc_len, value_utf16); git__free(value_utf16); @@ -81,13 +81,13 @@ char *cl_getenv(const char *name) int cl_setenv(const char *name, const char *value) { - git_win32_path_utf16 name_utf16; - git_win32_path_utf16 value_utf16; + git_win32_path name_utf16; + git_win32_path value_utf16; - git__win32_path_utf8_to_16(name_utf16, name); + git__win32_path_from_c(name_utf16, name); if (value) { - git__win32_path_utf8_to_16(value_utf16, value); + git__win32_path_from_c(value_utf16, value); cl_assert(SetEnvironmentVariableW(name_utf16, value_utf16)); } else { /* Windows XP returns 0 (failed) when passing NULL for lpValue when @@ -107,12 +107,12 @@ int cl_setenv(const char *name, const char *value) * the source is a directory, a child of the source). */ int cl_rename(const char *source, const char *dest) { - git_win32_path_utf16 source_utf16; - git_win32_path_utf16 dest_utf16; + git_win32_path source_utf16; + git_win32_path dest_utf16; unsigned retries = 1; - git__win32_path_utf8_to_16(source_utf16, source); - git__win32_path_utf8_to_16(dest_utf16, dest); + git__win32_path_from_c(source_utf16, source); + git__win32_path_from_c(dest_utf16, dest); while (!MoveFileW(source_utf16, dest_utf16)) { /* Only retry if the error is ERROR_ACCESS_DENIED; -- cgit v1.2.1 From 53d712dcb9d74979a3c678336c97e2f7564aadbe Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 13 Aug 2013 09:31:03 +0200 Subject: windows: Missing renames. --- src/win32/posix.h | 4 ++-- src/win32/utf-conv.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/win32/posix.h b/src/win32/posix.h index 7803c9c84..0d5effe08 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -20,9 +20,9 @@ GIT_INLINE(int) p_link(const char *old, const char *new) GIT_INLINE(int) p_mkdir(const char *path, mode_t mode) { - git_win32_path_utf16 buf; + git_win32_path buf; GIT_UNUSED(mode); - git__win32_path_utf8_to_16(buf, path); + git__win32_path_from_c(buf, path); return _wmkdir(buf); } diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h index 3cfb3514e..967db859e 100644 --- a/src/win32/utf-conv.h +++ b/src/win32/utf-conv.h @@ -25,7 +25,7 @@ GIT_INLINE(int) git__win32_path_from_c(git_win32_path dest, const char *src) return git__utf8_to_16(dest, GIT_WIN_PATH_UTF16, src); } -GIT_INLINE(int) git__win32_path_to_c(char *dest, const git_win32_path *src) +GIT_INLINE(int) git__win32_path_to_c(char *dest, const git_win32_path src) { return git__utf16_to_8(dest, GIT_WIN_PATH_UTF8, src); } -- cgit v1.2.1 From 345b6307be76e6f48e255f698d057c7ac5f9679d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 13 Aug 2013 09:35:07 +0200 Subject: windows: Require order --- src/path.c | 1 - src/win32/dir.c | 3 +-- src/win32/posix.h | 1 + 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/path.c b/src/path.c index cf9a3776a..c9716ef6a 100644 --- a/src/path.c +++ b/src/path.c @@ -8,7 +8,6 @@ #include "path.h" #include "posix.h" #ifdef GIT_WIN32 -#include "win32/dir.h" #include "win32/posix.h" #else #include diff --git a/src/win32/dir.c b/src/win32/dir.c index f75b8d57e..cd3c7de51 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -5,8 +5,7 @@ * a Linking Exception. For full terms see the included COPYING file. */ #define GIT__WIN32_NO_WRAP_DIR -#include "dir.h" -#include "utf-conv.h" +#include "posix.h" static int init_filter(char *filter, size_t n, const char *dir) { diff --git a/src/win32/posix.h b/src/win32/posix.h index 0d5effe08..b573f49af 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -9,6 +9,7 @@ #include "common.h" #include "utf-conv.h" +#include "dir.h" GIT_INLINE(int) p_link(const char *old, const char *new) { -- cgit v1.2.1 From 3948e86240e401adebe0d683709ddc32ecaf7f96 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 13 Aug 2013 09:38:37 +0200 Subject: windows: Fuck me --- src/win32/dir.c | 2 +- src/win32/posix.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/win32/dir.c b/src/win32/dir.c index cd3c7de51..65472dc80 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -79,7 +79,7 @@ int git__readdir_ext( if (wcslen(d->f.cFileName) >= sizeof(entry->d_name)) return -1; - git__win32_path_from_c(entry->d_name, d->f.cFileName); + git__win32_path_to_c(entry->d_name, d->f.cFileName); entry->d_ino = 0; *result = entry; diff --git a/src/win32/posix.h b/src/win32/posix.h index b573f49af..962877166 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -8,6 +8,7 @@ #define INCLUDE_posix__w32_h__ #include "common.h" +#include "../posix.h" #include "utf-conv.h" #include "dir.h" -- cgit v1.2.1 From 3869a171dd78e52436bcb779a04b910454932e55 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 8 Aug 2013 10:10:23 -0700 Subject: Fix mingw cross-compile build --- src/win32/utf-conv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h index 967db859e..835dc75a3 100644 --- a/src/win32/utf-conv.h +++ b/src/win32/utf-conv.h @@ -6,6 +6,7 @@ */ #include +#include "common.h" #ifndef INCLUDE_git_utfconv_h__ #define INCLUDE_git_utfconv_h__ -- cgit v1.2.1 From e12618b1ecea0eda5bc23662c78b678ca5a27013 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 13 Aug 2013 09:22:53 -0700 Subject: Add some things to precompiled header --- src/win32/precompiled.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/win32/precompiled.h b/src/win32/precompiled.h index 5de7e6f34..cbfe98812 100644 --- a/src/win32/precompiled.h +++ b/src/win32/precompiled.h @@ -1,4 +1,5 @@ #include "git2.h" +#include "common.h" #include #include @@ -6,6 +7,8 @@ #include #include #include +#include +#include #include #include -- cgit v1.2.1 From d4cff0cb1caac8c2c2cabbab9d3301f99b5ee230 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 13 Aug 2013 09:40:32 -0700 Subject: Rename git__win32_path fns to git_win32_path --- src/fileops.c | 2 +- src/path.c | 2 +- src/transports/winhttp.c | 4 ++-- src/win32/dir.c | 6 +++--- src/win32/posix.h | 2 +- src/win32/posix_w32.c | 26 +++++++++++++------------- src/win32/utf-conv.h | 11 +++++++---- tests-clar/clar_libgit2.c | 10 +++++----- 8 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index cf77ad164..aea8075d5 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -60,7 +60,7 @@ int git_futils_creat_locked(const char *path, const mode_t mode) #ifdef GIT_WIN32 git_win32_path buf; - git__win32_path_from_c(buf, path); + git_win32_path_from_c(buf, path); fd = _wopen(buf, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY | O_CLOEXEC, mode); #else diff --git a/src/path.c b/src/path.c index c9716ef6a..9a4b8c413 100644 --- a/src/path.c +++ b/src/path.c @@ -492,7 +492,7 @@ bool git_path_is_empty_dir(const char *path) if (!git_path_isdir(path)) return false; git_buf_printf(&pathbuf, "%s\\*", path); - git__win32_path_from_c(wbuf, git_buf_cstr(&pathbuf)); + git_win32_path_from_c(wbuf, git_buf_cstr(&pathbuf)); hFind = FindFirstFileW(wbuf, &ffd); if (INVALID_HANDLE_VALUE == hFind) { diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 6f182c94c..8decd8d51 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -920,7 +920,7 @@ static int winhttp_connect( return -1; /* Prepare host */ - git__win32_path_from_c(host, t->host); + git_win32_path_from_c(host, t->host); /* Establish session */ t->session = WinHttpOpen( @@ -934,7 +934,7 @@ static int winhttp_connect( giterr_set(GITERR_OS, "Failed to init WinHTTP"); return -1; } - + /* Establish connection */ t->connection = WinHttpConnect( t->session, diff --git a/src/win32/dir.c b/src/win32/dir.c index 65472dc80..0ea5124db 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -39,7 +39,7 @@ git__DIR *git__opendir(const char *dir) if (!new->dir) goto fail; - git__win32_path_from_c(filter_w, filter); + git_win32_path_from_c(filter_w, filter); new->h = FindFirstFileW(filter_w, &new->f); if (new->h == INVALID_HANDLE_VALUE) { @@ -79,7 +79,7 @@ int git__readdir_ext( if (wcslen(d->f.cFileName) >= sizeof(entry->d_name)) return -1; - git__win32_path_to_c(entry->d_name, d->f.cFileName); + git_win32_path_to_c(entry->d_name, d->f.cFileName); entry->d_ino = 0; *result = entry; @@ -115,7 +115,7 @@ void git__rewinddir(git__DIR *d) if (!init_filter(filter, sizeof(filter), d->dir)) return; - git__win32_path_from_c(filter_w, filter); + git_win32_path_from_c(filter_w, filter); d->h = FindFirstFileW(filter_w, &d->f); if (d->h == INVALID_HANDLE_VALUE) diff --git a/src/win32/posix.h b/src/win32/posix.h index 962877166..5f924a026 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -24,7 +24,7 @@ GIT_INLINE(int) p_mkdir(const char *path, mode_t mode) { git_win32_path buf; GIT_UNUSED(mode); - git__win32_path_from_c(buf, path); + git_win32_path_from_c(buf, path); return _wmkdir(buf); } diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 437ded284..3a626f767 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -17,7 +17,7 @@ int p_unlink(const char *path) { git_win32_path buf; - git__win32_path_from_c(buf, path); + git_win32_path_from_c(buf, path); _wchmod(buf, 0666); return _wunlink(buf); } @@ -63,7 +63,7 @@ static int do_lstat( wchar_t lastch; int flen; - flen = git__win32_path_from_c(fbuf, file_name); + flen = git_win32_path_from_c(fbuf, file_name); /* truncate trailing slashes */ for (; flen > 0; --flen) { @@ -189,7 +189,7 @@ int p_readlink(const char *link, char *target, size_t target_len) } } - git__win32_path_from_c(link_w, link); + git_win32_path_from_c(link_w, link); hFile = CreateFileW(link_w, // file to open GENERIC_READ, // open for reading @@ -258,7 +258,7 @@ int p_open(const char *path, int flags, ...) git_win32_path buf; mode_t mode = 0; - git__win32_path_from_c(buf, path); + git_win32_path_from_c(buf, path); if (flags & O_CREAT) { va_list arg_list; @@ -274,7 +274,7 @@ int p_open(const char *path, int flags, ...) int p_creat(const char *path, mode_t mode) { git_win32_path buf; - git__win32_path_from_c(buf, path); + git_win32_path_from_c(buf, path); return _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode); } @@ -317,14 +317,14 @@ int p_stat(const char* path, struct stat* buf) int p_chdir(const char* path) { git_win32_path buf; - git__win32_path_from_c(buf, path); + git_win32_path_from_c(buf, path); return _wchdir(buf); } int p_chmod(const char* path, mode_t mode) { git_win32_path buf; - git__win32_path_from_c(buf, path); + git_win32_path_from_c(buf, path); return _wchmod(buf, mode); } @@ -332,7 +332,7 @@ int p_rmdir(const char* path) { int error; git_win32_path buf; - git__win32_path_from_c(buf, path); + git_win32_path_from_c(buf, path); error = _wrmdir(buf); @@ -349,7 +349,7 @@ int p_rmdir(const char* path) int p_hide_directory__w32(const char *path) { git_win32_path buf; - git__win32_path_from_c(buf, path); + git_win32_path_from_c(buf, path); return (SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0) ? 0 : -1; } @@ -359,7 +359,7 @@ char *p_realpath(const char *orig_path, char *buffer) git_win32_path orig_path_w; git_win32_path buffer_w; - git__win32_path_from_c(orig_path_w, orig_path); + git_win32_path_from_c(orig_path_w, orig_path); /* Implicitly use GetCurrentDirectory which can be a threading issue */ ret = GetFullPathNameW(orig_path_w, GIT_WIN_PATH_UTF16, buffer_w, NULL); @@ -450,7 +450,7 @@ int p_setenv(const char* name, const char* value, int overwrite) int p_access(const char* path, mode_t mode) { git_win32_path buf; - git__win32_path_from_c(buf, path); + git_win32_path_from_c(buf, path); return _waccess(buf, mode); } @@ -459,8 +459,8 @@ int p_rename(const char *from, const char *to) git_win32_path wfrom; git_win32_path wto; - git__win32_path_from_c(wfrom, from); - git__win32_path_from_c(wto, to); + git_win32_path_from_c(wfrom, from); + git_win32_path_from_c(wto, to); return MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? 0 : -1; } diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h index 835dc75a3..1d008dba5 100644 --- a/src/win32/utf-conv.h +++ b/src/win32/utf-conv.h @@ -11,22 +11,25 @@ #ifndef INCLUDE_git_utfconv_h__ #define INCLUDE_git_utfconv_h__ +/* Maximum characters in a Windows path plus one for NUL byte */ #define GIT_WIN_PATH_UTF16 (260 + 1) + +/* Maximum bytes necessary to convert a full-length UTF16 path to UTF8 */ #define GIT_WIN_PATH_UTF8 (260 * 4 + 1) typedef wchar_t git_win32_path[GIT_WIN_PATH_UTF16]; -// dest_size is the size of dest in wchar_t's +/* dest_size is the size of dest in wchar_t's */ int git__utf8_to_16(wchar_t * dest, size_t dest_size, const char *src); -// dest_size is the size of dest in char's +/* dest_size is the size of dest in char's */ int git__utf16_to_8(char *dest, size_t dest_size, const wchar_t *src); -GIT_INLINE(int) git__win32_path_from_c(git_win32_path dest, const char *src) +GIT_INLINE(int) git_win32_path_from_c(git_win32_path dest, const char *src) { return git__utf8_to_16(dest, GIT_WIN_PATH_UTF16, src); } -GIT_INLINE(int) git__win32_path_to_c(char *dest, const git_win32_path src) +GIT_INLINE(int) git_win32_path_to_c(char *dest, const git_win32_path src) { return git__utf16_to_8(dest, GIT_WIN_PATH_UTF8, src); } diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 9e0fbfbac..305581ec2 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -61,7 +61,7 @@ char *cl_getenv(const char *name) wchar_t *value_utf16; char *value_utf8; - git__win32_path_from_c(name_utf16, name); + git_win32_path_from_c(name_utf16, name); alloc_len = GetEnvironmentVariableW(name_utf16, NULL, 0); if (alloc_len <= 0) return NULL; @@ -84,10 +84,10 @@ int cl_setenv(const char *name, const char *value) git_win32_path name_utf16; git_win32_path value_utf16; - git__win32_path_from_c(name_utf16, name); + git_win32_path_from_c(name_utf16, name); if (value) { - git__win32_path_from_c(value_utf16, value); + git_win32_path_from_c(value_utf16, value); cl_assert(SetEnvironmentVariableW(name_utf16, value_utf16)); } else { /* Windows XP returns 0 (failed) when passing NULL for lpValue when @@ -111,8 +111,8 @@ int cl_rename(const char *source, const char *dest) git_win32_path dest_utf16; unsigned retries = 1; - git__win32_path_from_c(source_utf16, source); - git__win32_path_from_c(dest_utf16, dest); + git_win32_path_from_c(source_utf16, source); + git_win32_path_from_c(dest_utf16, dest); while (!MoveFileW(source_utf16, dest_utf16)) { /* Only retry if the error is ERROR_ACCESS_DENIED; -- cgit v1.2.1 From 841034a35ee34190fa1cc136acccfa1a4abaed39 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 13 Aug 2013 09:45:56 -0700 Subject: Reintroduce type for UTF8 win32 path conversions --- src/win32/dir.c | 2 +- src/win32/dir.h | 2 +- src/win32/posix_w32.c | 8 ++++---- src/win32/utf-conv.h | 9 +++++---- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/win32/dir.c b/src/win32/dir.c index 0ea5124db..22050e875 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -24,7 +24,7 @@ static int init_filter(char *filter, size_t n, const char *dir) git__DIR *git__opendir(const char *dir) { - char filter[GIT_WIN_PATH_UTF8]; + git_win32_path_as_utf8 filter; git_win32_path filter_w; git__DIR *new = NULL; diff --git a/src/win32/dir.h b/src/win32/dir.h index 3875ab159..60883ffa5 100644 --- a/src/win32/dir.h +++ b/src/win32/dir.h @@ -11,7 +11,7 @@ struct git__dirent { int d_ino; - char d_name[GIT_WIN_PATH_UTF8]; + git_win32_path_as_utf8 d_name; }; typedef struct { diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 3a626f767..2d5479404 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -109,10 +109,10 @@ static int do_lstat( * the length of the path pointed to, which we expect everywhere else */ if (S_ISLNK(fMode)) { - char target[GIT_WIN_PATH_UTF8]; + git_win32_path_as_utf8 target; int readlink_result; - readlink_result = p_readlink(file_name, target, GIT_WIN_PATH_UTF8); + readlink_result = p_readlink(file_name, target, sizeof(target)); if (readlink_result == -1) return -1; @@ -300,7 +300,7 @@ int p_getcwd(char *buffer_out, size_t size) int p_stat(const char* path, struct stat* buf) { - char target[GIT_WIN_PATH_UTF8]; + git_win32_path_as_utf8 target; int error = 0; error = do_lstat(path, buf, 0); @@ -308,7 +308,7 @@ int p_stat(const char* path, struct stat* buf) /* We need not do this in a loop to unwind chains of symlinks since * p_readlink calls GetFinalPathNameByHandle which does it for us. */ if (error >= 0 && S_ISLNK(buf->st_mode) && - (error = p_readlink(path, target, GIT_WIN_PATH_UTF8)) >= 0) + (error = p_readlink(path, target, sizeof(target))) >= 0) error = do_lstat(target, buf, 0); return error; diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h index 1d008dba5..3af77580e 100644 --- a/src/win32/utf-conv.h +++ b/src/win32/utf-conv.h @@ -4,13 +4,12 @@ * 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_utfconv_h__ +#define INCLUDE_git_utfconv_h__ #include #include "common.h" -#ifndef INCLUDE_git_utfconv_h__ -#define INCLUDE_git_utfconv_h__ - /* Maximum characters in a Windows path plus one for NUL byte */ #define GIT_WIN_PATH_UTF16 (260 + 1) @@ -19,6 +18,8 @@ typedef wchar_t git_win32_path[GIT_WIN_PATH_UTF16]; +typedef char git_win32_path_as_utf8[GIT_WIN_PATH_UTF8]; + /* dest_size is the size of dest in wchar_t's */ int git__utf8_to_16(wchar_t * dest, size_t dest_size, const char *src); /* dest_size is the size of dest in char's */ @@ -29,7 +30,7 @@ GIT_INLINE(int) git_win32_path_from_c(git_win32_path dest, const char *src) return git__utf8_to_16(dest, GIT_WIN_PATH_UTF16, src); } -GIT_INLINE(int) git_win32_path_to_c(char *dest, const git_win32_path src) +GIT_INLINE(int) git_win32_path_to_c(git_win32_path_as_utf8 dest, const wchar_t *src) { return git__utf16_to_8(dest, GIT_WIN_PATH_UTF8, src); } -- cgit v1.2.1 From ee0656012c213a9589c7a0892f3e4a11caebc664 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 13 Aug 2013 09:53:56 -0700 Subject: Minor win32 fixes and improvements This is just a bunch of small fixes that I noticed while looking at the UTF8 and UTF16 path stuff. It fixes a slowdown in looking for an empty directory (not exiting loop asap), makes the dir name in the git__DIR structure be a GIT_FLEX_ARRAY to save an allocation, and fixes some slightly odd assumptions in the cl_getenv helper. --- src/path.c | 2 ++ src/win32/dir.c | 21 ++++++++------------- src/win32/dir.h | 2 +- src/win32/posix_w32.c | 4 ++-- tests-clar/clar_libgit2.c | 5 +++-- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/path.c b/src/path.c index 9a4b8c413..d64a5b33e 100644 --- a/src/path.c +++ b/src/path.c @@ -497,12 +497,14 @@ bool git_path_is_empty_dir(const char *path) hFind = FindFirstFileW(wbuf, &ffd); if (INVALID_HANDLE_VALUE == hFind) { giterr_set(GITERR_OS, "Couldn't open '%s'", path); + git_buf_free(&pathbuf); return false; } do { if (!git_path_is_dot_or_dotdotW(ffd.cFileName)) { retval = false; + break; } } while (FindNextFileW(hFind, &ffd) != 0); diff --git a/src/win32/dir.c b/src/win32/dir.c index 22050e875..b03c1d556 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -27,33 +27,29 @@ git__DIR *git__opendir(const char *dir) git_win32_path_as_utf8 filter; git_win32_path filter_w; git__DIR *new = NULL; + size_t dirlen; if (!dir || !init_filter(filter, sizeof(filter), dir)) return NULL; - new = git__calloc(1, sizeof(*new)); + dirlen = strlen(dir); + + new = git__calloc(sizeof(*new) + dirlen + 1, 1); if (!new) return NULL; - - new->dir = git__strdup(dir); - if (!new->dir) - goto fail; + memcpy(new->dir, dir, dirlen); git_win32_path_from_c(filter_w, filter); new->h = FindFirstFileW(filter_w, &new->f); if (new->h == INVALID_HANDLE_VALUE) { giterr_set(GITERR_OS, "Could not open directory '%s'", dir); - goto fail; + git__free(new); + return NULL; } new->first = 1; return new; - -fail: - git__free(new->dir); - git__free(new); - return NULL; } int git__readdir_ext( @@ -133,8 +129,7 @@ int git__closedir(git__DIR *d) FindClose(d->h); d->h = INVALID_HANDLE_VALUE; } - git__free(d->dir); - d->dir = NULL; + git__free(d); return 0; } diff --git a/src/win32/dir.h b/src/win32/dir.h index 60883ffa5..24d48f6ba 100644 --- a/src/win32/dir.h +++ b/src/win32/dir.h @@ -18,8 +18,8 @@ typedef struct { HANDLE h; WIN32_FIND_DATAW f; struct git__dirent entry; - char *dir; int first; + char dir[GIT_FLEX_ARRAY]; } git__DIR; extern git__DIR *git__opendir(const char *); diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 2d5479404..9d5b8d877 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -514,10 +514,10 @@ p_gmtime_r (const time_t *timer, struct tm *result) #else #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL #endif - + #ifndef _TIMEZONE_DEFINED #define _TIMEZONE_DEFINED -struct timezone +struct timezone { int tz_minuteswest; /* minutes W of Greenwich */ int tz_dsttime; /* type of dst correction */ diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 305581ec2..bf35a68eb 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -66,12 +66,13 @@ char *cl_getenv(const char *name) if (alloc_len <= 0) return NULL; - alloc_len = GIT_WIN_PATH_UTF8; cl_assert(value_utf16 = git__calloc(alloc_len, sizeof(wchar_t))); GetEnvironmentVariableW(name_utf16, value_utf16, alloc_len); - cl_assert(value_utf8 = git__malloc(alloc_len)); + alloc_len = alloc_len * 4 + 1; /* worst case UTF16->UTF8 growth */ + cl_assert(value_utf8 = git__calloc(alloc_len, 1)); + git__utf16_to_8(value_utf8, alloc_len, value_utf16); git__free(value_utf16); -- cgit v1.2.1 From 0228a514294bcb9d23bf24c61199a1a3e34d4772 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 13 Aug 2013 10:20:25 -0700 Subject: Missed one path for path_as_utf8 type --- src/win32/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32/dir.c b/src/win32/dir.c index b03c1d556..f7859b73f 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -96,7 +96,7 @@ struct git__dirent *git__readdir(git__DIR *d) void git__rewinddir(git__DIR *d) { - char filter[GIT_WIN_PATH_UTF8]; + git_win32_path_as_utf8 filter; git_win32_path filter_w; if (!d) -- cgit v1.2.1 From 9ccdb21155b3c9650acf58c55b2596c3503ea14d Mon Sep 17 00:00:00 2001 From: Brodie Rao Date: Tue, 13 Aug 2013 10:55:37 -0700 Subject: fileops: stat() before open()ing in git_futils_readbuffer_updated() This reverts refactoring done in 13224ea4aad9a1b3c9cc4c992ceaea9af623e047 that introduces a performance regression for NFS when reading files that don't exist. open() forces a cache invalidation on NFS, while stat()ing a file just uses the cache and is very quick. To give a specific example, say you have a repo with a thousand packed refs. Before this change, looking up every single one ould incur a thousand slow open() calls. With this change, it's a thousand fast stat() calls. --- src/fileops.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 7f8418d7a..e367ac244 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -147,6 +147,7 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len) int git_futils_readbuffer_updated( git_buf *buf, const char *path, time_t *mtime, size_t *size, int *updated) { + int error = 0; git_file fd; struct stat st; bool changed = false; @@ -156,11 +157,15 @@ int git_futils_readbuffer_updated( if (updated != NULL) *updated = 0; - if ((fd = git_futils_open_ro(path)) < 0) - return fd; + if (p_stat(path, &st) < 0) { + error = errno; + giterr_set(GITERR_OS, "Failed to stat '%s'", path); + if (error == ENOENT || error == ENOTDIR) + return GIT_ENOTFOUND; + return -1; + } - if (p_fstat(fd, &st) < 0 || S_ISDIR(st.st_mode) || !git__is_sizet(st.st_size+1)) { - p_close(fd); + if (S_ISDIR(st.st_mode) || !git__is_sizet(st.st_size+1)) { giterr_set(GITERR_OS, "Invalid regular file stat for '%s'", path); return -1; } @@ -177,7 +182,6 @@ int git_futils_readbuffer_updated( changed = true; if (!changed) { - p_close(fd); return 0; } @@ -186,6 +190,9 @@ int git_futils_readbuffer_updated( if (size != NULL) *size = (size_t)st.st_size; + if ((fd = git_futils_open_ro(path)) < 0) + return fd; + if (git_futils_readbuffer_fd(buf, fd, (size_t)st.st_size) < 0) { p_close(fd); return -1; -- cgit v1.2.1 From af6dab7ef74cf96c165e39cafd1aac3a659a3e8a Mon Sep 17 00:00:00 2001 From: Philip Kelley Date: Tue, 13 Aug 2013 13:10:52 -0400 Subject: Respect GIT_SSL_NO_VERIFY and http.sslVerify --- src/remote.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/remote.c b/src/remote.c index 158f3e938..efd1d1260 100644 --- a/src/remote.c +++ b/src/remote.c @@ -81,6 +81,31 @@ static int ensure_remote_name_is_valid(const char *name) return error; } +static int get_check_cert(git_repository *repo) +{ + git_config *cfg; + const char *val; + int check_cert; + + assert(repo); + + /* Go through the possible sources for SSL verification settings, from + * most specific to least specific. */ + + /* GIT_SSL_NO_VERIFY environment variable */ + if ((val = getenv("GIT_SSL_NO_VERIFY")) && + !git_config_parse_bool(&check_cert, val)) + return !check_cert; + + /* http.sslVerify config setting */ + if (!git_repository_config__weakptr(&cfg, repo) && + !git_config_get_bool(&check_cert, cfg, "http.sslVerify")) + return check_cert; + + /* By default, we *DO* want to verify the certificate. */ + return 1; +} + static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch) { git_remote *remote; @@ -94,7 +119,7 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n GITERR_CHECK_ALLOC(remote); remote->repo = repo; - remote->check_cert = 1; + remote->check_cert = (unsigned)get_check_cert(repo); remote->update_fetchhead = 1; if (git_vector_init(&remote->refs, 32, NULL) < 0) @@ -253,7 +278,7 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name) GITERR_CHECK_ALLOC(remote); memset(remote, 0x0, sizeof(git_remote)); - remote->check_cert = 1; + remote->check_cert = (unsigned)get_check_cert(repo); remote->update_fetchhead = 1; remote->name = git__strdup(name); GITERR_CHECK_ALLOC(remote->name); -- cgit v1.2.1 From f4be8209afd3cc996667196a1e437aac21485691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 14 Aug 2013 00:45:05 +0200 Subject: config: don't special-case the multivar iterator Build it on top of the normal iterator instead, which lets use re-use a lot of code. --- include/git2/config.h | 2 +- include/git2/sys/config.h | 2 - src/config.c | 123 +++++++++++++++----------- src/config.h | 3 + src/config_file.c | 201 +------------------------------------------ tests-clar/config/multivar.c | 2 +- 6 files changed, 83 insertions(+), 250 deletions(-) diff --git a/include/git2/config.h b/include/git2/config.h index 28216467b..f14415148 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -350,7 +350,7 @@ GIT_EXTERN(int) git_config_get_multivar_foreach(const git_config *cfg, const cha * @param regexp regular expression to filter which variables we're * interested in. Use NULL to indicate all */ -GIT_EXTERN(int) git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp); +GIT_EXTERN(int) git_config_multivar_iterator_new(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp); /** * Return the current entry and advance the iterator diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index e369fb8ab..7572ace51 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -58,8 +58,6 @@ struct git_config_backend { /* Open means open the file/database and parse if necessary */ int (*open)(struct git_config_backend *, git_config_level_t level); int (*get)(const struct git_config_backend *, const char *key, const git_config_entry **entry); - int (*get_multivar_foreach)(struct git_config_backend *, const char *key, const char *regexp, git_config_foreach_cb callback, void *payload); - int (*get_multivar)(git_config_iterator **, struct git_config_backend *, const char *name, const char *regexp); int (*set)(struct git_config_backend *, const char *key, const char *value); int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value); int (*del)(struct git_config_backend *, const char *key); diff --git a/src/config.c b/src/config.c index ae4e4816a..c98d6a52d 100644 --- a/src/config.c +++ b/src/config.c @@ -747,7 +747,7 @@ int git_config_get_multivar_foreach( git_config_iterator *iter; git_config_entry *entry; - if ((err = git_config_get_multivar(&iter, cfg, name, regexp)) < 0) + if ((err = git_config_multivar_iterator_new(&iter, cfg, name, regexp)) < 0) return err; found = 0; @@ -771,92 +771,82 @@ int git_config_get_multivar_foreach( typedef struct { git_config_iterator parent; - git_config_iterator *current; + git_config_iterator *iter; char *name; - char *regexp; - const git_config *cfg; - size_t i; + regex_t regex; + int have_regex; } multivar_iter; static int multivar_iter_next(git_config_entry **entry, git_config_iterator *_iter) { multivar_iter *iter = (multivar_iter *) _iter; - git_config_iterator *current = iter->current; - file_internal *internal; - git_config_backend *backend; - size_t i; int error = 0; - if (current != NULL && - (error = current->next(entry, current)) == 0) { - return 0; - } - - if (error < 0 && error != GIT_ITEROVER) - return error; - - do { - if (find_next_backend(&i, iter->cfg, iter->i) < 0) - return GIT_ITEROVER; - - internal = git_vector_get(&iter->cfg->files, i - 1); - backend = internal->file; - iter->i = i - 1; - - if (iter->current) - iter->current->free(current); - - iter->current = NULL; - error = backend->get_multivar(&iter->current, backend, iter->name, iter->regexp); - if (error == GIT_ENOTFOUND) + while ((error = iter->iter->next(entry, iter->iter)) == 0) { + if (git__strcmp(iter->name, (*entry)->name)) continue; - if (error < 0) - return error; - - return iter->current->next(entry, iter->current); + if (!iter->have_regex) + return 0; - } while(1); + if (regexec(&iter->regex, (*entry)->value, 0, NULL, 0) == 0) + return 0; + } - return GIT_ITEROVER; + return error; } void multivar_iter_free(git_config_iterator *_iter) { multivar_iter *iter = (multivar_iter *) _iter; - if (iter->current) - iter->current->free(iter->current); + iter->iter->free(iter->iter); git__free(iter->name); - git__free(iter->regexp); + regfree(&iter->regex); git__free(iter); } -int git_config_get_multivar(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp) +int git_config_multivar_iterator_new(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp) { - multivar_iter *iter; + multivar_iter *iter = NULL; + git_config_iterator *inner = NULL; + int error; + + if ((error = git_config_iterator_new(&inner, cfg)) < 0) + return error; iter = git__calloc(1, sizeof(multivar_iter)); GITERR_CHECK_ALLOC(iter); - iter->name = git__strdup(name); - GITERR_CHECK_ALLOC(iter->name); + if ((error = git_config__normalize_name(name, &iter->name)) < 0) + goto on_error; if (regexp != NULL) { - iter->regexp = git__strdup(regexp); - GITERR_CHECK_ALLOC(iter->regexp); + error = regcomp(&iter->regex, regexp, REG_EXTENDED); + if (error < 0) { + giterr_set_regex(&iter->regex, error); + error = -1; + regfree(&iter->regex); + goto on_error; + } + + iter->have_regex = 1; } + iter->iter = inner; iter->parent.free = multivar_iter_free; iter->parent.next = multivar_iter_next; - iter->i = cfg->files.length; - iter->cfg = cfg; - *out = (git_config_iterator *) iter; return 0; + +on_error: + + inner->free(inner); + git__free(iter); + return error; } int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value) @@ -1125,6 +1115,41 @@ fail_parse: return -1; } +/* Take something the user gave us and make it nice for our hash function */ +int git_config__normalize_name(const char *in, char **out) +{ + char *name, *fdot, *ldot; + + assert(in && out); + + name = git__strdup(in); + GITERR_CHECK_ALLOC(name); + + fdot = strchr(name, '.'); + ldot = strrchr(name, '.'); + + if (fdot == NULL || fdot == name || ldot == NULL || !ldot[1]) + goto invalid; + + /* Validate and downcase up to first dot and after last dot */ + if (git_config_file_normalize_section(name, fdot) < 0 || + git_config_file_normalize_section(ldot + 1, NULL) < 0) + goto invalid; + + /* If there is a middle range, make sure it doesn't have newlines */ + while (fdot < ldot) + if (*fdot++ == '\n') + goto invalid; + + *out = name; + return 0; + +invalid: + git__free(name); + giterr_set(GITERR_CONFIG, "Invalid config item name '%s'", in); + return GIT_EINVALIDSPEC; +} + struct rename_data { git_config *config; git_buf *name; diff --git a/src/config.h b/src/config.h index c5c11ae14..85db5e3e1 100644 --- a/src/config.h +++ b/src/config.h @@ -49,4 +49,7 @@ extern int git_config_rename_section( */ extern int git_config_file__ondisk(struct git_config_backend **out, const char *path); +extern int git_config__normalize_name(const char *in, char **out); + + #endif diff --git a/src/config_file.c b/src/config_file.c index 7c22be424..21dc22329 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -136,41 +136,6 @@ int git_config_file_normalize_section(char *start, char *end) return 0; } -/* Take something the user gave us and make it nice for our hash function */ -static int normalize_name(const char *in, char **out) -{ - char *name, *fdot, *ldot; - - assert(in && out); - - name = git__strdup(in); - GITERR_CHECK_ALLOC(name); - - fdot = strchr(name, '.'); - ldot = strrchr(name, '.'); - - if (fdot == NULL || fdot == name || ldot == NULL || !ldot[1]) - goto invalid; - - /* Validate and downcase up to first dot and after last dot */ - if (git_config_file_normalize_section(name, fdot) < 0 || - git_config_file_normalize_section(ldot + 1, NULL) < 0) - goto invalid; - - /* If there is a middle range, make sure it doesn't have newlines */ - while (fdot < ldot) - if (*fdot++ == '\n') - goto invalid; - - *out = name; - return 0; - -invalid: - git__free(name); - giterr_set(GITERR_CONFIG, "Invalid config item name '%s'", in); - return GIT_EINVALIDSPEC; -} - static void free_vars(git_strmap *values) { cvar_t *var = NULL; @@ -314,7 +279,7 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val khiter_t pos; int rval, ret; - if ((rval = normalize_name(name, &key)) < 0) + if ((rval = git_config__normalize_name(name, &key)) < 0) return rval; /* @@ -397,7 +362,7 @@ static int config_get(const git_config_backend *cfg, const char *name, const git khiter_t pos; int error; - if ((error = normalize_name(name, &key)) < 0) + if ((error = git_config__normalize_name(name, &key)) < 0) return error; pos = git_strmap_lookup_index(b->values, key); @@ -412,162 +377,6 @@ static int config_get(const git_config_backend *cfg, const char *name, const git return 0; } -typedef struct { - git_config_iterator parent; - cvar_t *var; - regex_t regex; - int have_regex; -} foreach_iter; - -static void foreach_iter_free(git_config_iterator *_iter) -{ - foreach_iter *iter = (foreach_iter *) _iter; - - if (iter->have_regex) - regfree(&iter->regex); - - git__free(iter); -} - -static int foreach_iter_next(git_config_entry **out, git_config_iterator *_iter) -{ - foreach_iter *iter = (foreach_iter *) _iter; - - cvar_t* var = iter->var; - - - if (var == NULL) - return GIT_ITEROVER; - - if (!iter->have_regex) { - *out = var->entry; - iter->var = var->next; - return 0; - } - - /* For the regex case, we must loop until we find something we like */ - do { - git_config_entry *entry = var->entry; - regex_t *regex = &iter->regex;; - if (regexec(regex, entry->value, 0, NULL, 0) == 0) { - *out = entry; - iter->var = var->next; - return 0; - } - var = var->next; - } while(var != NULL); - - return GIT_ITEROVER; -} - -static int config_get_multivar(git_config_iterator **out, git_config_backend *_backend, - const char *name, const char *regexp) -{ - foreach_iter *iter; - diskfile_backend *b = (diskfile_backend *) _backend; - - char *key; - khiter_t pos; - int error = 0; - - if ((error = normalize_name(name, &key)) < 0) - return error; - - pos = git_strmap_lookup_index(b->values, key); - git__free(key); - - if (!git_strmap_valid_index(b->values, pos)) - return GIT_ENOTFOUND; - - iter = git__calloc(1, sizeof(foreach_iter)); - GITERR_CHECK_ALLOC(iter); - - iter->var = git_strmap_value_at(b->values, pos); - - if (regexp != NULL) { - int result; - - result = regcomp(&iter->regex, regexp, REG_EXTENDED); - if (result < 0) { - giterr_set_regex(&iter->regex, result); - regfree(&iter->regex); - return -1; - } - iter->have_regex = 1; - } - - iter->parent.free = foreach_iter_free; - iter->parent.next = foreach_iter_next; - - *out = (git_config_iterator *) iter; - - return 0; - } - -static int config_get_multivar_foreach( - git_config_backend *cfg, - const char *name, - const char *regex_str, - int (*fn)(const git_config_entry *, void *), - void *data) -{ - cvar_t *var; - diskfile_backend *b = (diskfile_backend *)cfg; - char *key; - khiter_t pos; - int error; - - if ((error = normalize_name(name, &key)) < 0) - return error; - - pos = git_strmap_lookup_index(b->values, key); - git__free(key); - - if (!git_strmap_valid_index(b->values, pos)) - return GIT_ENOTFOUND; - - var = git_strmap_value_at(b->values, pos); - - if (regex_str != NULL) { - regex_t regex; - int result; - - /* regex matching; build the regex */ - result = regcomp(®ex, regex_str, REG_EXTENDED); - if (result < 0) { - giterr_set_regex(®ex, result); - regfree(®ex); - return -1; - } - - /* and throw the callback only on the variables that - * match the regex */ - do { - if (regexec(®ex, var->entry->value, 0, NULL, 0) == 0) { - /* early termination by the user is not an error; - * just break and return successfully */ - if (fn(var->entry, data)) - break; - } - - var = var->next; - } while (var != NULL); - regfree(®ex); - } else { - /* no regex; go through all the variables */ - do { - /* early termination by the user is not an error; - * just break and return successfully */ - if (fn(var->entry, data) < 0) - break; - - var = var->next; - } while (var != NULL); - } - - return 0; -} - static int config_set_multivar( git_config_backend *cfg, const char *name, const char *regexp, const char *value) { @@ -581,7 +390,7 @@ static int config_set_multivar( assert(regexp); - if ((result = normalize_name(name, &key)) < 0) + if ((result = git_config__normalize_name(name, &key)) < 0) return result; pos = git_strmap_lookup_index(b->values, key); @@ -654,7 +463,7 @@ static int config_delete(git_config_backend *cfg, const char *name) int result; khiter_t pos; - if ((result = normalize_name(name, &key)) < 0) + if ((result = git_config__normalize_name(name, &key)) < 0) return result; pos = git_strmap_lookup_index(b->values, key); @@ -694,8 +503,6 @@ int git_config_file__ondisk(git_config_backend **out, const char *path) backend->parent.open = config_open; backend->parent.get = config_get; - backend->parent.get_multivar_foreach = config_get_multivar_foreach; - backend->parent.get_multivar = config_get_multivar; backend->parent.set = config_set; backend->parent.set_multivar = config_set_multivar; backend->parent.del = config_delete; diff --git a/tests-clar/config/multivar.c b/tests-clar/config/multivar.c index afb993c18..0d552d65e 100644 --- a/tests-clar/config/multivar.c +++ b/tests-clar/config/multivar.c @@ -76,7 +76,7 @@ static void check_get_multivar(git_config *cfg, int expected) git_config_entry *entry; int n = 0; - cl_git_pass(git_config_get_multivar(&iter, cfg, _name, NULL)); + cl_git_pass(git_config_multivar_iterator_new(&iter, cfg, _name, NULL)); while (git_config_next(&entry, iter) == 0) n++; -- cgit v1.2.1 From 67591c8cd8d55e6f3218f1a734385c845459e1ff Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 14 Aug 2013 10:28:01 +0200 Subject: sha1_lookup: do not use the "experimental" lookup mode --- src/pack.c | 5 ++++- src/sha1_lookup.c | 24 +++++++++++++++++++++++- src/sha1_lookup.h | 5 +++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/pack.c b/src/pack.c index d7e6a1e94..e7fb9f1ae 100644 --- a/src/pack.c +++ b/src/pack.c @@ -1110,8 +1110,11 @@ static int pack_entry_find_offset( short_oid->id[0], short_oid->id[1], short_oid->id[2], lo, hi, p->num_objects); #endif - /* Use git.git lookup code */ +#ifdef GIT_USE_LOOKUP pos = sha1_entry_pos(index, stride, 0, lo, hi, p->num_objects, short_oid->id); +#else + pos = sha1_position(index, stride, lo, hi, short_oid->id); +#endif if (pos >= 0) { /* An object matching exactly the oid was found */ diff --git a/src/sha1_lookup.c b/src/sha1_lookup.c index b7e66cc69..8aca86335 100644 --- a/src/sha1_lookup.c +++ b/src/sha1_lookup.c @@ -9,6 +9,7 @@ #include "sha1_lookup.h" #include "common.h" +#include "oid.h" /* * Conventional binary search loop looks like this: @@ -123,7 +124,7 @@ int sha1_entry_pos(const void *table, lov = (lov << 8) | lo_key[ofs_0+1]; kyv = (kyv << 8) | key[ofs_0+1]; } - assert(lov < hiv); + assert(lov <= hiv); if (kyv < lov) return -1 - lo; @@ -176,3 +177,24 @@ int sha1_entry_pos(const void *table, } while (lo < hi); return -((int)lo)-1; } + +int sha1_position(const void *table, + size_t stride, + unsigned lo, unsigned hi, + const unsigned char *key) +{ + do { + unsigned mi = (lo + hi) / 2; + int cmp = git_oid__cmp(table + mi * stride, (git_oid *)key); + + if (!cmp) + return mi; + + if (cmp > 0) + hi = mi; + else + lo = mi+1; + } while (lo < hi); + + return -((int)lo)-1; +} diff --git a/src/sha1_lookup.h b/src/sha1_lookup.h index 9a3537273..3799620c7 100644 --- a/src/sha1_lookup.h +++ b/src/sha1_lookup.h @@ -15,4 +15,9 @@ int sha1_entry_pos(const void *table, unsigned lo, unsigned hi, unsigned nr, const unsigned char *key); +int sha1_position(const void *table, + size_t stride, + unsigned lo, unsigned hi, + const unsigned char *key); + #endif -- cgit v1.2.1 From e2164da5eb2d76129b8dae0b5ea2f7a606324fba Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 14 Aug 2013 10:31:02 +0200 Subject: sha1_lookup: Hello my name is MSVC and how do I pointer --- src/sha1_lookup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sha1_lookup.c b/src/sha1_lookup.c index 8aca86335..35149a18d 100644 --- a/src/sha1_lookup.c +++ b/src/sha1_lookup.c @@ -183,9 +183,11 @@ int sha1_position(const void *table, unsigned lo, unsigned hi, const unsigned char *key) { + const unsigned char *base = table; + do { unsigned mi = (lo + hi) / 2; - int cmp = git_oid__cmp(table + mi * stride, (git_oid *)key); + int cmp = git_oid__cmp((git_oid *)(base + mi * stride), (git_oid *)key); if (!cmp) return mi; -- cgit v1.2.1 From 59547ce77269e0667426327d9166aad0954bc686 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 14 Aug 2013 10:34:07 +0200 Subject: oid: Helper for old-school hashcmp --- src/oid.h | 23 +++++++++++++---------- src/sha1_lookup.c | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/oid.h b/src/oid.h index 077d0a4c8..cfe7ca1b2 100644 --- a/src/oid.h +++ b/src/oid.h @@ -9,17 +9,8 @@ #include "git2/oid.h" -/* - * Compare two oid structures. - * - * @param a first oid structure. - * @param b second oid structure. - * @return <0, 0, >0 if a < b, a == b, a > b. - */ -GIT_INLINE(int) git_oid__cmp(const git_oid *a, const git_oid *b) +GIT_INLINE(int) git_oid__hashcmp(const unsigned char *sha1, const unsigned char *sha2) { - const unsigned char *sha1 = a->id; - const unsigned char *sha2 = b->id; int i; for (i = 0; i < GIT_OID_RAWSZ; i++, sha1++, sha2++) { @@ -30,4 +21,16 @@ GIT_INLINE(int) git_oid__cmp(const git_oid *a, const git_oid *b) return 0; } +/* + * Compare two oid structures. + * + * @param a first oid structure. + * @param b second oid structure. + * @return <0, 0, >0 if a < b, a == b, a > b. + */ +GIT_INLINE(int) git_oid__cmp(const git_oid *a, const git_oid *b) +{ + return git_oid__hashcmp(a->id, b->id); +} + #endif diff --git a/src/sha1_lookup.c b/src/sha1_lookup.c index 35149a18d..ce067caaa 100644 --- a/src/sha1_lookup.c +++ b/src/sha1_lookup.c @@ -187,7 +187,7 @@ int sha1_position(const void *table, do { unsigned mi = (lo + hi) / 2; - int cmp = git_oid__cmp((git_oid *)(base + mi * stride), (git_oid *)key); + int cmp = git_oid__hashcmp(base + mi * stride, key); if (!cmp) return mi; -- cgit v1.2.1 From 5be622fb563c89341a7dd5da4e65e2c225cb2c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sun, 11 Aug 2013 01:37:44 +0200 Subject: Test SSH in travis Set up the ssh credentials so we are able to talk to localhost and issue git commands. Move to use a script, as the command list is getting somewhat long. While here, delay installing valgrind until we need it, as it and its dependencies are by far the largest downloads and this allows us to start compiling (and failing) faster and we only incur this cost when the test suite runs successfully. --- .travis.yml | 19 +++++-------------- CMakeLists.txt | 4 +++- script/cibuild.sh | 32 ++++++++++++++++++++++++++++++++ tests-clar/online/push.c | 10 ++++++++++ 4 files changed, 50 insertions(+), 15 deletions(-) create mode 100755 script/cibuild.sh diff --git a/.travis.yml b/.travis.yml index 0d5746f2e..71f8406fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ # Travis-CI Build for libgit2 # see travis-ci.org for details -# As CMake is not officially supported we use erlang VMs language: c compiler: @@ -18,25 +17,17 @@ matrix: - compiler: i586-mingw32msvc-gcc env: OPTIONS="-DBUILD_CLAR=OFF -DWIN32=ON -DMINGW=ON" -# Make sure CMake is installed install: - - sudo apt-get update >/dev/null - - sudo apt-get -q install cmake valgrind + - sudo apt-get -qq update + - sudo apt-get -qq install cmake libssh2-1-dev openssh-client openssh-server -# Run the Build script +# Run the Build script and tests script: - - mkdir _temp - - git init --bare _temp/test.git - - git daemon --listen=localhost --export-all --enable=receive-pack --base-path=_temp _temp 2>/dev/null & - - export GITTEST_REMOTE_URL="git://localhost/test.git" - - mkdir _build - - cd _build - - cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS - - cmake --build . --target install - - ctest -V . + - script/cibuild.sh # Run Tests after_success: + - sudo apt-get -qq install valgrind - valgrind --leak-check=full --show-reachable=yes --suppressions=../libgit2_clar.supp ./libgit2_clar -ionline # Only watch the development branch diff --git a/CMakeLists.txt b/CMakeLists.txt index 1500a3a68..1c70ec2d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,7 +148,9 @@ ELSE() FILE(GLOB SRC_ZLIB deps/zlib/*.c deps/zlib/*.h) ENDIF() -FIND_PACKAGE(LIBSSH2 QUIET) +IF (NOT MINGW) + FIND_PACKAGE(LIBSSH2 QUIET) +ENDIF() IF (LIBSSH2_FOUND) ADD_DEFINITIONS(-DGIT_SSH) INCLUDE_DIRECTORIES(${LIBSSH2_INCLUDE_DIR}) diff --git a/script/cibuild.sh b/script/cibuild.sh new file mode 100755 index 000000000..722b3349d --- /dev/null +++ b/script/cibuild.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +# Create a test repo which we can use for the online::push tests +mkdir $HOME/_temp +git init --bare $HOME/_temp/test.git +git daemon --listen=localhost --export-all --enable=receive-pack --base-path=$HOME/_temp $HOME/_temp 2>/dev/null & +export GITTEST_REMOTE_URL="git://localhost/test.git" + +mkdir _build +cd _build +cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS +cmake --build . --target install +ctest -V . + +# Now that we've tested the raw git protocol, let's set up ssh to we +# can do the push tests over it + +killall git-daemon +sudo start ssh +ssh-keygen -t rsa -f ~/.ssh/id_rsa -N "" -q +cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys +ssh-keyscan -t rsa localhost >>~/.ssh/known_hosts + +export GITTEST_REMOTE_URL="ssh://localhost/$HOME/_temp/test.git" +export GITTEST_REMOTE_USER=$USER +export GITTEST_REMOTE_SSH_KEY="$HOME/.ssh/id_rsa" +export GITTEST_REMOTE_SSH_PUBKEY="$HOME/.ssh/id_rsa.pub" +export GITTEST_REMOTE_SSH_PASSPHRASE="" + +if [ -e ./libgit2_clar ]; then + ./libgit2_clar -sonline::push +fi diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 5dc7974c7..8b9602b45 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -9,6 +9,10 @@ static git_repository *_repo; +static char *_remote_ssh_key; +static char *_remote_ssh_pubkey; +static char *_remote_ssh_passphrase; + static char *_remote_url; static char *_remote_user; static char *_remote_pass; @@ -42,6 +46,9 @@ static int cred_acquire_cb( *((bool*)payload) = true; + if (GIT_CREDTYPE_SSH_PUBLICKEY & allowed_types) + return git_cred_ssh_keyfile_passphrase_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase); + if ((GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) == 0 || git_cred_userpass_plaintext_new(cred, _remote_user, _remote_pass) < 0) return -1; @@ -277,6 +284,9 @@ void test_online_push__initialize(void) _remote_url = cl_getenv("GITTEST_REMOTE_URL"); _remote_user = cl_getenv("GITTEST_REMOTE_USER"); _remote_pass = cl_getenv("GITTEST_REMOTE_PASS"); + _remote_ssh_key = cl_getenv("GITTEST_REMOTE_SSH_KEY"); + _remote_ssh_pubkey = cl_getenv("GITTEST_REMOTE_SSH_PUBKEY"); + _remote_ssh_passphrase = cl_getenv("GITTEST_REMOTE_SSH_PASSPHRASE"); _remote = NULL; if (_remote_url) { -- cgit v1.2.1 From 0b9ebb54ff9aab86bb858e1d2952efa4dcdafefa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 14 Aug 2013 11:18:05 +0200 Subject: remote: relax the url rules Accept any value for the remote's url, including an empty string which we used to reject as invalid configuration. This is not quite what git does (although it has its own problems with such configurations) and it makes it harder to fix the issue, by not letting the user modify it. As we already need to check for a valid URL when we try to connect to the network, let that perform the check, as we don't need to do it anywhere else. --- src/remote.c | 6 ------ tests-clar/network/remote/remotes.c | 10 ++++++---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/remote.c b/src/remote.c index 158f3e938..0dda196df 100644 --- a/src/remote.c +++ b/src/remote.c @@ -272,12 +272,6 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name) if ((error = git_config_get_string(&val, config, git_buf_cstr(&buf))) < 0) goto cleanup; - if (strlen(val) == 0) { - giterr_set(GITERR_INVALID, "Malformed remote '%s' - missing URL", name); - error = -1; - goto cleanup; - } - remote->repo = repo; remote->url = git__strdup(val); GITERR_CHECK_ALLOC(remote->url); diff --git a/tests-clar/network/remote/remotes.c b/tests-clar/network/remote/remotes.c index 3c4fa96fa..dec646526 100644 --- a/tests-clar/network/remote/remotes.c +++ b/tests-clar/network/remote/remotes.c @@ -361,13 +361,15 @@ void test_network_remote_remotes__tagopt(void) git_config_free(cfg); } -void test_network_remote_remotes__cannot_load_with_an_empty_url(void) +void test_network_remote_remotes__can_load_with_an_empty_url(void) { git_remote *remote = NULL; - cl_git_fail(git_remote_load(&remote, _repo, "empty-remote-url")); - cl_assert(giterr_last()->klass == GITERR_INVALID); - cl_assert_equal_p(remote, NULL); + cl_git_pass(git_remote_load(&remote, _repo, "empty-remote-url")); + + cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + + git_remote_free(remote); } void test_network_remote_remotes__check_structure_version(void) -- cgit v1.2.1 From c87bf86cd739c30ab430a789e9eb0dfb1b1d78b7 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 14 Aug 2013 10:58:02 -0700 Subject: Commit 7affc2f7 removed var initialization That commit accidentally removed the initialization of the "start" variable giving undefined results for the host extraction from the url input. --- src/transports/ssh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 1258a8e68..e0126a8fb 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -215,6 +215,7 @@ static int git_ssh_extract_url_parts( *username = git__substrdup(url, at - url); GITERR_CHECK_ALLOC(*username); } else { + start = url; *username = NULL; } -- cgit v1.2.1 From 1e94df08dad9437164ac7727f23a51591b7c42f4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 15 Aug 2013 00:09:46 +0200 Subject: sha1-lookup: This assert was correct --- src/sha1_lookup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sha1_lookup.c b/src/sha1_lookup.c index ce067caaa..cdcadfaa9 100644 --- a/src/sha1_lookup.c +++ b/src/sha1_lookup.c @@ -124,7 +124,7 @@ int sha1_entry_pos(const void *table, lov = (lov << 8) | lo_key[ofs_0+1]; kyv = (kyv << 8) | key[ofs_0+1]; } - assert(lov <= hiv); + assert(lov < hiv); if (kyv < lov) return -1 - lo; -- cgit v1.2.1 From 899ec41fa18a13db50ae3c3fd1c4bb4045364e6d Mon Sep 17 00:00:00 2001 From: Evan Hanson Date: Thu, 15 Aug 2013 16:25:48 +1200 Subject: revparse: Free left side of invalid range revspecs This fixes a small memory leak in git_revparse where early returns on errors from git_revparse_single cause a free() on the (reallocated) left side of the revspec to be skipped. --- src/revparse.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/revparse.c b/src/revparse.c index d21f08b53..2fdad0049 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -912,13 +912,9 @@ int git_revparse( rstr++; } - if ((error = git_revparse_single(&revspec->from, repo, lstr)) < 0) { - return error; - } - - if ((error = git_revparse_single(&revspec->to, repo, rstr)) < 0) { - return error; - } + error = git_revparse_single(&revspec->from, repo, lstr); + if (error == 0) + error = git_revparse_single(&revspec->to, repo, rstr); git__free((void*)lstr); } else { -- cgit v1.2.1 From 1616fa68e520dbd29b839335065599f8a2b93a6f Mon Sep 17 00:00:00 2001 From: Evan Hanson Date: Thu, 15 Aug 2013 17:25:05 +1200 Subject: revparse: Use more idiomatic error value test --- src/revparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/revparse.c b/src/revparse.c index 2fdad0049..b84f0037f 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -913,7 +913,7 @@ int git_revparse( } error = git_revparse_single(&revspec->from, repo, lstr); - if (error == 0) + if (!error) error = git_revparse_single(&revspec->to, repo, rstr); git__free((void*)lstr); -- cgit v1.2.1 From 376e6c9f96ffcd572ba974c9cc4d13b4f1e31474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 15 Aug 2013 13:48:35 +0200 Subject: odb: wrap the stream reading and writing functions This is in preparation for moving the hashing to the frontend, which requires us to handle the incoming data before passing it to the backend's stream. --- include/git2/odb.h | 49 ++++++++++++++++++++++++++++++++++--------- src/blob.c | 14 ++++++------- src/odb.c | 26 ++++++++++++++++++++--- src/tag.c | 6 +++--- src/transports/local.c | 6 +++--- tests-clar/object/raw/write.c | 6 +++--- 6 files changed, 78 insertions(+), 29 deletions(-) diff --git a/include/git2/odb.h b/include/git2/odb.h index b3e9a57a6..3e93a932c 100644 --- a/include/git2/odb.h +++ b/include/git2/odb.h @@ -219,16 +219,9 @@ GIT_EXTERN(int) git_odb_write(git_oid *out, git_odb *odb, const void *data, size * The type and final length of the object must be specified * when opening the stream. * - * The returned stream will be of type `GIT_STREAM_WRONLY` and - * will have the following methods: - * - * - stream->write: write `n` bytes into the stream - * - stream->finalize_write: close the stream and store the object in - * the odb - * - stream->free: free the stream - * - * The streaming write won't be effective until `stream->finalize_write` - * is called and returns without an error + * The returned stream will be of type `GIT_STREAM_WRONLY`, and it + * won't be effective until `git_odb_stream_finalize_write` is called + * and returns without an error * * The stream must always be free'd or will leak memory. * @@ -242,6 +235,42 @@ GIT_EXTERN(int) git_odb_write(git_oid *out, git_odb *odb, const void *data, size */ GIT_EXTERN(int) git_odb_open_wstream(git_odb_stream **out, git_odb *db, size_t size, git_otype type); +/** + * Write to an odb stream + * + * @param stream the stream + * @param buffer the data to write + * @param len the buffer's length + * @return 0 if the write succeeded; error code otherwise + */ +GIT_EXTERN(int) git_odb_stream_write(git_odb_stream *stream, const char *buffer, size_t len); + +/** + * Finish writing to an odb stream + * + * The object will take its final name and will be available to the + * odb. + * + * @param out pointer to store the resulting object's id + * @param stream the stream + * @return 0 on success; an error code otherwise + */ +GIT_EXTERN(int) git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream); + +/** + * Read from an odb stream + * + * Most backends don't implement streaming reads + */ +GIT_EXTERN(int) git_odb_stream_read(git_odb_stream *stream, char *buffer, size_t len); + +/** + * Free an odb stream + * + * @param stream the stream to free + */ +GIT_EXTERN(void) git_odb_stream_free(git_odb_stream *stream); + /** * Open a stream to read an object from the ODB * diff --git a/src/blob.c b/src/blob.c index 5bb51f7cf..6a289f43b 100644 --- a/src/blob.c +++ b/src/blob.c @@ -60,10 +60,10 @@ int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *b (error = git_odb_open_wstream(&stream, odb, len, GIT_OBJ_BLOB)) < 0) return error; - if ((error = stream->write(stream, buffer, len)) == 0) - error = stream->finalize_write(oid, stream); + if ((error = git_odb_stream_write(stream, buffer, len)) == 0) + error = git_odb_stream_finalize_write(oid, stream); - stream->free(stream); + git_odb_stream_free(stream); return error; } @@ -80,12 +80,12 @@ static int write_file_stream( return error; if ((fd = git_futils_open_ro(path)) < 0) { - stream->free(stream); + git_odb_stream_free(stream); return -1; } while (!error && (read_len = p_read(fd, buffer, sizeof(buffer))) > 0) { - error = stream->write(stream, buffer, read_len); + error = git_odb_stream_write(stream, buffer, read_len); written += read_len; } @@ -97,9 +97,9 @@ static int write_file_stream( } if (!error) - error = stream->finalize_write(oid, stream); + error = git_odb_stream_finalize_write(oid, stream); - stream->free(stream); + git_odb_stream_free(stream); return error; } diff --git a/src/odb.c b/src/odb.c index 6969cf772..158159662 100644 --- a/src/odb.c +++ b/src/odb.c @@ -864,9 +864,9 @@ int git_odb_write( if ((error = git_odb_open_wstream(&stream, db, len, type)) != 0) return error; - stream->write(stream, data, len); - error = stream->finalize_write(oid, stream); - stream->free(stream); + git_odb_stream_write(stream, data, len); + error = git_odb_stream_finalize_write(oid, stream); + git_odb_stream_free(stream); return error; } @@ -904,6 +904,26 @@ int git_odb_open_wstream( return error; } +int git_odb_stream_write(git_odb_stream *stream, const char *buffer, size_t len) +{ + return stream->write(stream, buffer, len); +} + +int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream) +{ + return stream->finalize_write(out, stream); +} + +int git_odb_stream_read(git_odb_stream *stream, char *buffer, size_t len) +{ + return stream->read(stream, buffer, len); +} + +void git_odb_stream_free(git_odb_stream *stream) +{ + stream->free(stream); +} + int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oid) { size_t i, reads = 0; diff --git a/src/tag.c b/src/tag.c index 71f4c1eb1..31a3c8b80 100644 --- a/src/tag.c +++ b/src/tag.c @@ -366,10 +366,10 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu if (git_odb_open_wstream(&stream, odb, strlen(buffer), GIT_OBJ_TAG) < 0) return -1; - stream->write(stream, buffer, strlen(buffer)); + git_odb_stream_write(stream, buffer, strlen(buffer)); - error = stream->finalize_write(oid, stream); - stream->free(stream); + error = git_odb_stream_finalize_write(oid, stream); + git_odb_stream_free(stream); if (error < 0) { git_buf_free(&ref_name); diff --git a/src/transports/local.c b/src/transports/local.c index a9da8146c..8a75de727 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -287,9 +287,9 @@ static int local_push_copy_object( odb_obj_size, odb_obj_type)) < 0) goto on_error; - if (odb_stream->write(odb_stream, (char *)git_odb_object_data(odb_obj), + if (git_odb_stream_write(odb_stream, (char *)git_odb_object_data(odb_obj), odb_obj_size) < 0 || - odb_stream->finalize_write(&remote_odb_obj_oid, odb_stream) < 0) { + git_odb_stream_finalize_write(&remote_odb_obj_oid, odb_stream) < 0) { error = -1; } else if (git_oid__cmp(&obj->id, &remote_odb_obj_oid) != 0) { giterr_set(GITERR_ODB, "Error when writing object to remote odb " @@ -298,7 +298,7 @@ static int local_push_copy_object( error = -1; } - odb_stream->free(odb_stream); + git_odb_stream_free(odb_stream); on_error: git_odb_object_free(odb_obj); diff --git a/tests-clar/object/raw/write.c b/tests-clar/object/raw/write.c index 9709c0302..273f08f2c 100644 --- a/tests-clar/object/raw/write.c +++ b/tests-clar/object/raw/write.c @@ -31,9 +31,9 @@ static void streaming_write(git_oid *oid, git_odb *odb, git_rawobj *raw) int error; cl_git_pass(git_odb_open_wstream(&stream, odb, raw->len, raw->type)); - stream->write(stream, raw->data, raw->len); - error = stream->finalize_write(oid, stream); - stream->free(stream); + git_odb_stream_write(stream, raw->data, raw->len); + error = git_odb_stream_finalize_write(oid, stream); + git_odb_stream_free(stream); cl_git_pass(error); } -- cgit v1.2.1 From 8380b39a6761efa360398279083a65064d6770d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 15 Aug 2013 14:29:39 +0200 Subject: odb: perform the stream hashing in the frontend Hash the data as it's coming into the stream and tell the backend what its name is when finalizing the write. This makes it consistent with the way a plain git_odb_write() performs the write. --- include/git2/odb_backend.h | 3 +++ src/odb.c | 21 +++++++++++++++++++++ src/odb_loose.c | 4 +--- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index af1e3e5b9..d004238a4 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -65,10 +65,13 @@ typedef enum { GIT_STREAM_RW = (GIT_STREAM_RDONLY | GIT_STREAM_WRONLY), } git_odb_stream_t; +typedef struct git_hash_ctx git_hash_ctx; + /** A stream to read/write from a backend */ struct git_odb_stream { git_odb_backend *backend; unsigned int mode; + git_hash_ctx *hash_ctx; int (*read)(git_odb_stream *stream, char *buffer, size_t len); int (*write)(git_odb_stream *stream, const char *buffer, size_t len); diff --git a/src/odb.c b/src/odb.c index 158159662..b7f64dfc9 100644 --- a/src/odb.c +++ b/src/odb.c @@ -871,11 +871,21 @@ int git_odb_write( return error; } +static void hash_header(git_hash_ctx *ctx, size_t size, git_otype type) +{ + char header[64]; + int hdrlen; + + hdrlen = git_odb__format_object_header(header, sizeof(header), size, type); + git_hash_update(ctx, header, hdrlen); +} + int git_odb_open_wstream( git_odb_stream **stream, git_odb *db, size_t size, git_otype type) { size_t i, writes = 0; int error = GIT_ERROR; + git_hash_ctx *ctx; assert(stream && db); @@ -901,16 +911,26 @@ int git_odb_open_wstream( if (error < 0 && !writes) error = git_odb__error_unsupported_in_backend("write object"); + ctx = git__malloc(sizeof(git_hash_ctx)); + GITERR_CHECK_ALLOC(ctx); + + + git_hash_ctx_init(ctx); + hash_header(ctx, size, type); + (*stream)->hash_ctx = ctx; + return error; } int git_odb_stream_write(git_odb_stream *stream, const char *buffer, size_t len) { + git_hash_update(stream->hash_ctx, buffer, len); return stream->write(stream, buffer, len); } int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream) { + git_hash_final(out, stream->hash_ctx); return stream->finalize_write(out, stream); } @@ -921,6 +941,7 @@ int git_odb_stream_read(git_odb_stream *stream, char *buffer, size_t len) void git_odb_stream_free(git_odb_stream *stream) { + git__free(stream->hash_ctx); stream->free(stream); } diff --git a/src/odb_loose.c b/src/odb_loose.c index 76ed8e232..a0c2c8c4c 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -776,8 +776,7 @@ static int loose_backend__stream_fwrite(git_oid *oid, git_odb_stream *_stream) git_buf final_path = GIT_BUF_INIT; int error = 0; - if (git_filebuf_hash(oid, &stream->fbuf) < 0 || - object_file_name(&final_path, backend, oid) < 0 || + if (object_file_name(&final_path, backend, oid) < 0 || object_mkdir(&final_path, backend) < 0) error = -1; /* @@ -848,7 +847,6 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_ if (git_buf_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 || git_filebuf_open(&stream->fbuf, tmp_path.ptr, - GIT_FILEBUF_HASH_CONTENTS | GIT_FILEBUF_TEMPORARY | (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT)) < 0 || stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0) -- cgit v1.2.1 From d4e6cf0cd05540b373bfcb8908e4bc8f8f72c73c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 15 Aug 2013 14:32:47 +0200 Subject: odb: remove a duplicate object header formatting function --- src/odb_loose.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/odb_loose.c b/src/odb_loose.c index a0c2c8c4c..35f53fb7d 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -809,17 +809,6 @@ static void loose_backend__stream_free(git_odb_stream *_stream) git__free(stream); } -static int format_object_header(char *hdr, size_t n, size_t obj_len, git_otype obj_type) -{ - const char *type_str = git_object_type2string(obj_type); - int len = snprintf(hdr, n, "%s %"PRIuZ, type_str, obj_len); - - assert(len > 0); /* otherwise snprintf() is broken */ - assert(((size_t)len) < n); /* otherwise the caller is broken! */ - - return len+1; -} - static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_backend, size_t length, git_otype type) { loose_backend *backend; @@ -833,7 +822,7 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_ backend = (loose_backend *)_backend; *stream_out = NULL; - hdrlen = format_object_header(hdr, sizeof(hdr), length, type); + hdrlen = git_odb__format_object_header(hdr, sizeof(hdr), length, type); stream = git__calloc(1, sizeof(loose_writestream)); GITERR_CHECK_ALLOC(stream); @@ -872,7 +861,7 @@ static int loose_backend__write(git_oid *oid, git_odb_backend *_backend, const v backend = (loose_backend *)_backend; /* prepare the header for the file */ - header_len = format_object_header(header, sizeof(header), len, type); + 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, -- cgit v1.2.1 From 5ce6c1e917a4282455fef6c7fd2236a7fb68653a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 12 Aug 2013 16:15:36 +0200 Subject: push: handle tag chains correctly When dealing with a chain of tags, we need to enqueue each of them individually, which means we can't use `git_tag_peel` as that jumps over the intermediate tags. Do the peeling manually so we can look at each object and take the appropriate action. --- src/push.c | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/push.c b/src/push.c index 452d71789..eaaa46248 100644 --- a/src/push.c +++ b/src/push.c @@ -233,6 +233,37 @@ on_error: return error; } +/** + * Insert all tags until we find a non-tag object, which is returned + * in `out`. + */ +static int enqueue_tag(git_object **out, git_push *push, git_oid *id) +{ + git_object *obj = NULL, *target = NULL; + int error; + + if ((error = git_object_lookup(&obj, push->repo, id, GIT_OBJ_TAG)) < 0) + return error; + + while (git_object_type(obj) == GIT_OBJ_TAG) { + if ((error = git_packbuilder_insert(push->pb, git_object_id(obj), NULL)) < 0) + break; + + if ((error = git_tag_target(&target, (git_tag *) obj)) < 0) + break; + + git_object_free(obj); + obj = target; + } + + if (error < 0) + git_object_free(obj); + else + *out = obj; + + return error; +} + static int revwalk(git_vector *commits, git_push *push) { git_remote_head *head; @@ -265,21 +296,11 @@ static int revwalk(git_vector *commits, git_push *push) goto on_error; if (type == GIT_OBJ_TAG) { - git_tag *tag; git_object *target; - if (git_packbuilder_insert(push->pb, &spec->loid, NULL) < 0) + if ((error = enqueue_tag(&target, push, &spec->loid)) < 0) goto on_error; - if (git_tag_lookup(&tag, push->repo, &spec->loid) < 0) - goto on_error; - - if (git_tag_peel(&target, tag) < 0) { - git_tag_free(tag); - goto on_error; - } - git_tag_free(tag); - if (git_object_type(target) == GIT_OBJ_COMMIT) { if (git_revwalk_push(rw, git_object_id(target)) < 0) { git_object_free(target); -- cgit v1.2.1 From c9340df055d97ca55a3a358f7e02416671db6278 Mon Sep 17 00:00:00 2001 From: Martin Woodward Date: Fri, 16 Aug 2013 19:40:58 +0100 Subject: Give credit to PHP for the p_readlink function in posix_w32.c --- COPYING | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/win32/posix_w32.c | 9 ++++++++ 2 files changed, 72 insertions(+) diff --git a/COPYING b/COPYING index d1ca4d401..f7e9f3af7 100644 --- a/COPYING +++ b/COPYING @@ -928,3 +928,66 @@ necessary. Here is a sample; alter the names: Ty Coon, President of Vice That's all there is to it! + +---------------------------------------------------------------------- + +Portions of src/win32/posix_w32.c are derrived from link_win32.c in PHP: + +-------------------------------------------------------------------- + The PHP License, version 3.01 +Copyright (c) 1999 - 2012 The PHP Group. All rights reserved. +-------------------------------------------------------------------- + +Redistribution and use in source and binary forms, with or without +modification, is permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. The name "PHP" must not be used to endorse or promote products + derived from this software without prior written permission. For + written permission, please contact group@php.net. + + 4. Products derived from this software may not be called "PHP", nor + may "PHP" appear in their name, without prior written permission + from group@php.net. You may indicate that your software works in + conjunction with PHP by saying "Foo for PHP" instead of calling + it "PHP Foo" or "phpfoo" + + 5. The PHP Group may publish revised and/or new versions of the + license from time to time. Each version will be given a + distinguishing version number. + Once covered code has been published under a particular version + of the license, you may always continue to use it under the terms + of that version. You may also choose to use such covered code + under the terms of any subsequent version of the license + published by the PHP Group. No one other than the PHP Group has + the right to modify the terms applicable to covered code created + under this License. + + 6. Redistributions of any form whatsoever must retain the following + acknowledgment: + "This product includes PHP software, freely available from + ". + +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------- + diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 9d5b8d877..57ebaa12e 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -160,6 +160,15 @@ int p_lstat_posixly(const char *filename, struct stat *buf) return do_lstat(filename, buf, 1); } + +/* + * Parts of the The p_readlink function are heavily inspired by the php + * readlink function in link_win32.c + * + * Copyright (c) 1999 - 2012 The PHP Group. All rights reserved. + * + * For details of the PHP license see http://www.php.net/license/3_01.txt + */ int p_readlink(const char *link, char *target, size_t target_len) { typedef DWORD (WINAPI *fpath_func)(HANDLE, LPWSTR, DWORD, DWORD); -- cgit v1.2.1 From ce23330fd636a99a25b3a6b7c81e63c424ae7d7c Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 16 Aug 2013 14:34:51 -0700 Subject: Add new git_signature_default API using config This adds a new API for creating a signature that uses the config to look up "user.name" and "user.email". --- include/git2/signature.h | 13 +++++++++++++ src/signature.c | 19 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/include/git2/signature.h b/include/git2/signature.h index 00d19de66..2fa46d032 100644 --- a/include/git2/signature.h +++ b/include/git2/signature.h @@ -48,6 +48,19 @@ GIT_EXTERN(int) git_signature_new(git_signature **out, const char *name, const c */ GIT_EXTERN(int) git_signature_now(git_signature **out, const char *name, const char *email); +/** + * Create a new action signature with default user and now timestamp. + * + * This looks up the user.name and user.email from the configuration and + * uses the current time as the timestamp, and creates a new signature + * based on that information. It will return GIT_ENOTFOUND if either the + * user.name or user.email are not set. + * + * @param out new signature + * @param repo repository pointer + * @return 0 on success, GIT_ENOTFOUND if config is missing, or error code + */ +GIT_EXTERN(int) git_signature_default(git_signature **out, git_repository *repo); /** * Create a copy of an existing signature. All internal strings are also diff --git a/src/signature.c b/src/signature.c index 0a34ccfaa..52ca2b375 100644 --- a/src/signature.c +++ b/src/signature.c @@ -74,7 +74,7 @@ int git_signature_new(git_signature **sig_out, const char *name, const char *ema git_signature_free(p); return signature_error("Signature cannot have an empty name"); } - + p->when.time = time; p->when.offset = offset; @@ -129,6 +129,23 @@ int git_signature_now(git_signature **sig_out, const char *name, const char *ema return 0; } +int git_signature_default(git_signature **out, git_repository *repo) +{ + int error; + git_config *cfg; + const char *user_name, *user_email; + + if ((error = git_repository_config(&cfg, repo)) < 0) + return error; + + if (!(error = git_config_get_string(&user_name, cfg, "user.name")) && + !(error = git_config_get_string(&user_email, cfg, "user.email"))) + error = git_signature_now(out, user_name, user_email); + + git_config_free(cfg); + return error; +} + int git_signature__parse(git_signature *sig, const char **buffer_out, const char *buffer_end, const char *header, char ender) { -- cgit v1.2.1 From 579d87c5d352232671dcfda43ec153883c01fc6f Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 16 Aug 2013 14:48:14 -0700 Subject: New test that inits repo and make commit --- tests-clar/repo/init.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index 8cf73795f..02ea676fb 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -530,3 +530,52 @@ void test_repo_init__can_reinit_an_initialized_repository(void) git_repository_free(reinit); } + +void test_repo_init__init_with_initial_commit(void) +{ + git_index *index; + + cl_set_cleanup(&cleanup_repository, "committed"); + + /* Initialize the repository */ + cl_git_pass(git_repository_init(&_repo, "committed", 0)); + + /* Init will be automatically created when requested for a new repo */ + cl_git_pass(git_repository_index(&index, _repo)); + + /* Create a file so we can commit it + * + * If you are writing code outside the test suite, you can create this + * file any way that you like, such as: + * FILE *fp = fopen("committed/file.txt", "w"); + * fputs("some stuff\n", fp); + * fclose(fp); + * We like to use the help functions because they do error detection + * in a way that's easily compatible with our test suite. + */ + cl_git_mkfile("committed/file.txt", "some stuff\n"); + + /* Add file to the index */ + cl_git_pass(git_index_add_bypath(index, "file.txt")); + cl_git_pass(git_index_write(index)); + + /* Create a commit with the new contents of the index */ + { + git_signature *sig; + git_oid tree_id, commit_id; + git_tree *tree; + + cl_git_pass(git_signature_default(&sig, _repo)); + cl_git_pass(git_index_write_tree(&tree_id, index)); + cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id)); + + cl_git_pass(git_commit_create_v( + &commit_id, _repo, "HEAD", sig, sig, + NULL, "First", tree, 0)); + + git_tree_free(tree); + git_signature_free(sig); + } + + git_index_free(index); +} -- cgit v1.2.1 From 944c1589c25e011537dd9162265cedeab363a103 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 16 Aug 2013 14:49:38 -0700 Subject: Add example like "git init" --- examples/Makefile | 2 +- examples/init.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 examples/init.c diff --git a/examples/Makefile b/examples/Makefile index 95e46f0c6..d53ed8241 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -3,7 +3,7 @@ CC = gcc CFLAGS = -g -I../include -I../src -Wall -Wextra -Wmissing-prototypes -Wno-missing-field-initializers LFLAGS = -L../build -lgit2 -lz -APPS = general showindex diff rev-list cat-file status log rev-parse +APPS = general showindex diff rev-list cat-file status log rev-parse init all: $(APPS) diff --git a/examples/init.c b/examples/init.c new file mode 100644 index 000000000..76b037a88 --- /dev/null +++ b/examples/init.c @@ -0,0 +1,217 @@ +#include +#include +#include +#include +#include + +static void fail(const char *msg, const char *arg) +{ + if (arg) + fprintf(stderr, "%s %s\n", msg, arg); + else + fprintf(stderr, "%s\n", msg); + exit(1); +} + +static void usage(const char *error, const char *arg) +{ + fprintf(stderr, "error: %s '%s'\n", error, arg); + fprintf(stderr, "usage: init [-q | --quiet] [--bare] " + "[--template=] [--shared[=perms]] \n"); + exit(1); +} + +static size_t is_prefixed(const char *arg, const char *pfx) +{ + size_t len = strlen(pfx); + return !strncmp(arg, pfx, len) ? len : 0; +} + +static uint32_t parse_shared(const char *shared) +{ + if (!strcmp(shared, "false") || !strcmp(shared, "umask")) + return GIT_REPOSITORY_INIT_SHARED_UMASK; + + else if (!strcmp(shared, "true") || !strcmp(shared, "group")) + return GIT_REPOSITORY_INIT_SHARED_GROUP; + + else if (!strcmp(shared, "all") || !strcmp(shared, "world") || + !strcmp(shared, "everybody")) + return GIT_REPOSITORY_INIT_SHARED_ALL; + + else if (shared[0] == '0') { + long val; + char *end = NULL; + val = strtol(shared + 1, &end, 8); + if (end == shared + 1 || *end != 0) + usage("invalid octal value for --shared", shared); + return (uint32_t)val; + } + + else + usage("unknown value for --shared", shared); + + return 0; +} + +static void create_initial_commit(git_repository *repo); + +int main(int argc, char *argv[]) +{ + git_repository *repo = NULL; + int no_options = 1, quiet = 0, bare = 0, initial_commit = 0, i; + uint32_t shared = GIT_REPOSITORY_INIT_SHARED_UMASK; + const char *template = NULL, *gitdir = NULL, *dir = NULL; + size_t pfxlen; + + git_threads_init(); + + /* Process arguments */ + + for (i = 1; i < argc; ++i) { + char *a = argv[i]; + + if (a[0] == '-') + no_options = 0; + + if (a[0] != '-') { + if (dir != NULL) + usage("extra argument", a); + dir = a; + } + else if (!strcmp(a, "-q") || !strcmp(a, "--quiet")) + quiet = 1; + else if (!strcmp(a, "--bare")) + bare = 1; + else if ((pfxlen = is_prefixed(a, "--template=")) > 0) + template = a + pfxlen; + else if (!strcmp(a, "--separate-git-dir")) + gitdir = argv[++i]; + else if ((pfxlen = is_prefixed(a, "--separate-git-dir=")) > 0) + gitdir = a + pfxlen; + else if (!strcmp(a, "--shared")) + shared = GIT_REPOSITORY_INIT_SHARED_GROUP; + else if ((pfxlen = is_prefixed(a, "--shared=")) > 0) + shared = parse_shared(a + pfxlen); + else if (!strcmp(a, "--initial-commit")) + initial_commit = 1; + else + usage("unknown option", a); + } + + if (!dir) + usage("must specify directory to init", NULL); + + /* Initialize repository */ + + if (no_options) { + /* No options were specified, so let's demonstrate the default + * simple case of git_repository_init() API usage... + */ + + if (git_repository_init(&repo, dir, 0) < 0) + fail("Could not initialize repository", dir); + } + else { + /* Some command line options were specified, so we'll use the + * extended init API to handle them + */ + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + + if (bare) + opts.flags |= GIT_REPOSITORY_INIT_BARE; + + if (template) { + opts.flags |= GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; + opts.template_path = template; + } + + if (gitdir) { + /* if you specified a separate git directory, then initialize + * the repository at that path and use the second path as the + * working directory of the repository (with a git-link file) + */ + opts.workdir_path = dir; + dir = gitdir; + } + + if (shared != 0) + opts.mode = shared; + + if (git_repository_init_ext(&repo, dir, &opts) < 0) + fail("Could not initialize repository", dir); + } + + if (!quiet) { + if (bare || gitdir) + dir = git_repository_path(repo); + else + dir = git_repository_workdir(repo); + + printf("Initialized empty Git repository in %s\n", dir); + } + + /* As an extension to the basic "git init" command, this example + * gives the option to create an empty initial commit. This is + * mostly to demonstrate what it takes to do that, but also some + * people like to have that empty base commit in their repo. + */ + if (initial_commit) { + create_initial_commit(repo); + printf("Created empty initial commit\n"); + } + + git_repository_free(repo); + git_threads_shutdown(); + + return 0; +} + +static void create_initial_commit(git_repository *repo) +{ + git_signature *sig; + git_index *index; + git_oid tree_id, commit_id; + git_tree *tree; + + /* First use the config to initialize a commit signature for the user */ + + if (git_signature_default(&sig, repo) < 0) + fail("Unable to create a commit signature.", + "Perhaps 'user.name' and 'user.email' are not set"); + + /* Now let's create an empty tree for this commit */ + + if (git_repository_index(&index, repo) < 0) + fail("Could not open repository index", NULL); + + /* Outside of this example, you could call git_index_add_bypath() + * here to put actual files into the index. For our purposes, we'll + * leave it empty for now. + */ + + if (git_index_write_tree(&tree_id, index) < 0) + fail("Unable to write initial tree from index", NULL); + + git_index_free(index); + + if (git_tree_lookup(&tree, repo, &tree_id) < 0) + fail("Could not look up initial tree", NULL); + + /* Ready to create the initial commit + * + * Normally creating a commit would involve looking up the current + * HEAD commit and making that be the parent of the initial commit, + * but here this is the first commit so there will be no parent. + */ + + if (git_commit_create_v( + &commit_id, repo, "HEAD", sig, sig, + NULL, "Initial commit", tree, 0) < 0) + fail("Could not create the initial commit", NULL); + + /* Clean up so we don't leak memory */ + + git_tree_free(tree); + git_signature_free(sig); +} -- cgit v1.2.1 From 0ea41445f4028460aefcd55cb37f10870ea9311c Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 16 Aug 2013 15:03:15 -0700 Subject: Improve isolation of new test from user environs --- examples/init.c | 28 ++++++++++++++++++++++++++++ tests-clar/repo/init.c | 11 +++++++++++ 2 files changed, 39 insertions(+) diff --git a/examples/init.c b/examples/init.c index 76b037a88..4a379c6e3 100644 --- a/examples/init.c +++ b/examples/init.c @@ -1,9 +1,27 @@ +/* + * This is a sample program that is similar to "git init". See the + * documentation for that (try "git help init") to understand what this + * program is emulating. + * + * This demonstrates using the libgit2 APIs to initialize a new repository. + * + * This also contains a special additional option that regular "git init" + * does not support which is "--initial-commit" to make a first empty commit. + * That is demonstrated in the "create_initial_commit" helper function. + * + * 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 #include #include #include #include +/* not actually good error handling */ static void fail(const char *msg, const char *arg) { if (arg) @@ -21,12 +39,14 @@ static void usage(const char *error, const char *arg) exit(1); } +/* simple string prefix test used in argument parsing */ static size_t is_prefixed(const char *arg, const char *pfx) { size_t len = strlen(pfx); return !strncmp(arg, pfx, len) ? len : 0; } +/* parse the tail of the --shared= argument */ static uint32_t parse_shared(const char *shared) { if (!strcmp(shared, "false") || !strcmp(shared, "umask")) @@ -54,8 +74,10 @@ static uint32_t parse_shared(const char *shared) return 0; } +/* forward declaration of helper to make an empty parent-less commit */ static void create_initial_commit(git_repository *repo); + int main(int argc, char *argv[]) { git_repository *repo = NULL; @@ -142,6 +164,8 @@ int main(int argc, char *argv[]) fail("Could not initialize repository", dir); } + /* Print a message to stdout like "git init" does */ + if (!quiet) { if (bare || gitdir) dir = git_repository_path(repo); @@ -167,6 +191,10 @@ int main(int argc, char *argv[]) return 0; } +/* Unlike regular "git init", this example shows how to create an initial + * empty commit in the repository. This is the helper function that does + * that. + */ static void create_initial_commit(git_repository *repo) { git_signature *sig; diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index 02ea676fb..5076184b8 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -559,6 +559,17 @@ void test_repo_init__init_with_initial_commit(void) cl_git_pass(git_index_add_bypath(index, "file.txt")); cl_git_pass(git_index_write(index)); + /* Make sure we're ready to use git_signature_default :-) */ + { + git_config *cfg, *local; + cl_git_pass(git_repository_config(&cfg, _repo)); + cl_git_pass(git_config_open_level(&local, cfg, GIT_CONFIG_LEVEL_LOCAL)); + cl_git_pass(git_config_set_string(local, "user.name", "Test User")); + cl_git_pass(git_config_set_string(local, "user.email", "t@example.com")); + git_config_free(local); + git_config_free(cfg); + } + /* Create a commit with the new contents of the index */ { git_signature *sig; -- cgit v1.2.1 From fe0c6d4e712fa1bb072b8a847783bad47f3e91eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 17 Aug 2013 01:41:08 +0200 Subject: odb: make it clearer that the id is calculated in the frontend The frontend is in charge of calculating the id of the objects. Thus the backends should treat it as a read-only value. The positioning in the function signature made it seem as though it was an output parameter. Make the id const and move it from the front to behind the subject (backend or stream). --- include/git2/odb_backend.h | 2 +- include/git2/sys/odb_backend.h | 6 +----- src/odb.c | 8 ++++---- src/odb_loose.c | 4 ++-- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index d004238a4..5696ee07d 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -75,7 +75,7 @@ struct git_odb_stream { int (*read)(git_odb_stream *stream, char *buffer, size_t len); int (*write)(git_odb_stream *stream, const char *buffer, size_t len); - int (*finalize_write)(git_oid *oid_p, git_odb_stream *stream); + int (*finalize_write)(git_odb_stream *stream, const git_oid *oid); void (*free)(git_odb_stream *stream); }; diff --git a/include/git2/sys/odb_backend.h b/include/git2/sys/odb_backend.h index 3cd2734c0..2d06613d2 100644 --- a/include/git2/sys/odb_backend.h +++ b/include/git2/sys/odb_backend.h @@ -48,12 +48,8 @@ struct git_odb_backend { int (* read_header)( size_t *, git_otype *, git_odb_backend *, const git_oid *); - /* The writer may assume that the object - * has already been hashed and is passed - * in the first parameter. - */ int (* write)( - git_oid *, git_odb_backend *, const void *, size_t, git_otype); + git_odb_backend *, const git_oid *, const void *, size_t, git_otype); int (* writestream)( git_odb_stream **, git_odb_backend *, size_t, git_otype); diff --git a/src/odb.c b/src/odb.c index b7f64dfc9..d2be60f97 100644 --- a/src/odb.c +++ b/src/odb.c @@ -291,10 +291,10 @@ typedef struct { git_otype type; } fake_wstream; -static int fake_wstream__fwrite(git_oid *oid, git_odb_stream *_stream) +static int fake_wstream__fwrite(git_odb_stream *_stream, const git_oid *oid) { fake_wstream *stream = (fake_wstream *)_stream; - return _stream->backend->write(oid, _stream->backend, stream->buffer, stream->size, stream->type); + return _stream->backend->write(_stream->backend, oid, stream->buffer, stream->size, stream->type); } static int fake_wstream__write(git_odb_stream *_stream, const char *data, size_t len) @@ -851,7 +851,7 @@ int git_odb_write( continue; if (b->write != NULL) - error = b->write(oid, b, data, len, type); + error = b->write(b, oid, data, len, type); } if (!error || error == GIT_PASSTHROUGH) @@ -931,7 +931,7 @@ int git_odb_stream_write(git_odb_stream *stream, const char *buffer, size_t len) int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream) { git_hash_final(out, stream->hash_ctx); - return stream->finalize_write(out, stream); + return stream->finalize_write(stream, out); } int git_odb_stream_read(git_odb_stream *stream, char *buffer, size_t len) diff --git a/src/odb_loose.c b/src/odb_loose.c index 35f53fb7d..d1ca18edb 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -769,7 +769,7 @@ static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb return state.cb_error ? state.cb_error : error; } -static int loose_backend__stream_fwrite(git_oid *oid, git_odb_stream *_stream) +static int loose_backend__stream_fwrite(git_odb_stream *_stream, const git_oid *oid) { loose_writestream *stream = (loose_writestream *)_stream; loose_backend *backend = (loose_backend *)_stream->backend; @@ -850,7 +850,7 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_ return !stream ? -1 : 0; } -static int loose_backend__write(git_oid *oid, git_odb_backend *_backend, const void *data, size_t len, git_otype type) +static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_otype type) { int error = 0, header_len; git_buf final_path = GIT_BUF_INIT; -- cgit v1.2.1 From 7a3764bee92456e5ee2ed41be9abb0ffb4165eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 17 Aug 2013 01:55:52 +0200 Subject: odb: document git_odb_stream Clarify the role of each function and in particular mention that there is no need for the backend or stream to worry about the object's id, as it will be given when `finalize_write` is called. --- include/git2/odb_backend.h | 26 +++++++++++++++++++++++++- include/git2/sys/odb_backend.h | 4 ++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index 5696ee07d..dca499583 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -67,15 +67,39 @@ typedef enum { typedef struct git_hash_ctx git_hash_ctx; -/** A stream to read/write from a backend */ +/** + * A stream to read/write from a backend. + * + * This represents a stream of data being written to or read from a + * backend. When writing, the frontend functions take care of + * calculating the object's id and all `finalize_write` needs to do is + * store the object with the id it is passed. + */ struct git_odb_stream { git_odb_backend *backend; unsigned int mode; git_hash_ctx *hash_ctx; + /** + * Write at most `len` bytes into `buffer` and advance the + * stream. + */ int (*read)(git_odb_stream *stream, char *buffer, size_t len); + + /** + * Write `len` bytes from `buffer` into the stream. + */ int (*write)(git_odb_stream *stream, const char *buffer, size_t len); + + /** + * Store the contents of the stream as an object with the id + * specified in `oid`. + */ int (*finalize_write)(git_odb_stream *stream, const git_oid *oid); + + /** + * Free the stream's memory. + */ void (*free)(git_odb_stream *stream); }; diff --git a/include/git2/sys/odb_backend.h b/include/git2/sys/odb_backend.h index 2d06613d2..31ffe1c33 100644 --- a/include/git2/sys/odb_backend.h +++ b/include/git2/sys/odb_backend.h @@ -48,6 +48,10 @@ struct git_odb_backend { int (* read_header)( size_t *, git_otype *, git_odb_backend *, const git_oid *); + /** + * Write an object into the backend. The id of the object has + * already been calculated and is passed in. + */ int (* write)( git_odb_backend *, const git_oid *, const void *, size_t, git_otype); -- cgit v1.2.1 From 090a07d29548ce69034b4be6ba043014226893c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 17 Aug 2013 02:12:04 +0200 Subject: odb: avoid hashing twice in and edge case If none of the backends support direct writes and we must stream the whole file, we already know what the object's id should be; so use the stream's functions directly, bypassing the frontend's hashing and overwriting of our existing id. --- src/odb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/odb.c b/src/odb.c index d2be60f97..21b46bf56 100644 --- a/src/odb.c +++ b/src/odb.c @@ -864,8 +864,8 @@ int git_odb_write( if ((error = git_odb_open_wstream(&stream, db, len, type)) != 0) return error; - git_odb_stream_write(stream, data, len); - error = git_odb_stream_finalize_write(oid, stream); + stream->write(stream, data, len); + error = stream->finalize_write(stream, oid); git_odb_stream_free(stream); return error; -- cgit v1.2.1 From d19dd9cf73f1ebec135faf9fd6e702b09d3ee723 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sun, 18 Aug 2013 23:38:51 +0200 Subject: odb: Straighten oid prefix handling --- src/odb_loose.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/odb_loose.c b/src/odb_loose.c index 76ed8e232..90e258793 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -641,10 +641,12 @@ static int loose_backend__read_prefix( { int error = 0; + assert(len <= GIT_OID_HEXSZ); + if (len < GIT_OID_MINPREFIXLEN) error = git_odb__error_ambiguous("prefix length too short"); - else if (len >= GIT_OID_HEXSZ) { + else if (len == GIT_OID_HEXSZ) { /* We can fall back to regular read method */ error = loose_backend__read(buffer_p, len_p, type_p, backend, short_oid); if (!error) -- cgit v1.2.1 From 90a8ad63e3c861f15ad61379ed1355fd036ca6a7 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Mon, 19 Aug 2013 00:18:44 +0200 Subject: ci: Make Valgrind run on Travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 71f8406fc..151060fb4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ script: # Run Tests after_success: - sudo apt-get -qq install valgrind - - valgrind --leak-check=full --show-reachable=yes --suppressions=../libgit2_clar.supp ./libgit2_clar -ionline + - valgrind --leak-check=full --show-reachable=yes --suppressions=./libgit2_clar.supp _build/libgit2_clar -ionline # Only watch the development branch branches: -- cgit v1.2.1 From 3d2768747548ec24b58ebdaa012a6b757e65f5a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 19 Aug 2013 10:30:44 +0200 Subject: index: report when it's locked Report the index being locked with its own error code in order to be able to differentiate, as a locked index is typically the result of a crashed process or concurrent access, both of which often require user intervention to fix. --- include/git2/errors.h | 1 + src/filebuf.c | 10 +++++----- src/fileops.c | 2 +- src/index.c | 6 +++++- tests-clar/index/tests.c | 25 +++++++++++++++++++++++++ 5 files changed, 37 insertions(+), 7 deletions(-) diff --git a/include/git2/errors.h b/include/git2/errors.h index 2032a436a..0f0bddf07 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -32,6 +32,7 @@ typedef enum { GIT_ENONFASTFORWARD = -11, GIT_EINVALIDSPEC = -12, GIT_EMERGECONFLICT = -13, + GIT_ELOCKED = -14, GIT_PASSTHROUGH = -30, GIT_ITEROVER = -31, diff --git a/src/filebuf.c b/src/filebuf.c index 246ae34e7..714a32395 100644 --- a/src/filebuf.c +++ b/src/filebuf.c @@ -53,7 +53,7 @@ static int lock_file(git_filebuf *file, int flags) giterr_clear(); /* actual OS error code just confuses */ giterr_set(GITERR_OS, "Failed to lock file '%s' for writing", file->path_lock); - return -1; + return GIT_ELOCKED; } } @@ -66,7 +66,7 @@ static int lock_file(git_filebuf *file, int flags) } if (file->fd < 0) - return -1; + return file->fd; file->fd_is_open = true; @@ -197,7 +197,7 @@ static int write_deflate(git_filebuf *file, void *source, size_t len) int git_filebuf_open(git_filebuf *file, const char *path, int flags) { - int compression; + int compression, error = -1; size_t path_len; /* opening an already open buffer is a programming error; @@ -282,7 +282,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags) memcpy(file->path_lock + path_len, GIT_FILELOCK_EXTENSION, GIT_FILELOCK_EXTLENGTH); /* open the file for locking */ - if (lock_file(file, flags) < 0) + if ((error = lock_file(file, flags)) < 0) goto cleanup; } @@ -290,7 +290,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags) cleanup: git_filebuf_cleanup(file); - return -1; + return error; } int git_filebuf_hash(git_oid *oid, git_filebuf *file) diff --git a/src/fileops.c b/src/fileops.c index 3a5a53074..76119e02e 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -70,7 +70,7 @@ int git_futils_creat_locked(const char *path, const mode_t mode) if (fd < 0) { giterr_set(GITERR_OS, "Failed to create locked file '%s'", path); - return -1; + return errno == EEXIST ? GIT_ELOCKED : -1; } return fd; diff --git a/src/index.c b/src/index.c index 5f53f1e2f..17e43903f 100644 --- a/src/index.c +++ b/src/index.c @@ -498,8 +498,12 @@ int git_index_write(git_index *index) git_vector_sort(&index->reuc); if ((error = git_filebuf_open( - &file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS)) < 0) + &file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS)) < 0) { + if (error == GIT_ELOCKED) + giterr_set(GITERR_INDEX, "The index is locked. This might be due to a concurrrent or crashed process"); + return error; + } if ((error = write_index(index, &file)) < 0) { git_filebuf_cleanup(&file); diff --git a/tests-clar/index/tests.c b/tests-clar/index/tests.c index 1bc5e6a07..9090d4d8a 100644 --- a/tests-clar/index/tests.c +++ b/tests-clar/index/tests.c @@ -459,3 +459,28 @@ void test_index_tests__preserves_case(void) git_repository_free(repo); } +void test_index_tests__elocked(void) +{ + git_repository *repo; + git_index *index; + git_filebuf file = GIT_FILEBUF_INIT; + const git_error *err; + int error; + + cl_set_cleanup(&cleanup_myrepo, NULL); + + cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); + cl_git_pass(git_repository_index(&index, repo)); + + /* Lock the index file so we fail to lock it */ + cl_git_pass(git_filebuf_open(&file, index->index_file_path, 0)); + error = git_index_write(index); + cl_assert_equal_i(GIT_ELOCKED, error); + + err = giterr_last(); + cl_assert_equal_i(err->klass, GITERR_INDEX); + + git_filebuf_cleanup(&file); + git_index_free(index); + git_repository_free(repo); +} -- cgit v1.2.1 From 6818080871db227c2586a102306832b41ea1c0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 19 Aug 2013 10:50:28 +0200 Subject: travis: really fail if the tests fail When implementing the ssh testing, the move to the script made it so the first test suite's exit code was ignored. Check whether the main tests fail and exit with an error in that case. --- script/cibuild.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/script/cibuild.sh b/script/cibuild.sh index 722b3349d..2b8d1af08 100755 --- a/script/cibuild.sh +++ b/script/cibuild.sh @@ -11,6 +11,11 @@ cd _build cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS cmake --build . --target install ctest -V . +ecode=$? + +if [ $ecode -ne 0 ]; then + exit $ecode +fi # Now that we've tested the raw git protocol, let's set up ssh to we # can do the push tests over it -- cgit v1.2.1 From 6d69fbce31c391c7a7739f8156b0d63f399c53bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 19 Aug 2013 13:04:05 +0200 Subject: Revparse does not handle refspecs --- src/revparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/revparse.c b/src/revparse.c index b84f0037f..329b96dbc 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -129,7 +129,7 @@ static int revparse_lookup_object( if (error < 0 && error != GIT_ENOTFOUND) return error; - giterr_set(GITERR_REFERENCE, "Refspec '%s' not found.", spec); + giterr_set(GITERR_REFERENCE, "Revspec '%s' not found.", spec); return GIT_ENOTFOUND; } -- cgit v1.2.1 From 67c177ef26f25f4f7e5497393d075dde0f1b9415 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 19 Aug 2013 11:42:50 -0500 Subject: Don't expose git_hash_ctx since it's internal And doing so makes the mingw build choke. --- include/git2/odb_backend.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index dca499583..7b3c6a356 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -65,8 +65,6 @@ typedef enum { GIT_STREAM_RW = (GIT_STREAM_RDONLY | GIT_STREAM_WRONLY), } git_odb_stream_t; -typedef struct git_hash_ctx git_hash_ctx; - /** * A stream to read/write from a backend. * @@ -78,7 +76,7 @@ typedef struct git_hash_ctx git_hash_ctx; struct git_odb_stream { git_odb_backend *backend; unsigned int mode; - git_hash_ctx *hash_ctx; + void *hash_ctx; /** * Write at most `len` bytes into `buffer` and advance the -- cgit v1.2.1 From 5875e8d21a1f2db8849e7babe7f0e2c7aee5a2a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 19 Aug 2013 18:50:03 +0200 Subject: travis: exit on failure for anything related to building --- script/cibuild.sh | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/script/cibuild.sh b/script/cibuild.sh index 2b8d1af08..aa4fa47aa 100755 --- a/script/cibuild.sh +++ b/script/cibuild.sh @@ -8,14 +8,9 @@ export GITTEST_REMOTE_URL="git://localhost/test.git" mkdir _build cd _build -cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS -cmake --build . --target install -ctest -V . -ecode=$? - -if [ $ecode -ne 0 ]; then - exit $ecode -fi +cmake .. -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS || exit $? +cmake --build . --target install || exit $? +ctest -V . || exit $? # Now that we've tested the raw git protocol, let's set up ssh to we # can do the push tests over it -- cgit v1.2.1 From 86967cc579ee9e8c1a209a76c12605dd24dcf6cf Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 19 Aug 2013 16:44:17 -0500 Subject: Use time(2) to get the time We didn't use the added precision in gettimeofday, so remove it. This prevents us from having an unnecessary reimplementation on win32. --- src/date.c | 14 +++++++------- src/posix.h | 4 ---- src/win32/posix_w32.c | 50 -------------------------------------------------- 3 files changed, 7 insertions(+), 61 deletions(-) diff --git a/src/date.c b/src/date.c index 48841e4f9..7849c2f02 100644 --- a/src/date.c +++ b/src/date.c @@ -823,15 +823,13 @@ static void pending_number(struct tm *tm, int *num) } static git_time_t approxidate_str(const char *date, - const struct timeval *tv, - int *error_ret) + time_t time_sec, + int *error_ret) { int number = 0; int touched = 0; struct tm tm = {0}, now; - time_t time_sec; - time_sec = tv->tv_sec; p_localtime_r(&time_sec, &tm); now = tm; @@ -861,7 +859,7 @@ static git_time_t approxidate_str(const char *date, int git__date_parse(git_time_t *out, const char *date) { - struct timeval tv; + time_t time_sec; git_time_t timestamp; int offset, error_ret=0; @@ -870,7 +868,9 @@ int git__date_parse(git_time_t *out, const char *date) return 0; } - p_gettimeofday(&tv, NULL); - *out = approxidate_str(date, &tv, &error_ret); + if (time(&time_sec) == -1) + return -1; + + *out = approxidate_str(date, time_sec, &error_ret); return error_ret; } diff --git a/src/posix.h b/src/posix.h index ea97a1349..de2aa0b73 100644 --- a/src/posix.h +++ b/src/posix.h @@ -71,16 +71,12 @@ typedef int GIT_SOCKET; #define p_localtime_r localtime_r #define p_gmtime_r gmtime_r -#define p_gettimeofday gettimeofday #else typedef SOCKET GIT_SOCKET; -struct timezone; extern struct tm * p_localtime_r (const time_t *timer, struct tm *result); extern struct tm * p_gmtime_r (const time_t *timer, struct tm *result); -extern int p_gettimeofday(struct timeval *tv, struct timezone *tz); - #endif diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 57ebaa12e..087adcce3 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -518,56 +518,6 @@ p_gmtime_r (const time_t *timer, struct tm *result) return result; } -#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 -#else -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL -#endif - -#ifndef _TIMEZONE_DEFINED -#define _TIMEZONE_DEFINED -struct timezone -{ - int tz_minuteswest; /* minutes W of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; -#endif - -int p_gettimeofday(struct timeval *tv, struct timezone *tz) -{ - FILETIME ft; - unsigned __int64 tmpres = 0; - static int tzflag; - - if (NULL != tv) - { - GetSystemTimeAsFileTime(&ft); - - tmpres |= ft.dwHighDateTime; - tmpres <<= 32; - tmpres |= ft.dwLowDateTime; - - /*converting file time to unix epoch*/ - tmpres /= 10; /*convert into microseconds*/ - tmpres -= DELTA_EPOCH_IN_MICROSECS; - tv->tv_sec = (long)(tmpres / 1000000UL); - tv->tv_usec = (long)(tmpres % 1000000UL); - } - - if (NULL != tz) - { - if (!tzflag) - { - _tzset(); - tzflag++; - } - tz->tz_minuteswest = _timezone / 60; - tz->tz_dsttime = _daylight; - } - - return 0; -} - int p_inet_pton(int af, const char* src, void* dst) { union { -- cgit v1.2.1 From 238b761491bee6b03f95fca9037b8dff8cced7e7 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 16 Aug 2013 13:31:24 -0500 Subject: Fix p_inet_pton on windows p_inet_pton on Windows should set errno properly for callers. Rewrite p_inet_pton to handle error cases correctly and add test cases to exercise this function. --- src/win32/posix.h | 7 +++++ src/win32/posix_w32.c | 60 +++++++++++++++++------------------ tests-clar/core/posix.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 32 deletions(-) create mode 100644 tests-clar/core/posix.c diff --git a/src/win32/posix.h b/src/win32/posix.h index 5f924a026..24cba23e0 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -12,6 +12,13 @@ #include "utf-conv.h" #include "dir.h" +/* define some standard errnos that the runtime may be missing. for example, + * mingw lacks EAFNOSUPPORT. */ + +#ifndef EAFNOSUPPORT +# define EAFNOSUPPORT (INT_MAX-1) +#endif + GIT_INLINE(int) p_link(const char *old, const char *new) { GIT_UNUSED(old); diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 087adcce3..2f490529c 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -518,44 +518,40 @@ p_gmtime_r (const time_t *timer, struct tm *result) return result; } -int p_inet_pton(int af, const char* src, void* dst) +int p_inet_pton(int af, const char *src, void *dst) { - union { - struct sockaddr_in6 sin6; - struct sockaddr_in sin; - } sa; - int srcsize; + struct sockaddr_storage sin; + void *addr; + int sin_len = sizeof(struct sockaddr_storage), addr_len; + int error = 0; - switch(af) - { - case AF_INET: - sa.sin.sin_family = AF_INET; - srcsize = (int)sizeof(sa.sin); - break; - case AF_INET6: - sa.sin6.sin6_family = AF_INET6; - srcsize = (int)sizeof(sa.sin6); - break; - default: - errno = WSAEPFNOSUPPORT; - return -1; + if (af == AF_INET) { + addr = &((struct sockaddr_in *)&sin)->sin_addr; + addr_len = sizeof(struct in_addr); + } else if (af == AF_INET6) { + addr = &((struct sockaddr_in6 *)&sin)->sin6_addr; + addr_len = sizeof(struct in6_addr); + } else { + errno = EAFNOSUPPORT; + return -1; } - if (WSAStringToAddress((LPSTR)src, af, NULL, (struct sockaddr *) &sa, &srcsize) != 0) - { - errno = WSAGetLastError(); - return -1; + if ((error = WSAStringToAddressA((LPSTR)src, af, NULL, (LPSOCKADDR)&sin, &sin_len)) == 0) { + memcpy(dst, addr, addr_len); + return 1; } - switch(af) - { - case AF_INET: - memcpy(dst, &sa.sin.sin_addr, sizeof(sa.sin.sin_addr)); - break; - case AF_INET6: - memcpy(dst, &sa.sin6.sin6_addr, sizeof(sa.sin6.sin6_addr)); - break; + switch(WSAGetLastError()) { + case WSAEINVAL: + return 0; + case WSAEFAULT: + errno = ENOSPC; + return -1; + case WSA_NOT_ENOUGH_MEMORY: + errno = ENOMEM; + return -1; } - return 1; + errno = EINVAL; + return -1; } diff --git a/tests-clar/core/posix.c b/tests-clar/core/posix.c new file mode 100644 index 000000000..0d9443f92 --- /dev/null +++ b/tests-clar/core/posix.c @@ -0,0 +1,84 @@ +#ifndef _WIN32 +# include +#else +# include +# ifdef _MSC_VER +# pragma comment(lib, "ws2_32") +# endif +#endif + +#include "clar_libgit2.h" +#include "posix.h" + +void test_core_posix__initialize(void) +{ +#ifdef GIT_WIN32 + /* on win32, the WSA context needs to be initialized + * before any socket calls can be performed */ + WSADATA wsd; + + cl_git_pass(WSAStartup(MAKEWORD(2,2), &wsd)); + cl_assert(LOBYTE(wsd.wVersion) == 2 && HIBYTE(wsd.wVersion) == 2); +#endif +} + +void test_core_posix__inet_pton(void) +{ + struct in_addr addr; + struct in6_addr addr6; + size_t i; + + struct in_addr_data { + const char *p; + const uint8_t n[4]; + }; + + struct in6_addr_data { + const char *p; + const uint8_t n[16]; + }; + + static struct in_addr_data in_addr_data[] = { + { "0.0.0.0", { 0, 0, 0, 0 } }, + { "10.42.101.8", { 10, 42, 101, 8 } }, + { "127.0.0.1", { 127, 0, 0, 1 } }, + { "140.177.10.12", { 140, 177, 10, 12 } }, + { "204.232.175.90", { 204, 232, 175, 90 } }, + { "255.255.255.255", { 255, 255, 255, 255 } }, + }; + + static struct in6_addr_data in6_addr_data[] = { + { "::", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { "::1", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, + { "0:0:0:0:0:0:0:1", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, + { "2001:db8:8714:3a90::12", { 0x20, 0x01, 0x0d, 0xb8, 0x87, 0x14, 0x3a, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12 } }, + { "fe80::f8ba:c2d6:86be:3645", { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xba, 0xc2, 0xd6, 0x86, 0xbe, 0x36, 0x45 } }, + { "::ffff:204.152.189.116", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0x98, 0xbd, 0x74 } }, + }; + + /* Test some ipv4 addresses */ + for (i = 0; i < 6; i++) { + cl_assert(p_inet_pton(AF_INET, in_addr_data[i].p, &addr) == 1); + cl_assert(memcmp(&addr, in_addr_data[i].n, sizeof(struct in_addr)) == 0); + } + + /* Test some ipv6 addresses */ + for (i = 0; i < 6; i++) { + cl_assert(p_inet_pton(AF_INET6, in6_addr_data[i].p, &addr6) == 1); + cl_assert(memcmp(&addr6, in6_addr_data[i].n, sizeof(struct in6_addr)) == 0); + } + + /* Test some invalid strings */ + cl_assert(p_inet_pton(AF_INET, "", &addr) == 0); + cl_assert(p_inet_pton(AF_INET, "foo", &addr) == 0); + cl_assert(p_inet_pton(AF_INET, " 127.0.0.1", &addr) == 0); + cl_assert(p_inet_pton(AF_INET, "bar", &addr) == 0); + 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_assert_equal_i(EAFNOSUPPORT, errno); + + cl_git_fail(p_inet_pton(5, "315.124", NULL)); /* AF_CHAOS */ + cl_assert_equal_i(EAFNOSUPPORT, errno); +} -- cgit v1.2.1 From 8255b497b625735acab527f15617daa19f796165 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 19 Aug 2013 17:49:12 -0500 Subject: Quiet down some warnings --- src/win32/mingw-compat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32/mingw-compat.h b/src/win32/mingw-compat.h index 97b1cb71b..fe0abfb54 100644 --- a/src/win32/mingw-compat.h +++ b/src/win32/mingw-compat.h @@ -21,7 +21,7 @@ GIT_INLINE(size_t) p_strnlen(const char *s, size_t maxlen) { const char *end = memchr(s, 0, maxlen); - return end ? (end - s) : maxlen; + return end ? (size_t)(end - s) : maxlen; } #endif -- cgit v1.2.1 From c0b01b7572232bd6c0cd848e9b92ed8a8d678bcf Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 19 Aug 2013 18:46:26 -0500 Subject: Skip UTF-8 BOM in binary detection When a git_buf contains a UTF-8 BOM, the three bytes comprising that BOM are treated as unprintable characters. For a small git_buf, the three BOM characters overwhelm the printable characters. This is problematic when trying to check out a small file as the CR/LF filtering will not apply. --- src/buf_text.c | 6 ++++++ tests-clar/core/buffer.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/buf_text.c b/src/buf_text.c index 472339def..ecf592b51 100644 --- a/src/buf_text.c +++ b/src/buf_text.c @@ -170,8 +170,14 @@ int git_buf_text_common_prefix(git_buf *buf, const git_strarray *strings) bool git_buf_text_is_binary(const git_buf *buf) { const char *scan = buf->ptr, *end = buf->ptr + buf->size; + git_bom_t bom; int printable = 0, nonprintable = 0; + scan += git_buf_text_detect_bom(&bom, buf, 0); + + if (bom > GIT_BOM_UTF8) + return 1; + while (scan < end) { unsigned char c = *scan++; diff --git a/tests-clar/core/buffer.c b/tests-clar/core/buffer.c index 9d9628cfd..8a0b6711f 100644 --- a/tests-clar/core/buffer.c +++ b/tests-clar/core/buffer.c @@ -718,6 +718,8 @@ void test_core_buffer__classify_with_utf8(void) size_t data1len = 31; char *data2 = "Internal NUL!!!\000\n\nI see you!\n"; size_t data2len = 29; + char *data3 = "\xef\xbb\xbfThis is UTF-8 with a BOM.\n"; + size_t data3len = 20; git_buf b; b.ptr = data0; b.size = b.asize = data0len; @@ -731,6 +733,10 @@ void test_core_buffer__classify_with_utf8(void) b.ptr = data2; b.size = b.asize = data2len; cl_assert(git_buf_text_is_binary(&b)); cl_assert(git_buf_text_contains_nul(&b)); + + b.ptr = data3; b.size = b.asize = data3len; + cl_assert(!git_buf_text_is_binary(&b)); + cl_assert(!git_buf_text_contains_nul(&b)); } #define SIMILARITY_TEST_DATA_1 \ -- cgit v1.2.1 From 0f0f565507565520759bffc22976c583497ec01f Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 19 Aug 2013 10:42:48 -0700 Subject: Don't try to pack symbolic refs If there were symbolic refs among the loose refs then the code to create packed-refs would fail trying to parse the OID out of them (where Git just skips trying to pack them). This fixes it. --- src/refdb_fs.c | 11 ++++++++++- tests-clar/refs/pack.c | 30 ++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/refdb_fs.c b/src/refdb_fs.c index acd82594b..658bebb61 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -316,6 +316,12 @@ static int loose_lookup_to_packfile( if (reference_read(&ref_file, NULL, backend->path, name, NULL) < 0) return -1; + /* skip symbolic refs */ + if (!git__prefixcmp(git_buf_cstr(&ref_file), GIT_SYMREF)) { + git_buf_free(&ref_file); + return 0; + } + git_buf_rtrim(&ref_file); name_len = strlen(name); @@ -355,6 +361,9 @@ static int _dirent_loose_load(void *data, git_buf *full_path) if (loose_lookup_to_packfile(&ref, backend, file_path) < 0) return -1; + if (!ref) + return 0; + git_strmap_insert2( backend->refcache.packfile, ref->name, ref, old_ref, err); if (err < 0) { @@ -460,7 +469,7 @@ static int loose_lookup( if (error < 0) goto done; - if (git__prefixcmp((const char *)(ref_file.ptr), GIT_SYMREF) == 0) { + if (git__prefixcmp(git_buf_cstr(&ref_file), GIT_SYMREF) == 0) { git_buf_rtrim(&ref_file); if ((target = loose_parse_symbolic(&ref_file)) == NULL) { diff --git a/tests-clar/refs/pack.c b/tests-clar/refs/pack.c index d8d5cc6d0..6019ed75a 100644 --- a/tests-clar/refs/pack.c +++ b/tests-clar/refs/pack.c @@ -32,7 +32,7 @@ static void packall(void) void test_refs_pack__empty(void) { - // create a packfile for an empty folder + /* create a packfile for an empty folder */ git_buf temp_path = GIT_BUF_INIT; cl_git_pass(git_buf_join_n(&temp_path, '/', 3, git_repository_path(g_repo), GIT_REFS_HEADS_DIR, "empty_dir")); @@ -44,7 +44,7 @@ void test_refs_pack__empty(void) void test_refs_pack__loose(void) { - // create a packfile from all the loose rn a repo + /* create a packfile from all the loose rn a repo */ git_reference *reference; git_buf temp_path = GIT_BUF_INIT; @@ -77,3 +77,29 @@ void test_refs_pack__loose(void) git_reference_free(reference); git_buf_free(&temp_path); } + +void test_refs_pack__symbolic(void) +{ + /* create a packfile from loose refs skipping symbolic refs */ + int i; + git_oid head; + git_reference *ref; + char name[128]; + + cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); + + /* make a bunch of references */ + + for (i = 0; i < 100; ++i) { + snprintf(name, sizeof(name), "refs/heads/symbolic-%03d", i); + cl_git_pass(git_reference_symbolic_create( + &ref, g_repo, name, "refs/heads/master", 0)); + git_reference_free(ref); + + snprintf(name, sizeof(name), "refs/heads/direct-%03d", i); + cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0)); + git_reference_free(ref); + } + + packall(); +} -- cgit v1.2.1 From 0b7cdc02637bcc8491153a476460c9feab33f8ee Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 20 Aug 2013 15:18:48 -0700 Subject: Add sorted cache data type This adds a convenient new data type for caching the contents of file in memory when each item in that file corresponds to a name and you need to both be able to lookup items by name and iterate over them in some sorted order. The new data type has locks in place to manage usage in a threaded environment. --- src/sortedcache.c | 297 +++++++++++++++++++++++++++++++++++++++++ src/sortedcache.h | 101 ++++++++++++++ src/vector.h | 5 + tests-clar/core/sortedcache.c | 298 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 701 insertions(+) create mode 100644 src/sortedcache.c create mode 100644 src/sortedcache.h create mode 100644 tests-clar/core/sortedcache.c diff --git a/src/sortedcache.c b/src/sortedcache.c new file mode 100644 index 000000000..6015d616d --- /dev/null +++ b/src/sortedcache.c @@ -0,0 +1,297 @@ +#include "sortedcache.h" + +GIT__USE_STRMAP; + +int git_sortedcache_new( + git_sortedcache **out, + size_t item_path_offset, + git_sortedcache_free_item_fn free_item, + void *free_item_payload, + git_vector_cmp item_cmp, + const char *path) +{ + git_sortedcache *sc; + size_t pathlen; + + pathlen = path ? strlen(path) : 0; + + sc = git__calloc(sizeof(git_sortedcache) + pathlen + 1, 1); + GITERR_CHECK_ALLOC(sc); + + if (git_pool_init(&sc->pool, 1, 0) < 0 || + git_vector_init(&sc->items, 4, item_cmp) < 0 || + (sc->map = git_strmap_alloc()) == NULL) + goto fail; + + if (git_mutex_init(&sc->lock)) { + giterr_set(GITERR_OS, "Failed to initialize mutex"); + goto fail; + } + + sc->item_path_offset = item_path_offset; + sc->free_item = free_item; + sc->free_item_payload = free_item_payload; + GIT_REFCOUNT_INC(sc); + if (pathlen) + memcpy(sc->path, path, pathlen); + + *out = sc; + return 0; + +fail: + if (sc->map) + git_strmap_free(sc->map); + git_vector_free(&sc->items); + git_pool_clear(&sc->pool); + git__free(sc); + return -1; +} + +void git_sortedcache_incref(git_sortedcache *sc) +{ + GIT_REFCOUNT_INC(sc); +} + +static void sortedcache_clear(git_sortedcache *sc) +{ + git_strmap_clear(sc->map); + + if (sc->free_item) { + size_t i; + void *item; + + git_vector_foreach(&sc->items, i, item) { + sc->free_item(sc->free_item_payload, item); + } + } + + git_vector_clear(&sc->items); + + git_pool_clear(&sc->pool); +} + +static void sortedcache_free(git_sortedcache *sc) +{ + if (git_mutex_lock(&sc->lock) < 0) { + giterr_set(GITERR_OS, "Unable to acquire mutex lock for free"); + return; + } + + sortedcache_clear(sc); + + git_vector_free(&sc->items); + git_strmap_free(sc->map); + + git_mutex_unlock(&sc->lock); + git_mutex_free(&sc->lock); + + git__free(sc); +} + +void git_sortedcache_free(git_sortedcache *sc) +{ + if (!sc) + return; + GIT_REFCOUNT_DEC(sc, sortedcache_free); +} + +static int sortedcache_copy_item(void *payload, void *tgt_item, void *src_item) +{ + git_sortedcache *sc = payload; + /* path will already have been copied by upsert */ + memcpy(tgt_item, src_item, sc->item_path_offset); + return 0; +} + +/* copy a sorted cache */ +int git_sortedcache_copy( + git_sortedcache **out, + git_sortedcache *src, + int (*copy_item)(void *payload, void *tgt_item, void *src_item), + void *payload) +{ + git_sortedcache *tgt; + size_t i; + void *src_item, *tgt_item; + + if (!copy_item) { + copy_item = sortedcache_copy_item; + payload = src; + } + + if (git_sortedcache_new( + &tgt, src->item_path_offset, + src->free_item, src->free_item_payload, + src->items._cmp, src->path) < 0) + return -1; + + if (git_sortedcache_lock(src) < 0) { + git_sortedcache_free(tgt); + return -1; + } + + if (git_sortedcache_lock(tgt) < 0) + goto fail; + + git_vector_foreach(&src->items, i, src_item) { + if (git_sortedcache_upsert( + &tgt_item, tgt, ((char *)src_item) + src->item_path_offset) < 0) + goto fail; + if (copy_item(payload, tgt_item, src_item) < 0) + goto fail; + } + + git_sortedcache_unlock(tgt); + git_sortedcache_unlock(src); + + *out = tgt; + return 0; + +fail: + git_sortedcache_unlock(src); + git_sortedcache_free(tgt); + return -1; +} + +/* release all items in sorted cache */ +void git_sortedcache_clear(git_sortedcache *sc, bool lock) +{ + if (lock && git_mutex_lock(&sc->lock) < 0) { + giterr_set(GITERR_OS, "Unable to acquire mutex lock for clear"); + return; + } + + sortedcache_clear(sc); + + if (lock) + git_mutex_unlock(&sc->lock); +} + +/* check file stamp to see if reload is required */ +bool git_sortedcache_out_of_date(git_sortedcache *sc) +{ + return (git_futils_filestamp_check(&sc->stamp, sc->path) != 0); +} + +/* lock sortedcache while making modifications */ +int git_sortedcache_lock(git_sortedcache *sc) +{ + if (git_mutex_lock(&sc->lock) < 0) { + giterr_set(GITERR_OS, "Unable to acquire mutex lock"); + return -1; + } + return 0; +} + +/* unlock sorted cache when done with modifications */ +int git_sortedcache_unlock(git_sortedcache *sc) +{ + git_vector_sort(&sc->items); + git_mutex_unlock(&sc->lock); + return 0; +} + +/* if the file has changed, lock cache and load file contents into buf; + * returns <0 on error, >0 if file has not changed + */ +int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf) +{ + int error, fd; + + if ((error = git_sortedcache_lock(sc)) < 0) + return error; + + if ((error = git_futils_filestamp_check(&sc->stamp, sc->path)) <= 0) + goto unlock; + + if (!git__is_sizet(sc->stamp.size)) { + giterr_set(GITERR_INVALID, "Unable to load file larger than size_t"); + error = -1; + goto unlock; + } + + if ((fd = git_futils_open_ro(sc->path)) < 0) { + error = fd; + goto unlock; + } + + if (buf) + error = git_futils_readbuffer_fd(buf, fd, (size_t)sc->stamp.size); + + (void)p_close(fd); + + if (error < 0) + goto unlock; + + return 1; /* return 1 -> file needs reload and was successfully loaded */ + +unlock: + git_sortedcache_unlock(sc); + return error; +} + +/* find and/or insert item, returning pointer to item data */ +int git_sortedcache_upsert( + void **out, git_sortedcache *sc, const char *key) +{ + int error = 0; + khiter_t pos; + void *item; + size_t keylen; + char *item_key; + + pos = git_strmap_lookup_index(sc->map, key); + if (git_strmap_valid_index(sc->map, pos)) { + item = git_strmap_value_at(sc->map, pos); + goto done; + } + + keylen = strlen(key); + item = git_pool_mallocz(&sc->pool, sc->item_path_offset + keylen + 1); + GITERR_CHECK_ALLOC(item); + + /* one strange thing is that even if the vector or hash table insert + * fail, there is no way to free the pool item so we just abandon it + */ + + item_key = ((char *)item) + sc->item_path_offset; + memcpy(item_key, key, keylen); + + pos = kh_put(str, sc->map, item_key, &error); + if (error < 0) + goto done; + + if (!error) + kh_key(sc->map, pos) = item_key; + kh_val(sc->map, pos) = item; + + error = git_vector_insert(&sc->items, item); + if (error < 0) + git_strmap_delete_at(sc->map, pos); + +done: + if (out) + *out = !error ? item : NULL; + return error; +} + +/* lookup item by key */ +void *git_sortedcache_lookup(const git_sortedcache *sc, const char *key) +{ + khiter_t pos = git_strmap_lookup_index(sc->map, key); + if (git_strmap_valid_index(sc->map, pos)) + return git_strmap_value_at(sc->map, pos); + return NULL; +} + +/* find out how many items are in the cache */ +size_t git_sortedcache_entrycount(const git_sortedcache *sc) +{ + return git_vector_length(&sc->items); +} + +/* lookup item by index */ +void *git_sortedcache_entry(const git_sortedcache *sc, size_t pos) +{ + return git_vector_get(&sc->items, pos); +} diff --git a/src/sortedcache.h b/src/sortedcache.h new file mode 100644 index 000000000..5d0d8f5a7 --- /dev/null +++ b/src/sortedcache.h @@ -0,0 +1,101 @@ +/* + * 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_sorted_cache_h__ +#define INCLUDE_sorted_cache_h__ + +#include "util.h" +#include "fileops.h" +#include "vector.h" +#include "thread-utils.h" +#include "pool.h" +#include "strmap.h" + +/* + * The purpose of this data structure is to cache the parsed contents of a + * file where each item in the file can be identified by a key string and + * you want to both look them up by name and traverse them in sorted + * order. Each item is assumed to itself end in a GIT_FLEX_ARRAY. + */ + +typedef void (*git_sortedcache_free_item_fn)(void *payload, void *item); + +typedef struct { + git_refcount rc; + git_mutex lock; + size_t item_path_offset; + git_sortedcache_free_item_fn free_item; + void *free_item_payload; + git_pool pool; + git_vector items; + git_strmap *map; + git_futils_filestamp stamp; + char path[GIT_FLEX_ARRAY]; +} git_sortedcache; + +/* create a new sortedcache + * + * even though every sortedcache stores items with a GIT_FLEX_ARRAY at + * the end containing their key string, you have to provide the item_cmp + * sorting function because the sorting function doesn't get a payload + * and therefore can't know the offset to the item key string. :-( + */ +int git_sortedcache_new( + git_sortedcache **out, + size_t item_path_offset, /* use offsetof() macro */ + git_sortedcache_free_item_fn free_item, + void *free_item_payload, + git_vector_cmp item_cmp, + const char *path); + +/* copy a sorted cache + * + * - copy_item can be NULL to memcpy + * - locks src while copying + */ +int git_sortedcache_copy( + git_sortedcache **out, + git_sortedcache *src, + int (*copy_item)(void *payload, void *tgt_item, void *src_item), + void *payload); + +/* free sorted cache (first calling free_item callbacks) */ +void git_sortedcache_free(git_sortedcache *sc); + +/* increment reference count */ +void git_sortedcache_incref(git_sortedcache *sc); + +/* release all items in sorted cache - lock during clear if lock is true */ +void git_sortedcache_clear(git_sortedcache *sc, bool lock); + +/* check file stamp to see if reload is required */ +bool git_sortedcache_out_of_date(git_sortedcache *sc); + +/* lock sortedcache while making modifications */ +int git_sortedcache_lock(git_sortedcache *sc); + +/* unlock sorted cache when done with modifications */ +int git_sortedcache_unlock(git_sortedcache *sc); + +/* if the file has changed, lock cache and load file contents into buf; + * @return 0 if up-to-date, 1 if out-of-date, <0 on error + */ +int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf); + +/* find and/or insert item, returning pointer to item data - lock first */ +int git_sortedcache_upsert( + void **out, git_sortedcache *sc, const char *key); + +/* lookup item by key */ +void *git_sortedcache_lookup(const git_sortedcache *sc, const char *key); + +/* find out how many items are in the cache */ +size_t git_sortedcache_entrycount(const git_sortedcache *sc); + +/* lookup item by index */ +void *git_sortedcache_entry(const git_sortedcache *sc, size_t pos); + +#endif diff --git a/src/vector.h b/src/vector.h index 1bda9c93d..ad1c34ea1 100644 --- a/src/vector.h +++ b/src/vector.h @@ -55,6 +55,11 @@ GIT_INLINE(void *) git_vector_get(const git_vector *v, size_t position) #define GIT_VECTOR_GET(V,I) ((I) < (V)->length ? (V)->contents[(I)] : NULL) +GIT_INLINE(size_t) git_vector_length(const git_vector *v) +{ + return v->length; +} + GIT_INLINE(void *) git_vector_last(const git_vector *v) { return (v->length > 0) ? git_vector_get(v, v->length - 1) : NULL; diff --git a/tests-clar/core/sortedcache.c b/tests-clar/core/sortedcache.c new file mode 100644 index 000000000..f192af31d --- /dev/null +++ b/tests-clar/core/sortedcache.c @@ -0,0 +1,298 @@ +#include "clar_libgit2.h" +#include "sortedcache.h" + +static int name_only_cmp(const void *a, const void *b) +{ + return strcmp(a, b); +} + +void test_core_sortedcache__name_only(void) +{ + git_sortedcache *sc; + void *item; + + cl_git_pass(git_sortedcache_new( + &sc, 0, NULL, NULL, name_only_cmp, NULL)); + + cl_git_pass(git_sortedcache_lock(sc)); + cl_git_pass(git_sortedcache_upsert(&item, sc, "aaa")); + cl_git_pass(git_sortedcache_upsert(&item, sc, "bbb")); + cl_git_pass(git_sortedcache_upsert(&item, sc, "zzz")); + cl_git_pass(git_sortedcache_upsert(&item, sc, "mmm")); + cl_git_pass(git_sortedcache_upsert(&item, sc, "iii")); + cl_git_pass(git_sortedcache_unlock(sc)); + + cl_assert_equal_sz(5, git_sortedcache_entrycount(sc)); + + cl_assert((item = git_sortedcache_lookup(sc, "aaa")) != NULL); + cl_assert_equal_s("aaa", item); + cl_assert((item = git_sortedcache_lookup(sc, "mmm")) != NULL); + cl_assert_equal_s("mmm", item); + cl_assert((item = git_sortedcache_lookup(sc, "zzz")) != NULL); + cl_assert_equal_s("zzz", item); + cl_assert(git_sortedcache_lookup(sc, "qqq") == NULL); + + cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); + cl_assert_equal_s("aaa", item); + cl_assert((item = git_sortedcache_entry(sc, 1)) != NULL); + cl_assert_equal_s("bbb", item); + cl_assert((item = git_sortedcache_entry(sc, 2)) != NULL); + cl_assert_equal_s("iii", item); + cl_assert((item = git_sortedcache_entry(sc, 3)) != NULL); + cl_assert_equal_s("mmm", item); + cl_assert((item = git_sortedcache_entry(sc, 4)) != NULL); + cl_assert_equal_s("zzz", item); + cl_assert(git_sortedcache_entry(sc, 5) == NULL); + + git_sortedcache_clear(sc, true); + + cl_assert_equal_sz(0, git_sortedcache_entrycount(sc)); + cl_assert(git_sortedcache_entry(sc, 0) == NULL); + cl_assert(git_sortedcache_lookup(sc, "aaa") == NULL); + cl_assert(git_sortedcache_entry(sc, 0) == NULL); + + git_sortedcache_free(sc); +} + +typedef struct { + int value; + char smaller_value; + char path[GIT_FLEX_ARRAY]; +} sortedcache_test_struct; + +static int sortedcache_test_struct_cmp(const void *a_, const void *b_) +{ + const sortedcache_test_struct *a = a_, *b = b_; + return strcmp(a->path, b->path); +} + +static void sortedcache_test_struct_free(void *payload, void *item_) +{ + sortedcache_test_struct *item = item_; + int *count = payload; + (*count)++; + item->smaller_value = 0; +} + +void test_core_sortedcache__in_memory(void) +{ + git_sortedcache *sc; + sortedcache_test_struct *item; + int free_count = 0; + + cl_git_pass(git_sortedcache_new( + &sc, offsetof(sortedcache_test_struct, path), + sortedcache_test_struct_free, &free_count, + sortedcache_test_struct_cmp, NULL)); + + cl_git_pass(git_sortedcache_lock(sc)); + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "aaa")); + item->value = 10; + item->smaller_value = 1; + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "bbb")); + item->value = 20; + item->smaller_value = 2; + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "zzz")); + item->value = 30; + item->smaller_value = 26; + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "mmm")); + item->value = 40; + item->smaller_value = 14; + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "iii")); + item->value = 50; + item->smaller_value = 9; + cl_git_pass(git_sortedcache_unlock(sc)); + + cl_assert_equal_sz(5, git_sortedcache_entrycount(sc)); + + cl_assert((item = git_sortedcache_lookup(sc, "aaa")) != NULL); + cl_assert_equal_s("aaa", item->path); + cl_assert_equal_i(10, item->value); + cl_assert((item = git_sortedcache_lookup(sc, "mmm")) != NULL); + cl_assert_equal_s("mmm", item->path); + cl_assert_equal_i(40, item->value); + cl_assert((item = git_sortedcache_lookup(sc, "zzz")) != NULL); + cl_assert_equal_s("zzz", item->path); + cl_assert_equal_i(30, item->value); + cl_assert(git_sortedcache_lookup(sc, "abc") == NULL); + + cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); + cl_assert_equal_s("aaa", item->path); + cl_assert_equal_i(10, item->value); + cl_assert((item = git_sortedcache_entry(sc, 1)) != NULL); + cl_assert_equal_s("bbb", item->path); + cl_assert_equal_i(20, item->value); + cl_assert((item = git_sortedcache_entry(sc, 2)) != NULL); + cl_assert_equal_s("iii", item->path); + cl_assert_equal_i(50, item->value); + cl_assert((item = git_sortedcache_entry(sc, 3)) != NULL); + cl_assert_equal_s("mmm", item->path); + cl_assert_equal_i(40, item->value); + cl_assert((item = git_sortedcache_entry(sc, 4)) != NULL); + cl_assert_equal_s("zzz", item->path); + cl_assert_equal_i(30, item->value); + cl_assert(git_sortedcache_entry(sc, 5) == NULL); + + cl_assert_equal_i(0, free_count); + + git_sortedcache_clear(sc, true); + + cl_assert_equal_i(5, free_count); + + cl_assert_equal_sz(0, git_sortedcache_entrycount(sc)); + cl_assert(git_sortedcache_entry(sc, 0) == NULL); + cl_assert(git_sortedcache_lookup(sc, "aaa") == NULL); + cl_assert(git_sortedcache_entry(sc, 0) == NULL); + + free_count = 0; + + cl_git_pass(git_sortedcache_lock(sc)); + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "testing")); + item->value = 10; + item->smaller_value = 3; + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "again")); + item->value = 20; + item->smaller_value = 1; + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "final")); + item->value = 30; + item->smaller_value = 2; + cl_git_pass(git_sortedcache_unlock(sc)); + + cl_assert_equal_sz(3, git_sortedcache_entrycount(sc)); + + cl_assert((item = git_sortedcache_lookup(sc, "testing")) != NULL); + cl_assert_equal_s("testing", item->path); + cl_assert_equal_i(10, item->value); + cl_assert((item = git_sortedcache_lookup(sc, "again")) != NULL); + cl_assert_equal_s("again", item->path); + cl_assert_equal_i(20, item->value); + cl_assert((item = git_sortedcache_lookup(sc, "final")) != NULL); + cl_assert_equal_s("final", item->path); + cl_assert_equal_i(30, item->value); + cl_assert(git_sortedcache_lookup(sc, "zzz") == NULL); + + cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); + cl_assert_equal_s("again", item->path); + cl_assert_equal_i(20, item->value); + cl_assert((item = git_sortedcache_entry(sc, 1)) != NULL); + cl_assert_equal_s("final", item->path); + cl_assert_equal_i(30, item->value); + cl_assert((item = git_sortedcache_entry(sc, 2)) != NULL); + cl_assert_equal_s("testing", item->path); + cl_assert_equal_i(10, item->value); + cl_assert(git_sortedcache_entry(sc, 3) == NULL); + + git_sortedcache_free(sc); + + cl_assert_equal_i(3, free_count); +} + +static void sortedcache_test_reload(git_sortedcache *sc) +{ + int count = 0; + git_buf buf = GIT_BUF_INIT; + char *scan, *after; + sortedcache_test_struct *item; + + cl_assert(git_sortedcache_lockandload(sc, &buf) > 0); + + git_sortedcache_clear(sc, false); /* clear once we already have lock */ + + for (scan = buf.ptr; *scan; scan = after + 1) { + int val = strtol(scan, &after, 0); + cl_assert(after > scan); + scan = after; + + for (scan = after; git__isspace(*scan); ++scan) /* find start */; + for (after = scan; *after && *after != '\n'; ++after) /* find eol */; + *after = '\0'; + + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, scan)); + + item->value = val; + item->smaller_value = (char)(count++); + } + + cl_git_pass(git_sortedcache_unlock(sc)); + + git_buf_free(&buf); +} + +void test_core_sortedcache__on_disk(void) +{ + git_sortedcache *sc; + sortedcache_test_struct *item; + int free_count = 0; + + cl_git_mkfile("cacheitems.txt", "10 abc\n20 bcd\n30 cde\n"); + + cl_git_pass(git_sortedcache_new( + &sc, offsetof(sortedcache_test_struct, path), + sortedcache_test_struct_free, &free_count, + sortedcache_test_struct_cmp, "cacheitems.txt")); + + /* should need to reload the first time */ + + sortedcache_test_reload(sc); + + /* test what we loaded */ + + cl_assert_equal_sz(3, git_sortedcache_entrycount(sc)); + + cl_assert((item = git_sortedcache_lookup(sc, "abc")) != NULL); + cl_assert_equal_s("abc", item->path); + cl_assert_equal_i(10, item->value); + cl_assert((item = git_sortedcache_lookup(sc, "cde")) != NULL); + cl_assert_equal_s("cde", item->path); + cl_assert_equal_i(30, item->value); + cl_assert(git_sortedcache_lookup(sc, "aaa") == NULL); + + cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); + cl_assert_equal_s("abc", item->path); + cl_assert_equal_i(10, item->value); + cl_assert((item = git_sortedcache_entry(sc, 1)) != NULL); + cl_assert_equal_s("bcd", item->path); + cl_assert_equal_i(20, item->value); + cl_assert(git_sortedcache_entry(sc, 3) == NULL); + + /* should not need to reload this time */ + + cl_assert_equal_i(0, git_sortedcache_lockandload(sc, NULL)); + + /* rewrite ondisk file and reload */ + + cl_assert_equal_i(0, free_count); + + cl_git_rewritefile( + "cacheitems.txt", "100 abc\n200 zzz\n500 aaa\n10 final\n"); + sortedcache_test_reload(sc); + + cl_assert_equal_i(3, free_count); + + /* test what we loaded */ + + cl_assert_equal_sz(4, git_sortedcache_entrycount(sc)); + + cl_assert((item = git_sortedcache_lookup(sc, "abc")) != NULL); + cl_assert_equal_s("abc", item->path); + cl_assert_equal_i(100, item->value); + cl_assert((item = git_sortedcache_lookup(sc, "final")) != NULL); + cl_assert_equal_s("final", item->path); + cl_assert_equal_i(10, item->value); + cl_assert(git_sortedcache_lookup(sc, "cde") == NULL); + + cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); + cl_assert_equal_s("aaa", item->path); + cl_assert_equal_i(500, item->value); + cl_assert((item = git_sortedcache_entry(sc, 2)) != NULL); + cl_assert_equal_s("final", item->path); + cl_assert_equal_i(10, item->value); + cl_assert((item = git_sortedcache_entry(sc, 3)) != NULL); + cl_assert_equal_s("zzz", item->path); + cl_assert_equal_i(200, item->value); + + git_sortedcache_free(sc); + + cl_assert_equal_i(7, free_count); +} + -- cgit v1.2.1 From a4977169e1e1920ed33f10a77e5dd8706f103f4f Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 21 Aug 2013 14:09:38 -0700 Subject: Add sortedcache APIs to lookup index and remove This adds two other APIs that I need to the sortedcache type. --- src/sortedcache.c | 59 +++++++++++++++++++++++++++++++++++++++++++ src/sortedcache.h | 7 +++++ tests-clar/core/sortedcache.c | 52 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+) diff --git a/src/sortedcache.c b/src/sortedcache.c index 6015d616d..2efa3c4e9 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -295,3 +295,62 @@ void *git_sortedcache_entry(const git_sortedcache *sc, size_t pos) { return git_vector_get(&sc->items, pos); } + +struct sortedcache_magic_key { + size_t offset; + const char *key; +}; + +static int sortedcache_magic_cmp(const void *key, const void *value) +{ + const struct sortedcache_magic_key *magic = key; + const char *value_key = ((const char *)value) + magic->offset; + return strcmp(magic->key, value_key); +} + +/* lookup index of item by key */ +int git_sortedcache_lookup_index( + size_t *out, git_sortedcache *sc, const char *key) +{ + struct sortedcache_magic_key magic; + + magic.offset = sc->item_path_offset; + magic.key = key; + + return git_vector_bsearch2(out, &sc->items, sortedcache_magic_cmp, &magic); +} + +/* remove entry from cache */ +int git_sortedcache_remove(git_sortedcache *sc, size_t pos, bool lock) +{ + int error = 0; + char *item; + khiter_t mappos; + + if (lock && git_sortedcache_lock(sc) < 0) + return -1; + + /* because of pool allocation, this can't actually remove the item, + * but we can remove it from the items vector and the hash table. + */ + + if ((item = git_vector_get(&sc->items, pos)) == NULL) { + giterr_set(GITERR_INVALID, "Removing item out of range"); + error = GIT_ENOTFOUND; + goto done; + } + + (void)git_vector_remove(&sc->items, pos); + + mappos = git_strmap_lookup_index(sc->map, item + sc->item_path_offset); + git_strmap_delete_at(sc->map, mappos); + + if (sc->free_item) + sc->free_item(sc->free_item_payload, item); + +done: + if (lock) + git_sortedcache_unlock(sc); + return error; +} + diff --git a/src/sortedcache.h b/src/sortedcache.h index 5d0d8f5a7..f63ad645b 100644 --- a/src/sortedcache.h +++ b/src/sortedcache.h @@ -98,4 +98,11 @@ size_t git_sortedcache_entrycount(const git_sortedcache *sc); /* lookup item by index */ void *git_sortedcache_entry(const git_sortedcache *sc, size_t pos); +/* lookup index of item by key */ +int git_sortedcache_lookup_index( + size_t *out, git_sortedcache *sc, const char *key); + +/* remove entry from cache */ +int git_sortedcache_remove(git_sortedcache *sc, size_t pos, bool lock); + #endif diff --git a/tests-clar/core/sortedcache.c b/tests-clar/core/sortedcache.c index f192af31d..91415943d 100644 --- a/tests-clar/core/sortedcache.c +++ b/tests-clar/core/sortedcache.c @@ -10,6 +10,7 @@ void test_core_sortedcache__name_only(void) { git_sortedcache *sc; void *item; + size_t pos; cl_git_pass(git_sortedcache_new( &sc, 0, NULL, NULL, name_only_cmp, NULL)); @@ -44,6 +45,15 @@ void test_core_sortedcache__name_only(void) cl_assert_equal_s("zzz", item); cl_assert(git_sortedcache_entry(sc, 5) == NULL); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "aaa")); + cl_assert_equal_sz(0, pos); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "iii")); + cl_assert_equal_sz(2, pos); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "zzz")); + cl_assert_equal_sz(4, pos); + cl_assert_equal_i( + GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "abc")); + git_sortedcache_clear(sc, true); cl_assert_equal_sz(0, git_sortedcache_entrycount(sc)); @@ -182,6 +192,34 @@ void test_core_sortedcache__in_memory(void) cl_assert_equal_i(10, item->value); cl_assert(git_sortedcache_entry(sc, 3) == NULL); + { + size_t pos; + + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "again")); + cl_assert_equal_sz(0, pos); + cl_git_pass(git_sortedcache_remove(sc, pos, true)); + cl_assert_equal_i( + GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "again")); + + cl_assert_equal_sz(2, git_sortedcache_entrycount(sc)); + + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "testing")); + cl_assert_equal_sz(1, pos); + cl_git_pass(git_sortedcache_remove(sc, pos, true)); + cl_assert_equal_i( + GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "testing")); + + cl_assert_equal_sz(1, git_sortedcache_entrycount(sc)); + + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "final")); + cl_assert_equal_sz(0, pos); + cl_git_pass(git_sortedcache_remove(sc, pos, true)); + cl_assert_equal_i( + GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "final")); + + cl_assert_equal_sz(0, git_sortedcache_entrycount(sc)); + } + git_sortedcache_free(sc); cl_assert_equal_i(3, free_count); @@ -223,6 +261,7 @@ void test_core_sortedcache__on_disk(void) git_sortedcache *sc; sortedcache_test_struct *item; int free_count = 0; + size_t pos; cl_git_mkfile("cacheitems.txt", "10 abc\n20 bcd\n30 cde\n"); @@ -291,6 +330,19 @@ void test_core_sortedcache__on_disk(void) cl_assert_equal_s("zzz", item->path); cl_assert_equal_i(200, item->value); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "aaa")); + cl_assert_equal_sz(0, pos); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "abc")); + cl_assert_equal_sz(1, pos); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "final")); + cl_assert_equal_sz(2, pos); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "zzz")); + cl_assert_equal_sz(3, pos); + cl_assert_equal_i( + GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "missing")); + cl_assert_equal_i( + GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "cde")); + git_sortedcache_free(sc); cl_assert_equal_i(7, free_count); -- cgit v1.2.1 From 24c71f14b4dcb696d9d87330322c12fd2c185317 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 21 Aug 2013 14:10:27 -0700 Subject: Add internal ref set_name fn instead of realloc The refdb_fs implementation calls realloc directly on a reference object when it wants to rename it. It is not a public object, so this doesn't mess with the immutability of references, but it does assume certain constraints on the reference representation. This commit wraps that assumption in an isolated API to isolate it. --- src/refs.c | 11 +++++++++++ src/refs.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/src/refs.c b/src/refs.c index c0e460cc3..e59b34aae 100644 --- a/src/refs.c +++ b/src/refs.c @@ -88,6 +88,17 @@ git_reference *git_reference__alloc( return ref; } +git_reference *git_reference__set_name( + git_reference *ref, const char *name) +{ + size_t namelen = strlen(name); + git_reference *rewrite = + git__realloc(ref, sizeof(git_reference) + namelen + 1); + if (rewrite != NULL) + memcpy(rewrite->name, name, namelen + 1); + return rewrite; +} + void git_reference_free(git_reference *reference) { if (reference == NULL) diff --git a/src/refs.h b/src/refs.h index f487ee3fc..4bb49d02a 100644 --- a/src/refs.h +++ b/src/refs.h @@ -61,6 +61,8 @@ struct git_reference { char name[0]; }; +git_reference *git_reference__set_name(git_reference *ref, const char *name); + int git_reference__normalize_name_lax(char *buffer_out, size_t out_size, const char *name); int git_reference__normalize_name(git_buf *buf, const char *name, unsigned int flags); int git_reference__update_terminal(git_repository *repo, const char *ref_name, const git_oid *oid); -- cgit v1.2.1 From fe3727408001f9708aad09562ffae5b82c0f7171 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 21 Aug 2013 16:26:32 -0700 Subject: Rewrite refdb_fs using git_sortedcache object This adds thread safety to the refdb_fs by using the new git_sortedcache object and also by relaxing the handling of some filesystem errors where the fs may be changed out from under us. This also adds some new threading tests that hammer on the refdb. --- src/refdb_fs.c | 810 ++++++++++++++++++--------------------------- tests-clar/threads/refdb.c | 200 +++++++++++ 2 files changed, 514 insertions(+), 496 deletions(-) create mode 100644 tests-clar/threads/refdb.c diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 658bebb61..876e84588 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -15,6 +15,7 @@ #include "refdb.h" #include "refdb_fs.h" #include "iterator.h" +#include "sortedcache.h" #include #include @@ -53,243 +54,149 @@ typedef struct refdb_fs_backend { git_repository *repo; char *path; - git_refcache refcache; + git_sortedcache *refcache; int peeling_mode; } refdb_fs_backend; -static int reference_read( - git_buf *file_content, - time_t *mtime, - const char *repo_path, - const char *ref_name, - int *updated) +static int packref_cmp(const void *a_, const void *b_) { - git_buf path = GIT_BUF_INIT; - int result; - - assert(file_content && repo_path && ref_name); - - /* Determine the full path of the file */ - if (git_buf_joinpath(&path, repo_path, ref_name) < 0) - return -1; - - result = git_futils_readbuffer_updated(file_content, path.ptr, mtime, NULL, updated); - git_buf_free(&path); - - return result; + const struct packref *a = a_, *b = b_; + return strcmp(a->name, b->name); } -static int packed_parse_oid( - struct packref **ref_out, - const char **buffer_out, - const char *buffer_end) +static int packed_reload(refdb_fs_backend *backend) { - struct packref *ref = NULL; - - const char *buffer = *buffer_out; - const char *refname_begin, *refname_end; - - size_t refname_len; - git_oid id; - - refname_begin = (buffer + GIT_OID_HEXSZ + 1); - if (refname_begin >= buffer_end || refname_begin[-1] != ' ') - goto corrupt; - - /* Is this a valid object id? */ - if (git_oid_fromstr(&id, buffer) < 0) - goto corrupt; - - refname_end = memchr(refname_begin, '\n', buffer_end - refname_begin); - if (refname_end == NULL) - refname_end = buffer_end; - - if (refname_end[-1] == '\r') - refname_end--; - - refname_len = refname_end - refname_begin; - - ref = git__calloc(1, sizeof(struct packref) + refname_len + 1); - GITERR_CHECK_ALLOC(ref); - - memcpy(ref->name, refname_begin, refname_len); - ref->name[refname_len] = 0; - - git_oid_cpy(&ref->oid, &id); - - *ref_out = ref; - *buffer_out = refname_end + 1; - return 0; - -corrupt: - git__free(ref); - giterr_set(GITERR_REFERENCE, "The packed references file is corrupted"); - return -1; -} - -static int packed_parse_peel( - struct packref *tag_ref, - const char **buffer_out, - const char *buffer_end) -{ - const char *buffer = *buffer_out + 1; - - assert(buffer[-1] == '^'); - - /* Ensure it's not the first entry of the file */ - if (tag_ref == NULL) - goto corrupt; - - if (buffer + GIT_OID_HEXSZ > buffer_end) - goto corrupt; - - /* Is this a valid object id? */ - if (git_oid_fromstr(&tag_ref->peel, buffer) < 0) - goto corrupt; - - buffer = buffer + GIT_OID_HEXSZ; - if (*buffer == '\r') - buffer++; - - if (buffer != buffer_end) { - if (*buffer == '\n') - buffer++; - else - goto corrupt; - } - - tag_ref->flags |= PACKREF_HAS_PEEL; - *buffer_out = buffer; - return 0; - -corrupt: - giterr_set(GITERR_REFERENCE, "The packed references file is corrupted"); - return -1; -} - -static int packed_load(refdb_fs_backend *backend) -{ - int result, updated; - git_buf packfile = GIT_BUF_INIT; - const char *buffer_start, *buffer_end; - git_refcache *ref_cache = &backend->refcache; - - /* First we make sure we have allocated the hash table */ - if (ref_cache->packfile == NULL) { - ref_cache->packfile = git_strmap_alloc(); - GITERR_CHECK_ALLOC(ref_cache->packfile); - } + int error; + git_buf packedrefs = GIT_BUF_INIT; + char *scan, *eof, *eol; - if (backend->path == NULL) + if (!backend->path) return 0; - result = reference_read(&packfile, &ref_cache->packfile_time, - backend->path, GIT_PACKEDREFS_FILE, &updated); + error = git_sortedcache_lockandload(backend->refcache, &packedrefs); /* - * If we couldn't find the file, we need to clear the table and - * return. On any other error, we return that error. If everything - * went fine and the file wasn't updated, then there's nothing new - * for us here, so just return. Anything else means we need to - * refresh the packed refs. + * If we can't find the packed-refs, clear table and return. + * Any other error just gets passed through. + * If no error, and file wasn't changed, just return. + * Anything else means we need to refresh the packed refs. */ - if (result == GIT_ENOTFOUND) { - git_strmap_clear(ref_cache->packfile); - return 0; + if (error <= 0) { + if (error == GIT_ENOTFOUND) { + git_sortedcache_clear(backend->refcache, true); + giterr_clear(); + error = 0; + } + return error; } - if (result < 0) - return -1; - - if (!updated) - return 0; + /* At this point, refresh the packed refs from the loaded buffer. */ - /* - * At this point, we want to refresh the packed refs. We already - * have the contents in our buffer. - */ - git_strmap_clear(ref_cache->packfile); + git_sortedcache_clear(backend->refcache, false); - buffer_start = (const char *)packfile.ptr; - buffer_end = (const char *)(buffer_start) + packfile.size; + scan = (char *)packedrefs.ptr; + eof = scan + packedrefs.size; backend->peeling_mode = PEELING_NONE; - if (buffer_start[0] == '#') { + if (*scan == '#') { static const char *traits_header = "# pack-refs with: "; - if (git__prefixcmp(buffer_start, traits_header) == 0) { - char *traits = (char *)buffer_start + strlen(traits_header); - char *traits_end = strchr(traits, '\n'); + if (git__prefixcmp(scan, traits_header) == 0) { + scan += strlen(traits_header); + eol = strchr(scan, '\n'); - if (traits_end == NULL) + if (!eol) goto parse_failed; + *eol = '\0'; - *traits_end = '\0'; - - if (strstr(traits, " fully-peeled ") != NULL) { + if (strstr(scan, " fully-peeled ") != NULL) { backend->peeling_mode = PEELING_FULL; - } else if (strstr(traits, " peeled ") != NULL) { + } else if (strstr(scan, " peeled ") != NULL) { backend->peeling_mode = PEELING_STANDARD; } - buffer_start = traits_end + 1; + scan = eol + 1; } } - while (buffer_start < buffer_end && buffer_start[0] == '#') { - buffer_start = strchr(buffer_start, '\n'); - if (buffer_start == NULL) + while (scan < eof && *scan == '#') { + if (!(eol = strchr(scan, '\n'))) goto parse_failed; - - buffer_start++; + scan = eol + 1; } - while (buffer_start < buffer_end) { - int err; - struct packref *ref = NULL; + while (scan < eof) { + struct packref *ref; + git_oid oid; + + /* parse " \n" */ - if (packed_parse_oid(&ref, &buffer_start, buffer_end) < 0) + if (git_oid_fromstr(&oid, scan) < 0) goto parse_failed; + scan += GIT_OID_HEXSZ; - if (buffer_start[0] == '^') { - if (packed_parse_peel(ref, &buffer_start, buffer_end) < 0) - goto parse_failed; - } else if (backend->peeling_mode == PEELING_FULL || - (backend->peeling_mode == PEELING_STANDARD && - git__prefixcmp(ref->name, GIT_REFS_TAGS_DIR) == 0)) { - ref->flags |= PACKREF_CANNOT_PEEL; - } + if (*scan++ != ' ') + goto parse_failed; + if (!(eol = strchr(scan, '\n'))) + goto parse_failed; + *eol = '\0'; + if (eol[-1] == '\r') + eol[-1] = '\0'; - git_strmap_insert(ref_cache->packfile, ref->name, ref, err); - if (err < 0) + if (git_sortedcache_upsert((void **)&ref, backend->refcache, scan) < 0) goto parse_failed; + scan = eol + 1; + + git_oid_cpy(&ref->oid, &oid); + + /* look for optional "^\n" */ + + if (*scan == '^') { + if (git_oid_fromstr(&oid, scan + 1) < 0) + goto parse_failed; + scan += GIT_OID_HEXSZ + 1; + + if (scan < eof) { + if (!(eol = strchr(scan, '\n'))) + goto parse_failed; + scan = eol + 1; + } + + git_oid_cpy(&ref->peel, &oid); + ref->flags |= PACKREF_HAS_PEEL; + } + else if (backend->peeling_mode == PEELING_FULL || + (backend->peeling_mode == PEELING_STANDARD && + git__prefixcmp(ref->name, GIT_REFS_TAGS_DIR) == 0)) + ref->flags |= PACKREF_CANNOT_PEEL; } - git_buf_free(&packfile); + git_sortedcache_unlock(backend->refcache); + git_buf_free(&packedrefs); + return 0; parse_failed: - git_strmap_free(ref_cache->packfile); - ref_cache->packfile = NULL; - git_buf_free(&packfile); + giterr_set(GITERR_REFERENCE, "Corrupted packed references file"); + + git_sortedcache_clear(backend->refcache, false); + git_sortedcache_unlock(backend->refcache); + git_buf_free(&packedrefs); + return -1; } -static int loose_parse_oid(git_oid *oid, const char *filename, git_buf *file_content) +static int loose_parse_oid( + git_oid *oid, const char *filename, git_buf *file_content) { - size_t len; - const char *str; + const char *str = git_buf_cstr(file_content); - len = git_buf_len(file_content); - if (len < GIT_OID_HEXSZ) + if (git_buf_len(file_content) < GIT_OID_HEXSZ) goto corrupted; - /* str is guranteed to be zero-terminated */ - str = git_buf_cstr(file_content); - /* we need to get 40 OID characters from the file */ - if (git_oid_fromstr(oid, git_buf_cstr(file_content)) < 0) + if (git_oid_fromstr(oid, str) < 0) goto corrupted; /* If the file is longer than 40 chars, the 41st must be a space */ @@ -302,77 +209,71 @@ corrupted: return -1; } -static int loose_lookup_to_packfile( - struct packref **ref_out, - refdb_fs_backend *backend, - const char *name) +static int loose_readbuffer(git_buf *buf, const char *base, const char *path) +{ + int error; + + /* build full path to file */ + if ((error = git_buf_joinpath(buf, base, path)) < 0 || + (error = git_futils_readbuffer(buf, buf->ptr)) < 0) + git_buf_free(buf); + + return error; +} + +static int loose_lookup_to_packfile(refdb_fs_backend *backend, const char *name) { + int error = 0; git_buf ref_file = GIT_BUF_INIT; struct packref *ref = NULL; - size_t name_len; - - *ref_out = NULL; + git_oid oid; - if (reference_read(&ref_file, NULL, backend->path, name, NULL) < 0) - return -1; + /* 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) { + giterr_clear(); + goto done; + } /* skip symbolic refs */ - if (!git__prefixcmp(git_buf_cstr(&ref_file), GIT_SYMREF)) { - git_buf_free(&ref_file); - return 0; - } + if (!git__prefixcmp(git_buf_cstr(&ref_file), GIT_SYMREF)) + goto done; - git_buf_rtrim(&ref_file); + /* parse OID from file */ + if ((error = loose_parse_oid(&oid, name, &ref_file)) < 0) + goto done; - name_len = strlen(name); - ref = git__calloc(1, sizeof(struct packref) + name_len + 1); - GITERR_CHECK_ALLOC(ref); + git_sortedcache_lock(backend->refcache); - memcpy(ref->name, name, name_len); - ref->name[name_len] = 0; + if (!(error = git_sortedcache_upsert( + (void **)&ref, backend->refcache, name))) { - if (loose_parse_oid(&ref->oid, name, &ref_file) < 0) { - git_buf_free(&ref_file); - git__free(ref); - return -1; + git_oid_cpy(&ref->oid, &oid); + ref->flags = PACKREF_WAS_LOOSE; } - ref->flags = PACKREF_WAS_LOOSE; + git_sortedcache_unlock(backend->refcache); - *ref_out = ref; +done: git_buf_free(&ref_file); - return 0; + return error; } - static int _dirent_loose_load(void *data, git_buf *full_path) { refdb_fs_backend *backend = (refdb_fs_backend *)data; - void *old_ref = NULL; - struct packref *ref; const char *file_path; - int err; - if (git_path_isdir(full_path->ptr) == true) + if (git__suffixcmp(full_path->ptr, ".lock") == 0) + return 0; + + if (git_path_isdir(full_path->ptr)) return git_path_direach(full_path, _dirent_loose_load, backend); file_path = full_path->ptr + strlen(backend->path); - if (loose_lookup_to_packfile(&ref, backend, file_path) < 0) - return -1; - - if (!ref) - return 0; - - git_strmap_insert2( - backend->refcache.packfile, ref->name, ref, old_ref, err); - if (err < 0) { - git__free(ref); - return -1; - } - - git__free(old_ref); - return 0; + return loose_lookup_to_packfile(backend, file_path); } /* @@ -383,11 +284,8 @@ static int _dirent_loose_load(void *data, git_buf *full_path) */ static int packed_loadloose(refdb_fs_backend *backend) { + int error; git_buf refs_path = GIT_BUF_INIT; - int result; - - /* the packfile must have been previously loaded! */ - assert(backend->refcache.packfile); if (git_buf_joinpath(&refs_path, backend->path, GIT_REFS_DIR) < 0) return -1; @@ -397,10 +295,11 @@ static int packed_loadloose(refdb_fs_backend *backend) * This will overwrite any old packed entries with their * updated loose versions */ - result = git_path_direach(&refs_path, _dirent_loose_load, backend); + error = git_path_direach(&refs_path, _dirent_loose_load, backend); + git_buf_free(&refs_path); - return result; + return error; } static int refdb_fs_backend__exists( @@ -408,23 +307,17 @@ static int refdb_fs_backend__exists( git_refdb_backend *_backend, const char *ref_name) { - refdb_fs_backend *backend; + refdb_fs_backend *backend = (refdb_fs_backend *)_backend; git_buf ref_path = GIT_BUF_INIT; - assert(_backend); - backend = (refdb_fs_backend *)_backend; + assert(backend); - if (packed_load(backend) < 0) + if (packed_reload(backend) < 0 || + git_buf_joinpath(&ref_path, backend->path, ref_name) < 0) return -1; - if (git_buf_joinpath(&ref_path, backend->path, ref_name) < 0) - return -1; - - if (git_path_isfile(ref_path.ptr) == true || - git_strmap_exists(backend->refcache.packfile, ref_path.ptr)) - *exists = 1; - else - *exists = 0; + *exists = git_path_isfile(ref_path.ptr) || + git_sortedcache_lookup(backend->refcache, ref_name); git_buf_free(&ref_path); return 0; @@ -456,69 +349,39 @@ static int loose_lookup( refdb_fs_backend *backend, const char *ref_name) { - const char *target; - git_oid oid; git_buf ref_file = GIT_BUF_INIT; int error = 0; if (out) *out = NULL; - error = reference_read(&ref_file, NULL, backend->path, ref_name, NULL); + if ((error = loose_readbuffer(&ref_file, backend->path, ref_name)) < 0) + /* cannot read loose ref file - gah */; + else if (git__prefixcmp(git_buf_cstr(&ref_file), GIT_SYMREF) == 0) { + const char *target; - if (error < 0) - goto done; - - if (git__prefixcmp(git_buf_cstr(&ref_file), GIT_SYMREF) == 0) { git_buf_rtrim(&ref_file); - if ((target = loose_parse_symbolic(&ref_file)) == NULL) { + if (!(target = loose_parse_symbolic(&ref_file))) error = -1; - goto done; - } - - if (out) + else if (out != NULL) *out = git_reference__alloc_symbolic(ref_name, target); } else { - if ((error = loose_parse_oid(&oid, ref_name, &ref_file)) < 0) - goto done; + git_oid oid; - if (out) + if (!(error = loose_parse_oid(&oid, ref_name, &ref_file)) && + out != NULL) *out = git_reference__alloc(ref_name, &oid, NULL); } - if (out && *out == NULL) - error = -1; - -done: git_buf_free(&ref_file); return error; } -static int packed_map_entry( - struct packref **entry, - khiter_t *pos, - refdb_fs_backend *backend, - const char *ref_name) +static int ref_error_notfound(const char *name) { - git_strmap *packfile_refs; - - if (packed_load(backend) < 0) - return -1; - - /* Look up on the packfile */ - packfile_refs = backend->refcache.packfile; - - *pos = git_strmap_lookup_index(packfile_refs, ref_name); - - if (!git_strmap_valid_index(packfile_refs, *pos)) { - giterr_set(GITERR_REFERENCE, "Reference '%s' not found", ref_name); - return GIT_ENOTFOUND; - } - - *entry = git_strmap_value_at(packfile_refs, *pos); - - return 0; + giterr_set(GITERR_REFERENCE, "Reference '%s' not found", name); + return GIT_ENOTFOUND; } static int packed_lookup( @@ -526,18 +389,25 @@ static int packed_lookup( refdb_fs_backend *backend, const char *ref_name) { - struct packref *entry; - khiter_t pos; int error = 0; + struct packref *entry; - if ((error = packed_map_entry(&entry, &pos, backend, ref_name)) < 0) - return error; - - if ((*out = git_reference__alloc(ref_name, - &entry->oid, &entry->peel)) == NULL) + if (packed_reload(backend) < 0) return -1; - return 0; + git_sortedcache_lock(backend->refcache); + + entry = git_sortedcache_lookup(backend->refcache, ref_name); + if (!entry) { + error = ref_error_notfound(ref_name); + } else { + *out = git_reference__alloc(ref_name, &entry->oid, &entry->peel); + if (!*out) + error = -1; + } + + git_sortedcache_unlock(backend->refcache); + return error; } static int refdb_fs_backend__lookup( @@ -545,24 +415,22 @@ static int refdb_fs_backend__lookup( git_refdb_backend *_backend, const char *ref_name) { - refdb_fs_backend *backend; - int result; - - assert(_backend); + refdb_fs_backend *backend = (refdb_fs_backend *)_backend; + int error; - backend = (refdb_fs_backend *)_backend; + assert(backend); - if ((result = loose_lookup(out, backend, ref_name)) == 0) + if (!(error = loose_lookup(out, backend, ref_name))) return 0; /* only try to lookup this reference on the packfile if it * wasn't found on the loose refs; not if there was a critical error */ - if (result == GIT_ENOTFOUND) { + if (error == GIT_ENOTFOUND) { giterr_clear(); - result = packed_lookup(out, backend, ref_name); + error = packed_lookup(out, backend, ref_name); } - return result; + return error; } typedef struct { @@ -573,8 +441,8 @@ typedef struct { git_pool pool; git_vector loose; - unsigned int loose_pos; - khiter_t packed_pos; + size_t loose_pos; + size_t packed_pos; } refdb_fs_iter; static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter) @@ -589,7 +457,6 @@ static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter) static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) { int error = 0; - git_strmap *packfile = backend->refcache.packfile; git_buf path = GIT_BUF_INIT; git_iterator *fsit = NULL; const git_index_entry *entry = NULL; @@ -597,18 +464,18 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) if (!backend->path) /* do nothing if no path for loose refs */ return 0; - if (git_buf_printf(&path, "%s/refs", backend->path) < 0) - return -1; + if ((error = git_buf_printf(&path, "%s/refs", backend->path)) < 0 || + (error = git_iterator_for_filesystem( + &fsit, git_buf_cstr(&path), 0, NULL, NULL)) < 0) { + git_buf_free(&path); + return error; + } - if ((error = git_iterator_for_filesystem( - &fsit, git_buf_cstr(&path), 0, NULL, NULL)) < 0 || - (error = git_vector_init(&iter->loose, 8, NULL)) < 0 || - (error = git_buf_sets(&path, GIT_REFS_DIR)) < 0) - goto cleanup; + error = git_buf_sets(&path, GIT_REFS_DIR); - while (!git_iterator_advance(&entry, fsit)) { + while (!error && !git_iterator_advance(&entry, fsit)) { const char *ref_name; - khiter_t pos; + struct packref *ref; char *ref_dup; git_buf_truncate(&path, strlen(GIT_REFS_DIR)); @@ -619,26 +486,23 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) (iter->glob && p_fnmatch(iter->glob, ref_name, 0) != 0)) continue; - pos = git_strmap_lookup_index(packfile, ref_name); - if (git_strmap_valid_index(packfile, pos)) { - struct packref *ref = git_strmap_value_at(packfile, pos); + git_sortedcache_lock(backend->refcache); + ref = git_sortedcache_lookup(backend->refcache, ref_name); + if (ref) ref->flags |= PACKREF_SHADOWED; - } + git_sortedcache_unlock(backend->refcache); - if (!(ref_dup = git_pool_strdup(&iter->pool, ref_name))) { + ref_dup = git_pool_strdup(&iter->pool, ref_name); + if (!ref_dup) error = -1; - goto cleanup; - } - - if ((error = git_vector_insert(&iter->loose, ref_dup)) < 0) - goto cleanup; + else + error = git_vector_insert(&iter->loose, ref_dup); } -cleanup: git_iterator_free(fsit); git_buf_free(&path); - return 0; + return error; } static int refdb_fs_backend__iterator_next( @@ -646,7 +510,7 @@ static int refdb_fs_backend__iterator_next( { refdb_fs_iter *iter = (refdb_fs_iter *)_iter; refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend; - git_strmap *packfile = backend->refcache.packfile; + struct packref *ref; while (iter->loose_pos < iter->loose.length) { const char *path = git_vector_get(&iter->loose, iter->loose_pos++); @@ -657,17 +521,12 @@ static int refdb_fs_backend__iterator_next( giterr_clear(); } - while (iter->packed_pos < kh_end(packfile)) { - struct packref *ref = NULL; + git_sortedcache_lock(backend->refcache); - while (!kh_exist(packfile, iter->packed_pos)) { - iter->packed_pos++; - if (iter->packed_pos == kh_end(packfile)) - return GIT_ITEROVER; - } - - ref = kh_val(packfile, iter->packed_pos); - iter->packed_pos++; + while (iter->packed_pos < git_sortedcache_entrycount(backend->refcache)) { + ref = git_sortedcache_entry(backend->refcache, iter->packed_pos++); + if (!ref) /* stop now if another thread deleted refs and we past end */ + break; if (ref->flags & PACKREF_SHADOWED) continue; @@ -676,12 +535,11 @@ static int refdb_fs_backend__iterator_next( continue; *out = git_reference__alloc(ref->name, &ref->oid, &ref->peel); - if (*out == NULL) - return -1; - - return 0; + git_sortedcache_unlock(backend->refcache); + return (*out != NULL) ? 0 : -1; } + git_sortedcache_unlock(backend->refcache); return GIT_ITEROVER; } @@ -690,14 +548,10 @@ static int refdb_fs_backend__iterator_next_name( { refdb_fs_iter *iter = (refdb_fs_iter *)_iter; refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend; - git_strmap *packfile = backend->refcache.packfile; while (iter->loose_pos < iter->loose.length) { const char *path = git_vector_get(&iter->loose, iter->loose_pos++); - if (git_strmap_exists(packfile, path)) - continue; - if (loose_lookup(NULL, backend, path) != 0) { giterr_clear(); continue; @@ -707,22 +561,25 @@ static int refdb_fs_backend__iterator_next_name( return 0; } - while (iter->packed_pos < kh_end(packfile)) { - while (!kh_exist(packfile, iter->packed_pos)) { - iter->packed_pos++; - if (iter->packed_pos == kh_end(packfile)) - return GIT_ITEROVER; - } + git_sortedcache_lock(backend->refcache); + + while (iter->packed_pos < git_sortedcache_entrycount(backend->refcache)) { + struct packref *ref = + git_sortedcache_entry(backend->refcache, iter->packed_pos++); + + if (ref->flags & PACKREF_SHADOWED) + continue; - *out = kh_key(packfile, iter->packed_pos); - iter->packed_pos++; + *out = ref->name; if (iter->glob && p_fnmatch(iter->glob, *out, 0) != 0) continue; + git_sortedcache_unlock(backend->refcache); return 0; } + git_sortedcache_unlock(backend->refcache); return GIT_ITEROVER; } @@ -730,18 +587,18 @@ static int refdb_fs_backend__iterator( git_reference_iterator **out, git_refdb_backend *_backend, const char *glob) { refdb_fs_iter *iter; - refdb_fs_backend *backend; + refdb_fs_backend *backend = (refdb_fs_backend *)_backend; - assert(_backend); - backend = (refdb_fs_backend *)_backend; + assert(backend); - if (packed_load(backend) < 0) + if (packed_reload(backend) < 0) return -1; iter = git__calloc(1, sizeof(refdb_fs_iter)); GITERR_CHECK_ALLOC(iter); - if (git_pool_init(&iter->pool, 1, 0) < 0) + if (git_pool_init(&iter->pool, 1, 0) < 0 || + git_vector_init(&iter->loose, 8, NULL) < 0) goto fail; if (glob != NULL && @@ -786,15 +643,16 @@ static int reference_path_available( const char* old_ref, int force) { - struct packref *this_ref; + size_t i; - if (packed_load(backend) < 0) + if (packed_reload(backend) < 0) return -1; if (!force) { int exists; - if (refdb_fs_backend__exists(&exists, (git_refdb_backend *)backend, new_ref) < 0) + if (refdb_fs_backend__exists( + &exists, (git_refdb_backend *)backend, new_ref) < 0) return -1; if (exists) { @@ -805,14 +663,21 @@ static int reference_path_available( } } - git_strmap_foreach_value(backend->refcache.packfile, this_ref, { + git_sortedcache_lock(backend->refcache); + + for (i = 0; i < git_sortedcache_entrycount(backend->refcache); ++i) { + struct packref *this_ref = + git_sortedcache_entry(backend->refcache, i); + if (!ref_is_available(old_ref, new_ref, this_ref->name)) { + git_sortedcache_unlock(backend->refcache); giterr_set(GITERR_REFERENCE, "The path to reference '%s' collides with an existing one", new_ref); return -1; } - }); + } + git_sortedcache_unlock(backend->refcache); return 0; } @@ -839,12 +704,9 @@ static int loose_write(refdb_fs_backend *backend, const git_reference *ref) if (ref->type == GIT_REF_OID) { char oid[GIT_OID_HEXSZ + 1]; - - git_oid_fmt(oid, &ref->target.oid); - oid[GIT_OID_HEXSZ] = '\0'; + git_oid_nfmt(oid, sizeof(oid), &ref->target.oid); git_filebuf_printf(&file, "%s\n", oid); - } else if (ref->type == GIT_REF_SYMBOLIC) { git_filebuf_printf(&file, GIT_SYMREF "%s\n", ref->target.symbolic); } else { @@ -854,14 +716,6 @@ static int loose_write(refdb_fs_backend *backend, const git_reference *ref) return git_filebuf_commit(&file, GIT_REFS_FILE_MODE); } -static int packed_sort(const void *a, const void *b) -{ - const struct packref *ref_a = (const struct packref *)a; - const struct packref *ref_b = (const struct packref *)b; - - return strcmp(ref_a->name, ref_b->name); -} - /* * Find out what object this reference resolves to. * @@ -914,9 +768,7 @@ static int packed_find_peel(refdb_fs_backend *backend, struct packref *ref) static int packed_write_ref(struct packref *ref, git_filebuf *file) { char oid[GIT_OID_HEXSZ + 1]; - - git_oid_fmt(oid, &ref->oid); - oid[GIT_OID_HEXSZ] = 0; + git_oid_nfmt(oid, sizeof(oid), &ref->oid); /* * For references that peel to an object in the repo, we must @@ -930,8 +782,7 @@ static int packed_write_ref(struct packref *ref, git_filebuf *file) */ if (ref->flags & PACKREF_HAS_PEEL) { char peel[GIT_OID_HEXSZ + 1]; - git_oid_fmt(peel, &ref->peel); - peel[GIT_OID_HEXSZ] = 0; + git_oid_nfmt(peel, sizeof(peel), &ref->peel); if (git_filebuf_printf(file, "%s %s\n^%s\n", oid, ref->name, peel) < 0) return -1; @@ -954,16 +805,16 @@ static int packed_write_ref(struct packref *ref, git_filebuf *file) * is well-written, because we are destructing references * here otherwise. */ -static int packed_remove_loose( - refdb_fs_backend *backend, - git_vector *packing_list) +static int packed_remove_loose(refdb_fs_backend *backend) { size_t i; git_buf full_path = GIT_BUF_INIT; int failed = 0; - for (i = 0; i < packing_list->length; ++i) { - struct packref *ref = git_vector_get(packing_list, i); + /* backend->refcache is already locked when this is called */ + + for (i = 0; i < git_sortedcache_entrycount(backend->refcache); ++i) { + struct packref *ref = git_sortedcache_entry(backend->refcache, i); if ((ref->flags & PACKREF_WAS_LOOSE) == 0) continue; @@ -971,14 +822,13 @@ static int packed_remove_loose( if (git_buf_joinpath(&full_path, backend->path, ref->name) < 0) return -1; /* critical; do not try to recover on oom */ - if (git_path_exists(full_path.ptr) == true && p_unlink(full_path.ptr) < 0) { + if (git_path_exists(full_path.ptr) && p_unlink(full_path.ptr) < 0) { if (failed) continue; giterr_set(GITERR_REFERENCE, "Failed to remove loose reference '%s' after packing: %s", full_path.ptr, strerror(errno)); - failed = 1; } @@ -1002,33 +852,14 @@ static int packed_write(refdb_fs_backend *backend) git_filebuf pack_file = GIT_FILEBUF_INIT; size_t i; git_buf pack_file_path = GIT_BUF_INIT; - git_vector packing_list; - unsigned int total_refs; - - assert(backend && backend->refcache.packfile); - total_refs = - (unsigned int)git_strmap_num_entries(backend->refcache.packfile); - - if (git_vector_init(&packing_list, total_refs, packed_sort) < 0) + /* lock the cache to updates while we do this */ + if (git_sortedcache_lock(backend->refcache) < 0) return -1; - /* Load all the packfile into a vector */ - { - struct packref *reference; - - /* cannot fail: vector already has the right size */ - git_strmap_foreach_value(backend->refcache.packfile, reference, { - git_vector_insert(&packing_list, reference); - }); - } - - /* sort the vector so the entries appear sorted on the packfile */ - git_vector_sort(&packing_list); - - /* Now we can open the file! */ - if (git_buf_joinpath(&pack_file_path, - backend->path, GIT_PACKEDREFS_FILE) < 0) + /* Open the file! */ + if (git_buf_joinpath( + &pack_file_path, backend->path, GIT_PACKEDREFS_FILE) < 0) goto cleanup_memory; if (git_filebuf_open(&pack_file, pack_file_path.ptr, 0) < 0) @@ -1040,8 +871,9 @@ static int packed_write(refdb_fs_backend *backend) if (git_filebuf_printf(&pack_file, "%s\n", GIT_PACKEDREFS_HEADER) < 0) goto cleanup_packfile; - for (i = 0; i < packing_list.length; ++i) { - struct packref *ref = (struct packref *)git_vector_get(&packing_list, i); + for (i = 0; i < git_sortedcache_entrycount(backend->refcache); ++i) { + struct packref *ref = + git_sortedcache_entry(backend->refcache, i); if (packed_find_peel(backend, ref) < 0) goto cleanup_packfile; @@ -1057,16 +889,16 @@ static int packed_write(refdb_fs_backend *backend) /* when and only when the packfile has been properly written, * we can go ahead and remove the loose refs */ - if (packed_remove_loose(backend, &packing_list) < 0) - goto cleanup_memory; + if (packed_remove_loose(backend) < 0) + goto cleanup_memory; - { - struct stat st; - if (p_stat(pack_file_path.ptr, &st) == 0) - backend->refcache.packfile_time = st.st_mtime; - } + git_sortedcache_unlock(backend->refcache); + + /* update filestamp to latest value */ + if (git_futils_filestamp_check( + &backend->refcache->stamp, pack_file_path.ptr) < 0) + giterr_clear(); - git_vector_free(&packing_list); git_buf_free(&pack_file_path); /* we're good now */ @@ -1076,7 +908,7 @@ cleanup_packfile: git_filebuf_cleanup(&pack_file); cleanup_memory: - git_vector_free(&packing_list); + git_sortedcache_unlock(backend->refcache); git_buf_free(&pack_file_path); return -1; @@ -1087,11 +919,10 @@ static int refdb_fs_backend__write( const git_reference *ref, int force) { - refdb_fs_backend *backend; + refdb_fs_backend *backend = (refdb_fs_backend *)_backend; int error; - assert(_backend); - backend = (refdb_fs_backend *)_backend; + assert(backend); error = reference_path_available(backend, ref->name, NULL, force); if (error < 0) @@ -1104,17 +935,13 @@ static int refdb_fs_backend__delete( git_refdb_backend *_backend, const char *ref_name) { - refdb_fs_backend *backend; + refdb_fs_backend *backend = (refdb_fs_backend *)_backend; git_buf loose_path = GIT_BUF_INIT; - struct packref *pack_ref; - khiter_t pack_ref_pos; + size_t pack_pos; int error = 0; bool loose_deleted = 0; - assert(_backend); - assert(ref_name); - - backend = (refdb_fs_backend *)_backend; + assert(backend && ref_name); /* If a loose reference exists, remove it from the filesystem */ if (git_buf_joinpath(&loose_path, backend->path, ref_name) < 0) @@ -1130,19 +957,23 @@ static int refdb_fs_backend__delete( if (error != 0) return error; + if (packed_reload(backend) < 0) + return -1; + /* If a packed reference exists, remove it from the packfile and repack */ - error = packed_map_entry(&pack_ref, &pack_ref_pos, backend, ref_name); + if (git_sortedcache_lock(backend->refcache) < 0) + return -1; - if (error == GIT_ENOTFOUND) - return loose_deleted ? 0 : GIT_ENOTFOUND; + if (!(error = git_sortedcache_lookup_index( + &pack_pos, backend->refcache, ref_name))) + error = git_sortedcache_remove(backend->refcache, pack_pos, false); - if (error == 0) { - git_strmap_delete_at(backend->refcache.packfile, pack_ref_pos); - git__free(pack_ref); - error = packed_write(backend); - } + git_sortedcache_unlock(backend->refcache); - return error; + if (error == GIT_ENOTFOUND) + return loose_deleted ? 0 : ref_error_notfound(ref_name); + + return packed_write(backend); } static int refdb_fs_backend__rename( @@ -1152,53 +983,44 @@ static int refdb_fs_backend__rename( const char *new_name, int force) { - refdb_fs_backend *backend; + refdb_fs_backend *backend = (refdb_fs_backend *)_backend; git_reference *old, *new; int error; - assert(_backend); - backend = (refdb_fs_backend *)_backend; + assert(backend); - error = reference_path_available(backend, new_name, old_name, force); - if (error < 0) - return error; - - error = refdb_fs_backend__lookup(&old, _backend, old_name); - if (error < 0) + if ((error = reference_path_available( + backend, new_name, old_name, force)) < 0 || + (error = refdb_fs_backend__lookup(&old, _backend, old_name)) < 0) return error; - error = refdb_fs_backend__delete(_backend, old_name); - if (error < 0) { + if ((error = refdb_fs_backend__delete(_backend, old_name)) < 0) { git_reference_free(old); return error; } - new = realloc(old, sizeof(git_reference) + strlen(new_name) + 1); - memcpy(new->name, new_name, strlen(new_name) + 1); - - error = loose_write(backend, new); - if (error < 0) { - git_reference_free(new); - return error; + new = git_reference__set_name(old, new_name); + if (!new) { + git_reference_free(old); + return -1; } - if (out) { - *out = new; - } else { + if ((error = loose_write(backend, new)) < 0 || out == NULL) { git_reference_free(new); + return error; } + *out = new; return 0; } static int refdb_fs_backend__compress(git_refdb_backend *_backend) { - refdb_fs_backend *backend; + refdb_fs_backend *backend = (refdb_fs_backend *)_backend; - assert(_backend); - backend = (refdb_fs_backend *)_backend; + assert(backend); - if (packed_load(backend) < 0 || /* load the existing packfile */ + if (packed_reload(backend) < 0 || /* load the existing packfile */ packed_loadloose(backend) < 0 || /* add all the loose refs */ packed_write(backend) < 0) /* write back to disk */ return -1; @@ -1206,29 +1028,13 @@ static int refdb_fs_backend__compress(git_refdb_backend *_backend) return 0; } -static void refcache_free(git_refcache *refs) -{ - assert(refs); - - if (refs->packfile) { - struct packref *reference; - - git_strmap_foreach_value(refs->packfile, reference, { - git__free(reference); - }); - - git_strmap_free(refs->packfile); - } -} - static void refdb_fs_backend__free(git_refdb_backend *_backend) { - refdb_fs_backend *backend; + refdb_fs_backend *backend = (refdb_fs_backend *)_backend; - assert(_backend); - backend = (refdb_fs_backend *)_backend; + assert(backend); - refcache_free(&backend->refcache); + git_sortedcache_free(backend->refcache); git__free(backend->path); git__free(backend); } @@ -1252,7 +1058,7 @@ static int setup_namespace(git_buf *path, git_repository *repo) if (parts == NULL) return -1; - /** + /* * From `man gitnamespaces`: * namespaces which include a / will expand to a hierarchy * of namespaces; for example, GIT_NAMESPACE=foo/bar will store @@ -1269,7 +1075,7 @@ static int setup_namespace(git_buf *path, git_repository *repo) if (git_futils_mkdir_r(git_buf_cstr(path), repo->path_repository, 0777) < 0) return -1; - /* Return the root of the namespaced path, i.e. without the trailing '/refs' */ + /* Return root of the namespaced path, i.e. without the trailing '/refs' */ git_buf_rtruncate_at_char(path, '/'); return 0; } @@ -1286,13 +1092,19 @@ int git_refdb_backend_fs( backend->repo = repository; - if (setup_namespace(&path, repository) < 0) { - git__free(backend); - return -1; - } + if (setup_namespace(&path, repository) < 0) + goto fail; backend->path = git_buf_detach(&path); + if (git_buf_joinpath(&path, backend->path, GIT_PACKEDREFS_FILE) < 0 || + git_sortedcache_new( + &backend->refcache, offsetof(struct packref, name), + NULL, NULL, packref_cmp, git_buf_cstr(&path)) < 0) + goto fail; + + git_buf_free(&path); + backend->parent.exists = &refdb_fs_backend__exists; backend->parent.lookup = &refdb_fs_backend__lookup; backend->parent.iterator = &refdb_fs_backend__iterator; @@ -1304,4 +1116,10 @@ int git_refdb_backend_fs( *backend_out = (git_refdb_backend *)backend; return 0; + +fail: + git_buf_free(&path); + git__free(backend->path); + git__free(backend); + return -1; } diff --git a/tests-clar/threads/refdb.c b/tests-clar/threads/refdb.c new file mode 100644 index 000000000..11e90a458 --- /dev/null +++ b/tests-clar/threads/refdb.c @@ -0,0 +1,200 @@ +#include "clar_libgit2.h" +#include "git2/refdb.h" +#include "refdb.h" + +static git_repository *g_repo; +static int g_expected = 0; + +void test_threads_refdb__initialize(void) +{ + g_repo = NULL; +} + +void test_threads_refdb__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +#define REPEAT 20 +#define THREADS 20 + +static void *iterate_refs(void *arg) +{ + git_reference_iterator *i; + git_reference *ref; + int count = 0, *id = arg; + + usleep(THREADS - *id); + + cl_git_pass(git_reference_iterator_new(&i, g_repo)); + + for (count = 0; !git_reference_next(&ref, i); ++count) { + cl_assert(ref != NULL); + git_reference_free(ref); + } + + if (g_expected > 0) + cl_assert_equal_i(g_expected, count); + + git_reference_iterator_free(i); + + return arg; +} + +void test_threads_refdb__iterator(void) +{ + int r, t; + git_thread th[THREADS]; + int id[THREADS]; + git_oid head; + git_reference *ref; + char name[128]; + git_refdb *refdb; + + g_repo = cl_git_sandbox_init("testrepo2"); + + cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); + + /* make a bunch of references */ + + for (r = 0; r < 200; ++r) { + snprintf(name, sizeof(name), "refs/heads/direct-%03d", r); + cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0)); + git_reference_free(ref); + } + + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + git_refdb_free(refdb); + + g_expected = 206; + + for (r = 0; r < REPEAT; ++r) { + g_repo = cl_git_sandbox_reopen(); /* reopen to flush caches */ + + for (t = 0; t < THREADS; ++t) { + id[t] = t; + cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t])); + } + + for (t = 0; t < THREADS; ++t) { + cl_git_pass(git_thread_join(th[t], NULL)); + } + + memset(th, 0, sizeof(th)); + } +} + +static void *create_refs(void *arg) +{ + int *id = arg, i; + git_oid head; + char name[128]; + git_reference *ref[10]; + + cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); + + for (i = 0; i < 10; ++i) { + snprintf(name, sizeof(name), "refs/heads/thread-%03d-%02d", *id, i); + cl_git_pass(git_reference_create(&ref[i], g_repo, name, &head, 0)); + + if (i == 5) { + git_refdb *refdb; + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + git_refdb_free(refdb); + } + } + + for (i = 0; i < 10; ++i) + git_reference_free(ref[i]); + + return arg; +} + +static void *delete_refs(void *arg) +{ + int *id = arg, i; + git_reference *ref; + char name[128]; + + for (i = 0; i < 10; ++i) { + snprintf( + name, sizeof(name), "refs/heads/thread-%03d-%02d", (*id) & ~0x3, i); + + if (!git_reference_lookup(&ref, g_repo, name)) { + fprintf(stderr, "deleting %s\n", name); + cl_git_pass(git_reference_delete(ref)); + git_reference_delete(ref); + } + + if (i == 5) { + git_refdb *refdb; + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + git_refdb_free(refdb); + } + } + + return arg; +} + +void test_threads_refdb__edit_while_iterate(void) +{ + int r, t; + git_thread th[THREADS]; + int id[THREADS]; + git_oid head; + git_reference *ref; + char name[128]; + git_refdb *refdb; + + g_repo = cl_git_sandbox_init("testrepo2"); + + cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); + + /* make a bunch of references */ + + for (r = 0; r < 50; ++r) { + snprintf(name, sizeof(name), "refs/heads/starter-%03d", r); + cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0)); + git_reference_free(ref); + } + + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + git_refdb_free(refdb); + + g_expected = -1; + + g_repo = cl_git_sandbox_reopen(); /* reopen to flush caches */ + + for (t = 0; t < THREADS; ++t) { + void *(*fn)(void *arg); + + switch (t & 0x3) { + case 0: fn = create_refs; break; + case 1: fn = delete_refs; break; + default: fn = iterate_refs; break; + } + + id[t] = t; + cl_git_pass(git_thread_create(&th[t], NULL, fn, &id[t])); + } + + for (t = 0; t < THREADS; ++t) { + cl_git_pass(git_thread_join(th[t], NULL)); + } + + memset(th, 0, sizeof(th)); + + for (t = 0; t < THREADS; ++t) { + id[t] = t; + cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t])); + } + + for (t = 0; t < THREADS; ++t) { + cl_git_pass(git_thread_join(th[t], NULL)); + } +} -- cgit v1.2.1 From b37359aac5b02f59c07b453b53191432abc0f942 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 21 Aug 2013 16:50:03 -0700 Subject: Fix warnings when compiling without threads --- src/sortedcache.c | 2 ++ tests-clar/threads/refdb.c | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/sortedcache.c b/src/sortedcache.c index 2efa3c4e9..d7e74d3e5 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -176,6 +176,8 @@ bool git_sortedcache_out_of_date(git_sortedcache *sc) /* lock sortedcache while making modifications */ int git_sortedcache_lock(git_sortedcache *sc) { + GIT_UNUSED(sc); /* to prevent warning when compiled w/o threads */ + if (git_mutex_lock(&sc->lock) < 0) { giterr_set(GITERR_OS, "Unable to acquire mutex lock"); return -1; diff --git a/tests-clar/threads/refdb.c b/tests-clar/threads/refdb.c index 11e90a458..ffe437575 100644 --- a/tests-clar/threads/refdb.c +++ b/tests-clar/threads/refdb.c @@ -23,9 +23,7 @@ static void *iterate_refs(void *arg) { git_reference_iterator *i; git_reference *ref; - int count = 0, *id = arg; - - usleep(THREADS - *id); + int count = 0; cl_git_pass(git_reference_iterator_new(&i, g_repo)); @@ -75,12 +73,19 @@ void test_threads_refdb__iterator(void) for (t = 0; t < THREADS; ++t) { id[t] = t; +#ifdef GIT_THREADS cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t])); +#else + th[t] = t; + iterate_refs(&id[t]); +#endif } +#ifdef GIT_THREADS for (t = 0; t < THREADS; ++t) { cl_git_pass(git_thread_join(th[t], NULL)); } +#endif memset(th, 0, sizeof(th)); } @@ -124,7 +129,6 @@ static void *delete_refs(void *arg) name, sizeof(name), "refs/heads/thread-%03d-%02d", (*id) & ~0x3, i); if (!git_reference_lookup(&ref, g_repo, name)) { - fprintf(stderr, "deleting %s\n", name); cl_git_pass(git_reference_delete(ref)); git_reference_delete(ref); } @@ -180,9 +184,15 @@ void test_threads_refdb__edit_while_iterate(void) } id[t] = t; +#ifdef GIT_THREADS cl_git_pass(git_thread_create(&th[t], NULL, fn, &id[t])); +#else + th[t] = t; + fn(&id[t]); +#endif } +#ifdef GIT_THREADS for (t = 0; t < THREADS; ++t) { cl_git_pass(git_thread_join(th[t], NULL)); } @@ -197,4 +207,5 @@ void test_threads_refdb__edit_while_iterate(void) for (t = 0; t < THREADS; ++t) { cl_git_pass(git_thread_join(th[t], NULL)); } +#endif } -- cgit v1.2.1 From e8c5eb5537cc58fa29d4ed48ab9114238ba4cab0 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 21 Aug 2013 22:44:56 -0700 Subject: No need to lock newly created tgt in copy --- src/sortedcache.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sortedcache.c b/src/sortedcache.c index d7e74d3e5..d0a8031c3 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -130,9 +130,6 @@ int git_sortedcache_copy( return -1; } - if (git_sortedcache_lock(tgt) < 0) - goto fail; - git_vector_foreach(&src->items, i, src_item) { if (git_sortedcache_upsert( &tgt_item, tgt, ((char *)src_item) + src->item_path_offset) < 0) @@ -141,7 +138,6 @@ int git_sortedcache_copy( goto fail; } - git_sortedcache_unlock(tgt); git_sortedcache_unlock(src); *out = tgt; -- cgit v1.2.1 From 3eecadcce583fd7e825e35e2b6f101071c2be613 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 21 Aug 2013 22:50:37 -0700 Subject: Improve comments on locking for sortedcache APIs --- src/sortedcache.h | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/sortedcache.h b/src/sortedcache.h index f63ad645b..c1c9d1341 100644 --- a/src/sortedcache.h +++ b/src/sortedcache.h @@ -62,22 +62,24 @@ int git_sortedcache_copy( int (*copy_item)(void *payload, void *tgt_item, void *src_item), void *payload); -/* free sorted cache (first calling free_item callbacks) */ +/* free sorted cache (first calling free_item callbacks) + * don't call on a locked collection - it may acquire a lock + */ void git_sortedcache_free(git_sortedcache *sc); -/* increment reference count */ +/* increment reference count - balance with call to free */ void git_sortedcache_incref(git_sortedcache *sc); -/* release all items in sorted cache - lock during clear if lock is true */ +/* release all items in sorted cache - lock during clear if `lock` is true */ void git_sortedcache_clear(git_sortedcache *sc, bool lock); /* check file stamp to see if reload is required */ bool git_sortedcache_out_of_date(git_sortedcache *sc); -/* lock sortedcache while making modifications */ +/* lock sortedcache during access or modification */ int git_sortedcache_lock(git_sortedcache *sc); -/* unlock sorted cache when done with modifications */ +/* unlock sorted cache when done */ int git_sortedcache_unlock(git_sortedcache *sc); /* if the file has changed, lock cache and load file contents into buf; @@ -85,24 +87,33 @@ int git_sortedcache_unlock(git_sortedcache *sc); */ int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf); -/* find and/or insert item, returning pointer to item data - lock first */ +/* find and/or insert item, returning pointer to item data + * should only call on locked collection + */ int git_sortedcache_upsert( void **out, git_sortedcache *sc, const char *key); -/* lookup item by key */ +/* lookup item by key + * should only call on locked collection if return value will be used + */ void *git_sortedcache_lookup(const git_sortedcache *sc, const char *key); /* find out how many items are in the cache */ size_t git_sortedcache_entrycount(const git_sortedcache *sc); -/* lookup item by index */ +/* lookup item by index + * should only call on locked collection if return value will be used + */ void *git_sortedcache_entry(const git_sortedcache *sc, size_t pos); -/* lookup index of item by key */ +/* lookup index of item by key + * if collection is not locked, there is no guarantee the returned index + * will be correct if it used to look up the item + */ int git_sortedcache_lookup_index( size_t *out, git_sortedcache *sc, const char *key); -/* remove entry from cache */ +/* remove entry from cache - lock during delete if `lock` is true */ int git_sortedcache_remove(git_sortedcache *sc, size_t pos, bool lock); #endif -- cgit v1.2.1 From 8d9a85d43aa6ed7a9fb15a2ac9e0f9ba1c33461e Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 22 Aug 2013 11:40:53 -0700 Subject: Convert sortedcache to use rwlock This is the first use we have of pthread_rwlock_t in libgit2. Hopefully it won't cause any serious portability problems. --- src/refdb_fs.c | 131 ++++++++++++++++------------------- src/sortedcache.c | 155 ++++++++++++++++++++++++------------------ src/sortedcache.h | 106 +++++++++++++++++++---------- src/thread-utils.h | 27 +++++++- tests-clar/core/sortedcache.c | 31 ++++++--- 5 files changed, 265 insertions(+), 185 deletions(-) diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 876e84588..04516a5b0 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -172,7 +172,7 @@ static int packed_reload(refdb_fs_backend *backend) ref->flags |= PACKREF_CANNOT_PEEL; } - git_sortedcache_unlock(backend->refcache); + git_sortedcache_wunlock(backend->refcache); git_buf_free(&packedrefs); return 0; @@ -181,7 +181,7 @@ parse_failed: giterr_set(GITERR_REFERENCE, "Corrupted packed references file"); git_sortedcache_clear(backend->refcache, false); - git_sortedcache_unlock(backend->refcache); + git_sortedcache_wunlock(backend->refcache); git_buf_free(&packedrefs); return -1; @@ -244,7 +244,7 @@ static int loose_lookup_to_packfile(refdb_fs_backend *backend, const char *name) if ((error = loose_parse_oid(&oid, name, &ref_file)) < 0) goto done; - git_sortedcache_lock(backend->refcache); + git_sortedcache_wlock(backend->refcache); if (!(error = git_sortedcache_upsert( (void **)&ref, backend->refcache, name))) { @@ -253,7 +253,7 @@ static int loose_lookup_to_packfile(refdb_fs_backend *backend, const char *name) ref->flags = PACKREF_WAS_LOOSE; } - git_sortedcache_unlock(backend->refcache); + git_sortedcache_wunlock(backend->refcache); done: git_buf_free(&ref_file); @@ -317,7 +317,7 @@ static int refdb_fs_backend__exists( return -1; *exists = git_path_isfile(ref_path.ptr) || - git_sortedcache_lookup(backend->refcache, ref_name); + (git_sortedcache_lookup(backend->refcache, ref_name) != NULL); git_buf_free(&ref_path); return 0; @@ -395,7 +395,8 @@ static int packed_lookup( if (packed_reload(backend) < 0) return -1; - git_sortedcache_lock(backend->refcache); + if (git_sortedcache_rlock(backend->refcache) < 0) + return -1; entry = git_sortedcache_lookup(backend->refcache, ref_name); if (!entry) { @@ -406,7 +407,8 @@ static int packed_lookup( error = -1; } - git_sortedcache_unlock(backend->refcache); + git_sortedcache_runlock(backend->refcache); + return error; } @@ -486,11 +488,11 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) (iter->glob && p_fnmatch(iter->glob, ref_name, 0) != 0)) continue; - git_sortedcache_lock(backend->refcache); + git_sortedcache_rlock(backend->refcache); ref = git_sortedcache_lookup(backend->refcache, ref_name); if (ref) ref->flags |= PACKREF_SHADOWED; - git_sortedcache_unlock(backend->refcache); + git_sortedcache_runlock(backend->refcache); ref_dup = git_pool_strdup(&iter->pool, ref_name); if (!ref_dup) @@ -508,6 +510,7 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) static int refdb_fs_backend__iterator_next( git_reference **out, git_reference_iterator *_iter) { + int error = GIT_ITEROVER; refdb_fs_iter *iter = (refdb_fs_iter *)_iter; refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend; struct packref *ref; @@ -521,7 +524,7 @@ static int refdb_fs_backend__iterator_next( giterr_clear(); } - git_sortedcache_lock(backend->refcache); + git_sortedcache_rlock(backend->refcache); while (iter->packed_pos < git_sortedcache_entrycount(backend->refcache)) { ref = git_sortedcache_entry(backend->refcache, iter->packed_pos++); @@ -530,57 +533,56 @@ static int refdb_fs_backend__iterator_next( if (ref->flags & PACKREF_SHADOWED) continue; - if (iter->glob && p_fnmatch(iter->glob, ref->name, 0) != 0) continue; *out = git_reference__alloc(ref->name, &ref->oid, &ref->peel); - git_sortedcache_unlock(backend->refcache); - return (*out != NULL) ? 0 : -1; + error = (*out != NULL) ? 0 : -1; + break; } - git_sortedcache_unlock(backend->refcache); - return GIT_ITEROVER; + git_sortedcache_runlock(backend->refcache); + return error; } static int refdb_fs_backend__iterator_next_name( const char **out, git_reference_iterator *_iter) { + int error = GIT_ITEROVER; refdb_fs_iter *iter = (refdb_fs_iter *)_iter; refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend; + struct packref *ref; while (iter->loose_pos < iter->loose.length) { const char *path = git_vector_get(&iter->loose, iter->loose_pos++); - if (loose_lookup(NULL, backend, path) != 0) { - giterr_clear(); - continue; + if (loose_lookup(NULL, backend, path) == 0) { + *out = path; + return 0; } - *out = path; - return 0; + giterr_clear(); } - git_sortedcache_lock(backend->refcache); + git_sortedcache_rlock(backend->refcache); while (iter->packed_pos < git_sortedcache_entrycount(backend->refcache)) { - struct packref *ref = - git_sortedcache_entry(backend->refcache, iter->packed_pos++); + ref = git_sortedcache_entry(backend->refcache, iter->packed_pos++); + if (!ref) /* stop now if another thread deleted refs and we past end */ + break; if (ref->flags & PACKREF_SHADOWED) continue; - - *out = ref->name; - - if (iter->glob && p_fnmatch(iter->glob, *out, 0) != 0) + if (iter->glob && p_fnmatch(iter->glob, ref->name, 0) != 0) continue; - git_sortedcache_unlock(backend->refcache); - return 0; + *out = ref->name; + error = 0; + break; } - git_sortedcache_unlock(backend->refcache); - return GIT_ITEROVER; + git_sortedcache_runlock(backend->refcache); + return error; } static int refdb_fs_backend__iterator( @@ -658,26 +660,25 @@ static int reference_path_available( if (exists) { giterr_set(GITERR_REFERENCE, "Failed to write reference '%s': a reference with " - " that name already exists.", new_ref); + "that name already exists.", new_ref); return GIT_EEXISTS; } } - git_sortedcache_lock(backend->refcache); + git_sortedcache_rlock(backend->refcache); for (i = 0; i < git_sortedcache_entrycount(backend->refcache); ++i) { - struct packref *this_ref = - git_sortedcache_entry(backend->refcache, i); + struct packref *ref = git_sortedcache_entry(backend->refcache, i); - if (!ref_is_available(old_ref, new_ref, this_ref->name)) { - git_sortedcache_unlock(backend->refcache); + if (ref && !ref_is_available(old_ref, new_ref, ref->name)) { + git_sortedcache_runlock(backend->refcache); giterr_set(GITERR_REFERENCE, - "The path to reference '%s' collides with an existing one", new_ref); + "Path to reference '%s' collides with existing one", new_ref); return -1; } } - git_sortedcache_unlock(backend->refcache); + git_sortedcache_runlock(backend->refcache); return 0; } @@ -816,7 +817,7 @@ static int packed_remove_loose(refdb_fs_backend *backend) for (i = 0; i < git_sortedcache_entrycount(backend->refcache); ++i) { struct packref *ref = git_sortedcache_entry(backend->refcache, i); - if ((ref->flags & PACKREF_WAS_LOOSE) == 0) + if (!ref || !(ref->flags & PACKREF_WAS_LOOSE)) continue; if (git_buf_joinpath(&full_path, backend->path, ref->name) < 0) @@ -849,67 +850,53 @@ static int packed_remove_loose(refdb_fs_backend *backend) */ static int packed_write(refdb_fs_backend *backend) { + git_sortedcache *refcache = backend->refcache; git_filebuf pack_file = GIT_FILEBUF_INIT; size_t i; - git_buf pack_file_path = GIT_BUF_INIT; /* lock the cache to updates while we do this */ - if (git_sortedcache_lock(backend->refcache) < 0) + if (git_sortedcache_wlock(refcache) < 0) return -1; /* Open the file! */ - if (git_buf_joinpath( - &pack_file_path, backend->path, GIT_PACKEDREFS_FILE) < 0) - goto cleanup_memory; - - if (git_filebuf_open(&pack_file, pack_file_path.ptr, 0) < 0) - goto cleanup_packfile; + if (git_filebuf_open(&pack_file, git_sortedcache_path(refcache), 0) < 0) + goto fail; /* Packfiles have a header... apparently * This is in fact not required, but we might as well print it * just for kicks */ if (git_filebuf_printf(&pack_file, "%s\n", GIT_PACKEDREFS_HEADER) < 0) - goto cleanup_packfile; + goto fail; - for (i = 0; i < git_sortedcache_entrycount(backend->refcache); ++i) { - struct packref *ref = - git_sortedcache_entry(backend->refcache, i); + for (i = 0; i < git_sortedcache_entrycount(refcache); ++i) { + struct packref *ref = git_sortedcache_entry(refcache, i); if (packed_find_peel(backend, ref) < 0) - goto cleanup_packfile; + goto fail; if (packed_write_ref(ref, &pack_file) < 0) - goto cleanup_packfile; + goto fail; } /* if we've written all the references properly, we can commit * the packfile to make the changes effective */ if (git_filebuf_commit(&pack_file, GIT_PACKEDREFS_FILE_MODE) < 0) - goto cleanup_memory; + goto fail; /* when and only when the packfile has been properly written, * we can go ahead and remove the loose refs */ if (packed_remove_loose(backend) < 0) - goto cleanup_memory; - - git_sortedcache_unlock(backend->refcache); - - /* update filestamp to latest value */ - if (git_futils_filestamp_check( - &backend->refcache->stamp, pack_file_path.ptr) < 0) - giterr_clear(); + goto fail; - git_buf_free(&pack_file_path); + git_sortedcache_updated(refcache); + git_sortedcache_wunlock(refcache); /* we're good now */ return 0; -cleanup_packfile: +fail: git_filebuf_cleanup(&pack_file); - -cleanup_memory: - git_sortedcache_unlock(backend->refcache); - git_buf_free(&pack_file_path); + git_sortedcache_wunlock(refcache); return -1; } @@ -961,14 +948,14 @@ static int refdb_fs_backend__delete( return -1; /* If a packed reference exists, remove it from the packfile and repack */ - if (git_sortedcache_lock(backend->refcache) < 0) + if (git_sortedcache_wlock(backend->refcache) < 0) return -1; if (!(error = git_sortedcache_lookup_index( &pack_pos, backend->refcache, ref_name))) - error = git_sortedcache_remove(backend->refcache, pack_pos, false); + error = git_sortedcache_remove(backend->refcache, pack_pos); - git_sortedcache_unlock(backend->refcache); + git_sortedcache_wunlock(backend->refcache); if (error == GIT_ENOTFOUND) return loose_deleted ? 0 : ref_error_notfound(ref_name); diff --git a/src/sortedcache.c b/src/sortedcache.c index d0a8031c3..c087dbbe9 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -23,13 +23,13 @@ int git_sortedcache_new( (sc->map = git_strmap_alloc()) == NULL) goto fail; - if (git_mutex_init(&sc->lock)) { - giterr_set(GITERR_OS, "Failed to initialize mutex"); + if (git_rwlock_init(&sc->lock)) { + giterr_set(GITERR_OS, "Failed to initialize lock"); goto fail; } - sc->item_path_offset = item_path_offset; - sc->free_item = free_item; + sc->item_path_offset = item_path_offset; + sc->free_item = free_item; sc->free_item_payload = free_item_payload; GIT_REFCOUNT_INC(sc); if (pathlen) @@ -52,6 +52,11 @@ void git_sortedcache_incref(git_sortedcache *sc) GIT_REFCOUNT_INC(sc); } +const char *git_sortedcache_path(git_sortedcache *sc) +{ + return sc->path; +} + static void sortedcache_clear(git_sortedcache *sc) { git_strmap_clear(sc->map); @@ -72,19 +77,17 @@ static void sortedcache_clear(git_sortedcache *sc) static void sortedcache_free(git_sortedcache *sc) { - if (git_mutex_lock(&sc->lock) < 0) { - giterr_set(GITERR_OS, "Unable to acquire mutex lock for free"); + /* acquire write lock to make sure everyone else is done */ + if (git_sortedcache_wlock(sc) < 0) return; - } sortedcache_clear(sc); - git_vector_free(&sc->items); git_strmap_free(sc->map); - git_mutex_unlock(&sc->lock); - git_mutex_free(&sc->lock); + git_sortedcache_wunlock(sc); + git_rwlock_free(&sc->lock); git__free(sc); } @@ -107,86 +110,86 @@ static int sortedcache_copy_item(void *payload, void *tgt_item, void *src_item) int git_sortedcache_copy( git_sortedcache **out, git_sortedcache *src, + bool wlock, int (*copy_item)(void *payload, void *tgt_item, void *src_item), void *payload) { + int error = 0; git_sortedcache *tgt; size_t i; void *src_item, *tgt_item; + /* just use memcpy if no special copy fn is passed in */ if (!copy_item) { copy_item = sortedcache_copy_item; payload = src; } - if (git_sortedcache_new( + if ((error = git_sortedcache_new( &tgt, src->item_path_offset, src->free_item, src->free_item_payload, - src->items._cmp, src->path) < 0) - return -1; + src->items._cmp, src->path)) < 0) + return error; - if (git_sortedcache_lock(src) < 0) { + if (wlock && git_sortedcache_wlock(src) < 0) { git_sortedcache_free(tgt); return -1; } git_vector_foreach(&src->items, i, src_item) { - if (git_sortedcache_upsert( - &tgt_item, tgt, ((char *)src_item) + src->item_path_offset) < 0) - goto fail; - if (copy_item(payload, tgt_item, src_item) < 0) - goto fail; + char *path = ((char *)src_item) + src->item_path_offset; + + if ((error = git_sortedcache_upsert(&tgt_item, tgt, path)) < 0 || + (error = copy_item(payload, tgt_item, src_item)) < 0) + break; } - git_sortedcache_unlock(src); + if (wlock) + git_sortedcache_wunlock(src); + if (error) + git_sortedcache_free(tgt); - *out = tgt; - return 0; + *out = !error ? tgt : NULL; -fail: - git_sortedcache_unlock(src); - git_sortedcache_free(tgt); - return -1; + return error; } -/* release all items in sorted cache */ -void git_sortedcache_clear(git_sortedcache *sc, bool lock) +/* lock sortedcache while making modifications */ +int git_sortedcache_wlock(git_sortedcache *sc) { - if (lock && git_mutex_lock(&sc->lock) < 0) { - giterr_set(GITERR_OS, "Unable to acquire mutex lock for clear"); - return; - } + GIT_UNUSED(sc); /* prevent warning when compiled w/o threads */ - sortedcache_clear(sc); - - if (lock) - git_mutex_unlock(&sc->lock); + if (git_rwlock_wrlock(&sc->lock) < 0) { + giterr_set(GITERR_OS, "Unable to acquire write lock on cache"); + return -1; + } + return 0; } -/* check file stamp to see if reload is required */ -bool git_sortedcache_out_of_date(git_sortedcache *sc) +/* unlock sorted cache when done with modifications */ +void git_sortedcache_wunlock(git_sortedcache *sc) { - return (git_futils_filestamp_check(&sc->stamp, sc->path) != 0); + git_vector_sort(&sc->items); + git_rwlock_wrunlock(&sc->lock); } -/* lock sortedcache while making modifications */ -int git_sortedcache_lock(git_sortedcache *sc) +/* lock sortedcache for read */ +int git_sortedcache_rlock(git_sortedcache *sc) { - GIT_UNUSED(sc); /* to prevent warning when compiled w/o threads */ + GIT_UNUSED(sc); /* prevent warning when compiled w/o threads */ - if (git_mutex_lock(&sc->lock) < 0) { - giterr_set(GITERR_OS, "Unable to acquire mutex lock"); + if (git_rwlock_rdlock(&sc->lock) < 0) { + giterr_set(GITERR_OS, "Unable to acquire read lock on cache"); return -1; } return 0; } -/* unlock sorted cache when done with modifications */ -int git_sortedcache_unlock(git_sortedcache *sc) +/* unlock sorted cache when done reading */ +void git_sortedcache_runlock(git_sortedcache *sc) { - git_vector_sort(&sc->items); - git_mutex_unlock(&sc->lock); - return 0; + GIT_UNUSED(sc); /* prevent warning when compiled w/o threads */ + git_rwlock_rdunlock(&sc->lock); } /* if the file has changed, lock cache and load file contents into buf; @@ -196,7 +199,7 @@ int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf) { int error, fd; - if ((error = git_sortedcache_lock(sc)) < 0) + if ((error = git_sortedcache_wlock(sc)) < 0) return error; if ((error = git_futils_filestamp_check(&sc->stamp, sc->path)) <= 0) @@ -224,13 +227,33 @@ int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf) return 1; /* return 1 -> file needs reload and was successfully loaded */ unlock: - git_sortedcache_unlock(sc); + git_sortedcache_wunlock(sc); return error; } +void git_sortedcache_updated(git_sortedcache *sc) +{ + /* update filestamp to latest value */ + if (git_futils_filestamp_check(&sc->stamp, sc->path) < 0) + giterr_clear(); +} + +/* release all items in sorted cache */ +int git_sortedcache_clear(git_sortedcache *sc, bool wlock) +{ + if (wlock && git_sortedcache_wlock(sc) < 0) + return -1; + + sortedcache_clear(sc); + + if (wlock) + git_sortedcache_wunlock(sc); + + return 0; +} + /* find and/or insert item, returning pointer to item data */ -int git_sortedcache_upsert( - void **out, git_sortedcache *sc, const char *key) +int git_sortedcache_upsert(void **out, git_sortedcache *sc, const char *key) { int error = 0; khiter_t pos; @@ -246,7 +269,10 @@ int git_sortedcache_upsert( keylen = strlen(key); item = git_pool_mallocz(&sc->pool, sc->item_path_offset + keylen + 1); - GITERR_CHECK_ALLOC(item); + if (!item) { /* don't use GITERR_CHECK_ALLOC b/c of lock */ + error = -1; + goto done; + } /* one strange thing is that even if the vector or hash table insert * fail, there is no way to free the pool item so we just abandon it @@ -289,11 +315,16 @@ size_t git_sortedcache_entrycount(const git_sortedcache *sc) } /* lookup item by index */ -void *git_sortedcache_entry(const git_sortedcache *sc, size_t pos) +void *git_sortedcache_entry(git_sortedcache *sc, size_t pos) { + /* make sure the items are sorted so this gets the correct item */ + if (!sc->items.sorted) + git_vector_sort(&sc->items); + return git_vector_get(&sc->items, pos); } +/* helper struct so bsearch callback can know offset + key value for cmp */ struct sortedcache_magic_key { size_t offset; const char *key; @@ -319,23 +350,18 @@ int git_sortedcache_lookup_index( } /* remove entry from cache */ -int git_sortedcache_remove(git_sortedcache *sc, size_t pos, bool lock) +int git_sortedcache_remove(git_sortedcache *sc, size_t pos) { - int error = 0; char *item; khiter_t mappos; - if (lock && git_sortedcache_lock(sc) < 0) - return -1; - /* because of pool allocation, this can't actually remove the item, * but we can remove it from the items vector and the hash table. */ if ((item = git_vector_get(&sc->items, pos)) == NULL) { giterr_set(GITERR_INVALID, "Removing item out of range"); - error = GIT_ENOTFOUND; - goto done; + return GIT_ENOTFOUND; } (void)git_vector_remove(&sc->items, pos); @@ -346,9 +372,6 @@ int git_sortedcache_remove(git_sortedcache *sc, size_t pos, bool lock) if (sc->free_item) sc->free_item(sc->free_item_payload, item); -done: - if (lock) - git_sortedcache_unlock(sc); - return error; + return 0; } diff --git a/src/sortedcache.h b/src/sortedcache.h index c1c9d1341..7d1cd2f14 100644 --- a/src/sortedcache.h +++ b/src/sortedcache.h @@ -25,7 +25,7 @@ typedef void (*git_sortedcache_free_item_fn)(void *payload, void *item); typedef struct { git_refcount rc; - git_mutex lock; + git_rwlock lock; size_t item_path_offset; git_sortedcache_free_item_fn free_item; void *free_item_payload; @@ -36,84 +36,120 @@ typedef struct { char path[GIT_FLEX_ARRAY]; } git_sortedcache; -/* create a new sortedcache +/* Create a new sortedcache * - * even though every sortedcache stores items with a GIT_FLEX_ARRAY at + * Even though every sortedcache stores items with a GIT_FLEX_ARRAY at * the end containing their key string, you have to provide the item_cmp * sorting function because the sorting function doesn't get a payload * and therefore can't know the offset to the item key string. :-( */ int git_sortedcache_new( git_sortedcache **out, - size_t item_path_offset, /* use offsetof() macro */ + size_t item_path_offset, /* use offsetof(struct, path-field) macro */ git_sortedcache_free_item_fn free_item, void *free_item_payload, git_vector_cmp item_cmp, const char *path); -/* copy a sorted cache +/* Copy a sorted cache * - * - copy_item can be NULL to memcpy - * - locks src while copying + * - `copy_item` can be NULL to just use memcpy + * - if `wlock`, grabs write lock on `src` during copy and releases after */ int git_sortedcache_copy( git_sortedcache **out, git_sortedcache *src, + bool wlock, int (*copy_item)(void *payload, void *tgt_item, void *src_item), void *payload); -/* free sorted cache (first calling free_item callbacks) - * don't call on a locked collection - it may acquire a lock +/* Free sorted cache (first calling `free_item` callbacks) + * + * Don't call on a locked collection - it may acquire a write lock */ void git_sortedcache_free(git_sortedcache *sc); -/* increment reference count - balance with call to free */ +/* Increment reference count - balance with call to free */ void git_sortedcache_incref(git_sortedcache *sc); -/* release all items in sorted cache - lock during clear if `lock` is true */ -void git_sortedcache_clear(git_sortedcache *sc, bool lock); +/* Get the pathname associated with this cache at creation time */ +const char *git_sortedcache_path(git_sortedcache *sc); -/* check file stamp to see if reload is required */ -bool git_sortedcache_out_of_date(git_sortedcache *sc); +/* + * CACHE WRITE FUNCTIONS + * + * The following functions require you to have a writer lock to make the + * modification. Some of the functions take a `wlock` parameter and + * will optionally lock and unlock for you if that is passed as true. + * + */ -/* lock sortedcache during access or modification */ -int git_sortedcache_lock(git_sortedcache *sc); +/* Lock sortedcache for write */ +int git_sortedcache_wlock(git_sortedcache *sc); -/* unlock sorted cache when done */ -int git_sortedcache_unlock(git_sortedcache *sc); +/* Unlock sorted cache when done with write */ +void git_sortedcache_wunlock(git_sortedcache *sc); -/* if the file has changed, lock cache and load file contents into buf; +/* Lock cache and test if the file has changed. If the file has changed, + * then load the contents into `buf` otherwise unlock and return 0. + * * @return 0 if up-to-date, 1 if out-of-date, <0 on error */ int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf); -/* find and/or insert item, returning pointer to item data - * should only call on locked collection +/* Refresh file timestamp after write completes + * You should already be holding the write lock when you call this. + */ +void git_sortedcache_updated(git_sortedcache *sc); + +/* Release all items in sorted cache + * + * If `wlock` is true, grabs write lock and releases when done, otherwise + * you should already be holding a write lock when you call this. + */ +int git_sortedcache_clear(git_sortedcache *sc, bool wlock); + +/* Find and/or insert item, returning pointer to item data. + * You should already be holding the write lock when you call this. */ int git_sortedcache_upsert( void **out, git_sortedcache *sc, const char *key); -/* lookup item by key - * should only call on locked collection if return value will be used +/* Removes entry at pos from cache + * You should already be holding the write lock when you call this. + */ +int git_sortedcache_remove(git_sortedcache *sc, size_t pos); + +/* + * CACHE READ FUNCTIONS + * + * The following functions access items in the cache. To prevent the + * results from being invalidated before they can be used, you should be + * holding either a read lock or a write lock when using these functions. + * */ + +/* Lock sortedcache for read */ +int git_sortedcache_rlock(git_sortedcache *sc); + +/* Unlock sorted cache when done with read */ +void git_sortedcache_runlock(git_sortedcache *sc); + +/* Lookup item by key - returns NULL if not found */ void *git_sortedcache_lookup(const git_sortedcache *sc, const char *key); -/* find out how many items are in the cache */ +/* Get how many items are in the cache + * + * You can call this function without holding a lock, but be aware + * that it may change before you use it. + */ size_t git_sortedcache_entrycount(const git_sortedcache *sc); -/* lookup item by index - * should only call on locked collection if return value will be used - */ -void *git_sortedcache_entry(const git_sortedcache *sc, size_t pos); +/* Lookup item by index - returns NULL if out of range */ +void *git_sortedcache_entry(git_sortedcache *sc, size_t pos); -/* lookup index of item by key - * if collection is not locked, there is no guarantee the returned index - * will be correct if it used to look up the item - */ +/* Lookup index of item by key - returns GIT_ENOTFOUND if not found */ int git_sortedcache_lookup_index( size_t *out, git_sortedcache *sc, const char *key); -/* remove entry from cache - lock during delete if `lock` is true */ -int git_sortedcache_remove(git_sortedcache *sc, size_t pos, bool lock); - #endif diff --git a/src/thread-utils.h b/src/thread-utils.h index 04e02959f..ffcdb4ab0 100644 --- a/src/thread-utils.h +++ b/src/thread-utils.h @@ -41,7 +41,8 @@ typedef git_atomic git_atomic_ssize; #ifdef GIT_THREADS #define git_thread pthread_t -#define git_thread_create(thread, attr, start_routine, arg) pthread_create(thread, attr, start_routine, arg) +#define git_thread_create(thread, attr, start_routine, arg) \ + pthread_create(thread, attr, start_routine, arg) #define git_thread_kill(thread) pthread_cancel(thread) #define git_thread_exit(status) pthread_exit(status) #define git_thread_join(id, status) pthread_join(id, status) @@ -61,6 +62,17 @@ typedef git_atomic git_atomic_ssize; #define git_cond_signal(c) pthread_cond_signal(c) #define git_cond_broadcast(c) pthread_cond_broadcast(c) +/* Pthreads rwlock */ +#define git_rwlock pthread_rwlock_t +#define git_rwlock_init(a) pthread_rwlock_init(a, NULL) +#define git_rwlock_rdlock(a) pthread_rwlock_rdlock(a) +#define git_rwlock_rdunlock(a) pthread_rwlock_unlock(a) +#define git_rwlock_wrlock(a) pthread_rwlock_wrlock(a) +#define git_rwlock_wrunlock(a) pthread_rwlock_unlock(a) +#define git_rwlock_free(a) pthread_rwlock_destroy(a) +#define GIT_RWLOCK_STATIC_INIT PTHREAD_RWLOCK_INITIALIZER + + GIT_INLINE(void) git_atomic_set(git_atomic *a, int val) { #if defined(GIT_WIN32) @@ -147,7 +159,7 @@ GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend) #else #define git_thread unsigned int -#define git_thread_create(thread, attr, start_routine, arg) (void)0 +#define git_thread_create(thread, attr, start_routine, arg) 0 #define git_thread_kill(thread) (void)0 #define git_thread_exit(status) (void)0 #define git_thread_join(id, status) (void)0 @@ -167,6 +179,17 @@ GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend) #define git_cond_signal(c) (void)0 #define git_cond_broadcast(c) (void)0 +/* Pthreads rwlock */ +#define git_rwlock unsigned int +#define git_rwlock_init(a) 0 +#define git_rwlock_rdlock(a) 0 +#define git_rwlock_rdunlock(a) (void)0 +#define git_rwlock_wrlock(a) 0 +#define git_rwlock_wrunlock(a) (void)0 +#define git_rwlock_free(a) (void)0 +#define GIT_RWLOCK_STATIC_INIT 0 + + GIT_INLINE(void) git_atomic_set(git_atomic *a, int val) { a->val = val; diff --git a/tests-clar/core/sortedcache.c b/tests-clar/core/sortedcache.c index 91415943d..509d0df6b 100644 --- a/tests-clar/core/sortedcache.c +++ b/tests-clar/core/sortedcache.c @@ -15,13 +15,13 @@ void test_core_sortedcache__name_only(void) cl_git_pass(git_sortedcache_new( &sc, 0, NULL, NULL, name_only_cmp, NULL)); - cl_git_pass(git_sortedcache_lock(sc)); + cl_git_pass(git_sortedcache_wlock(sc)); cl_git_pass(git_sortedcache_upsert(&item, sc, "aaa")); cl_git_pass(git_sortedcache_upsert(&item, sc, "bbb")); cl_git_pass(git_sortedcache_upsert(&item, sc, "zzz")); cl_git_pass(git_sortedcache_upsert(&item, sc, "mmm")); cl_git_pass(git_sortedcache_upsert(&item, sc, "iii")); - cl_git_pass(git_sortedcache_unlock(sc)); + git_sortedcache_wunlock(sc); cl_assert_equal_sz(5, git_sortedcache_entrycount(sc)); @@ -95,7 +95,7 @@ void test_core_sortedcache__in_memory(void) sortedcache_test_struct_free, &free_count, sortedcache_test_struct_cmp, NULL)); - cl_git_pass(git_sortedcache_lock(sc)); + cl_git_pass(git_sortedcache_wlock(sc)); cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "aaa")); item->value = 10; item->smaller_value = 1; @@ -111,10 +111,12 @@ void test_core_sortedcache__in_memory(void) cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "iii")); item->value = 50; item->smaller_value = 9; - cl_git_pass(git_sortedcache_unlock(sc)); + git_sortedcache_wunlock(sc); cl_assert_equal_sz(5, git_sortedcache_entrycount(sc)); + cl_git_pass(git_sortedcache_rlock(sc)); + cl_assert((item = git_sortedcache_lookup(sc, "aaa")) != NULL); cl_assert_equal_s("aaa", item->path); cl_assert_equal_i(10, item->value); @@ -126,6 +128,8 @@ void test_core_sortedcache__in_memory(void) cl_assert_equal_i(30, item->value); cl_assert(git_sortedcache_lookup(sc, "abc") == NULL); + cl_git_pass(git_sortedcache_rlock(sc)); /* grab more than one */ + cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); cl_assert_equal_s("aaa", item->path); cl_assert_equal_i(10, item->value); @@ -143,6 +147,9 @@ void test_core_sortedcache__in_memory(void) cl_assert_equal_i(30, item->value); cl_assert(git_sortedcache_entry(sc, 5) == NULL); + git_sortedcache_runlock(sc); + git_sortedcache_runlock(sc); + cl_assert_equal_i(0, free_count); git_sortedcache_clear(sc, true); @@ -156,7 +163,7 @@ void test_core_sortedcache__in_memory(void) free_count = 0; - cl_git_pass(git_sortedcache_lock(sc)); + cl_git_pass(git_sortedcache_wlock(sc)); cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "testing")); item->value = 10; item->smaller_value = 3; @@ -166,7 +173,7 @@ void test_core_sortedcache__in_memory(void) cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "final")); item->value = 30; item->smaller_value = 2; - cl_git_pass(git_sortedcache_unlock(sc)); + git_sortedcache_wunlock(sc); cl_assert_equal_sz(3, git_sortedcache_entrycount(sc)); @@ -195,9 +202,11 @@ void test_core_sortedcache__in_memory(void) { size_t pos; + cl_git_pass(git_sortedcache_wlock(sc)); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "again")); cl_assert_equal_sz(0, pos); - cl_git_pass(git_sortedcache_remove(sc, pos, true)); + cl_git_pass(git_sortedcache_remove(sc, pos)); cl_assert_equal_i( GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "again")); @@ -205,7 +214,7 @@ void test_core_sortedcache__in_memory(void) cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "testing")); cl_assert_equal_sz(1, pos); - cl_git_pass(git_sortedcache_remove(sc, pos, true)); + cl_git_pass(git_sortedcache_remove(sc, pos)); cl_assert_equal_i( GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "testing")); @@ -213,11 +222,13 @@ void test_core_sortedcache__in_memory(void) cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "final")); cl_assert_equal_sz(0, pos); - cl_git_pass(git_sortedcache_remove(sc, pos, true)); + cl_git_pass(git_sortedcache_remove(sc, pos)); cl_assert_equal_i( GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "final")); cl_assert_equal_sz(0, git_sortedcache_entrycount(sc)); + + git_sortedcache_wunlock(sc); } git_sortedcache_free(sc); @@ -251,7 +262,7 @@ static void sortedcache_test_reload(git_sortedcache *sc) item->smaller_value = (char)(count++); } - cl_git_pass(git_sortedcache_unlock(sc)); + git_sortedcache_wunlock(sc); git_buf_free(&buf); } -- cgit v1.2.1 From 2b6e1908476c95c84d3e3a62ac069f789156b070 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 22 Aug 2013 11:50:10 -0700 Subject: A bit of item alignment paranoia --- src/sortedcache.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/sortedcache.c b/src/sortedcache.c index c087dbbe9..16dd6a7a1 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -258,7 +258,7 @@ int git_sortedcache_upsert(void **out, git_sortedcache *sc, const char *key) int error = 0; khiter_t pos; void *item; - size_t keylen; + size_t keylen, itemlen; char *item_key; pos = git_strmap_lookup_index(sc->map, key); @@ -267,9 +267,12 @@ int git_sortedcache_upsert(void **out, git_sortedcache *sc, const char *key) goto done; } - keylen = strlen(key); - item = git_pool_mallocz(&sc->pool, sc->item_path_offset + keylen + 1); - if (!item) { /* don't use GITERR_CHECK_ALLOC b/c of lock */ + keylen = strlen(key); + itemlen = sc->item_path_offset + keylen + 1; + itemlen = (itemlen + 7) & ~7; + + if ((item = git_pool_mallocz(&sc->pool, itemlen)) == NULL) { + /* don't use GITERR_CHECK_ALLOC b/c of lock */ error = -1; goto done; } -- cgit v1.2.1 From 972bb689c4a69ba5a5dfaeebacc7198622c4f051 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 22 Aug 2013 14:10:56 -0700 Subject: Add SRWLock implementation of rwlocks for Win32 --- src/thread-utils.h | 9 +++++++-- src/win32/pthread.c | 38 ++++++++++++++++++++++++++++++++++++++ src/win32/pthread.h | 14 +++++++++++++- tests-clar/core/sortedcache.c | 6 ++++-- 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/src/thread-utils.h b/src/thread-utils.h index ffcdb4ab0..819e24e7b 100644 --- a/src/thread-utils.h +++ b/src/thread-utils.h @@ -66,12 +66,17 @@ typedef git_atomic git_atomic_ssize; #define git_rwlock pthread_rwlock_t #define git_rwlock_init(a) pthread_rwlock_init(a, NULL) #define git_rwlock_rdlock(a) pthread_rwlock_rdlock(a) -#define git_rwlock_rdunlock(a) pthread_rwlock_unlock(a) +#define git_rwlock_rdunlock(a) pthread_rwlock_rdunlock(a) #define git_rwlock_wrlock(a) pthread_rwlock_wrlock(a) -#define git_rwlock_wrunlock(a) pthread_rwlock_unlock(a) +#define git_rwlock_wrunlock(a) pthread_rwlock_wrunlock(a) #define git_rwlock_free(a) pthread_rwlock_destroy(a) #define GIT_RWLOCK_STATIC_INIT PTHREAD_RWLOCK_INITIALIZER +#ifndef GIT_WIN32 +#define pthread_rwlock_rdunlock pthread_rwlock_unlock +#define pthread_rwlock_wrunlock pthread_rwlock_unlock +#endif + GIT_INLINE(void) git_atomic_set(git_atomic *a, int val) { diff --git a/src/win32/pthread.c b/src/win32/pthread.c index 2f263b3e0..41cb7a4c0 100644 --- a/src/win32/pthread.c +++ b/src/win32/pthread.c @@ -142,3 +142,41 @@ int pthread_num_processors_np(void) return n ? n : 1; } +int pthread_rwlock_init( + pthread_rwlock_t *GIT_RESTRICT lock, + const pthread_rwlockattr_t *GIT_RESTRICT attr) +{ + (void)attr; + InitializeSRWLock(lock); + return 0; +} + +int pthread_rwlock_rdlock(pthread_rwlock_t *lock) +{ + AcquireSRWLockShared(lock); + return 0; +} + +int pthread_rwlock_rdunlock(pthread_rwlock_t *lock) +{ + ReleaseSRWLockShared(lock); + return 0; +} + +int pthread_rwlock_wrlock(pthread_rwlock_t *lock) +{ + AcquireSRWLockExclusive(lock); + return 0; +} + +int pthread_rwlock_wrunlock(pthread_rwlock_t *lock) +{ + ReleaseSRWLockExclusive(lock); + return 0; +} + +int pthread_rwlock_destroy(pthread_rwlock_t *lock) +{ + (void)lock; + return 0; +} diff --git a/src/win32/pthread.h b/src/win32/pthread.h index 8277ecf6e..54e5286a6 100644 --- a/src/win32/pthread.h +++ b/src/win32/pthread.h @@ -19,11 +19,15 @@ typedef int pthread_mutexattr_t; typedef int pthread_condattr_t; typedef int pthread_attr_t; +typedef int pthread_rwlockattr_t; + typedef CRITICAL_SECTION pthread_mutex_t; typedef HANDLE pthread_t; typedef HANDLE pthread_cond_t; +typedef SRWLOCK pthread_rwlock_t; -#define PTHREAD_MUTEX_INITIALIZER {(void*)-1}; +#define PTHREAD_MUTEX_INITIALIZER {(void*)-1} +#define PTHREAD_RWLOCK_INITIALIZER SRWLOCK_INIT int pthread_create( pthread_t *GIT_RESTRICT, @@ -47,4 +51,12 @@ int pthread_cond_signal(pthread_cond_t *); int pthread_num_processors_np(void); +int pthread_rwlock_init( + pthread_rwlock_t *GIT_RESTRICT, const pthread_rwlockattr_t *GIT_RESTRICT); +int pthread_rwlock_rdlock(pthread_rwlock_t *); +int pthread_rwlock_rdunlock(pthread_rwlock_t *); +int pthread_rwlock_wrlock(pthread_rwlock_t *); +int pthread_rwlock_wrunlock(pthread_rwlock_t *); +int pthread_rwlock_destroy(pthread_rwlock_t *); + #endif diff --git a/tests-clar/core/sortedcache.c b/tests-clar/core/sortedcache.c index 509d0df6b..c1869bee0 100644 --- a/tests-clar/core/sortedcache.c +++ b/tests-clar/core/sortedcache.c @@ -128,7 +128,9 @@ void test_core_sortedcache__in_memory(void) cl_assert_equal_i(30, item->value); cl_assert(git_sortedcache_lookup(sc, "abc") == NULL); - cl_git_pass(git_sortedcache_rlock(sc)); /* grab more than one */ + /* not on Windows: + * cl_git_pass(git_sortedcache_rlock(sc)); -- grab more than one + */ cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); cl_assert_equal_s("aaa", item->path); @@ -148,7 +150,7 @@ void test_core_sortedcache__in_memory(void) cl_assert(git_sortedcache_entry(sc, 5) == NULL); git_sortedcache_runlock(sc); - git_sortedcache_runlock(sc); + /* git_sortedcache_runlock(sc); */ cl_assert_equal_i(0, free_count); -- cgit v1.2.1 From eb868b1e98d7cea8796f9b92be04843a7f819e5e Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 22 Aug 2013 14:34:21 -0700 Subject: Drop support for THREADSAFE on Windows XP This makes libgit2 require Windows Vista or newer if it is going to be compiled with the THREADSAFE option --- CMakeLists.txt | 7 ++++++- src/thread-utils.h | 14 +++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c70ec2d6..019777e78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -287,8 +287,13 @@ FILE(GLOB SRC_H include/git2.h include/git2/*.h include/git2/sys/*.h) # On Windows use specific platform sources IF (WIN32 AND NOT CYGWIN) - ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0501) + ADD_DEFINITIONS(-DWIN32) FILE(GLOB SRC_OS src/win32/*.c src/win32/*.h) + IF (THREADSAFE) + ADD_DEFINITIONS(-D_WIN32_WINNT=0x0600) + ELSE() + ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501) + ENDIF() ELSEIF (AMIGA) ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R) FILE(GLOB SRC_OS src/amiga/*.c src/amiga/*.h) diff --git a/src/thread-utils.h b/src/thread-utils.h index 819e24e7b..371dc0b26 100644 --- a/src/thread-utils.h +++ b/src/thread-utils.h @@ -40,6 +40,10 @@ typedef git_atomic git_atomic_ssize; #ifdef GIT_THREADS +#if defined(GIT_WIN32) && _WIN32_WINNT < 0x0600 +# error "Unsupported Windows version for thread support" +#endif + #define git_thread pthread_t #define git_thread_create(thread, attr, start_routine, arg) \ pthread_create(thread, attr, start_routine, arg) @@ -62,7 +66,15 @@ typedef git_atomic git_atomic_ssize; #define git_cond_signal(c) pthread_cond_signal(c) #define git_cond_broadcast(c) pthread_cond_broadcast(c) -/* Pthreads rwlock */ +/* Pthread (-ish) rwlock + * + * This differs from normal pthreads rwlocks in two ways: + * 1. Separate APIs for releasing read locks and write locks (as + * opposed to the pure POSIX API which only has one unlock fn) + * 2. You should not use recursive read locks (i.e. grabbing a read + * lock in a thread that already holds a read lock) because the + * Windows implementation doesn't support it + */ #define git_rwlock pthread_rwlock_t #define git_rwlock_init(a) pthread_rwlock_init(a, NULL) #define git_rwlock_rdlock(a) pthread_rwlock_rdlock(a) -- cgit v1.2.1 From b6ac07b51771641f3ae994c17f361fbd8bec36ef Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 22 Aug 2013 14:45:10 -0700 Subject: Trying to fix Win32 warnings --- src/cc-compat.h | 8 ++++++-- src/diff_tform.c | 6 +++--- src/sortedcache.c | 2 +- src/win32/pthread.h | 12 +++++++----- tests-clar/stress/diff.c | 2 +- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/cc-compat.h b/src/cc-compat.h index a5e4ce17e..37f1ea81e 100644 --- a/src/cc-compat.h +++ b/src/cc-compat.h @@ -54,8 +54,12 @@ #if defined (_MSC_VER) typedef unsigned char bool; -# define true 1 -# define false 0 +# ifndef true +# define true 1 +# endif +# ifndef false +# define false 0 +# endif #else # include #endif diff --git a/src/diff_tform.c b/src/diff_tform.c index ba35d3c14..6b8cf446e 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -859,9 +859,9 @@ find_best_matches: } /* write new mapping */ - tgt2src[t].idx = s; + tgt2src[t].idx = (uint32_t)s; tgt2src[t].similarity = (uint32_t)similarity; - src2tgt[s].idx = t; + src2tgt[s].idx = (uint32_t)t; src2tgt[s].similarity = (uint32_t)similarity; } @@ -869,7 +869,7 @@ find_best_matches: if (tgt2src_copy != NULL && tgt2src_copy[t].similarity < (uint32_t)similarity) { - tgt2src_copy[t].idx = s; + tgt2src_copy[t].idx = (uint32_t)s; tgt2src_copy[t].similarity = (uint32_t)similarity; } diff --git a/src/sortedcache.c b/src/sortedcache.c index 16dd6a7a1..33171c48d 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -271,7 +271,7 @@ int git_sortedcache_upsert(void **out, git_sortedcache *sc, const char *key) itemlen = sc->item_path_offset + keylen + 1; itemlen = (itemlen + 7) & ~7; - if ((item = git_pool_mallocz(&sc->pool, itemlen)) == NULL) { + if ((item = git_pool_mallocz(&sc->pool, (uint32_t)itemlen)) == NULL) { /* don't use GITERR_CHECK_ALLOC b/c of lock */ error = -1; goto done; diff --git a/src/win32/pthread.h b/src/win32/pthread.h index 54e5286a6..50d836247 100644 --- a/src/win32/pthread.h +++ b/src/win32/pthread.h @@ -30,15 +30,16 @@ typedef SRWLOCK pthread_rwlock_t; #define PTHREAD_RWLOCK_INITIALIZER SRWLOCK_INIT int pthread_create( - pthread_t *GIT_RESTRICT, - const pthread_attr_t *GIT_RESTRICT, + pthread_t *GIT_RESTRICT thread, + const pthread_attr_t *GIT_RESTRICT attr, void *(*start_routine)(void*), - void *__restrict); + void *GIT_RESTRICT arg); int pthread_join(pthread_t, void **); int pthread_mutex_init( - pthread_mutex_t *GIT_RESTRICT, const pthread_mutexattr_t *GIT_RESTRICT); + pthread_mutex_t *GIT_RESTRICT mutex, + const pthread_mutexattr_t *GIT_RESTRICT mutexattr); int pthread_mutex_destroy(pthread_mutex_t *); int pthread_mutex_lock(pthread_mutex_t *); int pthread_mutex_unlock(pthread_mutex_t *); @@ -52,7 +53,8 @@ int pthread_cond_signal(pthread_cond_t *); int pthread_num_processors_np(void); int pthread_rwlock_init( - pthread_rwlock_t *GIT_RESTRICT, const pthread_rwlockattr_t *GIT_RESTRICT); + pthread_rwlock_t *GIT_RESTRICT lock, + const pthread_rwlockattr_t *GIT_RESTRICT attr); int pthread_rwlock_rdlock(pthread_rwlock_t *); int pthread_rwlock_rdunlock(pthread_rwlock_t *); int pthread_rwlock_wrlock(pthread_rwlock_t *); diff --git a/tests-clar/stress/diff.c b/tests-clar/stress/diff.c index 62ccd5ec7..0524aa108 100644 --- a/tests-clar/stress/diff.c +++ b/tests-clar/stress/diff.c @@ -15,7 +15,7 @@ void test_stress_diff__cleanup(void) #define ANOTHER_POEM \ "OH, glorious are the guarded heights\nWhere guardian souls abide—\nSelf-exiled from our gross delights—\nAbove, beyond, outside:\nAn ampler arc their spirit swings—\nCommands a juster view—\nWe have their word for all these things,\nNo doubt their words are true.\n\nYet we, the bond slaves of our day,\nWhom dirt and danger press—\nCo-heirs of insolence, delay,\nAnd leagued unfaithfulness—\nSuch is our need must seek indeed\nAnd, having found, engage\nThe men who merely do the work\nFor which they draw the wage.\n\nFrom forge and farm and mine and bench,\nDeck, altar, outpost lone—\nMill, school, battalion, counter, trench,\nRail, senate, sheepfold, throne—\nCreation's cry goes up on high\nFrom age to cheated age:\n\"Send us the men who do the work\n\"For which they draw the wage!\"\n" -static void test_with_many(size_t expected_new) +static void test_with_many(int expected_new) { git_index *index; git_tree *tree, *new_tree; -- cgit v1.2.1 From 805755f49b0db5bc884f8929621ac61238b2c30e Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 22 Aug 2013 15:44:34 -0700 Subject: Fix sortedcache docs and other feedback This converts an internal lock from a write lock to a read lock where write isn't needed, and also clarifies some doc things about where various locks are acquired and how various APIs are intended to be used. --- src/sortedcache.c | 8 ++++---- src/sortedcache.h | 35 ++++++++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/sortedcache.c b/src/sortedcache.c index 33171c48d..466e55dbe 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -110,7 +110,7 @@ static int sortedcache_copy_item(void *payload, void *tgt_item, void *src_item) int git_sortedcache_copy( git_sortedcache **out, git_sortedcache *src, - bool wlock, + bool lock, int (*copy_item)(void *payload, void *tgt_item, void *src_item), void *payload) { @@ -131,7 +131,7 @@ int git_sortedcache_copy( src->items._cmp, src->path)) < 0) return error; - if (wlock && git_sortedcache_wlock(src) < 0) { + if (lock && git_sortedcache_rlock(src) < 0) { git_sortedcache_free(tgt); return -1; } @@ -144,8 +144,8 @@ int git_sortedcache_copy( break; } - if (wlock) - git_sortedcache_wunlock(src); + if (lock) + git_sortedcache_runlock(src); if (error) git_sortedcache_free(tgt); diff --git a/src/sortedcache.h b/src/sortedcache.h index 7d1cd2f14..5ebb116ed 100644 --- a/src/sortedcache.h +++ b/src/sortedcache.h @@ -16,9 +16,10 @@ /* * The purpose of this data structure is to cache the parsed contents of a - * file where each item in the file can be identified by a key string and - * you want to both look them up by name and traverse them in sorted - * order. Each item is assumed to itself end in a GIT_FLEX_ARRAY. + * file (a.k.a. the backing file) where each item in the file can be + * identified by a key string and you want to both look them up by name + * and traverse them in sorted order. Each item is assumed to itself end + * in a GIT_FLEX_ARRAY. */ typedef void (*git_sortedcache_free_item_fn)(void *payload, void *item); @@ -42,6 +43,16 @@ typedef struct { * the end containing their key string, you have to provide the item_cmp * sorting function because the sorting function doesn't get a payload * and therefore can't know the offset to the item key string. :-( + * + * @param out The allocated git_sortedcache + * @param item_path_offset Offset to the GIT_FLEX_ARRAY item key in the + * struct - use offsetof(struct mine, key-field) to get this + * @param free_item Optional callback to free each item + * @param free_item_payload Optional payload passed to free_item callback + * @param item_cmp Compare the keys of two items + * @param path The path to the backing store file for this cache; this + * may be NULL. The cache makes it easy to load this and check + * if it has been modified since the last load and/or write. */ int git_sortedcache_new( git_sortedcache **out, @@ -54,12 +65,12 @@ int git_sortedcache_new( /* Copy a sorted cache * * - `copy_item` can be NULL to just use memcpy - * - if `wlock`, grabs write lock on `src` during copy and releases after + * - if `lock`, grabs read lock on `src` during copy and releases after */ int git_sortedcache_copy( git_sortedcache **out, git_sortedcache *src, - bool wlock, + bool lock, int (*copy_item)(void *payload, void *tgt_item, void *src_item), void *payload); @@ -90,8 +101,18 @@ int git_sortedcache_wlock(git_sortedcache *sc); /* Unlock sorted cache when done with write */ void git_sortedcache_wunlock(git_sortedcache *sc); -/* Lock cache and test if the file has changed. If the file has changed, - * then load the contents into `buf` otherwise unlock and return 0. +/* Lock cache and load backing file into a buffer. + * + * This grabs a write lock on the cache then looks at the modification + * time and size of the file on disk. + * + * If the file appears to have changed, this loads the file contents into + * the buffer and returns a positive value leaving the cache locked - the + * caller should parse the file content, update the cache as needed, then + * release the lock. NOTE: In this case, the caller MUST unlock the cache. + * + * If the file appears to be unchanged, then this automatically releases + * the lock on the cache, clears the buffer, and returns 0. * * @return 0 if up-to-date, 1 if out-of-date, <0 on error */ -- cgit v1.2.1 From 44d655318661affa2feb51e9d6d533bb16d7f2b5 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 19 Aug 2013 16:03:15 -0700 Subject: Fix comment --- tests-clar/refs/pack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests-clar/refs/pack.c b/tests-clar/refs/pack.c index 6019ed75a..849a052aa 100644 --- a/tests-clar/refs/pack.c +++ b/tests-clar/refs/pack.c @@ -44,7 +44,7 @@ void test_refs_pack__empty(void) void test_refs_pack__loose(void) { - /* create a packfile from all the loose rn a repo */ + /* create a packfile from all the loose refs in a repo */ git_reference *reference; git_buf temp_path = GIT_BUF_INIT; -- cgit v1.2.1 From 9d85f00722c5161bda0727f5bb80d13d08ccb481 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale Date: Sat, 24 Aug 2013 17:39:15 +1000 Subject: fix tests on FreeBSD 238b761 introduced a test for posix behaviour, but on FreeBSD some of the structs and constants used aren't defined in . Include the appropriate headers to get the tests working again on FreeBSD. --- tests-clar/core/posix.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests-clar/core/posix.c b/tests-clar/core/posix.c index 0d9443f92..890e25d47 100644 --- a/tests-clar/core/posix.c +++ b/tests-clar/core/posix.c @@ -1,5 +1,7 @@ #ifndef _WIN32 # include +# include +# include #else # include # ifdef _MSC_VER -- cgit v1.2.1 From e52963080a1cc4c7cd7a921fd96d9656cc976022 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale Date: Sat, 24 Aug 2013 20:15:22 +1000 Subject: netops: remove duplicate include 9e9aee6 added an include to fix the build on FreeBSD. Sometime since then the same header is included ifndef _WIN32, so remove the duplicate include. --- src/netops.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/netops.c b/src/netops.c index 69179dd1c..803c2696a 100644 --- a/src/netops.c +++ b/src/netops.c @@ -19,10 +19,6 @@ # endif #endif -#ifdef __FreeBSD__ -# include -#endif - #ifdef GIT_SSL # include # include -- cgit v1.2.1 From 32614440561e2ccb33ee24462a120154e0009d08 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale Date: Sun, 25 Aug 2013 17:01:04 +1000 Subject: push: small documentation fix --- include/git2/push.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/git2/push.h b/include/git2/push.h index f92308144..ed6253afb 100644 --- a/include/git2/push.h +++ b/include/git2/push.h @@ -98,7 +98,7 @@ GIT_EXTERN(int) git_push_finish(git_push *push); * * @param push The push object * - * @return true if equal, false otherwise + * @return true if remote side successfully unpacked, false otherwise */ GIT_EXTERN(int) git_push_unpack_ok(git_push *push); -- cgit v1.2.1 From 504850cdf56190a61782abfec37f3533b42d769e Mon Sep 17 00:00:00 2001 From: Nikolai Vladimirov Date: Sun, 25 Aug 2013 15:59:50 +0300 Subject: refs: add git_reference_is_tag --- include/git2/refs.h | 9 +++++++++ src/refs.c | 11 +++++++++++ src/refs.h | 1 + tests-clar/refs/read.c | 16 ++++++++++++++++ 4 files changed, 37 insertions(+) diff --git a/include/git2/refs.h b/include/git2/refs.h index 205bfe59d..4871e9820 100644 --- a/include/git2/refs.h +++ b/include/git2/refs.h @@ -442,6 +442,15 @@ GIT_EXTERN(int) git_reference_is_branch(git_reference *ref); */ GIT_EXTERN(int) git_reference_is_remote(git_reference *ref); +/** + * Check if a reference is a tag + * + * @param ref A git reference + * + * @return 1 when the reference lives in the refs/tags + * namespace; 0 otherwise. + */ +GIT_EXTERN(int) git_reference_is_tag(git_reference *ref); typedef enum { GIT_REF_FORMAT_NORMAL = 0, diff --git a/src/refs.c b/src/refs.c index c0e460cc3..6cc937fda 100644 --- a/src/refs.c +++ b/src/refs.c @@ -952,6 +952,17 @@ int git_reference_is_remote(git_reference *ref) return git_reference__is_remote(ref->name); } +int git_reference__is_tag(const char *ref_name) +{ + return git__prefixcmp(ref_name, GIT_REFS_TAGS_DIR) == 0; +} + +int git_reference_is_tag(git_reference *ref) +{ + assert(ref); + return git_reference__is_tag(ref->name); +} + static int peel_error(int error, git_reference *ref, const char* msg) { giterr_set( diff --git a/src/refs.h b/src/refs.h index f487ee3fc..cb75abbe5 100644 --- a/src/refs.h +++ b/src/refs.h @@ -67,6 +67,7 @@ int git_reference__update_terminal(git_repository *repo, const char *ref_name, c int git_reference__is_valid_name(const char *refname, unsigned int flags); int git_reference__is_branch(const char *ref_name); int git_reference__is_remote(const char *ref_name); +int git_reference__is_tag(const char *ref_name); /** * Lookup a reference by name and try to resolve to an OID. diff --git a/tests-clar/refs/read.c b/tests-clar/refs/read.c index afb6be008..35cf17e9e 100644 --- a/tests-clar/refs/read.c +++ b/tests-clar/refs/read.c @@ -255,6 +255,22 @@ void test_refs_read__can_determine_if_a_reference_is_a_local_branch(void) assert_is_branch("refs/tags/e90810b", false); } +static void assert_is_tag(const char *name, bool expected_tagness) +{ + git_reference *reference; + cl_git_pass(git_reference_lookup(&reference, g_repo, name)); + cl_assert_equal_i(expected_tagness, git_reference_is_tag(reference)); + git_reference_free(reference); +} + +void test_refs_read__can_determine_if_a_reference_is_a_tag(void) +{ + assert_is_tag("refs/tags/e90810b", true); + assert_is_tag("refs/tags/test", true); + assert_is_tag("refs/heads/packed", false); + assert_is_tag("refs/remotes/test/master", false); +} + void test_refs_read__invalid_name_returns_EINVALIDSPEC(void) { git_reference *reference; -- cgit v1.2.1 From 430953417f74dfcdbe030bafc069e1c07edceeb6 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 26 Aug 2013 14:56:31 -0700 Subject: Load SRWLock APIs at runtime This loads SRWLock APIs at runtime and in their absence (i.e. on Windows before Vista) falls back on a regular CRITICAL_SECTION that will not permit concurrent readers. --- CMakeLists.txt | 7 +--- src/global.c | 12 ++++--- src/hash/hash_win32.c | 3 +- src/thread-utils.h | 4 --- src/win32/pthread.c | 89 +++++++++++++++++++++++++++++++++++++++++++++------ src/win32/pthread.h | 14 ++++++-- 6 files changed, 103 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 019777e78..1c70ec2d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -287,13 +287,8 @@ FILE(GLOB SRC_H include/git2.h include/git2/*.h include/git2/sys/*.h) # On Windows use specific platform sources IF (WIN32 AND NOT CYGWIN) - ADD_DEFINITIONS(-DWIN32) + ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0501) FILE(GLOB SRC_OS src/win32/*.c src/win32/*.h) - IF (THREADSAFE) - ADD_DEFINITIONS(-D_WIN32_WINNT=0x0600) - ELSE() - ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501) - ENDIF() ELSEIF (AMIGA) ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R) FILE(GLOB SRC_OS src/amiga/*.c src/amiga/*.h) diff --git a/src/global.c b/src/global.c index a06d0c81f..b504e5e0a 100644 --- a/src/global.c +++ b/src/global.c @@ -71,18 +71,22 @@ int git_threads_init(void) GIT_MEMORY_BARRIER; + win32_pthread_initialize(); + return error; } void git_threads_shutdown(void) { + /* Shut down any subsystems that have global state */ + win32_pthread_shutdown(); + git_futils_dirs_free(); + git_hash_global_shutdown(); + TlsFree(_tls_index); _tls_init = 0; - git_mutex_free(&git__mwindow_mutex); - /* Shut down any subsystems that have global state */ - git_hash_global_shutdown(); - git_futils_dirs_free(); + git_mutex_free(&git__mwindow_mutex); } git_global_st *git__global_state(void) diff --git a/src/hash/hash_win32.c b/src/hash/hash_win32.c index 43d54ca6d..6732f93d7 100644 --- a/src/hash/hash_win32.c +++ b/src/hash/hash_win32.c @@ -46,7 +46,8 @@ GIT_INLINE(int) hash_cng_prov_init(void) return -1; /* Load bcrypt.dll explicitly from the system directory */ - if ((dll_path_len = GetSystemDirectory(dll_path, MAX_PATH)) == 0 || dll_path_len > MAX_PATH || + if ((dll_path_len = GetSystemDirectory(dll_path, MAX_PATH)) == 0 || + dll_path_len > MAX_PATH || StringCchCat(dll_path, MAX_PATH, "\\") < 0 || StringCchCat(dll_path, MAX_PATH, GIT_HASH_CNG_DLL_NAME) < 0 || (hash_prov.prov.cng.dll = LoadLibrary(dll_path)) == NULL) diff --git a/src/thread-utils.h b/src/thread-utils.h index 371dc0b26..914c1357d 100644 --- a/src/thread-utils.h +++ b/src/thread-utils.h @@ -40,10 +40,6 @@ typedef git_atomic git_atomic_ssize; #ifdef GIT_THREADS -#if defined(GIT_WIN32) && _WIN32_WINNT < 0x0600 -# error "Unsupported Windows version for thread support" -#endif - #define git_thread pthread_t #define git_thread_create(thread, attr, start_routine, arg) \ pthread_create(thread, attr, start_routine, arg) diff --git a/src/win32/pthread.c b/src/win32/pthread.c index 41cb7a4c0..8775f632a 100644 --- a/src/win32/pthread.c +++ b/src/win32/pthread.c @@ -127,9 +127,10 @@ int pthread_cond_signal(pthread_cond_t *cond) return 0; } -/* pthread_cond_broadcast is not implemented because doing so with just Win32 events - * is quite complicated, and no caller in libgit2 uses it yet. */ - +/* pthread_cond_broadcast is not implemented because doing so with just + * Win32 events is quite complicated, and no caller in libgit2 uses it + * yet. + */ int pthread_num_processors_np(void) { DWORD_PTR p, s; @@ -142,41 +143,111 @@ int pthread_num_processors_np(void) return n ? n : 1; } + +static HINSTANCE win32_kernel32_dll; + +typedef void (WINAPI *win32_srwlock_fn)(SRWLOCK *); + +static win32_srwlock_fn win32_srwlock_initialize; +static win32_srwlock_fn win32_srwlock_acquire_shared; +static win32_srwlock_fn win32_srwlock_release_shared; +static win32_srwlock_fn win32_srwlock_acquire_exclusive; +static win32_srwlock_fn win32_srwlock_release_exclusive; + int pthread_rwlock_init( pthread_rwlock_t *GIT_RESTRICT lock, const pthread_rwlockattr_t *GIT_RESTRICT attr) { (void)attr; - InitializeSRWLock(lock); + + if (win32_srwlock_initialize) + win32_srwlock_initialize(&lock->native.srwl); + else + InitializeCriticalSection(&lock->native.csec); + return 0; } int pthread_rwlock_rdlock(pthread_rwlock_t *lock) { - AcquireSRWLockShared(lock); + if (win32_srwlock_acquire_shared) + win32_srwlock_acquire_shared(&lock->native.srwl); + else + EnterCriticalSection(&lock->native.csec); + return 0; } int pthread_rwlock_rdunlock(pthread_rwlock_t *lock) { - ReleaseSRWLockShared(lock); + if (win32_srwlock_release_shared) + win32_srwlock_release_shared(&lock->native.srwl); + else + LeaveCriticalSection(&lock->native.csec); + return 0; } int pthread_rwlock_wrlock(pthread_rwlock_t *lock) { - AcquireSRWLockExclusive(lock); + if (win32_srwlock_acquire_exclusive) + win32_srwlock_acquire_exclusive(&lock->native.srwl); + else + EnterCriticalSection(&lock->native.csec); + return 0; } int pthread_rwlock_wrunlock(pthread_rwlock_t *lock) { - ReleaseSRWLockExclusive(lock); + if (win32_srwlock_release_exclusive) + win32_srwlock_release_exclusive(&lock->native.srwl); + else + LeaveCriticalSection(&lock->native.csec); + return 0; } int pthread_rwlock_destroy(pthread_rwlock_t *lock) { - (void)lock; + if (!win32_srwlock_initialize) + DeleteCriticalSection(&lock->native.csec); + git__memzero(lock, sizeof(*lock)); + return 0; +} + + +int win32_pthread_initialize(void) +{ + if (win32_kernel32_dll) + return 0; + + win32_kernel32_dll = LoadLibrary("Kernel32.dll"); + if (!win32_kernel32_dll) { + giterr_set(GITERR_OS, "Could not load Kernel32.dll!"); + return -1; + } + + win32_srwlock_initialize = (win32_srwlock_fn) + GetProcAddress(win32_kernel32_dll, "InitializeSRWLock"); + win32_srwlock_acquire_shared = (win32_srwlock_fn) + GetProcAddress(win32_kernel32_dll, "AcquireSRWLockShared"); + win32_srwlock_release_shared = (win32_srwlock_fn) + GetProcAddress(win32_kernel32_dll, "ReleaseSRWLockShared"); + win32_srwlock_acquire_exclusive = (win32_srwlock_fn) + GetProcAddress(win32_kernel32_dll, "AcquireSRWLockExclusive"); + win32_srwlock_release_exclusive = (win32_srwlock_fn) + GetProcAddress(win32_kernel32_dll, "ReleaseSRWLockExclusive"); + + return 0; +} + +int win32_pthread_shutdown(void) +{ + if (win32_kernel32_dll) { + FreeLibrary(win32_kernel32_dll); + win32_kernel32_dll = NULL; + } + return 0; } diff --git a/src/win32/pthread.h b/src/win32/pthread.h index 50d836247..e84de471f 100644 --- a/src/win32/pthread.h +++ b/src/win32/pthread.h @@ -24,10 +24,17 @@ typedef int pthread_rwlockattr_t; typedef CRITICAL_SECTION pthread_mutex_t; typedef HANDLE pthread_t; typedef HANDLE pthread_cond_t; -typedef SRWLOCK pthread_rwlock_t; + +/* typedef struct { void *Ptr; } SRWLOCK; */ + +typedef struct { + union { + SRWLOCK srwl; + CRITICAL_SECTION csec; + } native; +} pthread_rwlock_t; #define PTHREAD_MUTEX_INITIALIZER {(void*)-1} -#define PTHREAD_RWLOCK_INITIALIZER SRWLOCK_INIT int pthread_create( pthread_t *GIT_RESTRICT thread, @@ -61,4 +68,7 @@ int pthread_rwlock_wrlock(pthread_rwlock_t *); int pthread_rwlock_wrunlock(pthread_rwlock_t *); int pthread_rwlock_destroy(pthread_rwlock_t *); +extern int win32_pthread_initialize(void); +extern int win32_pthread_shutdown(void); + #endif -- cgit v1.2.1 From 2f368a661c55b49a8f15905c221f9e76935bedd0 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 26 Aug 2013 15:17:35 -0700 Subject: Fix MINGW SRWLock typedefs --- src/win32/mingw-compat.h | 2 ++ src/win32/pthread.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/win32/mingw-compat.h b/src/win32/mingw-compat.h index fe0abfb54..b06dda209 100644 --- a/src/win32/mingw-compat.h +++ b/src/win32/mingw-compat.h @@ -24,6 +24,8 @@ GIT_INLINE(size_t) p_strnlen(const char *s, size_t maxlen) { return end ? (size_t)(end - s) : maxlen; } +typedef struct { void *Ptr; } SRWLOCK; + #endif #endif /* INCLUDE_mingw_compat__ */ diff --git a/src/win32/pthread.h b/src/win32/pthread.h index e84de471f..679ebed23 100644 --- a/src/win32/pthread.h +++ b/src/win32/pthread.h @@ -25,8 +25,6 @@ typedef CRITICAL_SECTION pthread_mutex_t; typedef HANDLE pthread_t; typedef HANDLE pthread_cond_t; -/* typedef struct { void *Ptr; } SRWLOCK; */ - typedef struct { union { SRWLOCK srwl; -- cgit v1.2.1 From b83c92dd6fe11adae0ff29e1db381c31f0f88cb7 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Wed, 21 Aug 2013 13:16:17 +0200 Subject: remote: Assert proper GIT_DIRECTION_XXXX values --- src/remote.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/remote.c b/src/remote.c index 7677e56b2..14ed740a8 100644 --- a/src/remote.c +++ b/src/remote.c @@ -534,6 +534,8 @@ const char* git_remote__urlfordirection(git_remote *remote, int direction) { assert(remote); + assert(direction == GIT_DIRECTION_FETCH || direction == GIT_DIRECTION_PUSH); + if (direction == GIT_DIRECTION_FETCH) { return remote->url; } -- cgit v1.2.1 From 44bc0c6ac3b939d3dfc1102be77e82e00e919ae4 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Wed, 21 Aug 2013 13:20:17 +0200 Subject: remote: Warn the user when connecting with no url --- src/remote.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/remote.c b/src/remote.c index 14ed740a8..948c755bb 100644 --- a/src/remote.c +++ b/src/remote.c @@ -558,8 +558,11 @@ int git_remote_connect(git_remote *remote, git_direction direction) t = remote->transport; url = git_remote__urlfordirection(remote, direction); - if (url == NULL ) + if (url == NULL ) { + giterr_set(GITERR_INVALID, + "Malformed remote '%s' - missing URL", remote->name); return -1; + } /* A transport could have been supplied in advance with * git_remote_set_transport */ -- cgit v1.2.1 From ece24ef7c4bb31eb2c715948bcf6dff6ed9d7dfc Mon Sep 17 00:00:00 2001 From: nulltoken Date: Wed, 21 Aug 2013 13:37:21 +0200 Subject: remote: Don't parse missing urls as empty strings --- src/remote.c | 2 +- tests-clar/network/remote/remotes.c | 6 ++++++ tests-clar/resources/testrepo.git/config | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/remote.c b/src/remote.c index 948c755bb..4bba1d57e 100644 --- a/src/remote.c +++ b/src/remote.c @@ -308,7 +308,7 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name) if ((error = get_optional_config(config, &buf, NULL, (void *)&val)) < 0) goto cleanup; - if (val) { + if (val && strlen(val) > 0) { remote->pushurl = git__strdup(val); GITERR_CHECK_ALLOC(remote->pushurl); } diff --git a/tests-clar/network/remote/remotes.c b/tests-clar/network/remote/remotes.c index dec646526..e356526ed 100644 --- a/tests-clar/network/remote/remotes.c +++ b/tests-clar/network/remote/remotes.c @@ -367,8 +367,14 @@ void test_network_remote_remotes__can_load_with_an_empty_url(void) cl_git_pass(git_remote_load(&remote, _repo, "empty-remote-url")); + cl_assert(remote->url == NULL); + cl_assert(remote->pushurl == NULL); + cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + cl_assert(giterr_last() != NULL); + cl_assert(giterr_last()->klass == GITERR_INVALID); + git_remote_free(remote); } diff --git a/tests-clar/resources/testrepo.git/config b/tests-clar/resources/testrepo.git/config index 904a4e3f3..1264f6ea7 100644 --- a/tests-clar/resources/testrepo.git/config +++ b/tests-clar/resources/testrepo.git/config @@ -10,7 +10,7 @@ url = git://github.com/libgit2/libgit2 [remote "empty-remote-url"] url = - + pushurl = [remote "test_with_pushurl"] url = git://github.com/libgit2/fetchlibgit2 pushurl = git://github.com/libgit2/pushlibgit2 -- cgit v1.2.1 From c9ffa84bde45021c40623553822916fb3d13b20a Mon Sep 17 00:00:00 2001 From: nulltoken Date: Wed, 21 Aug 2013 16:04:25 +0200 Subject: remote: Relax the parsing logic even more In order to be loaded, a remote needs to be configured with at least a `url` or a `pushurl`. ENOTFOUND will be returned when trying to git_remote_load() a remote with neither of these entries defined. --- src/remote.c | 33 ++++++++++++++++++++++++-------- tests-clar/network/remote/remotes.c | 22 +++++++++++++++++++++ tests-clar/resources/testrepo.git/config | 4 ++++ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/remote.c b/src/remote.c index 4bba1d57e..7276daa39 100644 --- a/src/remote.c +++ b/src/remote.c @@ -233,7 +233,8 @@ static int refspec_cb(const git_config_entry *entry, void *payload) } static int get_optional_config( - git_config *config, git_buf *buf, git_config_foreach_cb cb, void *payload) + bool *found, git_config *config, git_buf *buf, + git_config_foreach_cb cb, void *payload) { int error = 0; const char *key = git_buf_cstr(buf); @@ -246,6 +247,9 @@ static int get_optional_config( else error = git_config_get_string(payload, config, key); + if (found) + *found = !error; + if (error == GIT_ENOTFOUND) { giterr_clear(); error = 0; @@ -265,6 +269,7 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name) int error = 0; git_config *config; struct refspec_cb_data data; + bool optional_setting_found = false, found; assert(out && repo && name); @@ -294,21 +299,33 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name) goto cleanup; } - if ((error = git_config_get_string(&val, config, git_buf_cstr(&buf))) < 0) + if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0) goto cleanup; + optional_setting_found |= found; + remote->repo = repo; - remote->url = git__strdup(val); - GITERR_CHECK_ALLOC(remote->url); + + if (found && strlen(val) > 0) { + remote->url = git__strdup(val); + GITERR_CHECK_ALLOC(remote->url); + } val = NULL; git_buf_clear(&buf); git_buf_printf(&buf, "remote.%s.pushurl", name); - if ((error = get_optional_config(config, &buf, NULL, (void *)&val)) < 0) + if ((error = get_optional_config(&found, config, &buf, NULL, (void *)&val)) < 0) goto cleanup; - if (val && strlen(val) > 0) { + optional_setting_found |= found; + + if (!optional_setting_found) { + error = GIT_ENOTFOUND; + goto cleanup; + } + + if (found && strlen(val) > 0) { remote->pushurl = git__strdup(val); GITERR_CHECK_ALLOC(remote->pushurl); } @@ -318,14 +335,14 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name) git_buf_clear(&buf); git_buf_printf(&buf, "remote.%s.fetch", name); - if ((error = get_optional_config(config, &buf, refspec_cb, &data)) < 0) + if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0) goto cleanup; data.fetch = false; git_buf_clear(&buf); git_buf_printf(&buf, "remote.%s.push", name); - if ((error = get_optional_config(config, &buf, refspec_cb, &data)) < 0) + if ((error = get_optional_config(NULL, config, &buf, refspec_cb, &data)) < 0) goto cleanup; if (download_tags_value(remote, config) < 0) diff --git a/tests-clar/network/remote/remotes.c b/tests-clar/network/remote/remotes.c index e356526ed..55b233eda 100644 --- a/tests-clar/network/remote/remotes.c +++ b/tests-clar/network/remote/remotes.c @@ -378,6 +378,28 @@ void test_network_remote_remotes__can_load_with_an_empty_url(void) git_remote_free(remote); } +void test_network_remote_remotes__can_load_with_only_an_empty_pushurl(void) +{ + git_remote *remote = NULL; + + cl_git_pass(git_remote_load(&remote, _repo, "empty-remote-pushurl")); + + cl_assert(remote->url == NULL); + cl_assert(remote->pushurl == NULL); + + cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + + git_remote_free(remote); +} + +void test_network_remote_remotes__returns_ENOTFOUND_when_neither_url_nor_pushurl(void) +{ + git_remote *remote = NULL; + + cl_git_fail_with( + git_remote_load(&remote, _repo, "no-remote-url"), GIT_ENOTFOUND); +} + void test_network_remote_remotes__check_structure_version(void) { git_transport transport = GIT_TRANSPORT_INIT; diff --git a/tests-clar/resources/testrepo.git/config b/tests-clar/resources/testrepo.git/config index 1264f6ea7..dfab4eeb4 100644 --- a/tests-clar/resources/testrepo.git/config +++ b/tests-clar/resources/testrepo.git/config @@ -11,6 +11,10 @@ [remote "empty-remote-url"] url = pushurl = +[remote "empty-remote-pushurl"] + pushurl = +[remote "no-remote-url"] + fetch = [remote "test_with_pushurl"] url = git://github.com/libgit2/fetchlibgit2 pushurl = git://github.com/libgit2/pushlibgit2 -- cgit v1.2.1 From 191adce8751e728111a3b1c3e9b2c02fe9f5d775 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 27 Aug 2013 20:00:28 +0200 Subject: vector: Teach git_vector_uniq() to free while deduplicating --- src/util.h | 5 ++++- src/vector.c | 9 ++++++--- src/vector.h | 2 +- tests-clar/core/vector.c | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/util.h b/src/util.h index a784390c1..bd93b46b5 100644 --- a/src/util.h +++ b/src/util.h @@ -82,7 +82,10 @@ GIT_INLINE(void *) git__realloc(void *ptr, size_t size) return new_ptr; } -#define git__free(ptr) free(ptr) +GIT_INLINE(void) git__free(void *ptr) +{ + free(ptr); +} #define STRCMP_CASESELECT(IGNORE_CASE, STR1, STR2) \ ((IGNORE_CASE) ? strcasecmp((STR1), (STR2)) : strcmp((STR1), (STR2))) diff --git a/src/vector.c b/src/vector.c index 5ba2fab18..362e7b0c0 100644 --- a/src/vector.c +++ b/src/vector.c @@ -220,7 +220,7 @@ void git_vector_pop(git_vector *v) v->length--; } -void git_vector_uniq(git_vector *v) +void git_vector_uniq(git_vector *v, void (*git_free_cb)(void *)) { git_vector_cmp cmp; size_t i, j; @@ -232,9 +232,12 @@ void git_vector_uniq(git_vector *v) cmp = v->_cmp ? v->_cmp : strict_comparison; for (i = 0, j = 1 ; j < v->length; ++j) - if (!cmp(v->contents[i], v->contents[j])) + if (!cmp(v->contents[i], v->contents[j])) { + if (git_free_cb) + git_free_cb(v->contents[i]); + v->contents[i] = v->contents[j]; - else + } else v->contents[++i] = v->contents[j]; v->length -= j - i - 1; diff --git a/src/vector.h b/src/vector.h index 1bda9c93d..cca846f43 100644 --- a/src/vector.h +++ b/src/vector.h @@ -71,7 +71,7 @@ int git_vector_insert_sorted(git_vector *v, void *element, int (*on_dup)(void **old, void *new)); int git_vector_remove(git_vector *v, size_t idx); void git_vector_pop(git_vector *v); -void git_vector_uniq(git_vector *v); +void git_vector_uniq(git_vector *v, void (*git_free_cb)(void *)); void git_vector_remove_matching( git_vector *v, int (*match)(const git_vector *v, size_t idx)); diff --git a/tests-clar/core/vector.c b/tests-clar/core/vector.c index c9e43a149..db52c004f 100644 --- a/tests-clar/core/vector.c +++ b/tests-clar/core/vector.c @@ -54,7 +54,7 @@ void test_core_vector__2(void) cl_git_pass(git_vector_insert(&x, ptrs[1])); cl_assert(x.length == 5); - git_vector_uniq(&x); + git_vector_uniq(&x, NULL); cl_assert(x.length == 2); git_vector_free(&x); -- cgit v1.2.1 From aec87f712fd1e84038d5d14b83a97d78e2e1b1ad Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 27 Aug 2013 19:14:18 +0200 Subject: remote: Make git_remote_list() detect pushurl --- src/remote.c | 6 ++++-- tests-clar/network/remote/remotes.c | 10 ++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/remote.c b/src/remote.c index 7276daa39..10c1b5b81 100644 --- a/src/remote.c +++ b/src/remote.c @@ -1109,10 +1109,10 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo) if (git_repository_config__weakptr(&cfg, repo) < 0) return -1; - if (git_vector_init(&list, 4, NULL) < 0) + if (git_vector_init(&list, 4, git__strcmp_cb) < 0) return -1; - if (regcomp(&preg, "^remote\\.(.*)\\.url$", REG_EXTENDED) < 0) { + if (regcomp(&preg, "^remote\\.(.*)\\.(push)?url$", REG_EXTENDED) < 0) { giterr_set(GITERR_OS, "Remote catch regex failed to compile"); return -1; } @@ -1137,6 +1137,8 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo) return error; } + git_vector_uniq(&list, git__free); + remotes_list->strings = (char **)list.contents; remotes_list->count = list.length; diff --git a/tests-clar/network/remote/remotes.c b/tests-clar/network/remote/remotes.c index 55b233eda..6e0eeeb05 100644 --- a/tests-clar/network/remote/remotes.c +++ b/tests-clar/network/remote/remotes.c @@ -243,13 +243,19 @@ void test_network_remote_remotes__list(void) git_config *cfg; cl_git_pass(git_remote_list(&list, _repo)); - cl_assert(list.count == 4); + cl_assert(list.count == 5); git_strarray_free(&list); cl_git_pass(git_repository_config(&cfg, _repo)); + + /* Create a new remote */ cl_git_pass(git_config_set_string(cfg, "remote.specless.url", "http://example.com")); + + /* Update a remote (previously without any url/pushurl entry) */ + cl_git_pass(git_config_set_string(cfg, "remote.no-remote-url.pushurl", "http://example.com")); + cl_git_pass(git_remote_list(&list, _repo)); - cl_assert(list.count == 5); + cl_assert(list.count == 7); git_strarray_free(&list); git_config_free(cfg); -- cgit v1.2.1 From f087bc245e9f3934d43c49f4034ee9b5638884dd Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 27 Aug 2013 12:08:55 -0700 Subject: Convert to our own SRWLOCK type on Win32 --- src/win32/mingw-compat.h | 2 -- src/win32/pthread.c | 2 +- src/win32/pthread.h | 4 +++- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/win32/mingw-compat.h b/src/win32/mingw-compat.h index b06dda209..fe0abfb54 100644 --- a/src/win32/mingw-compat.h +++ b/src/win32/mingw-compat.h @@ -24,8 +24,6 @@ GIT_INLINE(size_t) p_strnlen(const char *s, size_t maxlen) { return end ? (size_t)(end - s) : maxlen; } -typedef struct { void *Ptr; } SRWLOCK; - #endif #endif /* INCLUDE_mingw_compat__ */ diff --git a/src/win32/pthread.c b/src/win32/pthread.c index 8775f632a..d50ace695 100644 --- a/src/win32/pthread.c +++ b/src/win32/pthread.c @@ -146,7 +146,7 @@ int pthread_num_processors_np(void) static HINSTANCE win32_kernel32_dll; -typedef void (WINAPI *win32_srwlock_fn)(SRWLOCK *); +typedef void (WINAPI *win32_srwlock_fn)(GIT_SRWLOCK *); static win32_srwlock_fn win32_srwlock_initialize; static win32_srwlock_fn win32_srwlock_acquire_shared; diff --git a/src/win32/pthread.h b/src/win32/pthread.h index 679ebed23..2ba2ca552 100644 --- a/src/win32/pthread.h +++ b/src/win32/pthread.h @@ -25,9 +25,11 @@ typedef CRITICAL_SECTION pthread_mutex_t; typedef HANDLE pthread_t; typedef HANDLE pthread_cond_t; +typedef struct { void *Ptr; } GIT_SRWLOCK; + typedef struct { union { - SRWLOCK srwl; + GIT_SRWLOCK srwl; CRITICAL_SECTION csec; } native; } pthread_rwlock_t; -- cgit v1.2.1 From 1ff3a094156baba11240f48924dd5e0c1d983d8e Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 27 Aug 2013 19:41:44 -0500 Subject: Improve win32 version check, no ipv6 tests on XP --- src/hash/hash_win32.c | 20 +------------------- src/transports/winhttp.c | 4 ++-- src/win32/error.c | 2 +- src/win32/version.h | 25 +++++++++++++++++++++---- tests-clar/core/posix.c | 19 ++++++++++++++++--- 5 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/hash/hash_win32.c b/src/hash/hash_win32.c index 43d54ca6d..362712e9a 100644 --- a/src/hash/hash_win32.c +++ b/src/hash/hash_win32.c @@ -20,29 +20,11 @@ static struct git_hash_prov hash_prov = {0}; /* Initialize CNG, if available */ GIT_INLINE(int) hash_cng_prov_init(void) { - OSVERSIONINFOEX version_test = {0}; - DWORD version_test_mask; - DWORDLONG version_condition_mask = 0; char dll_path[MAX_PATH]; DWORD dll_path_len, size_len; - return -1; - /* Only use CNG on Windows 2008 / Vista SP1 or better (Windows 6.0 SP1) */ - version_test.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - version_test.dwMajorVersion = 6; - version_test.dwMinorVersion = 0; - version_test.wServicePackMajor = 1; - version_test.wServicePackMinor = 0; - - version_test_mask = (VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR); - - VER_SET_CONDITION(version_condition_mask, VER_MAJORVERSION, VER_GREATER_EQUAL); - VER_SET_CONDITION(version_condition_mask, VER_MINORVERSION, VER_GREATER_EQUAL); - VER_SET_CONDITION(version_condition_mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); - VER_SET_CONDITION(version_condition_mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL); - - if (!VerifyVersionInfo(&version_test, version_test_mask, version_condition_mask)) + if (!git_has_win32_version(6, 0, 1)) return -1; /* Load bcrypt.dll explicitly from the system directory */ diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 8decd8d51..29d4ba619 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -511,7 +511,7 @@ replay: /* Check for Windows 7. This workaround is only necessary on * Windows Vista and earlier. Windows 7 is version 6.1. */ - if (!git_has_win32_version(6, 1)) { + if (!git_has_win32_version(6, 1, 0)) { wchar_t *location; DWORD location_length; int redirect_cmp; @@ -989,7 +989,7 @@ static int winhttp_receivepack( { /* WinHTTP only supports Transfer-Encoding: chunked * on Windows Vista (NT 6.0) and higher. */ - s->chunked = git_has_win32_version(6, 0); + s->chunked = git_has_win32_version(6, 0, 0); if (s->chunked) s->parent.write = winhttp_stream_write_chunked; diff --git a/src/win32/error.c b/src/win32/error.c index a62a07e82..bc598ae32 100644 --- a/src/win32/error.c +++ b/src/win32/error.c @@ -47,7 +47,7 @@ char *git_win32_get_error_message(DWORD error_code) (LPWSTR)&lpMsgBuf, 0, NULL)) { /* Invalid code point check supported on Vista+ only */ - if (git_has_win32_version(6, 0)) + if (git_has_win32_version(6, 0, 0)) dwFlags = WC_ERR_INVALID_CHARS; else dwFlags = 0; diff --git a/src/win32/version.h b/src/win32/version.h index 483962b57..518b0a379 100644 --- a/src/win32/version.h +++ b/src/win32/version.h @@ -9,12 +9,29 @@ #include -GIT_INLINE(int) git_has_win32_version(int major, int minor) +GIT_INLINE(int) git_has_win32_version(int major, int minor, int service_pack) { - WORD wVersion = LOWORD(GetVersion()); + OSVERSIONINFOEX version_test = {0}; + DWORD version_test_mask; + DWORDLONG version_condition_mask = 0; + + version_test.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + version_test.dwMajorVersion = major; + version_test.dwMinorVersion = minor; + version_test.wServicePackMajor = service_pack; + version_test.wServicePackMinor = 0; - return LOBYTE(wVersion) > major || - (LOBYTE(wVersion) == major && HIBYTE(wVersion) >= minor); + version_test_mask = (VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR); + + VER_SET_CONDITION(version_condition_mask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(version_condition_mask, VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(version_condition_mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); + VER_SET_CONDITION(version_condition_mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL); + + if (!VerifyVersionInfo(&version_test, version_test_mask, version_condition_mask)) + return 0; + + return 1; } #endif diff --git a/tests-clar/core/posix.c b/tests-clar/core/posix.c index 890e25d47..1cef937cd 100644 --- a/tests-clar/core/posix.c +++ b/tests-clar/core/posix.c @@ -24,6 +24,16 @@ void test_core_posix__initialize(void) #endif } +static bool supports_ipv6(void) +{ +#ifdef GIT_WIN32 + /* IPv6 is supported on Vista and newer */ + return git_has_win32_version(6, 0, 0); +#else + return 1; +#endif +} + void test_core_posix__inet_pton(void) { struct in_addr addr; @@ -65,9 +75,12 @@ void test_core_posix__inet_pton(void) } /* Test some ipv6 addresses */ - for (i = 0; i < 6; i++) { - cl_assert(p_inet_pton(AF_INET6, in6_addr_data[i].p, &addr6) == 1); - cl_assert(memcmp(&addr6, in6_addr_data[i].n, sizeof(struct in6_addr)) == 0); + if (supports_ipv6()) + { + for (i = 0; i < 6; i++) { + cl_assert(p_inet_pton(AF_INET6, in6_addr_data[i].p, &addr6) == 1); + cl_assert(memcmp(&addr6, in6_addr_data[i].n, sizeof(struct in6_addr)) == 0); + } } /* Test some invalid strings */ -- cgit v1.2.1 From 17c7fbf6d276443344c54f55800367b9837c0259 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 21 Aug 2013 14:07:53 -0500 Subject: Split rewrites, status doesn't return rewrites Ensure that we apply splits to rewrites, even if we're not interested in examining it closely for rename/copy detection. In keeping with core git, status should not display rewrites, it should simply show files as "modified". --- include/git2/diff.h | 3 +++ src/diff_tform.c | 6 +++++- src/status.c | 6 ++++-- tests-clar/diff/rename.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ tests-clar/status/renames.c | 41 +++++++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 3 deletions(-) diff --git a/include/git2/diff.h b/include/git2/diff.h index c989ba4ee..596098574 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -454,6 +454,9 @@ typedef enum { GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE = (1 << 13), /** measure similarity only by comparing SHAs (fast and cheap) */ GIT_DIFF_FIND_EXACT_MATCH_ONLY = (1 << 14), + + /** do not break rewrites unless they contribute to a rename */ + GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY = (1 << 15), } git_diff_find_t; /** diff --git a/src/diff_tform.c b/src/diff_tform.c index ba35d3c14..ca3c77187 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -799,6 +799,9 @@ int git_diff_find_similar( if (is_rename_target(diff, &opts, t, sigcache)) ++num_tgts; + + if ((tgt->flags & GIT_DIFF_FLAG__TO_SPLIT) != 0) + num_rewrites++; } /* if there are no candidate srcs or tgts, we're done */ @@ -1036,7 +1039,8 @@ find_best_matches: if (num_rewrites > 0 || num_updates > 0) error = apply_splits_and_deletes( diff, diff->deltas.length - num_rewrites, - FLAG_SET(&opts, GIT_DIFF_BREAK_REWRITES)); + FLAG_SET(&opts, GIT_DIFF_BREAK_REWRITES) && + !FLAG_SET(&opts, GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY)); cleanup: git__free(tgt2src); diff --git a/src/status.c b/src/status.c index b2353258b..4a0d65092 100644 --- a/src/status.c +++ b/src/status.c @@ -284,8 +284,10 @@ int git_status_list_new( diffopt.flags = diffopt.flags | GIT_DIFF_IGNORE_SUBMODULES; if ((flags & GIT_STATUS_OPT_RENAMES_FROM_REWRITES) != 0) - findopt.flags = findopt.flags | GIT_DIFF_FIND_AND_BREAK_REWRITES | - GIT_DIFF_FIND_RENAMES_FROM_REWRITES; + findopt.flags = findopt.flags | + GIT_DIFF_FIND_AND_BREAK_REWRITES | + GIT_DIFF_FIND_RENAMES_FROM_REWRITES | + GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY; if (show != GIT_STATUS_SHOW_WORKDIR_ONLY) { if ((error = git_diff_tree_to_index( diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index 5a35495f7..ac3814d59 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -1235,3 +1235,52 @@ void test_diff_rename__unmodified_can_be_renamed(void) git_index_free(index); git_tree_free(tree); } + +void test_diff_rename__rewrite_on_single_file(void) +{ + git_index *index; + git_diff_list *diff = NULL; + diff_expects exp; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + + diffopts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + + findopts.flags = GIT_DIFF_FIND_FOR_UNTRACKED | + GIT_DIFF_FIND_AND_BREAK_REWRITES | + GIT_DIFF_FIND_RENAMES_FROM_REWRITES; + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_rewritefile("renames/ikeepsix.txt", + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &diffopts)); + cl_git_pass(git_diff_find_similar(diff, &findopts)); + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(2, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_list_free(diff); + git_index_free(index); +} diff --git a/tests-clar/status/renames.c b/tests-clar/status/renames.c index 836e65c88..d72e563bf 100644 --- a/tests-clar/status/renames.c +++ b/tests-clar/status/renames.c @@ -403,6 +403,47 @@ void test_status_renames__both_rename_from_rewrite(void) git_index_free(index); } +void test_status_renames__rewrites_only_for_renames(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_WT_MODIFIED, "ikeepsix.txt", "ikeepsix.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES; + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_rewritefile("renames/ikeepsix.txt", + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 1); + git_status_list_free(statuslist); + + git_index_free(index); +} + void test_status_renames__both_casechange_one(void) { git_index *index; -- cgit v1.2.1 From b2d3efcbce2d12cfa9736ab4f9283c91600a8a75 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 28 Aug 2013 09:31:32 -0700 Subject: Some documentation improvements --- include/git2/commit.h | 16 ++++++++++++---- include/git2/revparse.h | 43 +++++++++++++++++++++++++++---------------- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/include/git2/commit.h b/include/git2/commit.h index fc0551be1..0eaf917bd 100644 --- a/include/git2/commit.h +++ b/include/git2/commit.h @@ -24,17 +24,24 @@ GIT_BEGIN_DECL /** * Lookup a commit object from a repository. * + * The returned object should be released with `git_commit_free` when no + * longer needed. + * * @param commit pointer to the looked up commit * @param repo the repo to use when locating the commit. * @param id identity of the commit to locate. If the object is * an annotated tag it will be peeled back to the commit. * @return 0 or an error code */ -GIT_EXTERN(int) git_commit_lookup(git_commit **commit, git_repository *repo, const git_oid *id); +GIT_EXTERN(int) git_commit_lookup( + git_commit **commit, git_repository *repo, const git_oid *id); /** - * Lookup a commit object from a repository, - * given a prefix of its identifier (short id). + * Lookup a commit object from a repository, given a prefix of its + * identifier (short id). + * + * The returned object should be released with `git_commit_free` when no + * longer needed. * * @see git_object_lookup_prefix * @@ -45,7 +52,8 @@ GIT_EXTERN(int) git_commit_lookup(git_commit **commit, git_repository *repo, con * @param len the length of the short identifier * @return 0 or an error code */ -GIT_EXTERN(int) git_commit_lookup_prefix(git_commit **commit, git_repository *repo, const git_oid *id, size_t len); +GIT_EXTERN(int) git_commit_lookup_prefix( + git_commit **commit, git_repository *repo, const git_oid *id, size_t len); /** * Close an open commit diff --git a/include/git2/revparse.h b/include/git2/revparse.h index 786a9da57..d170e1621 100644 --- a/include/git2/revparse.h +++ b/include/git2/revparse.h @@ -10,7 +10,6 @@ #include "common.h" #include "types.h" - /** * @file git2/revparse.h * @brief Git revision parsing routines @@ -21,27 +20,37 @@ GIT_BEGIN_DECL /** - * Find a single object, as specified by a revision string. See `man gitrevisions`, - * or http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for + * Find a single object, as specified by a revision string. + * + * See `man gitrevisions`, or + * http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for * information on the syntax accepted. * + * The returned object should be released with `git_object_free` when no + * longer needed. + * * @param out pointer to output object * @param repo the repository to search in * @param spec the textual specification for an object * @return 0 on success, GIT_ENOTFOUND, GIT_EAMBIGUOUS, GIT_EINVALIDSPEC or an error code */ -GIT_EXTERN(int) git_revparse_single(git_object **out, git_repository *repo, const char *spec); +GIT_EXTERN(int) git_revparse_single( + git_object **out, git_repository *repo, const char *spec); /** - * Find a single object, as specified by a revision string. - * See `man gitrevisions`, - * or http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for + * Find a single object and intermediate reference by a revision string. + * + * See `man gitrevisions`, or + * http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for * information on the syntax accepted. * * In some cases (`@{<-n>}` or `@{upstream}`), the expression may * point to an intermediate reference. When such expressions are being passed * in, `reference_out` will be valued as well. * + * The returned object should be released with `git_object_free` and the + * returned reference with `git_reference_free` when no longer needed. + * * @param object_out pointer to output object * @param reference_out pointer to output reference or NULL * @param repo the repository to search in @@ -76,25 +85,27 @@ typedef struct { git_object *from; /** The right element of the revspec; must be freed by the user */ git_object *to; - /** The intent of the revspec */ + /** The intent of the revspec (i.e. `git_revparse_mode_t` flags) */ unsigned int flags; } git_revspec; /** - * Parse a revision string for `from`, `to`, and intent. See `man gitrevisions` or - * http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for information - * on the syntax accepted. + * Parse a revision string for `from`, `to`, and intent. + * + * See `man gitrevisions` or + * http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for + * information on the syntax accepted. * - * @param revspec Pointer to an user-allocated git_revspec struct where the result - * of the rev-parse will be stored + * @param revspec Pointer to an user-allocated git_revspec struct where + * the result of the rev-parse will be stored * @param repo the repository to search in * @param spec the rev-parse spec to parse * @return 0 on success, GIT_INVALIDSPEC, GIT_ENOTFOUND, GIT_EAMBIGUOUS or an error code */ GIT_EXTERN(int) git_revparse( - git_revspec *revspec, - git_repository *repo, - const char *spec); + git_revspec *revspec, + git_repository *repo, + const char *spec); /** @} */ -- cgit v1.2.1 From 19b9a0920987f07d05040b3a067b1599e38f6013 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 28 Aug 2013 11:20:47 -0700 Subject: Add stddef include for sortedcache All use of sortedcache will need this header, so put it in the definition of the sortedcache API. --- src/sortedcache.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sortedcache.h b/src/sortedcache.h index 5ebb116ed..4cacad62b 100644 --- a/src/sortedcache.h +++ b/src/sortedcache.h @@ -14,6 +14,8 @@ #include "pool.h" #include "strmap.h" +#include + /* * The purpose of this data structure is to cache the parsed contents of a * file (a.k.a. the backing file) where each item in the file can be -- cgit v1.2.1 From 4ab6a759f63caa75ea716154887fc0a94de01b6e Mon Sep 17 00:00:00 2001 From: Justin Spahr-Summers Date: Wed, 28 Aug 2013 22:51:44 -0700 Subject: Fix incorrect precedence within git_repository_is_empty() Reverts part of 9146f1e57ec4f2b6fa293c78d54f1383464ff5be. --- src/repository.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/repository.c b/src/repository.c index 99ac56ef9..e5f23e4e4 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1500,7 +1500,7 @@ int git_repository_is_empty(git_repository *repo) if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0) return -1; - if (!((error = git_reference_type(head)) == GIT_REF_SYMBOLIC)) + if (!(error = (git_reference_type(head) == GIT_REF_SYMBOLIC))) goto cleanup; if (!(error = (strcmp( -- cgit v1.2.1 From 0001c0231607bd8bc9b09bde6c1d7d0fb396565f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 29 Aug 2013 13:22:44 +0200 Subject: Fix typo _delete -> _free --- tests-clar/threads/refdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests-clar/threads/refdb.c b/tests-clar/threads/refdb.c index ffe437575..f8d76cb9b 100644 --- a/tests-clar/threads/refdb.c +++ b/tests-clar/threads/refdb.c @@ -130,7 +130,7 @@ static void *delete_refs(void *arg) if (!git_reference_lookup(&ref, g_repo, name)) { cl_git_pass(git_reference_delete(ref)); - git_reference_delete(ref); + git_reference_free(ref); } if (i == 5) { -- cgit v1.2.1 From 8b2f230cd519010d202c57185dc4dc39ca3d53f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicent=20Mart=C3=AD?= Date: Thu, 29 Aug 2013 13:27:37 +0200 Subject: repository: Make the is_empty check more explicit --- src/repository.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/repository.c b/src/repository.c index e5f23e4e4..80904d5fa 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1500,8 +1500,10 @@ int git_repository_is_empty(git_repository *repo) if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0) return -1; - if (!(error = (git_reference_type(head) == GIT_REF_SYMBOLIC))) + if (git_reference_type(head) != GIT_REF_SYMBOLIC) { + error = -1; goto cleanup; + } if (!(error = (strcmp( git_reference_symbolic_target(head), -- cgit v1.2.1 From 4218183631faa48f97e76a23e928d1a98983be46 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 29 Aug 2013 10:27:01 -0700 Subject: Treat detached HEAD as non-empty repo This simplifies the git_repository_is_empty a bit so that a detached HEAD is just taken to mean the repo is not empty, since a newly initialized repo will not have a detached HEAD. --- src/repository.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/repository.c b/src/repository.c index 80904d5fa..eae22ce51 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1495,26 +1495,20 @@ static int repo_contains_no_reference(git_repository *repo) int git_repository_is_empty(git_repository *repo) { git_reference *head = NULL; - int error; + int is_empty = 0; if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0) return -1; - if (git_reference_type(head) != GIT_REF_SYMBOLIC) { - error = -1; - goto cleanup; - } + if (git_reference_type(head) == GIT_REF_SYMBOLIC) + is_empty = + (strcmp(git_reference_symbolic_target(head), + GIT_REFS_HEADS_DIR "master") == 0) && + repo_contains_no_reference(repo); - if (!(error = (strcmp( - git_reference_symbolic_target(head), - GIT_REFS_HEADS_DIR "master") == 0))) - goto cleanup; - - error = repo_contains_no_reference(repo); - -cleanup: git_reference_free(head); - return error < 0 ? -1 : error; + + return is_empty; } const char *git_repository_path(git_repository *repo) -- cgit v1.2.1 From a12e069a3e904728d55dc5c92094b0a5cee63da2 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Fri, 30 Aug 2013 16:31:52 +0200 Subject: odb: Honor the non refreshing capability of a backend --- src/odb.c | 6 +- tests-clar/odb/backend/nonrefreshing.c | 261 +++++++++++++++++++++++++++++++++ 2 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 tests-clar/odb/backend/nonrefreshing.c diff --git a/src/odb.c b/src/odb.c index 21b46bf56..9785c74da 100644 --- a/src/odb.c +++ b/src/odb.c @@ -622,7 +622,7 @@ attempt_lookup: backend_internal *internal = git_vector_get(&db->backends, i); git_odb_backend *b = internal->backend; - if (b->exists != NULL) + if (b->exists != NULL && (!refreshed || b->refresh)) found = b->exists(b, id); } @@ -717,7 +717,7 @@ attempt_lookup: backend_internal *internal = git_vector_get(&db->backends, i); git_odb_backend *b = internal->backend; - if (b->read != NULL) { + if (b->read != NULL && (!refreshed || b->refresh)) { ++reads; error = b->read(&raw.data, &raw.len, &raw.type, b, id); } @@ -774,7 +774,7 @@ attempt_lookup: backend_internal *internal = git_vector_get(&db->backends, i); git_odb_backend *b = internal->backend; - if (b->read_prefix != NULL) { + if (b->read_prefix != NULL && (!refreshed || b->refresh)) { git_oid full_oid; error = b->read_prefix(&full_oid, &raw.data, &raw.len, &raw.type, b, short_id, len); if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH) diff --git a/tests-clar/odb/backend/nonrefreshing.c b/tests-clar/odb/backend/nonrefreshing.c new file mode 100644 index 000000000..abb824d4b --- /dev/null +++ b/tests-clar/odb/backend/nonrefreshing.c @@ -0,0 +1,261 @@ +#include "clar_libgit2.h" +#include "git2/sys/odb_backend.h" +#include "repository.h" + +typedef struct fake_backend { + git_odb_backend parent; + + git_error_code error_code; + + int exists_calls; + int read_calls; + int read_header_calls; + int read_prefix_calls; +} fake_backend; + +static git_repository *_repo; +static fake_backend *_fake; +static git_oid _oid; + +static int fake_backend__exists(git_odb_backend *backend, const git_oid *oid) +{ + fake_backend *fake; + + GIT_UNUSED(oid); + + fake = (fake_backend *)backend; + + fake->exists_calls++; + + return (fake->error_code == GIT_OK); +} + +static int fake_backend__read( + void **buffer_p, size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *oid) +{ + fake_backend *fake; + + GIT_UNUSED(buffer_p); + GIT_UNUSED(len_p); + GIT_UNUSED(type_p); + GIT_UNUSED(oid); + + fake = (fake_backend *)backend; + + fake->read_calls++; + + *len_p = 0; + *buffer_p = NULL; + *type_p = GIT_OBJ_BLOB; + + return fake->error_code; +} + +static int fake_backend__read_header( + size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *oid) +{ + fake_backend *fake; + + GIT_UNUSED(len_p); + GIT_UNUSED(type_p); + GIT_UNUSED(oid); + + fake = (fake_backend *)backend; + + fake->read_header_calls++; + + *len_p = 0; + *type_p = GIT_OBJ_BLOB; + + return fake->error_code; +} + +static int fake_backend__read_prefix( + git_oid *out_oid, void **buffer_p, size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *short_oid, size_t len) +{ + fake_backend *fake; + + GIT_UNUSED(out_oid); + GIT_UNUSED(buffer_p); + GIT_UNUSED(len_p); + GIT_UNUSED(type_p); + GIT_UNUSED(short_oid); + GIT_UNUSED(len); + + fake = (fake_backend *)backend; + + fake->read_prefix_calls++; + + *len_p = 0; + *buffer_p = NULL; + *type_p = GIT_OBJ_BLOB; + + return fake->error_code; +} + +static void fake_backend__free(git_odb_backend *_backend) +{ + fake_backend *backend; + + backend = (fake_backend *)_backend; + + git__free(backend); +} + +static int build_fake_backend( + git_odb_backend **out, + git_error_code error_code) +{ + fake_backend *backend; + + backend = git__calloc(1, sizeof(fake_backend)); + GITERR_CHECK_ALLOC(backend); + + backend->parent.version = GIT_ODB_BACKEND_VERSION; + + backend->parent.refresh = NULL; + backend->error_code = error_code; + + backend->parent.read = fake_backend__read; + backend->parent.read_prefix = fake_backend__read_prefix; + backend->parent.read_header = fake_backend__read_header; + backend->parent.exists = fake_backend__exists; + backend->parent.free = &fake_backend__free; + + *out = (git_odb_backend *)backend; + + return 0; +} + +static void setup_repository_and_backend(git_error_code error_code) +{ + git_odb *odb; + git_odb_backend *backend; + + _repo = cl_git_sandbox_init("testrepo.git"); + + cl_git_pass(build_fake_backend(&backend, error_code)); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_git_pass(git_odb_add_backend(odb, backend, 10)); + + _fake = (fake_backend *)backend; + + cl_git_pass(git_oid_fromstr(&_oid, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")); +} + +void test_odb_backend_nonrefreshing__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_odb_backend_nonrefreshing__exists_is_invoked_once_on_failure(void) +{ + git_odb *odb; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_assert_equal_b(false, git_odb_exists(odb, &_oid)); + + cl_assert_equal_i(1, _fake->exists_calls); +} + +void test_odb_backend_nonrefreshing__read_is_invoked_once_on_failure(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_fail_with( + git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY), + GIT_ENOTFOUND); + + cl_assert_equal_i(1, _fake->read_calls); +} + +void test_odb_backend_nonrefreshing__readprefix_is_invoked_once_on_failure(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_fail_with( + git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY), + GIT_ENOTFOUND); + + cl_assert_equal_i(1, _fake->read_prefix_calls); +} + +void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_failure(void) +{ + git_odb *odb; + size_t len; + git_otype type; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + + cl_git_fail_with( + git_odb_read_header(&len, &type, odb, &_oid), + GIT_ENOTFOUND); + + cl_assert_equal_i(1, _fake->read_header_calls); +} + +void test_odb_backend_nonrefreshing__exists_is_invoked_once_on_success(void) +{ + git_odb *odb; + + setup_repository_and_backend(GIT_OK); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_assert_equal_b(true, git_odb_exists(odb, &_oid)); + + cl_assert_equal_i(1, _fake->exists_calls); +} + +void test_odb_backend_nonrefreshing__read_is_invoked_once_on_success(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_OK); + + cl_git_pass(git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY)); + + cl_assert_equal_i(1, _fake->read_calls); + + git_object_free(obj); +} + +void test_odb_backend_nonrefreshing__readprefix_is_invoked_once_on_success(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_OK); + + cl_git_pass(git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY)); + + cl_assert_equal_i(1, _fake->read_prefix_calls); + + git_object_free(obj); +} + +void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_success(void) +{ + git_odb *odb; + size_t len; + git_otype type; + + setup_repository_and_backend(GIT_OK); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + + cl_git_pass(git_odb_read_header(&len, &type, odb, &_oid)); + + cl_assert_equal_i(1, _fake->read_header_calls); +} -- cgit v1.2.1 From 9b4ed214f484f22f127d7398467f45affcc014af Mon Sep 17 00:00:00 2001 From: nulltoken Date: Fri, 30 Aug 2013 17:07:41 +0200 Subject: odb: Code beautification --- src/odb_pack.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/odb_pack.c b/src/odb_pack.c index 43880612a..d7abd1020 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -342,8 +342,9 @@ static int pack_backend__refresh(git_odb_backend *_backend) return 0; } - -static int pack_backend__read_header(size_t *len_p, git_otype *type_p, struct git_odb_backend *backend, const git_oid *oid) +static int pack_backend__read_header( + size_t *len_p, git_otype *type_p, + struct git_odb_backend *backend, const git_oid *oid) { struct git_pack_entry e; int error; @@ -356,7 +357,9 @@ static int pack_backend__read_header(size_t *len_p, git_otype *type_p, struct gi return git_packfile_resolve_header(len_p, type_p, e.p, e.offset); } -static int pack_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid) +static int pack_backend__read( + void **buffer_p, size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *oid) { struct git_pack_entry e; git_rawobj raw; -- cgit v1.2.1 From e68938e0b98fac52da20171f33ca3abfdbf3f434 Mon Sep 17 00:00:00 2001 From: Linquize Date: Sat, 31 Aug 2013 18:19:44 +0800 Subject: Update documentation of git_oid_streq to remove outdated error code --- include/git2/oid.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/git2/oid.h b/include/git2/oid.h index 662338d93..c69968ad1 100644 --- a/include/git2/oid.h +++ b/include/git2/oid.h @@ -188,8 +188,7 @@ GIT_EXTERN(int) git_oid_ncmp(const git_oid *a, const git_oid *b, size_t len); * * @param id oid structure. * @param str input hex string of an object id. - * @return GIT_ENOTOID if str is not a valid hex string, - * 0 in case of a match, GIT_ERROR otherwise. + * @return 0 in case of a match, -1 otherwise. */ GIT_EXTERN(int) git_oid_streq(const git_oid *id, const char *str); -- cgit v1.2.1 From d45e9480e74c3c6249aea631394e1364b138e66e Mon Sep 17 00:00:00 2001 From: Linquize Date: Sat, 31 Aug 2013 18:22:50 +0800 Subject: oid: git_oid_shorten_add() sets GITERR_INVALID when OID set is full --- include/git2/oid.h | 4 ++-- src/oid.c | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/git2/oid.h b/include/git2/oid.h index 662338d93..8bf43a279 100644 --- a/include/git2/oid.h +++ b/include/git2/oid.h @@ -241,13 +241,13 @@ GIT_EXTERN(git_oid_shorten *) git_oid_shorten_new(size_t min_length); * or freed. * * For performance reasons, there is a hard-limit of how many - * OIDs can be added to a single set (around ~22000, assuming + * OIDs can be added to a single set (around ~32000, assuming * a mostly randomized distribution), which should be enough * for any kind of program, and keeps the algorithm fast and * memory-efficient. * * Attempting to add more than those OIDs will result in a - * GIT_ENOMEM error + * GITERR_INVALID error * * @param os a `git_oid_shorten` instance * @param text_id an OID in text form diff --git a/src/oid.c b/src/oid.c index 8300e46c1..a70b7e099 100644 --- a/src/oid.c +++ b/src/oid.c @@ -369,8 +369,10 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid) bool is_leaf; node_index idx; - if (os->full) + if (os->full) { + giterr_set(GITERR_INVALID, "Unable to shorten OID - OID set full"); return -1; + } if (text_oid == NULL) return os->min_length; @@ -396,12 +398,19 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid) node->tail = NULL; node = push_leaf(os, idx, git__fromhex(tail[0]), &tail[1]); - GITERR_CHECK_ALLOC(node); + if (node == NULL) { + if (os->full) + giterr_set(GITERR_INVALID, "Unable to shorten OID - OID set full"); + return -1; + } } if (node->children[c] == 0) { - if (push_leaf(os, idx, c, &text_oid[i + 1]) == NULL) + 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"); return -1; + } break; } -- cgit v1.2.1 From a402179ae58c9954794bb6b172a30249d6be6127 Mon Sep 17 00:00:00 2001 From: Nirvana Date: Sat, 31 Aug 2013 09:25:25 -0400 Subject: Update readme to point to the currently maintained Erlang bindings. Namely: https://github.com/carlosmn/geef --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a89463b7c..bcab8ac51 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ Here are the bindings to libgit2 that are currently available: * Delphi * GitForDelphi * Erlang - * Geef + * Geef * Go * go-git * GObject -- cgit v1.2.1 From f2cda906e515bd4cb0cfe244652d764fdabbe23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 31 Aug 2013 17:42:38 +0200 Subject: Point to the right Go bindings --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bcab8ac51..44fd059c1 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ Here are the bindings to libgit2 that are currently available: * Erlang * Geef * Go - * go-git + * git2go * GObject * libgit2-glib * Haskell -- cgit v1.2.1 From 82b2fc2c8325830667ed780ae5402674c7b9bbf5 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Sun, 1 Sep 2013 18:45:36 +0200 Subject: Create ANDROID build option CMake seems not to support Android as a target and this option lets us test this in CMakeLists.txt. --- CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c70ec2d6..a9b87b8a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,8 @@ OPTION( PROFILE "Generate profiling information" OFF ) OPTION( ENABLE_TRACE "Enables tracing support" OFF ) OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF ) +OPTION( ANDROID "Build for android NDK" OFF ) + IF(MSVC) # This option is only available when building with MSVC. By default, libgit2 # is build using the cdecl calling convention, which is useful if you're @@ -127,7 +129,7 @@ IF (ENABLE_TRACE STREQUAL "ON") ENDIF() # Include POSIX regex when it is required -IF(WIN32 OR AMIGA) +IF(WIN32 OR AMIGA OR ANDROID) INCLUDE_DIRECTORIES(deps/regex) SET(SRC_REGEX deps/regex/regex.c) ENDIF() @@ -409,7 +411,7 @@ ENDIF () IF (BUILD_EXAMPLES) FILE(GLOB_RECURSE EXAMPLE_SRC examples/network/*.c examples/network/*.h) ADD_EXECUTABLE(cgit2 ${EXAMPLE_SRC}) - IF(WIN32) + IF(WIN32 OR ANDROID) TARGET_LINK_LIBRARIES(cgit2 git2) ELSE() TARGET_LINK_LIBRARIES(cgit2 git2 pthread) -- cgit v1.2.1 From b1447edebc15de58f46e5863e59acb7b4988f304 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Sun, 1 Sep 2013 18:47:56 +0200 Subject: Use git__insertsort_r on Android too. --- src/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.c b/src/util.c index ad7603829..d0c326ae5 100644 --- a/src/util.c +++ b/src/util.c @@ -711,7 +711,7 @@ void git__qsort_r( void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload) { #if defined(__MINGW32__) || defined(__OpenBSD__) || defined(AMIGA) || \ - defined(__gnu_hurd__) || \ + defined(__gnu_hurd__) || defined(__ANDROID_API__) || \ (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8) git__insertsort_r(els, nel, elsize, NULL, cmp, payload); #elif defined(GIT_WIN32) -- cgit v1.2.1 From 3b75b684a1ac32cbf726cc3d647453a769b8dfe4 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Sun, 1 Sep 2013 18:53:07 +0200 Subject: Define S_IREAD i S_IWRITE for Android. --- tests-clar/odb/loose.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests-clar/odb/loose.c b/tests-clar/odb/loose.c index 9539bb24c..eb6b788b7 100644 --- a/tests-clar/odb/loose.c +++ b/tests-clar/odb/loose.c @@ -3,6 +3,11 @@ #include "posix.h" #include "loose_data.h" +#ifdef __ANDROID_API__ +# define S_IREAD S_IRUSR +# define S_IWRITE S_IWUSR +#endif + static void write_object_files(object_data *d) { int fd; -- cgit v1.2.1 From d6d523486c26f8f10cd687fa2aa328c770650288 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Sun, 1 Sep 2013 18:30:11 +0200 Subject: Removing unneeded code duplication in ls-remote.c --- examples/network/ls-remote.c | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/examples/network/ls-remote.c b/examples/network/ls-remote.c index 252011828..e837654a1 100644 --- a/examples/network/ls-remote.c +++ b/examples/network/ls-remote.c @@ -14,31 +14,6 @@ static int show_ref__cb(git_remote_head *head, void *payload) return 0; } -static int use_unnamed(git_repository *repo, const char *url) -{ - git_remote *remote = NULL; - int error; - - // Create an instance of a remote from the URL. The transport to use - // is detected from the URL - error = git_remote_create_inmemory(&remote, repo, NULL, url); - if (error < 0) - goto cleanup; - - // When connecting, the underlying code needs to know wether we - // want to push or fetch - error = git_remote_connect(remote, GIT_DIRECTION_FETCH); - if (error < 0) - goto cleanup; - - // With git_remote_ls we can retrieve the advertised heads - error = git_remote_ls(remote, &show_ref__cb, NULL); - -cleanup: - git_remote_free(remote); - return error; -} - static int use_remote(git_repository *repo, char *name) { git_remote *remote = NULL; @@ -46,8 +21,12 @@ static int use_remote(git_repository *repo, char *name) // Find the remote by name error = git_remote_load(&remote, repo, name); - if (error < 0) - goto cleanup; + if (error < 0) { + error = git_remote_create_inmemory(&remote, repo, NULL, name); + if (error < 0) + goto cleanup; + } + error = git_remote_connect(remote, GIT_DIRECTION_FETCH); if (error < 0) @@ -72,12 +51,7 @@ int ls_remote(git_repository *repo, int argc, char **argv) return EXIT_FAILURE; } - /* If there's a ':' in the name, assume it's an URL */ - if (strchr(argv[1], ':') != NULL) { - error = use_unnamed(repo, argv[1]); - } else { - error = use_remote(repo, argv[1]); - } + error = use_remote(repo, argv[1]); return error; } -- cgit v1.2.1 From 255836ddac05418f6bb2d68d27f5ff290669e2a9 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Sun, 1 Sep 2013 18:35:39 +0200 Subject: Adding credentials callback to ls-remote and fetch too. --- examples/network/Makefile | 3 ++- examples/network/clone.c | 33 +-------------------------------- examples/network/common.c | 34 ++++++++++++++++++++++++++++++++++ examples/network/common.h | 6 ++++++ examples/network/fetch.c | 1 + examples/network/ls-remote.c | 1 + 6 files changed, 45 insertions(+), 33 deletions(-) create mode 100644 examples/network/common.c diff --git a/examples/network/Makefile b/examples/network/Makefile index 810eb705b..f65c6cb26 100644 --- a/examples/network/Makefile +++ b/examples/network/Makefile @@ -11,7 +11,8 @@ OBJECTS = \ ls-remote.o \ fetch.o \ clone.o \ - index-pack.o + index-pack.o \ + common.o all: $(OBJECTS) $(CC) $(CFLAGS) $(LDFLAGS) -o git2 $(OBJECTS) $(LIBRARIES) diff --git a/examples/network/clone.c b/examples/network/clone.c index 00c25c1ae..a09a94728 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -9,19 +9,6 @@ # include #endif -/* Shamelessly borrowed from http://stackoverflow.com/questions/3417837/ - * with permission of the original author, Martin Pool. - * http://sourcefrog.net/weblog/software/languages/C/unused.html - */ -#ifdef UNUSED -#elif defined(__GNUC__) -# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) -#elif defined(__LCLINT__) -# define UNUSED(x) /*@unused@*/ x -#else -# define UNUSED(x) x -#endif - typedef struct progress_data { git_transfer_progress fetch_progress; size_t completed_steps; @@ -63,24 +50,6 @@ static void checkout_progress(const char *path, size_t cur, size_t tot, void *pa print_progress(pd); } -static int cred_acquire(git_cred **out, - const char * UNUSED(url), - const char * UNUSED(username_from_url), - unsigned int UNUSED(allowed_types), - void * UNUSED(payload)) -{ - char username[128] = {0}; - char password[128] = {0}; - - printf("Username: "); - scanf("%s", username); - - /* Yup. Right there on your terminal. Careful where you copy/paste output. */ - printf("Password: "); - scanf("%s", password); - - return git_cred_userpass_plaintext_new(out, username, password); -} int do_clone(git_repository *repo, int argc, char **argv) { @@ -107,7 +76,7 @@ int do_clone(git_repository *repo, int argc, char **argv) clone_opts.checkout_opts = checkout_opts; clone_opts.fetch_progress_cb = &fetch_progress; clone_opts.fetch_progress_payload = &pd; - clone_opts.cred_acquire_cb = cred_acquire; + clone_opts.cred_acquire_cb = cred_acquire_cb; // Do the clone error = git_clone(&cloned_repo, url, path, &clone_opts); diff --git a/examples/network/common.c b/examples/network/common.c new file mode 100644 index 000000000..d123eedbd --- /dev/null +++ b/examples/network/common.c @@ -0,0 +1,34 @@ +#include "common.h" +#include + +/* Shamelessly borrowed from http://stackoverflow.com/questions/3417837/ + * with permission of the original author, Martin Pool. + * http://sourcefrog.net/weblog/software/languages/C/unused.html + */ +#ifdef UNUSED +#elif defined(__GNUC__) +# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) +#elif defined(__LCLINT__) +# define UNUSED(x) /*@unused@*/ x +#else +# define UNUSED(x) x +#endif + +int cred_acquire_cb(git_cred **out, + const char * UNUSED(url), + const char * UNUSED(username_from_url), + unsigned int UNUSED(allowed_types), + void * UNUSED(payload)) +{ + char username[128] = {0}; + char password[128] = {0}; + + printf("Username: "); + scanf("%s", username); + + /* Yup. Right there on your terminal. Careful where you copy/paste output. */ + printf("Password: "); + scanf("%s", password); + + return git_cred_userpass_plaintext_new(out, username, password); +} diff --git a/examples/network/common.h b/examples/network/common.h index a4cfa1a7e..1b09caad4 100644 --- a/examples/network/common.h +++ b/examples/network/common.h @@ -12,6 +12,12 @@ int fetch(git_repository *repo, int argc, char **argv); int index_pack(git_repository *repo, int argc, char **argv); int do_clone(git_repository *repo, int argc, char **argv); +int cred_acquire_cb(git_cred **out, + const char * url, + const char * username_from_url, + unsigned int allowed_types, + void *payload); + #ifndef PRIuZ /* Define the printf format specifer to use for size_t output */ #if defined(_MSC_VER) || defined(__MINGW32__) diff --git a/examples/network/fetch.c b/examples/network/fetch.c index 6020ec6ec..ce016ce0b 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -92,6 +92,7 @@ int fetch(git_repository *repo, int argc, char **argv) callbacks.update_tips = &update_cb; callbacks.progress = &progress_cb; git_remote_set_callbacks(remote, &callbacks); + git_remote_set_cred_acquire_cb(remote, &cred_acquire_cb, NULL); // Set up the information for the background worker thread data.remote = remote; diff --git a/examples/network/ls-remote.c b/examples/network/ls-remote.c index e837654a1..b22ac47a0 100644 --- a/examples/network/ls-remote.c +++ b/examples/network/ls-remote.c @@ -27,6 +27,7 @@ static int use_remote(git_repository *repo, char *name) goto cleanup; } + git_remote_set_cred_acquire_cb(remote, &cred_acquire_cb, NULL); error = git_remote_connect(remote, GIT_DIRECTION_FETCH); if (error < 0) -- cgit v1.2.1 From 5c37f00505bf00c14468813d94df69f3387f15b3 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Sun, 1 Sep 2013 18:59:42 +0200 Subject: Build all example files if BUILD_EXAMPLES used. --- CMakeLists.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c70ec2d6..317ed1bee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -426,4 +426,19 @@ IF (BUILD_EXAMPLES) ADD_EXECUTABLE(git-rev-list examples/rev-list.c) TARGET_LINK_LIBRARIES(git-rev-list git2) + + ADD_EXECUTABLE(git-rev-parse examples/rev-parse.c) + TARGET_LINK_LIBRARIES(git-rev-parse git2) + + ADD_EXECUTABLE(git-log examples/log.c) + TARGET_LINK_LIBRARIES(git-log git2) + + ADD_EXECUTABLE(git-status examples/status.c) + TARGET_LINK_LIBRARIES(git-status git2) + + ADD_EXECUTABLE(git-init examples/init.c) + TARGET_LINK_LIBRARIES(git-init git2) + + ADD_EXECUTABLE(git-cat-file examples/cat-file.c) + TARGET_LINK_LIBRARIES(git-cat-file git2) ENDIF () -- cgit v1.2.1 From 01cd5ae3772a32b29c6bd1cdc1cdc50d98961c1c Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Sun, 1 Sep 2013 19:43:35 +0200 Subject: Add instructions about buiding for Android to README.md --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index 44fd059c1..9222f3dcf 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,28 @@ See [the wiki] (https://github.com/libgit2/libgit2/wiki/Building-libgit2-on-Windows) for more detailed instructions. +Android +------- + +Extract toolchain from NDK using, `make-standalone-toolchain.sh` script. +Optionaly, crosscompile and install OpenSSL inside of it. Then create CMake +toolchain file that configures paths to your crosscompiler (substitude `{PATH}` +with full path to the toolchain): + + SET(CMAKE_SYSTEM_NAME Linux) + SET(CMAKE_SYSTEM_VERSION Android) + + SET(CMAKE_C_COMPILER {PATH}/bin/arm-linux-androideabi-gcc) + SET(CMAKE_CXX_COMPILER {PATH}/bin/arm-linux-androideabi-g++) + SET(CMAKE_FIND_ROOT_PATH {PATH}/sysroot/) + + SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +Add `-DCMAKE_TOOLCHAIN_FILE={pathToToolchainFile} -DANDROID=1` to cmake command +when configuring. + Language Bindings ================================== -- cgit v1.2.1 From 6d9a6c5cecebfaaecb4c39d002c8e0cdd26c4b85 Mon Sep 17 00:00:00 2001 From: Nikolai Vladimirov Date: Tue, 3 Sep 2013 07:58:21 +0300 Subject: path: properly resolve relative paths --- src/path.c | 31 +++++++++++++--- tests-clar/core/path.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 119 insertions(+), 10 deletions(-) diff --git a/src/path.c b/src/path.c index a753a734d..50a990b27 100644 --- a/src/path.c +++ b/src/path.c @@ -646,12 +646,33 @@ int git_path_resolve_relative(git_buf *path, size_t ceiling) /* do nothing with singleton dot */; else if (len == 2 && from[0] == '.' && from[1] == '.') { - while (to > base && to[-1] == '/') to--; - while (to > base && to[-1] != '/') to--; - } + /* 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"); + return -1; + } + + /* no more path segments to strip, + * use '../' as a new base path */ + if (to == base) { + if (*next == '/') + len++; - else { - if (*next == '/') + if (to != from) + memmove(to, from, len); + + to += len; + /* this is now the base, can't back up from a + * relative prefix */ + base = to; + } else { + /* back up a path segment */ + while (to > base && to[-1] == '/') to--; + while (to > base && to[-1] != '/') to--; + } + } else { + if (*next == '/' && *from != '/') len++; if (to != from) diff --git a/tests-clar/core/path.c b/tests-clar/core/path.c index 407770baa..d35a5bda8 100644 --- a/tests-clar/core/path.c +++ b/tests-clar/core/path.c @@ -446,16 +446,15 @@ void test_core_path__14_apply_relative(void) cl_git_pass(git_path_apply_relative(&p, "../../../../../..")); cl_assert_equal_s("/this/", p.ptr); - cl_git_pass(git_path_apply_relative(&p, "../../../../../")); + cl_git_pass(git_path_apply_relative(&p, "../")); cl_assert_equal_s("/", p.ptr); - cl_git_pass(git_path_apply_relative(&p, "../../../../..")); - cl_assert_equal_s("/", p.ptr); + cl_git_fail(git_path_apply_relative(&p, "../../..")); cl_git_pass(git_buf_sets(&p, "d:/another/test")); - cl_git_pass(git_path_apply_relative(&p, "../../../../..")); + cl_git_pass(git_path_apply_relative(&p, "../..")); cl_assert_equal_s("d:/", p.ptr); cl_git_pass(git_path_apply_relative(&p, "from/here/to/../and/./back/.")); @@ -473,8 +472,97 @@ void test_core_path__14_apply_relative(void) cl_git_pass(git_path_apply_relative(&p, "..")); cl_assert_equal_s("https://my.url.com/full/path/", p.ptr); - cl_git_pass(git_path_apply_relative(&p, "../../../../../")); + cl_git_pass(git_path_apply_relative(&p, "../../../")); cl_assert_equal_s("https://", p.ptr); + + cl_git_pass(git_buf_sets(&p, "../../this/is/relative")); + + cl_git_pass(git_path_apply_relative(&p, "../../preserves/the/prefix")); + cl_assert_equal_s("../../this/preserves/the/prefix", p.ptr); + + cl_git_pass(git_path_apply_relative(&p, "../../../../that")); + cl_assert_equal_s("../../that", p.ptr); + + cl_git_pass(git_path_apply_relative(&p, "../there")); + cl_assert_equal_s("../../there", p.ptr); git_buf_free(&p); } + +static inline void assert_resolve_relative(git_buf *buf, const char *expected, const char *path) +{ + cl_git_pass(git_buf_sets(buf, path)); + cl_git_pass(git_path_resolve_relative(buf, 0)); + cl_assert_equal_s(expected, buf->ptr); +} + +void test_core_path__15_resolve_relative(void) +{ + git_buf buf = GIT_BUF_INIT; + + assert_resolve_relative(&buf, "", ""); + assert_resolve_relative(&buf, "", "."); + assert_resolve_relative(&buf, "", "./"); + assert_resolve_relative(&buf, "..", ".."); + assert_resolve_relative(&buf, "../", "../"); + assert_resolve_relative(&buf, "..", "./.."); + assert_resolve_relative(&buf, "../", "./../"); + assert_resolve_relative(&buf, "../", "../."); + assert_resolve_relative(&buf, "../", ".././"); + assert_resolve_relative(&buf, "../..", "../.."); + assert_resolve_relative(&buf, "../../", "../../"); + + assert_resolve_relative(&buf, "/", "/"); + assert_resolve_relative(&buf, "/", "/."); + + assert_resolve_relative(&buf, "", "a/.."); + assert_resolve_relative(&buf, "", "a/../"); + assert_resolve_relative(&buf, "", "a/../."); + + assert_resolve_relative(&buf, "/a", "/a"); + assert_resolve_relative(&buf, "/a/", "/a/."); + assert_resolve_relative(&buf, "/", "/a/../"); + assert_resolve_relative(&buf, "/", "/a/../."); + assert_resolve_relative(&buf, "/", "/a/.././"); + + assert_resolve_relative(&buf, "a", "a"); + assert_resolve_relative(&buf, "a/", "a/"); + assert_resolve_relative(&buf, "a/", "a/."); + assert_resolve_relative(&buf, "a/", "a/./"); + + assert_resolve_relative(&buf, "a/b", "a//b"); + assert_resolve_relative(&buf, "a/b/c", "a/b/c"); + assert_resolve_relative(&buf, "b/c", "./b/c"); + assert_resolve_relative(&buf, "a/c", "a/./c"); + assert_resolve_relative(&buf, "a/b/", "a/b/."); + + assert_resolve_relative(&buf, "/a/b/c", "///a/b/c"); + assert_resolve_relative(&buf, "/a/b/c", "//a/b/c"); + assert_resolve_relative(&buf, "/", "////"); + assert_resolve_relative(&buf, "/a", "///a"); + assert_resolve_relative(&buf, "/", "///."); + assert_resolve_relative(&buf, "/", "///a/.."); + + assert_resolve_relative(&buf, "../../path", "../../test//../././path"); + assert_resolve_relative(&buf, "../d", "a/b/../../../c/../d"); + + cl_git_pass(git_buf_sets(&buf, "/..")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); + + cl_git_pass(git_buf_sets(&buf, "/./..")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); + + cl_git_pass(git_buf_sets(&buf, "/.//..")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); + + cl_git_pass(git_buf_sets(&buf, "/../.")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); + + cl_git_pass(git_buf_sets(&buf, "/../.././../a")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); + + cl_git_pass(git_buf_sets(&buf, "////..")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); + + git_buf_free(&buf); +} -- cgit v1.2.1 From 0d1af399e958b50540c83d5eef51cf119da76667 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 3 Sep 2013 12:33:34 -0700 Subject: don't use inline in tests for win32 --- tests-clar/core/path.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests-clar/core/path.c b/tests-clar/core/path.c index d35a5bda8..300600115 100644 --- a/tests-clar/core/path.c +++ b/tests-clar/core/path.c @@ -489,7 +489,8 @@ void test_core_path__14_apply_relative(void) git_buf_free(&p); } -static inline void assert_resolve_relative(git_buf *buf, const char *expected, const char *path) +static void assert_resolve_relative( + git_buf *buf, const char *expected, const char *path) { cl_git_pass(git_buf_sets(buf, path)); cl_git_pass(git_path_resolve_relative(buf, 0)); -- cgit v1.2.1 From cae529385437a24094ef2997dbf546723f7fd1ee Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 3 Sep 2013 14:00:27 -0700 Subject: Fix resolving relative windows network paths --- src/path.c | 4 ++-- tests-clar/core/path.c | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/path.c b/src/path.c index 50a990b27..7c1ec2cd0 100644 --- a/src/path.c +++ b/src/path.c @@ -242,8 +242,8 @@ int git_path_root(const char *path) #ifdef GIT_WIN32 /* Are we dealing with a windows network path? */ - else if ((path[0] == '/' && path[1] == '/') || - (path[0] == '\\' && path[1] == '\\')) + else if ((path[0] == '/' && path[1] == '/' && path[2] != '/') || + (path[0] == '\\' && path[1] == '\\' && path[2] != '\\')) { offset += 2; diff --git a/tests-clar/core/path.c b/tests-clar/core/path.c index 300600115..e584d6115 100644 --- a/tests-clar/core/path.c +++ b/tests-clar/core/path.c @@ -538,7 +538,6 @@ void test_core_path__15_resolve_relative(void) assert_resolve_relative(&buf, "a/b/", "a/b/."); assert_resolve_relative(&buf, "/a/b/c", "///a/b/c"); - assert_resolve_relative(&buf, "/a/b/c", "//a/b/c"); assert_resolve_relative(&buf, "/", "////"); assert_resolve_relative(&buf, "/a", "///a"); assert_resolve_relative(&buf, "/", "///."); @@ -565,5 +564,20 @@ void test_core_path__15_resolve_relative(void) cl_git_pass(git_buf_sets(&buf, "////..")); cl_git_fail(git_path_resolve_relative(&buf, 0)); + /* things that start with Windows network paths */ +#ifdef GIT_WIN32 + assert_resolve_relative(&buf, "//a/b/c", "//a/b/c"); + assert_resolve_relative(&buf, "//a/", "//a/b/.."); + assert_resolve_relative(&buf, "//a/b/c", "//a/Q/../b/x/y/../../c"); + + cl_git_pass(git_buf_sets(&buf, "//a/b/../..")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); +#else + assert_resolve_relative(&buf, "/a/b/c", "//a/b/c"); + assert_resolve_relative(&buf, "/a/", "//a/b/.."); + assert_resolve_relative(&buf, "/a/b/c", "//a/Q/../b/x/y/../../c"); + assert_resolve_relative(&buf, "/", "//a/b/../.."); +#endif + git_buf_free(&buf); } -- cgit v1.2.1 From 60ee53dfce5ff0201e6f519c653cf0de195ff35b Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 3 Sep 2013 15:14:04 -0700 Subject: Split examples CMakeLists.txt Also, this converts the examples/CMakeLists.txt from explicitly listing to just globbing for all the individual C files. --- CMakeLists.txt | 35 +---------------------------------- examples/CMakeLists.txt | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 34 deletions(-) create mode 100644 examples/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 78c25b101..5c09b4178 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -409,38 +409,5 @@ IF (TAGS) ENDIF () IF (BUILD_EXAMPLES) - FILE(GLOB_RECURSE EXAMPLE_SRC examples/network/*.c examples/network/*.h) - ADD_EXECUTABLE(cgit2 ${EXAMPLE_SRC}) - IF(WIN32 OR ANDROID) - TARGET_LINK_LIBRARIES(cgit2 git2) - ELSE() - TARGET_LINK_LIBRARIES(cgit2 git2 pthread) - ENDIF() - - ADD_EXECUTABLE(git-diff examples/diff.c) - TARGET_LINK_LIBRARIES(git-diff git2) - - ADD_EXECUTABLE(git-general examples/general.c) - TARGET_LINK_LIBRARIES(git-general git2) - - ADD_EXECUTABLE(git-showindex examples/showindex.c) - TARGET_LINK_LIBRARIES(git-showindex git2) - - ADD_EXECUTABLE(git-rev-list examples/rev-list.c) - TARGET_LINK_LIBRARIES(git-rev-list git2) - - ADD_EXECUTABLE(git-rev-parse examples/rev-parse.c) - TARGET_LINK_LIBRARIES(git-rev-parse git2) - - ADD_EXECUTABLE(git-log examples/log.c) - TARGET_LINK_LIBRARIES(git-log git2) - - ADD_EXECUTABLE(git-status examples/status.c) - TARGET_LINK_LIBRARIES(git-status git2) - - ADD_EXECUTABLE(git-init examples/init.c) - TARGET_LINK_LIBRARIES(git-init git2) - - ADD_EXECUTABLE(git-cat-file examples/cat-file.c) - TARGET_LINK_LIBRARIES(git-cat-file git2) + ADD_SUBDIRECTORY(examples) ENDIF () diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 000000000..c20a6df3b --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,14 @@ +FILE(GLOB_RECURSE SRC_EXAMPLE_GIT2 network/*.c network/*.h) +ADD_EXECUTABLE(cgit2 ${SRC_EXAMPLE_GIT2}) +IF(WIN32 OR ANDROID) + TARGET_LINK_LIBRARIES(cgit2 git2) +ELSE() + TARGET_LINK_LIBRARIES(cgit2 git2 pthread) +ENDIF() + +FILE(GLOB SRC_EXAMPLE_APPS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.c) +FOREACH(src_app ${SRC_EXAMPLE_APPS}) + STRING(REPLACE ".c" "" app_name ${src_app}) + ADD_EXECUTABLE(${app_name} ${src_app}) + TARGET_LINK_LIBRARIES(${app_name} git2) +ENDFOREACH() -- cgit v1.2.1 From b1a6c316a6070fac4ab1ec5792979838f7145c39 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Fri, 30 Aug 2013 17:36:00 +0200 Subject: odb: Move the auto refresh logic to the pack backend Previously, `git_object_read()`, `git_object_read_prefix()` and `git_object_exists()` were implementing an auto refresh logic. When the expected object couldn't be found in any backend, a call to `git_odb_refresh()` was triggered and the lookup was once again performed against all backends. This commit removes this auto-refresh logic from the odb layer and pushes it down into the pack-backend (as it's the only one currently exposing a `refresh()` endpoint). --- include/git2/sys/odb_backend.h | 10 ++++++ src/odb.c | 39 +++------------------- src/odb_pack.c | 76 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 38 deletions(-) diff --git a/include/git2/sys/odb_backend.h b/include/git2/sys/odb_backend.h index 31ffe1c33..4365906d4 100644 --- a/include/git2/sys/odb_backend.h +++ b/include/git2/sys/odb_backend.h @@ -64,6 +64,16 @@ struct git_odb_backend { int (* exists)( git_odb_backend *, const git_oid *); + /** + * If the backend implements a refreshing mechanism, it should be exposed + * through this endpoint. Each call to `git_odb_refresh()` will invoke it. + * + * However, the backend implementation should try to stay up-to-date as much + * as possible by itself as libgit2 will not automatically invoke + * `git_odb_refresh()`. For instance, a potential strategy for the backend + * implementation to achieve this could be to internally invoke this + * endpoint on failed lookups (ie. `exists()`, `read()`, `read_header()`). + */ int (* refresh)(git_odb_backend *); int (* foreach)( diff --git a/src/odb.c b/src/odb.c index 9785c74da..e47715f79 100644 --- a/src/odb.c +++ b/src/odb.c @@ -608,7 +608,6 @@ int git_odb_exists(git_odb *db, const git_oid *id) git_odb_object *object; size_t i; bool found = false; - bool refreshed = false; assert(db && id); @@ -617,25 +616,14 @@ int git_odb_exists(git_odb *db, const git_oid *id) return (int)true; } -attempt_lookup: for (i = 0; i < db->backends.length && !found; ++i) { backend_internal *internal = git_vector_get(&db->backends, i); git_odb_backend *b = internal->backend; - if (b->exists != NULL && (!refreshed || b->refresh)) + if (b->exists != NULL) found = b->exists(b, id); } - if (!found && !refreshed) { - if (git_odb_refresh(db) < 0) { - giterr_clear(); - return (int)false; - } - - refreshed = true; - goto attempt_lookup; - } - return (int)found; } @@ -700,7 +688,6 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id) { size_t i, reads = 0; int error; - bool refreshed = false; git_rawobj raw; git_odb_object *object; @@ -710,27 +697,18 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id) if (*out != NULL) return 0; -attempt_lookup: error = GIT_ENOTFOUND; for (i = 0; i < db->backends.length && error < 0; ++i) { backend_internal *internal = git_vector_get(&db->backends, i); git_odb_backend *b = internal->backend; - if (b->read != NULL && (!refreshed || b->refresh)) { + if (b->read != NULL) { ++reads; error = b->read(&raw.data, &raw.len, &raw.type, b, id); } } - if (error == GIT_ENOTFOUND && !refreshed) { - if ((error = git_odb_refresh(db)) < 0) - return error; - - refreshed = true; - goto attempt_lookup; - } - if (error && error != GIT_PASSTHROUGH) { if (!reads) return git_odb__error_notfound("no match for id", id); @@ -752,7 +730,7 @@ int git_odb_read_prefix( git_oid found_full_oid = {{0}}; git_rawobj raw; void *data = NULL; - bool found = false, refreshed = false; + bool found = false; git_odb_object *object; assert(out && db); @@ -769,12 +747,11 @@ int git_odb_read_prefix( return 0; } -attempt_lookup: for (i = 0; i < db->backends.length; ++i) { backend_internal *internal = git_vector_get(&db->backends, i); git_odb_backend *b = internal->backend; - if (b->read_prefix != NULL && (!refreshed || b->refresh)) { + if (b->read_prefix != NULL) { git_oid full_oid; error = b->read_prefix(&full_oid, &raw.data, &raw.len, &raw.type, b, short_id, len); if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH) @@ -796,14 +773,6 @@ attempt_lookup: } } - if (!found && !refreshed) { - if ((error = git_odb_refresh(db)) < 0) - return error; - - refreshed = true; - goto attempt_lookup; - } - if (!found) return git_odb__error_notfound("no match for prefix", short_id); diff --git a/src/odb_pack.c b/src/odb_pack.c index d7abd1020..d24b4aa99 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -342,7 +342,7 @@ static int pack_backend__refresh(git_odb_backend *_backend) return 0; } -static int pack_backend__read_header( +static int pack_backend__read_header_internal( size_t *len_p, git_otype *type_p, struct git_odb_backend *backend, const git_oid *oid) { @@ -357,7 +357,24 @@ static int pack_backend__read_header( return git_packfile_resolve_header(len_p, type_p, e.p, e.offset); } -static int pack_backend__read( +static int pack_backend__read_header( + size_t *len_p, git_otype *type_p, + struct git_odb_backend *backend, const git_oid *oid) +{ + int error; + + error = pack_backend__read_header_internal(len_p, type_p, backend, oid); + + if (error != GIT_ENOTFOUND) + return error; + + if ((error = pack_backend__refresh(backend)) < 0) + return error; + + return pack_backend__read_header_internal(len_p, type_p, backend, oid); +} + +static int pack_backend__read_internal( void **buffer_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid) { @@ -376,7 +393,24 @@ static int pack_backend__read( return 0; } -static int pack_backend__read_prefix( +static int pack_backend__read( + void **buffer_p, size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *oid) +{ + int error; + + error = pack_backend__read_internal(buffer_p, len_p, type_p, backend, oid); + + if (error != GIT_ENOTFOUND) + return error; + + if ((error = pack_backend__refresh(backend)) < 0) + return error; + + return pack_backend__read_internal(buffer_p, len_p, type_p, backend, oid); +} + +static int pack_backend__read_prefix_internal( git_oid *out_oid, void **buffer_p, size_t *len_p, @@ -413,9 +447,45 @@ static int pack_backend__read_prefix( return error; } +static int pack_backend__read_prefix( + git_oid *out_oid, + void **buffer_p, + size_t *len_p, + git_otype *type_p, + git_odb_backend *backend, + const git_oid *short_oid, + size_t len) +{ + int error; + + error = pack_backend__read_prefix_internal( + out_oid, buffer_p, len_p, type_p, backend, short_oid, len); + + if (error != GIT_ENOTFOUND) + return error; + + if ((error = pack_backend__refresh(backend)) < 0) + return error; + + return pack_backend__read_prefix_internal( + out_oid, buffer_p, len_p, type_p, backend, short_oid, len); +} + static int pack_backend__exists(git_odb_backend *backend, const git_oid *oid) { struct git_pack_entry e; + int error; + + error = pack_entry_find(&e, (struct pack_backend *)backend, oid); + + if (error != GIT_ENOTFOUND) + return error == 0; + + if ((error = pack_backend__refresh(backend)) < 0) { + giterr_clear(); + return (int)false; + } + return pack_entry_find(&e, (struct pack_backend *)backend, oid) == 0; } -- cgit v1.2.1 From 74b38d199ebe74c25180e0baf4bf945c97cd3daf Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 4 Sep 2013 13:16:57 +0200 Subject: Backport @peff's fix for duplicates in sha1_lookup --- src/sha1_lookup.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/sha1_lookup.c b/src/sha1_lookup.c index cdcadfaa9..c6b561340 100644 --- a/src/sha1_lookup.c +++ b/src/sha1_lookup.c @@ -109,7 +109,54 @@ int sha1_entry_pos(const void *table, * byte 0 thru (ofs-1) are the same between * lo and hi; ofs is the first byte that is * different. + * + * If ofs==20, then no bytes are different, + * meaning we have entries with duplicate + * keys. We know that we are in a solid run + * of this entry (because the entries are + * sorted, and our lo and hi are the same, + * there can be nothing but this single key + * in between). So we can stop the search. + * Either one of these entries is it (and + * we do not care which), or we do not have + * it. + * + * Furthermore, we know that one of our + * endpoints must be the edge of the run of + * duplicates. For example, given this + * sequence: + * + * idx 0 1 2 3 4 5 + * key A C C C C D + * + * If we are searching for "B", we might + * hit the duplicate run at lo=1, hi=3 + * (e.g., by first mi=3, then mi=0). But we + * can never have lo > 1, because B < C. + * That is, if our key is less than the + * run, we know that "lo" is the edge, but + * we can say nothing of "hi". Similarly, + * if our key is greater than the run, we + * know that "hi" is the edge, but we can + * say nothing of "lo". + * + * Therefore if we do not find it, we also + * know where it would go if it did exist: + * just on the far side of the edge that we + * know about. */ + if (ofs == 20) { + mi = lo; + mi_key = base + elem_size * mi + key_offset; + cmp = memcmp(mi_key, key, 20); + if (!cmp) + return mi; + if (cmp < 0) + return -1 - hi; + else + return -1 - lo; + } + hiv = hi_key[ofs_0]; if (ofs_0 < 19) hiv = (hiv << 8) | hi_key[ofs_0+1]; -- cgit v1.2.1 From f42d546c632d0458503efd01390bac76c185ebef Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 4 Sep 2013 13:07:42 -0700 Subject: Provide better errors for push on non-bare local remotes --- src/transports/local.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/transports/local.c b/src/transports/local.c index 8a75de727..9ebea979c 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -361,7 +361,8 @@ static int local_push( non-bare repo push support would require checking configs to see if we should override the default 'don't let this happen' behavior */ if (!remote_repo->is_bare) { - error = -1; + error = GIT_EBAREREPO; + giterr_set(GITERR_INVALID, "Local push doesn't (yet) support pushing to non-bare repos."); goto on_error; } -- cgit v1.2.1 From 61d57b7a21b2ac5ca7a763a1b768481926f56014 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 4 Sep 2013 14:27:59 -0700 Subject: Test pushing to remotes with "file:///" urls --- tests-clar/network/remote/local.c | 71 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/tests-clar/network/remote/local.c b/tests-clar/network/remote/local.c index d5d75fdc6..79eb73c5a 100644 --- a/tests-clar/network/remote/local.c +++ b/tests-clar/network/remote/local.c @@ -52,7 +52,6 @@ static void connect_to_local_repository(const char *local_repository) cl_git_pass(git_remote_create_inmemory(&remote, repo, NULL, git_buf_cstr(&file_path_buf))); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - } void test_network_remote_local__connected(void) @@ -170,3 +169,73 @@ void test_network_remote_local__tagopt(void) cl_git_pass(git_reference_lookup(&ref, repo, "refs/tags/hard_tag")); git_reference_free(ref); } + +void test_network_remote_local__push_to_bare_remote(void) +{ + /* Should be able to push to a bare remote */ + git_remote *localremote; + git_push *push; + + /* Get some commits */ + connect_to_local_repository(cl_fixture("testrepo.git")); + cl_git_pass(git_remote_add_fetch(remote, "master:master")); + cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_update_tips(remote)); + git_remote_disconnect(remote); + + /* Set up an empty bare repo to push into */ + { + git_repository *localbarerepo; + cl_git_pass(git_repository_init(&localbarerepo, "./localbare.git", 1)); + git_repository_free(localbarerepo); + } + + /* Connect to the bare repo */ + cl_git_pass(git_remote_create_inmemory(&localremote, repo, NULL, "./localbare.git")); + cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH)); + + /* Try to push */ + cl_git_pass(git_push_new(&push, localremote)); + cl_git_pass(git_push_add_refspec(push, "refs/heads/master:")); + cl_git_pass(git_push_finish(push)); + cl_assert(git_push_unpack_ok(push)); + + /* Clean up */ + git_remote_free(localremote); + cl_fixture_cleanup("localbare.git"); +} + +void test_network_remote_local__push_to_non_bare_remote(void) +{ + /* Shouldn't be able to push to a non-bare remote */ + git_remote *localremote; + git_push *push; + + /* Get some commits */ + connect_to_local_repository(cl_fixture("testrepo.git")); + cl_git_pass(git_remote_add_fetch(remote, "master:master")); + cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_update_tips(remote)); + git_remote_disconnect(remote); + + /* Set up an empty non-bare repo to push into */ + { + git_repository *remoterepo = NULL; + cl_git_pass(git_repository_init(&remoterepo, "localnonbare", 0)); + git_repository_free(remoterepo); + } + + /* Connect to the bare repo */ + cl_git_pass(git_remote_create_inmemory(&localremote, repo, NULL, "./localnonbare")); + cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH)); + + /* Try to push */ + cl_git_pass(git_push_new(&push, localremote)); + cl_git_pass(git_push_add_refspec(push, "refs/heads/master:")); + cl_git_fail_with(git_push_finish(push), GIT_EBAREREPO); + cl_assert_equal_i(0, git_push_unpack_ok(push)); + + /* Clean up */ + git_remote_free(localremote); + cl_fixture_cleanup("localbare.git"); +} -- cgit v1.2.1 From cf94024c589591e9a5c46a71f8fdce9f8b467161 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 4 Sep 2013 11:42:48 -0700 Subject: Update clar --- tests-clar/checkout/checkout_helpers.c | 4 +- tests-clar/clar.c | 138 +++++++++++++++++++++++---------- tests-clar/clar.h | 23 ++++-- tests-clar/clar/sandbox.h | 6 +- tests-clar/diff/submodules.c | 5 +- 5 files changed, 117 insertions(+), 59 deletions(-) diff --git a/tests-clar/checkout/checkout_helpers.c b/tests-clar/checkout/checkout_helpers.c index 8da024dda..f55f7b611 100644 --- a/tests-clar/checkout/checkout_helpers.c +++ b/tests-clar/checkout/checkout_helpers.c @@ -74,8 +74,8 @@ static void check_file_contents_internal( if (strip_cr) strip_cr_from_buf(&buf); - clar__assert_equal_i((int)expected_len, (int)buf.size, file, line, "strlen(expected_content) != strlen(actual_content)", 1); - clar__assert_equal_s(expected_content, buf.ptr, file, line, msg, 1); + clar__assert_equal(file, line, "strlen(expected_content) != strlen(actual_content)", 1, PRIuZ, expected_len, (size_t)buf.size); + clar__assert_equal(file, line, msg, 1, "%s", expected_content, buf.ptr); } void check_file_contents_at_line( diff --git a/tests-clar/clar.c b/tests-clar/clar.c index 585af8a74..5189e7919 100644 --- a/tests-clar/clar.c +++ b/tests-clar/clar.c @@ -24,28 +24,59 @@ # define _MAIN_CC __cdecl -# define stat(path, st) _stat(path, st) -# define mkdir(path, mode) _mkdir(path) -# define chdir(path) _chdir(path) -# define access(path, mode) _access(path, mode) -# define strdup(str) _strdup(str) -# define strcasecmp(a,b) _stricmp(a,b) +# ifndef stat +# define stat(path, st) _stat(path, st) +# endif +# ifndef mkdir +# define mkdir(path, mode) _mkdir(path) +# endif +# ifndef chdir +# define chdir(path) _chdir(path) +# endif +# ifndef access +# define access(path, mode) _access(path, mode) +# endif +# ifndef strdup +# define strdup(str) _strdup(str) +# endif +# ifndef strcasecmp +# define strcasecmp(a,b) _stricmp(a,b) +# endif # ifndef __MINGW32__ # pragma comment(lib, "shell32") -# define strncpy(to, from, to_size) strncpy_s(to, to_size, from, _TRUNCATE) -# define W_OK 02 -# define S_ISDIR(x) ((x & _S_IFDIR) != 0) -# define snprint_eq(buf,sz,fmt,...) _snprintf_s(buf,sz,_TRUNCATE,fmt,__VA_ARGS__) +# ifndef strncpy +# define strncpy(to, from, to_size) strncpy_s(to, to_size, from, _TRUNCATE) +# endif +# ifndef W_OK +# define W_OK 02 +# endif +# ifndef S_ISDIR +# define S_ISDIR(x) ((x & _S_IFDIR) != 0) +# endif +# define p_snprintf(buf,sz,fmt,...) _snprintf_s(buf,sz,_TRUNCATE,fmt,__VA_ARGS__) # else -# define snprint_eq snprintf +# define p_snprintf snprintf +# endif + +# ifndef PRIuZ +# define PRIuZ "Iu" +# endif +# ifndef PRIxZ +# define PRIxZ "Ix" # endif typedef struct _stat STAT_T; #else # include /* waitpid(2) */ # include # define _MAIN_CC -# define snprint_eq snprintf +# define p_snprintf snprintf +# ifndef PRIuZ +# define PRIuZ "zu" +# endif +# ifndef PRIxZ +# define PRIxZ "zx" +# endif typedef struct stat STAT_T; #endif @@ -406,45 +437,66 @@ void clar__assert( clar__fail(file, line, error_msg, description, should_abort); } -void clar__assert_equal_s( - const char *s1, - const char *s2, +void clar__assert_equal( const char *file, int line, const char *err, - int should_abort) + int should_abort, + const char *fmt, + ...) { - int match = (s1 == NULL || s2 == NULL) ? (s1 == s2) : (strcmp(s1, s2) == 0); - - if (!match) { - char buf[4096]; - - if (s1 && s2) { - int pos; - for (pos = 0; s1[pos] == s2[pos] && s1[pos] && s2[pos]; ++pos) - /* find differing byte offset */; - snprint_eq(buf, sizeof(buf), "'%s' != '%s' (at byte %d)", s1, s2, pos); - } else { - snprint_eq(buf, sizeof(buf), "'%s' != '%s'", s1, s2); + va_list args; + char buf[4096]; + int is_equal = 1; + + va_start(args, fmt); + + if (!strcmp("%s", fmt)) { + const char *s1 = va_arg(args, const char *); + const char *s2 = va_arg(args, const char *); + is_equal = (!s1 || !s2) ? (s1 == s2) : !strcmp(s1, s2); + + if (!is_equal) { + if (s1 && s2) { + int pos; + for (pos = 0; s1[pos] == s2[pos] && s1[pos] && s2[pos]; ++pos) + /* find differing byte offset */; + p_snprintf(buf, sizeof(buf), "'%s' != '%s' (at byte %d)", + s1, s2, pos); + } else { + p_snprintf(buf, sizeof(buf), "'%s' != '%s'", s1, s2); + } + } + } + else if (!strcmp(PRIuZ, fmt) || !strcmp(PRIxZ, fmt)) { + size_t sz1 = va_arg(args, size_t), sz2 = va_arg(args, size_t); + is_equal = (sz1 == sz2); + if (!is_equal) { + int offset = p_snprintf(buf, sizeof(buf), fmt, sz1); + strncat(buf, " != ", sizeof(buf) - offset); + p_snprintf(buf + offset + 4, sizeof(buf) - offset - 4, fmt, sz2); + } + } + else if (!strcmp("%p", fmt)) { + void *p1 = va_arg(args, void *), *p2 = va_arg(args, void *); + is_equal = (p1 == p2); + if (!is_equal) + p_snprintf(buf, sizeof(buf), "%p != %p", p1, p2); + } + else { + int i1 = va_arg(args, int), i2 = va_arg(args, int); + is_equal = (i1 == i2); + if (!is_equal) { + int offset = p_snprintf(buf, sizeof(buf), fmt, i1); + strncat(buf, " != ", sizeof(buf) - offset); + p_snprintf(buf + offset + 4, sizeof(buf) - offset - 4, fmt, i2); } - - clar__fail(file, line, err, buf, should_abort); } -} -void clar__assert_equal_i( - int i1, - int i2, - const char *file, - int line, - const char *err, - int should_abort) -{ - if (i1 != i2) { - char buf[128]; - snprint_eq(buf, sizeof(buf), "%d != %d", i1, i2); + va_end(args); + + if (!is_equal) clar__fail(file, line, err, buf, should_abort); - } } void cl_set_cleanup(void (*cleanup)(void *), void *opaque) diff --git a/tests-clar/clar.h b/tests-clar/clar.h index d92318bd4..e1f244eba 100644 --- a/tests-clar/clar.h +++ b/tests-clar/clar.h @@ -57,15 +57,17 @@ void cl_fixture_cleanup(const char *fixture_name); /** * Typed assertion macros */ -#define cl_assert_equal_s(s1,s2) clar__assert_equal_s((s1),(s2),__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2, 1) -#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal_s((s1),(s2),__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1) +#define cl_assert_equal_s(s1,s2) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2)) +#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2)) -#define cl_assert_equal_i(i1,i2) clar__assert_equal_i((i1),(i2),__FILE__,__LINE__,#i1 " != " #i2, 1) -#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal_i((i1),(i2),__FILE__,__LINE__,#i1 " != " #i2 " (" #note ")", 1) +#define cl_assert_equal_i(i1,i2) clar__assert_equal(__FILE__,__LINE__,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2)) +#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(__FILE__,__LINE__,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2)) +#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(__FILE__,__LINE__,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2)) -#define cl_assert_equal_b(b1,b2) clar__assert_equal_i(!!(b1),!!(b2),__FILE__,__LINE__,#b1 " != " #b2, 1) +#define cl_assert_equal_b(b1,b2) clar__assert_equal(__FILE__,__LINE__,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0)) + +#define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2)) -#define cl_assert_equal_p(p1,p2) cl_assert((p1) == (p2)) void clar__fail( const char *file, @@ -82,7 +84,12 @@ void clar__assert( const char *description, int should_abort); -void clar__assert_equal_s(const char *,const char *,const char *,int,const char *,int); -void clar__assert_equal_i(int,int,const char *,int,const char *,int); +void clar__assert_equal( + const char *file, + int line, + const char *err, + int should_abort, + const char *fmt, + ...); #endif diff --git a/tests-clar/clar/sandbox.h b/tests-clar/clar/sandbox.h index 1ca6fcae8..ee7564148 100644 --- a/tests-clar/clar/sandbox.h +++ b/tests-clar/clar/sandbox.h @@ -43,10 +43,8 @@ find_tmp_path(char *buffer, size_t length) } #else - DWORD env_len; - - if ((env_len = GetEnvironmentVariable("CLAR_TMP", buffer, length)) > 0 && - env_len < length) + DWORD env_len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length); + if (env_len > 0 && env_len < (DWORD)length) return 0; if (GetTempPath((DWORD)length, buffer)) diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index 94804db22..9dcf8194e 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -39,8 +39,9 @@ static void check_diff_patches_at_line( cl_git_pass(git_diff_patch_to_str(&patch_text, patch)); - clar__assert_equal_s(expected[d], patch_text, file, line, - "expected diff did not match actual diff", 1); + clar__assert_equal( + file, line, "expected diff did not match actual diff", 1, + "%s", expected[d], patch_text); git__free(patch_text); } -- cgit v1.2.1 From 780f3e540fa6492b244ef2750a71e39407526c1e Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 4 Sep 2013 16:13:18 -0700 Subject: Make tests take umask into account It seems that libgit2 is correctly applying the umask when initializing a repository from a template and when creating new directories during checkout, but the test suite is not accounting for possible variations due to the umask. This updates that so that the test suite will work regardless of the umask. --- tests-clar/checkout/index.c | 10 +++++++--- tests-clar/clar_libgit2.h | 2 +- tests-clar/repo/init.c | 15 +++++++++++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/tests-clar/checkout/index.c b/tests-clar/checkout/index.c index 982bf9ee5..a185aec44 100644 --- a/tests-clar/checkout/index.c +++ b/tests-clar/checkout/index.c @@ -229,6 +229,7 @@ void test_checkout_index__options_dir_modes(void) struct stat st; git_oid oid; git_commit *commit; + mode_t um; cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); @@ -240,12 +241,15 @@ void test_checkout_index__options_dir_modes(void) cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + /* umask will influence actual directory creation mode */ + (void)p_umask(um = p_umask(022)); + cl_git_pass(p_stat("./testrepo/a", &st)); - cl_assert_equal_i(st.st_mode & 0777, 0701); + cl_assert_equal_i_fmt(st.st_mode, GIT_FILEMODE_TREE | 0701 & ~um, "%07o"); /* File-mode test, since we're on the 'dir' branch */ cl_git_pass(p_stat("./testrepo/a/b.txt", &st)); - cl_assert_equal_i(st.st_mode & 0777, 0755); + cl_assert_equal_i_fmt(st.st_mode, GIT_FILEMODE_BLOB_EXECUTABLE, "%07o"); git_commit_free(commit); #endif @@ -263,7 +267,7 @@ void test_checkout_index__options_override_file_modes(void) cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); cl_git_pass(p_stat("./testrepo/new.txt", &st)); - cl_assert_equal_i(st.st_mode & 0777, 0700); + cl_assert_equal_i_fmt(st.st_mode & 0777, 0700, "%07o"); #endif } diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index 8c8357e40..080d32bea 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -32,7 +32,7 @@ void cl_git_report_failure(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) -#define cl_assert_equal_sz(sz1,sz2) cl_assert_equal_i((int)sz1, (int)(sz2)) +#define cl_assert_equal_sz(sz1,sz2) clar__assert_equal(__FILE__,__LINE__,#sz1 " != " #sz2, 1, PRIuZ, (size_t)(sz1), (size_t)(sz2)) GIT_INLINE(void) clar__assert_in_range( int lo, int val, int hi, diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index 5076184b8..4d93f3d0e 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -10,10 +10,17 @@ enum repo_mode { }; static git_repository *_repo = NULL; +static mode_t _umask = 0; void test_repo_init__initialize(void) { _repo = NULL; + + /* load umask if not already loaded */ + if (!_umask) { + _umask = p_umask(022); + (void)p_umask(_umask); + } } static void cleanup_repository(void *path) @@ -377,14 +384,18 @@ static void assert_hooks_match( cl_git_pass(git_buf_joinpath(&actual, repo_dir, hook_path)); cl_git_pass(git_path_lstat(actual.ptr, &st)); - cl_assert(expected_st.st_size == st.st_size); + cl_assert_equal_sz(expected_st.st_size, st.st_size); + + expected_st.st_mode = + (expected_st.st_mode & ~0777) | + (((expected_st.st_mode & 0111) ? 0100777 : 0100666) & ~_umask); if (!core_filemode) { expected_st.st_mode = expected_st.st_mode & ~0111; st.st_mode = st.st_mode & ~0111; } - cl_assert_equal_i((int)expected_st.st_mode, (int)st.st_mode); + cl_assert_equal_i_fmt(expected_st.st_mode, st.st_mode, "%07o"); git_buf_free(&expected); git_buf_free(&actual); -- cgit v1.2.1 From abfed59c2797e9436f2b20fadecd982d6637dc22 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 4 Sep 2013 16:21:18 -0700 Subject: Clean up one other mode_t assertion --- tests-clar/core/mkdir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests-clar/core/mkdir.c b/tests-clar/core/mkdir.c index 1e50b4336..a969e4de2 100644 --- a/tests-clar/core/mkdir.c +++ b/tests-clar/core/mkdir.c @@ -115,9 +115,9 @@ static void check_mode(mode_t expected, mode_t actual) { #ifdef GIT_WIN32 /* chmod on Win32 doesn't support exec bit, not group/world bits */ - cl_assert((expected & 0600) == (actual & 0777)); + cl_assert_equal_i_fmt((expected & 0600), (actual & 0777), "%07o"); #else - cl_assert(expected == (actual & 0777)); + cl_assert_equal_i_fmt(expected, (actual & 0777), "%07o"); #endif } -- cgit v1.2.1 From 2a54c7f447acfc74368a766369a9923ecdf19b21 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 4 Sep 2013 16:24:36 -0700 Subject: _umask is function name on Windows --- tests-clar/repo/init.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index 4d93f3d0e..aeb35d3b4 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -10,16 +10,16 @@ enum repo_mode { }; static git_repository *_repo = NULL; -static mode_t _umask = 0; +static mode_t g_umask = 0; void test_repo_init__initialize(void) { _repo = NULL; /* load umask if not already loaded */ - if (!_umask) { - _umask = p_umask(022); - (void)p_umask(_umask); + if (!g_umask) { + g_umask = p_umask(022); + (void)p_umask(g_umask); } } @@ -388,7 +388,7 @@ static void assert_hooks_match( expected_st.st_mode = (expected_st.st_mode & ~0777) | - (((expected_st.st_mode & 0111) ? 0100777 : 0100666) & ~_umask); + (((expected_st.st_mode & 0111) ? 0100777 : 0100666) & ~g_umask); if (!core_filemode) { expected_st.st_mode = expected_st.st_mode & ~0111; -- cgit v1.2.1 From 9ce4f7da4a69b3853da587b67e8f137ddf036e4c Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 4 Sep 2013 16:41:34 -0700 Subject: Fix tests to use core.filemode correctly Some windows tests were failing --- tests-clar/clar_libgit2.c | 10 ++++++++++ tests-clar/clar_libgit2.h | 1 + tests-clar/repo/init.c | 22 +++++++++------------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index bf35a68eb..340943ca8 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -344,3 +344,13 @@ void cl_repo_set_bool(git_repository *repo, const char *cfg, int value) cl_git_pass(git_config_set_bool(config, cfg, value != 0)); git_config_free(config); } + +int cl_repo_get_bool(git_repository *repo, const char *cfg) +{ + int val = 0; + git_config *config; + cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_config_get_bool(&val, config, cfg));; + git_config_free(config); + return val; +} diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index 080d32bea..3cb0607f1 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -88,5 +88,6 @@ int cl_git_remove_placeholders(const char *directory_path, const char *filename) /* config setting helpers */ void cl_repo_set_bool(git_repository *repo, const char *cfg, int value); +int cl_repo_get_bool(git_repository *repo, const char *cfg); #endif diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index aeb35d3b4..62e4ecd59 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -270,7 +270,6 @@ void test_repo_init__reinit_doesnot_overwrite_ignorecase(void) void test_repo_init__reinit_overwrites_filemode(void) { - git_config *config; int expected, current_value; #ifdef GIT_WIN32 @@ -291,13 +290,10 @@ void test_repo_init__reinit_overwrites_filemode(void) /* Reinit the repository */ cl_git_pass(git_repository_init(&_repo, "overwrite.git", 1)); - git_repository_config(&config, _repo); /* Ensure the "core.filemode" config value has been reset */ - cl_git_pass(git_config_get_bool(¤t_value, config, "core.filemode")); + current_value = cl_repo_get_bool(_repo, "core.filemode"); cl_assert_equal_i(expected, current_value); - - git_config_free(config); } void test_repo_init__sets_logAllRefUpdates_according_to_type_of_repository(void) @@ -391,8 +387,8 @@ static void assert_hooks_match( (((expected_st.st_mode & 0111) ? 0100777 : 0100666) & ~g_umask); if (!core_filemode) { - expected_st.st_mode = expected_st.st_mode & ~0111; - st.st_mode = st.st_mode & ~0111; + expected_st.st_mode = expected_st.st_mode & ~0177; + st.st_mode = st.st_mode & ~0177; } cl_assert_equal_i_fmt(expected_st.st_mode, st.st_mode, "%07o"); @@ -438,6 +434,7 @@ void test_repo_init__extended_with_template(void) git_buf expected = GIT_BUF_INIT; git_buf actual = GIT_BUF_INIT; git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + int filemode; cl_set_cleanup(&cleanup_repository, "templated.git"); @@ -461,13 +458,15 @@ void test_repo_init__extended_with_template(void) git_buf_free(&expected); git_buf_free(&actual); + filemode = cl_repo_get_bool(_repo, "core.filemode"); + assert_hooks_match( cl_fixture("template"), git_repository_path(_repo), - "hooks/update.sample", true); + "hooks/update.sample", filemode); assert_hooks_match( cl_fixture("template"), git_repository_path(_repo), - "hooks/link.sample", true); + "hooks/link.sample", filemode); } void test_repo_init__extended_with_template_and_shared_mode(void) @@ -475,7 +474,6 @@ void test_repo_init__extended_with_template_and_shared_mode(void) git_buf expected = GIT_BUF_INIT; git_buf actual = GIT_BUF_INIT; git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; - git_config *config; int filemode = true; const char *repo_path = NULL; @@ -491,9 +489,7 @@ void test_repo_init__extended_with_template_and_shared_mode(void) cl_assert(!git_repository_is_bare(_repo)); cl_assert(!git__suffixcmp(git_repository_path(_repo), "/init_shared_from_tpl/.git/")); - cl_git_pass(git_repository_config(&config, _repo)); - cl_git_pass(git_config_get_bool(&filemode, config, "core.filemode")); - git_config_free(config); + filemode = cl_repo_get_bool(_repo, "core.filemode"); cl_git_pass(git_futils_readbuffer( &expected, cl_fixture("template/description"))); -- cgit v1.2.1 From 21753d48691c41fbedc0c074d8b0f278f3ba2f1d Mon Sep 17 00:00:00 2001 From: Linquize Date: Thu, 5 Sep 2013 20:42:47 +0800 Subject: Fix warning in src/win32/version.h --- src/win32/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32/version.h b/src/win32/version.h index 518b0a379..79667697f 100644 --- a/src/win32/version.h +++ b/src/win32/version.h @@ -18,7 +18,7 @@ GIT_INLINE(int) git_has_win32_version(int major, int minor, int service_pack) version_test.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); version_test.dwMajorVersion = major; version_test.dwMinorVersion = minor; - version_test.wServicePackMajor = service_pack; + version_test.wServicePackMajor = (WORD)service_pack; version_test.wServicePackMinor = 0; version_test_mask = (VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR); -- cgit v1.2.1 From d209cc47515d2feeaa30de20882ded5cb4039736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 5 Sep 2013 18:06:12 +0200 Subject: config: decouple the backend from the reader at the low level In order to support config includes, we must differentiate between the backend's main file and the file we are currently parsing. This lays the groundwork for includes, keeping the current behaviours. --- src/config_file.c | 180 +++++++++++++++++++++++++++++------------------------- 1 file changed, 96 insertions(+), 84 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index efc9df965..fa8aba061 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -25,6 +25,7 @@ GIT__USE_STRMAP; typedef struct cvar_t { struct cvar_t *next; git_config_entry *entry; + int included; /* whether this is part of [include] */ } cvar_t; typedef struct git_config_file_iter { @@ -72,17 +73,20 @@ typedef struct git_config_file_iter { (iter) && (((tmp) = CVAR_LIST_NEXT(iter) || 1));\ (iter) = (tmp)) +struct reader { + char *file_path; + git_buf buffer; + char *read_ptr; + int line_number; + int eof; +}; + typedef struct { git_config_backend parent; git_strmap *values; - struct { - git_buf buffer; - char *read_ptr; - int line_number; - int eof; - } reader; + struct reader reader; char *file_path; time_t file_mtime; @@ -91,15 +95,15 @@ typedef struct { git_config_level_t level; } diskfile_backend; -static int config_parse(diskfile_backend *cfg_file, git_config_level_t level); -static int parse_variable(diskfile_backend *cfg, char **var_name, char **var_value); +static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_config_level_t level, int depth); +static int parse_variable(struct reader *reader, char **var_name, char **var_value); static int config_write(diskfile_backend *cfg, const char *key, const regex_t *preg, const char *value); static char *escape_value(const char *ptr); -static void set_parse_error(diskfile_backend *backend, int col, const char *error_str) +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)", - error_str, backend->file_path, backend->reader.line_number, col); + error_str, reader->file_path, reader->line_number, col); } static void cvar_free(cvar_t *var) @@ -171,7 +175,7 @@ static int config_open(git_config_backend *cfg, git_config_level_t level) if (res == GIT_ENOTFOUND) return 0; - if (res < 0 || (res = config_parse(b, level)) < 0) { + if (res < 0 || (res = config_parse(b, &b->reader, level, 0)) < 0) { free_vars(b->values); b->values = NULL; } @@ -196,7 +200,7 @@ static int config_refresh(git_config_backend *cfg) b->values = git_strmap_alloc(); GITERR_CHECK_ALLOC(b->values); - if ((res = config_parse(b, b->level)) < 0) { + if ((res = config_parse(b, &b->reader, b->level, 0)) < 0) { free_vars(b->values); b->values = old_values; } else { @@ -214,6 +218,7 @@ static void backend_free(git_config_backend *_backend) if (backend == NULL) return; + git__free(backend->reader.file_path); git__free(backend->file_path); free_vars(backend->values); git__free(backend); @@ -501,6 +506,10 @@ int git_config_file__ondisk(git_config_backend **out, const char *path) backend->file_path = git__strdup(path); GITERR_CHECK_ALLOC(backend->file_path); + /* the reader needs its own copy */ + backend->reader.file_path = git__strdup(path); + GITERR_CHECK_ALLOC(backend->reader.file_path); + backend->parent.open = config_open; backend->parent.get = config_get; backend->parent.set = config_set; @@ -515,26 +524,26 @@ int git_config_file__ondisk(git_config_backend **out, const char *path) return 0; } -static int cfg_getchar_raw(diskfile_backend *cfg) +static int reader_getchar_raw(struct reader *reader) { int c; - c = *cfg->reader.read_ptr++; + c = *reader->read_ptr++; /* Win 32 line breaks: if we find a \r\n sequence, return only the \n as a newline */ - if (c == '\r' && *cfg->reader.read_ptr == '\n') { - cfg->reader.read_ptr++; + if (c == '\r' && *reader->read_ptr == '\n') { + reader->read_ptr++; c = '\n'; } if (c == '\n') - cfg->reader.line_number++; + reader->line_number++; if (c == 0) { - cfg->reader.eof = 1; + reader->eof = 1; c = '\n'; } @@ -544,21 +553,23 @@ static int cfg_getchar_raw(diskfile_backend *cfg) #define SKIP_WHITESPACE (1 << 1) #define SKIP_COMMENTS (1 << 2) -static int cfg_getchar(diskfile_backend *cfg_file, int flags) +static int reader_getchar(struct reader *reader, int flags) { const int skip_whitespace = (flags & SKIP_WHITESPACE); const int skip_comments = (flags & SKIP_COMMENTS); int c; - assert(cfg_file->reader.read_ptr); + assert(reader->read_ptr); - do c = cfg_getchar_raw(cfg_file); - while (skip_whitespace && git__isspace(c) && - !cfg_file->reader.eof); + do { + c = reader_getchar_raw(reader); + } while (skip_whitespace && git__isspace(c) && + !reader->eof); if (skip_comments && (c == '#' || c == ';')) { - do c = cfg_getchar_raw(cfg_file); - while (c != '\n'); + do { + c = reader_getchar_raw(reader); + } while (c != '\n'); } return c; @@ -567,23 +578,23 @@ static int cfg_getchar(diskfile_backend *cfg_file, int flags) /* * Read the next char, but don't move the reading pointer. */ -static int cfg_peek(diskfile_backend *cfg, int flags) +static int reader_peek(struct reader *reader, int flags) { void *old_read_ptr; int old_lineno, old_eof; int ret; - assert(cfg->reader.read_ptr); + assert(reader->read_ptr); - old_read_ptr = cfg->reader.read_ptr; - old_lineno = cfg->reader.line_number; - old_eof = cfg->reader.eof; + old_read_ptr = reader->read_ptr; + old_lineno = reader->line_number; + old_eof = reader->eof; - ret = cfg_getchar(cfg, flags); + ret = reader_getchar(reader, flags); - cfg->reader.read_ptr = old_read_ptr; - cfg->reader.line_number = old_lineno; - cfg->reader.eof = old_eof; + reader->read_ptr = old_read_ptr; + reader->line_number = old_lineno; + reader->eof = old_eof; return ret; } @@ -591,13 +602,13 @@ static int cfg_peek(diskfile_backend *cfg, int flags) /* * Read and consume a line, returning it in newly-allocated memory. */ -static char *cfg_readline(diskfile_backend *cfg, bool skip_whitespace) +static char *reader_readline(struct reader *reader, bool skip_whitespace) { char *line = NULL; char *line_src, *line_end; size_t line_len; - line_src = cfg->reader.read_ptr; + line_src = reader->read_ptr; if (skip_whitespace) { /* Skip empty empty lines */ @@ -626,10 +637,10 @@ static char *cfg_readline(diskfile_backend *cfg, bool skip_whitespace) line_end++; if (*line_end == '\0') - cfg->reader.eof = 1; + reader->eof = 1; - cfg->reader.line_number++; - cfg->reader.read_ptr = line_end; + reader->line_number++; + reader->read_ptr = line_end; return line; } @@ -637,11 +648,11 @@ static char *cfg_readline(diskfile_backend *cfg, bool skip_whitespace) /* * Consume a line, without storing it anywhere */ -static void cfg_consume_line(diskfile_backend *cfg) +static void reader_consume_line(struct reader *reader) { char *line_start, *line_end; - line_start = cfg->reader.read_ptr; + line_start = reader->read_ptr; line_end = strchr(line_start, '\n'); /* No newline at EOF */ if(line_end == NULL){ @@ -652,10 +663,10 @@ static void cfg_consume_line(diskfile_backend *cfg) line_end++; if (*line_end == '\0') - cfg->reader.eof = 1; + reader->eof = 1; - cfg->reader.line_number++; - cfg->reader.read_ptr = line_end; + reader->line_number++; + reader->read_ptr = line_end; } GIT_INLINE(int) config_keychar(int c) @@ -663,7 +674,7 @@ GIT_INLINE(int) config_keychar(int c) return isalnum(c) || c == '-'; } -static int parse_section_header_ext(diskfile_backend *cfg, const char *line, const char *base_name, char **section_name) +static int parse_section_header_ext(struct reader *reader, const char *line, const char *base_name, char **section_name) { int c, rpos; char *first_quote, *last_quote; @@ -679,7 +690,7 @@ static int parse_section_header_ext(diskfile_backend *cfg, const char *line, con last_quote = strrchr(line, '"'); if (last_quote - first_quote == 0) { - set_parse_error(cfg, 0, "Missing closing quotation mark in section header"); + set_parse_error(reader, 0, "Missing closing quotation mark in section header"); return -1; } @@ -698,14 +709,14 @@ static int parse_section_header_ext(diskfile_backend *cfg, const char *line, con */ do { if (quote_marks == 2) { - set_parse_error(cfg, rpos, "Unexpected text after closing quotes"); + set_parse_error(reader, rpos, "Unexpected text after closing quotes"); git_buf_free(&buf); return -1; } switch (c) { case 0: - set_parse_error(cfg, 0, "Unexpected end-of-line in section header"); + set_parse_error(reader, 0, "Unexpected end-of-line in section header"); git_buf_free(&buf); return -1; @@ -719,7 +730,7 @@ static int parse_section_header_ext(diskfile_backend *cfg, const char *line, con switch (c) { case '"': if (&line[rpos-1] == last_quote) { - set_parse_error(cfg, 0, "Missing closing quotation mark in section header"); + set_parse_error(reader, 0, "Missing closing quotation mark in section header"); git_buf_free(&buf); return -1; } @@ -728,7 +739,7 @@ static int parse_section_header_ext(diskfile_backend *cfg, const char *line, con break; default: - set_parse_error(cfg, rpos, "Unsupported escape sequence"); + set_parse_error(reader, rpos, "Unsupported escape sequence"); git_buf_free(&buf); return -1; } @@ -744,14 +755,14 @@ static int parse_section_header_ext(diskfile_backend *cfg, const char *line, con return 0; } -static int parse_section_header(diskfile_backend *cfg, char **section_out) +static int parse_section_header(struct reader *reader, char **section_out) { char *name, *name_end; int name_length, c, pos; int result; char *line; - line = cfg_readline(cfg, true); + line = reader_readline(reader, true); if (line == NULL) return -1; @@ -759,7 +770,7 @@ static int parse_section_header(diskfile_backend *cfg, char **section_out) name_end = strchr(line, ']'); if (name_end == NULL) { git__free(line); - set_parse_error(cfg, 0, "Missing ']' in section header"); + set_parse_error(reader, 0, "Missing ']' in section header"); return -1; } @@ -778,14 +789,14 @@ static int parse_section_header(diskfile_backend *cfg, char **section_out) do { if (git__isspace(c)){ name[name_length] = '\0'; - result = parse_section_header_ext(cfg, line, name, section_out); + result = parse_section_header_ext(reader, line, name, section_out); git__free(line); git__free(name); return result; } if (!config_keychar(c) && c != '.') { - set_parse_error(cfg, pos, "Unexpected character in header"); + set_parse_error(reader, pos, "Unexpected character in header"); goto fail_parse; } @@ -794,7 +805,7 @@ static int parse_section_header(diskfile_backend *cfg, char **section_out) } while ((c = line[pos++]) != ']'); if (line[pos - 1] != ']') { - set_parse_error(cfg, pos, "Unexpected end of file"); + set_parse_error(reader, pos, "Unexpected end of file"); goto fail_parse; } @@ -811,14 +822,14 @@ fail_parse: return -1; } -static int skip_bom(diskfile_backend *cfg) +static int skip_bom(struct reader *reader) { git_bom_t bom; int bom_offset = git_buf_text_detect_bom(&bom, - &cfg->reader.buffer, cfg->reader.read_ptr - cfg->reader.buffer.ptr); + &reader->buffer, reader->read_ptr - reader->buffer.ptr); if (bom == GIT_BOM_UTF8) - cfg->reader.read_ptr += bom_offset; + reader->read_ptr += bom_offset; /* TODO: reference implementation is pretty stupid with BoM */ @@ -888,7 +899,7 @@ static int strip_comments(char *line, int in_quotes) return quote_count; } -static int config_parse(diskfile_backend *cfg_file, git_config_level_t level) +static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_config_level_t level, int depth) { int c; char *current_section = NULL; @@ -900,37 +911,37 @@ static int config_parse(diskfile_backend *cfg_file, git_config_level_t level) khiter_t pos; /* Initialize the reading position */ - cfg_file->reader.read_ptr = cfg_file->reader.buffer.ptr; - cfg_file->reader.eof = 0; + reader->read_ptr = reader->buffer.ptr; + reader->eof = 0; /* If the file is empty, there's nothing for us to do */ - if (*cfg_file->reader.read_ptr == '\0') + if (*reader->read_ptr == '\0') return 0; - skip_bom(cfg_file); + skip_bom(reader); - while (result == 0 && !cfg_file->reader.eof) { + while (result == 0 && !reader->eof) { - c = cfg_peek(cfg_file, SKIP_WHITESPACE); + c = reader_peek(reader, SKIP_WHITESPACE); switch (c) { case '\n': /* EOF when peeking, set EOF in the reader to exit the loop */ - cfg_file->reader.eof = 1; + reader->eof = 1; break; case '[': /* section header, new section begins */ git__free(current_section); current_section = NULL; - result = parse_section_header(cfg_file, ¤t_section); + result = parse_section_header(reader, ¤t_section); break; case ';': case '#': - cfg_consume_line(cfg_file); + reader_consume_line(reader); break; default: /* assume variable declaration */ - result = parse_variable(cfg_file, &var_name, &var_value); + result = parse_variable(reader, &var_name, &var_value); if (result < 0) break; @@ -951,6 +962,7 @@ static int config_parse(diskfile_backend *cfg_file, git_config_level_t level) var->entry->name = git_buf_detach(&buf); var->entry->value = var_value; var->entry->level = level; + var->included = !!depth; /* Add or append the new config option */ pos = git_strmap_lookup_index(cfg_file->values, var->entry->name); @@ -1037,13 +1049,13 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p if (git_filebuf_open(&file, cfg->file_path, 0) < 0) return -1; - skip_bom(cfg); + skip_bom(&cfg->reader); ldot = strrchr(key, '.'); name = ldot + 1; section = git__strndup(key, ldot - key); while (!cfg->reader.eof) { - c = cfg_peek(cfg, SKIP_WHITESPACE); + c = reader_peek(&cfg->reader, SKIP_WHITESPACE); if (c == '\0') { /* We've arrived at the end of the file */ break; @@ -1060,7 +1072,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p git__free(current_section); current_section = NULL; - if (parse_section_header(cfg, ¤t_section) < 0) + if (parse_section_header(&cfg->reader, ¤t_section) < 0) goto rewrite_fail; /* Keep track of when it stops matching */ @@ -1069,7 +1081,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p } else if (c == ';' || c == '#') { - cfg_consume_line(cfg); + reader_consume_line(&cfg->reader); } else { @@ -1085,7 +1097,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p */ if (!section_matches) { if (!last_section_matched) { - cfg_consume_line(cfg); + reader_consume_line(&cfg->reader); continue; } } else { @@ -1093,7 +1105,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p char *var_name, *var_value; pre_end = cfg->reader.read_ptr; - if (parse_variable(cfg, &var_name, &var_value) < 0) + if (parse_variable(&cfg->reader, &var_name, &var_value) < 0) goto rewrite_fail; /* First try to match the name of the variable */ @@ -1291,19 +1303,19 @@ static int is_multiline_var(const char *str) return (end > str) && (count & 1); } -static int parse_multiline_variable(diskfile_backend *cfg, git_buf *value, int in_quotes) +static int parse_multiline_variable(struct reader *reader, git_buf *value, int in_quotes) { char *line = NULL, *proc_line = NULL; int quote_count; /* Check that the next line exists */ - line = cfg_readline(cfg, false); + line = reader_readline(reader, false); if (line == NULL) return -1; /* We've reached the end of the file, there is input missing */ if (line[0] == '\0') { - set_parse_error(cfg, 0, "Unexpected end of file while parsing multine var"); + set_parse_error(reader, 0, "Unexpected end of file while parsing multine var"); git__free(line); return -1; } @@ -1313,7 +1325,7 @@ static int parse_multiline_variable(diskfile_backend *cfg, git_buf *value, int i /* If it was just a comment, pretend it didn't exist */ if (line[0] == '\0') { git__free(line); - return parse_multiline_variable(cfg, value, quote_count); + return parse_multiline_variable(reader, value, quote_count); /* TODO: unbounded recursion. This **could** be exploitable */ } @@ -1338,19 +1350,19 @@ static int parse_multiline_variable(diskfile_backend *cfg, git_buf *value, int i * keep putting stuff in the buffer */ if (is_multiline_var(value->ptr)) - return parse_multiline_variable(cfg, value, quote_count); + return parse_multiline_variable(reader, value, quote_count); return 0; } -static int parse_variable(diskfile_backend *cfg, char **var_name, char **var_value) +static int parse_variable(struct reader *reader, char **var_name, char **var_value) { const char *var_end = NULL; const char *value_start = NULL; char *line; int quote_count; - line = cfg_readline(cfg, true); + line = reader_readline(reader, true); if (line == NULL) return -1; @@ -1385,7 +1397,7 @@ static int parse_variable(diskfile_backend *cfg, char **var_name, char **var_val GITERR_CHECK_ALLOC(proc_line); git_buf_puts(&multi_value, proc_line); git__free(proc_line); - if (parse_multiline_variable(cfg, &multi_value, quote_count) < 0 || git_buf_oom(&multi_value)) { + if (parse_multiline_variable(reader, &multi_value, quote_count) < 0 || git_buf_oom(&multi_value)) { git__free(*var_name); git__free(line); git_buf_free(&multi_value); -- cgit v1.2.1 From 27061b151a7e0225186365ee0b5ca802d68782a9 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 5 Sep 2013 10:25:16 -0700 Subject: Fix some newer GCC compiler warnings --- tests-clar/checkout/index.c | 2 +- tests-clar/diff/rename.c | 3 --- tests-clar/odb/backend/nonrefreshing.c | 4 ++-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tests-clar/checkout/index.c b/tests-clar/checkout/index.c index a185aec44..c9352d8ce 100644 --- a/tests-clar/checkout/index.c +++ b/tests-clar/checkout/index.c @@ -245,7 +245,7 @@ void test_checkout_index__options_dir_modes(void) (void)p_umask(um = p_umask(022)); cl_git_pass(p_stat("./testrepo/a", &st)); - cl_assert_equal_i_fmt(st.st_mode, GIT_FILEMODE_TREE | 0701 & ~um, "%07o"); + cl_assert_equal_i_fmt(st.st_mode, (GIT_FILEMODE_TREE | 0701) & ~um, "%07o"); /* File-mode test, since we're on the 'dir' branch */ cl_git_pass(p_stat("./testrepo/a/b.txt", &st)); diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index ac3814d59..b5a9935fd 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -1100,7 +1100,6 @@ void test_diff_rename__can_rename_from_rewrite(void) { git_index *index; git_tree *tree; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; git_diff_list *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; @@ -1110,8 +1109,6 @@ void test_diff_rename__can_rename_from_rewrite(void) const char *targets[] = { "songof7cities.txt", "this-is-a-rename.txt" }; struct rename_expected expect = { 2, status, sources, targets }; - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - cl_git_pass(git_repository_index(&index, g_repo)); cl_git_pass(p_rename("renames/songof7cities.txt", "renames/this-is-a-rename.txt")); diff --git a/tests-clar/odb/backend/nonrefreshing.c b/tests-clar/odb/backend/nonrefreshing.c index abb824d4b..9abca2bd3 100644 --- a/tests-clar/odb/backend/nonrefreshing.c +++ b/tests-clar/odb/backend/nonrefreshing.c @@ -132,8 +132,8 @@ static int build_fake_backend( static void setup_repository_and_backend(git_error_code error_code) { - git_odb *odb; - git_odb_backend *backend; + git_odb *odb = NULL; + git_odb_backend *backend = NULL; _repo = cl_git_sandbox_init("testrepo.git"); -- cgit v1.2.1 From f240acce865ec14df0d517d5000316a933e7ffed Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 5 Sep 2013 11:20:12 -0700 Subject: Add more file mode permissions macros This adds some more macros for some standard operations on file modes, particularly related to permissions, and then updates a number of places around the code base to use the new macros. --- src/checkout.c | 13 +++++-------- src/diff_print.c | 4 ++-- src/fileops.c | 4 ++-- src/fileops.h | 5 ++++- src/index.c | 2 +- src/tree.c | 12 ++++++------ 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/checkout.c b/src/checkout.c index ec9da7e2e..f3a9b343d 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -693,17 +693,14 @@ static int buffer_to_file( buffer, path, file_open_flags, file_mode)) < 0) return error; - if (st != NULL && (error = p_stat(path, st)) < 0) { - giterr_set(GITERR_OS, "Error while statting '%s'", path); - return error; - } + if (st != NULL && (error = p_stat(path, st)) < 0) + giterr_set(GITERR_OS, "Error statting '%s'", path); - if ((file_mode & 0100) != 0 && (error = p_chmod(path, file_mode)) < 0) { + else if (GIT_PERMS_EXECUTABLE(file_mode) && + (error = p_chmod(path, file_mode)) < 0) giterr_set(GITERR_OS, "Failed to set permissions on '%s'", path); - return error; - } - return 0; + return error; } static int blob_content_to_file( diff --git a/src/diff_print.c b/src/diff_print.c index 4ddd72443..96937d84d 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -7,7 +7,7 @@ #include "common.h" #include "diff.h" #include "diff_patch.h" -#include "buffer.h" +#include "fileops.h" typedef struct { git_diff_list *diff; @@ -46,7 +46,7 @@ static char diff_pick_suffix(int mode) { if (S_ISDIR(mode)) return '/'; - else if (mode & 0100) /* -V536 */ + else if (GIT_PERMS_EXECUTABLE(mode)) /* -V536 */ /* in git, modes are very regular, so we must have 0100755 mode */ return '*'; else diff --git a/src/fileops.c b/src/fileops.c index 76119e02e..92cda82e7 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -110,7 +110,7 @@ git_off_t git_futils_filesize(git_file fd) mode_t git_futils_canonical_mode(mode_t raw_mode) { if (S_ISREG(raw_mode)) - return S_IFREG | GIT_CANONICAL_PERMS(raw_mode); + return S_IFREG | GIT_PERMS_CANONICAL(raw_mode); else if (S_ISLNK(raw_mode)) return S_IFLNK; else if (S_ISGITLINK(raw_mode)) @@ -972,7 +972,7 @@ static int _cp_r_callback(void *ref, git_buf *from) mode_t usemode = from_st.st_mode; if ((info->flags & GIT_CPDIR_SIMPLE_TO_MODE) != 0) - usemode = (usemode & 0111) ? 0777 : 0666; + usemode = GIT_PERMS_FOR_WRITE(usemode); error = git_futils_cp(from->ptr, info->to.ptr, usemode); } diff --git a/src/fileops.h b/src/fileops.h index 5adedfc57..142eb99d2 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -223,8 +223,11 @@ extern int git_futils_open_ro(const char *path); */ extern git_off_t git_futils_filesize(git_file fd); +#define GIT_PERMS_EXECUTABLE(MODE) (((MODE) & 0111) != 0) +#define GIT_PERMS_CANONICAL(MODE) (GIT_PERMS_EXECUTABLE(MODE) ? 0755 : 0644) +#define GIT_PERMS_FOR_WRITE(MODE) (GIT_PERMS_EXECUTABLE(MODE) ? 0777 : 0666) + #define GIT_MODE_PERMS_MASK 0777 -#define GIT_CANONICAL_PERMS(MODE) (((MODE) & 0100) ? 0755 : 0644) #define GIT_MODE_TYPE(MODE) ((MODE) & ~GIT_MODE_PERMS_MASK) #define GIT_MODE_ISBLOB(MODE) (GIT_MODE_TYPE(MODE) == GIT_MODE_TYPE(GIT_FILEMODE_BLOB)) diff --git a/src/index.c b/src/index.c index 17e43903f..9b32222a7 100644 --- a/src/index.c +++ b/src/index.c @@ -284,7 +284,7 @@ static unsigned int index_create_mode(unsigned int mode) if (S_ISDIR(mode) || (mode & S_IFMT) == (S_IFLNK | S_IFDIR)) return (S_IFLNK | S_IFDIR); - return S_IFREG | ((mode & 0100) ? 0755 : 0644); + return S_IFREG | GIT_PERMS_CANONICAL(mode); } static unsigned int index_merge_mode( diff --git a/src/tree.c b/src/tree.c index 65d01b4d5..91309e107 100644 --- a/src/tree.c +++ b/src/tree.c @@ -10,7 +10,7 @@ #include "tree.h" #include "git2/repository.h" #include "git2/object.h" -#include "path.h" +#include "fileops.h" #include "tree-cache.h" #include "index.h" @@ -29,19 +29,19 @@ static bool valid_filemode(const int filemode) GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode) { /* Tree bits set, but it's not a commit */ - if (filemode & GIT_FILEMODE_TREE && !(filemode & 0100000)) + if (GIT_MODE_TYPE(filemode) == GIT_FILEMODE_TREE) return GIT_FILEMODE_TREE; - /* If any of the x bits is set */ - if (filemode & 0111) + /* If any of the x bits are set */ + if (GIT_PERMS_EXECUTABLE(filemode)) return GIT_FILEMODE_BLOB_EXECUTABLE; /* 16XXXX means commit */ - if ((filemode & GIT_FILEMODE_COMMIT) == GIT_FILEMODE_COMMIT) + if (GIT_MODE_TYPE(filemode) == GIT_FILEMODE_COMMIT) return GIT_FILEMODE_COMMIT; /* 12XXXX means commit */ - if ((filemode & GIT_FILEMODE_LINK) == GIT_FILEMODE_LINK) + if (GIT_MODE_TYPE(filemode) == GIT_FILEMODE_LINK) return GIT_FILEMODE_LINK; /* Otherwise, return a blob */ -- cgit v1.2.1 From c97d407d9cc54fc99af0a57e09e04e9e0bc68cb6 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 5 Sep 2013 11:45:29 -0700 Subject: Fix tests of file modes This fixes an issue checking file modes in the tests that initialize a repo from a template directory when a symlink is used in the template. Also, this updates some other places where we are examining file modes to use the new macros. --- tests-clar/checkout/index.c | 2 +- tests-clar/index/addall.c | 7 +++++-- tests-clar/repo/init.c | 33 ++++++++++++++++++--------------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/tests-clar/checkout/index.c b/tests-clar/checkout/index.c index c9352d8ce..73050d08e 100644 --- a/tests-clar/checkout/index.c +++ b/tests-clar/checkout/index.c @@ -267,7 +267,7 @@ void test_checkout_index__options_override_file_modes(void) cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); cl_git_pass(p_stat("./testrepo/new.txt", &st)); - cl_assert_equal_i_fmt(st.st_mode & 0777, 0700, "%07o"); + cl_assert_equal_i_fmt(st.st_mode & GIT_MODE_PERMS_MASK, 0700, "%07o"); #endif } diff --git a/tests-clar/index/addall.c b/tests-clar/index/addall.c index fca6e77fa..e6ce463a3 100644 --- a/tests-clar/index/addall.c +++ b/tests-clar/index/addall.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "../status/status_helpers.h" #include "posix.h" +#include "fileops.h" git_repository *g_repo = NULL; @@ -108,8 +109,10 @@ static void check_stat_data(git_index *index, const char *path, bool match) cl_assert(st.st_size == entry->file_size); cl_assert(st.st_uid == entry->uid); cl_assert(st.st_gid == entry->gid); - cl_assert_equal_b(st.st_mode & ~0777, entry->mode & ~0777); - cl_assert_equal_b(st.st_mode & 0111, entry->mode & 0111); + cl_assert_equal_i_fmt( + GIT_MODE_TYPE(st.st_mode), GIT_MODE_TYPE(entry->mode), "%07o"); + cl_assert_equal_b( + GIT_PERMS_EXECUTABLE(st.st_mode), GIT_PERMS_EXECUTABLE(entry->mode)); } else { /* most things will still match */ cl_assert(st.st_size != entry->file_size); diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index 62e4ecd59..d7f2524c8 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -364,6 +364,8 @@ void test_repo_init__extended_1(void) cl_fixture_cleanup("root"); } +#define CLEAR_FOR_CORE_FILEMODE(M) ((M) &= ~0177) + static void assert_hooks_match( const char *template_dir, const char *repo_dir, @@ -382,16 +384,18 @@ static void assert_hooks_match( cl_assert_equal_sz(expected_st.st_size, st.st_size); - expected_st.st_mode = - (expected_st.st_mode & ~0777) | - (((expected_st.st_mode & 0111) ? 0100777 : 0100666) & ~g_umask); + if (GIT_MODE_TYPE(expected_st.st_mode) != GIT_FILEMODE_LINK) { + mode_t expected_mode = + GIT_MODE_TYPE(expected_st.st_mode) | + (GIT_PERMS_FOR_WRITE(expected_st.st_mode) & ~g_umask); - if (!core_filemode) { - expected_st.st_mode = expected_st.st_mode & ~0177; - st.st_mode = st.st_mode & ~0177; - } + if (!core_filemode) { + CLEAR_FOR_CORE_FILEMODE(expected_mode); + CLEAR_FOR_CORE_FILEMODE(st.st_mode); + } - cl_assert_equal_i_fmt(expected_st.st_mode, st.st_mode, "%07o"); + cl_assert_equal_i_fmt(expected_mode, st.st_mode, "%07o"); + } git_buf_free(&expected); git_buf_free(&actual); @@ -409,8 +413,8 @@ static void assert_mode_seems_okay( git_buf_free(&full); if (!core_filemode) { - expect_mode = expect_mode & ~0111; - st.st_mode = st.st_mode & ~0111; + CLEAR_FOR_CORE_FILEMODE(expect_mode); + CLEAR_FOR_CORE_FILEMODE(st.st_mode); expect_setgid = false; } @@ -421,12 +425,11 @@ static void assert_mode_seems_okay( cl_assert((st.st_mode & S_ISGID) == 0); } - if ((expect_mode & 0111) != 0) - cl_assert((st.st_mode & 0111) != 0); - else - cl_assert((st.st_mode & 0111) == 0); + cl_assert_equal_b( + GIT_PERMS_EXECUTABLE(expect_mode), GIT_PERMS_EXECUTABLE(st.st_mode)); - cl_assert((expect_mode & 0170000) == (st.st_mode & 0170000)); + cl_assert_equal_i_fmt( + GIT_MODE_TYPE(expect_mode), GIT_MODE_TYPE(st.st_mode), "%07o"); } void test_repo_init__extended_with_template(void) -- cgit v1.2.1 From af22dabb4366f8b2dd4acd5725a25e88842d6938 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 5 Sep 2013 12:01:17 -0700 Subject: GIT_MODE_TYPE should exclude setgid bits The GIT_MODE_TYPE macro was looking at all bits above the permissions, but it should really just look at the top bits so that it will give the right results for a setgid or setuid entry. Since we're now using these macros in the tests, this was causing a test failure on platforms that don't support setgid. --- src/fileops.h | 3 ++- tests-clar/repo/init.c | 8 ++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/fileops.h b/src/fileops.h index 142eb99d2..f2144566d 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -228,7 +228,8 @@ extern git_off_t git_futils_filesize(git_file fd); #define GIT_PERMS_FOR_WRITE(MODE) (GIT_PERMS_EXECUTABLE(MODE) ? 0777 : 0666) #define GIT_MODE_PERMS_MASK 0777 -#define GIT_MODE_TYPE(MODE) ((MODE) & ~GIT_MODE_PERMS_MASK) +#define GIT_MODE_TYPE_MASK 0170000 +#define GIT_MODE_TYPE(MODE) ((MODE) & GIT_MODE_TYPE_MASK) #define GIT_MODE_ISBLOB(MODE) (GIT_MODE_TYPE(MODE) == GIT_MODE_TYPE(GIT_FILEMODE_BLOB)) /** diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index d7f2524c8..43bd7afe0 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -418,12 +418,8 @@ static void assert_mode_seems_okay( expect_setgid = false; } - if (S_ISGID != 0) { - if (expect_setgid) - cl_assert((st.st_mode & S_ISGID) != 0); - else - cl_assert((st.st_mode & S_ISGID) == 0); - } + if (S_ISGID != 0) + cl_assert_equal_b(expect_setgid, (st.st_mode & S_ISGID) != 0); cl_assert_equal_b( GIT_PERMS_EXECUTABLE(expect_mode), GIT_PERMS_EXECUTABLE(st.st_mode)); -- cgit v1.2.1 From a7fcc44dcf3b2925ba366543486afd102b41838c Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 5 Sep 2013 16:14:32 -0700 Subject: Better macro name for is-exec-bit-set test --- src/checkout.c | 2 +- src/diff_print.c | 2 +- src/fileops.h | 6 +++--- src/tree.c | 2 +- tests-clar/index/addall.c | 2 +- tests-clar/repo/init.c | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/checkout.c b/src/checkout.c index f3a9b343d..aae354ca6 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -696,7 +696,7 @@ static int buffer_to_file( if (st != NULL && (error = p_stat(path, st)) < 0) giterr_set(GITERR_OS, "Error statting '%s'", path); - else if (GIT_PERMS_EXECUTABLE(file_mode) && + else if (GIT_PERMS_IS_EXEC(file_mode) && (error = p_chmod(path, file_mode)) < 0) giterr_set(GITERR_OS, "Failed to set permissions on '%s'", path); diff --git a/src/diff_print.c b/src/diff_print.c index 96937d84d..ee4b5fc17 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -46,7 +46,7 @@ static char diff_pick_suffix(int mode) { if (S_ISDIR(mode)) return '/'; - else if (GIT_PERMS_EXECUTABLE(mode)) /* -V536 */ + else if (GIT_PERMS_IS_EXEC(mode)) /* -V536 */ /* in git, modes are very regular, so we must have 0100755 mode */ return '*'; else diff --git a/src/fileops.h b/src/fileops.h index f2144566d..02f79b9e7 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -223,9 +223,9 @@ extern int git_futils_open_ro(const char *path); */ extern git_off_t git_futils_filesize(git_file fd); -#define GIT_PERMS_EXECUTABLE(MODE) (((MODE) & 0111) != 0) -#define GIT_PERMS_CANONICAL(MODE) (GIT_PERMS_EXECUTABLE(MODE) ? 0755 : 0644) -#define GIT_PERMS_FOR_WRITE(MODE) (GIT_PERMS_EXECUTABLE(MODE) ? 0777 : 0666) +#define GIT_PERMS_IS_EXEC(MODE) (((MODE) & 0111) != 0) +#define GIT_PERMS_CANONICAL(MODE) (GIT_PERMS_IS_EXEC(MODE) ? 0755 : 0644) +#define GIT_PERMS_FOR_WRITE(MODE) (GIT_PERMS_IS_EXEC(MODE) ? 0777 : 0666) #define GIT_MODE_PERMS_MASK 0777 #define GIT_MODE_TYPE_MASK 0170000 diff --git a/src/tree.c b/src/tree.c index 91309e107..f9469195a 100644 --- a/src/tree.c +++ b/src/tree.c @@ -33,7 +33,7 @@ GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode) return GIT_FILEMODE_TREE; /* If any of the x bits are set */ - if (GIT_PERMS_EXECUTABLE(filemode)) + if (GIT_PERMS_IS_EXEC(filemode)) return GIT_FILEMODE_BLOB_EXECUTABLE; /* 16XXXX means commit */ diff --git a/tests-clar/index/addall.c b/tests-clar/index/addall.c index e6ce463a3..00388ee00 100644 --- a/tests-clar/index/addall.c +++ b/tests-clar/index/addall.c @@ -112,7 +112,7 @@ static void check_stat_data(git_index *index, const char *path, bool match) cl_assert_equal_i_fmt( GIT_MODE_TYPE(st.st_mode), GIT_MODE_TYPE(entry->mode), "%07o"); cl_assert_equal_b( - GIT_PERMS_EXECUTABLE(st.st_mode), GIT_PERMS_EXECUTABLE(entry->mode)); + GIT_PERMS_IS_EXEC(st.st_mode), GIT_PERMS_IS_EXEC(entry->mode)); } else { /* most things will still match */ cl_assert(st.st_size != entry->file_size); diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index 43bd7afe0..e3fc112b3 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -422,7 +422,7 @@ static void assert_mode_seems_okay( cl_assert_equal_b(expect_setgid, (st.st_mode & S_ISGID) != 0); cl_assert_equal_b( - GIT_PERMS_EXECUTABLE(expect_mode), GIT_PERMS_EXECUTABLE(st.st_mode)); + GIT_PERMS_IS_EXEC(expect_mode), GIT_PERMS_IS_EXEC(st.st_mode)); cl_assert_equal_i_fmt( GIT_MODE_TYPE(expect_mode), GIT_MODE_TYPE(st.st_mode), "%07o"); -- cgit v1.2.1 From fb23d05f0bc3084cdb5a9737b1c678817c5bc9e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 17 Aug 2013 07:58:55 +0200 Subject: revwalk: make mark_unintersting use a loop Using a recursive function can blow the stack when dealing with long histories. Use a loop instead to limit the call chain depth. This fixes #1223. --- src/array.h | 2 ++ src/revwalk.c | 42 ++++++++++++++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/array.h b/src/array.h index c25a1b29e..b82079bd8 100644 --- a/src/array.h +++ b/src/array.h @@ -63,6 +63,8 @@ GIT_INLINE(void *) git_array_grow(void *_a, size_t item_size) #define git_array_last(a) ((a).size ? &(a).ptr[(a).size - 1] : NULL) +#define git_array_pop(a) ((a).size ? &(a).ptr[--(a).size] : NULL) + #define git_array_get(a, i) (((i) < (a).size) ? &(a).ptr[(i)] : NULL) #define git_array_size(a) (a).size diff --git a/src/revwalk.c b/src/revwalk.c index 528d02b20..1ff41bfb1 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -41,28 +41,50 @@ git_commit_list_node *git_revwalk__commit_lookup( return commit; } -static void mark_uninteresting(git_commit_list_node *commit) +static int mark_uninteresting(git_commit_list_node *commit) { unsigned short i; + git_array_t(git_commit_list_node *) pending = GIT_ARRAY_INIT; + git_commit_list_node **tmp; + assert(commit); - commit->uninteresting = 1; + git_array_alloc(pending); + GITERR_CHECK_ARRAY(pending); - /* This means we've reached a merge base, so there's no need to walk any more */ - if ((commit->flags & (RESULT | STALE)) == RESULT) - return; + do { + commit->uninteresting = 1; + + /* This means we've reached a merge base, so there's no need to walk any more */ + if ((commit->flags & (RESULT | STALE)) == RESULT) { + tmp = git_array_pop(pending); + commit = tmp ? *tmp : NULL; + continue; + } + + for (i = 0; i < commit->out_degree; ++i) + if (!commit->parents[i]->uninteresting) { + git_commit_list_node **node = git_array_alloc(pending); + GITERR_CHECK_ALLOC(node); + *node = commit->parents[i]; + } + + tmp = git_array_pop(pending); + commit = tmp ? *tmp : NULL; + + } while (git_array_size(pending) > 0); - for (i = 0; i < commit->out_degree; ++i) - if (!commit->parents[i]->uninteresting) - mark_uninteresting(commit->parents[i]); + git_array_clear(pending); + + return 0; } static int process_commit(git_revwalk *walk, git_commit_list_node *commit, int hide) { int error; - if (hide) - mark_uninteresting(commit); + if (hide && mark_uninteresting(commit) < 0) + return -1; if (commit->seen) return 0; -- cgit v1.2.1 From ae4a486605c258aa38a53534c99f94e66379c9ae Mon Sep 17 00:00:00 2001 From: nulltoken Date: Thu, 29 Aug 2013 14:12:13 +0200 Subject: blob: Slightly enforce a create_fromchunks() test --- tests-clar/object/blob/fromchunks.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests-clar/object/blob/fromchunks.c b/tests-clar/object/blob/fromchunks.c index dc57d4fbe..9fe62daef 100644 --- a/tests-clar/object/blob/fromchunks.c +++ b/tests-clar/object/blob/fromchunks.c @@ -41,11 +41,15 @@ void test_object_blob_fromchunks__can_create_a_blob_from_a_in_memory_chunk_provi cl_git_pass(git_oid_fromstr(&expected_oid, "321cbdf08803c744082332332838df6bd160f8f9")); - cl_git_fail(git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY)); + cl_git_fail_with( + git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY), + GIT_ENOTFOUND); cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany)); cl_git_pass(git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY)); + cl_assert(git_oid_cmp(&expected_oid, git_object_id(blob)) == 0); + git_object_free(blob); } -- cgit v1.2.1 From 4047950f30618c160cd2fdf5da39fb8e26b031d9 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Thu, 29 Aug 2013 14:19:34 +0200 Subject: odb: Prevent stream_finalize_write() from overwriting Now that #1785 is merged, git_odb_stream_finalize_write() calculates the object id before invoking the odb backend. This commit gives a chance to the backend to check if it already knows this object. --- include/git2/odb_backend.h | 4 ++++ src/odb.c | 4 ++++ src/odb_loose.c | 7 ------- tests-clar/object/blob/fromchunks.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index 7b3c6a356..bafeec047 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -92,6 +92,10 @@ struct git_odb_stream { /** * Store the contents of the stream as an object with the id * specified in `oid`. + * + * This method will *not* be invoked by libgit2 if the object pointed at + * by `oid` already exists in any backend. Libgit2 will however take care + * of properly disposing the stream through a call to `free()`. */ int (*finalize_write)(git_odb_stream *stream, const git_oid *oid); diff --git a/src/odb.c b/src/odb.c index e47715f79..dfb252178 100644 --- a/src/odb.c +++ b/src/odb.c @@ -900,6 +900,10 @@ int git_odb_stream_write(git_odb_stream *stream, const char *buffer, size_t len) int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream) { git_hash_final(out, stream->hash_ctx); + + if (git_odb_exists(stream->backend->odb, out)) + return 0; + return stream->finalize_write(stream, out); } diff --git a/src/odb_loose.c b/src/odb_loose.c index abf46a118..ce63f4673 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -781,13 +781,6 @@ static int loose_backend__stream_fwrite(git_odb_stream *_stream, const git_oid * if (object_file_name(&final_path, backend, oid) < 0 || object_mkdir(&final_path, backend) < 0) error = -1; - /* - * Don't try to add an existing object to the repository. This - * is what git does and allows us to sidestep the fact that - * we're not allowed to overwrite a read-only file on Windows. - */ - else if (git_path_exists(final_path.ptr) == true) - git_filebuf_cleanup(&stream->fbuf); else error = git_filebuf_commit_at( &stream->fbuf, final_path.ptr, GIT_OBJECT_FILE_MODE); diff --git a/tests-clar/object/blob/fromchunks.c b/tests-clar/object/blob/fromchunks.c index 9fe62daef..03ed4efb4 100644 --- a/tests-clar/object/blob/fromchunks.c +++ b/tests-clar/object/blob/fromchunks.c @@ -53,6 +53,34 @@ void test_object_blob_fromchunks__can_create_a_blob_from_a_in_memory_chunk_provi git_object_free(blob); } +void test_object_blob_fromchunks__doesnot_overwrite_an_already_existing_object(void) +{ + git_buf path = GIT_BUF_INIT; + git_buf content = GIT_BUF_INIT; + git_oid expected_oid, oid; + int howmany = 7; + + cl_git_pass(git_oid_fromstr(&expected_oid, "321cbdf08803c744082332332838df6bd160f8f9")); + + cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany)); + + /* Let's replace the content of the blob file storage with something else... */ + cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/32/1cbdf08803c744082332332838df6bd160f8f9")); + cl_git_pass(p_unlink(git_buf_cstr(&path))); + cl_git_mkfile(git_buf_cstr(&path), "boom"); + + /* ...request a creation of the same blob... */ + howmany = 7; + cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany)); + + /* ...and ensure the content of the faked blob file hasn't been altered */ + cl_git_pass(git_futils_readbuffer(&content, git_buf_cstr(&path))); + cl_assert(!git__strcmp("boom", git_buf_cstr(&content))); + + git_buf_free(&path); + git_buf_free(&content); +} + #define GITATTR "* text=auto\n" \ "*.txt text\n" \ "*.data binary\n" -- cgit v1.2.1 From a8d67afe42e6c79cb15383ceb1264f665dc4ad8d Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 7 Sep 2013 17:21:41 +0200 Subject: revparse: Prevent unnecessary odb backend calls --- src/revparse.c | 9 +++------ tests-clar/odb/backend/nonrefreshing.c | 13 +++++++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/revparse.c b/src/revparse.c index 329b96dbc..05ddc6c35 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -115,12 +115,9 @@ static int revparse_lookup_object( if (error < 0 && error != GIT_ENOTFOUND) return error; - error = maybe_abbrev(object_out, repo, spec); - if (!error) - return 0; - - if (error < 0 && error != GIT_ENOTFOUND) - return error; + if ((strlen(spec) < GIT_OID_HEXSZ) && + ((error = maybe_abbrev(object_out, repo, spec)) != GIT_ENOTFOUND)) + return error; error = maybe_describe(object_out, repo, spec); if (!error) diff --git a/tests-clar/odb/backend/nonrefreshing.c b/tests-clar/odb/backend/nonrefreshing.c index 9abca2bd3..b43529479 100644 --- a/tests-clar/odb/backend/nonrefreshing.c +++ b/tests-clar/odb/backend/nonrefreshing.c @@ -259,3 +259,16 @@ void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_success(void) cl_assert_equal_i(1, _fake->read_header_calls); } + +void test_odb_backend_nonrefreshing__read_is_invoked_once_when_revparsing_a_full_oid(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_fail_with( + git_revparse_single(&obj, _repo, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"), + GIT_ENOTFOUND); + + cl_assert_equal_i(1, _fake->read_calls); +} -- cgit v1.2.1 From 1634df8c287da5acbe017ac786e2bb9fcd723eaa Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 7 Sep 2013 17:31:30 +0200 Subject: revparse: Simplify error handling --- src/revparse.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/revparse.c b/src/revparse.c index 05ddc6c35..3dde22ce1 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -93,11 +93,7 @@ static int revparse_lookup_object( int error; git_reference *ref; - error = maybe_sha(object_out, repo, spec); - if (!error) - return 0; - - if (error < 0 && error != GIT_ENOTFOUND) + if ((error = maybe_sha(object_out, repo, spec)) != GIT_ENOTFOUND) return error; error = git_reference_dwim(&ref, repo, spec); @@ -112,18 +108,14 @@ static int revparse_lookup_object( return error; } - if (error < 0 && error != GIT_ENOTFOUND) + if (error != GIT_ENOTFOUND) return error; if ((strlen(spec) < GIT_OID_HEXSZ) && ((error = maybe_abbrev(object_out, repo, spec)) != GIT_ENOTFOUND)) return error; - error = maybe_describe(object_out, repo, spec); - if (!error) - return 0; - - if (error < 0 && error != GIT_ENOTFOUND) + if ((error = maybe_describe(object_out, repo, spec)) != GIT_ENOTFOUND) return error; giterr_set(GITERR_REFERENCE, "Revspec '%s' not found.", spec); -- cgit v1.2.1 From e839efbe2468905d82ffb717c225a738de6f192c Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 7 Sep 2013 17:51:24 +0200 Subject: tests: Fix memory leaks --- tests-clar/network/remote/local.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests-clar/network/remote/local.c b/tests-clar/network/remote/local.c index 79eb73c5a..c8edd37f5 100644 --- a/tests-clar/network/remote/local.c +++ b/tests-clar/network/remote/local.c @@ -201,6 +201,7 @@ void test_network_remote_local__push_to_bare_remote(void) cl_assert(git_push_unpack_ok(push)); /* Clean up */ + git_push_free(push); git_remote_free(localremote); cl_fixture_cleanup("localbare.git"); } @@ -236,6 +237,7 @@ void test_network_remote_local__push_to_non_bare_remote(void) cl_assert_equal_i(0, git_push_unpack_ok(push)); /* Clean up */ + git_push_free(push); git_remote_free(localremote); cl_fixture_cleanup("localbare.git"); } -- cgit v1.2.1 From d8d25acb9a2e560a5fce66d4b1c9bdf4969ea2c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 5 Sep 2013 19:24:20 +0200 Subject: config: add support for include directives Relative, absolute and home-relative paths are supported. The recursion limit it set at 10, just like in git. --- src/config_file.c | 57 ++++++++++++++++++++++++++--- tests-clar/config/include.c | 50 +++++++++++++++++++++++++ tests-clar/resources/config/config-include | 2 + tests-clar/resources/config/config-included | 2 + 4 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 tests-clar/config/include.c create mode 100644 tests-clar/resources/config/config-include create mode 100644 tests-clar/resources/config/config-included diff --git a/src/config_file.c b/src/config_file.c index fa8aba061..891bc29d3 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -34,6 +34,8 @@ typedef struct git_config_file_iter { cvar_t* next_var; } git_config_file_iter; +/* Max depth for [include] directives */ +#define MAX_INCLUDE_DEPTH 10 #define CVAR_LIST_HEAD(list) ((list)->head) @@ -74,6 +76,8 @@ typedef struct git_config_file_iter { (iter) = (tmp)) struct reader { + time_t file_mtime; + size_t file_size; char *file_path; git_buf buffer; char *read_ptr; @@ -89,8 +93,6 @@ typedef struct { struct reader reader; char *file_path; - time_t file_mtime; - size_t file_size; git_config_level_t level; } diskfile_backend; @@ -169,7 +171,7 @@ static int config_open(git_config_backend *cfg, git_config_level_t level) git_buf_init(&b->reader.buffer, 0); res = git_futils_readbuffer_updated( - &b->reader.buffer, b->file_path, &b->file_mtime, &b->file_size, NULL); + &b->reader.buffer, b->file_path, &b->reader.file_mtime, &b->reader.file_size, NULL); /* It's fine if the file doesn't exist */ if (res == GIT_ENOTFOUND) @@ -191,7 +193,7 @@ static int config_refresh(git_config_backend *cfg) git_strmap *old_values; res = git_futils_readbuffer_updated( - &b->reader.buffer, b->file_path, &b->file_mtime, &b->file_size, &updated); + &b->reader.buffer, b->file_path, &b->reader.file_mtime, &b->reader.file_size, &updated); if (res < 0 || !updated) return (res == GIT_ENOTFOUND) ? 0 : res; @@ -899,6 +901,15 @@ static int strip_comments(char *line, int in_quotes) return quote_count; } +static int included_path(git_buf *out, const char *dir, const char *path) +{ + /* From the user's home */ + if (path[0] == '~' && path[1] == '/') + return git_futils_find_global_file(out, &path[1]); + + return git_path_join_unrooted(out, path, dir, NULL); +} + static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_config_level_t level, int depth) { int c; @@ -910,6 +921,10 @@ static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_c int result = 0; khiter_t pos; + /* FIXME: should we return an error? */ + if (depth >= MAX_INCLUDE_DEPTH) + return 0; + /* Initialize the reading position */ reader->read_ptr = reader->buffer.ptr; reader->eof = 0; @@ -979,6 +994,38 @@ static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_c existing->next = var; } + if (!git__strcmp(var->entry->name, "include.path")) { + struct reader r; + git_buf path = GIT_BUF_INIT; + char *dir; + + memset(&r, 0, sizeof(r)); + if ((result = git_path_dirname_r(&path, reader->file_path)) < 0) + break; + + dir = git_buf_detach(&path); + result = included_path(&path, dir, var->entry->value); + git__free(dir); + + if (result < 0) + break; + + r.file_path = git_buf_detach(&path); + git_buf_init(&r.buffer, 0); + if ((result = git_futils_readbuffer_updated(&r.buffer, r.file_path, &r.file_mtime, + &r.file_size, NULL)) < 0) { + git__free(r.file_path); + break; + } + + result = config_parse(cfg_file, &r, level, depth+1); + git__free(r.file_path); + git_buf_free(&r.buffer); + + if (result < 0) + break; + } + break; } } @@ -1199,7 +1246,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p git__free(current_section); /* refresh stats - if this errors, then commit will error too */ - (void)git_filebuf_stats(&cfg->file_mtime, &cfg->file_size, &file); + (void)git_filebuf_stats(&cfg->reader.file_mtime, &cfg->reader.file_size, &file); result = git_filebuf_commit(&file, GIT_CONFIG_FILE_MODE); git_buf_free(&cfg->reader.buffer); diff --git a/tests-clar/config/include.c b/tests-clar/config/include.c new file mode 100644 index 000000000..b88a7b2d1 --- /dev/null +++ b/tests-clar/config/include.c @@ -0,0 +1,50 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "fileops.h" + +void test_config_include__relative(void) +{ + git_config *cfg; + const char *str; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config-include"))); + + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); + cl_assert_equal_s(str, "huzzah"); + + git_config_free(cfg); +} + +void test_config_include__absolute(void) +{ + git_config *cfg; + const char *str; + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_buf_printf(&buf, "[include]\npath = %s/config-included", cl_fixture("config"))); + + cl_git_mkfile("config-include-absolute", git_buf_cstr(&buf)); + git_buf_free(&buf); + cl_git_pass(git_config_open_ondisk(&cfg, "config-include-absolute")); + + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); + cl_assert_equal_s(str, "huzzah"); + + git_config_free(cfg); +} + +void test_config_include__homedir(void) +{ + git_config *cfg; + const char *str; + + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, cl_fixture("config"))); + cl_git_mkfile("config-include-homedir", "[include]\npath = ~/config-included"); + + cl_git_pass(git_config_open_ondisk(&cfg, "config-include-homedir")); + + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); + cl_assert_equal_s(str, "huzzah"); + + git_config_free(cfg); +} diff --git a/tests-clar/resources/config/config-include b/tests-clar/resources/config/config-include new file mode 100644 index 000000000..6b5e79de7 --- /dev/null +++ b/tests-clar/resources/config/config-include @@ -0,0 +1,2 @@ +[include] + path = config-included diff --git a/tests-clar/resources/config/config-included b/tests-clar/resources/config/config-included new file mode 100644 index 000000000..089ca08a7 --- /dev/null +++ b/tests-clar/resources/config/config-included @@ -0,0 +1,2 @@ +[foo "bar"] + baz = huzzah -- cgit v1.2.1 From 19be0692b40f7ba8583ea96b1d0f382e45c13071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 6 Sep 2013 20:34:02 +0200 Subject: config: keep a list of included files When refreshing we need to refresh if any of the files have been touched, so we need to keep the list. --- src/config_file.c | 105 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 58 insertions(+), 47 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 891bc29d3..3732fd15c 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -15,6 +15,7 @@ #include "git2/sys/config.h" #include "git2/types.h" #include "strmap.h" +#include "array.h" #include #include @@ -90,7 +91,7 @@ typedef struct { git_strmap *values; - struct reader reader; + git_array_t(struct reader) readers; char *file_path; @@ -162,6 +163,7 @@ static void free_vars(git_strmap *values) static int config_open(git_config_backend *cfg, git_config_level_t level) { int res; + struct reader *reader; diskfile_backend *b = (diskfile_backend *)cfg; b->level = level; @@ -169,20 +171,27 @@ static int config_open(git_config_backend *cfg, git_config_level_t level) b->values = git_strmap_alloc(); GITERR_CHECK_ALLOC(b->values); - git_buf_init(&b->reader.buffer, 0); + git_array_init(b->readers); + reader = git_array_alloc(b->readers); + memset(reader, 0, sizeof(struct reader)); + + reader->file_path = git__strdup(b->file_path); + GITERR_CHECK_ALLOC(reader->file_path); + + git_buf_init(&reader->buffer, 0); res = git_futils_readbuffer_updated( - &b->reader.buffer, b->file_path, &b->reader.file_mtime, &b->reader.file_size, NULL); + &reader->buffer, b->file_path, &reader->file_mtime, &reader->file_size, NULL); /* It's fine if the file doesn't exist */ if (res == GIT_ENOTFOUND) return 0; - if (res < 0 || (res = config_parse(b, &b->reader, level, 0)) < 0) { + if (res < 0 || (res = config_parse(b, reader, level, 0)) < 0) { free_vars(b->values); b->values = NULL; } - git_buf_free(&b->reader.buffer); + git_buf_free(&reader->buffer); return res; } @@ -191,9 +200,10 @@ static int config_refresh(git_config_backend *cfg) int res, updated = 0; diskfile_backend *b = (diskfile_backend *)cfg; git_strmap *old_values; + struct reader *reader = git_array_get(b->readers, 0); res = git_futils_readbuffer_updated( - &b->reader.buffer, b->file_path, &b->reader.file_mtime, &b->reader.file_size, &updated); + &reader->buffer, b->file_path, &reader->file_mtime, &reader->file_size, &updated); if (res < 0 || !updated) return (res == GIT_ENOTFOUND) ? 0 : res; @@ -202,25 +212,31 @@ static int config_refresh(git_config_backend *cfg) b->values = git_strmap_alloc(); GITERR_CHECK_ALLOC(b->values); - if ((res = config_parse(b, &b->reader, b->level, 0)) < 0) { + if ((res = config_parse(b, reader, b->level, 0)) < 0) { free_vars(b->values); b->values = old_values; } else { free_vars(old_values); } - git_buf_free(&b->reader.buffer); + git_buf_free(&reader->buffer); return res; } static void backend_free(git_config_backend *_backend) { diskfile_backend *backend = (diskfile_backend *)_backend; + uint32_t i; if (backend == NULL) return; - git__free(backend->reader.file_path); + for (i = 0; i < git_array_size(backend->readers); i++) { + struct reader *r = git_array_get(backend->readers, i); + git__free(r->file_path); + } + git_array_clear(backend->readers); + git__free(backend->file_path); free_vars(backend->values); git__free(backend); @@ -508,10 +524,6 @@ int git_config_file__ondisk(git_config_backend **out, const char *path) backend->file_path = git__strdup(path); GITERR_CHECK_ALLOC(backend->file_path); - /* the reader needs its own copy */ - backend->reader.file_path = git__strdup(path); - GITERR_CHECK_ALLOC(backend->reader.file_path); - backend->parent.open = config_open; backend->parent.get = config_get; backend->parent.set = config_set; @@ -995,11 +1007,12 @@ static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_c } if (!git__strcmp(var->entry->name, "include.path")) { - struct reader r; + struct reader *r; git_buf path = GIT_BUF_INIT; char *dir; - memset(&r, 0, sizeof(r)); + r = git_array_alloc(cfg_file->readers); + memset(r, 0, sizeof(struct reader)); if ((result = git_path_dirname_r(&path, reader->file_path)) < 0) break; @@ -1010,17 +1023,14 @@ static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_c if (result < 0) break; - r.file_path = git_buf_detach(&path); - git_buf_init(&r.buffer, 0); - if ((result = git_futils_readbuffer_updated(&r.buffer, r.file_path, &r.file_mtime, - &r.file_size, NULL)) < 0) { - git__free(r.file_path); + r->file_path = git_buf_detach(&path); + git_buf_init(&r->buffer, 0); + if ((result = git_futils_readbuffer_updated(&r->buffer, r->file_path, &r->file_mtime, + &r->file_size, NULL)) < 0) break; - } - result = config_parse(cfg_file, &r, level, depth+1); - git__free(r.file_path); - git_buf_free(&r.buffer); + result = config_parse(cfg_file, r, level, depth+1); + git_buf_free(&r->buffer); if (result < 0) break; @@ -1074,20 +1084,21 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p const char *pre_end = NULL, *post_start = NULL, *data_start; char *current_section = NULL, *section, *name, *ldot; git_filebuf file = GIT_FILEBUF_INIT; + struct reader *reader = git_array_get(cfg->readers, 0); /* We need to read in our own config file */ - result = git_futils_readbuffer(&cfg->reader.buffer, cfg->file_path); + result = git_futils_readbuffer(&reader->buffer, cfg->file_path); /* Initialise the reading position */ if (result == GIT_ENOTFOUND) { - cfg->reader.read_ptr = NULL; - cfg->reader.eof = 1; + reader->read_ptr = NULL; + reader->eof = 1; data_start = NULL; - git_buf_clear(&cfg->reader.buffer); + git_buf_clear(&reader->buffer); } else if (result == 0) { - cfg->reader.read_ptr = cfg->reader.buffer.ptr; - cfg->reader.eof = 0; - data_start = cfg->reader.read_ptr; + reader->read_ptr = reader->buffer.ptr; + reader->eof = 0; + data_start = reader->read_ptr; } else { return -1; /* OS error when reading the file */ } @@ -1096,13 +1107,13 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p if (git_filebuf_open(&file, cfg->file_path, 0) < 0) return -1; - skip_bom(&cfg->reader); + skip_bom(reader); ldot = strrchr(key, '.'); name = ldot + 1; section = git__strndup(key, ldot - key); - while (!cfg->reader.eof) { - c = reader_peek(&cfg->reader, SKIP_WHITESPACE); + while (!reader->eof) { + c = reader_peek(reader, SKIP_WHITESPACE); if (c == '\0') { /* We've arrived at the end of the file */ break; @@ -1115,11 +1126,11 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p * new section. If we actually want to replace it, the * default case will take care of updating them. */ - pre_end = post_start = cfg->reader.read_ptr; + pre_end = post_start = reader->read_ptr; git__free(current_section); current_section = NULL; - if (parse_section_header(&cfg->reader, ¤t_section) < 0) + if (parse_section_header(reader, ¤t_section) < 0) goto rewrite_fail; /* Keep track of when it stops matching */ @@ -1128,7 +1139,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p } else if (c == ';' || c == '#') { - reader_consume_line(&cfg->reader); + reader_consume_line(reader); } else { @@ -1144,15 +1155,15 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p */ if (!section_matches) { if (!last_section_matched) { - reader_consume_line(&cfg->reader); + reader_consume_line(reader); continue; } } else { int has_matched = 0; char *var_name, *var_value; - pre_end = cfg->reader.read_ptr; - if (parse_variable(&cfg->reader, &var_name, &var_value) < 0) + pre_end = reader->read_ptr; + if (parse_variable(reader, &var_name, &var_value) < 0) goto rewrite_fail; /* First try to match the name of the variable */ @@ -1171,7 +1182,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p if (!has_matched) continue; - post_start = cfg->reader.read_ptr; + post_start = reader->read_ptr; } /* We've found the variable we wanted to change, so @@ -1214,12 +1225,12 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p */ if (write_trailer) { /* Write out rest of the file */ - git_filebuf_write(&file, post_start, cfg->reader.buffer.size - (post_start - data_start)); + git_filebuf_write(&file, post_start, reader->buffer.size - (post_start - data_start)); } else { if (preg_replaced) { git_filebuf_printf(&file, "\n%s", data_start); } else { - git_filebuf_write(&file, cfg->reader.buffer.ptr, cfg->reader.buffer.size); + git_filebuf_write(&file, reader->buffer.ptr, reader->buffer.size); /* And now if we just need to add a variable */ if (!section_matches && write_section(&file, section) < 0) @@ -1235,7 +1246,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p } /* If we are here, there is at least a section line */ - if (cfg->reader.buffer.size > 0 && *(cfg->reader.buffer.ptr + cfg->reader.buffer.size - 1) != '\n') + if (reader->buffer.size > 0 && *(reader->buffer.ptr + reader->buffer.size - 1) != '\n') git_filebuf_write(&file, "\n", 1); git_filebuf_printf(&file, "\t%s = %s\n", name, value); @@ -1246,10 +1257,10 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p git__free(current_section); /* refresh stats - if this errors, then commit will error too */ - (void)git_filebuf_stats(&cfg->reader.file_mtime, &cfg->reader.file_size, &file); + (void)git_filebuf_stats(&reader->file_mtime, &reader->file_size, &file); result = git_filebuf_commit(&file, GIT_CONFIG_FILE_MODE); - git_buf_free(&cfg->reader.buffer); + git_buf_free(&reader->buffer); return result; @@ -1258,7 +1269,7 @@ rewrite_fail: git__free(current_section); git_filebuf_cleanup(&file); - git_buf_free(&cfg->reader.buffer); + git_buf_free(&reader->buffer); return -1; } -- cgit v1.2.1 From a9fb79896e59f4e58cd7d174e7835e8a9c850a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 6 Sep 2013 20:51:35 +0200 Subject: config: refresh included files We need to refresh the variables from the included files if they are changed, so loop over all included files and re-parse the files if any of them has changed. --- src/config_file.c | 21 ++++++++++++++++----- tests-clar/config/include.c | 23 +++++++++++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 3732fd15c..c83576524 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -197,14 +197,25 @@ static int config_open(git_config_backend *cfg, git_config_level_t level) static int config_refresh(git_config_backend *cfg) { - int res, updated = 0; + int res = 0, updated = 0, any_updated = 0; diskfile_backend *b = (diskfile_backend *)cfg; git_strmap *old_values; - struct reader *reader = git_array_get(b->readers, 0); + struct reader *reader; + uint32_t i; - res = git_futils_readbuffer_updated( - &reader->buffer, b->file_path, &reader->file_mtime, &reader->file_size, &updated); - if (res < 0 || !updated) + for (i = 0; i < git_array_size(b->readers); i++) { + reader = git_array_get(b->readers, i); + res = git_futils_readbuffer_updated( + &reader->buffer, reader->file_path, &reader->file_mtime, &reader->file_size, &updated); + + if (res < 0) + return (res == GIT_ENOTFOUND) ? 0 : res; + + if (updated) + any_updated = 1; + } + + if (!any_updated) return (res == GIT_ENOTFOUND) ? 0 : res; /* need to reload - store old values and prep for reload */ diff --git a/tests-clar/config/include.c b/tests-clar/config/include.c index b88a7b2d1..94669a57c 100644 --- a/tests-clar/config/include.c +++ b/tests-clar/config/include.c @@ -48,3 +48,26 @@ void test_config_include__homedir(void) git_config_free(cfg); } + +void test_config_include__refresh(void) +{ + git_config *cfg; + const char *str; + + cl_fixture_sandbox("config"); + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config-include")); + + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); + cl_assert_equal_s(str, "huzzah"); + + /* Change the included file and see if we refresh */ + cl_git_mkfile("config/config-included", "[foo \"bar\"]\nbaz = hurrah"); + cl_git_pass(git_config_refresh(cfg)); + + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); + cl_assert_equal_s(str, "hurrah"); + + git_config_free(cfg); + cl_fixture_cleanup("config"); +} -- cgit v1.2.1 From 73fc5e01c2ad4af7912201fc938b234a2dc854ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 6 Sep 2013 21:12:26 +0200 Subject: config: fix variable overriding When two or more variables of the same name exist and the user asks for a scalar, we must return the latest value assign to it. --- src/config_file.c | 7 ++++++- tests-clar/config/include.c | 22 ++++++++++++++++++++++ tests-clar/config/read.c | 15 +++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/config_file.c b/src/config_file.c index c83576524..48a91eb4e 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -395,6 +395,7 @@ static int config_get(const git_config_backend *cfg, const char *name, const git char *key; khiter_t pos; int error; + cvar_t *var; if ((error = git_config__normalize_name(name, &key)) < 0) return error; @@ -406,7 +407,11 @@ static int config_get(const git_config_backend *cfg, const char *name, const git if (!git_strmap_valid_index(b->values, pos)) return GIT_ENOTFOUND; - *out = ((cvar_t *)git_strmap_value_at(b->values, pos))->entry; + var = git_strmap_value_at(b->values, pos); + while (var->next) + var = var->next; + + *out = var->entry; return 0; } diff --git a/tests-clar/config/include.c b/tests-clar/config/include.c index 94669a57c..f1019a9dc 100644 --- a/tests-clar/config/include.c +++ b/tests-clar/config/include.c @@ -71,3 +71,25 @@ void test_config_include__refresh(void) git_config_free(cfg); cl_fixture_cleanup("config"); } + +/* We need to pretend that the variables were defined where the file was included */ +void test_config_include__ordering(void) +{ + git_config *cfg; + const char *str; + + cl_git_mkfile("included", "[foo \"bar\"]\nbaz = hurrah\nfrotz = hiya"); + cl_git_mkfile("including", + "[foo \"bar\"]\nfrotz = hello\n" + "[include]\npath = included\n" + "[foo \"bar\"]\nbaz = huzzah\n"); + + cl_git_pass(git_config_open_ondisk(&cfg, "including")); + + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.frotz")); + cl_assert_equal_s(str, "hiya"); + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); + cl_assert_equal_s(str, "huzzah"); + + git_config_free(cfg); +} diff --git a/tests-clar/config/read.c b/tests-clar/config/read.c index 395f1cfdb..722a15a71 100644 --- a/tests-clar/config/read.c +++ b/tests-clar/config/read.c @@ -523,3 +523,18 @@ void test_config_read__corrupt_header(void) git_config_free(cfg); } + +void test_config_read__override_variable(void) +{ + git_config *cfg; + const char *str; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "[some] var = one\nvar = two"); + cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig")); + + cl_git_pass(git_config_get_string(&str, cfg, "some.var")); + cl_assert_equal_s(str, "two"); + + git_config_free(cfg); +} -- cgit v1.2.1 From 69789922984d2e22f267da5f35cd64cd17c36dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 7 Sep 2013 18:50:35 +0200 Subject: config: return an error when reaching the maximum include depth --- src/config_file.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 48a91eb4e..034d1d7b1 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -949,9 +949,10 @@ static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_c int result = 0; khiter_t pos; - /* FIXME: should we return an error? */ - if (depth >= MAX_INCLUDE_DEPTH) - return 0; + if (depth >= MAX_INCLUDE_DEPTH) { + giterr_set(GITERR_CONFIG, "Maximum config include depth reached"); + return -1; + } /* Initialize the reading position */ reader->read_ptr = reader->buffer.ptr; -- cgit v1.2.1 From 53ea0513716a8d1e1bc1347cca5a333e26ca9f1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 7 Sep 2013 19:07:39 +0200 Subject: config: handle realloc issues from larger depths As the include depth increases, the chance of a realloc increases. This means that whenever we run git_array_alloc() or call config_parse(), we need to remember what our reader's index is so we can look it up again. --- src/config_file.c | 9 +++++++++ tests-clar/config/include.c | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/config_file.c b/src/config_file.c index 034d1d7b1..bd4fa7471 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -191,6 +191,7 @@ static int config_open(git_config_backend *cfg, git_config_level_t level) b->values = NULL; } + reader = git_array_get(b->readers, 0); git_buf_free(&reader->buffer); return res; } @@ -948,12 +949,14 @@ static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_c git_buf buf = GIT_BUF_INIT; int result = 0; khiter_t pos; + uint32_t reader_idx; if (depth >= MAX_INCLUDE_DEPTH) { giterr_set(GITERR_CONFIG, "Maximum config include depth reached"); return -1; } + reader_idx = git_array_size(cfg_file->readers) - 1; /* Initialize the reading position */ reader->read_ptr = reader->buffer.ptr; reader->eof = 0; @@ -1027,12 +1030,17 @@ static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_c struct reader *r; git_buf path = GIT_BUF_INIT; char *dir; + uint32_t index; r = git_array_alloc(cfg_file->readers); + /* The reader may have been reallocated */ + reader = git_array_get(cfg_file->readers, reader_idx); memset(r, 0, sizeof(struct reader)); if ((result = git_path_dirname_r(&path, reader->file_path)) < 0) break; + /* We need to know out index in the array, as the next config_parse call may realloc */ + index = git_array_size(cfg_file->readers) - 1; dir = git_buf_detach(&path); result = included_path(&path, dir, var->entry->value); git__free(dir); @@ -1047,6 +1055,7 @@ static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_c break; result = config_parse(cfg_file, r, level, depth+1); + r = git_array_get(cfg_file->readers, index); git_buf_free(&r->buffer); if (result < 0) diff --git a/tests-clar/config/include.c b/tests-clar/config/include.c index f1019a9dc..535573808 100644 --- a/tests-clar/config/include.c +++ b/tests-clar/config/include.c @@ -93,3 +93,17 @@ void test_config_include__ordering(void) git_config_free(cfg); } + +/* We need to pretend that the variables were defined where the file was included */ +void test_config_include__depth(void) +{ + git_config *cfg; + + cl_git_mkfile("a", "[include]\npath = b"); + cl_git_mkfile("b", "[include]\npath = a"); + + cl_git_fail(git_config_open_ondisk(&cfg, "a")); + + unlink("a"); + unlink("b"); +} -- cgit v1.2.1 From 031f3f8028835c935d1e75ebd136aaaefffea821 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 7 Sep 2013 22:39:05 +0200 Subject: odb: Error when streaming in too [few|many] bytes --- include/git2/odb.h | 6 +++++ include/git2/odb_backend.h | 13 +++++++--- src/odb.c | 27 +++++++++++++++++++++ tests-clar/odb/streamwrite.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 tests-clar/odb/streamwrite.c diff --git a/include/git2/odb.h b/include/git2/odb.h index 3e93a932c..e50a2a1c1 100644 --- a/include/git2/odb.h +++ b/include/git2/odb.h @@ -238,6 +238,9 @@ GIT_EXTERN(int) git_odb_open_wstream(git_odb_stream **out, git_odb *db, size_t s /** * Write to an odb stream * + * This method will fail as soon as the total number of + * received bytes exceeds the size declared with `git_odb_open_wstream()` + * * @param stream the stream * @param buffer the data to write * @param len the buffer's length @@ -251,6 +254,9 @@ GIT_EXTERN(int) git_odb_stream_write(git_odb_stream *stream, const char *buffer, * The object will take its final name and will be available to the * odb. * + * This method will fail if the total number of received bytes + * differs from the size declared with `git_odb_open_wstream()` + * * @param out pointer to store the resulting object's id * @param stream the stream * @return 0 on success; an error code otherwise diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index bafeec047..e558bbb1c 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -78,6 +78,9 @@ struct git_odb_stream { unsigned int mode; void *hash_ctx; + size_t declared_size; + size_t received_bytes; + /** * Write at most `len` bytes into `buffer` and advance the * stream. @@ -93,9 +96,13 @@ struct git_odb_stream { * Store the contents of the stream as an object with the id * specified in `oid`. * - * This method will *not* be invoked by libgit2 if the object pointed at - * by `oid` already exists in any backend. Libgit2 will however take care - * of properly disposing the stream through a call to `free()`. + * This method will *not* be invoked by libgit2 when: + * - the object pointed at by `oid` already exists in any backend. + * - the total number of received bytes differs from the size declared + * with `git_odb_open_wstream()` + * + * Libgit2 will however take care of properly disposing the stream through + * a call to `free()`. */ int (*finalize_write)(git_odb_stream *stream, const git_oid *oid); diff --git a/src/odb.c b/src/odb.c index dfb252178..2e6869547 100644 --- a/src/odb.c +++ b/src/odb.c @@ -888,17 +888,44 @@ int git_odb_open_wstream( hash_header(ctx, size, type); (*stream)->hash_ctx = ctx; + (*stream)->declared_size = size; + (*stream)->received_bytes = 0; + return error; } +static int git_odb_stream__invalid_length( + const git_odb_stream *stream, + const char *action) +{ + giterr_set(GITERR_ODB, + "Cannot %s - " + "Invalid length. %"PRIuZ" was expected. The " + "total size of the received chunks amounts to %"PRIuZ".", + action, stream->declared_size, stream->received_bytes); + + return -1; +} + int git_odb_stream_write(git_odb_stream *stream, const char *buffer, size_t len) { git_hash_update(stream->hash_ctx, buffer, len); + + stream->received_bytes += len; + + if (stream->received_bytes > stream->declared_size) + return git_odb_stream__invalid_length(stream, + "stream_write()"); + return stream->write(stream, buffer, len); } int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream) { + if (stream->received_bytes != stream->declared_size) + return git_odb_stream__invalid_length(stream, + "stream_finalize_write()"); + git_hash_final(out, stream->hash_ctx); if (git_odb_exists(stream->backend->odb, out)) diff --git a/tests-clar/odb/streamwrite.c b/tests-clar/odb/streamwrite.c new file mode 100644 index 000000000..591a20040 --- /dev/null +++ b/tests-clar/odb/streamwrite.c @@ -0,0 +1,56 @@ +#include "clar_libgit2.h" +#include "git2/odb_backend.h" + +static git_repository *repo; +static git_odb *odb; +static git_odb_stream *stream; + +void test_odb_streamwrite__initialize(void) +{ + repo = cl_git_sandbox_init("testrepo.git"); + cl_git_pass(git_repository_odb(&odb, repo)); + + cl_git_pass(git_odb_open_wstream(&stream, odb, 14, GIT_OBJ_BLOB)); + cl_assert_equal_sz(14, stream->declared_size); +} + +void test_odb_streamwrite__cleanup(void) +{ + git_odb_stream_free(stream); + git_odb_free(odb); + cl_git_sandbox_cleanup(); +} + +void test_odb_streamwrite__can_accept_chunks(void) +{ + git_oid oid; + + cl_git_pass(git_odb_stream_write(stream, "deadbeef", 8)); + cl_assert_equal_sz(8, stream->received_bytes); + + cl_git_pass(git_odb_stream_write(stream, "deadbeef", 6)); + cl_assert_equal_sz(8 + 6, stream->received_bytes); + + cl_git_pass(git_odb_stream_finalize_write(&oid, stream)); +} + +void test_odb_streamwrite__can_detect_missing_bytes(void) +{ + git_oid oid; + + cl_git_pass(git_odb_stream_write(stream, "deadbeef", 8)); + cl_assert_equal_sz(8, stream->received_bytes); + + cl_git_pass(git_odb_stream_write(stream, "deadbeef", 4)); + cl_assert_equal_sz(8 + 4, stream->received_bytes); + + cl_git_fail(git_odb_stream_finalize_write(&oid, stream)); +} + +void test_odb_streamwrite__can_detect_additional_bytes(void) +{ + cl_git_pass(git_odb_stream_write(stream, "deadbeef", 8)); + cl_assert_equal_sz(8, stream->received_bytes); + + cl_git_fail(git_odb_stream_write(stream, "deadbeef", 7)); +} -- cgit v1.2.1 From fbabe855ad6f9a7b2a50a54d0d826d2e65538154 Mon Sep 17 00:00:00 2001 From: Isaac Kearse Date: Sun, 8 Sep 2013 14:11:08 +1200 Subject: Trim leading colon from ssh repository path --- src/transports/ssh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/transports/ssh.c b/src/transports/ssh.c index e0126a8fb..47ea5ccf7 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -51,6 +51,7 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url) repo = strchr(url, '/'); } else { repo = strchr(url, ':'); + repo++; } if (!repo) { -- cgit v1.2.1 From 917e5fa9a18b42bb00140db9112e362bc810aa45 Mon Sep 17 00:00:00 2001 From: John Josef Date: Sun, 8 Sep 2013 18:31:56 -0400 Subject: fixes issues with objective-git --- include/git2/merge.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/git2/merge.h b/include/git2/merge.h index cef6f775b..3f21fb4c8 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -7,11 +7,11 @@ #ifndef INCLUDE_git_merge_h__ #define INCLUDE_git_merge_h__ -#include "git2/common.h" -#include "git2/types.h" -#include "git2/oid.h" -#include "git2/checkout.h" -#include "git2/index.h" +#include "common.h" +#include "types.h" +#include "oid.h" +#include "checkout.h" +#include "index.h" /** * @file git2/merge.h -- cgit v1.2.1 From b345026baaed21ffe8d325f784e597cf6bb779a6 Mon Sep 17 00:00:00 2001 From: Isaac Kearse Date: Tue, 10 Sep 2013 05:16:52 +1200 Subject: Test for repo before removing leading colon --- src/transports/ssh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 47ea5ccf7..bf62bd185 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -51,7 +51,7 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url) repo = strchr(url, '/'); } else { repo = strchr(url, ':'); - repo++; + if (repo) repo++; } if (!repo) { -- cgit v1.2.1 From 4dfe38205b7ddd255c87ff4656720072991fc432 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 9 Sep 2013 10:24:48 -0700 Subject: Comment updates --- include/git2/odb.h | 7 ++++--- include/git2/odb_backend.h | 18 +++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/git2/odb.h b/include/git2/odb.h index e50a2a1c1..3bd18e782 100644 --- a/include/git2/odb.h +++ b/include/git2/odb.h @@ -223,7 +223,8 @@ GIT_EXTERN(int) git_odb_write(git_oid *out, git_odb *odb, const void *data, size * won't be effective until `git_odb_stream_finalize_write` is called * and returns without an error * - * The stream must always be free'd or will leak memory. + * The stream must always be freed when done with `git_odb_stream_free` or + * will leak memory. * * @see git_odb_stream * @@ -238,8 +239,8 @@ GIT_EXTERN(int) git_odb_open_wstream(git_odb_stream **out, git_odb *db, size_t s /** * Write to an odb stream * - * This method will fail as soon as the total number of - * received bytes exceeds the size declared with `git_odb_open_wstream()` + * This method will fail if the total number of received bytes exceeds the + * size declared with `git_odb_open_wstream()` * * @param stream the stream * @param buffer the data to write diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index e558bbb1c..87010f5eb 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -82,8 +82,7 @@ struct git_odb_stream { size_t received_bytes; /** - * Write at most `len` bytes into `buffer` and advance the - * stream. + * Write at most `len` bytes into `buffer` and advance the stream. */ int (*read)(git_odb_stream *stream, char *buffer, size_t len); @@ -96,18 +95,19 @@ struct git_odb_stream { * Store the contents of the stream as an object with the id * specified in `oid`. * - * This method will *not* be invoked by libgit2 when: - * - the object pointed at by `oid` already exists in any backend. - * - the total number of received bytes differs from the size declared - * with `git_odb_open_wstream()` - * - * Libgit2 will however take care of properly disposing the stream through - * a call to `free()`. + * This method might not be invoked if: + * - an error occurs earlier with the `write` callback, + * - the object referred to by `oid` already exists in any backend, or + * - the final number of received bytes differs from the size declared + * with `git_odb_open_wstream()` */ int (*finalize_write)(git_odb_stream *stream, const git_oid *oid); /** * Free the stream's memory. + * + * This method might be called without a call to `finalize_write` if + * an error occurs or if the object is already present in the ODB. */ void (*free)(git_odb_stream *stream); }; -- cgit v1.2.1 From f313843c8a3e9716d030ad0c23ce2194034c7f59 Mon Sep 17 00:00:00 2001 From: John Josef Date: Mon, 9 Sep 2013 13:53:22 -0400 Subject: fixing headers with bad values for objective-c --- include/git2/cred_helpers.h | 2 +- include/git2/odb_backend.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/git2/cred_helpers.h b/include/git2/cred_helpers.h index 5d93cf4dd..1d8809211 100644 --- a/include/git2/cred_helpers.h +++ b/include/git2/cred_helpers.h @@ -7,7 +7,7 @@ #ifndef INCLUDE_git_cred_helpers_h__ #define INCLUDE_git_cred_helpers_h__ -#include "git2/transport.h" +#include "transport.h" /** * @file git2/cred_helpers.h diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index 87010f5eb..a6cb285dc 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -7,8 +7,8 @@ #ifndef INCLUDE_git_odb_backend_h__ #define INCLUDE_git_odb_backend_h__ -#include "git2/common.h" -#include "git2/types.h" +#include "common.h" +#include "types.h" /** * @file git2/backend.h -- cgit v1.2.1 From 62020aa8f999a89df8458dbf50540eb1aee5c97b Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Mon, 2 Sep 2013 02:01:40 +0200 Subject: Adding add example. --- examples/add.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 examples/add.c diff --git a/examples/add.c b/examples/add.c new file mode 100644 index 000000000..b4bc6a166 --- /dev/null +++ b/examples/add.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include + +enum print_options { + SKIP = 1, + VERBOSE = 2, +}; + +struct print_payload { + enum print_options options; + git_repository *repo; +}; + +void init_array(git_strarray *array, int argc, char **argv) +{ + unsigned int i; + + array->count = argc; + array->strings = malloc(sizeof(char*) * array->count); + assert(array->strings!=NULL); + + for(i=0; icount; i++) { + array->strings[i]=argv[i]; + } + + return; +} + +int print_matched_cb(const char *path, const char *matched_pathspec, void *payload) +{ + (void)matched_pathspec; + + struct print_payload p = *(struct print_payload*)(payload); + int ret; + git_status_t status; + + if (git_status_file(&status, p.repo, path)) { + return -1; //abort + } + + if (status & GIT_STATUS_WT_MODIFIED || + status & GIT_STATUS_WT_NEW) { + if (p.options & VERBOSE || p.options & SKIP) { + printf("add '%s'\n", path); + } + ret = 0; + } else { + ret = 1; + } + + if(p.options & SKIP) { + ret = 1; + } + + return ret; +} + +int main (int argc, char** argv) +{ + git_index_matched_path_cb matched_cb = NULL; + git_repository *repo = NULL; + git_index *index; + git_strarray array = {0}; + int i, options = 0; + struct print_payload payload = {0}; + + if (argc < 2) { + fprintf(stderr, "usage: add file-spec [file-spec] [...]\n"); + return 1; + } + + for (i = 1; i < argc; ++i) { + if (argv[i][0] != '-') { + break; + } + else if(!strcmp(argv[i], "--verbose") || !strcmp(argv[i], "-v")) { + options |= VERBOSE; + } + else if(!strcmp(argv[i], "--dry-run") || !strcmp(argv[i], "-n")) { + options |= SKIP; + } + else if(!strcmp(argv[i], "--")) { + break; + } + else { + fprintf(stderr, "Unsupported option %s.\n", argv[i]); + return 1; + } + } + + init_array(&array, argc-i, argv+i); + + printf("args:\n"); + for(i=0; i Date: Tue, 3 Sep 2013 19:11:50 +0200 Subject: Supported options information in add example. --- examples/add.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/add.c b/examples/add.c index b4bc6a166..f1e7b7b7e 100644 --- a/examples/add.c +++ b/examples/add.c @@ -67,7 +67,7 @@ int main (int argc, char** argv) struct print_payload payload = {0}; if (argc < 2) { - fprintf(stderr, "usage: add file-spec [file-spec] [...]\n"); + fprintf(stderr, "usage: add [-n|--dry-run] [-v|--verbose] file-spec [file-spec] [...]\n"); return 1; } -- cgit v1.2.1 From 24d23220969a976c9a6ede2993837715824cac64 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Wed, 4 Sep 2013 18:34:03 +0200 Subject: Add -u option to add example. --- examples/add.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/add.c b/examples/add.c index f1e7b7b7e..12e660d43 100644 --- a/examples/add.c +++ b/examples/add.c @@ -6,6 +6,7 @@ enum print_options { SKIP = 1, VERBOSE = 2, + UPDATE = 4, }; struct print_payload { @@ -67,7 +68,7 @@ int main (int argc, char** argv) struct print_payload payload = {0}; if (argc < 2) { - fprintf(stderr, "usage: add [-n|--dry-run] [-v|--verbose] file-spec [file-spec] [...]\n"); + fprintf(stderr, "usage: add [-n|--dry-run] [-v|--verbose] [-u|--update] file-spec [file-spec] [...]\n"); return 1; } @@ -81,6 +82,9 @@ int main (int argc, char** argv) else if(!strcmp(argv[i], "--dry-run") || !strcmp(argv[i], "-n")) { options |= SKIP; } + else if(!strcmp(argv[i], "--update") || !strcmp(argv[i], "-u")) { + options |= UPDATE; + } else if(!strcmp(argv[i], "--")) { break; } @@ -111,7 +115,12 @@ int main (int argc, char** argv) payload.options = options; payload.repo = repo; - git_index_add_all(index, &array, 0, matched_cb, &payload); + + if (options&UPDATE) { + git_index_update_all(index, &array, matched_cb, &payload); + } else { + git_index_add_all(index, &array, 0, matched_cb, &payload); + } git_index_write(index); git_index_free(index); -- cgit v1.2.1 From 813937ce4e99f8ba208548ef557a776bbc7029f9 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Wed, 4 Sep 2013 18:42:47 +0200 Subject: Better usage info in add example. --- examples/add.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/examples/add.c b/examples/add.c index 12e660d43..f2a33f959 100644 --- a/examples/add.c +++ b/examples/add.c @@ -58,6 +58,15 @@ int print_matched_cb(const char *path, const char *matched_pathspec, void *paylo return ret; } +void print_usage(void) +{ + fprintf(stderr, "usage: add [options] [--] file-spec [file-spec] [...]\n\n"); + fprintf(stderr, "\t-n, --dry-run dry run\n"); + fprintf(stderr, "\t-v, --verbose be verbose\n"); + fprintf(stderr, "\t-u, --update update tracked files\n"); +} + + int main (int argc, char** argv) { git_index_matched_path_cb matched_cb = NULL; @@ -67,11 +76,6 @@ int main (int argc, char** argv) int i, options = 0; struct print_payload payload = {0}; - if (argc < 2) { - fprintf(stderr, "usage: add [-n|--dry-run] [-v|--verbose] [-u|--update] file-spec [file-spec] [...]\n"); - return 1; - } - for (i = 1; i < argc; ++i) { if (argv[i][0] != '-') { break; @@ -85,22 +89,31 @@ int main (int argc, char** argv) else if(!strcmp(argv[i], "--update") || !strcmp(argv[i], "-u")) { options |= UPDATE; } + else if(!strcmp(argv[i], "-h")) { + print_usage(); + break; + } else if(!strcmp(argv[i], "--")) { + i++; break; } else { fprintf(stderr, "Unsupported option %s.\n", argv[i]); + print_usage(); return 1; } } - - init_array(&array, argc-i, argv+i); printf("args:\n"); for(i=0; i Date: Wed, 4 Sep 2013 18:43:14 +0200 Subject: Remove unnececery arguments priting in add example. --- examples/add.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/add.c b/examples/add.c index f2a33f959..5e59b2b92 100644 --- a/examples/add.c +++ b/examples/add.c @@ -104,9 +104,6 @@ int main (int argc, char** argv) } } - printf("args:\n"); - for(i=0; i Date: Wed, 4 Sep 2013 18:44:12 +0200 Subject: Move statement after declarations in add example. --- examples/add.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/add.c b/examples/add.c index 5e59b2b92..96595f895 100644 --- a/examples/add.c +++ b/examples/add.c @@ -31,11 +31,10 @@ void init_array(git_strarray *array, int argc, char **argv) int print_matched_cb(const char *path, const char *matched_pathspec, void *payload) { - (void)matched_pathspec; - struct print_payload p = *(struct print_payload*)(payload); int ret; git_status_t status; + (void)matched_pathspec; if (git_status_file(&status, p.repo, path)) { return -1; //abort -- cgit v1.2.1 From b2395a826780c84640c3bd5d3ccec51d34086524 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Wed, 4 Sep 2013 18:49:10 +0200 Subject: Only use callbacks when -n or -v in add example. --- examples/add.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/add.c b/examples/add.c index 96595f895..cab57dca7 100644 --- a/examples/add.c +++ b/examples/add.c @@ -42,9 +42,7 @@ int print_matched_cb(const char *path, const char *matched_pathspec, void *paylo if (status & GIT_STATUS_WT_MODIFIED || status & GIT_STATUS_WT_NEW) { - if (p.options & VERBOSE || p.options & SKIP) { - printf("add '%s'\n", path); - } + printf("add '%s'\n", path); ret = 0; } else { ret = 1; @@ -120,7 +118,9 @@ int main (int argc, char** argv) return 1; } - matched_cb = &print_matched_cb; + if (options&VERBOSE || options&SKIP) { + matched_cb = &print_matched_cb; + } payload.options = options; payload.repo = repo; -- cgit v1.2.1 From 0c52b204c5a792cb9515e93fdea35811ae09807b Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 9 Sep 2013 11:07:17 -0700 Subject: Make work if built with threading enabled --- examples/add.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/add.c b/examples/add.c index cab57dca7..a0edf4376 100644 --- a/examples/add.c +++ b/examples/add.c @@ -106,6 +106,8 @@ int main (int argc, char** argv) return 1; } + git_threads_init(); + init_array(&array, argc-i, argv+i); if (git_repository_open(&repo, ".") < 0) { @@ -135,5 +137,7 @@ int main (int argc, char** argv) git_index_free(index); git_repository_free(repo); + git_threads_shutdown(); + return 0; } -- cgit v1.2.1 From 15f7b9b8d9bdfb68ca52d582be40cf6112464e77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sun, 8 Sep 2013 00:52:26 +0200 Subject: revwalk: allow simplifying by first-parent When enabled, only the first parent of each commit will be queued, enabling a simple way of using first-parent simplification. --- include/git2/revwalk.h | 8 +++++++ src/revwalk.c | 22 +++++++++++++++---- src/revwalk.h | 3 ++- tests-clar/revwalk/simplify.c | 51 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 tests-clar/revwalk/simplify.c diff --git a/include/git2/revwalk.h b/include/git2/revwalk.h index 8bfe0b502..c59b79938 100644 --- a/include/git2/revwalk.h +++ b/include/git2/revwalk.h @@ -231,6 +231,14 @@ GIT_EXTERN(void) git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode); */ GIT_EXTERN(int) git_revwalk_push_range(git_revwalk *walk, const char *range); +/** + * Simplify the history by first-parent + * + * No parents other than the first for each commit will be enqueued. + */ +GIT_EXTERN(void) git_revwalk_simplify_first_parent(git_revwalk *walk); + + /** * Free a revision walker previously allocated. * diff --git a/src/revwalk.c b/src/revwalk.c index 1ff41bfb1..9e1e39ca4 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -99,10 +99,14 @@ static int process_commit(git_revwalk *walk, git_commit_list_node *commit, int h static int process_commit_parents(git_revwalk *walk, git_commit_list_node *commit) { - unsigned short i; + unsigned short i, max; int error = 0; - for (i = 0; i < commit->out_degree && !error; ++i) + max = commit->out_degree; + if (walk->first_parent && commit->out_degree) + max = 1; + + for (i = 0; i < max && !error; ++i) error = process_commit(walk, commit->parents[i], commit->uninteresting); return error; @@ -333,7 +337,7 @@ static int revwalk_next_unsorted(git_commit_list_node **object_out, git_revwalk static int revwalk_next_toposort(git_commit_list_node **object_out, git_revwalk *walk) { git_commit_list_node *next; - unsigned short i; + unsigned short i, max; for (;;) { next = git_commit_list_pop(&walk->iterator_topo); @@ -347,7 +351,12 @@ static int revwalk_next_toposort(git_commit_list_node **object_out, git_revwalk continue; } - for (i = 0; i < next->out_degree; ++i) { + + max = next->out_degree; + if (walk->first_parent && next->out_degree) + max = 1; + + for (i = 0; i < max; ++i) { git_commit_list_node *parent = next->parents[i]; if (--parent->in_degree == 0 && parent->topo_delay) { @@ -505,6 +514,11 @@ void git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode) } } +void git_revwalk_simplify_first_parent(git_revwalk *walk) +{ + walk->first_parent = 1; +} + int git_revwalk_next(git_oid *oid, git_revwalk *walk) { int error; diff --git a/src/revwalk.h b/src/revwalk.h index 22696dfcd..8c821d098 100644 --- a/src/revwalk.h +++ b/src/revwalk.h @@ -31,7 +31,8 @@ struct git_revwalk { int (*get_next)(git_commit_list_node **, git_revwalk *); int (*enqueue)(git_revwalk *, git_commit_list_node *); - unsigned walking:1; + unsigned walking:1, + first_parent: 1; unsigned int sorting; /* merge base calculation */ diff --git a/tests-clar/revwalk/simplify.c b/tests-clar/revwalk/simplify.c new file mode 100644 index 000000000..c94952105 --- /dev/null +++ b/tests-clar/revwalk/simplify.c @@ -0,0 +1,51 @@ +#include "clar_libgit2.h" + +/* + * a4a7dce [0] Merge branch 'master' into br2 + |\ + | * 9fd738e [1] a fourth commit + | * 4a202b3 [2] a third commit + * | c47800c [3] branch commit one + |/ + * 5b5b025 [5] another commit + * 8496071 [4] testing +*/ +static const char *commit_head = "a4a7dce85cf63874e984719f4fdd239f5145052f"; + +static const char *expected_str[] = { + "a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */ + "c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */ + "8496071c1b46c854b31185ea97743be6a8774479", /* 4 */ + "5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */ +}; + +void test_revwalk_simplify__first_parent(void) +{ + git_repository *repo; + git_revwalk *walk; + git_oid id, expected[4]; + int i, error; + + for (i = 0; i < 4; i++) { + git_oid_fromstr(&expected[i], expected_str[i]); + } + + repo = cl_git_sandbox_init("testrepo.git"); + cl_git_pass(git_revwalk_new(&walk, repo)); + + git_oid_fromstr(&id, commit_head); + cl_git_pass(git_revwalk_push(walk, &id)); + git_revwalk_simplify_first_parent(walk); + + i = 0; + while ((error = git_revwalk_next(&id, walk)) == 0) { + git_oid_cmp(&id, &expected[i]); + i++; + } + + cl_assert_equal_i(i, 4); + cl_assert_equal_i(error, GIT_ITEROVER); + + git_revwalk_free(walk); + git_repository_free(repo); +} -- cgit v1.2.1 From d0cd6c427a35b257373c7178d1e17d82001e125f Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sun, 8 Sep 2013 18:22:28 +0200 Subject: path: Make direach() return EUSER on callback error --- src/fileops.c | 30 +++++++++++++++++++++--------- src/odb_pack.c | 2 +- src/path.c | 4 ++-- src/refdb_fs.c | 2 +- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 92cda82e7..126d45f26 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -869,6 +869,7 @@ typedef struct { uint32_t flags; uint32_t mkdir_flags; mode_t dirmode; + int error; } cp_r_info; #define GIT_CPDIR__MKDIR_DONE_FOR_TO_ROOT (1u << 10) @@ -907,20 +908,23 @@ static int _cp_r_callback(void *ref, git_buf *from) return 0; if (git_buf_joinpath( - &info->to, info->to_root, from->ptr + info->from_prefix) < 0) - return -1; + &info->to, info->to_root, from->ptr + info->from_prefix) < 0) { + error = -1; + goto exit; + } if (p_lstat(info->to.ptr, &to_st) < 0) { if (errno != ENOENT && errno != ENOTDIR) { giterr_set(GITERR_OS, "Could not access %s while copying files", info->to.ptr); - return -1; + error = -1; + goto exit; } } else exists = true; if ((error = git_path_lstat(from->ptr, &from_st)) < 0) - return error; + goto exit; if (S_ISDIR(from_st.st_mode)) { mode_t oldmode = info->dirmode; @@ -934,13 +938,14 @@ static int _cp_r_callback(void *ref, git_buf *from) error = _cp_r_mkdir(info, from); /* recurse onto target directory */ - if (!error && (!exists || S_ISDIR(to_st.st_mode))) - error = git_path_direach(from, _cp_r_callback, info); + if (!error && (!exists || S_ISDIR(to_st.st_mode)) && + ((error = git_path_direach(from, _cp_r_callback, info)) == GIT_EUSER)) + error = info->error; if (oldmode != 0) info->dirmode = oldmode; - return error; + goto exit; } if (exists) { @@ -950,7 +955,8 @@ static int _cp_r_callback(void *ref, git_buf *from) if (p_unlink(info->to.ptr) < 0) { giterr_set(GITERR_OS, "Cannot overwrite existing file '%s'", info->to.ptr); - return -1; + error = -1; + goto exit; } } @@ -963,7 +969,7 @@ static int _cp_r_callback(void *ref, git_buf *from) /* Make container directory on demand if needed */ if ((info->flags & GIT_CPDIR_CREATE_EMPTY_DIRS) == 0 && (error = _cp_r_mkdir(info, from)) < 0) - return error; + goto exit; /* make symlink or regular file */ if (S_ISLNK(from_st.st_mode)) @@ -977,6 +983,8 @@ static int _cp_r_callback(void *ref, git_buf *from) error = git_futils_cp(from->ptr, info->to.ptr, usemode); } +exit: + info->error = error; return error; } @@ -997,6 +1005,7 @@ int git_futils_cp_r( info.flags = flags; info.dirmode = dirmode; info.from_prefix = path.size; + info.error = 0; git_buf_init(&info.to, 0); /* precalculate mkdir flags */ @@ -1018,6 +1027,9 @@ int git_futils_cp_r( git_buf_free(&path); git_buf_free(&info.to); + if (error == GIT_EUSER) + error = info.error; + return error; } diff --git a/src/odb_pack.c b/src/odb_pack.c index d24b4aa99..cadc93a65 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -336,7 +336,7 @@ static int pack_backend__refresh(git_odb_backend *_backend) git_buf_free(&path); if (error < 0) - return error; + return -1; git_vector_sort(&backend->packs); return 0; diff --git a/src/path.c b/src/path.c index 7c1ec2cd0..56b0b49ca 100644 --- a/src/path.c +++ b/src/path.c @@ -765,10 +765,10 @@ int git_path_direach( git_buf_truncate(path, wd_len); /* restore path */ - if (result < 0) { + if (result) { closedir(dir); git__free(de_buf); - return -1; + return GIT_EUSER; } } diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 04516a5b0..894ff7c84 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -299,7 +299,7 @@ static int packed_loadloose(refdb_fs_backend *backend) git_buf_free(&refs_path); - return error; + return (error == GIT_EUSER) ? -1 : error; } static int refdb_fs_backend__exists( -- cgit v1.2.1 From 209f9b67c4f9b2c5bba26f2bdcbee10cf4e25a6b Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sun, 8 Sep 2013 18:25:17 +0200 Subject: odb: Teach loose backend to return EAMBIGUOUS --- src/odb_loose.c | 8 ++++++-- tests-clar/refs/revparse.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/odb_loose.c b/src/odb_loose.c index ce63f4673..4ff57158d 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -499,7 +499,7 @@ static int fn_locate_object_short_oid(void *state, git_buf *pathbuf) { } if (sstate->found > 1) - return git_odb__error_ambiguous("multiple matches in loose objects"); + return GIT_EAMBIGUOUS; return 0; } @@ -545,12 +545,16 @@ static int locate_object_short_oid( /* Explore directory to find a unique object matching short_oid */ error = git_path_direach( object_location, fn_locate_object_short_oid, &state); - if (error) + + if (error && error != GIT_EUSER) return error; if (!state.found) return git_odb__error_notfound("no matching loose object for prefix", short_oid); + if (state.found > 1) + return git_odb__error_ambiguous("multiple matches in loose objects"); + /* Convert obtained hex formatted oid to raw */ error = git_oid_fromstr(res_oid, (char *)state.res_oid); if (error) diff --git a/tests-clar/refs/revparse.c b/tests-clar/refs/revparse.c index 9657054de..37d3981bb 100644 --- a/tests-clar/refs/revparse.c +++ b/tests-clar/refs/revparse.c @@ -544,6 +544,37 @@ void test_refs_revparse__a_too_short_objectid_returns_EAMBIGUOUS(void) GIT_EAMBIGUOUS, git_revparse_single(&g_obj, g_repo, "e90")); } +/* + * $ echo "aabqhq" | git hash-object -t blob --stdin + * dea509d0b3cb8ee0650f6ca210bc83f4678851ba + * + * $ echo "aaazvc" | git hash-object -t blob --stdin + * dea509d097ce692e167dfc6a48a7a280cc5e877e + */ +void test_refs_revparse__a_not_precise_enough_objectid_returns_EAMBIGUOUS(void) +{ + git_repository *repo; + git_index *index; + git_object *obj; + + repo = cl_git_sandbox_init("testrepo"); + + cl_git_mkfile("testrepo/one.txt", "aabqhq\n"); + cl_git_mkfile("testrepo/two.txt", "aaazvc\n"); + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_bypath(index, "one.txt")); + cl_git_pass(git_index_add_bypath(index, "two.txt")); + + cl_git_fail_with(git_revparse_single(&obj, repo, "dea509d0"), GIT_EAMBIGUOUS); + + cl_git_pass(git_revparse_single(&obj, repo, "dea509d09")); + + git_object_free(obj); + git_index_free(index); + cl_git_sandbox_cleanup(); +} + void test_refs_revparse__issue_994(void) { git_repository *repo; -- cgit v1.2.1 From 8cf805253407e35627aa86f79b17070279106322 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Wed, 11 Sep 2013 20:13:59 +0200 Subject: errors: Fix format of some error messages --- src/odb.c | 2 +- src/reflog.c | 2 +- src/revparse.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/odb.c b/src/odb.c index 2e6869547..a0bfec403 100644 --- a/src/odb.c +++ b/src/odb.c @@ -445,7 +445,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; } diff --git a/src/reflog.c b/src/reflog.c index 4cc20d2c7..a6752f618 100644 --- a/src/reflog.c +++ b/src/reflog.c @@ -484,7 +484,7 @@ int git_reflog_drop( 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/revparse.c b/src/revparse.c index 3dde22ce1..e470a954d 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -217,7 +217,7 @@ static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, size_t ide if (numentries < identifier + 1) { 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); error = GIT_ENOTFOUND; -- cgit v1.2.1 From 273ddc54f5818b73725298f17915a307bd7c884b Mon Sep 17 00:00:00 2001 From: nulltoken Date: Thu, 12 Sep 2013 13:50:00 +0200 Subject: clar: Fix clar__assert_equal error message formating --- tests-clar/clar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests-clar/clar.c b/tests-clar/clar.c index 5189e7919..6c7399a54 100644 --- a/tests-clar/clar.c +++ b/tests-clar/clar.c @@ -468,7 +468,7 @@ void clar__assert_equal( } } } - else if (!strcmp(PRIuZ, fmt) || !strcmp(PRIxZ, fmt)) { + else if (!strcmp("%"PRIuZ, fmt) || !strcmp("%"PRIxZ, fmt)) { size_t sz1 = va_arg(args, size_t), sz2 = va_arg(args, size_t); is_equal = (sz1 == sz2); if (!is_equal) { -- cgit v1.2.1 From 6f2003612c27ffbcc865059e57e257ed92acb722 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Thu, 12 Sep 2013 13:50:35 +0200 Subject: clar: Move cl_assert_equal_sz() definition to clar.h --- tests-clar/clar.h | 1 + tests-clar/clar_libgit2.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests-clar/clar.h b/tests-clar/clar.h index e1f244eba..c40bc7ac9 100644 --- a/tests-clar/clar.h +++ b/tests-clar/clar.h @@ -68,6 +68,7 @@ void cl_fixture_cleanup(const char *fixture_name); #define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2)) +#define cl_assert_equal_sz(sz1,sz2) clar__assert_equal(__FILE__,__LINE__,#sz1 " != " #sz2, 1, "%"PRIuZ, (size_t)(sz1), (size_t)(sz2)) void clar__fail( const char *file, diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index 3cb0607f1..8dcfdee48 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -32,8 +32,6 @@ void cl_git_report_failure(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) -#define cl_assert_equal_sz(sz1,sz2) clar__assert_equal(__FILE__,__LINE__,#sz1 " != " #sz2, 1, PRIuZ, (size_t)(sz1), (size_t)(sz2)) - GIT_INLINE(void) clar__assert_in_range( int lo, int val, int hi, const char *file, int line, const char *err, int should_abort) -- cgit v1.2.1 From 4e01e3029b389dc45a040b794ceeeb0cbe32004a Mon Sep 17 00:00:00 2001 From: wilke Date: Fri, 13 Sep 2013 21:21:33 +0200 Subject: Prevent git_tree_walk 'skip entry' callback return code from leaking through as the return value of git_tree_walk --- src/tree.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tree.c b/src/tree.c index f9469195a..cd8adfb96 100644 --- a/src/tree.c +++ b/src/tree.c @@ -881,8 +881,10 @@ static int tree_walk( git_vector_foreach(&tree->entries, i, entry) { if (preorder) { error = callback(path->ptr, entry, payload); - if (error > 0) + if (error > 0) { + error = 0; continue; + } if (error < 0) { giterr_clear(); return GIT_EUSER; -- cgit v1.2.1 From d7fc2eb29b4574b96b190572470bfcb7dab9d078 Mon Sep 17 00:00:00 2001 From: wilke Date: Fri, 13 Sep 2013 21:36:39 +0200 Subject: Fix memory leak in git_tree_walk on error or when stopping the walk from the supplied callback --- src/tree.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tree.c b/src/tree.c index cd8adfb96..0bdf9a93e 100644 --- a/src/tree.c +++ b/src/tree.c @@ -907,11 +907,12 @@ static int tree_walk( return -1; error = tree_walk(subtree, callback, path, payload, preorder); + git_tree_free(subtree); + if (error != 0) break; git_buf_truncate(path, path_len); - git_tree_free(subtree); } if (!preorder && callback(path->ptr, entry, payload) < 0) { -- cgit v1.2.1 From e580afd8634c99449b0ed6e8113873518359c2c5 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 13 Sep 2013 14:33:26 -0700 Subject: Add tests for git_tree_walk This tests the fixes for issues from #1849 --- tests-clar/object/tree/walk.c | 74 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/tests-clar/object/tree/walk.c b/tests-clar/object/tree/walk.c index b7af4924d..1207e864c 100644 --- a/tests-clar/object/tree/walk.c +++ b/tests-clar/object/tree/walk.c @@ -101,3 +101,77 @@ void test_object_tree_walk__1(void) git_tree_free(tree); } + + +struct treewalk_skip_data { + int files; + int dirs; + const char *skip; + const char *stop; +}; + +static int treewalk_skip_de_cb( + const char *root, const git_tree_entry *entry, void *payload) +{ + struct treewalk_skip_data *data = payload; + const char *name = git_tree_entry_name(entry); + + GIT_UNUSED(root); + + if (git_tree_entry_type(entry) == GIT_OBJ_TREE) + data->dirs++; + else + data->files++; + + if (data->skip && !strcmp(name, data->skip)) + return 1; + else if (data->stop && !strcmp(name, data->stop)) + return -1; + else + return 0; +} + +void test_object_tree_walk__2(void) +{ + git_oid id; + git_tree *tree; + struct treewalk_skip_data data; + + /* look up a deep tree */ + git_oid_fromstr(&id, "ae90f12eea699729ed24555e40b9fd669da12a12"); + cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); + + memset(&data, 0, sizeof(data)); + data.skip = "de"; + + cl_assert_equal_i(0, git_tree_walk( + tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); + cl_assert_equal_i(5, data.files); + cl_assert_equal_i(3, data.dirs); + + memset(&data, 0, sizeof(data)); + data.stop = "3.txt"; + + cl_assert_equal_i(GIT_EUSER, git_tree_walk( + tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); + cl_assert_equal_i(3, data.files); + cl_assert_equal_i(2, data.dirs); + + memset(&data, 0, sizeof(data)); + data.skip = "new.txt"; + + cl_assert_equal_i(0, git_tree_walk( + tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); + cl_assert_equal_i(7, data.files); + cl_assert_equal_i(4, data.dirs); + + memset(&data, 0, sizeof(data)); + data.stop = "new.txt"; + + cl_assert_equal_i(GIT_EUSER, git_tree_walk( + tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); + cl_assert_equal_i(7, data.files); + cl_assert_equal_i(4, data.dirs); + + git_tree_free(tree); +} -- cgit v1.2.1 From f2df503bab6ae6e77ff0bbe17f358822be51b944 Mon Sep 17 00:00:00 2001 From: Linquize Date: Sat, 14 Sep 2013 18:22:16 +0800 Subject: git_clone supports optional init_options --- include/git2/clone.h | 1 + src/clone.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index 5858b4e32..580352ac1 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -67,6 +67,7 @@ typedef struct git_clone_options { unsigned int version; git_checkout_opts checkout_opts; + git_repository_init_options *init_options; int bare; git_transfer_progress_callback fetch_progress_cb; void *fetch_progress_payload; diff --git a/src/clone.c b/src/clone.c index 5c11872cc..5b8fc5e45 100644 --- a/src/clone.c +++ b/src/clone.c @@ -418,7 +418,7 @@ static bool should_checkout( return !git_repository_head_orphan(repo); } -static void normalize_options(git_clone_options *dst, const git_clone_options *src) +static void normalize_options(git_clone_options *dst, const git_clone_options *src, git_repository_init_options *initOptions) { git_clone_options default_options = GIT_CLONE_OPTIONS_INIT; if (!src) src = &default_options; @@ -427,6 +427,13 @@ static void normalize_options(git_clone_options *dst, const git_clone_options *s /* Provide defaults for null pointers */ if (!dst->remote_name) dst->remote_name = "origin"; + if (!dst->init_options) + { + dst->init_options = initOptions; + initOptions->flags = GIT_REPOSITORY_INIT_MKPATH; + if (dst->bare) + initOptions->flags |= GIT_REPOSITORY_INIT_BARE; + } } int git_clone( @@ -439,10 +446,11 @@ int git_clone( git_repository *repo = NULL; git_clone_options normOptions; int remove_directory_on_failure = 0; + git_repository_init_options initOptions = GIT_REPOSITORY_INIT_OPTIONS_INIT; assert(out && url && local_path); - normalize_options(&normOptions, options); + normalize_options(&normOptions, options, &initOptions); GITERR_CHECK_VERSION(&normOptions, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); /* Only clone to a new directory or an empty directory */ @@ -455,7 +463,7 @@ int git_clone( /* Only remove the directory on failure if we create it */ remove_directory_on_failure = !git_path_exists(local_path); - if (!(retcode = git_repository_init(&repo, local_path, normOptions.bare))) { + if (!(retcode = git_repository_init_ext(&repo, local_path, normOptions.init_options))) { if ((retcode = setup_remotes_and_fetch(repo, url, &normOptions)) < 0) { /* Failed to fetch; clean up */ git_repository_free(repo); -- cgit v1.2.1 From c62b5ca590fb2f1743f43439b04159b168a36dda Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 16 Sep 2013 22:23:05 +0200 Subject: clone: Anal as fuck --- src/clone.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/clone.c b/src/clone.c index 5b8fc5e45..9f47e07b6 100644 --- a/src/clone.c +++ b/src/clone.c @@ -427,8 +427,7 @@ static void normalize_options(git_clone_options *dst, const git_clone_options *s /* Provide defaults for null pointers */ if (!dst->remote_name) dst->remote_name = "origin"; - if (!dst->init_options) - { + if (!dst->init_options) { dst->init_options = initOptions; initOptions->flags = GIT_REPOSITORY_INIT_MKPATH; if (dst->bare) -- cgit v1.2.1 From b622aabec0d8cf659f9a1f458f728f76e4090a81 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Fri, 9 Aug 2013 13:14:06 +0200 Subject: Add a wrapper to provide the libssh2 error message --- include/git2/errors.h | 1 + src/transports/ssh.c | 34 +++++++++++++++++++++------------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/include/git2/errors.h b/include/git2/errors.h index 0f0bddf07..6b47e00e8 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -67,6 +67,7 @@ typedef enum { GITERR_CHECKOUT, GITERR_FETCHHEAD, GITERR_MERGE, + GITERR_SSH, } git_error_t; /** diff --git a/src/transports/ssh.c b/src/transports/ssh.c index bf62bd185..4fb4719f2 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -37,6 +37,14 @@ typedef struct { git_cred *cred; } ssh_subtransport; +static void ssh_error(LIBSSH2_SESSION *session, const char *errmsg) +{ + char *ssherr; + libssh2_session_last_error(session, &ssherr, NULL, 0); + + giterr_set(GITERR_SSH, "%s: %s", errmsg, ssherr); +} + /* * Create a git protocol request. * @@ -81,8 +89,8 @@ static int send_command(ssh_stream *s) goto cleanup; error = libssh2_channel_exec(s->channel, request.ptr); - if (error < 0) { - giterr_set(GITERR_NET, "SSH could not execute request"); + if (error < LIBSSH2_ERROR_NONE) { + ssh_error(s->session, "SSH could not execute request"); goto cleanup; } @@ -107,8 +115,8 @@ static int ssh_stream_read( if (!s->sent_command && send_command(s) < 0) return -1; - if ((rc = libssh2_channel_read(s->channel, buffer, buf_size)) < 0) { - giterr_set(GITERR_NET, "SSH could not read data"); + if ((rc = libssh2_channel_read(s->channel, buffer, buf_size)) < LIBSSH2_ERROR_NONE) { + ssh_error(s->session, "SSH could not read data");; return -1; } @@ -127,8 +135,8 @@ static int ssh_stream_write( if (!s->sent_command && send_command(s) < 0) return -1; - if (libssh2_channel_write(s->channel, buffer, len) < 0) { - giterr_set(GITERR_NET, "SSH could not write data"); + if (libssh2_channel_write(s->channel, buffer, len) < LIBSSH2_ERROR_NONE) { + ssh_error(s->session, "SSH could not write data"); return -1; } @@ -262,8 +270,8 @@ static int _git_ssh_authenticate_session( } } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); - if (rc != 0) { - giterr_set(GITERR_NET, "Failed to authenticate SSH session"); + if (rc != LIBSSH2_ERROR_NONE) { + ssh_error(session, "Failed to authenticate SSH session"); return -1; } @@ -289,9 +297,9 @@ static int _git_ssh_session_create( rc = libssh2_session_startup(s, socket.socket); } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); - if (0 != rc) { + if (rc != LIBSSH2_ERROR_NONE) { + ssh_error(s, "Failed to start SSH session"); libssh2_session_free(s); - giterr_set(GITERR_NET, "Failed to start SSH session"); return -1; } @@ -346,11 +354,11 @@ static int _git_ssh_setup_conn( goto on_error; if (!t->cred) { - giterr_set(GITERR_NET, "Callback failed to initialize SSH credentials"); + giterr_set(GITERR_SSH, "Callback failed to initialize SSH credentials"); goto on_error; } } else { - giterr_set(GITERR_NET, "Cannot set up SSH connection without credentials"); + giterr_set(GITERR_SSH, "Cannot set up SSH connection without credentials"); goto on_error; } assert(t->cred); @@ -368,7 +376,7 @@ static int _git_ssh_setup_conn( channel = libssh2_channel_open_session(session); if (!channel) { - giterr_set(GITERR_NET, "Failed to open SSH channel"); + ssh_error(session, "Failed to open SSH channel"); goto on_error; } -- cgit v1.2.1 From eec4dcc34b511606ae9386baa3831f3a624c6fde Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Fri, 9 Aug 2013 13:14:19 +0200 Subject: Whitespace. --- src/transports/ssh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 4fb4719f2..62f3f0bbf 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -220,7 +220,7 @@ static int git_ssh_extract_url_parts( at = strchr(url, '@'); if (at) { - start = at+1; + start = at + 1; *username = git__substrdup(url, at - url); GITERR_CHECK_ALLOC(*username); } else { -- cgit v1.2.1 From ceab4e260637dc8374d0348ee9a078ab1c16e4ad Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 16 Sep 2013 16:20:38 -0700 Subject: Port blame from git.git --- include/git2/blame.h | 69 ++- include/git2/object.h | 19 +- src/blame.c | 492 +++++++++++++++++ src/blame.h | 37 ++ src/blame_git.c | 591 +++++++++++++++++++++ src/blame_git.h | 93 ++++ src/object.c | 36 ++ tests-clar/blame/blame_helpers.c | 58 ++ tests-clar/blame/blame_helpers.h | 15 + tests-clar/blame/buffer.c | 130 +++++ tests-clar/blame/getters.c | 56 ++ tests-clar/blame/harder.c | 71 +++ tests-clar/blame/simple.c | 204 +++++++ tests-clar/object/lookupbypath.c | 83 +++ tests-clar/resources/blametest.git/HEAD | 1 + tests-clar/resources/blametest.git/config | 5 + tests-clar/resources/blametest.git/description | 1 + .../0c/bab4d45fd61e55a1c9697f9f9cb07a12e15448 | Bin 0 -> 46 bytes .../1a/ac69ae5d96461afc4d81d0066cb12f5b05a35b | Bin 0 -> 28 bytes .../1b/5f0775af166331c854bd8d1bca3450eaf2532a | Bin 0 -> 35 bytes .../48/2f2c370e35c2c314fc1f96db2beb33f955a26a | Bin 0 -> 35 bytes .../63/d671eb32d250e4a83766ebbc60e818c1e1e93a | 3 + .../63/eb57322e363e18d460da5ea8284f3cd2340b36 | Bin 0 -> 76 bytes .../8b/137891791fe96927ad78e64b0aad7bded08bdc | Bin 0 -> 16 bytes .../96/679d59cf9f74d69b3c920f258559b5e8c9a18a | Bin 0 -> 47 bytes .../98/89d6e5557761aa8e3607e80c874a6dc51ada7c | Bin 0 -> 43 bytes .../aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 | 1 + .../b1/76dfc3a4dc8734e4c579f77236a9c8d0a965d2 | Bin 0 -> 76 bytes .../b9/0bb887b7c03750ae6b352ffe76ab9d2e86ee7d | Bin 0 -> 56 bytes .../b9/9f7ac0b88909253d829554c14af488c3b0f3a5 | 2 + .../bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 | 3 + .../cf/e0e1e1e3ba18f149fd47f5e1aef6016b2260c3 | Bin 0 -> 76 bytes .../d0/67729932057cdb7527a833d6799c4ddc520640 | 1 + .../da/237394e6132d20d30f175b9b73c8638fddddda | 4 + .../e5/b41c1ea533f87388ab69b13baf0b5a562d6243 | Bin 0 -> 76 bytes .../ef/32df4d259143933715c74951f932d9892364d1 | Bin 0 -> 42 bytes .../resources/blametest.git/refs/heads/master | 1 + 37 files changed, 1946 insertions(+), 30 deletions(-) create mode 100644 src/blame.c create mode 100644 src/blame.h create mode 100644 src/blame_git.c create mode 100644 src/blame_git.h create mode 100644 tests-clar/blame/blame_helpers.c create mode 100644 tests-clar/blame/blame_helpers.h create mode 100644 tests-clar/blame/buffer.c create mode 100644 tests-clar/blame/getters.c create mode 100644 tests-clar/blame/harder.c create mode 100644 tests-clar/blame/simple.c create mode 100644 tests-clar/object/lookupbypath.c create mode 100644 tests-clar/resources/blametest.git/HEAD create mode 100644 tests-clar/resources/blametest.git/config create mode 100644 tests-clar/resources/blametest.git/description create mode 100644 tests-clar/resources/blametest.git/objects/0c/bab4d45fd61e55a1c9697f9f9cb07a12e15448 create mode 100644 tests-clar/resources/blametest.git/objects/1a/ac69ae5d96461afc4d81d0066cb12f5b05a35b create mode 100644 tests-clar/resources/blametest.git/objects/1b/5f0775af166331c854bd8d1bca3450eaf2532a create mode 100644 tests-clar/resources/blametest.git/objects/48/2f2c370e35c2c314fc1f96db2beb33f955a26a create mode 100644 tests-clar/resources/blametest.git/objects/63/d671eb32d250e4a83766ebbc60e818c1e1e93a create mode 100644 tests-clar/resources/blametest.git/objects/63/eb57322e363e18d460da5ea8284f3cd2340b36 create mode 100644 tests-clar/resources/blametest.git/objects/8b/137891791fe96927ad78e64b0aad7bded08bdc create mode 100644 tests-clar/resources/blametest.git/objects/96/679d59cf9f74d69b3c920f258559b5e8c9a18a create mode 100644 tests-clar/resources/blametest.git/objects/98/89d6e5557761aa8e3607e80c874a6dc51ada7c create mode 100644 tests-clar/resources/blametest.git/objects/aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 create mode 100644 tests-clar/resources/blametest.git/objects/b1/76dfc3a4dc8734e4c579f77236a9c8d0a965d2 create mode 100644 tests-clar/resources/blametest.git/objects/b9/0bb887b7c03750ae6b352ffe76ab9d2e86ee7d create mode 100644 tests-clar/resources/blametest.git/objects/b9/9f7ac0b88909253d829554c14af488c3b0f3a5 create mode 100644 tests-clar/resources/blametest.git/objects/bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 create mode 100644 tests-clar/resources/blametest.git/objects/cf/e0e1e1e3ba18f149fd47f5e1aef6016b2260c3 create mode 100644 tests-clar/resources/blametest.git/objects/d0/67729932057cdb7527a833d6799c4ddc520640 create mode 100644 tests-clar/resources/blametest.git/objects/da/237394e6132d20d30f175b9b73c8638fddddda create mode 100644 tests-clar/resources/blametest.git/objects/e5/b41c1ea533f87388ab69b13baf0b5a562d6243 create mode 100644 tests-clar/resources/blametest.git/objects/ef/32df4d259143933715c74951f932d9892364d1 create mode 100644 tests-clar/resources/blametest.git/refs/heads/master diff --git a/include/git2/blame.h b/include/git2/blame.h index 443b33503..fe1311362 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -36,6 +36,8 @@ typedef enum { /** Track lines that have been copied from another file that exists in *any* * commit (like `git blame -CCC`) */ GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<1 | 1<<2 | 1<<3), + /** Track through file renames */ + GIT_BLAME_TRACK_FILE_RENAMES = (1<<4), } git_blame_flag_t; /** @@ -51,15 +53,14 @@ typedef enum { * associate those lines with the parent commit. The default value is 20. * This value only takes effect if any of the `GIT_BLAME_TRACK_COPIES_*` * flags are specified. - * - `newest_commit` is a rev-parse spec that resolves to the most recent - * commit to consider. The default is HEAD. - * - `newest_commit` is the newest commit to consider. The default is HEAD. - * - `oldest_commit` is the oldest commit to consider. The default is the - * first commit encountered with a NULL parent. + * - `newest_commit` is the id of the newest commit to consider. The default + * is HEAD. + * - `oldest_commit` is the id of the oldest commit to consider. The default + * is the first commit encountered with a NULL parent. * - `min_line` is the first line in the file to blame. The default is 1 (line - * numbers start with 1). + * numbers start with 1). * - `max_line` is the last line in the file to blame. The default is the last - * line of the file. + * line of the file. */ typedef struct git_blame_options { @@ -67,8 +68,8 @@ typedef struct git_blame_options { uint32_t flags; uint16_t min_match_characters; - git_commit *newest_commit; - git_commit *oldest_commit; + git_oid newest_commit; + git_oid oldest_commit; uint32_t min_line; uint32_t max_line; } git_blame_options; @@ -105,39 +106,40 @@ typedef struct git_blame_hunk { } git_blame_hunk; -typedef struct git_blame_results git_blame_results; +/* Opaque structure to hold blame results */ +typedef struct git_blame git_blame; /** - * Gets the number of hunks that exist in the results structure. + * Gets the number of hunks that exist in the blame structure. */ -GIT_EXTERN(uint32_t) git_blame_results_hunk_count(git_blame_results *results); +GIT_EXTERN(uint32_t) git_blame_get_hunk_count(git_blame *blame); /** * Gets the blame hunk at the given index. * - * @param results the results structure to query + * @param blame the blame structure to query * @param index index of the hunk to retrieve * @return the hunk at the given index, or NULL on error */ -GIT_EXTERN(const git_blame_hunk*) git_blame_results_hunk_byindex( - git_blame_results *results, +GIT_EXTERN(const git_blame_hunk*) git_blame_get_hunk_byindex( + git_blame *blame, uint32_t index); /** * Gets the hunk that relates to the given line number in the newest commit. * - * @param results the results structure to query + * @param blame the blame structure to query * @param lineno the (1-based) line number to find a hunk for * @return the hunk that contains the given line, or NULL on error */ -GIT_EXTERN(const git_blame_hunk*) git_blame_results_hunk_byline( - git_blame_results *results, +GIT_EXTERN(const git_blame_hunk*) git_blame_get_hunk_byline( + git_blame *blame, uint32_t lineno); /** * Get the blame for a single file. * - * @param out pointer that will receive the results object + * @param out pointer that will receive the blame object * @param repo repository whose history is to be walked * @param path path to file to consider * @param options options for the blame operation. If NULL, this is treated as @@ -146,32 +148,41 @@ GIT_EXTERN(const git_blame_hunk*) git_blame_results_hunk_byline( * about the error.) */ GIT_EXTERN(int) git_blame_file( - git_blame_results **out, + git_blame **out, git_repository *repo, const char *path, git_blame_options *options); /** - * Get blame data for a file that has been modified. + * Get blame data for a file that has been modified in memory. The `reference` + * parameter is a pre-calculated blame for the in-odb history of the file. This + * means that once a file blame is completed (which can be expensive), updating + * the buffer blame is very fast. * - * @param out pointer that will receive the results object - * @param reference output from git_blame_file for the file in question + * Lines that differ between the buffer and the committed version are marked as + * having a zero OID for their final_commit_id. + * + * @param out pointer that will receive the resulting blame data + * @param reference cached blame from the history of the file (usually the output + * from git_blame_file) * @param buffer the (possibly) modified contents of the file + * @param buffer_len number of valid bytes in the buffer * @return 0 on success, or an error code. (use giterr_last for information * about the error) */ GIT_EXTERN(int) git_blame_buffer( - git_blame_results **out, - git_blame_results *reference, - const char *buffer); + git_blame **out, + git_blame *reference, + const char *buffer, + size_t buffer_len); /** - * Free memory allocated by git_blame. + * Free memory allocated by git_blame_file or git_blame_buffer. * - * @param results results structure to free + * @param blame the blame structure to free */ -GIT_EXTERN(void) git_blame_free(git_blame_results *results); +GIT_EXTERN(void) git_blame_free(git_blame *blame); /** @} */ GIT_END_DECL diff --git a/include/git2/object.h b/include/git2/object.h index f74f3dfd1..7ec17cd8e 100644 --- a/include/git2/object.h +++ b/include/git2/object.h @@ -36,7 +36,7 @@ GIT_BEGIN_DECL * @param repo the repository to look up the object * @param id the unique identifier for the object * @param type the type of the object - * @return 0 or an error code + * @return a reference to the object */ GIT_EXTERN(int) git_object_lookup( git_object **object, @@ -78,6 +78,23 @@ GIT_EXTERN(int) git_object_lookup_prefix( size_t len, git_otype type); + +/** + * Lookup an object that represents a tree entry. + * + * @param out buffer that receives a pointer to the object (which must be freed + * by the caller) + * @param treeish root object that can be peeled to a tree + * @param path relative path from the root object to the desired object + * @param type type of object desired + * @return 0 on success, or an error code + */ +GIT_EXTERN(int) git_object_lookup_bypath( + git_object **out, + const git_object *treeish, + const char *path, + git_otype type); + /** * Get the id (SHA1) of a repository object * diff --git a/src/blame.c b/src/blame.c new file mode 100644 index 000000000..30d65f02c --- /dev/null +++ b/src/blame.c @@ -0,0 +1,492 @@ +/* + * 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 "blame.h" +#include "git2/commit.h" +#include "git2/revparse.h" +#include "git2/revwalk.h" +#include "git2/tree.h" +#include "git2/diff.h" +#include "git2/blob.h" +#include "util.h" +#include "repository.h" +#include "blame_git.h" + + +static int hunk_search_cmp_helper(const void *key, size_t start_line, size_t num_lines) +{ + uint32_t lineno = *(size_t*)key; + if (lineno < start_line) + return -1; + if (lineno >= ((uint32_t)start_line + num_lines)) + return 1; + return 0; +} +static int hunk_byfinalline_search_cmp(const void *key, const void *entry) +{ + git_blame_hunk *hunk = (git_blame_hunk*)entry; + return hunk_search_cmp_helper(key, hunk->final_start_line_number, hunk->lines_in_hunk); +} +static int hunk_sort_cmp_by_start_line(const void *_a, const void *_b) +{ + git_blame_hunk *a = (git_blame_hunk*)_a, + *b = (git_blame_hunk*)_b; + + return a->final_start_line_number - b->final_start_line_number; +} + +static bool hunk_ends_at_or_before_line(git_blame_hunk *hunk, size_t line) +{ + return line >= (size_t)(hunk->final_start_line_number + hunk->lines_in_hunk - 1); +} + +static bool hunk_starts_at_or_after_line(git_blame_hunk *hunk, size_t line) +{ + return line <= hunk->final_start_line_number; +} + +static git_blame_hunk* new_hunk(uint16_t start, uint16_t lines, uint16_t orig_start, const char *path) +{ + git_blame_hunk *hunk = git__calloc(1, sizeof(git_blame_hunk)); + if (!hunk) return NULL; + + hunk->lines_in_hunk = lines; + hunk->final_start_line_number = start; + hunk->orig_start_line_number = orig_start; + hunk->orig_path = path ? git__strdup(path) : NULL; + + return hunk; +} + +git_blame_hunk* git_blame__alloc_hunk() +{ + return new_hunk(0,0,0,NULL); +} + +static git_blame_hunk* dup_hunk(git_blame_hunk *hunk) +{ + git_blame_hunk *newhunk = new_hunk(hunk->final_start_line_number, hunk->lines_in_hunk, hunk->orig_start_line_number, hunk->orig_path); + git_oid_cpy(&newhunk->orig_commit_id, &hunk->orig_commit_id); + git_oid_cpy(&newhunk->final_commit_id, &hunk->final_commit_id); + return newhunk; +} + +static void free_hunk(git_blame_hunk *hunk) +{ + git__free((void*)hunk->orig_path); + git__free(hunk); +} + +/* Starting with the hunk that includes start_line, shift all following hunks' + * final_start_line by shift_by lines */ +static void shift_hunks_by_final(git_vector *v, size_t start_line, int shift_by) +{ + size_t i; + + if (!git_vector_bsearch2( &i, v, hunk_byfinalline_search_cmp, &start_line)) { + for (; i < v->length; i++) { + git_blame_hunk *hunk = (git_blame_hunk*)v->contents[i]; + hunk->final_start_line_number += shift_by; + } + } +} +static int paths_cmp(const void *a, const void *b) { return git__strcmp((char*)a, (char*)b); } +git_blame* git_blame__alloc( + git_repository *repo, + git_blame_options opts, + const char *path) +{ + git_blame *gbr = (git_blame*)git__calloc(1, sizeof(git_blame)); + if (!gbr) { + giterr_set_oom(); + return NULL; + } + git_vector_init(&gbr->hunks, 8, hunk_sort_cmp_by_start_line); + git_vector_init(&gbr->unclaimed_hunks, 8, hunk_sort_cmp_by_start_line); + git_vector_init(&gbr->paths, 8, paths_cmp); + gbr->repository = repo; + gbr->options = opts; + gbr->path = git__strdup(path); + git_vector_insert(&gbr->paths, git__strdup(path)); + gbr->final_blob = NULL; + return gbr; +} + +void git_blame_free(git_blame *blame) +{ + size_t i; + git_blame_hunk *hunk; + char *path; + + if (!blame) return; + + git_vector_foreach(&blame->hunks, i, hunk) + free_hunk(hunk); + git_vector_free(&blame->hunks); + + git_vector_foreach(&blame->unclaimed_hunks, i, hunk) + free_hunk(hunk); + git_vector_free(&blame->unclaimed_hunks); + + git_vector_foreach(&blame->paths, i, path) + git__free(path); + git_vector_free(&blame->paths); + + git__free((void*)blame->path); + git_blob_free(blame->final_blob); + git__free(blame); +} + +uint32_t git_blame_get_hunk_count(git_blame *blame) +{ + assert(blame); + return blame->hunks.length; +} + +const git_blame_hunk *git_blame_get_hunk_byindex(git_blame *blame, uint32_t index) +{ + assert(blame); + return (git_blame_hunk*)git_vector_get(&blame->hunks, index); +} + +const git_blame_hunk *git_blame_get_hunk_byline(git_blame *blame, uint32_t lineno) +{ + size_t i; + assert(blame); + + if (!git_vector_bsearch2( &i, &blame->hunks, hunk_byfinalline_search_cmp, &lineno)) { + return git_blame_get_hunk_byindex(blame, i); + } + + return NULL; +} + +static void normalize_options( + git_blame_options *out, + const git_blame_options *in, + git_repository *repo) +{ + git_blame_options dummy = GIT_BLAME_OPTIONS_INIT; + if (!in) in = &dummy; + + memcpy(out, in, sizeof(git_blame_options)); + + /* No newest_commit => HEAD */ + if (git_oid_iszero(&out->newest_commit)) { + git_reference_name_to_id(&out->newest_commit, repo, "HEAD"); + } +} + +static git_blame_hunk *split_hunk_in_vector( + git_vector *vec, + git_blame_hunk *hunk, + size_t rel_line, + bool return_new) +{ + size_t new_line_count; + git_blame_hunk *nh; + + /* Don't split if already at a boundary */ + if (rel_line <= 0 || + rel_line >= hunk->lines_in_hunk) + { + return hunk; + } + + new_line_count = hunk->lines_in_hunk - rel_line; + nh = new_hunk(hunk->final_start_line_number+rel_line, new_line_count, + hunk->orig_start_line_number+rel_line, hunk->orig_path); + git_oid_cpy(&nh->final_commit_id, &hunk->final_commit_id); + git_oid_cpy(&nh->orig_commit_id, &hunk->orig_commit_id); + + /* Adjust hunk that was split */ + hunk->lines_in_hunk -= new_line_count; + git_vector_insert_sorted(vec, nh, NULL); + { + git_blame_hunk *ret = return_new ? nh : hunk; + return ret; + } +} + + +/* + * To allow quick access to the contents of nth line in the + * final image, prepare an index in the scoreboard. + */ +static int prepare_lines(struct scoreboard *sb) +{ + const char *buf = sb->final_buf; + git_off_t len = sb->final_buf_size; + int num = 0, incomplete = 0, bol = 1; + + if (len && buf[len-1] != '\n') + incomplete++; /* incomplete line at the end */ + while (len--) { + if (bol) { + bol = 0; + } + if (*buf++ == '\n') { + num++; + bol = 1; + } + } + sb->num_lines = num + incomplete; + return sb->num_lines; +} + +static git_blame_hunk* hunk_from_entry(struct blame_entry *e) +{ + git_blame_hunk *h = new_hunk( + e->lno+1, e->num_lines, e->s_lno+1, e->suspect->path); + git_oid_cpy(&h->final_commit_id, git_commit_id(e->suspect->commit)); + return h; +} + +static void free_if_not_already_freed(git_vector *already, struct origin *o) +{ + size_t i; + + if (!o) return; + if (!git_vector_search(&i, already, o)) + return; + + git_vector_insert(already, o); + free_if_not_already_freed(already, o->previous); + git_blob_free(o->blob); + git_commit_free(o->commit); + git__free(o); +} + +static int walk_and_mark(git_blame *blame) +{ + int error; + + struct scoreboard sb = {0}; + struct blame_entry *ent = NULL; + git_blob *blob = NULL; + struct origin *o; + git_vector already = GIT_VECTOR_INIT; + + if ((error = git_commit_lookup(&sb.final, blame->repository, &blame->options.newest_commit)) < 0 || + (error = git_object_lookup_bypath((git_object**)&blob, (git_object*)sb.final, blame->path, GIT_OBJ_BLOB)) < 0) + goto cleanup; + sb.final_buf = git_blob_rawcontent(blob); + sb.final_buf_size = git_blob_rawsize(blob); + if ((error = get_origin(&o, &sb, sb.final, blame->path)) < 0) + goto cleanup; + + ent = git__calloc(1, sizeof(*ent)); + ent->num_lines = prepare_lines(&sb); + ent->suspect = o; + sb.ent = ent; + sb.path = blame->path; + sb.blame = blame; + + assign_blame(&sb, blame->options.flags); + coalesce(&sb); + + for (ent = sb.ent; ent; ) { + git_vector_insert(&blame->hunks, hunk_from_entry(ent)); + ent = ent->next; + } + +cleanup: + for (ent = sb.ent; ent; ) { + struct blame_entry *e = ent->next; + struct origin *o = ent->suspect; + + /* Linkages might not be ordered, so we only free pointers we haven't + * seen before. */ + free_if_not_already_freed(&already, o); + + git__free(ent); + ent = e; + } + + git_vector_free(&already); + git_commit_free(sb.final); + git_blob_free(blob); + return error; +} + +static int load_blob(git_blame *blame, git_repository *repo, git_oid *commit_id, const char *path) +{ + int retval = -1; + git_commit *commit = NULL; + git_tree *tree = NULL; + git_tree_entry *tree_entry = NULL; + git_object *obj = NULL; + + if (((retval = git_commit_lookup(&commit, repo, commit_id)) < 0) || + ((retval = git_object_lookup_bypath(&obj, (git_object*)commit, path, GIT_OBJ_BLOB)) < 0) || + ((retval = git_object_type(obj)) != GIT_OBJ_BLOB)) + goto cleanup; + blame->final_blob = (git_blob*)obj; + +cleanup: + git_tree_entry_free(tree_entry); + git_tree_free(tree); + git_commit_free(commit); + return retval; +} + +/******************************************************************************* + * File blaming + ******************************************************************************/ + +int git_blame_file( + git_blame **out, + git_repository *repo, + const char *path, + git_blame_options *options) +{ + int error = -1; + git_blame_options normOptions = GIT_BLAME_OPTIONS_INIT; + git_blame *blame = NULL; + + assert(out && repo && path); + normalize_options(&normOptions, options, repo); + + blame = git_blame__alloc(repo, normOptions, path); + GITERR_CHECK_ALLOC(blame); + + if ((error = load_blob(blame, repo, &normOptions.newest_commit, path)) < 0) + goto on_error; + + if ((error = walk_and_mark(blame)) < 0) + goto on_error; + + *out = blame; + return 0; + +on_error: + git_blame_free(blame); + return error; +} + +/******************************************************************************* + * Buffer blaming + *******************************************************************************/ + +static bool hunk_is_bufferblame(git_blame_hunk *hunk) +{ + return git_oid_iszero(&hunk->final_commit_id); +} + +static int buffer_hunk_cb( + const git_diff_delta *delta, + const git_diff_range *range, + const char *header, + size_t header_len, + void *payload) +{ + git_blame *blame = (git_blame*)payload; + size_t wedge_line; + + GIT_UNUSED(delta); + GIT_UNUSED(header); + GIT_UNUSED(header_len); + + wedge_line = (range->old_lines == 0) ? range->new_start : range->old_start; + blame->current_diff_line = wedge_line; + + /* If this hunk doesn't start between existing hunks, split a hunk up so it does */ + blame->current_hunk = (git_blame_hunk*)git_blame_get_hunk_byline(blame, wedge_line); + if (!hunk_starts_at_or_after_line(blame->current_hunk, wedge_line)){ + blame->current_hunk = split_hunk_in_vector(&blame->hunks, blame->current_hunk, + wedge_line - blame->current_hunk->orig_start_line_number, true); + } + + return 0; +} + +static int ptrs_equal_cmp(const void *a, const void *b) { return ab ? 1 : 0; } +static int buffer_line_cb( + const git_diff_delta *delta, + const git_diff_range *range, + char line_origin, + const char *content, + size_t content_len, + void *payload) +{ + git_blame *blame = (git_blame*)payload; + + GIT_UNUSED(delta); + GIT_UNUSED(range); + GIT_UNUSED(content); + GIT_UNUSED(content_len); + +#ifdef DO_DEBUG + { + char *str = git__substrdup(content, content_len); + git__free(str); + } +#endif + + if (line_origin == GIT_DIFF_LINE_ADDITION) { + if (hunk_is_bufferblame(blame->current_hunk) && + hunk_ends_at_or_before_line(blame->current_hunk, blame->current_diff_line)) { + /* Append to the current buffer-blame hunk */ + blame->current_hunk->lines_in_hunk++; + shift_hunks_by_final(&blame->hunks, blame->current_diff_line+1, 1); + } else { + /* Create a new buffer-blame hunk with this line */ + shift_hunks_by_final(&blame->hunks, blame->current_diff_line, 1); + blame->current_hunk = new_hunk(blame->current_diff_line, 1, 0, blame->path); + git_vector_insert_sorted(&blame->hunks, blame->current_hunk, NULL); + } + blame->current_diff_line++; + } + + if (line_origin == GIT_DIFF_LINE_DELETION) { + /* Trim the line from the current hunk; remove it if it's now empty */ + size_t shift_base = blame->current_diff_line + blame->current_hunk->lines_in_hunk+1; + + if (--(blame->current_hunk->lines_in_hunk) == 0) { + size_t i; + shift_base--; + if (!git_vector_search2(&i, &blame->hunks, ptrs_equal_cmp, blame->current_hunk)) { + git_vector_remove(&blame->hunks, i); + free_hunk(blame->current_hunk); + blame->current_hunk = (git_blame_hunk*)git_blame_get_hunk_byindex(blame, i); + } + } + shift_hunks_by_final(&blame->hunks, shift_base, -1); + } + return 0; +} + +int git_blame_buffer( + git_blame **out, + git_blame *reference, + const char *buffer, + size_t buffer_len) +{ + git_blame *blame; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + size_t i; + git_blame_hunk *hunk; + + diffopts.context_lines = 0; + + assert(out && reference && buffer && buffer_len); + + blame = git_blame__alloc(reference->repository, reference->options, reference->path); + + /* Duplicate all of the hunk structures in the reference blame */ + git_vector_foreach(&reference->hunks, i, hunk) { + git_vector_insert(&blame->hunks, dup_hunk(hunk)); + } + + /* Diff to the reference blob */ + git_diff_blob_to_buffer(reference->final_blob, blame->path, + buffer, buffer_len, blame->path, + &diffopts, NULL, buffer_hunk_cb, buffer_line_cb, blame); + + *out = blame; + return 0; +} diff --git a/src/blame.h b/src/blame.h new file mode 100644 index 000000000..260d5b5a1 --- /dev/null +++ b/src/blame.h @@ -0,0 +1,37 @@ +#ifndef INCLUDE_blame_h__ +#define INCLUDE_blame_h__ + +#include "git2/blame.h" +#include "common.h" +#include "vector.h" +#include "diff.h" +#include "array.h" +#include "git2/oid.h" + +struct git_blame { + const char *path; + git_repository *repository; + git_blame_options options; + + git_vector hunks; + git_vector unclaimed_hunks; + git_vector paths; + + git_blob *final_blob; + size_t num_lines; + + git_oid current_commit; + git_oid parent_commit; + size_t current_diff_line; + size_t current_blame_line; + git_blame_hunk *current_hunk; +}; + +git_blame *git_blame__alloc( + git_repository *repo, + git_blame_options opts, + const char *path); + +git_blame_hunk *git_blame__alloc_hunk(); + +#endif diff --git a/src/blame_git.c b/src/blame_git.c new file mode 100644 index 000000000..0dae2d9c1 --- /dev/null +++ b/src/blame_git.c @@ -0,0 +1,591 @@ +/* + * 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 "blame_git.h" +#include "commit.h" + +/* + * Locate an existing origin or create a new one. + */ +int get_origin(struct origin **out, struct scoreboard *sb, git_commit *commit, const char *path) +{ + struct blame_entry *e; + + for (e = sb->ent; e; e = e->next) + if (e->suspect->commit == commit && !strcmp(e->suspect->path, path)) + *out = origin_incref(e->suspect); + return make_origin(out, commit, path); +} + +/* + * Given a commit and a path in it, create a new origin structure. + * The callers that add blame to the scoreboard should use + * get_origin() to obtain shared, refcounted copy instead of calling + * this function directly. + */ +int make_origin(struct origin **out, git_commit *commit, const char *path) +{ + int error = 0; + struct origin *o; + o = git__calloc(1, sizeof(*o) + strlen(path) + 1); + GITERR_CHECK_ALLOC(o); + o->commit = commit; + o->refcnt = 1; + strcpy(o->path, path); + + if (!(error = git_object_lookup_bypath((git_object**)&o->blob, (git_object*)commit, + path, GIT_OBJ_BLOB))) + *out = o; + else + origin_decref(o); + return error; +} + +struct blame_chunk_cb_data { + struct scoreboard *sb; + struct origin *target; + struct origin *parent; + long plno; + long tlno; +}; + +static bool same_suspect(struct origin *a, struct origin *b) +{ + if (a == b) + return true; + if (git_oid_cmp(git_commit_id(a->commit), git_commit_id(b->commit))) + return false; + return 0 == strcmp(a->path, b->path); +} + +/* Find the line number of the last line the target is suspected for */ +static int find_last_in_target(struct scoreboard *sb, struct origin *target) +{ + struct blame_entry *e; + int last_in_target = -1; + + for (e=sb->ent; e; e=e->next) { + if (e->guilty || !same_suspect(e->suspect, target)) + continue; + if (last_in_target < e->s_lno + e->num_lines) + last_in_target = e->s_lno + e->num_lines; + } + return last_in_target; +} + +/* + * It is known that lines between tlno to same came from parent, and e + * has an overlap with that range. it also is known that parent's + * line plno corresponds to e's line tlno. + * + * <---- e -----> + * <------> + * <------------> + * <------------> + * <------------------> + * + * Split e into potentially three parts; before this chunk, the chunk + * to be blamed for the parent, and after that portion. + */ +static void split_overlap(struct blame_entry *split, struct blame_entry *e, + int tlno, int plno, int same, struct origin *parent) +{ + int chunk_end_lno; + + if (e->s_lno < tlno) { + /* there is a pre-chunk part not blamed on the parent */ + split[0].suspect = origin_incref(e->suspect); + split[0].lno = e->lno; + split[0].s_lno = e->s_lno; + split[0].num_lines = tlno - e->s_lno; + split[1].lno = e->lno + tlno - e->s_lno; + split[1].s_lno = plno; + } else { + split[1].lno = e->lno; + split[1].s_lno = plno + (e->s_lno - tlno); + } + + if (same < e->s_lno + e->num_lines) { + /* there is a post-chunk part not blamed on parent */ + split[2].suspect = origin_incref(e->suspect); + split[2].lno = e->lno + (same - e->s_lno); + split[2].s_lno = e->s_lno + (same - e->s_lno); + split[2].num_lines = e->s_lno + e->num_lines - same; + chunk_end_lno = split[2].lno; + } else { + chunk_end_lno = e->lno + e->num_lines; + } + split[1].num_lines = chunk_end_lno - split[1].lno; + + /* + * if it turns out there is nothing to blame the parent for, forget about + * the splitting. !split[1].suspect signals this. + */ + if (split[1].num_lines < 1) + return; + split[1].suspect = origin_incref(parent); +} + +/* + * Link in a new blame entry to the scoreboard. Entries that cover the same + * line range have been removed from the scoreboard previously. + */ +static void add_blame_entry(struct scoreboard *sb, struct blame_entry *e) +{ + struct blame_entry *ent, *prev = NULL; + + origin_incref(e->suspect); + + for (ent = sb->ent; ent && ent->lno < e->lno; ent = ent->next) + prev = ent; + + /* prev, if not NULL, is the last one that is below e */ + e->prev = prev; + if (prev) { + e->next = prev->next; + prev->next = e; + } else { + e->next = sb->ent; + sb->ent = e; + } + if (e->next) + e->next->prev = e; +} + +/* + * src typically is on-stack; we want to copy the information in it to + * a malloced blame_entry that is already on the linked list of the scoreboard. + * The origin of dst loses a refcnt while the origin of src gains one. + */ +static void dup_entry(struct blame_entry *dst, struct blame_entry *src) +{ + struct blame_entry *p, *n; + + p = dst->prev; + n = dst->next; + origin_incref(src->suspect); + origin_decref(dst->suspect); + memcpy(dst, src, sizeof(*src)); + dst->prev = p; + dst->next = n; + dst->score = 0; +} + +/* + * split_overlap() divided an existing blame e into up to three parts in split. + * Adjust the linked list of blames in the scoreboard to reflect the split. + */ +static void split_blame(struct scoreboard *sb, struct blame_entry *split, struct blame_entry *e) +{ + struct blame_entry *new_entry; + + if (split[0].suspect && split[2].suspect) { + /* The first part (reuse storage for the existing entry e */ + dup_entry(e, &split[0]); + + /* The last part -- me */ + new_entry = git__malloc(sizeof(*new_entry)); + memcpy(new_entry, &(split[2]), sizeof(struct blame_entry)); + add_blame_entry(sb, new_entry); + + /* ... and the middle part -- parent */ + new_entry = git__malloc(sizeof(*new_entry)); + memcpy(new_entry, &(split[1]), sizeof(struct blame_entry)); + add_blame_entry(sb, new_entry); + } else if (!split[0].suspect && !split[2].suspect) { + /* + * The parent covers the entire area; reuse storage for e and replace it + * with the parent + */ + dup_entry(e, &split[1]); + } else if (split[0].suspect) { + /* me and then parent */ + dup_entry(e, &split[0]); + new_entry = git__malloc(sizeof(*new_entry)); + memcpy(new_entry, &(split[1]), sizeof(struct blame_entry)); + add_blame_entry(sb, new_entry); + } else { + /* parent and then me */ + dup_entry(e, &split[1]); + new_entry = git__malloc(sizeof(*new_entry)); + memcpy(new_entry, &(split[2]), sizeof(struct blame_entry)); + add_blame_entry(sb, new_entry); + } +} + +/* + * After splitting the blame, the origins used by the on-stack blame_entry + * should lose one refcnt each. + */ +static void decref_split(struct blame_entry *split) +{ + int i; + for (i=0; i<3; i++) + origin_decref(split[i].suspect); +} + +/* + * Helper for blame_chunk(). blame_entry e is known to overlap with the patch + * hunk; split it and pass blame to the parent. + */ +static void blame_overlap(struct scoreboard *sb, struct blame_entry *e, int tlno, int plno, int same, struct origin *parent) +{ + struct blame_entry split[3] = {{0}}; + + split_overlap(split, e, tlno, plno, same, parent); + if (split[1].suspect) + split_blame(sb, split, e); + decref_split(split); +} + +/* + * Process one hunk from the patch between the current suspect for blame_entry + * e and its parent. Find and split the overlap, and pass blame to the + * overlapping part to the parent. + */ +static void blame_chunk(struct scoreboard *sb, int tlno, int plno, int same, struct origin *target, struct origin *parent) +{ + struct blame_entry *e; + + for (e = sb->ent; e; e = e->next) { + if (e->guilty || !same_suspect(e->suspect, target)) + continue; + if (same <= e->s_lno) + continue; + if (tlno < e->s_lno + e->num_lines) { + blame_overlap(sb, e, tlno, plno, same, parent); + } + } +} + +static void blame_chunk_cb(long start_a, long count_a, long start_b, long count_b, void *data) +{ + struct blame_chunk_cb_data *d = data; + blame_chunk(d->sb, d->tlno, d->plno, start_b, d->target, d->parent); + d->plno = start_a + count_a; + d->tlno = start_b + count_b; +} + +static int my_emit_func(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg) +{ + xdchange_t *xch = xscr; + GIT_UNUSED(xe); + GIT_UNUSED(xecfg); + while (xch) { + blame_chunk_cb(xch->i1, xch->chg1, xch->i2, xch->chg2, ecb->priv); + xch = xch->next; + } + return 0; +} + +static void trim_common_tail(mmfile_t *a, mmfile_t *b, long ctx) +{ + const int blk = 1024; + long trimmed = 0, recovered = 0; + char *ap = a->ptr + a->size; + char *bp = b->ptr + b->size; + long smaller = (a->size < b->size) ? a->size : b->size; + + if (ctx) + return; + + while (blk + trimmed <= smaller && !memcmp(ap - blk, bp - blk, blk)) { + trimmed += blk; + ap -= blk; + bp -= blk; + } + + while (recovered < trimmed) + if (ap[recovered++] == '\n') + break; + a->size -= trimmed - recovered; + b->size -= trimmed - recovered; +} + +static int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *xecb) +{ + mmfile_t a = *mf1; + mmfile_t b = *mf2; + + trim_common_tail(&a, &b, xecfg->ctxlen); + + return xdl_diff(&a, &b, xpp, xecfg, xecb); +} + + +static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, void *cb_data) +{ + xpparam_t xpp = {0}; + xdemitconf_t xecfg = {0}; + xdemitcb_t ecb = {0}; + + xecfg.emit_func = (void(*)(void))my_emit_func; + ecb.priv = cb_data; + return xdi_diff(file_a, file_b, &xpp, &xecfg, &ecb); +} + +static void fill_origin_blob(struct origin *o, mmfile_t *file) +{ + memset(file, 0, sizeof(*file)); + if (o->blob) { + file->ptr = (char*)git_blob_rawcontent(o->blob); + file->size = (size_t)git_blob_rawsize(o->blob); + } +} + +static int pass_blame_to_parent(struct scoreboard *sb, + struct origin *target, + struct origin *parent) +{ + int last_in_target; + mmfile_t file_p, file_o; + struct blame_chunk_cb_data d = { sb, target, parent, 0, 0 }; + + last_in_target = find_last_in_target(sb, target); + if (last_in_target < 0) + return 1; /* nothing remains for this target */ + + fill_origin_blob(parent, &file_p); + fill_origin_blob(target, &file_o); + + diff_hunks(&file_p, &file_o, &d); + /* The reset (i.e. anything after tlno) are the same as the parent */ + blame_chunk(sb, d.tlno, d.plno, last_in_target, target, parent); + + return 0; +} + +static int paths_on_dup(void **old, void *new) +{ + GIT_UNUSED(old); + git__free(new); + return -1; +} +static struct origin* find_origin(struct scoreboard *sb, git_commit *parent, + struct origin *origin) +{ + struct origin *porigin = NULL; + git_diff_list *difflist = NULL; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_tree *otree=NULL, *ptree=NULL; + + /* Get the trees from this commit and its parent */ + // TODO: check errors + git_commit_tree(&otree, origin->commit); + git_commit_tree(&ptree, parent); + + /* Configure the diff */ + diffopts.context_lines = 0; + diffopts.flags = GIT_DIFF_SKIP_BINARY_CHECK; + + /* Check to see if files we're interested have changed */ + diffopts.pathspec.count = sb->blame->paths.length; + diffopts.pathspec.strings = (char**)sb->blame->paths.contents; + // TODO: check error + git_diff_tree_to_tree(&difflist, sb->blame->repository, ptree, otree, &diffopts); + + if (!git_diff_num_deltas(difflist)) { + /* No changes; copy data */ + // TODO: check error + get_origin(&porigin, sb, parent, origin->path); + } else { + git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + int i; + + /* Generate a full diff between the two trees */ + git_diff_list_free(difflist); + diffopts.pathspec.count = 0; + // TODO: check error + git_diff_tree_to_tree(&difflist, sb->blame->repository, ptree, otree, &diffopts); + + /* Let diff find renames */ + findopts.flags = GIT_DIFF_FIND_RENAMES; + // TODO: check error + git_diff_find_similar(difflist, &findopts); + + /* Find one that matches */ + for (i=0; i<(int)git_diff_num_deltas(difflist); i++) { + const git_diff_delta *delta; + git_diff_get_patch(NULL, &delta, difflist, i); + if (git_vector_bsearch(NULL, &sb->blame->paths, delta->new_file.path) != 0) + continue; + + git_vector_insert_sorted(&sb->blame->paths, (void*)git__strdup(delta->old_file.path), paths_on_dup); + // TODO: check error + make_origin(&porigin, parent, delta->old_file.path); + } + } + + git_diff_list_free(difflist); + git_tree_free(otree); + git_tree_free(ptree); + return porigin; + +} + +/* + * The blobs of origin and porigin exactly match, so everything origin is + * suspected for can be blamed on the parent. + */ +static void pass_whole_blame(struct scoreboard *sb, + struct origin *origin, struct origin *porigin) +{ + struct blame_entry *e; + + if (!porigin->blob) + git_object_lookup((git_object**)&porigin->blob, sb->blame->repository, git_blob_id(origin->blob), + GIT_OBJ_BLOB); + for (e=sb->ent; e; e=e->next) { + if (!same_suspect(e->suspect, origin)) + continue; + origin_incref(porigin); + origin_decref(e->suspect); + e->suspect = porigin; + } +} + +static void pass_blame(struct scoreboard *sb, struct origin *origin, uint32_t opt) +{ + git_commit *commit = origin->commit; + int i, num_sg; + struct origin *sg_buf[16]; + struct origin *porigin, **sg_origin = sg_buf; + + GIT_UNUSED(opt); + + num_sg = git_commit_parentcount(commit); + if (!num_sg) + goto finish; + else if (num_sg < (int)ARRAY_SIZE(sg_buf)) + memset(sg_buf, 0, sizeof(sg_buf)); + else + sg_origin = git__calloc(num_sg, sizeof(*sg_origin)); + + for (i=0; icommit, i); + porigin = find_origin(sb, p, origin); + + if (!porigin) + continue; + if (porigin->blob && origin->blob && + !git_oid_cmp(git_blob_id(porigin->blob), git_blob_id(origin->blob))) { + pass_whole_blame(sb, origin, porigin); + origin_decref(porigin); + goto finish; + } + for (j = same = 0; jblob), git_blob_id(porigin->blob))) { + same = 1; + break; + } + if (!same) + sg_origin[i] = porigin; + else + origin_decref(porigin); + } + + for (i=0; iprevious) { + origin_incref(porigin); + origin->previous = porigin; + } + if (pass_blame_to_parent(sb, origin, porigin)) + goto finish; + } + + /* TODO: optionally find moves in parents' files */ + + /* TODO: optionally find copies in parents' files */ + +finish: + for (i=0; irefcnt++; + return o; +} + +void origin_decref(struct origin *o) +{ + if (o && --o->refcnt <= 0) { + if (o->previous) + origin_decref(o->previous); + git_blob_free(o->blob); + git_commit_free(o->commit); + git__free(o); + } +} + +void assign_blame(struct scoreboard *sb, uint32_t opt) +{ + while (true) { + struct blame_entry *ent; + struct origin *suspect = NULL; + + /* Find a suspect to break down */ + for (ent = sb->ent; !suspect && ent; ent = ent->next) + if (!ent->guilty) + suspect = ent->suspect; + if (!suspect) + return; /* all done */ + + /* We'll use this suspect later in the loop, so hold on to it for now. */ + origin_incref(suspect); + pass_blame(sb, suspect, opt); + + /* Take responsibility for the remaining entries */ + for (ent = sb->ent; ent; ent = ent->next) + if (same_suspect(ent->suspect, suspect)) + ent->guilty = 1; + origin_decref(suspect); + } +} + +void coalesce(struct scoreboard *sb) +{ + struct blame_entry *ent, *next; + + for (ent=sb->ent; ent && (next = ent->next); ent = next) { + if (same_suspect(ent->suspect, next->suspect) && + ent->guilty == next->guilty && + ent->s_lno + ent->num_lines == next->s_lno) + { + ent->num_lines += next->num_lines; + ent->next = next->next; + if (ent->next) + ent->next->prev = ent; + origin_decref(next->suspect); + git__free(next); + ent->score = 0; + next = ent; /* again */ + } + } +} + diff --git a/src/blame_git.h b/src/blame_git.h new file mode 100644 index 000000000..89ebc3228 --- /dev/null +++ b/src/blame_git.h @@ -0,0 +1,93 @@ + +#ifndef INCLUDE_blame_git__ +#define INCLUDE_blame_git__ + +#include "git2.h" +#include "xdiff/xinclude.h" +#include "blame.h" + +/* + * One blob in a commit that is being suspected + */ +struct origin { + int refcnt; + struct origin *previous; + git_commit *commit; + git_blob *blob; + char path[]; +}; + +/* + * Each group of lines is described by a blame_entry; it can be split + * as we pass blame to the parents. They form a linked list in the + * scoreboard structure, sorted by the target line number. + */ +struct blame_entry { + struct blame_entry *prev; + struct blame_entry *next; + + /* the first line of this group in the final image; + * internally all line numbers are 0 based. + */ + int lno; + + /* how many lines this group has */ + int num_lines; + + /* the commit that introduced this group into the final image */ + struct origin *suspect; + + /* true if the suspect is truly guilty; false while we have not + * checked if the group came from one of its parents. + */ + char guilty; + + /* true if the entry has been scanned for copies in the current parent + */ + char scanned; + + /* the line number of the first line of this group in the + * suspect's file; internally all line numbers are 0 based. + */ + int s_lno; + + /* how significant this entry is -- cached to avoid + * scanning the lines over and over. + */ + unsigned score; +}; + +/* + * The current state of the blame assignment. + */ +struct scoreboard { + /* the final commit (i.e. where we started digging from) */ + git_commit *final; + const char *path; + + /* + * The contents in the final image. + * Used by many functions to obtain contents of the nth line, + * indexed with scoreboard.lineno[blame_entry.lno]. + */ + const char *final_buf; + git_off_t final_buf_size; + + /* linked list of blames */ + struct blame_entry *ent; + + /* look-up a line in the final buffer */ + int num_lines; + + git_blame *blame; +}; + + +int get_origin(struct origin **out, struct scoreboard *sb, git_commit *commit, const char *path); +int make_origin(struct origin **out, git_commit *commit, const char *path); +struct origin *origin_incref(struct origin *o); +void origin_decref(struct origin *o); +void assign_blame(struct scoreboard *sb, uint32_t flags); +void coalesce(struct scoreboard *sb); + +#endif diff --git a/src/object.c b/src/object.c index 9b8ccdd3e..53666ffe4 100644 --- a/src/object.c +++ b/src/object.c @@ -364,3 +364,39 @@ int git_object_dup(git_object **dest, git_object *source) *dest = source; return 0; } + +int git_object_lookup_bypath( + git_object **out, + const git_object *treeish, + const char *path, + git_otype type) +{ + int error = -1; + git_tree *tree = NULL; + git_tree_entry *entry = NULL; + git_object *tmpobj = NULL; + + assert(out && treeish && path); + + if (((error = git_object_peel((git_object**)&tree, treeish, GIT_OBJ_TREE)) < 0) || + ((error = git_tree_entry_bypath(&entry, tree, path)) < 0) || + ((error = git_tree_entry_to_object(&tmpobj, git_object_owner(treeish), entry)) < 0)) + { + goto cleanup; + } + + if (type == GIT_OBJ_ANY || git_object_type(tmpobj) == type) { + *out = tmpobj; + } else { + giterr_set(GITERR_OBJECT, + "object at path '%s' is not of the asked-for type %d", + path, type); + error = GIT_EINVALIDSPEC; + git_object_free(tmpobj); + } + +cleanup: + git_tree_entry_free(entry); + git_tree_free(tree); + return error; +} diff --git a/tests-clar/blame/blame_helpers.c b/tests-clar/blame/blame_helpers.c new file mode 100644 index 000000000..25c62a1ff --- /dev/null +++ b/tests-clar/blame/blame_helpers.c @@ -0,0 +1,58 @@ +#include "blame_helpers.h" + +void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...) +{ + va_list arglist; + + printf("Hunk %zd (line %d +%d): ", idx, + hunk->final_start_line_number, hunk->lines_in_hunk-1); + + va_start(arglist, fmt); + vprintf(fmt, arglist); + va_end(arglist); + + printf("\n"); +} + +void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx, + int start_line, int len, const char *commit_id, const char *orig_path) +{ + char expected[41] = {0}, actual[41] = {0}; + const git_blame_hunk *hunk = git_blame_get_hunk_byindex(blame, idx); + cl_assert(hunk); + + if (!strncmp(commit_id, "0000", 4)) { + strcpy(expected, "0000000000000000000000000000000000000000"); + } else { + git_object *obj; + cl_git_pass(git_revparse_single(&obj, repo, commit_id)); + git_oid_fmt(expected, git_object_id(obj)); + git_object_free(obj); + } + + if (hunk->final_start_line_number != start_line) { + hunk_message(idx, hunk, "mismatched start line number: expected %d, got %d", + start_line, hunk->final_start_line_number); + } + cl_assert_equal_i(hunk->final_start_line_number, start_line); + + if (hunk->lines_in_hunk != len) { + hunk_message(idx, hunk, "mismatched line count: expected %d, got %d", + len, hunk->lines_in_hunk); + } + cl_assert_equal_i(hunk->lines_in_hunk, len); + + git_oid_fmt(actual, &hunk->final_commit_id); + if (strcmp(expected, actual)) { + hunk_message(idx, hunk, "has mismatched original id (got %s, expected %s)\n", + actual, expected); + } + cl_assert_equal_s(actual, expected); + if (strcmp(hunk->orig_path, orig_path)) { + hunk_message(idx, hunk, "has mismatched original path (got '%s', expected '%s')\n", + hunk->orig_path, orig_path); + } + cl_assert_equal_s(hunk->orig_path, orig_path); +} + + diff --git a/tests-clar/blame/blame_helpers.h b/tests-clar/blame/blame_helpers.h new file mode 100644 index 000000000..15fa1c33e --- /dev/null +++ b/tests-clar/blame/blame_helpers.h @@ -0,0 +1,15 @@ +#include "clar_libgit2.h" +#include "blame.h" + +void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...); + +void check_blame_hunk_index( + git_repository *repo, + git_blame *blame, + int idx, + int start_line, + int len, + const char *commit_id, + const char *orig_path); + + diff --git a/tests-clar/blame/buffer.c b/tests-clar/blame/buffer.c new file mode 100644 index 000000000..20435eb6c --- /dev/null +++ b/tests-clar/blame/buffer.c @@ -0,0 +1,130 @@ +#include "blame_helpers.h" + +git_repository *g_repo; +git_blame *g_fileblame, *g_bufferblame; + +void test_blame_buffer__initialize(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); + cl_git_pass(git_blame_file(&g_fileblame, g_repo, "b.txt", NULL)); + g_bufferblame = NULL; +} + +void test_blame_buffer__cleanup(void) +{ + git_blame_free(g_fileblame); + git_blame_free(g_bufferblame); + git_repository_free(g_repo); +} + +void test_blame_buffer__added_line(void) +{ + const char *buffer = "\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +\n\ +abcdefg\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; + + cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); + cl_assert_equal_i(5, git_blame_get_hunk_count(g_bufferblame)); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, "000000", "b.txt"); +} + +void test_blame_buffer__deleted_line(void) +{ + const char *buffer = "\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; + + cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 3, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 9, 1, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 4, 10, 5, "aa06ecca", "b.txt"); +} + +void test_blame_buffer__add_splits_hunk(void) +{ + const char *buffer = "\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +abc\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; + + cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 2, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 8, 1, "00000000", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 4, 9, 3, "63d671eb", "b.txt"); +} + +void test_blame_buffer__delete_crosses_hunk_boundary(void) +{ + const char *buffer = "\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; + + cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 2, "aa06ecca", "b.txt"); +} + +void test_blame_buffer__replace_line(void) +{ + const char *buffer = "\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +abc\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; + + cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 1, "00000000", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 4, 8, 3, "63d671eb", "b.txt"); +} diff --git a/tests-clar/blame/getters.c b/tests-clar/blame/getters.c new file mode 100644 index 000000000..82e0de59e --- /dev/null +++ b/tests-clar/blame/getters.c @@ -0,0 +1,56 @@ +#include "clar_libgit2.h" + +#include "blame.h" + +git_blame *g_blame; + +void test_blame_getters__initialize(void) +{ + size_t i; + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + git_blame_hunk hunks[] = { + { 3, {{0}}, 1, {{0}}, "a", 0}, + { 3, {{0}}, 4, {{0}}, "b", 0}, + { 3, {{0}}, 7, {{0}}, "c", 0}, + { 3, {{0}}, 10, {{0}}, "d", 0}, + { 3, {{0}}, 13, {{0}}, "e", 0}, + }; + + g_blame = git_blame__alloc(NULL, opts, ""); + + for (i=0; i<5; i++) { + git_blame_hunk *h = git_blame__alloc_hunk(); + h->final_start_line_number = hunks[i].final_start_line_number; + h->orig_path = git__strdup(hunks[i].orig_path); + h->lines_in_hunk = hunks[i].lines_in_hunk; + + git_vector_insert(&g_blame->hunks, h); + } +} + +void test_blame_getters__cleanup(void) +{ + git_blame_free(g_blame); +} + + +void test_blame_getters__byindex(void) +{ + const git_blame_hunk *h = git_blame_get_hunk_byindex(g_blame, 2); + cl_assert(h); + cl_assert_equal_s(h->orig_path, "c"); + + h = git_blame_get_hunk_byindex(g_blame, 95); + cl_assert_equal_p(h, NULL); +} + +void test_blame_getters__byline(void) +{ + const git_blame_hunk *h = git_blame_get_hunk_byline(g_blame, 5); + cl_assert(h); + cl_assert_equal_s(h->orig_path, "b"); + + h = git_blame_get_hunk_byline(g_blame, 95); + cl_assert_equal_p(h, NULL); +} diff --git a/tests-clar/blame/harder.c b/tests-clar/blame/harder.c new file mode 100644 index 000000000..7c4dd4f74 --- /dev/null +++ b/tests-clar/blame/harder.c @@ -0,0 +1,71 @@ +#include "clar_libgit2.h" + +#include "blame.h" + + +/** + * The test repo has a history that looks like this: + * + * * (A) bc7c5ac + * |\ + * | * (B) aa06ecc + * * | (C) 63d671e + * |/ + * * (D) da23739 + * * (E) b99f7ac + * + */ + +static git_repository *g_repo = NULL; + +void test_blame_harder__initialize(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); +} + +void test_blame_harder__cleanup(void) +{ + git_repository_free(g_repo); + g_repo = NULL; +} + + + +void test_blame_harder__m(void) +{ + /* TODO */ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + opts.flags = GIT_BLAME_TRACK_COPIES_SAME_FILE; +} + + +void test_blame_harder__c(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + /* Attribute the first hunk in b.txt to (E), since it was cut/pasted from + * a.txt in (D). + */ + opts.flags = GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; +} + +void test_blame_harder__cc(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + /* Attribute the second hunk in b.txt to (E), since it was copy/pasted from + * a.txt in (C). + */ + opts.flags = GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; +} + +void test_blame_harder__ccc(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + /* Attribute the third hunk in b.txt to (E). This hunk was deleted from + * a.txt in (D), but reintroduced in (B). + */ + opts.flags = GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES; +} diff --git a/tests-clar/blame/simple.c b/tests-clar/blame/simple.c new file mode 100644 index 000000000..4e2d88653 --- /dev/null +++ b/tests-clar/blame/simple.c @@ -0,0 +1,204 @@ +#include "blame_helpers.h" + +/* + * $ git blame -s branch_file.txt + * orig line no final line no + * commit V author timestamp V + * c47800c7 1 (Scott Chacon 2010-05-25 11:58:14 -0700 1 + * a65fedf3 2 (Scott Chacon 2011-08-09 19:33:46 -0700 2 + */ +void test_blame_simple__trivial_testrepo(void) +{ + git_blame *blame = NULL; + git_repository *repo; + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo/.gitted"))); + cl_git_pass(git_blame_file(&blame, repo, "branch_file.txt", NULL)); + + cl_assert_equal_i(2, git_blame_get_hunk_count(blame)); + check_blame_hunk_index(repo, blame, 0, 1, 1, "c47800c7", "branch_file.txt"); + check_blame_hunk_index(repo, blame, 1, 2, 1, "a65fedf3", "branch_file.txt"); + + git_blame_free(blame); + git_repository_free(repo); +} + +/* + * $ git blame -n b.txt + * orig line no final line no + * commit V author timestamp V + * da237394 1 (Ben Straub 2013-02-12 15:11:30 -0800 1 + * da237394 2 (Ben Straub 2013-02-12 15:11:30 -0800 2 + * da237394 3 (Ben Straub 2013-02-12 15:11:30 -0800 3 + * da237394 4 (Ben Straub 2013-02-12 15:11:30 -0800 4 + * ^b99f7ac 1 (Ben Straub 2013-02-12 15:10:12 -0800 5 + * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 + * 63d671eb 7 (Ben Straub 2013-02-12 15:13:04 -0800 7 + * 63d671eb 8 (Ben Straub 2013-02-12 15:13:04 -0800 8 + * 63d671eb 9 (Ben Straub 2013-02-12 15:13:04 -0800 9 + * 63d671eb 10 (Ben Straub 2013-02-12 15:13:04 -0800 10 + * aa06ecca 6 (Ben Straub 2013-02-12 15:14:46 -0800 11 + * aa06ecca 7 (Ben Straub 2013-02-12 15:14:46 -0800 12 + * aa06ecca 8 (Ben Straub 2013-02-12 15:14:46 -0800 13 + * aa06ecca 9 (Ben Straub 2013-02-12 15:14:46 -0800 14 + * aa06ecca 10 (Ben Straub 2013-02-12 15:14:46 -0800 15 + */ +void test_blame_simple__trivial_blamerepo(void) +{ + git_blame *blame = NULL; + git_repository *repo; + cl_git_pass(git_repository_open(&repo, cl_fixture("blametest.git"))); + cl_git_pass(git_blame_file(&blame, repo, "b.txt", NULL)); + + cl_assert_equal_i(4, git_blame_get_hunk_count(blame)); + check_blame_hunk_index(repo, blame, 0, 1, 4, "da237394", "b.txt"); + check_blame_hunk_index(repo, blame, 1, 5, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(repo, blame, 2, 6, 5, "63d671eb", "b.txt"); + check_blame_hunk_index(repo, blame, 3, 11, 5, "aa06ecca", "b.txt"); + + git_blame_free(blame); + git_repository_free(repo); +} + + +/* + * $ git blame -n 359fc2d -- include/git2.h + * orig line no final line no + * commit orig path V author timestamp V + * d12299fe src/git.h 1 (Vicent Martí 2010-12-03 22:22:10 +0200 1 + * 359fc2d2 include/git2.h 2 (Edward Thomson 2013-01-08 17:07:25 -0600 2 + * d12299fe src/git.h 5 (Vicent Martí 2010-12-03 22:22:10 +0200 3 + * bb742ede include/git2.h 4 (Vicent Martí 2011-09-19 01:54:32 +0300 4 + * bb742ede include/git2.h 5 (Vicent Martí 2011-09-19 01:54:32 +0300 5 + * d12299fe src/git.h 24 (Vicent Martí 2010-12-03 22:22:10 +0200 6 + * d12299fe src/git.h 25 (Vicent Martí 2010-12-03 22:22:10 +0200 7 + * d12299fe src/git.h 26 (Vicent Martí 2010-12-03 22:22:10 +0200 8 + * d12299fe src/git.h 27 (Vicent Martí 2010-12-03 22:22:10 +0200 9 + * d12299fe src/git.h 28 (Vicent Martí 2010-12-03 22:22:10 +0200 10 + * 96fab093 include/git2.h 11 (Sven Strickroth 2011-10-09 18:37:41 +0200 11 + * 9d1dcca2 src/git2.h 33 (Vicent Martí 2011-02-07 10:35:58 +0200 12 + * 44908fe7 src/git2.h 29 (Vicent Martí 2010-12-06 23:03:16 +0200 13 + * a15c550d include/git2.h 14 (Vicent Martí 2011-11-16 14:09:44 +0100 14 + * 44908fe7 src/git2.h 30 (Vicent Martí 2010-12-06 23:03:16 +0200 15 + * d12299fe src/git.h 32 (Vicent Martí 2010-12-03 22:22:10 +0200 16 + * 44908fe7 src/git2.h 33 (Vicent Martí 2010-12-06 23:03:16 +0200 17 + * d12299fe src/git.h 34 (Vicent Martí 2010-12-03 22:22:10 +0200 18 + * 44908fe7 src/git2.h 35 (Vicent Martí 2010-12-06 23:03:16 +0200 19 + * 638c2ca4 src/git2.h 36 (Vicent Martí 2010-12-18 02:10:25 +0200 20 + * 44908fe7 src/git2.h 36 (Vicent Martí 2010-12-06 23:03:16 +0200 21 + * d12299fe src/git.h 37 (Vicent Martí 2010-12-03 22:22:10 +0200 22 + * 44908fe7 src/git2.h 38 (Vicent Martí 2010-12-06 23:03:16 +0200 23 + * 44908fe7 src/git2.h 39 (Vicent Martí 2010-12-06 23:03:16 +0200 24 + * bf787bd8 include/git2.h 25 (Carlos Martín Nieto 2012-04-08 18:56:50 +0200 25 + * 0984c876 include/git2.h 26 (Scott J. Goldman 2012-11-28 18:27:43 -0800 26 + * 2f8a8ab2 src/git2.h 41 (Vicent Martí 2011-01-29 01:56:25 +0200 27 + * 27df4275 include/git2.h 47 (Michael Schubert 2011-06-28 14:13:12 +0200 28 + * a346992f include/git2.h 28 (Ben Straub 2012-05-10 09:47:14 -0700 29 + * d12299fe src/git.h 40 (Vicent Martí 2010-12-03 22:22:10 +0200 30 + * 44908fe7 src/git2.h 41 (Vicent Martí 2010-12-06 23:03:16 +0200 31 + * 44908fe7 src/git2.h 42 (Vicent Martí 2010-12-06 23:03:16 +0200 32 + * 44908fe7 src/git2.h 43 (Vicent Martí 2010-12-06 23:03:16 +0200 33 + * 44908fe7 src/git2.h 44 (Vicent Martí 2010-12-06 23:03:16 +0200 34 + * 44908fe7 src/git2.h 45 (Vicent Martí 2010-12-06 23:03:16 +0200 35 + * 65b09b1d include/git2.h 33 (Russell Belfer 2012-02-02 18:03:43 -0800 36 + * d12299fe src/git.h 46 (Vicent Martí 2010-12-03 22:22:10 +0200 37 + * 44908fe7 src/git2.h 47 (Vicent Martí 2010-12-06 23:03:16 +0200 38 + * 5d4cd003 include/git2.h 55 (Carlos Martín Nieto 2011-03-28 17:02:45 +0200 39 + * 41fb1ca0 include/git2.h 39 (Philip Kelley 2012-10-29 13:41:14 -0400 40 + * 2dc31040 include/git2.h 56 (Carlos Martín Nieto 2011-06-20 18:58:57 +0200 41 + * 764df57e include/git2.h 40 (Ben Straub 2012-06-15 13:14:43 -0700 42 + * 5280f4e6 include/git2.h 41 (Ben Straub 2012-07-31 19:39:06 -0700 43 + * 613d5eb9 include/git2.h 43 (Philip Kelley 2012-11-28 11:42:37 -0500 44 + * d12299fe src/git.h 48 (Vicent Martí 2010-12-03 22:22:10 +0200 45 + * 111ee3fe include/git2.h 41 (Vicent Martí 2012-07-11 14:37:26 +0200 46 + * f004c4a8 include/git2.h 44 (Russell Belfer 2012-08-21 17:26:39 -0700 47 + * 111ee3fe include/git2.h 42 (Vicent Martí 2012-07-11 14:37:26 +0200 48 + * 9c82357b include/git2.h 58 (Carlos Martín Nieto 2011-06-17 18:13:14 +0200 49 + * d6258deb include/git2.h 61 (Carlos Martín Nieto 2011-06-25 15:10:09 +0200 50 + * b311e313 include/git2.h 63 (Julien Miotte 2011-07-27 18:31:13 +0200 51 + * 3412391d include/git2.h 63 (Carlos Martín Nieto 2011-07-07 11:47:31 +0200 52 + * bfc9ca59 include/git2.h 43 (Russell Belfer 2012-03-28 16:45:36 -0700 53 + * bf477ed4 include/git2.h 44 (Michael Schubert 2012-02-15 00:33:38 +0100 54 + * edebceff include/git2.h 46 (nulltoken 2012-05-01 13:57:45 +0200 55 + * 743a4b3b include/git2.h 48 (nulltoken 2012-06-15 22:24:59 +0200 56 + * 0a32dca5 include/git2.h 54 (Michael Schubert 2012-08-19 22:26:32 +0200 57 + * 590fb68b include/git2.h 55 (nulltoken 2012-10-04 13:47:45 +0200 58 + * bf477ed4 include/git2.h 45 (Michael Schubert 2012-02-15 00:33:38 +0100 59 + * d12299fe src/git.h 49 (Vicent Martí 2010-12-03 22:22:10 +0200 60 + */ +void test_blame_simple__trivial_libgit2(void) +{ + git_repository *repo; + git_blame *blame; + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + git_object *obj; + + cl_git_pass(git_repository_open(&repo, cl_fixture("../.."))); + + /* This test can't work on a shallow clone */ + if (git_repository_is_shallow(repo)) { + git_repository_free(repo); + return; + } + + cl_git_pass(git_revparse_single(&obj, repo, "359fc2d")); + git_oid_cpy(&opts.newest_commit, git_object_id(obj)); + git_object_free(obj); + + cl_git_pass(git_blame_file(&blame, repo, "include/git2.h", &opts)); + + check_blame_hunk_index(repo, blame, 0, 1, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(repo, blame, 1, 2, 1, "359fc2d2", "include/git2.h"); + check_blame_hunk_index(repo, blame, 2, 3, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(repo, blame, 3, 4, 2, "bb742ede", "include/git2.h"); + check_blame_hunk_index(repo, blame, 4, 6, 5, "d12299fe", "src/git.h"); + check_blame_hunk_index(repo, blame, 5, 11, 1, "96fab093", "include/git2.h"); + check_blame_hunk_index(repo, blame, 6, 12, 1, "9d1dcca2", "src/git2.h"); + check_blame_hunk_index(repo, blame, 7, 13, 1, "44908fe7", "src/git2.h"); + check_blame_hunk_index(repo, blame, 8, 14, 1, "a15c550d", "include/git2.h"); + check_blame_hunk_index(repo, blame, 9, 15, 1, "44908fe7", "src/git2.h"); + check_blame_hunk_index(repo, blame, 10, 16, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(repo, blame, 11, 17, 1, "44908fe7", "src/git2.h"); + check_blame_hunk_index(repo, blame, 12, 18, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(repo, blame, 13, 19, 1, "44908fe7", "src/git2.h"); + check_blame_hunk_index(repo, blame, 14, 20, 1, "638c2ca4", "src/git2.h"); + check_blame_hunk_index(repo, blame, 15, 21, 1, "44908fe7", "src/git2.h"); + check_blame_hunk_index(repo, blame, 16, 22, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(repo, blame, 17, 23, 2, "44908fe7", "src/git2.h"); + check_blame_hunk_index(repo, blame, 18, 25, 1, "bf787bd8", "include/git2.h"); + check_blame_hunk_index(repo, blame, 19, 26, 1, "0984c876", "include/git2.h"); + check_blame_hunk_index(repo, blame, 20, 27, 1, "2f8a8ab2", "src/git2.h"); + check_blame_hunk_index(repo, blame, 21, 28, 1, "27df4275", "include/git2.h"); + check_blame_hunk_index(repo, blame, 22, 29, 1, "a346992f", "include/git2.h"); + check_blame_hunk_index(repo, blame, 23, 30, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(repo, blame, 24, 31, 5, "44908fe7", "src/git2.h"); + check_blame_hunk_index(repo, blame, 25, 36, 1, "65b09b1d", "include/git2.h"); + check_blame_hunk_index(repo, blame, 26, 37, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(repo, blame, 27, 38, 1, "44908fe7", "src/git2.h"); + check_blame_hunk_index(repo, blame, 28, 39, 1, "5d4cd003", "include/git2.h"); + check_blame_hunk_index(repo, blame, 29, 40, 1, "41fb1ca0", "include/git2.h"); + check_blame_hunk_index(repo, blame, 30, 41, 1, "2dc31040", "include/git2.h"); + check_blame_hunk_index(repo, blame, 31, 42, 1, "764df57e", "include/git2.h"); + check_blame_hunk_index(repo, blame, 32, 43, 1, "5280f4e6", "include/git2.h"); + check_blame_hunk_index(repo, blame, 33, 44, 1, "613d5eb9", "include/git2.h"); + check_blame_hunk_index(repo, blame, 34, 45, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(repo, blame, 35, 46, 1, "111ee3fe", "include/git2.h"); + check_blame_hunk_index(repo, blame, 36, 47, 1, "f004c4a8", "include/git2.h"); + check_blame_hunk_index(repo, blame, 37, 48, 1, "111ee3fe", "include/git2.h"); + check_blame_hunk_index(repo, blame, 38, 49, 1, "9c82357b", "include/git2.h"); + check_blame_hunk_index(repo, blame, 39, 50, 1, "d6258deb", "include/git2.h"); + check_blame_hunk_index(repo, blame, 40, 51, 1, "b311e313", "include/git2.h"); + check_blame_hunk_index(repo, blame, 41, 52, 1, "3412391d", "include/git2.h"); + check_blame_hunk_index(repo, blame, 42, 53, 1, "bfc9ca59", "include/git2.h"); + check_blame_hunk_index(repo, blame, 43, 54, 1, "bf477ed4", "include/git2.h"); + check_blame_hunk_index(repo, blame, 44, 55, 1, "edebceff", "include/git2.h"); + check_blame_hunk_index(repo, blame, 45, 56, 1, "743a4b3b", "include/git2.h"); + check_blame_hunk_index(repo, blame, 46, 57, 1, "0a32dca5", "include/git2.h"); + check_blame_hunk_index(repo, blame, 47, 58, 1, "590fb68b", "include/git2.h"); + check_blame_hunk_index(repo, blame, 48, 59, 1, "bf477ed4", "include/git2.h"); + check_blame_hunk_index(repo, blame, 49, 60, 1, "d12299fe", "src/git.h"); + + git_blame_free(blame); + git_repository_free(repo); +} + +/* TODO: no newline at end of file? */ diff --git a/tests-clar/object/lookupbypath.c b/tests-clar/object/lookupbypath.c new file mode 100644 index 000000000..31aac7647 --- /dev/null +++ b/tests-clar/object/lookupbypath.c @@ -0,0 +1,83 @@ +#include "clar_libgit2.h" + +#include "repository.h" + +static git_repository *g_repo; +static git_tree *g_root_tree; +static git_commit *g_head_commit; +static git_object *g_expectedobject, + *g_actualobject; + +void test_object_lookupbypath__initialize(void) +{ + git_reference *head; + git_tree_entry *tree_entry; + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("attr/.gitted"))); + + cl_git_pass(git_repository_head(&head, g_repo)); + cl_git_pass(git_reference_peel((git_object**)&g_head_commit, head, GIT_OBJ_COMMIT)); + cl_git_pass(git_commit_tree(&g_root_tree, g_head_commit)); + cl_git_pass(git_tree_entry_bypath(&tree_entry, g_root_tree, "subdir/subdir_test2.txt")); + cl_git_pass(git_object_lookup(&g_expectedobject, g_repo, git_tree_entry_id(tree_entry), + GIT_OBJ_ANY)); + + git_tree_entry_free(tree_entry); + git_reference_free(head); + + g_actualobject = NULL; +} +void test_object_lookupbypath__cleanup(void) +{ + git_object_free(g_actualobject); + git_object_free(g_expectedobject); + git_tree_free(g_root_tree); + git_commit_free(g_head_commit); + g_expectedobject = NULL; + git_repository_free(g_repo); + g_repo = NULL; +} + +void test_object_lookupbypath__errors(void) +{ + cl_assert_equal_i(GIT_EINVALIDSPEC, + git_object_lookup_bypath(&g_actualobject, (git_object*)g_root_tree, + "subdir/subdir_test2.txt", GIT_OBJ_TREE)); // It's not a tree + cl_assert_equal_i(GIT_ENOTFOUND, + git_object_lookup_bypath(&g_actualobject, (git_object*)g_root_tree, + "file/doesnt/exist", GIT_OBJ_ANY)); +} + +void test_object_lookupbypath__from_root_tree(void) +{ + cl_git_pass(git_object_lookup_bypath(&g_actualobject, (git_object*)g_root_tree, + "subdir/subdir_test2.txt", GIT_OBJ_BLOB)); + cl_assert_equal_i(0, git_oid_cmp(git_object_id(g_expectedobject), + git_object_id(g_actualobject))); +} + +void test_object_lookupbypath__from_head_commit(void) +{ + cl_git_pass(git_object_lookup_bypath(&g_actualobject, (git_object*)g_head_commit, + "subdir/subdir_test2.txt", GIT_OBJ_BLOB)); + cl_assert_equal_i(0, git_oid_cmp(git_object_id(g_expectedobject), + git_object_id(g_actualobject))); +} + +void test_object_lookupbypath__from_subdir_tree(void) +{ + git_tree_entry *entry = NULL; + git_tree *tree = NULL; + + cl_git_pass(git_tree_entry_bypath(&entry, g_root_tree, "subdir")); + cl_git_pass(git_tree_lookup(&tree, g_repo, git_tree_entry_id(entry))); + + cl_git_pass(git_object_lookup_bypath(&g_actualobject, (git_object*)tree, + "subdir_test2.txt", GIT_OBJ_BLOB)); + cl_assert_equal_i(0, git_oid_cmp(git_object_id(g_expectedobject), + git_object_id(g_actualobject))); + + git_tree_entry_free(entry); + git_tree_free(tree); +} + diff --git a/tests-clar/resources/blametest.git/HEAD b/tests-clar/resources/blametest.git/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests-clar/resources/blametest.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests-clar/resources/blametest.git/config b/tests-clar/resources/blametest.git/config new file mode 100644 index 000000000..c53d818dd --- /dev/null +++ b/tests-clar/resources/blametest.git/config @@ -0,0 +1,5 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true + ignorecase = true diff --git a/tests-clar/resources/blametest.git/description b/tests-clar/resources/blametest.git/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests-clar/resources/blametest.git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/blametest.git/objects/0c/bab4d45fd61e55a1c9697f9f9cb07a12e15448 b/tests-clar/resources/blametest.git/objects/0c/bab4d45fd61e55a1c9697f9f9cb07a12e15448 new file mode 100644 index 000000000..90331cef9 Binary files /dev/null and b/tests-clar/resources/blametest.git/objects/0c/bab4d45fd61e55a1c9697f9f9cb07a12e15448 differ diff --git a/tests-clar/resources/blametest.git/objects/1a/ac69ae5d96461afc4d81d0066cb12f5b05a35b b/tests-clar/resources/blametest.git/objects/1a/ac69ae5d96461afc4d81d0066cb12f5b05a35b new file mode 100644 index 000000000..71890274a Binary files /dev/null and b/tests-clar/resources/blametest.git/objects/1a/ac69ae5d96461afc4d81d0066cb12f5b05a35b differ diff --git a/tests-clar/resources/blametest.git/objects/1b/5f0775af166331c854bd8d1bca3450eaf2532a b/tests-clar/resources/blametest.git/objects/1b/5f0775af166331c854bd8d1bca3450eaf2532a new file mode 100644 index 000000000..e66430637 Binary files /dev/null and b/tests-clar/resources/blametest.git/objects/1b/5f0775af166331c854bd8d1bca3450eaf2532a differ diff --git a/tests-clar/resources/blametest.git/objects/48/2f2c370e35c2c314fc1f96db2beb33f955a26a b/tests-clar/resources/blametest.git/objects/48/2f2c370e35c2c314fc1f96db2beb33f955a26a new file mode 100644 index 000000000..7da4cf5d4 Binary files /dev/null and b/tests-clar/resources/blametest.git/objects/48/2f2c370e35c2c314fc1f96db2beb33f955a26a differ diff --git a/tests-clar/resources/blametest.git/objects/63/d671eb32d250e4a83766ebbc60e818c1e1e93a b/tests-clar/resources/blametest.git/objects/63/d671eb32d250e4a83766ebbc60e818c1e1e93a new file mode 100644 index 000000000..5f41f2936 --- /dev/null +++ b/tests-clar/resources/blametest.git/objects/63/d671eb32d250e4a83766ebbc60e818c1e1e93a @@ -0,0 +1,3 @@ +xA E]su@bGP뢭Azk<y~60I1S=-6FfC.cp, $b +8MF +ᨹO!1eȏ]TqkZV>m)49d-#mgwTK@ \ No newline at end of file diff --git a/tests-clar/resources/blametest.git/objects/63/eb57322e363e18d460da5ea8284f3cd2340b36 b/tests-clar/resources/blametest.git/objects/63/eb57322e363e18d460da5ea8284f3cd2340b36 new file mode 100644 index 000000000..c6c285eeb Binary files /dev/null and b/tests-clar/resources/blametest.git/objects/63/eb57322e363e18d460da5ea8284f3cd2340b36 differ diff --git a/tests-clar/resources/blametest.git/objects/8b/137891791fe96927ad78e64b0aad7bded08bdc b/tests-clar/resources/blametest.git/objects/8b/137891791fe96927ad78e64b0aad7bded08bdc new file mode 100644 index 000000000..9d8f60531 Binary files /dev/null and b/tests-clar/resources/blametest.git/objects/8b/137891791fe96927ad78e64b0aad7bded08bdc differ diff --git a/tests-clar/resources/blametest.git/objects/96/679d59cf9f74d69b3c920f258559b5e8c9a18a b/tests-clar/resources/blametest.git/objects/96/679d59cf9f74d69b3c920f258559b5e8c9a18a new file mode 100644 index 000000000..d716e3b03 Binary files /dev/null and b/tests-clar/resources/blametest.git/objects/96/679d59cf9f74d69b3c920f258559b5e8c9a18a differ diff --git a/tests-clar/resources/blametest.git/objects/98/89d6e5557761aa8e3607e80c874a6dc51ada7c b/tests-clar/resources/blametest.git/objects/98/89d6e5557761aa8e3607e80c874a6dc51ada7c new file mode 100644 index 000000000..12407f662 Binary files /dev/null and b/tests-clar/resources/blametest.git/objects/98/89d6e5557761aa8e3607e80c874a6dc51ada7c differ diff --git a/tests-clar/resources/blametest.git/objects/aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 b/tests-clar/resources/blametest.git/objects/aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 new file mode 100644 index 000000000..bc13badb1 --- /dev/null +++ b/tests-clar/resources/blametest.git/objects/aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 @@ -0,0 +1 @@ +xK0 DYu6I%P9'ǡ]ޟ"NI#3L vo{R-e1#B0}s9xR6d1SZx#dj&F #AGK?Kg2r \ No newline at end of file diff --git a/tests-clar/resources/blametest.git/objects/bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 b/tests-clar/resources/blametest.git/objects/bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 new file mode 100644 index 000000000..4e6ad159e --- /dev/null +++ b/tests-clar/resources/blametest.git/objects/bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 @@ -0,0 +1,3 @@ +xAn0 {+t))JA3<^Gn@$H\;MoѬƤ \ No newline at end of file diff --git a/tests-clar/resources/blametest.git/objects/da/237394e6132d20d30f175b9b73c8638fddddda b/tests-clar/resources/blametest.git/objects/da/237394e6132d20d30f175b9b73c8638fddddda new file mode 100644 index 000000000..e9e13833f --- /dev/null +++ b/tests-clar/resources/blametest.git/objects/da/237394e6132d20d30f175b9b73c8638fddddda @@ -0,0 +1,4 @@ +xK +0@]J|'"$vVbz :Sj)ifёDNS dObs[ޱAb( +Y;f([ +ո%85qK'Y (zF8b@vKc?S \ No newline at end of file diff --git a/tests-clar/resources/blametest.git/objects/e5/b41c1ea533f87388ab69b13baf0b5a562d6243 b/tests-clar/resources/blametest.git/objects/e5/b41c1ea533f87388ab69b13baf0b5a562d6243 new file mode 100644 index 000000000..7e5586c2b Binary files /dev/null and b/tests-clar/resources/blametest.git/objects/e5/b41c1ea533f87388ab69b13baf0b5a562d6243 differ diff --git a/tests-clar/resources/blametest.git/objects/ef/32df4d259143933715c74951f932d9892364d1 b/tests-clar/resources/blametest.git/objects/ef/32df4d259143933715c74951f932d9892364d1 new file mode 100644 index 000000000..d021ccfde Binary files /dev/null and b/tests-clar/resources/blametest.git/objects/ef/32df4d259143933715c74951f932d9892364d1 differ diff --git a/tests-clar/resources/blametest.git/refs/heads/master b/tests-clar/resources/blametest.git/refs/heads/master new file mode 100644 index 000000000..b763025d8 --- /dev/null +++ b/tests-clar/resources/blametest.git/refs/heads/master @@ -0,0 +1 @@ +bc7c5ac2bafe828a68e9d1d460343718d6fbe136 -- cgit v1.2.1 From 4c7fdb4d3d7b24e4bca69a710d347cfeb05ac78f Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 16 Sep 2013 16:27:10 -0700 Subject: Add blame example --- examples/.gitignore | 1 + examples/Makefile | 2 +- examples/blame.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 examples/blame.c diff --git a/examples/.gitignore b/examples/.gitignore index e8e0820a5..2b693f1ef 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -2,4 +2,5 @@ general showindex diff rev-list +blame *.dSYM diff --git a/examples/Makefile b/examples/Makefile index d53ed8241..79c57d7d7 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -3,7 +3,7 @@ CC = gcc CFLAGS = -g -I../include -I../src -Wall -Wextra -Wmissing-prototypes -Wno-missing-field-initializers LFLAGS = -L../build -lgit2 -lz -APPS = general showindex diff rev-list cat-file status log rev-parse init +APPS = general blame showindex diff rev-list cat-file status log rev-parse all: $(APPS) diff --git a/examples/blame.c b/examples/blame.c new file mode 100644 index 000000000..1b08ec487 --- /dev/null +++ b/examples/blame.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include + +static void check(int error, const char *msg) +{ + if (error) { + fprintf(stderr, "%s (%d)\n", msg, error); + exit(error); + } +} + +static void usage(const char *msg, const char *arg) +{ + if (msg && arg) + fprintf(stderr, "%s: %s\n", msg, arg); + else if (msg) + fprintf(stderr, "%s\n", msg); + fprintf(stderr, "usage: blame [options] []\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " example: `HEAD~10..HEAD`, or `1234abcd`\n"); + fprintf(stderr, " -L process only line range n-m, counting from 1\n"); + fprintf(stderr, " -M fine line moves within and across files\n"); + fprintf(stderr, " -C find line copies within and across files\n"); + fprintf(stderr, "\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + int i; + char *path = NULL, *a; + const char *rawdata, *commitspec=NULL; + git_repository *repo = NULL; + git_revspec revspec = {0}; + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + git_blame *blame = NULL; + git_commit *commit; + git_tree *tree; + git_tree_entry *entry; + git_blob *blob; + + if (argc < 2) usage(NULL, NULL); + path = argv[1]; + + for (i=2; i= argc) check(-1, "Not enough arguments to -L"); + check(sscanf(a, "%d,%d", &opts.min_line, &opts.max_line)-2, "-L format error"); + } + else { + /* commit range */ + if (commitspec) check(-1, "Only one commit spec allowed"); + commitspec = a; + } + } + + /* Open the repo */ + check(git_repository_open_ext(&repo, ".", 0, NULL), "Couldn't open repository"); + + /* Parse the end points */ + if (commitspec) { + check(git_revparse(&revspec, repo, commitspec), "Couldn't parse commit spec"); + if (revspec.flags & GIT_REVPARSE_SINGLE) { + git_oid_cpy(&opts.newest_commit, git_object_id(revspec.from)); + git_object_free(revspec.from); + } else { + git_oid_cpy(&opts.oldest_commit, git_object_id(revspec.from)); + git_oid_cpy(&opts.newest_commit, git_object_id(revspec.to)); + git_object_free(revspec.from); + git_object_free(revspec.to); + } + } + + /* Run the blame */ + check(git_blame_file(&blame, repo, path, &opts), "Blame error"); + + /* Get the raw data for output */ + if (git_oid_iszero(&opts.newest_commit)) { + git_object *obj; + check(git_revparse_single(&obj, repo, "HEAD"), "Can't find HEAD"); + git_oid_cpy(&opts.newest_commit, git_object_id(obj)); + git_object_free(obj); + } + check(git_commit_lookup(&commit, repo, &opts.newest_commit), "Commit lookup error"); + check(git_commit_tree(&tree, commit), "Commit tree lookup error"); + check(git_tree_entry_bypath(&entry, tree, path), "Tree entry lookup error"); + check(git_blob_lookup(&blob, repo, git_tree_entry_id(entry)), "Blob lookup error"); + rawdata = git_blob_rawcontent(blob); + + /* Produce the output */ + i = 1; + while (rawdata[0]) { + const char *eol = strchr(rawdata, '\n'); + char oid[10] = {0}; + const git_blame_hunk *hunk = git_blame_get_hunk_byline(blame, i); + git_commit *hunkcommit; + const git_signature *sig; + + git_oid_tostr(oid, 10, &hunk->final_commit_id); + check(git_commit_lookup(&hunkcommit, repo, &hunk->final_commit_id), "Commit lookup error"); + sig = git_commit_author(hunkcommit); + + printf("%s ( %-30s %3d) %.*s\n", + oid, + sig->name, + i, + (int)(eol-rawdata), + rawdata); + + git_commit_free(hunkcommit); + rawdata = eol+1; + i++; + } + + /* Cleanup */ + git_blob_free(blob); + git_tree_entry_free(entry); + git_tree_free(tree); + git_commit_free(commit); + git_blame_free(blame); + git_repository_free(repo); +} -- cgit v1.2.1 From 605da51a2cfd86901b6fa5f9cf71111a63ab4418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 17 Sep 2013 09:50:30 +0200 Subject: No such thing as an orphan branch Unfortunately git-core uses the term "unborn branch" and "orphan branch" interchangeably. However, "orphan" is only really there for the checkout command, which has the `--orphan` option so it doesn't actually create the branch. Branches never have parents, so the distinction of a branch with no parents is odd to begin with. Crucially, the error messages deal with unborn branches, so let's use that. --- examples/status.c | 2 +- include/git2/checkout.h | 2 +- include/git2/errors.h | 2 +- include/git2/repository.h | 12 ++++++------ src/branch.c | 2 +- src/checkout.c | 2 +- src/clone.c | 2 +- src/remote.c | 2 +- src/repository.c | 6 +++--- src/stash.c | 2 +- src/status.c | 2 +- src/submodule.c | 2 +- tests-clar/checkout/head.c | 6 +++--- tests-clar/clone/empty.c | 4 ++-- tests-clar/clone/nonetwork.c | 2 +- tests-clar/online/clone.c | 2 +- tests-clar/refs/branches/delete.c | 4 ++-- tests-clar/refs/branches/ishead.c | 4 ++-- tests-clar/repo/head.c | 26 +++++++++++++------------- tests-clar/repo/headtree.c | 8 ++++---- tests-clar/repo/repo_helpers.c | 2 +- tests-clar/repo/repo_helpers.h | 2 +- tests-clar/reset/soft.c | 8 ++++---- tests-clar/stash/save.c | 2 +- tests-clar/submodule/lookup.c | 10 +++++----- 25 files changed, 59 insertions(+), 59 deletions(-) diff --git a/examples/status.c b/examples/status.c index 689098415..0d9f55f13 100644 --- a/examples/status.c +++ b/examples/status.c @@ -71,7 +71,7 @@ static void show_branch(git_repository *repo, int format) error = git_repository_head(&head, repo); - if (error == GIT_EORPHANEDHEAD || error == GIT_ENOTFOUND) + if (error == GIT_EUNBORNBRANCH || error == GIT_ENOTFOUND) branch = NULL; else if (!error) { branch = git_reference_name(head); diff --git a/include/git2/checkout.h b/include/git2/checkout.h index a086408c7..aa48069cd 100644 --- a/include/git2/checkout.h +++ b/include/git2/checkout.h @@ -249,7 +249,7 @@ typedef struct git_checkout_opts { * * @param repo repository to check out (must be non-bare) * @param opts specifies checkout options (may be NULL) - * @return 0 on success, GIT_EORPHANEDHEAD when HEAD points to a non existing + * @return 0 on success, GIT_EUNBORNBRANCH when HEAD points to a non existing * branch, GIT_ERROR otherwise (use giterr_last for information * about the error) */ diff --git a/include/git2/errors.h b/include/git2/errors.h index 0f0bddf07..dd566440c 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -27,7 +27,7 @@ typedef enum { GIT_EBUFS = -6, GIT_EUSER = -7, GIT_EBAREREPO = -8, - GIT_EORPHANEDHEAD = -9, + GIT_EUNBORNBRANCH = -9, GIT_EUNMERGED = -10, GIT_ENONFASTFORWARD = -11, GIT_EINVALIDSPEC = -12, diff --git a/include/git2/repository.h b/include/git2/repository.h index 807d834fe..b4d561992 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -297,7 +297,7 @@ GIT_EXTERN(int) git_repository_init_ext( * @param out pointer to the reference which will be retrieved * @param repo a repository object * - * @return 0 on success, GIT_EORPHANEDHEAD when HEAD points to a non existing + * @return 0 on success, GIT_EUNBORNBRANCH when HEAD points to a non existing * branch, GIT_ENOTFOUND when HEAD is missing; an error code otherwise */ GIT_EXTERN(int) git_repository_head(git_reference **out, git_repository *repo); @@ -315,16 +315,16 @@ GIT_EXTERN(int) git_repository_head(git_reference **out, git_repository *repo); GIT_EXTERN(int) git_repository_head_detached(git_repository *repo); /** - * Check if the current branch is an orphan + * Check if the current branch is unborn * - * An orphan branch is one named from HEAD but which doesn't exist in + * An unborn branch is one named from HEAD but which doesn't exist in * the refs namespace, because it doesn't have any commit to point to. * * @param repo Repo to test - * @return 1 if the current branch is an orphan, 0 if it's not; error + * @return 1 if the current branch is unborn, 0 if it's not; error * code if there was an error */ -GIT_EXTERN(int) git_repository_head_orphan(git_repository *repo); +GIT_EXTERN(int) git_repository_head_unborn(git_repository *repo); /** * Check if a repository is empty @@ -611,7 +611,7 @@ GIT_EXTERN(int) git_repository_set_head_detached( * Otherwise, the HEAD will be detached and point to the peeled Commit. * * @param repo Repository pointer - * @return 0 on success, GIT_EORPHANEDHEAD when HEAD points to a non existing + * @return 0 on success, GIT_EUNBORNBRANCH when HEAD points to a non existing * branch or an error code */ GIT_EXTERN(int) git_repository_detach_head( diff --git a/src/branch.c b/src/branch.c index 7064fa7fc..3a745c127 100644 --- a/src/branch.c +++ b/src/branch.c @@ -585,7 +585,7 @@ int git_branch_is_head( error = git_repository_head(&head, git_reference_owner(branch)); - if (error == GIT_EORPHANEDHEAD || error == GIT_ENOTFOUND) + if (error == GIT_EUNBORNBRANCH || error == GIT_ENOTFOUND) return false; if (error < 0) diff --git a/src/checkout.c b/src/checkout.c index aae354ca6..eb92e8fd6 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -1232,7 +1232,7 @@ static int checkout_data_init( error = checkout_lookup_head_tree(&data->opts.baseline, repo); - if (error == GIT_EORPHANEDHEAD) { + if (error == GIT_EUNBORNBRANCH) { error = 0; giterr_clear(); } diff --git a/src/clone.c b/src/clone.c index 9f47e07b6..ff251be1b 100644 --- a/src/clone.c +++ b/src/clone.c @@ -415,7 +415,7 @@ static bool should_checkout( if (opts->checkout_strategy == GIT_CHECKOUT_NONE) return false; - return !git_repository_head_orphan(repo); + return !git_repository_head_unborn(repo); } static void normalize_options(git_clone_options *dst, const git_clone_options *src, git_repository_init_options *initOptions) diff --git a/src/remote.c b/src/remote.c index bdc8e0e67..bfcb3eb65 100644 --- a/src/remote.c +++ b/src/remote.c @@ -806,7 +806,7 @@ static int remote_head_for_ref(git_remote_head **out, git_refspec *spec, git_vec (!git_reference_is_branch(resolved_ref)) || (error = git_branch_upstream(&tracking_ref, resolved_ref)) < 0 || (error = git_refspec_transform_l(&remote_name, spec, git_reference_name(tracking_ref))) < 0) { - /* Not an error if HEAD is orphaned or no tracking branch */ + /* Not an error if HEAD is unborn or no tracking branch */ if (error == GIT_ENOTFOUND) error = 0; diff --git a/src/repository.c b/src/repository.c index eae22ce51..eead41201 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1451,10 +1451,10 @@ int git_repository_head(git_reference **head_out, git_repository *repo) error = git_reference_lookup_resolved(head_out, repo, git_reference_symbolic_target(head), -1); git_reference_free(head); - return error == GIT_ENOTFOUND ? GIT_EORPHANEDHEAD : error; + return error == GIT_ENOTFOUND ? GIT_EUNBORNBRANCH : error; } -int git_repository_head_orphan(git_repository *repo) +int git_repository_head_unborn(git_repository *repo) { git_reference *ref = NULL; int error; @@ -1462,7 +1462,7 @@ int git_repository_head_orphan(git_repository *repo) error = git_repository_head(&ref, repo); git_reference_free(ref); - if (error == GIT_EORPHANEDHEAD) + if (error == GIT_EUNBORNBRANCH) return 1; if (error < 0) diff --git a/src/stash.c b/src/stash.c index 48f19144d..ab4a68575 100644 --- a/src/stash.c +++ b/src/stash.c @@ -27,7 +27,7 @@ static int retrieve_head(git_reference **out, git_repository *repo) { int error = git_repository_head(out, repo); - if (error == GIT_EORPHANEDHEAD) + if (error == GIT_EUNBORNBRANCH) return create_error(error, "You do not have the initial commit yet."); return error; diff --git a/src/status.c b/src/status.c index 4a0d65092..be40b9f83 100644 --- a/src/status.c +++ b/src/status.c @@ -252,7 +252,7 @@ int git_status_list_new( /* if there is no HEAD, that's okay - we'll make an empty iterator */ if (((error = git_repository_head_tree(&head, repo)) < 0) && - error != GIT_ENOTFOUND && error != GIT_EORPHANEDHEAD) { + error != GIT_ENOTFOUND && error != GIT_EUNBORNBRANCH) { git_index_free(index); /* release index */ return error; } diff --git a/src/submodule.c b/src/submodule.c index 40bda9a41..121383b9c 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -1557,7 +1557,7 @@ static void submodule_get_wd_status( if (ign == GIT_SUBMODULE_IGNORE_NONE) opt.flags |= GIT_DIFF_INCLUDE_UNTRACKED; - /* if we don't have an orphaned head, check diff with index */ + /* if we don't have an unborn head, check diff with index */ if (git_repository_head_tree(&sm_head, sm_repo) < 0) giterr_clear(); else { diff --git a/tests-clar/checkout/head.c b/tests-clar/checkout/head.c index 46646f8bf..74c6fb87a 100644 --- a/tests-clar/checkout/head.c +++ b/tests-clar/checkout/head.c @@ -16,11 +16,11 @@ void test_checkout_head__cleanup(void) cl_git_sandbox_cleanup(); } -void test_checkout_head__orphaned_head_returns_GIT_EORPHANEDHEAD(void) +void test_checkout_head__unborn_head_returns_GIT_EUNBORNBRANCH(void) { - make_head_orphaned(g_repo, NON_EXISTING_HEAD); + make_head_unborn(g_repo, NON_EXISTING_HEAD); - cl_assert_equal_i(GIT_EORPHANEDHEAD, git_checkout_head(g_repo, NULL)); + cl_assert_equal_i(GIT_EUNBORNBRANCH, git_checkout_head(g_repo, NULL)); } void test_checkout_head__with_index_only_tree(void) diff --git a/tests-clar/clone/empty.c b/tests-clar/clone/empty.c index f92fa6cbb..d9dc24fde 100644 --- a/tests-clar/clone/empty.c +++ b/tests-clar/clone/empty.c @@ -44,7 +44,7 @@ void test_clone_empty__can_clone_an_empty_local_repo_barely(void) g_options.bare = true; cl_git_pass(git_clone(&g_repo_cloned, "./empty_bare.git", "./empty", &g_options)); - /* Although the HEAD is orphaned... */ + /* Although the HEAD is unborn... */ cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo_cloned, local_name)); /* ...one can still retrieve the name of the remote tracking reference */ @@ -59,7 +59,7 @@ void test_clone_empty__can_clone_an_empty_local_repo_barely(void) cl_assert_equal_s(expected_remote_name, buffer); - /* ...even when the remote HEAD is orphaned as well */ + /* ...even when the remote HEAD is unborn as well */ cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo_cloned, expected_tracked_branch_name)); } diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 339b1e70d..5b9faa645 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -228,7 +228,7 @@ void test_clone_nonetwork__can_checkout_given_branch(void) g_options.checkout_branch = "test"; cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - cl_assert_equal_i(0, git_repository_head_orphan(g_repo)); + cl_assert_equal_i(0, git_repository_head_unborn(g_repo)); cl_git_pass(git_repository_head(&g_ref, g_repo)); cl_assert_equal_s(git_reference_name(g_ref), "refs/heads/test"); diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index bc4285a00..dc5aa4150 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -69,7 +69,7 @@ void test_online_clone__empty_repository(void) cl_git_pass(git_clone(&g_repo, LIVE_EMPTYREPO_URL, "./foo", &g_options)); cl_assert_equal_i(true, git_repository_is_empty(g_repo)); - cl_assert_equal_i(true, git_repository_head_orphan(g_repo)); + cl_assert_equal_i(true, git_repository_head_unborn(g_repo)); cl_git_pass(git_reference_lookup(&head, g_repo, GIT_HEAD_FILE)); cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); diff --git a/tests-clar/refs/branches/delete.c b/tests-clar/refs/branches/delete.c index 7af5a3e86..de90cb734 100644 --- a/tests-clar/refs/branches/delete.c +++ b/tests-clar/refs/branches/delete.c @@ -57,11 +57,11 @@ void test_refs_branches_delete__can_delete_a_branch_even_if_HEAD_is_missing(void git_reference_free(branch); } -void test_refs_branches_delete__can_delete_a_branch_when_HEAD_is_orphaned(void) +void test_refs_branches_delete__can_delete_a_branch_when_HEAD_is_unborn(void) { git_reference *branch; - make_head_orphaned(repo, NON_EXISTING_HEAD); + make_head_unborn(repo, NON_EXISTING_HEAD); cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL)); cl_git_pass(git_branch_delete(branch)); diff --git a/tests-clar/refs/branches/ishead.c b/tests-clar/refs/branches/ishead.c index dfcf1b5f1..b1ad09c3e 100644 --- a/tests-clar/refs/branches/ishead.c +++ b/tests-clar/refs/branches/ishead.c @@ -26,13 +26,13 @@ void test_refs_branches_ishead__can_tell_if_a_branch_is_pointed_at_by_HEAD(void) cl_assert_equal_i(true, git_branch_is_head(branch)); } -void test_refs_branches_ishead__can_properly_handle_orphaned_HEAD(void) +void test_refs_branches_ishead__can_properly_handle_unborn_HEAD(void) { git_repository_free(repo); repo = cl_git_sandbox_init("testrepo.git"); - make_head_orphaned(repo, NON_EXISTING_HEAD); + make_head_unborn(repo, NON_EXISTING_HEAD); cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master")); diff --git a/tests-clar/repo/head.c b/tests-clar/repo/head.c index a9f5cfc58..5a55984bd 100644 --- a/tests-clar/repo/head.c +++ b/tests-clar/repo/head.c @@ -32,20 +32,20 @@ void test_repo_head__head_detached(void) cl_assert_equal_i(false, git_repository_head_detached(repo)); } -void test_repo_head__head_orphan(void) +void test_repo_head__unborn_head(void) { git_reference *ref; cl_git_pass(git_repository_head_detached(repo)); - make_head_orphaned(repo, NON_EXISTING_HEAD); + make_head_unborn(repo, NON_EXISTING_HEAD); - cl_assert(git_repository_head_orphan(repo) == 1); + cl_assert(git_repository_head_unborn(repo) == 1); /* take the repo back to it's original state */ cl_git_pass(git_reference_symbolic_create(&ref, repo, "HEAD", "refs/heads/master", 1)); - cl_assert(git_repository_head_orphan(repo) == 0); + cl_assert(git_repository_head_unborn(repo) == 0); git_reference_free(ref); } @@ -58,7 +58,7 @@ void test_repo_head__set_head_Attaches_HEAD_to_un_unborn_branch_when_the_branch_ cl_assert_equal_i(false, git_repository_head_detached(repo)); - cl_assert_equal_i(GIT_EORPHANEDHEAD, git_repository_head(&head, repo)); + cl_assert_equal_i(GIT_EUNBORNBRANCH, git_repository_head(&head, repo)); } void test_repo_head__set_head_Returns_ENOTFOUND_when_the_reference_doesnt_exist(void) @@ -163,20 +163,20 @@ void test_repo_head__detach_head_Fails_if_HEAD_and_point_to_a_non_commitish(void git_reference_free(head); } -void test_repo_head__detaching_an_orphaned_head_returns_GIT_EORPHANEDHEAD(void) +void test_repo_head__detaching_an_unborn_branch_returns_GIT_EUNBORNBRANCH(void) { - make_head_orphaned(repo, NON_EXISTING_HEAD); + make_head_unborn(repo, NON_EXISTING_HEAD); - cl_assert_equal_i(GIT_EORPHANEDHEAD, git_repository_detach_head(repo)); + cl_assert_equal_i(GIT_EUNBORNBRANCH, git_repository_detach_head(repo)); } -void test_repo_head__retrieving_an_orphaned_head_returns_GIT_EORPHANEDHEAD(void) +void test_repo_head__retrieving_an_unborn_branch_returns_GIT_EUNBORNBRANCH(void) { git_reference *head; - make_head_orphaned(repo, NON_EXISTING_HEAD); + make_head_unborn(repo, NON_EXISTING_HEAD); - cl_assert_equal_i(GIT_EORPHANEDHEAD, git_repository_head(&head, repo)); + cl_assert_equal_i(GIT_EUNBORNBRANCH, git_repository_head(&head, repo)); } void test_repo_head__retrieving_a_missing_head_returns_GIT_ENOTFOUND(void) @@ -188,9 +188,9 @@ void test_repo_head__retrieving_a_missing_head_returns_GIT_ENOTFOUND(void) cl_assert_equal_i(GIT_ENOTFOUND, git_repository_head(&head, repo)); } -void test_repo_head__can_tell_if_an_orphaned_head_is_detached(void) +void test_repo_head__can_tell_if_an_unborn_head_is_detached(void) { - make_head_orphaned(repo, NON_EXISTING_HEAD); + make_head_unborn(repo, NON_EXISTING_HEAD); cl_assert_equal_i(false, git_repository_head_detached(repo)); } diff --git a/tests-clar/repo/headtree.c b/tests-clar/repo/headtree.c index 0e7fe93e5..e899ac399 100644 --- a/tests-clar/repo/headtree.c +++ b/tests-clar/repo/headtree.c @@ -36,13 +36,13 @@ void test_repo_headtree__can_retrieve_the_root_tree_from_a_non_detached_head(voi cl_assert(git_oid_streq(git_tree_id(tree), "az")); } -void test_repo_headtree__when_head_is_orphaned_returns_EORPHANEDHEAD(void) +void test_repo_headtree__when_head_is_unborn_returns_EUNBORNBRANCH(void) { - make_head_orphaned(repo, NON_EXISTING_HEAD); + make_head_unborn(repo, NON_EXISTING_HEAD); - cl_assert_equal_i(true, git_repository_head_orphan(repo)); + cl_assert_equal_i(true, git_repository_head_unborn(repo)); - cl_assert_equal_i(GIT_EORPHANEDHEAD, git_repository_head_tree(&tree, repo)); + cl_assert_equal_i(GIT_EUNBORNBRANCH, git_repository_head_tree(&tree, repo)); } void test_repo_headtree__when_head_is_missing_returns_ENOTFOUND(void) diff --git a/tests-clar/repo/repo_helpers.c b/tests-clar/repo/repo_helpers.c index 74902e439..3d477ff42 100644 --- a/tests-clar/repo/repo_helpers.c +++ b/tests-clar/repo/repo_helpers.c @@ -3,7 +3,7 @@ #include "repo_helpers.h" #include "posix.h" -void make_head_orphaned(git_repository* repo, const char *target) +void make_head_unborn(git_repository* repo, const char *target) { git_reference *head; diff --git a/tests-clar/repo/repo_helpers.h b/tests-clar/repo/repo_helpers.h index 09b5cac84..6783d5701 100644 --- a/tests-clar/repo/repo_helpers.h +++ b/tests-clar/repo/repo_helpers.h @@ -2,5 +2,5 @@ #define NON_EXISTING_HEAD "refs/heads/hide/and/seek" -extern void make_head_orphaned(git_repository* repo, const char *target); +extern void make_head_unborn(git_repository* repo, const char *target); extern void delete_head(git_repository* repo); diff --git a/tests-clar/reset/soft.c b/tests-clar/reset/soft.c index 884697c91..bd6fcc205 100644 --- a/tests-clar/reset/soft.c +++ b/tests-clar/reset/soft.c @@ -95,19 +95,19 @@ void test_reset_soft__cannot_reset_to_a_tag_not_pointing_at_a_commit(void) cl_git_fail(git_reset(repo, target, GIT_RESET_SOFT)); } -void test_reset_soft__resetting_against_an_orphaned_head_repo_makes_the_head_no_longer_orphaned(void) +void test_reset_soft__resetting_against_an_unborn_head_repo_makes_the_head_no_longer_unborn(void) { git_reference *head; retrieve_target_from_oid(&target, repo, KNOWN_COMMIT_IN_BARE_REPO); - make_head_orphaned(repo, NON_EXISTING_HEAD); + make_head_unborn(repo, NON_EXISTING_HEAD); - cl_assert_equal_i(true, git_repository_head_orphan(repo)); + cl_assert_equal_i(true, git_repository_head_unborn(repo)); cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT)); - cl_assert_equal_i(false, git_repository_head_orphan(repo)); + cl_assert_equal_i(false, git_repository_head_unborn(repo)); cl_git_pass(git_reference_lookup(&head, repo, NON_EXISTING_HEAD)); cl_assert_equal_i(0, git_oid_streq(git_reference_target(head), KNOWN_COMMIT_IN_BARE_REPO)); diff --git a/tests-clar/stash/save.c b/tests-clar/stash/save.c index eae116ac5..bb35a3d71 100644 --- a/tests-clar/stash/save.c +++ b/tests-clar/stash/save.c @@ -194,7 +194,7 @@ void test_stash_save__cannot_stash_against_an_unborn_branch(void) cl_git_pass(git_reference_symbolic_create(&head, repo, "HEAD", "refs/heads/unborn", 1)); - cl_assert_equal_i(GIT_EORPHANEDHEAD, + cl_assert_equal_i(GIT_EUNBORNBRANCH, git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); git_reference_free(head); diff --git a/tests-clar/submodule/lookup.c b/tests-clar/submodule/lookup.c index 013bbdf96..b626cdf04 100644 --- a/tests-clar/submodule/lookup.c +++ b/tests-clar/submodule/lookup.c @@ -114,15 +114,15 @@ void test_submodule_lookup__foreach(void) cl_assert_equal_i(8, data.count); } -void test_submodule_lookup__lookup_even_with_orphaned_head(void) +void test_submodule_lookup__lookup_even_with_unborn_head(void) { - git_reference *orphan; + git_reference *head; git_submodule *sm; - /* orphan the head */ + /* put us on an unborn branch */ cl_git_pass(git_reference_symbolic_create( - &orphan, g_repo, "HEAD", "refs/heads/garbage", 1)); - git_reference_free(orphan); + &head, g_repo, "HEAD", "refs/heads/garbage", 1)); + git_reference_free(head); /* lookup existing */ cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); -- cgit v1.2.1 From ffbd337aefae76a646bafd6e5f3c1edc18400f05 Mon Sep 17 00:00:00 2001 From: Linquize Date: Tue, 17 Sep 2013 22:57:06 +0800 Subject: Fix failure in win32_find_git_in_registry() The buffer size 0 was definitely not enough so it failed --- src/win32/findfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32/findfile.c b/src/win32/findfile.c index a1c11fcfb..eb83178a5 100644 --- a/src/win32/findfile.c +++ b/src/win32/findfile.c @@ -130,7 +130,7 @@ static int win32_find_git_in_registry( assert(buf); - path16.len = 0; + path16.len = MAX_PATH; if (RegOpenKeyExW(hieve, key, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) { if (RegQueryValueExW(hKey, L"InstallLocation", NULL, &dwType, -- cgit v1.2.1 From 89095fbddcba3c3e27d0573bc7202ca9a5f4f00b Mon Sep 17 00:00:00 2001 From: Linquize Date: Tue, 17 Sep 2013 22:57:30 +0800 Subject: Fix failure in win32_find_git_in_registry() when UAC is turned on Demand read only access to registry key instead of full access. This might happen in Windows Vista and later. --- src/win32/findfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32/findfile.c b/src/win32/findfile.c index eb83178a5..d8b8f60ca 100644 --- a/src/win32/findfile.c +++ b/src/win32/findfile.c @@ -132,7 +132,7 @@ static int win32_find_git_in_registry( path16.len = MAX_PATH; - if (RegOpenKeyExW(hieve, key, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) { + if (RegOpenKeyExW(hieve, key, 0, KEY_READ, &hKey) == ERROR_SUCCESS) { if (RegQueryValueExW(hKey, L"InstallLocation", NULL, &dwType, (LPBYTE)&path16.path, &path16.len) == ERROR_SUCCESS) { -- cgit v1.2.1 From f84bc3885327670babbfed1e351036d113fce903 Mon Sep 17 00:00:00 2001 From: Linquize Date: Tue, 17 Sep 2013 23:24:44 +0800 Subject: Refactor git_win32__find_system_dirs() to extract "etc\\" as subpath parameter --- src/fileops.c | 2 +- src/win32/findfile.c | 20 ++++++++++---------- src/win32/findfile.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 126d45f26..4dfc8a533 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -592,7 +592,7 @@ clean_up: static int git_futils_guess_system_dirs(git_buf *out) { #ifdef GIT_WIN32 - return git_win32__find_system_dirs(out); + return git_win32__find_system_dirs(out, L"etc\\"); #else return git_buf_sets(out, "/etc"); #endif diff --git a/src/win32/findfile.c b/src/win32/findfile.c index d8b8f60ca..a9e812e28 100644 --- a/src/win32/findfile.c +++ b/src/win32/findfile.c @@ -86,7 +86,7 @@ static wchar_t* win32_walkpath(wchar_t *path, wchar_t *buf, size_t buflen) return (path != base) ? path : NULL; } -static int win32_find_git_in_path(git_buf *buf, const wchar_t *gitexe) +static int win32_find_git_in_path(git_buf *buf, const wchar_t *gitexe, const wchar_t *subdir) { wchar_t *env = _wgetenv(L"PATH"), lastch; struct git_win32__path root; @@ -110,8 +110,8 @@ static int win32_find_git_in_path(git_buf *buf, const wchar_t *gitexe) wcscpy(&root.path[root.len], gitexe); if (_waccess(root.path, F_OK) == 0 && root.len > 5) { - /* replace "bin\\" or "cmd\\" with "etc\\" */ - wcscpy(&root.path[root.len - 4], L"etc\\"); + /* replace "bin\\" or "cmd\\" with subdir */ + wcscpy(&root.path[root.len - 4], subdir); win32_path_to_8(buf, root.path); return 0; @@ -122,7 +122,7 @@ static int win32_find_git_in_path(git_buf *buf, const wchar_t *gitexe) } static int win32_find_git_in_registry( - git_buf *buf, const HKEY hieve, const wchar_t *key) + git_buf *buf, const HKEY hieve, const wchar_t *key, const wchar_t *subdir) { HKEY hKey; DWORD dwType = REG_SZ; @@ -143,7 +143,7 @@ static int win32_find_git_in_registry( return -1; } - wcscat(path16.path, L"etc\\"); + wcscat(path16.path, subdir); path16.len += 4; win32_path_to_8(buf, path16.path); @@ -180,26 +180,26 @@ static int win32_find_existing_dirs( return (git_buf_oom(out) ? -1 : 0); } -int git_win32__find_system_dirs(git_buf *out) +int git_win32__find_system_dirs(git_buf *out, const wchar_t *subdir) { git_buf buf = GIT_BUF_INIT; /* directories where git.exe & git.cmd are found */ - if (!win32_find_git_in_path(&buf, L"git.exe") && buf.size) + if (!win32_find_git_in_path(&buf, L"git.exe", subdir) && buf.size) git_buf_set(out, buf.ptr, buf.size); else git_buf_clear(out); - if (!win32_find_git_in_path(&buf, L"git.cmd") && buf.size) + if (!win32_find_git_in_path(&buf, L"git.cmd", subdir) && buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); /* directories where git is installed according to registry */ if (!win32_find_git_in_registry( - &buf, HKEY_CURRENT_USER, REG_MSYSGIT_INSTALL_LOCAL) && buf.size) + &buf, HKEY_CURRENT_USER, REG_MSYSGIT_INSTALL_LOCAL, subdir) && buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); if (!win32_find_git_in_registry( - &buf, HKEY_LOCAL_MACHINE, REG_MSYSGIT_INSTALL) && buf.size) + &buf, HKEY_LOCAL_MACHINE, REG_MSYSGIT_INSTALL, subdir) && buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); git_buf_free(&buf); diff --git a/src/win32/findfile.h b/src/win32/findfile.h index fc79e1b72..11bf7e620 100644 --- a/src/win32/findfile.h +++ b/src/win32/findfile.h @@ -19,7 +19,7 @@ extern int git_win32__expand_path( extern int git_win32__find_file( git_buf *path, const struct git_win32__path *root, const char *filename); -extern int git_win32__find_system_dirs(git_buf *out); +extern int git_win32__find_system_dirs(git_buf *out, const wchar_t *subpath); extern int git_win32__find_global_dirs(git_buf *out); extern int git_win32__find_xdg_dirs(git_buf *out); -- cgit v1.2.1 From 7e8934bba206bf28e3f51eb583aadde051129b11 Mon Sep 17 00:00:00 2001 From: Linquize Date: Tue, 17 Sep 2013 23:29:02 +0800 Subject: Can guess win32 git template dir --- src/fileops.c | 12 +++++++++++- src/fileops.h | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 4dfc8a533..b7ae94b75 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -624,15 +624,25 @@ static int git_futils_guess_xdg_dirs(git_buf *out) #endif } +static int git_futils_guess_template_dirs(git_buf *out) +{ +#ifdef GIT_WIN32 + return git_win32__find_system_dirs(out, L"share\\git-core\\templates"); +#else + return git_buf_sets(out, "/usr/share/git-core/templates"); +#endif +} + typedef int (*git_futils_dirs_guess_cb)(git_buf *out); static git_buf git_futils__dirs[GIT_FUTILS_DIR__MAX] = - { GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT }; + { GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT }; static git_futils_dirs_guess_cb git_futils__dir_guess[GIT_FUTILS_DIR__MAX] = { git_futils_guess_system_dirs, git_futils_guess_global_dirs, git_futils_guess_xdg_dirs, + git_futils_guess_template_dirs, }; int git_futils_dirs_global_init(void) diff --git a/src/fileops.h b/src/fileops.h index 02f79b9e7..0ac9b9007 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -310,7 +310,8 @@ typedef enum { GIT_FUTILS_DIR_SYSTEM = 0, GIT_FUTILS_DIR_GLOBAL = 1, GIT_FUTILS_DIR_XDG = 2, - GIT_FUTILS_DIR__MAX = 3, + GIT_FUTILS_DIR_TEMPLATE = 3, + GIT_FUTILS_DIR__MAX = 4, } git_futils_dir_t; /** -- cgit v1.2.1 From b99b10f285fec710273d1233b057ff33a6e44993 Mon Sep 17 00:00:00 2001 From: Linquize Date: Tue, 17 Sep 2013 23:38:52 +0800 Subject: Can git_libgit2_opts() with GIT_OPT_GET_TEMPLATE_PATH and GIT_OPT_SET_TEMPLATE_PATH --- include/git2/common.h | 16 +++++++++++++++- src/util.c | 13 +++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/include/git2/common.h b/include/git2/common.h index d7df7327e..bb2e63637 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -136,7 +136,9 @@ typedef enum { GIT_OPT_SET_CACHE_OBJECT_LIMIT, GIT_OPT_SET_CACHE_MAX_SIZE, GIT_OPT_ENABLE_CACHING, - GIT_OPT_GET_CACHED_MEMORY + GIT_OPT_GET_CACHED_MEMORY, + GIT_OPT_GET_TEMPLATE_PATH, + GIT_OPT_SET_TEMPLATE_PATH } git_libgit2_opt_t; /** @@ -210,6 +212,18 @@ typedef enum { * > Get the current bytes in cache and the maximum that would be * > allowed in the cache. * + * * opts(GIT_OPT_GET_SEARCH_PATH, char *out, size_t len) + * + * > Get the default template path. + * > The path is written to the `out` + * > buffer up to size `len`. Returns GIT_EBUFS if buffer is too small. + * + * * opts(GIT_OPT_SET_TEMPLATE_PATH, const char *path) + * + * > Set the default template path. + * > + * > - `path` directory of template. + * * @param option Option key * @param ... value to set the option * @return 0 on success, <0 on failure diff --git a/src/util.c b/src/util.c index d0c326ae5..4bb1f7e4e 100644 --- a/src/util.c +++ b/src/util.c @@ -117,6 +117,19 @@ int git_libgit2_opts(int key, ...) *(va_arg(ap, ssize_t *)) = git_cache__current_storage.val; *(va_arg(ap, ssize_t *)) = git_cache__max_storage; break; + + case GIT_OPT_GET_TEMPLATE_PATH: + { + char *out = va_arg(ap, char *); + size_t outlen = va_arg(ap, size_t); + + error = git_futils_dirs_get_str(out, outlen, GIT_FUTILS_DIR_TEMPLATE); + } + break; + + case GIT_OPT_SET_TEMPLATE_PATH: + error = git_futils_dirs_set(GIT_FUTILS_DIR_TEMPLATE, va_arg(ap, const char *)); + break; } va_end(ap); -- cgit v1.2.1 From a025907e0d751ed1022e65365243ae97acf3f598 Mon Sep 17 00:00:00 2001 From: Linquize Date: Tue, 17 Sep 2013 23:55:11 +0800 Subject: Can load default template directory --- src/fileops.c | 9 ++++++++- src/fileops.h | 8 ++++++++ src/repository.c | 12 ++++++++---- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index b7ae94b75..ba88dfec7 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -763,7 +763,8 @@ static int git_futils_find_in_dirlist( continue; GITERR_CHECK_ERROR(git_buf_set(path, scan, len)); - GITERR_CHECK_ERROR(git_buf_joinpath(path, path->ptr, name)); + if (name) + GITERR_CHECK_ERROR(git_buf_joinpath(path, path->ptr, name)); if (git_path_exists(path->ptr)) return 0; @@ -792,6 +793,12 @@ int git_futils_find_xdg_file(git_buf *path, const char *filename) path, filename, GIT_FUTILS_DIR_XDG, "global/xdg"); } +int git_futils_find_template_dir(git_buf *path) +{ + return git_futils_find_in_dirlist( + path, NULL, GIT_FUTILS_DIR_TEMPLATE, "template"); +} + int git_futils_fake_symlink(const char *old, const char *new) { int retcode = GIT_ERROR; diff --git a/src/fileops.h b/src/fileops.h index 0ac9b9007..64d3da70a 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -306,6 +306,14 @@ extern int git_futils_find_xdg_file(git_buf *path, const char *filename); */ extern int git_futils_find_system_file(git_buf *path, const char *filename); +/** + * Find template directory. + * + * @param path buffer to write the full path into + * @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error + */ +extern int git_futils_find_template_dir(git_buf *path); + typedef enum { GIT_FUTILS_DIR_SYSTEM = 0, GIT_FUTILS_DIR_GLOBAL = 1, diff --git a/src/repository.c b/src/repository.c index eead41201..e67d1f013 100644 --- a/src/repository.c +++ b/src/repository.c @@ -33,8 +33,6 @@ #define GIT_REPO_VERSION 0 -#define GIT_TEMPLATE_DIR "/usr/share/git-core/templates" - static void set_odb(git_repository *repo, git_odb *odb) { if (odb) { @@ -1136,6 +1134,9 @@ static int repo_init_structure( if (external_tpl) { git_config *cfg; const char *tdir; + git_buf template_buf = GIT_BUF_INIT; + + git_futils_find_template_dir(&template_buf); if (opts->template_path) tdir = opts->template_path; @@ -1150,7 +1151,7 @@ static int repo_init_structure( return error; giterr_clear(); - tdir = GIT_TEMPLATE_DIR; + tdir = template_buf.ptr; } error = git_futils_cp_r(tdir, repo_dir, @@ -1158,14 +1159,17 @@ static int repo_init_structure( GIT_CPDIR_SIMPLE_TO_MODE, dmode); if (error < 0) { - if (strcmp(tdir, GIT_TEMPLATE_DIR) != 0) + if (strcmp(tdir, template_buf.ptr) != 0) { + git_buf_free(&template_buf); return error; + } /* if template was default, ignore error and use internal */ giterr_clear(); external_tpl = false; error = 0; } + git_buf_free(&template_buf); } /* Copy internal template -- cgit v1.2.1 From 0cf77103b218ad3622aff34f3296db1bdd5f0df9 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 26 Aug 2013 23:17:07 -0700 Subject: Start of filter API + git_blob_filtered_content This begins the process of exposing git_filter objects to the public API. This includes: * new public type and API for `git_buffer` through which an allocated buffer can be passed to the user * new API `git_blob_filtered_content` * make the git_filter type and GIT_FILTER_TO_... constants public --- include/git2.h | 3 ++ include/git2/blob.h | 32 +++++++++++++++++ include/git2/buffer.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++ include/git2/filter.h | 54 +++++++++++++++++++++++++++++ src/blob.c | 51 +++++++++++++++++++++++++++ src/buf_text.c | 19 ++++++---- src/buf_text.h | 8 ++--- src/buffer.c | 54 +++++++++++++++++++++++++++++ src/crlf.c | 20 ++++++----- src/filter.h | 19 +++++----- tests-clar/checkout/crlf.c | 11 +----- tests-clar/core/buffer.c | 47 ++++++++++++++++++++++--- tests-clar/filter/blob.c | 43 +++++++++++++++++++++++ tests-clar/filter/crlf.h | 26 ++++++++++++++ 14 files changed, 428 insertions(+), 45 deletions(-) create mode 100644 include/git2/buffer.h create mode 100644 include/git2/filter.h create mode 100644 tests-clar/filter/blob.c create mode 100644 tests-clar/filter/crlf.h diff --git a/include/git2.h b/include/git2.h index e8638a830..73c11ad83 100644 --- a/include/git2.h +++ b/include/git2.h @@ -58,4 +58,7 @@ #include "git2/stash.h" #include "git2/pathspec.h" +#include "git2/buffer.h" +#include "git2/filter.h" + #endif diff --git a/include/git2/blob.h b/include/git2/blob.h index 8fca48966..dcb815b2f 100644 --- a/include/git2/blob.h +++ b/include/git2/blob.h @@ -11,6 +11,7 @@ #include "types.h" #include "oid.h" #include "object.h" +#include "buffer.h" /** * @file git2/blob.h @@ -95,6 +96,37 @@ GIT_EXTERN(const void *) git_blob_rawcontent(const git_blob *blob); */ GIT_EXTERN(git_off_t) git_blob_rawsize(const git_blob *blob); +/** + * Get a buffer with the filtered content of a blob. + * + * This applies filters as if the blob was being checked out to the + * working directory under the specified filename. This may apply + * CRLF filtering or other types of changes depending on the file + * attributes set for the blob and the content detected in it. + * + * The output is written into a `git_buffer` which the caller must free + * when done (via `git_buffer_free`). + * + * If no filters need to be applied, then the `out` buffer will just be + * populated with a pointer to the raw content of the blob. In that case, + * be careful to *not* free the blob until done with the buffer. To keep + * the data detached from the blob, call `git_buffer_resize` on the buffer + * with a `want_size` of 0 and the buffer will be reallocated to be + * detached from the blob. + * + * @param out The git_buffer to be filled in + * @param blob Pointer to the blob + * @param as_path Path used for file attribute lookups, etc. + * @param check_for_binary_data Should this test if blob content contains + * NUL bytes / looks like binary data before applying filters? + * @return 0 on success or an error code + */ +GIT_EXTERN(int) git_blob_filtered_content( + git_buffer *out, + git_blob *blob, + const char *as_path, + int check_for_binary_data); + /** * Read a file from the working folder of a repository * and write it to the Object Database as a loose blob diff --git a/include/git2/buffer.h b/include/git2/buffer.h new file mode 100644 index 000000000..454a1faa5 --- /dev/null +++ b/include/git2/buffer.h @@ -0,0 +1,86 @@ +/* + * 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_buffer_h__ +#define INCLUDE_git_buffer_h__ + +#include "common.h" + +/** + * @file git2/buffer.h + * @brief Buffer export structure + * + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * A data buffer for exporting data from libgit2 + * + * There are a number of places where libgit2 wants to return an allocated + * data buffer to the caller and have the caller take ownership of that + * allocated memory. This can be awkward if the caller does not have easy + * access to the same allocation functions that libgit2 is using. In those + * cases, libgit2 will instead fill in a `git_buffer` and the caller can + * use `git_buffer_free()` to release it when they are done. + * + * * `ptr` refers to the start of the allocated memory. + * * `size` contains the size of the data in `ptr` that is actually used. + * * `available` refers to the known total amount of allocated memory in + * cases where it is larger than the `size` actually in use. + * + * In a few cases, for uniformity and simplicity, an API may populate a + * `git_buffer` with data that should *not* be freed (i.e. the lifetime of + * the data buffer is actually tied to another libgit2 object). These + * cases will be clearly documented in the APIs that use the `git_buffer`. + * In those cases, the `available` field will be set to zero even though + * the `ptr` and `size` will be valid. + */ +typedef struct git_buffer { + char *ptr; + size_t size; + size_t available; +} git_buffer; + +/** + * Use to initialize buffer structure when git_buffer is on stack + */ +#define GIT_BUFFER_INIT { NULL, 0, 0 } + +/** + * Free the memory referred to by the git_buffer. + * + * Note that this does not free the `git_buffer` itself, just the memory + * pointed to by `buffer->ptr`. If that memory was not allocated by + * libgit2 itself, be careful with using this function because it could + * cause problems. + * + * @param buffer The buffer with allocated memory + */ +GIT_EXTERN(void) git_buffer_free(git_buffer *buffer); + +/** + * Resize the buffer allocation to make more space. + * + * This will update `buffer->available` with the new size (which will be + * at least `want_size` and may be larger). This may or may not change + * `buffer->ptr` depending on whether there is an existing allocation and + * whether that allocation can be increased in place. + * + * Currently, this will never shrink the buffer, only expand it. + * + * @param buffer The buffer to be resized; may or may not be allocated yet + * @param want_size The desired available size + * @return 0 on success, negative error code on allocation failure + */ +GIT_EXTERN(int) git_buffer_resize(git_buffer *buffer, size_t want_size); + +GIT_END_DECL + +/** @} */ + +#endif diff --git a/include/git2/filter.h b/include/git2/filter.h new file mode 100644 index 000000000..3bc4a9037 --- /dev/null +++ b/include/git2/filter.h @@ -0,0 +1,54 @@ +/* + * 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_filter_h__ +#define INCLUDE_git_filter_h__ + +#include "common.h" +#include "types.h" +#include "oid.h" +#include "buffer.h" + +/** + * @file git2/filter.h + * @brief Git filter APIs + * + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Filters are applied in one of two directions: smudging - which is + * exporting a file from the Git object database to the working directory, + * and cleaning - which is importing a file from the working directory to + * the Git object database. These values control which direction of + * change is being applied. + */ +typedef enum { + GIT_FILTER_SMUDGE = 0, + GIT_FILTER_TO_WORKTREE = GIT_FILTER_SMUDGE, + GIT_FILTER_CLEAN = 1, + GIT_FILTER_TO_ODB = GIT_FILTER_CLEAN, +} git_filter_mode_t; + +/** + * A filter that can transform file data + * + * This represents a filter that can be used to transform or even replace + * file data. Libgit2 currently includes one built in filter: + * + * * "crlf" which uses the complex rules with the "text", "eol", and + * "crlf" file attributes to decide how to convert between LF and CRLF + * line endings + */ +typedef struct git_filter git_filter; + +GIT_END_DECL + +/** @} */ + +#endif diff --git a/src/blob.c b/src/blob.c index 6a289f43b..6a866538c 100644 --- a/src/blob.c +++ b/src/blob.c @@ -338,3 +338,54 @@ int git_blob_is_binary(git_blob *blob) return git_buf_text_is_binary(&content); } + +int git_blob_filtered_content( + git_buffer *out, + git_blob *blob, + const char *as_path, + int check_for_binary_data) +{ + int error = 0, num_filters = 0; + git_buf filtered = GIT_BUF_INIT, unfiltered = GIT_BUF_INIT; + git_vector filters = GIT_VECTOR_INIT; + + assert(blob && as_path && out); + + /* Create a fake git_buf from the blob raw data... */ + filtered.ptr = (void *)git_blob_rawcontent(blob); + filtered.size = (size_t)git_blob_rawsize(blob); + filtered.asize = 0; + + if (check_for_binary_data && git_buf_text_is_binary(&filtered)) + return 0; + + num_filters = git_filters_load( + &filters, git_blob_owner(blob), as_path, GIT_FILTER_TO_WORKTREE); + if (num_filters < 0) + return num_filters; + + if (num_filters > 0) { + if (out->ptr && out->available) { + filtered.ptr = out->ptr; + filtered.size = out->size; + filtered.asize = out->available; + } else { + git_buf_init(&filtered, filtered.size + 1); + } + + if (!(error = git_blob__getbuf(&unfiltered, blob))) + error = git_filters_apply(&filtered, &unfiltered, &filters); + + git_filters_free(&filters); + git_buf_free(&unfiltered); + } + + if (!error) { + out->ptr = filtered.ptr; + out->size = filtered.size; + out->available = filtered.asize; + } + + return error; +} + diff --git a/src/buf_text.c b/src/buf_text.c index ecf592b51..eda86adb3 100644 --- a/src/buf_text.c +++ b/src/buf_text.c @@ -70,10 +70,10 @@ int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src) assert(tgt != src); if (!next) - return GIT_ENOTFOUND; + return git_buf_set(tgt, src->ptr, src->size); /* reduce reallocs while in the loop */ - if (git_buf_grow(tgt, src->size) < 0) + if (git_buf_grow(tgt, src->size + 1) < 0) return -1; out = tgt->ptr; tgt->size = 0; @@ -81,7 +81,7 @@ int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src) /* Find the next \r and copy whole chunk up to there to tgt */ for (; next; scan = next + 1, next = memchr(scan, '\r', scan_end - scan)) { if (next > scan) { - size_t copylen = next - scan; + size_t copylen = (size_t)(next - scan); memcpy(out, scan, copylen); out += copylen; } @@ -92,9 +92,14 @@ int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src) } /* Copy remaining input into dest */ - memcpy(out, scan, scan_end - scan + 1); /* +1 for NUL byte */ - out += (scan_end - scan); - tgt->size = out - tgt->ptr; + if (scan < scan_end) { + size_t remaining = (size_t)(scan_end - scan); + memcpy(out, scan, remaining); + out += remaining; + } + + tgt->size = (size_t)(out - tgt->ptr); + tgt->ptr[tgt->size] = '\0'; return 0; } @@ -109,7 +114,7 @@ int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src) assert(tgt != src); if (!next) - return GIT_ENOTFOUND; + return git_buf_set(tgt, src->ptr, src->size); /* attempt to reduce reallocs while in the loop */ if (git_buf_grow(tgt, src->size + (src->size >> 4) + 1) < 0) diff --git a/src/buf_text.h b/src/buf_text.h index 58e4e26a7..3ac9d1443 100644 --- a/src/buf_text.h +++ b/src/buf_text.h @@ -56,16 +56,16 @@ GIT_INLINE(int) git_buf_text_puts_escape_regex(git_buf *buf, const char *string) extern void git_buf_text_unescape(git_buf *buf); /** - * Replace all \r\n with \n (or do nothing if no \r\n are found) + * Replace all \r\n with \n. Does not modify \r without trailing \n. * - * @return 0 on success, GIT_ENOTFOUND if no \r\n, -1 on memory error + * @return 0 on success, -1 on memory error */ extern int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src); /** - * Replace all \n with \r\n (or do nothing if no \n are found) + * Replace all \n with \r\n. Does not modify existing \r\n. * - * @return 0 on success, GIT_ENOTFOUND if no \n, -1 on memory error + * @return 0 on success, -1 on memory error */ extern int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src); diff --git a/src/buffer.c b/src/buffer.c index b5b2fd678..a92133674 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -6,6 +6,7 @@ */ #include "buffer.h" #include "posix.h" +#include "git2/buffer.h" #include #include @@ -484,3 +485,56 @@ int git_buf_splice( buf->ptr[buf->size] = '\0'; return 0; } + +/* + * Public buffers API + */ + +void git_buffer_free(git_buffer *buffer) +{ + if (!buffer) + return; + + if (buffer->ptr != NULL && buffer->available > 0) + git__free(buffer->ptr); + + git__memzero(buffer, sizeof(*buffer)); +} + +int git_buffer_resize(git_buffer *buffer, size_t want_size) +{ + int non_allocated_buffer = 0; + char *new_ptr; + + assert(buffer); + + /* check if buffer->ptr points to memory owned elsewhere */ + non_allocated_buffer = (buffer->ptr != NULL && buffer->available == 0); + + if (non_allocated_buffer && !want_size) + want_size = buffer->size; + + if (buffer->available <= want_size) + return 0; + + if (non_allocated_buffer) { + new_ptr = NULL; + if (want_size < buffer->size) + want_size = buffer->size; + } else { + new_ptr = buffer->ptr; + } + + want_size = (want_size + 7) & ~7; /* round up to multiple of 8 */ + + new_ptr = git__realloc(new_ptr, want_size); + GITERR_CHECK_ALLOC(new_ptr); + + if (non_allocated_buffer) + memcpy(new_ptr, buffer->ptr, buffer->size); + + buffer->ptr = new_ptr; + buffer->available = want_size; + + return 0; +} diff --git a/src/crlf.c b/src/crlf.c index 65039f9cc..fbb3ba2dd 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -235,32 +235,36 @@ line_ending_error: } static int crlf_apply_to_workdir( - git_filter *self, git_buf *dest, const git_buf *source) + git_filter *self, git_buf *tgt, const git_buf *src) { struct crlf_filter *filter = (struct crlf_filter *)self; const char *workdir_ending = NULL; - assert(self && dest && source); + assert(self && tgt && src); /* Empty file? Nothing to do. */ - if (git_buf_len(source) == 0) + if (git_buf_len(src) == 0) return -1; /* Determine proper line ending */ workdir_ending = line_ending(filter); if (!workdir_ending) return -1; - if (!strcmp("\n", workdir_ending)) /* do nothing for \n ending */ - return -1; - /* for now, only lf->crlf conversion is supported here */ + if (!strcmp("\n", workdir_ending)) { + if (git_buf_find(src, '\r') < 0) + return -1; + return git_buf_text_crlf_to_lf(tgt, src); + } + + /* only other supported option is lf->crlf conversion */ assert(!strcmp("\r\n", workdir_ending)); - return git_buf_text_lf_to_crlf(dest, source); + return git_buf_text_lf_to_crlf(tgt, src); } static int find_and_add_filter( git_vector *filters, git_repository *repo, const char *path, - int (*apply)(struct git_filter *self, git_buf *dest, const git_buf *source)) + int (*apply)(struct git_filter *self, git_buf *tgt, const git_buf *src)) { struct crlf_attrs ca; struct crlf_filter *filter; diff --git a/src/filter.h b/src/filter.h index 42a44ebdb..67845ad6a 100644 --- a/src/filter.h +++ b/src/filter.h @@ -11,16 +11,12 @@ #include "buffer.h" #include "git2/odb.h" #include "git2/repository.h" +#include "git2/filter.h" -typedef struct git_filter { +struct git_filter { int (*apply)(struct git_filter *self, git_buf *dest, const git_buf *source); void (*do_free)(struct git_filter *self); -} git_filter; - -typedef enum { - GIT_FILTER_TO_WORKTREE, - GIT_FILTER_TO_ODB -} git_filter_mode; +}; typedef enum { GIT_CRLF_GUESS = -1, @@ -60,13 +56,14 @@ extern int git_filters_load(git_vector *filters, git_repository *repo, const cha * and `dest` buffers are owned by the caller and must be freed once * they are no longer needed. * - * NOTE: Because of the double-buffering schema, the `source` buffer that contains - * the original file may be tampered once the filtering is complete. Regardless, - * the `dest` buffer will always contain the final result of the filtering + * NOTE: Because of the double-buffering schema, the `source` buffer that + * contains the original file may be tampered once the filtering is + * complete. Regardless, the `dest` buffer will always contain the final + * result of the filtering * * @param dest Buffer to store the result of the filtering * @param source Buffer containing the document to filter - * @param filters A non-empty vector of filters as supplied by `git_filters_load` + * @param filters Vector of filters as supplied by `git_filters_load` * @return 0 on success, an error code otherwise */ extern int git_filters_apply(git_buf *dest, git_buf *source, git_vector *filters); diff --git a/tests-clar/checkout/crlf.c b/tests-clar/checkout/crlf.c index 285b1f272..5f5f1b776 100644 --- a/tests-clar/checkout/crlf.c +++ b/tests-clar/checkout/crlf.c @@ -1,19 +1,10 @@ #include "clar_libgit2.h" #include "checkout_helpers.h" +#include "../filter/crlf.h" #include "git2/checkout.h" #include "repository.h" -#define UTF8_BOM "\xEF\xBB\xBF" -#define ALL_CRLF_TEXT_RAW "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n" -#define ALL_LF_TEXT_RAW "lf\nlf\nlf\nlf\nlf\n" -#define MORE_CRLF_TEXT_RAW "crlf\r\ncrlf\r\nlf\ncrlf\r\ncrlf\r\n" -#define MORE_LF_TEXT_RAW "lf\nlf\ncrlf\r\nlf\nlf\n" - -#define ALL_LF_TEXT_AS_CRLF "lf\r\nlf\r\nlf\r\nlf\r\nlf\r\n" -#define MORE_CRLF_TEXT_AS_CRLF "crlf\r\ncrlf\r\nlf\r\ncrlf\r\ncrlf\r\n" -#define MORE_LF_TEXT_AS_CRLF "lf\r\nlf\r\ncrlf\r\nlf\r\nlf\r\n" - static git_repository *g_repo; void test_checkout_crlf__initialize(void) diff --git a/tests-clar/core/buffer.c b/tests-clar/core/buffer.c index 8a0b6711f..11d173d49 100644 --- a/tests-clar/core/buffer.c +++ b/tests-clar/core/buffer.c @@ -919,6 +919,8 @@ void test_core_buffer__similarity_metric_whitespace(void) git_buf_free(&buf); } +#include "../filter/crlf.h" + #define check_buf(expected,buf) do { \ cl_assert_equal_s(expected, buf.ptr); \ cl_assert_equal_sz(strlen(expected), buf.size); } while (0) @@ -934,16 +936,16 @@ void test_core_buffer__lf_and_crlf_conversions(void) cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); check_buf("lf\r\nlf\r\nlf\r\nlf\r\n", tgt); - cl_assert_equal_i(GIT_ENOTFOUND, git_buf_text_crlf_to_lf(&tgt, &src)); - /* no conversion needed if all LFs already */ + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf(src.ptr, tgt); git_buf_sets(&src, "\nlf\nlf\nlf\nlf\nlf"); cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); check_buf("\r\nlf\r\nlf\r\nlf\r\nlf\r\nlf", tgt); - cl_assert_equal_i(GIT_ENOTFOUND, git_buf_text_crlf_to_lf(&tgt, &src)); - /* no conversion needed if all LFs already */ + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf(src.ptr, tgt); /* CRLF source */ @@ -993,10 +995,45 @@ void test_core_buffer__lf_and_crlf_conversions(void) check_buf("\rcrlf\nlf\nlf\ncr\rcrlf\nlf\ncr\r", tgt); git_buf_sets(&src, "\rcr\r"); - cl_assert_equal_i(GIT_ENOTFOUND, git_buf_text_lf_to_crlf(&tgt, &src)); + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf(src.ptr, tgt); cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); check_buf("\rcr\r", tgt); git_buf_free(&src); git_buf_free(&tgt); + + /* blob correspondence tests */ + + git_buf_sets(&src, ALL_CRLF_TEXT_RAW); + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf(ALL_CRLF_TEXT_AS_CRLF, tgt); + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf(ALL_CRLF_TEXT_AS_LF, tgt); + git_buf_free(&src); + git_buf_free(&tgt); + + git_buf_sets(&src, ALL_LF_TEXT_RAW); + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf(ALL_LF_TEXT_AS_CRLF, tgt); + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf(ALL_LF_TEXT_AS_LF, tgt); + git_buf_free(&src); + git_buf_free(&tgt); + + git_buf_sets(&src, MORE_CRLF_TEXT_RAW); + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf(MORE_CRLF_TEXT_AS_CRLF, tgt); + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf(MORE_CRLF_TEXT_AS_LF, tgt); + git_buf_free(&src); + git_buf_free(&tgt); + + git_buf_sets(&src, MORE_LF_TEXT_RAW); + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf(MORE_LF_TEXT_AS_CRLF, tgt); + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf(MORE_LF_TEXT_AS_LF, tgt); + git_buf_free(&src); + git_buf_free(&tgt); } diff --git a/tests-clar/filter/blob.c b/tests-clar/filter/blob.c new file mode 100644 index 000000000..27e001f99 --- /dev/null +++ b/tests-clar/filter/blob.c @@ -0,0 +1,43 @@ +#include "clar_libgit2.h" +#include "crlf.h" + +static git_repository *g_repo = NULL; + +void test_filter_blob__initialize(void) +{ + g_repo = cl_git_sandbox_init("crlf"); + cl_git_mkfile("crlf/.gitattributes", + "*.txt text\n*.bin binary\n*.crlf text eol=crlf\n*.lf text eol=lf\n"); +} + +void test_filter_blob__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_filter_blob__all_crlf(void) +{ + git_blob *blob; + git_buffer buf = GIT_BUFFER_INIT; + + cl_git_pass(git_revparse_single( + (git_object **)&blob, g_repo, "a9a2e891")); /* all-crlf */ + + cl_assert_equal_s(ALL_CRLF_TEXT_RAW, git_blob_rawcontent(blob)); + + cl_git_pass(git_blob_filtered_content(&buf, blob, "file.bin", 1)); + + cl_assert_equal_s(ALL_CRLF_TEXT_RAW, buf.ptr); + + cl_git_pass(git_blob_filtered_content(&buf, blob, "file.crlf", 1)); + + /* in this case, raw content has crlf in it already */ + cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr); + + cl_git_pass(git_blob_filtered_content(&buf, blob, "file.lf", 1)); + + cl_assert_equal_s(ALL_CRLF_TEXT_AS_LF, buf.ptr); + + git_buffer_free(&buf); + git_blob_free(blob); +} diff --git a/tests-clar/filter/crlf.h b/tests-clar/filter/crlf.h new file mode 100644 index 000000000..8fadee950 --- /dev/null +++ b/tests-clar/filter/crlf.h @@ -0,0 +1,26 @@ +#ifndef INCLUDE_filter_crlf_h__ +#define INCLUDE_filter_crlf_h__ + +/* + * file content for files in the resources/crlf repository + */ + +#define UTF8_BOM "\xEF\xBB\xBF" + +#define ALL_CRLF_TEXT_RAW "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n" +#define ALL_LF_TEXT_RAW "lf\nlf\nlf\nlf\nlf\n" +#define MORE_CRLF_TEXT_RAW "crlf\r\ncrlf\r\nlf\ncrlf\r\ncrlf\r\n" +#define MORE_LF_TEXT_RAW "lf\nlf\ncrlf\r\nlf\nlf\n" + +#define ALL_CRLF_TEXT_AS_CRLF ALL_CRLF_TEXT_RAW +#define ALL_LF_TEXT_AS_CRLF "lf\r\nlf\r\nlf\r\nlf\r\nlf\r\n" +#define MORE_CRLF_TEXT_AS_CRLF "crlf\r\ncrlf\r\nlf\r\ncrlf\r\ncrlf\r\n" +#define MORE_LF_TEXT_AS_CRLF "lf\r\nlf\r\ncrlf\r\nlf\r\nlf\r\n" + +#define ALL_CRLF_TEXT_AS_LF "crlf\ncrlf\ncrlf\ncrlf\n" +#define ALL_LF_TEXT_AS_LF ALL_LF_TEXT_RAW +#define MORE_CRLF_TEXT_AS_LF "crlf\ncrlf\nlf\ncrlf\ncrlf\n" +#define MORE_LF_TEXT_AS_LF "lf\nlf\ncrlf\nlf\nlf\n" + + +#endif -- cgit v1.2.1 From 85d5481206a932d747b2d5587b6d4c7f69993ba6 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 28 Aug 2013 16:44:04 -0700 Subject: Create public filter object and use it This creates include/sys/filter.h with a basic definition of a git_filter and then converts the internal code to use it. There are related internal objects (git_filter_list) that we will want to publish at some point, but this is a first step. --- include/git2/filter.h | 16 +++- include/git2/sys/filter.h | 104 ++++++++++++++++++++++++ src/blob.c | 48 +++++------ src/buffer.h | 22 +++++ src/checkout.c | 56 +++++-------- src/crlf.c | 171 ++++++++++++++++++++++---------------- src/diff.c | 12 +-- src/diff_file.c | 46 +++++------ src/filter.c | 176 ++++++++++++++++++++++++++++++++-------- src/filter.h | 61 +++++++------- src/odb.c | 6 +- src/odb.h | 3 +- src/repository.c | 8 +- tests-clar/object/blob/filter.c | 12 +-- 14 files changed, 497 insertions(+), 244 deletions(-) create mode 100644 include/git2/sys/filter.h diff --git a/include/git2/filter.h b/include/git2/filter.h index 3bc4a9037..478f3a6ad 100644 --- a/include/git2/filter.h +++ b/include/git2/filter.h @@ -39,7 +39,10 @@ typedef enum { * A filter that can transform file data * * This represents a filter that can be used to transform or even replace - * file data. Libgit2 currently includes one built in filter: + * file data. Libgit2 includes one built in filter and it is possible to + * write your own (see git2/sys/filter.h for information on that). + * + * The built in filter is: * * * "crlf" which uses the complex rules with the "text", "eol", and * "crlf" file attributes to decide how to convert between LF and CRLF @@ -47,6 +50,17 @@ typedef enum { */ typedef struct git_filter git_filter; +GIT_EXTERN(git_filter *) git_filter_lookup(const char *name); + +#define GIT_FILTER_CRLF "crlf" + +GIT_EXTERN(int) git_filter_apply_to_buffer( + git_buffer *out, + git_filter *filter, + const git_buffer *input, + const char *as_path, + git_filter_mode_t mode); + GIT_END_DECL /** @} */ diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h new file mode 100644 index 000000000..2264be080 --- /dev/null +++ b/include/git2/sys/filter.h @@ -0,0 +1,104 @@ +/* + * 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_sys_git_config_backend_h__ +#define INCLUDE_sys_git_config_backend_h__ + +#include "git2/filter.h" + +/** + * @file git2/sys/filter.h + * @brief Git filter backend and plugin routines + * @defgroup git_backend Git custom backend APIs + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * A filter source represents a file/blob to be processed + */ +typedef struct git_filter_source git_filter_source; +struct git_filter_source { + git_repository *repo; + const char *path; + git_oid oid; /* zero if unknown (which is likely) */ + uint16_t filemode; /* zero if unknown */ +}; + +/** + * Callback to actually perform the data filtering + */ +typedef int (*git_filter_apply_fn)( + git_filter *self, + void **payload, /* may be read and/or set */ + git_filter_mode_t mode, + git_buffer *to, + const git_buffer *from, + const git_filter_source *src); + +/** + * Callback to decide if a given source needs this filter + */ +typedef int (*git_filter_check_fn)( + git_filter *self, + void **payload, /* points to NULL ptr on entry, may be set */ + git_filter_mode_t mode, + const git_filter_source *src); + +/** + * Callback to clean up after filtering has been applied + */ +typedef void (*git_filter_cleanup_fn)( + git_filter *self, + void *payload); + +/** + * Filter structure used to register a new filter. + * + * To associate extra data with a filter, simply allocate extra data + * and put the `git_filter` struct at the start of your data buffer, + * then cast the `self` pointer to your larger structure when your + * callback is invoked. + * + * `version` should be set to GIT_FILTER_VERSION + * + * `apply` is the callback that actually filters data. + * + * `check` is an optional callback that checks if filtering is needed for + * a given source. + * + * `cleanup` is an optional callback that is made after the filter has + * been applied. Both the `check` and `apply` callbacks are able to + * allocate a `payload` to keep per-source filter state, and this callback + * is given that value and can clean up as needed. + */ +struct git_filter { + unsigned int version; + git_filter_apply_fn apply; + git_filter_check_fn check; + git_filter_cleanup_fn cleanup; +}; + +#define GIT_FILTER_VERSION 1 + +/** + * Register a filter under a given name + * + * Two filters will be preregistered with libgit2: GIT_FILTER_CRLF and + * GIT_FILTER_IDENT. + */ +GIT_EXTERN(int) git_filter_register( + const char *name, const git_filter *filter); + +/** + * Remove the filter with the given name + */ +GIT_EXTERN(int) git_filter_unregister(const char *name); + +/** @} */ +GIT_END_DECL +#endif diff --git a/src/blob.c b/src/blob.c index 6a866538c..3581ee9d1 100644 --- a/src/blob.c +++ b/src/blob.c @@ -108,7 +108,7 @@ static int write_file_filtered( git_off_t *size, git_odb *odb, const char *full_path, - git_vector *filters) + git_filter_list *fl) { int error; git_buf source = GIT_BUF_INIT; @@ -117,7 +117,7 @@ static int write_file_filtered( if ((error = git_futils_readbuffer(&source, full_path)) < 0) return error; - error = git_filters_apply(&dest, &source, filters); + error = git_filter_list_apply(&dest, &source, fl); /* Free the source as soon as possible. This can be big in memory, * and we don't want to ODB write to choke */ @@ -198,29 +198,25 @@ int git_blob__create_from_paths( if (S_ISLNK(mode)) { error = write_symlink(oid, odb, content_path, (size_t)size); } else { - git_vector write_filters = GIT_VECTOR_INIT; - int filter_count = 0; + git_filter_list *fl = NULL; - if (try_load_filters) { + if (try_load_filters) /* Load the filters for writing this file to the ODB */ - filter_count = git_filters_load( - &write_filters, repo, hint_path, GIT_FILTER_TO_ODB); - } + error = git_filter_list_load( + &fl, repo, hint_path, GIT_FILTER_TO_ODB); - if (filter_count < 0) { - /* Negative value means there was a critical error */ - error = filter_count; - } else if (filter_count == 0) { + if (error < 0) + /* well, that didn't work */; + else if (fl == NULL) /* No filters need to be applied to the document: we can stream * directly from disk */ error = write_file_stream(oid, odb, content_path, size); - } else { + else { /* We need to apply one or more filters */ - error = write_file_filtered( - oid, &size, odb, content_path, &write_filters); - } + error = write_file_filtered(oid, &size, odb, content_path, fl); - git_filters_free(&write_filters); + git_filter_list_free(fl); + } /* * TODO: eventually support streaming filtered files, for files @@ -345,9 +341,9 @@ int git_blob_filtered_content( const char *as_path, int check_for_binary_data) { - int error = 0, num_filters = 0; + int error = 0; git_buf filtered = GIT_BUF_INIT, unfiltered = GIT_BUF_INIT; - git_vector filters = GIT_VECTOR_INIT; + git_filter_list *fl = NULL; assert(blob && as_path && out); @@ -359,12 +355,12 @@ int git_blob_filtered_content( if (check_for_binary_data && git_buf_text_is_binary(&filtered)) return 0; - num_filters = git_filters_load( - &filters, git_blob_owner(blob), as_path, GIT_FILTER_TO_WORKTREE); - if (num_filters < 0) - return num_filters; + error = git_filter_list_load( + &fl, git_blob_owner(blob), as_path, GIT_FILTER_TO_WORKTREE); + if (error < 0) + return error; - if (num_filters > 0) { + if (fl != NULL) { if (out->ptr && out->available) { filtered.ptr = out->ptr; filtered.size = out->size; @@ -374,9 +370,9 @@ int git_blob_filtered_content( } if (!(error = git_blob__getbuf(&unfiltered, blob))) - error = git_filters_apply(&filtered, &unfiltered, &filters); + error = git_filter_list_apply(&filtered, &unfiltered, fl); - git_filters_free(&filters); + git_filter_list_free(fl); git_buf_free(&unfiltered); } diff --git a/src/buffer.h b/src/buffer.h index f3e1d506f..b1cb5d06a 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -9,6 +9,7 @@ #include "common.h" #include "git2/strarray.h" +#include "git2/buffer.h" #include typedef struct { @@ -174,4 +175,25 @@ int git_buf_splice( const char *data, size_t nb_to_insert); + +#define GIT_BUF_FROM_BUFFER(buffer) \ + { (buffer)->ptr, (buffer)->available, (buffer)->size } + +GIT_INLINE(void) git_buf_from_buffer(git_buf *buf, const git_buffer *buffer) +{ + buf->ptr = buffer->ptr; + buf->size = buffer->size; + buf->asize = buffer->available; +} + +#define GIT_BUFFER_FROM_BUF(buf) \ + { (buf)->ptr, (buf)->size, (buf)->asize } + +GIT_INLINE(void) git_buffer_from_buf(git_buffer *buffer, const git_buf *buf) +{ + buffer->ptr = buf->ptr; + buffer->size = buf->size; + buffer->available = buf->asize; +} + #endif diff --git a/src/checkout.c b/src/checkout.c index eb92e8fd6..5ce4a19c5 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -710,56 +710,40 @@ static int blob_content_to_file( mode_t entry_filemode, git_checkout_opts *opts) { - int error = -1, nb_filters = 0; - mode_t file_mode = opts->file_mode; - bool dont_free_filtered; + int error = 0; + mode_t file_mode = opts->file_mode ? opts->file_mode : entry_filemode; git_buf unfiltered = GIT_BUF_INIT, filtered = GIT_BUF_INIT; - git_vector filters = GIT_VECTOR_INIT; + git_filter_list *fl = NULL; /* Create a fake git_buf from the blob raw data... */ filtered.ptr = (void *)git_blob_rawcontent(blob); filtered.size = (size_t)git_blob_rawsize(blob); - /* ... and make sure it doesn't get unexpectedly freed */ - dont_free_filtered = true; - - if (!opts->disable_filters && - !git_buf_text_is_binary(&filtered) && - (nb_filters = git_filters_load( - &filters, - git_object_owner((git_object *)blob), - path, - GIT_FILTER_TO_WORKTREE)) > 0) - { + + if (!opts->disable_filters && !git_buf_text_is_binary(&filtered)) { + error = git_filter_list_load( + &fl, git_blob_owner(blob), path, GIT_FILTER_TO_WORKTREE); + } + + if (fl != NULL) { /* reset 'filtered' so it can be a filter target */ git_buf_init(&filtered, 0); - dont_free_filtered = false; - } - if (nb_filters < 0) - return nb_filters; + if (!(error = git_blob__getbuf(&unfiltered, blob))) { + error = git_filter_list_apply(&filtered, &unfiltered, fl); - if (nb_filters > 0) { - if ((error = git_blob__getbuf(&unfiltered, blob)) < 0) - goto cleanup; + git_buf_free(&unfiltered); + } - if ((error = git_filters_apply(&filtered, &unfiltered, &filters)) < 0) - goto cleanup; + git_filter_list_free(fl); } - /* Allow overriding of file mode */ - if (!file_mode) - file_mode = entry_filemode; - - error = buffer_to_file( - st, &filtered, path, opts->dir_mode, opts->file_open_flags, file_mode); - - if (!error) + if (!error && + !(error = buffer_to_file( + st, &filtered, path, opts->dir_mode, + opts->file_open_flags, file_mode))) st->st_mode = entry_filemode; -cleanup: - git_filters_free(&filters); - git_buf_free(&unfiltered); - if (!dont_free_filtered) + if (filtered.asize != 0) git_buf_free(&filtered); return error; diff --git a/src/crlf.c b/src/crlf.c index fbb3ba2dd..2177bff98 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -19,13 +19,11 @@ struct crlf_attrs { int crlf_action; int eol; + int auto_crlf; }; struct crlf_filter { git_filter f; - struct crlf_attrs attrs; - git_repository *repo; - char path[GIT_FLEX_ARRAY]; }; static int check_crlf(const char *value) @@ -76,7 +74,8 @@ static int crlf_input_action(struct crlf_attrs *ca) return ca->crlf_action; } -static int crlf_load_attributes(struct crlf_attrs *ca, git_repository *repo, const char *path) +static int crlf_load_attributes( + struct crlf_attrs *ca, git_repository *repo, const char *path) { #define NUM_CONV_ATTRS 3 @@ -108,9 +107,8 @@ static int crlf_load_attributes(struct crlf_attrs *ca, git_repository *repo, con return -1; } -static int has_cr_in_index(git_filter *self) +static int has_cr_in_index(git_repository *repo, const char *path) { - struct crlf_filter *filter = (struct crlf_filter *)self; git_index *index; const git_index_entry *entry; git_blob *blob; @@ -118,19 +116,19 @@ static int has_cr_in_index(git_filter *self) git_off_t blobsize; bool found_cr; - if (git_repository_index__weakptr(&index, filter->repo) < 0) { + if (git_repository_index__weakptr(&index, repo) < 0) { giterr_clear(); return false; } - if (!(entry = git_index_get_bypath(index, filter->path, 0)) && - !(entry = git_index_get_bypath(index, filter->path, 1))) + if (!(entry = git_index_get_bypath(index, path, 0)) && + !(entry = git_index_get_bypath(index, path, 1))) return false; if (!S_ISREG(entry->mode)) /* don't crlf filter non-blobs */ return true; - if (git_blob_lookup(&blob, filter->repo, &entry->oid) < 0) + if (git_blob_lookup(&blob, repo, &entry->oid) < 0) return false; blobcontent = git_blob_rawcontent(blob); @@ -147,26 +145,26 @@ static int has_cr_in_index(git_filter *self) } static int crlf_apply_to_odb( - git_filter *self, git_buf *dest, const git_buf *source) + struct crlf_attrs *ca, + git_buffer *to, + const git_buffer *from, + const git_filter_source *src) { - struct crlf_filter *filter = (struct crlf_filter *)self; - - assert(self && dest && source); + const git_buf from_buf = GIT_BUF_FROM_BUFFER(from); + git_buf to_buf = GIT_BUF_FROM_BUFFER(to); /* Empty file? Nothing to do */ - if (git_buf_len(source) == 0) + if (!git_buf_len(&from_buf)) return 0; /* Heuristics to see if we can skip the conversion. * Straight from Core Git. */ - if (filter->attrs.crlf_action == GIT_CRLF_AUTO || - filter->attrs.crlf_action == GIT_CRLF_GUESS) { - + if (ca->crlf_action == GIT_CRLF_AUTO || ca->crlf_action == GIT_CRLF_GUESS) { git_buf_text_stats stats; /* Check heuristics for binary vs text... */ - if (git_buf_text_gather_stats(&stats, source, false)) + if (git_buf_text_gather_stats(&stats, &from_buf, false)) return -1; /* @@ -175,28 +173,34 @@ static int crlf_apply_to_odb( * stuff? */ if (stats.cr != stats.crlf) - return -1; + return GIT_ENOTFOUND; - if (filter->attrs.crlf_action == GIT_CRLF_GUESS) { + if (ca->crlf_action == GIT_CRLF_GUESS) { /* * If the file in the index has any CR in it, do not convert. * This is the new safer autocrlf handling. */ - if (has_cr_in_index(self)) - return -1; + if (has_cr_in_index(src->repo, src->path)) + return GIT_ENOTFOUND; } if (!stats.cr) - return -1; + return GIT_ENOTFOUND; } /* Actually drop the carriage returns */ - return git_buf_text_crlf_to_lf(dest, source); + if (git_buf_text_crlf_to_lf(&to_buf, &from_buf) < 0) + return -1; + + /* Overwrite "to" buffer in case data was resized */ + git_buffer_from_buf(to, &to_buf); + + return 0; } -static const char *line_ending(struct crlf_filter *filter) +static const char *line_ending(struct crlf_attrs *ca) { - switch (filter->attrs.crlf_action) { + switch (ca->crlf_action) { case GIT_CRLF_BINARY: case GIT_CRLF_INPUT: return "\n"; @@ -213,7 +217,7 @@ static const char *line_ending(struct crlf_filter *filter) goto line_ending_error; } - switch (filter->attrs.eol) { + switch (ca->eol) { case GIT_EOL_UNSET: return GIT_EOL_NATIVE == GIT_EOL_CRLF ? "\r\n" @@ -235,44 +239,58 @@ line_ending_error: } static int crlf_apply_to_workdir( - git_filter *self, git_buf *tgt, const git_buf *src) + struct crlf_attrs *ca, git_buffer *to, const git_buffer *from) { - struct crlf_filter *filter = (struct crlf_filter *)self; + const git_buf from_buf = GIT_BUF_FROM_BUFFER(from); + git_buf to_buf = GIT_BUF_FROM_BUFFER(to); const char *workdir_ending = NULL; - assert(self && tgt && src); - /* Empty file? Nothing to do. */ - if (git_buf_len(src) == 0) - return -1; + if (git_buf_len(&from_buf) == 0) + return 0; /* Determine proper line ending */ - workdir_ending = line_ending(filter); + workdir_ending = line_ending(ca); if (!workdir_ending) return -1; if (!strcmp("\n", workdir_ending)) { - if (git_buf_find(src, '\r') < 0) + if (ca->crlf_action == GIT_CRLF_GUESS && ca->auto_crlf) + return GIT_ENOTFOUND; + + if (git_buf_find(&from_buf, '\r') < 0) + return GIT_ENOTFOUND; + + if (git_buf_text_crlf_to_lf(&to_buf, &from_buf) < 0) + return -1; + } else { + /* only other supported option is lf->crlf conversion */ + assert(!strcmp("\r\n", workdir_ending)); + + if (git_buf_text_lf_to_crlf(&to_buf, &from_buf) < 0) return -1; - return git_buf_text_crlf_to_lf(tgt, src); } - /* only other supported option is lf->crlf conversion */ - assert(!strcmp("\r\n", workdir_ending)); - return git_buf_text_lf_to_crlf(tgt, src); + /* Overwrite "to" buffer in case data was resized */ + git_buffer_from_buf(to, &to_buf); + + return 0; } -static int find_and_add_filter( - git_vector *filters, git_repository *repo, const char *path, - int (*apply)(struct git_filter *self, git_buf *tgt, const git_buf *src)) +static int crlf_check( + git_filter *self, + void **payload, /* points to NULL ptr on entry, may be set */ + git_filter_mode_t mode, + const git_filter_source *src) { - struct crlf_attrs ca; - struct crlf_filter *filter; - size_t pathlen; int error; + struct crlf_attrs ca; + + GIT_UNUSED(self); + GIT_UNUSED(mode); /* Load gitattributes for the path */ - if ((error = crlf_load_attributes(&ca, repo, path)) < 0) + if ((error = crlf_load_attributes(&ca, src->repo, src->path)) < 0) return error; /* @@ -282,41 +300,54 @@ static int find_and_add_filter( ca.crlf_action = crlf_input_action(&ca); if (ca.crlf_action == GIT_CRLF_BINARY) - return 0; + return GIT_ENOTFOUND; if (ca.crlf_action == GIT_CRLF_GUESS) { - int auto_crlf; - - if ((error = git_repository__cvar(&auto_crlf, repo, GIT_CVAR_AUTO_CRLF)) < 0) + if ((error = git_repository__cvar( + &ca.auto_crlf, src->repo, GIT_CVAR_AUTO_CRLF)) < 0) return error; - if (auto_crlf == GIT_AUTO_CRLF_FALSE) - return 0; + if (ca.auto_crlf == GIT_AUTO_CRLF_FALSE) + return GIT_ENOTFOUND; } - /* If we're good, we create a new filter object and push it - * into the filters array */ - pathlen = strlen(path); - filter = git__malloc(sizeof(struct crlf_filter) + pathlen + 1); - GITERR_CHECK_ALLOC(filter); + *payload = git__malloc(sizeof(ca)); + GITERR_CHECK_ALLOC(*payload); + memcpy(*payload, &ca, sizeof(ca)); - filter->f.apply = apply; - filter->f.do_free = NULL; - memcpy(&filter->attrs, &ca, sizeof(struct crlf_attrs)); - filter->repo = repo; - memcpy(filter->path, path, pathlen + 1); + return 0; +} + +static int crlf_apply( + git_filter *self, + void **payload, /* may be read and/or set */ + git_filter_mode_t mode, + git_buffer *to, + const git_buffer *from, + const git_filter_source *src) +{ + GIT_UNUSED(self); - return git_vector_insert(filters, filter); + if (mode == GIT_FILTER_SMUDGE) + return crlf_apply_to_workdir(*payload, to, from); + else + return crlf_apply_to_odb(*payload, to, from, src); } -int git_filter_add__crlf_to_odb( - git_vector *filters, git_repository *repo, const char *path) +static void crlf_cleanup( + git_filter *self, + void *payload) { - return find_and_add_filter(filters, repo, path, &crlf_apply_to_odb); + GIT_UNUSED(self); + git__free(payload); } -int git_filter_add__crlf_to_workdir( - git_vector *filters, git_repository *repo, const char *path) +git_filter *git_crlf_filter_new(void) { - return find_and_add_filter(filters, repo, path, &crlf_apply_to_workdir); + struct crlf_filter *f = git__calloc(1, sizeof(struct crlf_filter)); + f->f.version = GIT_FILTER_VERSION; + f->f.check = crlf_check; + f->f.apply = crlf_apply; + f->f.cleanup = crlf_cleanup; + return (git_filter *)f; } diff --git a/src/diff.c b/src/diff.c index 77dbbd8bc..b1cde36bc 100644 --- a/src/diff.c +++ b/src/diff.c @@ -568,21 +568,21 @@ int git_diff__oid_for_file( giterr_set(GITERR_OS, "File size overflow (for 32-bits) on '%s'", path); result = -1; } else { - git_vector filters = GIT_VECTOR_INIT; + git_filter_list *fl = NULL; - result = git_filters_load(&filters, repo, path, GIT_FILTER_TO_ODB); - if (result >= 0) { + result = git_filter_list_load(&fl, repo, path, GIT_FILTER_TO_ODB); + if (!result) { int fd = git_futils_open_ro(full_path.ptr); if (fd < 0) result = fd; else { result = git_odb__hashfd_filtered( - oid, fd, (size_t)size, GIT_OBJ_BLOB, &filters); + oid, fd, (size_t)size, GIT_OBJ_BLOB, fl); p_close(fd); } - } - git_filters_free(&filters); + git_filter_list_free(fl); + } } cleanup: diff --git a/src/diff_file.c b/src/diff_file.c index bcfef13cd..7602591cf 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -296,7 +296,7 @@ static int diff_file_content_load_workdir_file( git_diff_file_content *fc, git_buf *path) { int error = 0; - git_vector filters = GIT_VECTOR_INIT; + git_filter_list *fl = NULL; git_buf raw = GIT_BUF_INIT, filtered = GIT_BUF_INIT; git_file fd = git_futils_open_ro(git_buf_cstr(path)); @@ -310,41 +310,35 @@ static int diff_file_content_load_workdir_file( if (diff_file_content_binary_by_size(fc)) goto cleanup; - if ((error = git_filters_load( - &filters, fc->repo, fc->file->path, GIT_FILTER_TO_ODB)) < 0) + if ((error = git_filter_list_load( + &fl, fc->repo, fc->file->path, GIT_FILTER_TO_ODB)) < 0) goto cleanup; - /* error >= is a filter count */ - if (error == 0) { + /* if there are no filters, try to mmap the file */ + if (fl == NULL) { if (!(error = git_futils_mmap_ro( - &fc->map, fd, 0, (size_t)fc->file->size))) + &fc->map, fd, 0, (size_t)fc->file->size))) { fc->flags |= GIT_DIFF_FLAG__UNMAP_DATA; - else /* fall through to try readbuffer below */ - giterr_clear(); - } - - if (error != 0) { - error = git_futils_readbuffer_fd(&raw, fd, (size_t)fc->file->size); - if (error < 0) goto cleanup; - - if (!filters.length) - git_buf_swap(&filtered, &raw); - else - error = git_filters_apply(&filtered, &raw, &filters); - - if (!error) { - fc->map.len = git_buf_len(&filtered); - fc->map.data = git_buf_detach(&filtered); - fc->flags |= GIT_DIFF_FLAG__FREE_DATA; } - git_buf_free(&raw); - git_buf_free(&filtered); + /* if mmap failed, fall through to try readbuffer below */ + giterr_clear(); } + if (!(error = git_futils_readbuffer_fd(&raw, fd, (size_t)fc->file->size)) && + !(error = git_filter_list_apply(&filtered, &raw, fl))) + { + fc->map.len = git_buf_len(&filtered); + fc->map.data = git_buf_detach(&filtered); + fc->flags |= GIT_DIFF_FLAG__FREE_DATA; + } + + git_buf_free(&raw); + git_buf_free(&filtered); + cleanup: - git_filters_free(&filters); + git_filter_list_free(fl); p_close(fd); return error; diff --git a/src/filter.c b/src/filter.c index 9f749dcbd..7935e6518 100644 --- a/src/filter.c +++ b/src/filter.c @@ -13,62 +13,155 @@ #include "git2/config.h" #include "blob.h" -int git_filters_load(git_vector *filters, git_repository *repo, const char *path, int mode) +typedef struct { + git_filter *filter; + void *payload; +} git_filter_entry; + +struct git_filter_list { + git_array_t(git_filter_entry) filters; + git_filter_mode_t mode; + git_filter_source source; + char path[GIT_FLEX_ARRAY]; +}; + +typedef struct { + const char *filter_name; + git_filter *filter; +} git_filter_def; + +static git_array_t(git_filter_def) filter_registry = GIT_ARRAY_INIT; + +static int filter_load_defaults(void) { - int error; - - if (mode == GIT_FILTER_TO_ODB) { - /* Load the CRLF cleanup filter when writing to the ODB */ - error = git_filter_add__crlf_to_odb(filters, repo, path); - if (error < 0) - return error; - } else { - error = git_filter_add__crlf_to_workdir(filters, repo, path); - if (error < 0) - return error; + if (!git_array_size(filter_registry)) { + git_filter_def *fdef = git_array_alloc(filter_registry); + GITERR_CHECK_ALLOC(fdef); + + fdef->filter_name = GIT_FILTER_CRLF; + fdef->filter = git_crlf_filter_new(); + GITERR_CHECK_ALLOC(fdef->filter); } - return (int)filters->length; + return 0; } -void git_filters_free(git_vector *filters) +static int git_filter_list_new( + git_filter_list **out, git_filter_mode_t mode, const git_filter_source *src) { - size_t i; - git_filter *filter; + git_filter_list *fl = NULL; + size_t pathlen = src->path ? strlen(src->path) : 0; + + fl = git__calloc(1, sizeof(git_filter_list) + pathlen + 1); + GITERR_CHECK_ALLOC(fl); + + fl->mode = mode; + if (src->path) + memcpy(fl->path, src->path, pathlen); + fl->source.repo = src->repo; + fl->source.path = fl->path; + + *out = fl; + return 0; +} + +int git_filter_list_load( + git_filter_list **filters, + git_repository *repo, + const char *path, + git_filter_mode_t mode) +{ + int error = 0; + git_filter_list *fl = NULL; + git_filter_source src = { 0 }; + git_filter_entry *fe; + uint32_t f; + + if (filter_load_defaults() < 0) + return -1; + + src.repo = repo; + src.path = path; + + for (f = 0; f < git_array_size(filter_registry); ++f) { + void *payload = NULL; + git_filter_def *fdef = git_array_get(filter_registry, f); + + if (!fdef || !fdef->filter) + continue; - git_vector_foreach(filters, i, filter) { - if (filter->do_free != NULL) - filter->do_free(filter); - else - git__free(filter); + if (fdef->filter->check) + error = fdef->filter->check(fdef->filter, &payload, mode, &src); + + if (error == GIT_ENOTFOUND) + error = 0; + else if (error < 0) + break; + else { + if (!fl && (error = git_filter_list_new(&fl, mode, &src)) < 0) + return error; + + fe = git_array_alloc(fl->filters); + GITERR_CHECK_ALLOC(fe); + fe->filter = fdef->filter; + fe->payload = payload; + } + } + + if (error && fl != NULL) { + git_array_clear(fl->filters); + git__free(fl); + fl = NULL; + } + + *filters = fl; + return error; +} + +void git_filter_list_free(git_filter_list *fl) +{ + uint32_t i; + + if (!fl) + return; + + for (i = 0; i < git_array_size(fl->filters); ++i) { + git_filter_entry *fe = git_array_get(fl->filters, i); + if (fe->filter->cleanup) + fe->filter->cleanup(fe->filter, fe->payload); } - git_vector_free(filters); + git_array_clear(fl->filters); + git__free(fl); } -int git_filters_apply(git_buf *dest, git_buf *source, git_vector *filters) +int git_filter_list_apply( + git_buf *dest, + git_buf *source, + git_filter_list *fl) { - size_t i; + int error = 0; + uint32_t i; unsigned int src; git_buf *dbuffer[2]; + if (!fl) { + git_buf_swap(dest, source); + return 0; + } + dbuffer[0] = source; dbuffer[1] = dest; src = 0; - if (git_buf_len(source) == 0) { - git_buf_clear(dest); - return 0; - } - /* Pre-grow the destination buffer to more or less the size * we expect it to have */ if (git_buf_grow(dest, git_buf_len(source)) < 0) return -1; - for (i = 0; i < filters->length; ++i) { - git_filter *filter = git_vector_get(filters, i); + for (i = 0; i < git_array_size(fl->filters); ++i) { + git_filter_entry *fe = git_array_get(fl->filters, i); unsigned int dst = 1 - src; git_buf_clear(dbuffer[dst]); @@ -79,8 +172,25 @@ int git_filters_apply(git_buf *dest, git_buf *source, git_vector *filters) * of the double buffering (so that the text goes through * cleanly). */ - if (filter->apply(filter, dbuffer[dst], dbuffer[src]) == 0) - src = dst; + { + git_buffer srcb = GIT_BUFFER_FROM_BUF(dbuffer[src]); + git_buffer dstb = GIT_BUFFER_FROM_BUF(dbuffer[dst]); + + error = fe->filter->apply( + fe->filter, &fe->payload, fl->mode, &dstb, &srcb, &fl->source); + + if (error == GIT_ENOTFOUND) + error = 0; + else if (error < 0) { + git_buf_clear(dest); + return error; + } + else { + git_buf_from_buffer(dbuffer[src], &srcb); + git_buf_from_buffer(dbuffer[dst], &dstb); + src = dst; + } + } if (git_buf_oom(dbuffer[dst])) return -1; diff --git a/src/filter.h b/src/filter.h index 67845ad6a..a4ee2172d 100644 --- a/src/filter.h +++ b/src/filter.h @@ -9,14 +9,11 @@ #include "common.h" #include "buffer.h" +#include "array.h" #include "git2/odb.h" #include "git2/repository.h" #include "git2/filter.h" - -struct git_filter { - int (*apply)(struct git_filter *self, git_buf *dest, const git_buf *source); - void (*do_free)(struct git_filter *self); -}; +#include "git2/sys/filter.h" typedef enum { GIT_CRLF_GUESS = -1, @@ -27,34 +24,38 @@ typedef enum { GIT_CRLF_AUTO, } git_crlf_t; +typedef struct git_filter_list git_filter_list; + /* * FILTER API */ /* - * For any given path in the working directory, fill the `filters` - * array with the relevant filters that need to be applied. + * For any given path in the working directory, create a `git_filter_list` + * with the relevant filters that need to be applied. * - * Mode is either `GIT_FILTER_TO_WORKTREE` if you need to load the - * filters that will be used when checking out a file to the working - * directory, or `GIT_FILTER_TO_ODB` for the filters used when writing - * a file to the ODB. + * This will return 0 (success) but set the output git_filter_list to NULL + * if no filters are requested for the given file. * - * @param filters Vector where to store all the loaded filters + * @param filters Output newly created git_filter_list (or NULL) * @param repo Repository object that contains `path` * @param path Relative path of the file to be filtered * @param mode Filtering direction (WT->ODB or ODB->WT) - * @return the number of filters loaded for the file (0 if the file - * doesn't need filtering), or a negative error code + * @return 0 on success (which could still return NULL if no filters are + * needed for the requested file), <0 on error */ -extern int git_filters_load(git_vector *filters, git_repository *repo, const char *path, int mode); +extern int git_filter_list_load( + git_filter_list **filters, + git_repository *repo, + const char *path, + git_filter_mode_t mode); /* - * Apply one or more filters to a file. + * Apply one or more filters to a data buffer. * - * The file must have been loaded as a `git_buf` object. Both the `source` - * and `dest` buffers are owned by the caller and must be freed once - * they are no longer needed. + * The source data must have been loaded as a `git_buf` object. Both the + * `source` and `dest` buffers are owned by the caller and must be freed + * once they are no longer needed. * * NOTE: Because of the double-buffering schema, the `source` buffer that * contains the original file may be tampered once the filtering is @@ -63,29 +64,25 @@ extern int git_filters_load(git_vector *filters, git_repository *repo, const cha * * @param dest Buffer to store the result of the filtering * @param source Buffer containing the document to filter - * @param filters Vector of filters as supplied by `git_filters_load` + * @param filters An already loaded git_filter_list * @return 0 on success, an error code otherwise */ -extern int git_filters_apply(git_buf *dest, git_buf *source, git_vector *filters); +extern int git_filter_list_apply( + git_buf *dest, + git_buf *source, + git_filter_list *filters); /* - * Free the `filters` array generated by `git_filters_load`. + * Free the git_filter_list * - * Note that this frees both the array and its contents. The array will - * be clean/reusable after this call. - * - * @param filters A filters array as supplied by `git_filters_load` + * @param filters A git_filter_list created by `git_filter_list_load` */ -extern void git_filters_free(git_vector *filters); +extern void git_filter_list_free(git_filter_list *filters); /* * Available filters */ -/* Strip CRLF, from Worktree to ODB */ -extern int git_filter_add__crlf_to_odb(git_vector *filters, git_repository *repo, const char *path); - -/* Add CRLF, from ODB to worktree */ -extern int git_filter_add__crlf_to_workdir(git_vector *filters, git_repository *repo, const char *path); +extern git_filter *git_crlf_filter_new(void); #endif diff --git a/src/odb.c b/src/odb.c index a0bfec403..d9310a9d7 100644 --- a/src/odb.c +++ b/src/odb.c @@ -179,13 +179,13 @@ done: } int git_odb__hashfd_filtered( - git_oid *out, git_file fd, size_t size, git_otype type, git_vector *filters) + git_oid *out, git_file fd, size_t size, git_otype type, git_filter_list *fl) { int error; git_buf raw = GIT_BUF_INIT; git_buf filtered = GIT_BUF_INIT; - if (!filters || !filters->length) + if (!fl) return git_odb__hashfd(out, fd, size, type); /* size of data is used in header, so we have to read the whole file @@ -193,7 +193,7 @@ int git_odb__hashfd_filtered( */ if (!(error = git_futils_readbuffer_fd(&raw, fd, size))) - error = git_filters_apply(&filtered, &raw, filters); + error = git_filter_list_apply(&filtered, &raw, fl); git_buf_free(&raw); diff --git a/src/odb.h b/src/odb.h index 0d9f9e2ea..61dd9a7fd 100644 --- a/src/odb.h +++ b/src/odb.h @@ -14,6 +14,7 @@ #include "vector.h" #include "cache.h" #include "posix.h" +#include "filter.h" #define GIT_OBJECTS_DIR "objects/" #define GIT_OBJECT_DIR_MODE 0777 @@ -66,7 +67,7 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type); * Acts just like git_odb__hashfd with the addition of filters... */ int git_odb__hashfd_filtered( - git_oid *out, git_file fd, size_t len, git_otype type, git_vector *filters); + git_oid *out, git_file fd, size_t len, git_otype type, git_filter_list *fl); /* * Hash a `path`, assuming it could be a POSIX symlink: if the path is a diff --git a/src/repository.c b/src/repository.c index eead41201..94700e4e3 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1649,7 +1649,7 @@ int git_repository_hashfile( const char *as_path) { int error; - git_vector filters = GIT_VECTOR_INIT; + git_filter_list *fl = NULL; git_file fd = -1; git_off_t len; git_buf full_path = GIT_BUF_INIT; @@ -1671,7 +1671,7 @@ int git_repository_hashfile( /* passing empty string for "as_path" indicated --no-filters */ if (strlen(as_path) > 0) { - error = git_filters_load(&filters, repo, as_path, GIT_FILTER_TO_ODB); + error = git_filter_list_load(&fl, repo, as_path, GIT_FILTER_TO_ODB); if (error < 0) return error; } else { @@ -1698,12 +1698,12 @@ int git_repository_hashfile( goto cleanup; } - error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, &filters); + error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, fl); cleanup: if (fd >= 0) p_close(fd); - git_filters_free(&filters); + git_filter_list_free(fl); git_buf_free(&full_path); return error; diff --git a/tests-clar/object/blob/filter.c b/tests-clar/object/blob/filter.c index 2b3954d9c..33ebedcde 100644 --- a/tests-clar/object/blob/filter.c +++ b/tests-clar/object/blob/filter.c @@ -101,7 +101,7 @@ void test_object_blob_filter__stats(void) void test_object_blob_filter__to_odb(void) { - git_vector filters = GIT_VECTOR_INIT; + git_filter_list *fl = NULL; git_config *cfg; int i; git_blob *blob; @@ -113,21 +113,21 @@ void test_object_blob_filter__to_odb(void) git_attr_cache_flush(g_repo); cl_git_append2file("empty_standard_repo/.gitattributes", "*.txt text\n"); - cl_assert(git_filters_load( - &filters, g_repo, "filename.txt", GIT_FILTER_TO_ODB) > 0); - cl_assert(filters.length == 1); + cl_git_pass( + git_filter_list_load(&fl, g_repo, "filename.txt", GIT_FILTER_TO_ODB)); + cl_assert(fl != NULL); for (i = 0; i < NUM_TEST_OBJECTS; i++) { cl_git_pass(git_blob_lookup(&blob, g_repo, &g_oids[i])); cl_git_pass(git_blob__getbuf(&orig, blob)); - cl_git_pass(git_filters_apply(&out, &orig, &filters)); + cl_git_pass(git_filter_list_apply(&out, &orig, fl)); cl_assert(git_buf_cmp(&out, &g_crlf_filtered[i]) == 0); git_blob_free(blob); } - git_filters_free(&filters); + git_filter_list_free(fl); git_buf_free(&orig); git_buf_free(&out); git_config_free(cfg); -- cgit v1.2.1 From 570ba25cb0f757f993e06df629faced32fdf2f8f Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 30 Aug 2013 16:02:07 -0700 Subject: Make git_filter_source opaque --- include/git2/sys/filter.h | 29 +++++++++++++++++++++++------ src/crlf.c | 15 ++++++++++----- src/filter.c | 27 +++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h index 2264be080..b1193a538 100644 --- a/include/git2/sys/filter.h +++ b/include/git2/sys/filter.h @@ -22,12 +22,29 @@ GIT_BEGIN_DECL * A filter source represents a file/blob to be processed */ typedef struct git_filter_source git_filter_source; -struct git_filter_source { - git_repository *repo; - const char *path; - git_oid oid; /* zero if unknown (which is likely) */ - uint16_t filemode; /* zero if unknown */ -}; + +/** + * Get the repository that the source data is coming from. + */ +GIT_EXTERN(git_repository *) git_filter_source_repo(const git_filter_source *src); + +/** + * Get the path that the source data is coming from. + */ +GIT_EXTERN(const char *) git_filter_source_path(const git_filter_source *src); + +/** + * Get the file mode of the source file + * If the mode is unknown, this will return 0 + */ +GIT_EXTERN(uint16_t) git_filter_source_filemode(const git_filter_source *src); + +/** + * Get the OID of the source + * If the OID is unknown (often the case with GIT_FILTER_CLEAN) then + * this will return NULL. + */ +GIT_EXTERN(const git_oid *) git_filter_source_id(const git_filter_source *src); /** * Callback to actually perform the data filtering diff --git a/src/crlf.c b/src/crlf.c index 2177bff98..cfc2d1eb1 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -107,8 +107,10 @@ static int crlf_load_attributes( return -1; } -static int has_cr_in_index(git_repository *repo, const char *path) +static int has_cr_in_index(const git_filter_source *src) { + git_repository *repo = git_filter_source_repo(src); + const char *path = git_filter_source_path(src); git_index *index; const git_index_entry *entry; git_blob *blob; @@ -180,7 +182,7 @@ static int crlf_apply_to_odb( * If the file in the index has any CR in it, do not convert. * This is the new safer autocrlf handling. */ - if (has_cr_in_index(src->repo, src->path)) + if (has_cr_in_index(src)) return GIT_ENOTFOUND; } @@ -290,7 +292,9 @@ static int crlf_check( GIT_UNUSED(mode); /* Load gitattributes for the path */ - if ((error = crlf_load_attributes(&ca, src->repo, src->path)) < 0) + error = crlf_load_attributes( + &ca, git_filter_source_repo(src), git_filter_source_path(src)); + if (error < 0) return error; /* @@ -303,8 +307,9 @@ static int crlf_check( return GIT_ENOTFOUND; if (ca.crlf_action == GIT_CRLF_GUESS) { - if ((error = git_repository__cvar( - &ca.auto_crlf, src->repo, GIT_CVAR_AUTO_CRLF)) < 0) + error = git_repository__cvar( + &ca.auto_crlf, git_filter_source_repo(src), GIT_CVAR_AUTO_CRLF); + if (error < 0) return error; if (ca.auto_crlf == GIT_AUTO_CRLF_FALSE) diff --git a/src/filter.c b/src/filter.c index 7935e6518..3d4c6d6ce 100644 --- a/src/filter.c +++ b/src/filter.c @@ -13,6 +13,13 @@ #include "git2/config.h" #include "blob.h" +struct git_filter_source { + git_repository *repo; + const char *path; + git_oid oid; /* zero if unknown (which is likely) */ + uint16_t filemode; /* zero if unknown */ +}; + typedef struct { git_filter *filter; void *payload; @@ -32,6 +39,26 @@ typedef struct { static git_array_t(git_filter_def) filter_registry = GIT_ARRAY_INIT; +git_repository *git_filter_source_repo(const git_filter_source *src) +{ + return src->repo; +} + +const char *git_filter_source_path(const git_filter_source *src) +{ + return src->path; +} + +uint16_t git_filter_source_filemode(const git_filter_source *src) +{ + return src->filemode; +} + +const git_oid *git_filter_source_id(const git_filter_source *src) +{ + return git_oid_iszero(&src->oid) ? NULL : &src->oid; +} + static int filter_load_defaults(void) { if (!git_array_size(filter_registry)) { -- cgit v1.2.1 From 974774c7b00c08585b05ff87174872be005a1f29 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 9 Sep 2013 16:57:34 -0700 Subject: Add attributes to filters and fix registry The filter registry as implemented was too primitive to actually work once multiple filters were coming into play. This expands the implementation of the registry to handle multiple prioritized filters correctly. Additionally, this adds an "attributes" field to a filter that makes it really really easy to implement filters that are based on one or more attribute values. The lookup and even simple value checking can all happen automatically without custom filter code. Lastly, with the registry improvements, this fills out the filter lifecycle callbacks, with initialize and shutdown callbacks that will be called before the filter is first used and after it is last invoked. This allows for system-wide initialization and cleanup by the filter. --- include/git2/errors.h | 1 + include/git2/sys/filter.h | 101 ++++++++++++++---- src/attr.c | 8 +- src/crlf.c | 55 +++------- src/filter.c | 263 ++++++++++++++++++++++++++++++++++++++++++---- tests-clar/attr/repo.c | 16 +++ 6 files changed, 364 insertions(+), 80 deletions(-) diff --git a/include/git2/errors.h b/include/git2/errors.h index dc4486ade..a454ac956 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -68,6 +68,7 @@ typedef enum { GITERR_FETCHHEAD, GITERR_MERGE, GITERR_SSH, + GITERR_FILTER, } git_error_t; /** diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h index b1193a538..b0a753019 100644 --- a/include/git2/sys/filter.h +++ b/include/git2/sys/filter.h @@ -46,16 +46,26 @@ GIT_EXTERN(uint16_t) git_filter_source_filemode(const git_filter_source *src); */ GIT_EXTERN(const git_oid *) git_filter_source_id(const git_filter_source *src); +/* + * struct git_filter + * + * The filter lifecycle: + * - initialize - first use of filter + * - shutdown - filter removed/unregistered from system + * - check - considering for file + * - apply - applied to file + * - cleanup - done with file + */ + /** - * Callback to actually perform the data filtering + * Initialize callback on filter */ -typedef int (*git_filter_apply_fn)( - git_filter *self, - void **payload, /* may be read and/or set */ - git_filter_mode_t mode, - git_buffer *to, - const git_buffer *from, - const git_filter_source *src); +typedef int (*git_filter_init_fn)(git_filter *self); + +/** + * Shutdown callback on filter + */ +typedef void (*git_filter_shutdown_fn)(git_filter *self); /** * Callback to decide if a given source needs this filter @@ -64,6 +74,18 @@ typedef int (*git_filter_check_fn)( git_filter *self, void **payload, /* points to NULL ptr on entry, may be set */ git_filter_mode_t mode, + const git_filter_source *src, + const char **attr_values); + +/** + * Callback to actually perform the data filtering + */ +typedef int (*git_filter_apply_fn)( + git_filter *self, + void **payload, /* may be read and/or set */ + git_filter_mode_t mode, + git_buffer *to, + const git_buffer *from, const git_filter_source *src); /** @@ -83,10 +105,32 @@ typedef void (*git_filter_cleanup_fn)( * * `version` should be set to GIT_FILTER_VERSION * - * `apply` is the callback that actually filters data. + * `attributes` is a list of attributes to check on a file to see if the + * filter applies. The format is a whitespace-delimited list of names + * (like "eol crlf text"). Each name may have an optional value that will + * be tested even without a `check` callback. If the value does not + * match, the filter will be skipped. The values are specified as in a + * .gitattributes file (e.g. "myattr=foobar" or "myattr" or "-myattr"). + * If a check function is supplied, then the values of the attributes will + * be passed to that function. + * + * `initialize` is an optional callback invoked before a filter is first + * used. It will be called once at most. + * + * `shutdown` is an optional callback invoked when the filter is + * unregistered or when libgit2 is shutting down. It will be called once + * at most and should free any memory as needed. * * `check` is an optional callback that checks if filtering is needed for - * a given source. + * a given source. It should return 0 if the filter should be applied + * (i.e. success), GIT_ENOTFOUND if the filter should not be applied, or + * an other error code to fail out of the filter processing pipeline and + * return to the caller. + * + * `apply` is the callback that actually filters data. If it successfully + * writes the output, it should return 0. Like `check`, it can return + * GIT_ENOTFOUND to indicate that the filter doesn't actually want to run. + * Other error codes will stop filter processing and return to the caller. * * `cleanup` is an optional callback that is made after the filter has * been applied. Both the `check` and `apply` callbacks are able to @@ -94,25 +138,46 @@ typedef void (*git_filter_cleanup_fn)( * is given that value and can clean up as needed. */ struct git_filter { - unsigned int version; - git_filter_apply_fn apply; - git_filter_check_fn check; - git_filter_cleanup_fn cleanup; + unsigned int version; + const char *attributes; + git_filter_init_fn initialize; + git_filter_shutdown_fn shutdown; + git_filter_check_fn check; + git_filter_apply_fn apply; + git_filter_cleanup_fn cleanup; }; #define GIT_FILTER_VERSION 1 /** - * Register a filter under a given name + * Register a filter under a given name with a given priority. + * + * If non-NULL, the filter's initialize callback will be invoked before + * the first use of the filter, so you can defer expensive operations (in + * case libgit2 is being used in a way that doesn't need the filter). * - * Two filters will be preregistered with libgit2: GIT_FILTER_CRLF and - * GIT_FILTER_IDENT. + * A filter's attribute checks and `check` and `apply` callbacks will be + * issued in order of `priority` on smudge (to workdir), and in reverse + * order of `priority` on clean (to odb). + * + * One filter will be preregistered with libgit2: + * - GIT_FILTER_CRLF with priority of 0. + * + * Currently the filter registry is not thread safe, so any registering or + * deregistering of filters must be done outside of any possible usage of + * the filters (i.e. during application setup or shutdown). */ GIT_EXTERN(int) git_filter_register( - const char *name, const git_filter *filter); + const char *name, git_filter *filter, int priority); /** * Remove the filter with the given name + * + * It is not allowed to remove the builtin libgit2 filters. + * + * Currently the filter registry is not thread safe, so any registering or + * deregistering of filters must be done outside of any possible usage of + * the filters (i.e. during application setup or shutdown). */ GIT_EXTERN(int) git_filter_unregister(const char *name); diff --git a/src/attr.c b/src/attr.c index 6cdff29f9..7946db4d6 100644 --- a/src/attr.c +++ b/src/attr.c @@ -26,7 +26,6 @@ git_attr_t git_attr_value(const char *attr) return GIT_ATTR_VALUE_T; } - static int collect_attr_files( git_repository *repo, uint32_t flags, @@ -103,8 +102,6 @@ int git_attr_get_many( attr_get_many_info *info = NULL; size_t num_found = 0; - memset((void *)values, 0, sizeof(const char *) * num_attr); - if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) return -1; @@ -141,6 +138,11 @@ int git_attr_get_many( } } + for (k = 0; k < num_attr; k++) { + if (!info[k].found) + values[k] = NULL; + } + cleanup: git_vector_free(&files); git_attr_path__free(&path); diff --git a/src/crlf.c b/src/crlf.c index cfc2d1eb1..1242450d8 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -74,39 +74,6 @@ static int crlf_input_action(struct crlf_attrs *ca) return ca->crlf_action; } -static int crlf_load_attributes( - struct crlf_attrs *ca, git_repository *repo, const char *path) -{ -#define NUM_CONV_ATTRS 3 - - static const char *attr_names[NUM_CONV_ATTRS] = { - "crlf", "eol", "text", - }; - - const char *attr_vals[NUM_CONV_ATTRS]; - int error; - - error = git_attr_get_many(attr_vals, - repo, 0, path, NUM_CONV_ATTRS, attr_names); - - if (error == GIT_ENOTFOUND) { - ca->crlf_action = GIT_CRLF_GUESS; - ca->eol = GIT_EOL_UNSET; - return 0; - } - - if (error == 0) { - ca->crlf_action = check_crlf(attr_vals[2]); /* text */ - if (ca->crlf_action == GIT_CRLF_GUESS) - ca->crlf_action = check_crlf(attr_vals[0]); /* clrf */ - - ca->eol = check_eol(attr_vals[1]); /* eol */ - return 0; - } - - return -1; -} - static int has_cr_in_index(const git_filter_source *src) { git_repository *repo = git_filter_source_repo(src); @@ -283,7 +250,8 @@ static int crlf_check( git_filter *self, void **payload, /* points to NULL ptr on entry, may be set */ git_filter_mode_t mode, - const git_filter_source *src) + const git_filter_source *src, + const char **attr_values) { int error; struct crlf_attrs ca; @@ -291,11 +259,16 @@ static int crlf_check( GIT_UNUSED(self); GIT_UNUSED(mode); - /* Load gitattributes for the path */ - error = crlf_load_attributes( - &ca, git_filter_source_repo(src), git_filter_source_path(src)); - if (error < 0) - return error; + if (!attr_values) { + ca.crlf_action = GIT_CRLF_GUESS; + ca.eol = GIT_EOL_UNSET; + } else { + ca.crlf_action = check_crlf(attr_values[2]); /* text */ + if (ca.crlf_action == GIT_CRLF_GUESS) + ca.crlf_action = check_crlf(attr_values[0]); /* clrf */ + ca.eol = check_eol(attr_values[1]); /* eol */ + } + ca.auto_crlf = GIT_AUTO_CRLF_DEFAULT; /* * Use the core Git logic to see if we should perform CRLF for this file @@ -350,7 +323,11 @@ static void crlf_cleanup( git_filter *git_crlf_filter_new(void) { struct crlf_filter *f = git__calloc(1, sizeof(struct crlf_filter)); + f->f.version = GIT_FILTER_VERSION; + f->f.attributes = "crlf eol text"; + f->f.initialize = NULL; + f->f.shutdown = NULL; f->f.check = crlf_check; f->f.apply = crlf_apply; f->f.cleanup = crlf_cleanup; diff --git a/src/filter.c b/src/filter.c index 3d4c6d6ce..7fbc20a41 100644 --- a/src/filter.c +++ b/src/filter.c @@ -12,6 +12,7 @@ #include "repository.h" #include "git2/config.h" #include "blob.h" +#include "attr_file.h" struct git_filter_source { git_repository *repo; @@ -35,9 +36,187 @@ struct git_filter_list { typedef struct { const char *filter_name; git_filter *filter; + int priority; + size_t nattrs, nmatches; + char *attrdata; + const char *attrs[GIT_FLEX_ARRAY]; } git_filter_def; -static git_array_t(git_filter_def) filter_registry = GIT_ARRAY_INIT; +static int filter_def_priority_cmp(const void *a, const void *b) +{ + int pa = ((const git_filter_def *)a)->priority; + int pb = ((const git_filter_def *)b)->priority; + return (pa < pb) ? -1 : (pa > pb) ? 1 : 0; +} + +static git_vector git__filter_registry = { + 0, filter_def_priority_cmp, NULL, 0, 0 +}; + +static int filter_def_scan_attrs( + git_buf *attrs, size_t *nattr, size_t *nmatch, const char *attr_str) +{ + const char *start, *scan = attr_str; + int has_eq; + + *nattr = *nmatch = 0; + + if (!scan) + return 0; + + while (*scan) { + while (git__isspace(*scan)) scan++; + + for (start = scan, has_eq = 0; *scan && !git__isspace(*scan); ++scan) { + if (*scan == '=') + has_eq = 1; + } + + if (scan > start) { + (*nattr)++; + if (has_eq || *scan == '-' || *scan == '+' || *scan == '!') + (*nmatch)++; + + if (has_eq) + git_buf_putc(attrs, '='); + git_buf_put(attrs, start, scan - start); + git_buf_putc(attrs, '\0'); + } + } + + return 0; +} + +static void filter_def_set_attrs(git_filter_def *fdef) +{ + char *scan = fdef->attrdata; + size_t i; + + for (i = 0; i < fdef->nattrs; ++i) { + const char *name, *value; + + switch (*scan) { + case '=': + name = scan + 1; + for (scan++; *scan != '='; scan++) /* find '=' */; + *scan++ = '\0'; + value = scan; + break; + case '-': + name = scan + 1; value = git_attr__false; break; + case '+': + name = scan + 1; value = git_attr__true; break; + case '!': + name = scan + 1; value = git_attr__unset; break; + default: + name = scan; value = NULL; break; + } + + fdef->attrs[i] = name; + fdef->attrs[i + fdef->nattrs] = value; + + scan += strlen(scan) + 1; + } +} + +int git_filter_register( + const char *name, git_filter *filter, int priority) +{ + git_filter_def *fdef; + size_t nattr = 0, nmatch = 0; + git_buf attrs = GIT_BUF_INIT; + + if (git_filter_lookup(name) != NULL) { + giterr_set( + GITERR_FILTER, "Attempt to reregister existing filter '%s'", name); + return -1; + } + + if (filter_def_scan_attrs(&attrs, &nattr, &nmatch, filter->attributes) < 0) + return -1; + + fdef = git__calloc( + sizeof(git_filter_def) + 2 * nattr * sizeof(char *), 1); + GITERR_CHECK_ALLOC(fdef); + + fdef->filter_name = name; + fdef->filter = filter; + fdef->priority = priority; + fdef->nattrs = nattr; + fdef->nmatches = nmatch; + fdef->attrdata = git_buf_detach(&attrs); + + filter_def_set_attrs(fdef); + + if (git_vector_insert(&git__filter_registry, fdef) < 0) { + git__free(fdef->attrdata); + git__free(fdef); + return -1; + } + + git_vector_sort(&git__filter_registry); + return 0; +} + +static int filter_def_name_key_check(const void *key, const void *fdef) +{ + const char *name = + fdef ? ((const git_filter_def *)fdef)->filter_name : NULL; + return name ? -1 : git__strcmp(key, name); +} + +static git_filter_def *filter_find_by_name(size_t *pos, const char *name) +{ + git_filter_def *fdef = NULL; + + if (!git_vector_search2( + pos, &git__filter_registry, filter_def_name_key_check, name)) + fdef = git_vector_get(&git__filter_registry, *pos); + + return fdef; +} + +int git_filter_unregister(const char *name) +{ + size_t pos; + git_filter_def *fdef; + + /* cannot unregister default filters */ + if (!strcmp(GIT_FILTER_CRLF, name)) { + giterr_set(GITERR_FILTER, "Cannot unregister filter '%s'", name); + return -1; + } + + if ((fdef = filter_find_by_name(&pos, name)) == NULL) { + giterr_set(GITERR_FILTER, "Cannot find filter '%s' to unregister", name); + return GIT_ENOTFOUND; + } + + (void)git_vector_remove(&git__filter_registry, pos); + + if (fdef->filter->shutdown) + fdef->filter->shutdown(fdef->filter); + + git__free(fdef->attrdata); + git__free(fdef); + + return 0; +} + +git_filter *git_filter_lookup(const char *name) +{ + size_t pos; + git_filter_def *fdef = filter_find_by_name(&pos, name); + return fdef ? fdef->filter : NULL; +} + +static int filter_load_defaults(void) +{ + if (!git_vector_length(&git__filter_registry)) + return git_filter_register(GIT_FILTER_CRLF, git_crlf_filter_new(), 0); + + return 0; +} git_repository *git_filter_source_repo(const git_filter_source *src) { @@ -59,20 +238,6 @@ const git_oid *git_filter_source_id(const git_filter_source *src) return git_oid_iszero(&src->oid) ? NULL : &src->oid; } -static int filter_load_defaults(void) -{ - if (!git_array_size(filter_registry)) { - git_filter_def *fdef = git_array_alloc(filter_registry); - GITERR_CHECK_ALLOC(fdef); - - fdef->filter_name = GIT_FILTER_CRLF; - fdef->filter = git_crlf_filter_new(); - GITERR_CHECK_ALLOC(fdef->filter); - } - - return 0; -} - static int git_filter_list_new( git_filter_list **out, git_filter_mode_t mode, const git_filter_source *src) { @@ -92,6 +257,47 @@ static int git_filter_list_new( return 0; } +static int filter_list_check_attributes( + const char ***out, git_filter_def *fdef, const git_filter_source *src) +{ + int error; + size_t i; + const char **strs = git__calloc(fdef->nattrs, sizeof(const char *)); + GITERR_CHECK_ALLOC(strs); + + error = git_attr_get_many( + strs, src->repo, 0, src->path, fdef->nattrs, fdef->attrs); + + /* if no values were found but no matches are needed, it's okay! */ + if (error == GIT_ENOTFOUND && !fdef->nmatches) { + giterr_clear(); + git__free(strs); + return 0; + } + + for (i = 0; !error && i < fdef->nattrs; ++i) { + const char *want = fdef->attrs[fdef->nattrs + i]; + git_attr_t want_type, found_type; + + if (!want) + continue; + + want_type = git_attr_value(want); + found_type = git_attr_value(strs[i]); + + if (want_type != found_type || + (want_type == GIT_ATTR_VALUE_T && strcmp(want, strs[i]))) + error = GIT_ENOTFOUND; + } + + if (error) + git__free(strs); + else + *out = strs; + + return error; +} + int git_filter_list_load( git_filter_list **filters, git_repository *repo, @@ -102,7 +308,8 @@ int git_filter_list_load( git_filter_list *fl = NULL; git_filter_source src = { 0 }; git_filter_entry *fe; - uint32_t f; + size_t idx; + git_filter_def *fdef; if (filter_load_defaults() < 0) return -1; @@ -110,15 +317,27 @@ int git_filter_list_load( src.repo = repo; src.path = path; - for (f = 0; f < git_array_size(filter_registry); ++f) { + git_vector_foreach(&git__filter_registry, idx, fdef) { + const char **values = NULL; void *payload = NULL; - git_filter_def *fdef = git_array_get(filter_registry, f); if (!fdef || !fdef->filter) continue; + if (fdef->nattrs > 0) { + error = filter_list_check_attributes(&values, fdef, &src); + if (error == GIT_ENOTFOUND) { + error = 0; + continue; + } else if (error < 0) + break; + } + if (fdef->filter->check) - error = fdef->filter->check(fdef->filter, &payload, mode, &src); + error = fdef->filter->check( + fdef->filter, &payload, mode, &src, values); + + git__free(values); if (error == GIT_ENOTFOUND) error = 0; @@ -171,6 +390,7 @@ int git_filter_list_apply( uint32_t i; unsigned int src; git_buf *dbuffer[2]; + git_filter_entry *fe; if (!fl) { git_buf_swap(dest, source); @@ -188,11 +408,14 @@ int git_filter_list_apply( return -1; for (i = 0; i < git_array_size(fl->filters); ++i) { - git_filter_entry *fe = git_array_get(fl->filters, i); unsigned int dst = 1 - src; git_buf_clear(dbuffer[dst]); + fe = git_array_get( + fl->filters, (fl->mode == GIT_FILTER_TO_ODB) ? + i : git_array_size(fl->filters) - 1 - i); + /* Apply the filter from dbuffer[src] to the other buffer; * if the filtering is canceled by the user mid-filter, * we skip to the next filter without changing the source diff --git a/tests-clar/attr/repo.c b/tests-clar/attr/repo.c index ca3e71e7f..ef2ad5ce9 100644 --- a/tests-clar/attr/repo.c +++ b/tests-clar/attr/repo.c @@ -100,6 +100,22 @@ void test_attr_repo__get_many(void) cl_assert_equal_s("yes", values[3]); } +void test_attr_repo__get_many_in_place(void) +{ + const char *vals[4] = { "repoattr", "rootattr", "missingattr", "subattr" }; + + /* it should be legal to look up values into the same array that has + * the attribute names, overwriting each name as the value is found. + */ + + cl_git_pass(git_attr_get_many(vals, g_repo, 0, "sub/subdir_test1", 4, vals)); + + cl_assert(GIT_ATTR_TRUE(vals[0])); + cl_assert(GIT_ATTR_TRUE(vals[1])); + cl_assert(GIT_ATTR_UNSPECIFIED(vals[2])); + cl_assert_equal_s("yes", vals[3]); +} + static int count_attrs( const char *name, const char *value, -- cgit v1.2.1 From 2a7d224f99a053d93079644947d04e7cc085930f Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 10 Sep 2013 16:33:32 -0700 Subject: Extend public filter api with filter lists This moves the git_filter_list into the public API so that users can create, apply, and dispose of filter lists. This allows more granular application of filters to user data outside of libgit2 internals. This also converts all the internal usage of filters to the public APIs along with a few small tweaks to make it easier to use the public git_buffer stuff alongside the internal git_buf. --- include/git2/buffer.h | 27 +++++--- include/git2/filter.h | 94 +++++++++++++++++++++++-- include/git2/sys/filter.h | 20 +++--- src/blob.c | 57 ++++------------ src/buffer.c | 23 ++++++- src/buffer.h | 5 ++ src/checkout.c | 38 ++++------- src/crlf.c | 7 +- src/diff_file.c | 23 ++++--- src/filter.c | 147 ++++++++++++++++++++++++++-------------- src/filter.h | 60 ---------------- src/odb.c | 16 +++-- tests-clar/object/blob/filter.c | 14 ++-- 13 files changed, 297 insertions(+), 234 deletions(-) diff --git a/include/git2/buffer.h b/include/git2/buffer.h index 454a1faa5..cb80e48f7 100644 --- a/include/git2/buffer.h +++ b/include/git2/buffer.h @@ -21,17 +21,17 @@ GIT_BEGIN_DECL /** * A data buffer for exporting data from libgit2 * - * There are a number of places where libgit2 wants to return an allocated - * data buffer to the caller and have the caller take ownership of that - * allocated memory. This can be awkward if the caller does not have easy - * access to the same allocation functions that libgit2 is using. In those - * cases, libgit2 will instead fill in a `git_buffer` and the caller can - * use `git_buffer_free()` to release it when they are done. + * Sometimes libgit2 wants to return an allocated data buffer to the + * caller and have the caller take responsibility for freeing that memory. + * This can be awkward if the caller does not have easy access to the same + * allocation functions that libgit2 is using. In those cases, libgit2 + * will instead fill in a `git_buffer` and the caller can use + * `git_buffer_free()` to release it when they are done. * * * `ptr` refers to the start of the allocated memory. * * `size` contains the size of the data in `ptr` that is actually used. - * * `available` refers to the known total amount of allocated memory in - * cases where it is larger than the `size` actually in use. + * * `available` refers to the known total amount of allocated memory. It + * may be larger than the `size` actually in use. * * In a few cases, for uniformity and simplicity, an API may populate a * `git_buffer` with data that should *not* be freed (i.e. the lifetime of @@ -79,6 +79,17 @@ GIT_EXTERN(void) git_buffer_free(git_buffer *buffer); */ GIT_EXTERN(int) git_buffer_resize(git_buffer *buffer, size_t want_size); +/** + * Set buffer to a copy of some raw data. + * + * @param buffer The buffer to set + * @param data The data to copy into the buffer + * @param datalen The length of the data to copy into the buffer + * @return 0 on success, negative error code on allocation failure + */ +GIT_EXTERN(int) git_buffer_copy( + git_buffer *buffer, const void *data, size_t datalen); + GIT_END_DECL /** @} */ diff --git a/include/git2/filter.h b/include/git2/filter.h index 478f3a6ad..cb23ae4f4 100644 --- a/include/git2/filter.h +++ b/include/git2/filter.h @@ -29,10 +29,10 @@ GIT_BEGIN_DECL * change is being applied. */ typedef enum { - GIT_FILTER_SMUDGE = 0, - GIT_FILTER_TO_WORKTREE = GIT_FILTER_SMUDGE, - GIT_FILTER_CLEAN = 1, - GIT_FILTER_TO_ODB = GIT_FILTER_CLEAN, + GIT_FILTER_TO_WORKTREE = 0, + GIT_FILTER_SMUDGE = GIT_FILTER_TO_WORKTREE, + GIT_FILTER_TO_ODB = 1, + GIT_FILTER_CLEAN = GIT_FILTER_TO_ODB, } git_filter_mode_t; /** @@ -50,10 +50,28 @@ typedef enum { */ typedef struct git_filter git_filter; +/** + * List of filters to be applied + * + * This represents a list of filters to be applied to a file / blob. You + * can build the list with one call, apply it with another, and dispose it + * with a third. In typical usage, there are not many occasions where a + * git_filter_list is needed directly since the library will generally + * handle conversions for you, but it can be convenient to be able to + * build and apply the list sometimes. + */ +typedef struct git_filter_list git_filter_list; + +/** + * Look up a filter by name + */ GIT_EXTERN(git_filter *) git_filter_lookup(const char *name); #define GIT_FILTER_CRLF "crlf" +/** + * Apply a single filter to a buffer of data + */ GIT_EXTERN(int) git_filter_apply_to_buffer( git_buffer *out, git_filter *filter, @@ -61,6 +79,74 @@ GIT_EXTERN(int) git_filter_apply_to_buffer( const char *as_path, git_filter_mode_t mode); +/** + * Load the filter list for a given path. + * + * This will return 0 (success) but set the output git_filter_list to NULL + * if no filters are requested for the given file. + * + * @param filters Output newly created git_filter_list (or NULL) + * @param repo Repository object that contains `path` + * @param path Relative path of the file to be filtered + * @param mode Filtering direction (WT->ODB or ODB->WT) + * @return 0 on success (which could still return NULL if no filters are + * needed for the requested file), <0 on error + */ +GIT_EXTERN(int) git_filter_list_load( + git_filter_list **filters, + git_repository *repo, + const char *path, + git_filter_mode_t mode); + +/** + * Apply filter list to a data buffer. + * + * See `git2/buffer.h` for background on `git_buffer` objects. + * + * If the `in` buffer refers to data managed by libgit2 + * (i.e. `in->available` is not zero), then it will be overwritten when + * applying the filters. If not, then it will be left untouched. + * + * If there are no filters to apply (or `filters` is NULL), then the `out` + * buffer will reference the `in` buffer data (with `available` set to + * zero) instead of allocating data. This keeps allocations to a minimum, + * but it means you have to be careful about freeing the `in` data. + * + * @param out Buffer to store the result of the filtering + * @param filters A loaded git_filter_list (or NULL) + * @param in Buffer containing the data to filter + * @return 0 on success, an error code otherwise + */ +GIT_EXTERN(int) git_filter_list_apply_to_data( + git_buffer *out, + git_filter_list *filters, + git_buffer *in); + +/** + * Apply filter list to the contents of a file on disk + */ +GIT_EXTERN(int) git_filter_list_apply_to_file( + git_buffer *out, + git_filter_list *filters, + git_repository *repo, + const char *path); + +/** + * Apply filter list to the contents of a blob + */ +GIT_EXTERN(int) git_filter_list_apply_to_blob( + git_buffer *out, + git_filter_list *filters, + git_blob *blob); + +/** + * Free a git_filter_list + * + * @param filters A git_filter_list created by `git_filter_list_load` + */ +GIT_EXTERN(void) git_filter_list_free(git_filter_list *filters); + + GIT_END_DECL /** @} */ diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h index b0a753019..ca1fbfcce 100644 --- a/include/git2/sys/filter.h +++ b/include/git2/sys/filter.h @@ -46,6 +46,11 @@ GIT_EXTERN(uint16_t) git_filter_source_filemode(const git_filter_source *src); */ GIT_EXTERN(const git_oid *) git_filter_source_id(const git_filter_source *src); +/** + * Get the git_filter_mode_t to be applied + */ +GIT_EXTERN(git_filter_mode_t) git_filter_source_mode(const git_filter_source *src); + /* * struct git_filter * @@ -73,7 +78,6 @@ typedef void (*git_filter_shutdown_fn)(git_filter *self); typedef int (*git_filter_check_fn)( git_filter *self, void **payload, /* points to NULL ptr on entry, may be set */ - git_filter_mode_t mode, const git_filter_source *src, const char **attr_values); @@ -83,7 +87,6 @@ typedef int (*git_filter_check_fn)( typedef int (*git_filter_apply_fn)( git_filter *self, void **payload, /* may be read and/or set */ - git_filter_mode_t mode, git_buffer *to, const git_buffer *from, const git_filter_source *src); @@ -105,14 +108,11 @@ typedef void (*git_filter_cleanup_fn)( * * `version` should be set to GIT_FILTER_VERSION * - * `attributes` is a list of attributes to check on a file to see if the - * filter applies. The format is a whitespace-delimited list of names - * (like "eol crlf text"). Each name may have an optional value that will - * be tested even without a `check` callback. If the value does not - * match, the filter will be skipped. The values are specified as in a - * .gitattributes file (e.g. "myattr=foobar" or "myattr" or "-myattr"). - * If a check function is supplied, then the values of the attributes will - * be passed to that function. + * `attributes` is a whitespace-separated list of attribute names to check + * for this filter (e.g. "eol crlf text"). If the attribute name is bare, + * it will be simply loaded and passed to the `check` callback. If it has + * a value (i.e. "name=value"), the attribute must match that value for + * the filter to be applied. * * `initialize` is an optional callback invoked before a filter is first * used. It will be called once at most. diff --git a/src/blob.c b/src/blob.c index 3581ee9d1..e6bba033a 100644 --- a/src/blob.c +++ b/src/blob.c @@ -111,26 +111,18 @@ static int write_file_filtered( git_filter_list *fl) { int error; - git_buf source = GIT_BUF_INIT; - git_buf dest = GIT_BUF_INIT; + git_buffer tgt = GIT_BUFFER_INIT; - if ((error = git_futils_readbuffer(&source, full_path)) < 0) - return error; - - error = git_filter_list_apply(&dest, &source, fl); - - /* Free the source as soon as possible. This can be big in memory, - * and we don't want to ODB write to choke */ - git_buf_free(&source); + error = git_filter_list_apply_to_file(&tgt, fl, NULL, full_path); /* Write the file to disk if it was properly filtered */ if (!error) { - *size = dest.size; + *size = tgt.size; - error = git_odb_write(oid, odb, dest.ptr, dest.size, GIT_OBJ_BLOB); + error = git_odb_write(oid, odb, tgt.ptr, tgt.size, GIT_OBJ_BLOB); } - git_buf_free(&dest); + git_buffer_free(&tgt); return error; } @@ -329,8 +321,9 @@ int git_blob_is_binary(git_blob *blob) assert(blob); - content.ptr = blob->odb_object->buffer; - content.size = min(blob->odb_object->cached.size, 4000); + content.ptr = blob->odb_object->buffer; + content.size = min(blob->odb_object->cached.size, 4000); + content.asize = 0; return git_buf_text_is_binary(&content); } @@ -342,46 +335,20 @@ int git_blob_filtered_content( int check_for_binary_data) { int error = 0; - git_buf filtered = GIT_BUF_INIT, unfiltered = GIT_BUF_INIT; git_filter_list *fl = NULL; assert(blob && as_path && out); - /* Create a fake git_buf from the blob raw data... */ - filtered.ptr = (void *)git_blob_rawcontent(blob); - filtered.size = (size_t)git_blob_rawsize(blob); - filtered.asize = 0; - - if (check_for_binary_data && git_buf_text_is_binary(&filtered)) + if (check_for_binary_data && git_blob_is_binary(blob)) return 0; - error = git_filter_list_load( - &fl, git_blob_owner(blob), as_path, GIT_FILTER_TO_WORKTREE); - if (error < 0) - return error; + if (!(error = git_filter_list_load( + &fl, git_blob_owner(blob), as_path, GIT_FILTER_TO_WORKTREE))) { - if (fl != NULL) { - if (out->ptr && out->available) { - filtered.ptr = out->ptr; - filtered.size = out->size; - filtered.asize = out->available; - } else { - git_buf_init(&filtered, filtered.size + 1); - } - - if (!(error = git_blob__getbuf(&unfiltered, blob))) - error = git_filter_list_apply(&filtered, &unfiltered, fl); + error = git_filter_list_apply_to_blob(out, fl, blob); git_filter_list_free(fl); - git_buf_free(&unfiltered); - } - - if (!error) { - out->ptr = filtered.ptr; - out->size = filtered.size; - out->available = filtered.asize; } return error; } - diff --git a/src/buffer.c b/src/buffer.c index a92133674..aaebac776 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -501,7 +501,8 @@ void git_buffer_free(git_buffer *buffer) git__memzero(buffer, sizeof(*buffer)); } -int git_buffer_resize(git_buffer *buffer, size_t want_size) +static int git_buffer__resize( + git_buffer *buffer, size_t want_size, int preserve_data) { int non_allocated_buffer = 0; char *new_ptr; @@ -514,7 +515,7 @@ int git_buffer_resize(git_buffer *buffer, size_t want_size) if (non_allocated_buffer && !want_size) want_size = buffer->size; - if (buffer->available <= want_size) + if (buffer->available >= want_size) return 0; if (non_allocated_buffer) { @@ -530,7 +531,7 @@ int git_buffer_resize(git_buffer *buffer, size_t want_size) new_ptr = git__realloc(new_ptr, want_size); GITERR_CHECK_ALLOC(new_ptr); - if (non_allocated_buffer) + if (non_allocated_buffer && preserve_data) memcpy(new_ptr, buffer->ptr, buffer->size); buffer->ptr = new_ptr; @@ -538,3 +539,19 @@ int git_buffer_resize(git_buffer *buffer, size_t want_size) return 0; } + +int git_buffer_resize(git_buffer *buffer, size_t want_size) +{ + return git_buffer__resize(buffer, want_size, true); +} + +int git_buffer_copy( + git_buffer *buffer, const void *data, size_t datalen) +{ + if (git_buffer__resize(buffer, datalen, false) < 0) + return -1; + memcpy(buffer->ptr, data, datalen); + buffer->size = datalen; + return 0; +} + diff --git a/src/buffer.h b/src/buffer.h index b1cb5d06a..e07f29131 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -176,6 +176,11 @@ int git_buf_splice( size_t nb_to_insert); +GIT_INLINE(bool) git_buffer_is_allocated(const git_buffer *buffer) +{ + return (buffer->ptr != NULL && buffer->available > 0); +} + #define GIT_BUF_FROM_BUFFER(buffer) \ { (buffer)->ptr, (buffer)->available, (buffer)->size } diff --git a/src/checkout.c b/src/checkout.c index 5ce4a19c5..1def58b0a 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -678,19 +678,20 @@ fail: static int buffer_to_file( struct stat *st, - git_buf *buffer, + git_buffer *buffer, const char *path, mode_t dir_mode, int file_open_flags, mode_t file_mode) { int error; + git_buf buf = GIT_BUF_FROM_BUFFER(buffer); if ((error = git_futils_mkpath2file(path, dir_mode)) < 0) return error; if ((error = git_futils_writebuffer( - buffer, path, file_open_flags, file_mode)) < 0) + &buf, path, file_open_flags, file_mode)) < 0) return error; if (st != NULL && (error = p_stat(path, st)) < 0) @@ -712,39 +713,26 @@ static int blob_content_to_file( { int error = 0; mode_t file_mode = opts->file_mode ? opts->file_mode : entry_filemode; - git_buf unfiltered = GIT_BUF_INIT, filtered = GIT_BUF_INIT; + git_buffer out = GIT_BUFFER_INIT; git_filter_list *fl = NULL; - /* Create a fake git_buf from the blob raw data... */ - filtered.ptr = (void *)git_blob_rawcontent(blob); - filtered.size = (size_t)git_blob_rawsize(blob); - - if (!opts->disable_filters && !git_buf_text_is_binary(&filtered)) { + if (!opts->disable_filters && !git_blob_is_binary(blob)) error = git_filter_list_load( &fl, git_blob_owner(blob), path, GIT_FILTER_TO_WORKTREE); - } - if (fl != NULL) { - /* reset 'filtered' so it can be a filter target */ - git_buf_init(&filtered, 0); + if (!error) + error = git_filter_list_apply_to_blob(&out, fl, blob); - if (!(error = git_blob__getbuf(&unfiltered, blob))) { - error = git_filter_list_apply(&filtered, &unfiltered, fl); - - git_buf_free(&unfiltered); - } + git_filter_list_free(fl); - git_filter_list_free(fl); - } + if (!error) { + error = buffer_to_file( + st, &out, path, opts->dir_mode, opts->file_open_flags, file_mode); - if (!error && - !(error = buffer_to_file( - st, &filtered, path, opts->dir_mode, - opts->file_open_flags, file_mode))) st->st_mode = entry_filemode; - if (filtered.asize != 0) - git_buf_free(&filtered); + git_buffer_free(&out); + } return error; } diff --git a/src/crlf.c b/src/crlf.c index 1242450d8..cc256fc70 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -8,6 +8,7 @@ #include "git2/attr.h" #include "git2/blob.h" #include "git2/index.h" +#include "git2/sys/filter.h" #include "common.h" #include "fileops.h" @@ -249,7 +250,6 @@ static int crlf_apply_to_workdir( static int crlf_check( git_filter *self, void **payload, /* points to NULL ptr on entry, may be set */ - git_filter_mode_t mode, const git_filter_source *src, const char **attr_values) { @@ -257,7 +257,6 @@ static int crlf_check( struct crlf_attrs ca; GIT_UNUSED(self); - GIT_UNUSED(mode); if (!attr_values) { ca.crlf_action = GIT_CRLF_GUESS; @@ -299,14 +298,13 @@ static int crlf_check( static int crlf_apply( git_filter *self, void **payload, /* may be read and/or set */ - git_filter_mode_t mode, git_buffer *to, const git_buffer *from, const git_filter_source *src) { GIT_UNUSED(self); - if (mode == GIT_FILTER_SMUDGE) + if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE) return crlf_apply_to_workdir(*payload, to, from); else return crlf_apply_to_odb(*payload, to, from, src); @@ -331,5 +329,6 @@ git_filter *git_crlf_filter_new(void) f->f.check = crlf_check; f->f.apply = crlf_apply; f->f.cleanup = crlf_cleanup; + return (git_filter *)f; } diff --git a/src/diff_file.c b/src/diff_file.c index 7602591cf..e0e244b65 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -297,8 +297,8 @@ static int diff_file_content_load_workdir_file( { int error = 0; git_filter_list *fl = NULL; - git_buf raw = GIT_BUF_INIT, filtered = GIT_BUF_INIT; git_file fd = git_futils_open_ro(git_buf_cstr(path)); + git_buf raw = GIT_BUF_INIT; if (fd < 0) return fd; @@ -326,16 +326,19 @@ static int diff_file_content_load_workdir_file( giterr_clear(); } - if (!(error = git_futils_readbuffer_fd(&raw, fd, (size_t)fc->file->size)) && - !(error = git_filter_list_apply(&filtered, &raw, fl))) - { - fc->map.len = git_buf_len(&filtered); - fc->map.data = git_buf_detach(&filtered); - fc->flags |= GIT_DIFF_FLAG__FREE_DATA; - } + if (!(error = git_futils_readbuffer_fd(&raw, fd, (size_t)fc->file->size))) { + git_buffer in = GIT_BUFFER_FROM_BUF(&raw), out = GIT_BUFFER_INIT; + + error = git_filter_list_apply_to_data(&out, fl, &in); + + git_buffer_free(&in); - git_buf_free(&raw); - git_buf_free(&filtered); + if (!error) { + fc->map.len = out.size; + fc->map.data = out.ptr; + fc->flags |= GIT_DIFF_FLAG__FREE_DATA; + } + } cleanup: git_filter_list_free(fl); diff --git a/src/filter.c b/src/filter.c index 7fbc20a41..de0d490aa 100644 --- a/src/filter.c +++ b/src/filter.c @@ -10,15 +10,18 @@ #include "hash.h" #include "filter.h" #include "repository.h" +#include "git2/sys/filter.h" #include "git2/config.h" #include "blob.h" #include "attr_file.h" +#include "array.h" struct git_filter_source { git_repository *repo; const char *path; git_oid oid; /* zero if unknown (which is likely) */ uint16_t filemode; /* zero if unknown */ + git_filter_mode_t mode; }; typedef struct { @@ -28,7 +31,6 @@ typedef struct { struct git_filter_list { git_array_t(git_filter_entry) filters; - git_filter_mode_t mode; git_filter_source source; char path[GIT_FLEX_ARRAY]; }; @@ -238,8 +240,13 @@ const git_oid *git_filter_source_id(const git_filter_source *src) return git_oid_iszero(&src->oid) ? NULL : &src->oid; } +git_filter_mode_t git_filter_source_mode(const git_filter_source *src) +{ + return src->mode; +} + static int git_filter_list_new( - git_filter_list **out, git_filter_mode_t mode, const git_filter_source *src) + git_filter_list **out, const git_filter_source *src) { git_filter_list *fl = NULL; size_t pathlen = src->path ? strlen(src->path) : 0; @@ -247,11 +254,11 @@ static int git_filter_list_new( fl = git__calloc(1, sizeof(git_filter_list) + pathlen + 1); GITERR_CHECK_ALLOC(fl); - fl->mode = mode; if (src->path) memcpy(fl->path, src->path, pathlen); fl->source.repo = src->repo; fl->source.path = fl->path; + fl->source.mode = src->mode; *out = fl; return 0; @@ -316,6 +323,7 @@ int git_filter_list_load( src.repo = repo; src.path = path; + src.mode = mode; git_vector_foreach(&git__filter_registry, idx, fdef) { const char **values = NULL; @@ -335,7 +343,7 @@ int git_filter_list_load( if (fdef->filter->check) error = fdef->filter->check( - fdef->filter, &payload, mode, &src, values); + fdef->filter, &payload, &src, values); git__free(values); @@ -344,7 +352,7 @@ int git_filter_list_load( else if (error < 0) break; else { - if (!fl && (error = git_filter_list_new(&fl, mode, &src)) < 0) + if (!fl && (error = git_filter_list_new(&fl, &src)) < 0) return error; fe = git_array_alloc(fl->filters); @@ -381,40 +389,46 @@ void git_filter_list_free(git_filter_list *fl) git__free(fl); } -int git_filter_list_apply( - git_buf *dest, - git_buf *source, - git_filter_list *fl) +static int filter_list_out_buffer_from_raw( + git_buffer *out, const void *ptr, size_t size) +{ + if (git_buffer_is_allocated(out)) + git_buffer_free(out); + + out->ptr = (char *)ptr; + out->size = size; + out->available = 0; + return 0; +} + +int git_filter_list_apply_to_data( + git_buffer *tgt, git_filter_list *fl, git_buffer *src) { int error = 0; uint32_t i; - unsigned int src; - git_buf *dbuffer[2]; - git_filter_entry *fe; + git_buffer *dbuffer[2], local = GIT_BUFFER_INIT; + unsigned int si = 0; - if (!fl) { - git_buf_swap(dest, source); - return 0; - } - - dbuffer[0] = source; - dbuffer[1] = dest; + if (!fl) + return filter_list_out_buffer_from_raw(tgt, src->ptr, src->size); - src = 0; + dbuffer[0] = src; + dbuffer[1] = tgt; - /* Pre-grow the destination buffer to more or less the size - * we expect it to have */ - if (git_buf_grow(dest, git_buf_len(source)) < 0) - return -1; + /* if `src` buffer is reallocable, then use it, otherwise copy it */ + if (!git_buffer_is_allocated(src)) { + if (git_buffer_copy(&local, src->ptr, src->size) < 0) + return -1; + dbuffer[0] = &local; + } for (i = 0; i < git_array_size(fl->filters); ++i) { - unsigned int dst = 1 - src; - - git_buf_clear(dbuffer[dst]); + unsigned int di = 1 - si; + uint32_t fidx = (fl->source.mode == GIT_FILTER_TO_ODB) ? + i : git_array_size(fl->filters) - 1 - i; + git_filter_entry *fe = git_array_get(fl->filters, fidx); - fe = git_array_get( - fl->filters, (fl->mode == GIT_FILTER_TO_ODB) ? - i : git_array_size(fl->filters) - 1 - i); + dbuffer[di]->size = 0; /* Apply the filter from dbuffer[src] to the other buffer; * if the filtering is canceled by the user mid-filter, @@ -422,33 +436,64 @@ int git_filter_list_apply( * of the double buffering (so that the text goes through * cleanly). */ - { - git_buffer srcb = GIT_BUFFER_FROM_BUF(dbuffer[src]); - git_buffer dstb = GIT_BUFFER_FROM_BUF(dbuffer[dst]); - error = fe->filter->apply( - fe->filter, &fe->payload, fl->mode, &dstb, &srcb, &fl->source); + error = fe->filter->apply( + fe->filter, &fe->payload, dbuffer[di], dbuffer[si], &fl->source); - if (error == GIT_ENOTFOUND) - error = 0; - else if (error < 0) { - git_buf_clear(dest); - return error; - } - else { - git_buf_from_buffer(dbuffer[src], &srcb); - git_buf_from_buffer(dbuffer[dst], &dstb); - src = dst; - } + if (error == GIT_ENOTFOUND) + error = 0; + else if (!error) + si = di; /* swap buffers */ + else { + tgt->size = 0; + return error; } - - if (git_buf_oom(dbuffer[dst])) - return -1; } /* Ensure that the output ends up in dbuffer[1] (i.e. the dest) */ - if (src != 1) - git_buf_swap(dest, source); + if (si != 1) { + git_buffer sw = *dbuffer[1]; + *dbuffer[1] = *dbuffer[0]; + *dbuffer[0] = sw; + } + + git_buffer_free(&local); /* don't leak if we allocated locally */ return 0; } + +int git_filter_list_apply_to_file( + git_buffer *out, + git_filter_list *filters, + git_repository *repo, + const char *path) +{ + int error; + const char *base = repo ? git_repository_workdir(repo) : NULL; + git_buf abspath = GIT_BUF_INIT, raw = GIT_BUF_INIT; + + if (!(error = git_path_join_unrooted(&abspath, path, base, NULL)) && + !(error = git_futils_readbuffer(&raw, abspath.ptr))) + { + git_buffer in = GIT_BUFFER_FROM_BUF(&raw); + + error = git_filter_list_apply_to_data(out, filters, &in); + + git_buffer_free(&in); + } + + git_buf_free(&abspath); + return error; +} + +int git_filter_list_apply_to_blob( + git_buffer *out, + git_filter_list *filters, + git_blob *blob) +{ + git_buffer in = { + (char *)git_blob_rawcontent(blob), git_blob_rawsize(blob), 0 + }; + + return git_filter_list_apply_to_data(out, filters, &in); +} diff --git a/src/filter.h b/src/filter.h index a4ee2172d..1bde1e306 100644 --- a/src/filter.h +++ b/src/filter.h @@ -8,12 +8,7 @@ #define INCLUDE_filter_h__ #include "common.h" -#include "buffer.h" -#include "array.h" -#include "git2/odb.h" -#include "git2/repository.h" #include "git2/filter.h" -#include "git2/sys/filter.h" typedef enum { GIT_CRLF_GUESS = -1, @@ -24,61 +19,6 @@ typedef enum { GIT_CRLF_AUTO, } git_crlf_t; -typedef struct git_filter_list git_filter_list; - -/* - * FILTER API - */ - -/* - * For any given path in the working directory, create a `git_filter_list` - * with the relevant filters that need to be applied. - * - * This will return 0 (success) but set the output git_filter_list to NULL - * if no filters are requested for the given file. - * - * @param filters Output newly created git_filter_list (or NULL) - * @param repo Repository object that contains `path` - * @param path Relative path of the file to be filtered - * @param mode Filtering direction (WT->ODB or ODB->WT) - * @return 0 on success (which could still return NULL if no filters are - * needed for the requested file), <0 on error - */ -extern int git_filter_list_load( - git_filter_list **filters, - git_repository *repo, - const char *path, - git_filter_mode_t mode); - -/* - * Apply one or more filters to a data buffer. - * - * The source data must have been loaded as a `git_buf` object. Both the - * `source` and `dest` buffers are owned by the caller and must be freed - * once they are no longer needed. - * - * NOTE: Because of the double-buffering schema, the `source` buffer that - * contains the original file may be tampered once the filtering is - * complete. Regardless, the `dest` buffer will always contain the final - * result of the filtering - * - * @param dest Buffer to store the result of the filtering - * @param source Buffer containing the document to filter - * @param filters An already loaded git_filter_list - * @return 0 on success, an error code otherwise - */ -extern int git_filter_list_apply( - git_buf *dest, - git_buf *source, - git_filter_list *filters); - -/* - * Free the git_filter_list - * - * @param filters A git_filter_list created by `git_filter_list_load` - */ -extern void git_filter_list_free(git_filter_list *filters); - /* * Available filters */ diff --git a/src/odb.c b/src/odb.c index d9310a9d7..b71b038bf 100644 --- a/src/odb.c +++ b/src/odb.c @@ -183,7 +183,6 @@ int git_odb__hashfd_filtered( { int error; git_buf raw = GIT_BUF_INIT; - git_buf filtered = GIT_BUF_INIT; if (!fl) return git_odb__hashfd(out, fd, size, type); @@ -192,15 +191,18 @@ int git_odb__hashfd_filtered( * into memory to apply filters before beginning to calculate the hash */ - if (!(error = git_futils_readbuffer_fd(&raw, fd, size))) - error = git_filter_list_apply(&filtered, &raw, fl); + if (!(error = git_futils_readbuffer_fd(&raw, fd, size))) { + git_buffer pre = GIT_BUFFER_FROM_BUF(&raw), post = GIT_BUFFER_INIT; - git_buf_free(&raw); + error = git_filter_list_apply_to_data(&post, fl, &pre); - if (!error) - error = git_odb_hash(out, filtered.ptr, filtered.size, type); + git_buffer_free(&pre); - git_buf_free(&filtered); + if (!error) + error = git_odb_hash(out, post.ptr, post.size, type); + + git_buffer_free(&post); + } return error; } diff --git a/tests-clar/object/blob/filter.c b/tests-clar/object/blob/filter.c index 33ebedcde..a23f897f9 100644 --- a/tests-clar/object/blob/filter.c +++ b/tests-clar/object/blob/filter.c @@ -1,7 +1,6 @@ #include "clar_libgit2.h" #include "posix.h" #include "blob.h" -#include "filter.h" #include "buf_text.h" static git_repository *g_repo = NULL; @@ -105,7 +104,7 @@ void test_object_blob_filter__to_odb(void) git_config *cfg; int i; git_blob *blob; - git_buf orig = GIT_BUF_INIT, out = GIT_BUF_INIT; + git_buffer out = GIT_BUFFER_INIT; cl_git_pass(git_repository_config(&cfg, g_repo)); cl_assert(cfg); @@ -119,17 +118,18 @@ void test_object_blob_filter__to_odb(void) for (i = 0; i < NUM_TEST_OBJECTS; i++) { cl_git_pass(git_blob_lookup(&blob, g_repo, &g_oids[i])); - cl_git_pass(git_blob__getbuf(&orig, blob)); - cl_git_pass(git_filter_list_apply(&out, &orig, fl)); - cl_assert(git_buf_cmp(&out, &g_crlf_filtered[i]) == 0); + cl_git_pass(git_filter_list_apply_to_blob(&out, fl, blob)); + + cl_assert(!memcmp( + out.ptr, g_crlf_filtered[i].ptr, + min(out.size, g_crlf_filtered[i].size))); git_blob_free(blob); } git_filter_list_free(fl); - git_buf_free(&orig); - git_buf_free(&out); + git_buffer_free(&out); git_config_free(cfg); } -- cgit v1.2.1 From 29e92d385e0bb43d45ddea5f8173d78fcceac3a6 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 10 Sep 2013 16:53:09 -0700 Subject: Hook up filter initialize callback I knew I forgot something --- include/git2/sys/filter.h | 2 ++ src/filter.c | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h index ca1fbfcce..dbb086b0e 100644 --- a/include/git2/sys/filter.h +++ b/include/git2/sys/filter.h @@ -139,7 +139,9 @@ typedef void (*git_filter_cleanup_fn)( */ struct git_filter { unsigned int version; + const char *attributes; + git_filter_init_fn initialize; git_filter_shutdown_fn shutdown; git_filter_check_fn check; diff --git a/src/filter.c b/src/filter.c index de0d490aa..050014671 100644 --- a/src/filter.c +++ b/src/filter.c @@ -39,6 +39,7 @@ typedef struct { const char *filter_name; git_filter *filter; int priority; + int initialized; size_t nattrs, nmatches; char *attrdata; const char *attrs[GIT_FLEX_ARRAY]; @@ -178,6 +179,23 @@ static git_filter_def *filter_find_by_name(size_t *pos, const char *name) return fdef; } +static int filter_initialize(git_filter_def *fdef) +{ + int error = 0; + + if (!fdef->initialized && + fdef->filter && + fdef->filter->initialize && + (error = fdef->filter->initialize(fdef->filter)) < 0) + { + git_filter_unregister(fdef->filter_name); + return error; + } + + fdef->initialized = true; + return 0; +} + int git_filter_unregister(const char *name) { size_t pos; @@ -196,8 +214,10 @@ int git_filter_unregister(const char *name) (void)git_vector_remove(&git__filter_registry, pos); - if (fdef->filter->shutdown) + if (fdef->initialized && fdef->filter && fdef->filter->shutdown) { fdef->filter->shutdown(fdef->filter); + fdef->initialized = false; + } git__free(fdef->attrdata); git__free(fdef); @@ -209,7 +229,14 @@ git_filter *git_filter_lookup(const char *name) { size_t pos; git_filter_def *fdef = filter_find_by_name(&pos, name); - return fdef ? fdef->filter : NULL; + + if (!fdef) + return NULL; + + if (!fdef->initialized && filter_initialize(fdef) < 0) + return NULL; + + return fdef->filter; } static int filter_load_defaults(void) @@ -341,6 +368,9 @@ int git_filter_list_load( break; } + if (!fdef->initialized && (error = filter_initialize(fdef)) < 0) + break; + if (fdef->filter->check) error = fdef->filter->check( fdef->filter, &payload, &src, values); -- cgit v1.2.1 From e7d0ced2192c5efeea6d9f5667d366891010b86a Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 11 Sep 2013 12:38:06 -0700 Subject: Fix longstanding valgrind warning There was a possible circumstance that could result in reading past the end of a buffer. This check fixes that. --- src/buf_text.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/buf_text.c b/src/buf_text.c index eda86adb3..631feb3f8 100644 --- a/src/buf_text.c +++ b/src/buf_text.c @@ -87,7 +87,7 @@ int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src) } /* Do not drop \r unless it is followed by \n */ - if (next[1] != '\n') + if (next + 1 == scan_end || next[1] != '\n') *out++ = '\r'; } -- cgit v1.2.1 From a3aa5f4d5dcbe038f1d1c5ff40eed29d27953fbe Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 11 Sep 2013 12:45:20 -0700 Subject: Add simple global shutdown hooks Increasingly there are a number of components that want to do some cleanup at global shutdown time (at least if there are not going to be memory leaks). This creates a very simple system of shutdown hooks that will be invoked by git_threads_shutdown. Right now, the maximum number of hooks is hardcoded, but since adding a hook is not a public API, it should be fine and I thought it was better to start off with really simple code. --- src/fileops.c | 17 ++++++++++------- src/fileops.h | 5 ----- src/global.c | 38 ++++++++++++++++++++++++++++---------- src/global.h | 4 ++++ src/hash.h | 2 -- src/hash/hash_generic.h | 1 - src/hash/hash_openssl.h | 1 - src/hash/hash_win32.c | 20 +++++++++++--------- src/win32/pthread.c | 18 +++++++++--------- src/win32/pthread.h | 1 - 10 files changed, 62 insertions(+), 45 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 126d45f26..3b271e6f6 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -6,6 +6,7 @@ */ #include "common.h" #include "fileops.h" +#include "global.h" #include #if GIT_WIN32 #include "win32/findfile.h" @@ -635,6 +636,13 @@ static git_futils_dirs_guess_cb git_futils__dir_guess[GIT_FUTILS_DIR__MAX] = { git_futils_guess_xdg_dirs, }; +static void git_futils_dirs_global_shutdown(void) +{ + int i; + for (i = 0; i < GIT_FUTILS_DIR__MAX; ++i) + git_buf_free(&git_futils__dirs[i]); +} + int git_futils_dirs_global_init(void) { git_futils_dir_t i; @@ -644,6 +652,8 @@ int git_futils_dirs_global_init(void) for (i = 0; !error && i < GIT_FUTILS_DIR__MAX; i++) error = git_futils_dirs_get(&path, i); + git__on_shutdown(git_futils_dirs_global_shutdown); + return error; } @@ -726,13 +736,6 @@ int git_futils_dirs_set(git_futils_dir_t which, const char *search_path) return git_buf_oom(&git_futils__dirs[which]) ? -1 : 0; } -void git_futils_dirs_free(void) -{ - int i; - for (i = 0; i < GIT_FUTILS_DIR__MAX; ++i) - git_buf_free(&git_futils__dirs[i]); -} - static int git_futils_find_in_dirlist( git_buf *path, const char *name, git_futils_dir_t which, const char *label) { diff --git a/src/fileops.h b/src/fileops.h index 02f79b9e7..16bc58e93 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -353,11 +353,6 @@ extern int git_futils_dirs_get_str( */ extern int git_futils_dirs_set(git_futils_dir_t which, const char *paths); -/** - * Release / reset all search paths - */ -extern void git_futils_dirs_free(void); - /** * Create a "fake" symlink (text file containing the target path). * diff --git a/src/global.c b/src/global.c index b504e5e0a..4f024f17e 100644 --- a/src/global.c +++ b/src/global.c @@ -14,6 +14,28 @@ git_mutex git__mwindow_mutex; +#define MAX_SHUTDOWN_CB 8 + +git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB]; +git_atomic git__n_shutdown_callbacks; + +void git__on_shutdown(git_global_shutdown_fn callback) +{ + int count = git_atomic_inc(&git__n_shutdown_callbacks); + assert(count <= MAX_SHUTDOWN_CB); + git__shutdown_callbacks[count - 1] = callback; +} + +static void git__shutdown(void) +{ + int pos; + + while ((pos = git_atomic_dec(&git__n_shutdown_callbacks)) >= 0) { + if (git__shutdown_callbacks[pos]) + git__shutdown_callbacks[pos](); + } +} + /** * Handle the global state with TLS * @@ -79,9 +101,7 @@ int git_threads_init(void) void git_threads_shutdown(void) { /* Shut down any subsystems that have global state */ - win32_pthread_shutdown(); - git_futils_dirs_free(); - git_hash_global_shutdown(); + git__shutdown(); TlsFree(_tls_index); _tls_init = 0; @@ -140,6 +160,9 @@ int git_threads_init(void) void git_threads_shutdown(void) { + /* Shut down any subsystems that have global state */ + git__shutdown(); + if (_tls_init) { void *ptr = pthread_getspecific(_tls_key); pthread_setspecific(_tls_key, NULL); @@ -149,10 +172,6 @@ void git_threads_shutdown(void) pthread_key_delete(_tls_key); _tls_init = 0; git_mutex_free(&git__mwindow_mutex); - - /* Shut down any subsystems that have global state */ - git_hash_global_shutdown(); - git_futils_dirs_free(); } git_global_st *git__global_state(void) @@ -179,15 +198,14 @@ static git_global_st __state; int git_threads_init(void) { - /* noop */ + /* noop */ return 0; } void git_threads_shutdown(void) { /* Shut down any subsystems that have global state */ - git_hash_global_shutdown(); - git_futils_dirs_free(); + git__shutdown(); } git_global_st *git__global_state(void) diff --git a/src/global.h b/src/global.h index badbc0883..778250376 100644 --- a/src/global.h +++ b/src/global.h @@ -21,4 +21,8 @@ extern git_mutex git__mwindow_mutex; #define GIT_GLOBAL (git__global_state()) +typedef void (*git_global_shutdown_fn)(void); + +extern void git__on_shutdown(git_global_shutdown_fn callback); + #endif diff --git a/src/hash.h b/src/hash.h index 5b848981f..c47f33549 100644 --- a/src/hash.h +++ b/src/hash.h @@ -13,8 +13,6 @@ typedef struct git_hash_prov git_hash_prov; typedef struct git_hash_ctx git_hash_ctx; int git_hash_global_init(void); -void git_hash_global_shutdown(void); - int git_hash_ctx_init(git_hash_ctx *ctx); void git_hash_ctx_cleanup(git_hash_ctx *ctx); diff --git a/src/hash/hash_generic.h b/src/hash/hash_generic.h index 6b60c98c4..daeb1cda8 100644 --- a/src/hash/hash_generic.h +++ b/src/hash/hash_generic.h @@ -17,7 +17,6 @@ struct git_hash_ctx { }; #define git_hash_global_init() 0 -#define git_hash_global_shutdown() /* noop */ #define git_hash_ctx_init(ctx) git_hash_init(ctx) #define git_hash_ctx_cleanup(ctx) diff --git a/src/hash/hash_openssl.h b/src/hash/hash_openssl.h index f83279a5a..9a55d472d 100644 --- a/src/hash/hash_openssl.h +++ b/src/hash/hash_openssl.h @@ -17,7 +17,6 @@ struct git_hash_ctx { }; #define git_hash_global_init() 0 -#define git_hash_global_shutdown() /* noop */ #define git_hash_ctx_init(ctx) git_hash_init(ctx) #define git_hash_ctx_cleanup(ctx) diff --git a/src/hash/hash_win32.c b/src/hash/hash_win32.c index 095ceb359..bb2231364 100644 --- a/src/hash/hash_win32.c +++ b/src/hash/hash_win32.c @@ -89,7 +89,15 @@ GIT_INLINE(void) hash_cryptoapi_prov_shutdown(void) hash_prov.type = INVALID; } -int git_hash_global_init() +static void git_hash_global_shutdown(void) +{ + if (hash_prov.type == CNG) + hash_cng_prov_shutdown(); + else if(hash_prov.type == CRYPTOAPI) + hash_cryptoapi_prov_shutdown(); +} + +int git_hash_global_init(void) { int error = 0; @@ -99,15 +107,9 @@ int git_hash_global_init() if ((error = hash_cng_prov_init()) < 0) error = hash_cryptoapi_prov_init(); - return error; -} + git__on_shutdown(git_hash_global_shutdown); -void git_hash_global_shutdown() -{ - if (hash_prov.type == CNG) - hash_cng_prov_shutdown(); - else if(hash_prov.type == CRYPTOAPI) - hash_cryptoapi_prov_shutdown(); + return error; } /* CryptoAPI: available in Windows XP and newer */ diff --git a/src/win32/pthread.c b/src/win32/pthread.c index d50ace695..8c7ef2856 100644 --- a/src/win32/pthread.c +++ b/src/win32/pthread.c @@ -217,6 +217,14 @@ int pthread_rwlock_destroy(pthread_rwlock_t *lock) } +static void win32_pthread_shutdown(void) +{ + if (win32_kernel32_dll) { + FreeLibrary(win32_kernel32_dll); + win32_kernel32_dll = NULL; + } +} + int win32_pthread_initialize(void) { if (win32_kernel32_dll) @@ -239,15 +247,7 @@ int win32_pthread_initialize(void) win32_srwlock_release_exclusive = (win32_srwlock_fn) GetProcAddress(win32_kernel32_dll, "ReleaseSRWLockExclusive"); - return 0; -} - -int win32_pthread_shutdown(void) -{ - if (win32_kernel32_dll) { - FreeLibrary(win32_kernel32_dll); - win32_kernel32_dll = NULL; - } + git__on_shutdown(win32_pthread_shutdown); return 0; } diff --git a/src/win32/pthread.h b/src/win32/pthread.h index 2ba2ca552..af5b121f0 100644 --- a/src/win32/pthread.h +++ b/src/win32/pthread.h @@ -69,6 +69,5 @@ int pthread_rwlock_wrunlock(pthread_rwlock_t *); int pthread_rwlock_destroy(pthread_rwlock_t *); extern int win32_pthread_initialize(void); -extern int win32_pthread_shutdown(void); #endif -- cgit v1.2.1 From 0646634e2fea3e0adf724e0b7b15118574b589fc Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 11 Sep 2013 12:45:37 -0700 Subject: Update filter registry code This updates the git filter registry to be a little cleaner and plugs some memory leaks. --- src/crlf.c | 13 +++-- src/filter.c | 167 ++++++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 122 insertions(+), 58 deletions(-) diff --git a/src/crlf.c b/src/crlf.c index cc256fc70..e974208a6 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -318,6 +318,11 @@ static void crlf_cleanup( git__free(payload); } +static void crlf_shutdown(git_filter *self) +{ + git__free(self); +} + git_filter *git_crlf_filter_new(void) { struct crlf_filter *f = git__calloc(1, sizeof(struct crlf_filter)); @@ -325,10 +330,10 @@ git_filter *git_crlf_filter_new(void) f->f.version = GIT_FILTER_VERSION; f->f.attributes = "crlf eol text"; f->f.initialize = NULL; - f->f.shutdown = NULL; - f->f.check = crlf_check; - f->f.apply = crlf_apply; - f->f.cleanup = crlf_cleanup; + f->f.shutdown = crlf_shutdown; + f->f.check = crlf_check; + f->f.apply = crlf_apply; + f->f.cleanup = crlf_cleanup; return (git_filter *)f; } diff --git a/src/filter.c b/src/filter.c index 050014671..73c2ceacb 100644 --- a/src/filter.c +++ b/src/filter.c @@ -10,6 +10,7 @@ #include "hash.h" #include "filter.h" #include "repository.h" +#include "global.h" #include "git2/sys/filter.h" #include "git2/config.h" #include "blob.h" @@ -52,10 +53,64 @@ static int filter_def_priority_cmp(const void *a, const void *b) return (pa < pb) ? -1 : (pa > pb) ? 1 : 0; } -static git_vector git__filter_registry = { - 0, filter_def_priority_cmp, NULL, 0, 0 +struct filter_registry { + git_vector filters; }; +static struct filter_registry *git__filter_registry = NULL; + +static void filter_registry_shutdown(void) +{ + struct filter_registry *reg = NULL; + size_t pos; + git_filter_def *fdef; + + if ((reg = git__swap(git__filter_registry, NULL)) == NULL) + return; + + git_vector_foreach(®->filters, pos, fdef) { + if (fdef->initialized && fdef->filter && fdef->filter->shutdown) { + fdef->filter->shutdown(fdef->filter); + fdef->initialized = false; + } + + git__free(fdef->attrdata); + git__free(fdef); + } + + git_vector_free(®->filters); + git__free(reg); +} + +static int filter_registry_initialize(void) +{ + int error = 0; + struct filter_registry *reg; + + if (git__filter_registry) + return 0; + + reg = git__calloc(1, sizeof(struct filter_registry)); + GITERR_CHECK_ALLOC(reg); + + if ((error = git_vector_init( + ®->filters, 2, filter_def_priority_cmp)) < 0) + goto cleanup; + + reg = git__compare_and_swap(&git__filter_registry, NULL, reg); + if (reg != NULL) + goto cleanup; + + git__on_shutdown(filter_registry_shutdown); + + return git_filter_register(GIT_FILTER_CRLF, git_crlf_filter_new(), 0); + +cleanup: + git_vector_free(®->filters); + git__free(reg); + return error; +} + static int filter_def_scan_attrs( git_buf *attrs, size_t *nattr, size_t *nmatch, const char *attr_str) { @@ -122,6 +177,29 @@ static void filter_def_set_attrs(git_filter_def *fdef) } } +static int filter_def_name_key_check(const void *key, const void *fdef) +{ + const char *name = + fdef ? ((const git_filter_def *)fdef)->filter_name : NULL; + return name ? -1 : git__strcmp(key, name); +} + +static int filter_registry_find(size_t *pos, const char *name) +{ + return git_vector_search2( + pos, &git__filter_registry->filters, filter_def_name_key_check, name); +} + +static git_filter_def *filter_registry_lookup(size_t *pos, const char *name) +{ + git_filter_def *fdef = NULL; + + if (!filter_registry_find(pos, name)) + fdef = git_vector_get(&git__filter_registry->filters, *pos); + + return fdef; +} + int git_filter_register( const char *name, git_filter *filter, int priority) { @@ -129,7 +207,10 @@ int git_filter_register( size_t nattr = 0, nmatch = 0; git_buf attrs = GIT_BUF_INIT; - if (git_filter_lookup(name) != NULL) { + if (filter_registry_initialize() < 0) + return -1; + + if (!filter_registry_find(NULL, name)) { giterr_set( GITERR_FILTER, "Attempt to reregister existing filter '%s'", name); return -1; @@ -151,48 +232,13 @@ int git_filter_register( filter_def_set_attrs(fdef); - if (git_vector_insert(&git__filter_registry, fdef) < 0) { + if (git_vector_insert(&git__filter_registry->filters, fdef) < 0) { git__free(fdef->attrdata); git__free(fdef); return -1; } - git_vector_sort(&git__filter_registry); - return 0; -} - -static int filter_def_name_key_check(const void *key, const void *fdef) -{ - const char *name = - fdef ? ((const git_filter_def *)fdef)->filter_name : NULL; - return name ? -1 : git__strcmp(key, name); -} - -static git_filter_def *filter_find_by_name(size_t *pos, const char *name) -{ - git_filter_def *fdef = NULL; - - if (!git_vector_search2( - pos, &git__filter_registry, filter_def_name_key_check, name)) - fdef = git_vector_get(&git__filter_registry, *pos); - - return fdef; -} - -static int filter_initialize(git_filter_def *fdef) -{ - int error = 0; - - if (!fdef->initialized && - fdef->filter && - fdef->filter->initialize && - (error = fdef->filter->initialize(fdef->filter)) < 0) - { - git_filter_unregister(fdef->filter_name); - return error; - } - - fdef->initialized = true; + git_vector_sort(&git__filter_registry->filters); return 0; } @@ -207,12 +253,12 @@ int git_filter_unregister(const char *name) return -1; } - if ((fdef = filter_find_by_name(&pos, name)) == NULL) { + if ((fdef = filter_registry_lookup(&pos, name)) == NULL) { giterr_set(GITERR_FILTER, "Cannot find filter '%s' to unregister", name); return GIT_ENOTFOUND; } - (void)git_vector_remove(&git__filter_registry, pos); + (void)git_vector_remove(&git__filter_registry->filters, pos); if (fdef->initialized && fdef->filter && fdef->filter->shutdown) { fdef->filter->shutdown(fdef->filter); @@ -225,12 +271,33 @@ int git_filter_unregister(const char *name) return 0; } +static int filter_initialize(git_filter_def *fdef) +{ + int error = 0; + + if (!fdef->initialized && + fdef->filter && + fdef->filter->initialize && + (error = fdef->filter->initialize(fdef->filter)) < 0) + { + /* auto-unregister if initialize fails */ + git_filter_unregister(fdef->filter_name); + return error; + } + + fdef->initialized = true; + return 0; +} + git_filter *git_filter_lookup(const char *name) { size_t pos; - git_filter_def *fdef = filter_find_by_name(&pos, name); + git_filter_def *fdef; + + if (filter_registry_initialize() < 0) + return NULL; - if (!fdef) + if ((fdef = filter_registry_lookup(&pos, name)) == NULL) return NULL; if (!fdef->initialized && filter_initialize(fdef) < 0) @@ -239,14 +306,6 @@ git_filter *git_filter_lookup(const char *name) return fdef->filter; } -static int filter_load_defaults(void) -{ - if (!git_vector_length(&git__filter_registry)) - return git_filter_register(GIT_FILTER_CRLF, git_crlf_filter_new(), 0); - - return 0; -} - git_repository *git_filter_source_repo(const git_filter_source *src) { return src->repo; @@ -345,14 +404,14 @@ int git_filter_list_load( size_t idx; git_filter_def *fdef; - if (filter_load_defaults() < 0) + if (filter_registry_initialize() < 0) return -1; src.repo = repo; src.path = path; src.mode = mode; - git_vector_foreach(&git__filter_registry, idx, fdef) { + git_vector_foreach(&git__filter_registry->filters, idx, fdef) { const char **values = NULL; void *payload = NULL; -- cgit v1.2.1 From 40cb40fab93281c808255d980bbe81a18a4d9e9a Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 11 Sep 2013 14:23:39 -0700 Subject: Add functions to manipulate filter lists Extend the git2/sys/filter API with functions to look up a filter and add it manually to a filter list. This requires some trickery because the regular attribute lookups and checks are bypassed when this happens, but in the right hands, it will allow a user to have granular control over applying filters. --- include/git2/filter.h | 17 ---------- include/git2/sys/filter.h | 37 +++++++++++++++++++++ src/buffer.c | 3 +- src/crlf.c | 14 +++++--- src/filter.c | 52 +++++++++++++++++++++++++++-- tests-clar/filter/crlf.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 181 insertions(+), 25 deletions(-) create mode 100644 tests-clar/filter/crlf.c diff --git a/include/git2/filter.h b/include/git2/filter.h index cb23ae4f4..8ef88d81b 100644 --- a/include/git2/filter.h +++ b/include/git2/filter.h @@ -62,23 +62,6 @@ typedef struct git_filter git_filter; */ typedef struct git_filter_list git_filter_list; -/** - * Look up a filter by name - */ -GIT_EXTERN(git_filter *) git_filter_lookup(const char *name); - -#define GIT_FILTER_CRLF "crlf" - -/** - * Apply a single filter to a buffer of data - */ -GIT_EXTERN(int) git_filter_apply_to_buffer( - git_buffer *out, - git_filter *filter, - const git_buffer *input, - const char *as_path, - git_filter_mode_t mode); - /** * Load the filter list for a given path. * diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h index dbb086b0e..ca5738a53 100644 --- a/include/git2/sys/filter.h +++ b/include/git2/sys/filter.h @@ -18,6 +18,43 @@ */ GIT_BEGIN_DECL +/** + * Look up a filter by name + * + * @param name The name of the filter + * @return Pointer to the filter object or NULL if not found + */ +GIT_EXTERN(git_filter *) git_filter_lookup(const char *name); + +#define GIT_FILTER_CRLF "crlf" + +/** + * Create a new empty filter list + * + * Normally you won't use this because `git_filter_list_load` will create + * the filter list for you, but you can use this in combination with the + * `git_filter_lookup` and `git_filter_list_push` functions to assemble + * your own chains of filters. + */ +GIT_EXTERN(int) git_filter_list_new( + git_filter_list **out, git_repository *repo, git_filter_mode_t mode); + +/** + * Add a filter to a filter list with the given payload. + * + * Normally you won't have to do this because the filter list is created + * by calling the "check" function on registered filters when the filter + * attributes are set, but this does allow more direct manipulation of + * filter lists when desired. + * + * Note that normally the "check" function can set up a payload for the + * filter. Using this function, you can either pass in a payload if you + * know the expected payload format, or you can pass NULL. Some filters + * may fail with a NULL payload. Good luck! + */ +GIT_EXTERN(int) git_filter_list_push( + git_filter_list *fl, git_filter *filter, void *payload); + /** * A filter source represents a file/blob to be processed */ diff --git a/src/buffer.c b/src/buffer.c index aaebac776..07725b9cc 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -548,9 +548,10 @@ int git_buffer_resize(git_buffer *buffer, size_t want_size) int git_buffer_copy( git_buffer *buffer, const void *data, size_t datalen) { - if (git_buffer__resize(buffer, datalen, false) < 0) + if (git_buffer__resize(buffer, datalen + 1, false) < 0) return -1; memcpy(buffer->ptr, data, datalen); + buffer->ptr[datalen] = '\0'; buffer->size = datalen; return 0; } diff --git a/src/crlf.c b/src/crlf.c index e974208a6..99c154f70 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -86,6 +86,9 @@ static int has_cr_in_index(const git_filter_source *src) git_off_t blobsize; bool found_cr; + if (!path) + return false; + if (git_repository_index__weakptr(&index, repo) < 0) { giterr_clear(); return false; @@ -189,9 +192,7 @@ static const char *line_ending(struct crlf_attrs *ca) switch (ca->eol) { case GIT_EOL_UNSET: - return GIT_EOL_NATIVE == GIT_EOL_CRLF - ? "\r\n" - : "\n"; + return GIT_EOL_NATIVE == GIT_EOL_CRLF ? "\r\n" : "\n"; case GIT_EOL_CRLF: return "\r\n"; @@ -302,7 +303,12 @@ static int crlf_apply( const git_buffer *from, const git_filter_source *src) { - GIT_UNUSED(self); + /* initialize payload in case `check` was bypassed */ + if (!*payload) { + int error = crlf_check(self, payload, src, NULL); + if (error < 0 && error != GIT_ENOTFOUND) + return error; + } if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE) return crlf_apply_to_workdir(*payload, to, from); diff --git a/src/filter.c b/src/filter.c index 73c2ceacb..79ccac0cf 100644 --- a/src/filter.c +++ b/src/filter.c @@ -181,7 +181,13 @@ static int filter_def_name_key_check(const void *key, const void *fdef) { const char *name = fdef ? ((const git_filter_def *)fdef)->filter_name : NULL; - return name ? -1 : git__strcmp(key, name); + return name ? git__strcmp(key, name) : -1; +} + +static int filter_def_filter_key_check(const void *key, const void *fdef) +{ + const void *filter = fdef ? ((const git_filter_def *)fdef)->filter : NULL; + return (key == filter) ? 0 : -1; } static int filter_registry_find(size_t *pos, const char *name) @@ -331,7 +337,7 @@ git_filter_mode_t git_filter_source_mode(const git_filter_source *src) return src->mode; } -static int git_filter_list_new( +static int filter_list_new( git_filter_list **out, const git_filter_source *src) { git_filter_list *fl = NULL; @@ -391,6 +397,16 @@ static int filter_list_check_attributes( return error; } +int git_filter_list_new( + git_filter_list **out, git_repository *repo, git_filter_mode_t mode) +{ + git_filter_source src = { 0 }; + src.repo = repo; + src.path = NULL; + src.mode = mode; + return filter_list_new(out, &src); +} + int git_filter_list_load( git_filter_list **filters, git_repository *repo, @@ -441,7 +457,7 @@ int git_filter_list_load( else if (error < 0) break; else { - if (!fl && (error = git_filter_list_new(&fl, &src)) < 0) + if (!fl && (error = filter_list_new(&fl, &src)) < 0) return error; fe = git_array_alloc(fl->filters); @@ -478,6 +494,36 @@ void git_filter_list_free(git_filter_list *fl) git__free(fl); } +int git_filter_list_push( + git_filter_list *fl, git_filter *filter, void *payload) +{ + int error = 0; + size_t pos; + git_filter_def *fdef; + git_filter_entry *fe; + + assert(fl && filter); + + if (git_vector_search2( + &pos, &git__filter_registry->filters, + filter_def_filter_key_check, filter) < 0) { + giterr_set(GITERR_FILTER, "Cannot use an unregistered filter"); + return -1; + } + + fdef = git_vector_get(&git__filter_registry->filters, pos); + + if (!fdef->initialized && (error = filter_initialize(fdef)) < 0) + return error; + + fe = git_array_alloc(fl->filters); + GITERR_CHECK_ALLOC(fe); + fe->filter = filter; + fe->payload = payload; + + return 0; +} + static int filter_list_out_buffer_from_raw( git_buffer *out, const void *ptr, size_t size) { diff --git a/tests-clar/filter/crlf.c b/tests-clar/filter/crlf.c new file mode 100644 index 000000000..098a85d4c --- /dev/null +++ b/tests-clar/filter/crlf.c @@ -0,0 +1,83 @@ +#include "clar_libgit2.h" +#include "git2/sys/filter.h" + +static git_repository *g_repo = NULL; + +void test_filter_crlf__initialize(void) +{ + g_repo = cl_git_sandbox_init("crlf"); + + cl_git_mkfile("crlf/.gitattributes", + "*.txt text\n*.bin binary\n*.crlf text eol=crlf\n*.lf text eol=lf\n"); +} + +void test_filter_crlf__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_filter_crlf__to_worktree(void) +{ + git_filter_list *fl; + git_filter *crlf; + git_buffer in = GIT_BUFFER_INIT, out = GIT_BUFFER_INIT; + + { + git_config *cfg; + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_string(cfg, "core.autocrlf", "true")); + git_config_free(cfg); + } + + cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_WORKTREE)); + + crlf = git_filter_lookup(GIT_FILTER_CRLF); + cl_assert(crlf != NULL); + + cl_git_pass(git_filter_list_push(fl, crlf, NULL)); + + in.ptr = "Some text\nRight here\n"; + in.size = strlen(in.ptr); + + cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); + +#ifdef GIT_WIN32 + cl_assert_equal_s("Some text\r\nRight here\r\n", out.ptr); +#else + cl_assert_equal_s("Some text\nRight here\n", out.ptr); +#endif + + git_filter_list_free(fl); + git_buffer_free(&out); +} + +void test_filter_crlf__to_odb(void) +{ + git_filter_list *fl; + git_filter *crlf; + git_buffer in = GIT_BUFFER_INIT, out = GIT_BUFFER_INIT; + + { + git_config *cfg; + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_string(cfg, "core.autocrlf", "true")); + git_config_free(cfg); + } + + cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_ODB)); + + crlf = git_filter_lookup(GIT_FILTER_CRLF); + cl_assert(crlf != NULL); + + cl_git_pass(git_filter_list_push(fl, crlf, NULL)); + + in.ptr = "Some text\r\nRight here\r\n"; + in.size = strlen(in.ptr); + + cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); + + cl_assert_equal_s("Some text\nRight here\n", out.ptr); + + git_filter_list_free(fl); + git_buffer_free(&out); +} -- cgit v1.2.1 From 4b11f25a4fbb6952284e037a70e2d61fde841ab6 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 11 Sep 2013 16:38:33 -0700 Subject: Add ident filter This adds the ident filter (that knows how to replace $Id$) and tweaks the filter APIs and code so that git_filter_source objects actually have the updated OID of the object being filtered when it is a known value. --- include/git2/filter.h | 6 +- include/git2/sys/filter.h | 11 +++- src/blob.c | 8 +-- src/checkout.c | 2 +- src/crlf.c | 7 +-- src/diff.c | 2 +- src/diff_file.c | 2 +- src/filter.c | 31 +++++++++- src/filter.h | 3 + src/ident.c | 128 +++++++++++++++++++++++++++++++++++++++ src/repository.c | 3 +- tests-clar/filter/blob.c | 40 +++++++++++- tests-clar/filter/ident.c | 131 ++++++++++++++++++++++++++++++++++++++++ tests-clar/object/blob/filter.c | 4 +- 14 files changed, 355 insertions(+), 23 deletions(-) create mode 100644 src/ident.c create mode 100644 tests-clar/filter/ident.c diff --git a/include/git2/filter.h b/include/git2/filter.h index 8ef88d81b..649ed97cf 100644 --- a/include/git2/filter.h +++ b/include/git2/filter.h @@ -42,11 +42,13 @@ typedef enum { * file data. Libgit2 includes one built in filter and it is possible to * write your own (see git2/sys/filter.h for information on that). * - * The built in filter is: + * The two builtin filters are: * * * "crlf" which uses the complex rules with the "text", "eol", and * "crlf" file attributes to decide how to convert between LF and CRLF * line endings + * * "ident" which replaces "$Id$" in a blob with "$Id: $" upon + * checkout and replaced "$Id: $" with "$Id$" on checkin. */ typedef struct git_filter git_filter; @@ -70,6 +72,7 @@ typedef struct git_filter_list git_filter_list; * * @param filters Output newly created git_filter_list (or NULL) * @param repo Repository object that contains `path` + * @param blob The blob to which the filter will be applied (if known) * @param path Relative path of the file to be filtered * @param mode Filtering direction (WT->ODB or ODB->WT) * @return 0 on success (which could still return NULL if no filters are @@ -78,6 +81,7 @@ typedef struct git_filter_list git_filter_list; GIT_EXTERN(int) git_filter_list_load( git_filter_list **filters, git_repository *repo, + git_blob *blob, /* can be NULL */ const char *path, git_filter_mode_t mode); diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h index ca5738a53..c35fe55f6 100644 --- a/include/git2/sys/filter.h +++ b/include/git2/sys/filter.h @@ -26,7 +26,11 @@ GIT_BEGIN_DECL */ GIT_EXTERN(git_filter *) git_filter_lookup(const char *name); -#define GIT_FILTER_CRLF "crlf" +#define GIT_FILTER_CRLF "crlf" +#define GIT_FILTER_IDENT "ident" + +#define GIT_FILTER_CRLF_PRIORITY 0 +#define GIT_FILTER_IDENT_PRIORITY 100 /** * Create a new empty filter list @@ -199,8 +203,9 @@ struct git_filter { * issued in order of `priority` on smudge (to workdir), and in reverse * order of `priority` on clean (to odb). * - * One filter will be preregistered with libgit2: - * - GIT_FILTER_CRLF with priority of 0. + * Two filters are preregistered with libgit2: + * - GIT_FILTER_CRLF with priority 0 + * - GIT_FILTER_IDENT with priority 100 * * Currently the filter registry is not thread safe, so any registering or * deregistering of filters must be done outside of any possible usage of diff --git a/src/blob.c b/src/blob.c index e6bba033a..97fd6f70d 100644 --- a/src/blob.c +++ b/src/blob.c @@ -195,7 +195,7 @@ int git_blob__create_from_paths( if (try_load_filters) /* Load the filters for writing this file to the ODB */ error = git_filter_list_load( - &fl, repo, hint_path, GIT_FILTER_TO_ODB); + &fl, repo, NULL, hint_path, GIT_FILTER_TO_ODB); if (error < 0) /* well, that didn't work */; @@ -331,19 +331,19 @@ int git_blob_is_binary(git_blob *blob) int git_blob_filtered_content( git_buffer *out, git_blob *blob, - const char *as_path, + const char *path, int check_for_binary_data) { int error = 0; git_filter_list *fl = NULL; - assert(blob && as_path && out); + assert(blob && path && out); if (check_for_binary_data && git_blob_is_binary(blob)) return 0; if (!(error = git_filter_list_load( - &fl, git_blob_owner(blob), as_path, GIT_FILTER_TO_WORKTREE))) { + &fl, git_blob_owner(blob), blob, path, GIT_FILTER_TO_WORKTREE))) { error = git_filter_list_apply_to_blob(out, fl, blob); diff --git a/src/checkout.c b/src/checkout.c index 1def58b0a..7e79c9b5e 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -718,7 +718,7 @@ static int blob_content_to_file( if (!opts->disable_filters && !git_blob_is_binary(blob)) error = git_filter_list_load( - &fl, git_blob_owner(blob), path, GIT_FILTER_TO_WORKTREE); + &fl, git_blob_owner(blob), blob, path, GIT_FILTER_TO_WORKTREE); if (!error) error = git_filter_list_apply_to_blob(&out, fl, blob); diff --git a/src/crlf.c b/src/crlf.c index 99c154f70..f61a870da 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -324,11 +324,6 @@ static void crlf_cleanup( git__free(payload); } -static void crlf_shutdown(git_filter *self) -{ - git__free(self); -} - git_filter *git_crlf_filter_new(void) { struct crlf_filter *f = git__calloc(1, sizeof(struct crlf_filter)); @@ -336,7 +331,7 @@ git_filter *git_crlf_filter_new(void) f->f.version = GIT_FILTER_VERSION; f->f.attributes = "crlf eol text"; f->f.initialize = NULL; - f->f.shutdown = crlf_shutdown; + f->f.shutdown = git_filter_free; f->f.check = crlf_check; f->f.apply = crlf_apply; f->f.cleanup = crlf_cleanup; diff --git a/src/diff.c b/src/diff.c index b1cde36bc..4d9ace183 100644 --- a/src/diff.c +++ b/src/diff.c @@ -570,7 +570,7 @@ int git_diff__oid_for_file( } else { git_filter_list *fl = NULL; - result = git_filter_list_load(&fl, repo, path, GIT_FILTER_TO_ODB); + result = git_filter_list_load(&fl, repo, NULL, path, GIT_FILTER_TO_ODB); if (!result) { int fd = git_futils_open_ro(full_path.ptr); if (fd < 0) diff --git a/src/diff_file.c b/src/diff_file.c index e0e244b65..d02787c75 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -311,7 +311,7 @@ static int diff_file_content_load_workdir_file( goto cleanup; if ((error = git_filter_list_load( - &fl, fc->repo, fc->file->path, GIT_FILTER_TO_ODB)) < 0) + &fl, fc->repo, NULL, fc->file->path, GIT_FILTER_TO_ODB)) < 0) goto cleanup; /* if there are no filters, try to mmap the file */ diff --git a/src/filter.c b/src/filter.c index 79ccac0cf..f20611471 100644 --- a/src/filter.c +++ b/src/filter.c @@ -103,7 +103,23 @@ static int filter_registry_initialize(void) git__on_shutdown(filter_registry_shutdown); - return git_filter_register(GIT_FILTER_CRLF, git_crlf_filter_new(), 0); + /* try to register both default filters */ + { + git_filter *crlf = git_crlf_filter_new(); + git_filter *ident = git_ident_filter_new(); + + if (crlf && git_filter_register( + GIT_FILTER_CRLF, crlf, GIT_FILTER_CRLF_PRIORITY) < 0) + crlf = NULL; + if (ident && git_filter_register( + GIT_FILTER_IDENT, ident, GIT_FILTER_IDENT_PRIORITY) < 0) + ident = NULL; + + if (!crlf || !ident) + return -1; + } + + return 0; cleanup: git_vector_free(®->filters); @@ -132,7 +148,7 @@ static int filter_def_scan_attrs( if (scan > start) { (*nattr)++; - if (has_eq || *scan == '-' || *scan == '+' || *scan == '!') + if (has_eq || *start == '-' || *start == '+' || *start == '!') (*nmatch)++; if (has_eq) @@ -312,6 +328,11 @@ git_filter *git_filter_lookup(const char *name) return fdef->filter; } +void git_filter_free(git_filter *filter) +{ + git__free(filter); +} + git_repository *git_filter_source_repo(const git_filter_source *src) { return src->repo; @@ -410,6 +431,7 @@ int git_filter_list_new( int git_filter_list_load( git_filter_list **filters, git_repository *repo, + git_blob *blob, /* can be NULL */ const char *path, git_filter_mode_t mode) { @@ -426,6 +448,8 @@ int git_filter_list_load( src.repo = repo; src.path = path; src.mode = mode; + if (blob) + git_oid_cpy(&src.oid, git_blob_id(blob)); git_vector_foreach(&git__filter_registry->filters, idx, fdef) { const char **values = NULL; @@ -630,5 +654,8 @@ int git_filter_list_apply_to_blob( (char *)git_blob_rawcontent(blob), git_blob_rawsize(blob), 0 }; + if (filters) + git_oid_cpy(&filters->source.oid, git_blob_id(blob)); + return git_filter_list_apply_to_data(out, filters, &in); } diff --git a/src/filter.h b/src/filter.h index 1bde1e306..d0ace0f9a 100644 --- a/src/filter.h +++ b/src/filter.h @@ -19,10 +19,13 @@ typedef enum { GIT_CRLF_AUTO, } git_crlf_t; +extern void git_filter_free(git_filter *filter); + /* * Available filters */ extern git_filter *git_crlf_filter_new(void); +extern git_filter *git_ident_filter_new(void); #endif diff --git a/src/ident.c b/src/ident.c new file mode 100644 index 000000000..aedb973f9 --- /dev/null +++ b/src/ident.c @@ -0,0 +1,128 @@ +/* + * 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/sys/filter.h" +#include "filter.h" +#include "buffer.h" + +int ident_find_id( + const char **id_start, const char **id_end, const char *start, size_t len) +{ + const char *found; + + while (len > 0 && (found = memchr(start, '$', len)) != NULL) { + size_t remaining = len - (size_t)(found - start); + if (remaining < 3) + return GIT_ENOTFOUND; + if (found[1] == 'I' && found[2] == 'd') + break; + start = found + 1; + len = remaining - 1; + } + + if (len < 3) + return GIT_ENOTFOUND; + *id_start = found; + + if ((found = memchr(found + 3, '$', len - 3)) == NULL) + return GIT_ENOTFOUND; + + *id_end = found + 1; + return 0; +} + +static int ident_insert_id( + git_buffer *to, const git_buffer *from, const git_filter_source *src) +{ + char oid[GIT_OID_HEXSZ+1]; + const char *id_start, *id_end, *from_end = from->ptr + from->size; + size_t need_size; + git_buf to_buf = GIT_BUF_FROM_BUFFER(to); + + /* replace $Id$ with blob id */ + + if (!git_filter_source_id(src)) + return GIT_ENOTFOUND; + + git_oid_tostr(oid, sizeof(oid), git_filter_source_id(src)); + + if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0) + return GIT_ENOTFOUND; + + need_size = (size_t)(id_start - from->ptr) + + 5 /* "$Id: " */ + GIT_OID_HEXSZ + 1 /* "$" */ + + (size_t)(from_end - id_end); + + if (git_buf_grow(&to_buf, need_size) < 0) + return -1; + + git_buf_set(&to_buf, from->ptr, (size_t)(id_start - from->ptr)); + git_buf_put(&to_buf, "$Id: ", 5); + git_buf_put(&to_buf, oid, GIT_OID_HEXSZ); + git_buf_putc(&to_buf, '$'); + git_buf_put(&to_buf, id_end, (size_t)(from_end - id_end)); + + if (git_buf_oom(&to_buf)) + return -1; + + git_buffer_from_buf(to, &to_buf); + return 0; +} + +static int ident_remove_id( + git_buffer *to, const git_buffer *from) +{ + const char *id_start, *id_end, *from_end = from->ptr + from->size; + size_t need_size; + git_buf to_buf = GIT_BUF_FROM_BUFFER(to); + + if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0) + return GIT_ENOTFOUND; + + need_size = (size_t)(id_start - from->ptr) + + 4 /* "$Id$" */ + (size_t)(from_end - id_end); + + if (git_buf_grow(&to_buf, need_size) < 0) + return -1; + + git_buf_set(&to_buf, from->ptr, (size_t)(id_start - from->ptr)); + git_buf_put(&to_buf, "$Id$", 4); + git_buf_put(&to_buf, id_end, (size_t)(from_end - id_end)); + + if (git_buf_oom(&to_buf)) + return -1; + + git_buffer_from_buf(to, &to_buf); + return 0; +} + +static int ident_apply( + git_filter *self, + void **payload, + git_buffer *to, + const git_buffer *from, + const git_filter_source *src) +{ + GIT_UNUSED(self); GIT_UNUSED(payload); + + if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE) + return ident_insert_id(to, from, src); + else + return ident_remove_id(to, from); +} + +git_filter *git_ident_filter_new(void) +{ + git_filter *f = git__calloc(1, sizeof(git_filter)); + + f->version = GIT_FILTER_VERSION; + f->attributes = "+ident"; /* apply to files with ident attribute set */ + f->shutdown = git_filter_free; + f->apply = ident_apply; + + return f; +} diff --git a/src/repository.c b/src/repository.c index 94700e4e3..76e8228b7 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1671,7 +1671,8 @@ int git_repository_hashfile( /* passing empty string for "as_path" indicated --no-filters */ if (strlen(as_path) > 0) { - error = git_filter_list_load(&fl, repo, as_path, GIT_FILTER_TO_ODB); + error = git_filter_list_load( + &fl, repo, NULL, as_path, GIT_FILTER_TO_ODB); if (error < 0) return error; } else { diff --git a/tests-clar/filter/blob.c b/tests-clar/filter/blob.c index 27e001f99..c265ed67a 100644 --- a/tests-clar/filter/blob.c +++ b/tests-clar/filter/blob.c @@ -7,7 +7,12 @@ void test_filter_blob__initialize(void) { g_repo = cl_git_sandbox_init("crlf"); cl_git_mkfile("crlf/.gitattributes", - "*.txt text\n*.bin binary\n*.crlf text eol=crlf\n*.lf text eol=lf\n"); + "*.txt text\n*.bin binary\n" + "*.crlf text eol=crlf\n" + "*.lf text eol=lf\n" + "*.ident text ident\n" + "*.identcrlf ident text eol=crlf\n" + "*.identlf ident text eol.lf\n"); } void test_filter_blob__cleanup(void) @@ -41,3 +46,36 @@ void test_filter_blob__all_crlf(void) git_buffer_free(&buf); git_blob_free(blob); } + +void test_filter_blob__ident(void) +{ + git_oid id; + git_blob *blob; + git_buffer buf = GIT_BUFFER_INIT; + + cl_git_mkfile("crlf/test.ident", "Some text\n$Id$\nGoes there\n"); + cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "test.ident")); + cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); + cl_assert_equal_s( + "Some text\n$Id$\nGoes there\n", git_blob_rawcontent(blob)); + git_blob_free(blob); + + cl_git_mkfile("crlf/test.ident", "Some text\n$Id: Any old just you want$\nGoes there\n"); + cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "test.ident")); + cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); + cl_assert_equal_s( + "Some text\n$Id$\nGoes there\n", git_blob_rawcontent(blob)); + + cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.bin", 1)); + cl_assert_equal_s( + "Some text\n$Id$\nGoes there\n", buf.ptr); + + cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.identcrlf", 1)); + cl_assert_equal_s( + "Some text\r\n$Id: 3164f585d548ac68027d22b104f2d8100b2b6845$\r\nGoes there\r\n", buf.ptr); + + cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.identlf", 1)); + cl_assert_equal_s( + "Some text\n$Id: 3164f585d548ac68027d22b104f2d8100b2b6845$\nGoes there\n", buf.ptr); + +} diff --git a/tests-clar/filter/ident.c b/tests-clar/filter/ident.c new file mode 100644 index 000000000..55774fbdd --- /dev/null +++ b/tests-clar/filter/ident.c @@ -0,0 +1,131 @@ +#include "clar_libgit2.h" +#include "git2/sys/filter.h" + +static git_repository *g_repo = NULL; + +void test_filter_ident__initialize(void) +{ + g_repo = cl_git_sandbox_init("crlf"); +} + +void test_filter_ident__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void add_blob_and_filter( + const char *data, + git_filter_list *fl, + const char *expected) +{ + git_oid id; + git_blob *blob; + git_buffer out = GIT_BUFFER_INIT; + + cl_git_mkfile("crlf/identtest", data); + cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "identtest")); + cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); + + cl_git_pass(git_filter_list_apply_to_blob(&out, fl, blob)); + + cl_assert_equal_s(expected, out.ptr); + + git_blob_free(blob); + git_buffer_free(&out); +} + +void test_filter_ident__to_worktree(void) +{ + git_filter_list *fl; + git_filter *ident; + + cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_WORKTREE)); + + ident = git_filter_lookup(GIT_FILTER_IDENT); + cl_assert(ident != NULL); + + cl_git_pass(git_filter_list_push(fl, ident, NULL)); + + add_blob_and_filter( + "Hello\n$Id$\nFun stuff\n", fl, + "Hello\n$Id: b69e2387aafcaf73c4de5b9ab59abe27fdadee30$\nFun stuff\n"); + add_blob_and_filter( + "Hello\n$Id: Junky$\nFun stuff\n", fl, + "Hello\n$Id: 45cd107a7102911cb2a7df08404674327fa050b9$\nFun stuff\n"); + add_blob_and_filter( + "$Id$\nAt the start\n", fl, + "$Id: b13415c767abc196fb95bd17070e8c1113e32160$\nAt the start\n"); + add_blob_and_filter( + "At the end\n$Id$", fl, + "At the end\n$Id: 1344925c6bc65b34c5a7b50f86bf688e48e9a272$"); + add_blob_and_filter( + "$Id$", fl, + "$Id: b3f5ebfb5843bc43ceecff6d4f26bb37c615beb1$"); + add_blob_and_filter( + "$Id: Some sort of junk goes here$", fl, + "$Id: ab2dd3853c7c9a4bff55aca2bea077a73c32ac06$"); + + add_blob_and_filter("$Id: ", fl, "$Id: "); + add_blob_and_filter("$Id", fl, "$Id"); + add_blob_and_filter("$I", fl, "$I"); + add_blob_and_filter("Id$", fl, "Id$"); + + git_filter_list_free(fl); +} + +void test_filter_ident__to_odb(void) +{ + git_filter_list *fl; + git_filter *ident; + + cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_ODB)); + + ident = git_filter_lookup(GIT_FILTER_IDENT); + cl_assert(ident != NULL); + + cl_git_pass(git_filter_list_push(fl, ident, NULL)); + + add_blob_and_filter( + "Hello\n$Id$\nFun stuff\n", + fl, "Hello\n$Id$\nFun stuff\n"); + add_blob_and_filter( + "Hello\n$Id: b69e2387aafcaf73c4de5b9ab59abe27fdadee30$\nFun stuff\n", + fl, "Hello\n$Id$\nFun stuff\n"); + add_blob_and_filter( + "Hello\n$Id: Any junk you may have left here$\nFun stuff\n", + fl, "Hello\n$Id$\nFun stuff\n"); + add_blob_and_filter( + "Hello\n$Id:$\nFun stuff\n", + fl, "Hello\n$Id$\nFun stuff\n"); + add_blob_and_filter( + "Hello\n$Id:x$\nFun stuff\n", + fl, "Hello\n$Id$\nFun stuff\n"); + + add_blob_and_filter( + "$Id$\nAt the start\n", fl, "$Id$\nAt the start\n"); + add_blob_and_filter( + "$Id: lots of random text that should be removed from here$\nAt the start\n", fl, "$Id$\nAt the start\n"); + add_blob_and_filter( + "$Id: lots of random text that should not be removed without a terminator\nAt the start\n", fl, "$Id: lots of random text that should not be removed without a terminator\nAt the start\n"); + + add_blob_and_filter( + "At the end\n$Id$", fl, "At the end\n$Id$"); + add_blob_and_filter( + "At the end\n$Id:$", fl, "At the end\n$Id$"); + add_blob_and_filter( + "At the end\n$Id:asdfasdf$", fl, "At the end\n$Id$"); + add_blob_and_filter( + "At the end\n$Id", fl, "At the end\n$Id"); + add_blob_and_filter( + "At the end\n$IddI", fl, "At the end\n$IddI"); + + add_blob_and_filter("$Id$", fl, "$Id$"); + add_blob_and_filter("$Id: any$", fl, "$Id$"); + add_blob_and_filter("$Id: any long stuff goes here you see$", fl, "$Id$"); + add_blob_and_filter("$Id: ", fl, "$Id: "); + add_blob_and_filter("$Id", fl, "$Id"); + add_blob_and_filter("$I", fl, "$I"); + add_blob_and_filter("Id$", fl, "Id$"); + + git_filter_list_free(fl); +} diff --git a/tests-clar/object/blob/filter.c b/tests-clar/object/blob/filter.c index a23f897f9..1e82b69cd 100644 --- a/tests-clar/object/blob/filter.c +++ b/tests-clar/object/blob/filter.c @@ -112,8 +112,8 @@ void test_object_blob_filter__to_odb(void) git_attr_cache_flush(g_repo); cl_git_append2file("empty_standard_repo/.gitattributes", "*.txt text\n"); - cl_git_pass( - git_filter_list_load(&fl, g_repo, "filename.txt", GIT_FILTER_TO_ODB)); + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "filename.txt", GIT_FILTER_TO_ODB)); cl_assert(fl != NULL); for (i = 0; i < NUM_TEST_OBJECTS; i++) { -- cgit v1.2.1 From a9f51e430fef49b3299ec33c11a4e6623e3f58cc Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 11 Sep 2013 22:00:36 -0700 Subject: Merge git_buf and git_buffer This makes the git_buf struct that was used internally into an externally available structure and eliminates the git_buffer. As part of that, some of the special cases that arose with the externally used git_buffer were blended into the git_buf, such as being careful about git_buf objects that may have a NULL ptr and allowing for bufs with a valid ptr and size but zero asize as a way of referring to externally owned data. --- include/git2/blob.h | 10 ++--- include/git2/buffer.h | 96 +++++++++++++++++++++++------------------ include/git2/filter.h | 23 +++++----- include/git2/sys/filter.h | 18 ++++---- src/blob.c | 6 +-- src/buffer.c | 93 ++++++++------------------------------- src/buffer.h | 65 ++++++++-------------------- src/checkout.c | 9 ++-- src/config_file.c | 2 + src/crlf.c | 42 ++++++------------ src/diff_file.c | 6 +-- src/filter.c | 48 ++++++++++----------- src/ident.c | 48 ++++++++------------- src/odb.c | 8 ++-- src/path.c | 2 +- src/util.c | 3 ++ tests-clar/filter/blob.c | 9 ++-- tests-clar/filter/crlf.c | 8 ++-- tests-clar/filter/ident.c | 4 +- tests-clar/object/blob/filter.c | 4 +- 20 files changed, 206 insertions(+), 298 deletions(-) diff --git a/include/git2/blob.h b/include/git2/blob.h index dcb815b2f..dcab4fbe0 100644 --- a/include/git2/blob.h +++ b/include/git2/blob.h @@ -104,17 +104,17 @@ GIT_EXTERN(git_off_t) git_blob_rawsize(const git_blob *blob); * CRLF filtering or other types of changes depending on the file * attributes set for the blob and the content detected in it. * - * The output is written into a `git_buffer` which the caller must free - * when done (via `git_buffer_free`). + * The output is written into a `git_buf` which the caller must free + * when done (via `git_buf_free`). * * If no filters need to be applied, then the `out` buffer will just be * populated with a pointer to the raw content of the blob. In that case, * be careful to *not* free the blob until done with the buffer. To keep - * the data detached from the blob, call `git_buffer_resize` on the buffer + * the data detached from the blob, call `git_buf_grow` on the buffer * with a `want_size` of 0 and the buffer will be reallocated to be * detached from the blob. * - * @param out The git_buffer to be filled in + * @param out The git_buf to be filled in * @param blob Pointer to the blob * @param as_path Path used for file attribute lookups, etc. * @param check_for_binary_data Should this test if blob content contains @@ -122,7 +122,7 @@ GIT_EXTERN(git_off_t) git_blob_rawsize(const git_blob *blob); * @return 0 on success or an error code */ GIT_EXTERN(int) git_blob_filtered_content( - git_buffer *out, + git_buf *out, git_blob *blob, const char *as_path, int check_for_binary_data); diff --git a/include/git2/buffer.h b/include/git2/buffer.h index cb80e48f7..ae8681f13 100644 --- a/include/git2/buffer.h +++ b/include/git2/buffer.h @@ -4,8 +4,8 @@ * 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_buffer_h__ -#define INCLUDE_git_buffer_h__ +#ifndef INCLUDE_git_buf_h__ +#define INCLUDE_git_buf_h__ #include "common.h" @@ -25,59 +25,69 @@ GIT_BEGIN_DECL * caller and have the caller take responsibility for freeing that memory. * This can be awkward if the caller does not have easy access to the same * allocation functions that libgit2 is using. In those cases, libgit2 - * will instead fill in a `git_buffer` and the caller can use - * `git_buffer_free()` to release it when they are done. - * - * * `ptr` refers to the start of the allocated memory. - * * `size` contains the size of the data in `ptr` that is actually used. - * * `available` refers to the known total amount of allocated memory. It - * may be larger than the `size` actually in use. - * - * In a few cases, for uniformity and simplicity, an API may populate a - * `git_buffer` with data that should *not* be freed (i.e. the lifetime of - * the data buffer is actually tied to another libgit2 object). These - * cases will be clearly documented in the APIs that use the `git_buffer`. - * In those cases, the `available` field will be set to zero even though - * the `ptr` and `size` will be valid. + * will fill in a `git_buf` and the caller can use `git_buf_free()` to + * release it when they are done. + * + * A `git_buf` may also be used for the caller to pass in a reference to + * a block of memory they hold. In this case, libgit2 will not resize or + * free the memory, but will read from it as needed. + * + * A `git_buf` is a public structure with three fields: + * + * - `ptr` points to the start of the allocated memory. If it is NULL, + * then the `git_buf` is considered empty and libgit2 will feel free + * to overwrite it with new data. + * + * - `size` holds the size (in bytes) of the data that is actually used. + * + * - `asize` holds the known total amount of allocated memory if the `ptr` + * was allocated by libgit2. It may be larger than `size`. If `ptr` + * was not allocated by libgit2 and should not be resized and/or freed, + * then `asize` will be set to zero. + * + * Some APIs may occasionally do something slightly unusual with a buffer, + * such as setting `ptr` to a value that was passed in by the user. In + * those cases, the behavior will be clearly documented by the API. */ -typedef struct git_buffer { +typedef struct { char *ptr; - size_t size; - size_t available; -} git_buffer; + size_t asize, size; +} git_buf; /** - * Use to initialize buffer structure when git_buffer is on stack - */ -#define GIT_BUFFER_INIT { NULL, 0, 0 } - -/** - * Free the memory referred to by the git_buffer. + * Free the memory referred to by the git_buf. * - * Note that this does not free the `git_buffer` itself, just the memory - * pointed to by `buffer->ptr`. If that memory was not allocated by - * libgit2 itself, be careful with using this function because it could - * cause problems. + * Note that this does not free the `git_buf` itself, just the memory + * pointed to by `buffer->ptr`. This will not free the memory if it looks + * like it was not allocated internally, but it will clear the buffer back + * to the empty state. * - * @param buffer The buffer with allocated memory + * @param buffer The buffer to deallocate */ -GIT_EXTERN(void) git_buffer_free(git_buffer *buffer); +GIT_EXTERN(void) git_buf_free(git_buf *buffer); /** * Resize the buffer allocation to make more space. * - * This will update `buffer->available` with the new size (which will be - * at least `want_size` and may be larger). This may or may not change - * `buffer->ptr` depending on whether there is an existing allocation and - * whether that allocation can be increased in place. + * This will attempt to grow the buffer to accomodate the target size. + * + * If the buffer refers to memory that was not allocated by libgit2 (i.e. + * the `asize` field is zero), then `ptr` will be replaced with a newly + * allocated block of data. Be careful so that memory allocated by the + * caller is not lost. As a special variant, if you pass `target_size` as + * 0 and the memory is not allocated by libgit2, this will allocate a new + * buffer of size `size` and copy the external data into it. + * + * Currently, this will never shrink a buffer, only expand it. * - * Currently, this will never shrink the buffer, only expand it. + * If the allocation fails, this will return an error and the buffer will be + * marked as invalid for future operations, invaliding the contents. * * @param buffer The buffer to be resized; may or may not be allocated yet - * @param want_size The desired available size - * @return 0 on success, negative error code on allocation failure + * @param target_size The desired available size + * @return 0 on success, -1 on allocation failure */ -GIT_EXTERN(int) git_buffer_resize(git_buffer *buffer, size_t want_size); +GIT_EXTERN(int) git_buf_grow(git_buf *buffer, size_t target_size); /** * Set buffer to a copy of some raw data. @@ -85,10 +95,10 @@ GIT_EXTERN(int) git_buffer_resize(git_buffer *buffer, size_t want_size); * @param buffer The buffer to set * @param data The data to copy into the buffer * @param datalen The length of the data to copy into the buffer - * @return 0 on success, negative error code on allocation failure + * @return 0 on success, -1 on allocation failure */ -GIT_EXTERN(int) git_buffer_copy( - git_buffer *buffer, const void *data, size_t datalen); +GIT_EXTERN(int) git_buf_set( + git_buf *buffer, const void *data, size_t datalen); GIT_END_DECL diff --git a/include/git2/filter.h b/include/git2/filter.h index 649ed97cf..f96b6766b 100644 --- a/include/git2/filter.h +++ b/include/git2/filter.h @@ -88,16 +88,17 @@ GIT_EXTERN(int) git_filter_list_load( /** * Apply filter list to a data buffer. * - * See `git2/buffer.h` for background on `git_buffer` objects. + * See `git2/buffer.h` for background on `git_buf` objects. * - * If the `in` buffer refers to data managed by libgit2 - * (i.e. `in->available` is not zero), then it will be overwritten when - * applying the filters. If not, then it will be left untouched. + * If the `in` buffer holds data allocated by libgit2 (i.e. `in->asize` is + * not zero), then it will be overwritten when applying the filters. If + * not, then it will be left untouched. * * If there are no filters to apply (or `filters` is NULL), then the `out` - * buffer will reference the `in` buffer data (with `available` set to - * zero) instead of allocating data. This keeps allocations to a minimum, - * but it means you have to be careful about freeing the `in` data. + * buffer will reference the `in` buffer data (with `asize` set to zero) + * instead of allocating data. This keeps allocations to a minimum, but + * it means you have to be careful about freeing the `in` data since `out` + * may be pointing to it! * * @param out Buffer to store the result of the filtering * @param filters A loaded git_filter_list (or NULL) @@ -105,15 +106,15 @@ GIT_EXTERN(int) git_filter_list_load( * @return 0 on success, an error code otherwise */ GIT_EXTERN(int) git_filter_list_apply_to_data( - git_buffer *out, + git_buf *out, git_filter_list *filters, - git_buffer *in); + git_buf *in); /** * Apply filter list to the contents of a file on disk */ GIT_EXTERN(int) git_filter_list_apply_to_file( - git_buffer *out, + git_buf *out, git_filter_list *filters, git_repository *repo, const char *path); @@ -122,7 +123,7 @@ GIT_EXTERN(int) git_filter_list_apply_to_file( * Apply filter list to the contents of a blob */ GIT_EXTERN(int) git_filter_list_apply_to_blob( - git_buffer *out, + git_buf *out, git_filter_list *filters, git_blob *blob); diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h index c35fe55f6..36e97fe91 100644 --- a/include/git2/sys/filter.h +++ b/include/git2/sys/filter.h @@ -4,8 +4,8 @@ * 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_sys_git_config_backend_h__ -#define INCLUDE_sys_git_config_backend_h__ +#ifndef INCLUDE_sys_git_filter_h__ +#define INCLUDE_sys_git_filter_h__ #include "git2/filter.h" @@ -117,19 +117,19 @@ typedef void (*git_filter_shutdown_fn)(git_filter *self); * Callback to decide if a given source needs this filter */ typedef int (*git_filter_check_fn)( - git_filter *self, - void **payload, /* points to NULL ptr on entry, may be set */ + git_filter *self, + void **payload, /* points to NULL ptr on entry, may be set */ const git_filter_source *src, - const char **attr_values); + const char **attr_values); /** * Callback to actually perform the data filtering */ typedef int (*git_filter_apply_fn)( - git_filter *self, - void **payload, /* may be read and/or set */ - git_buffer *to, - const git_buffer *from, + git_filter *self, + void **payload, /* may be read and/or set */ + git_buf *to, + const git_buf *from, const git_filter_source *src); /** diff --git a/src/blob.c b/src/blob.c index 97fd6f70d..e18db4dfc 100644 --- a/src/blob.c +++ b/src/blob.c @@ -111,7 +111,7 @@ static int write_file_filtered( git_filter_list *fl) { int error; - git_buffer tgt = GIT_BUFFER_INIT; + git_buf tgt = GIT_BUF_INIT; error = git_filter_list_apply_to_file(&tgt, fl, NULL, full_path); @@ -122,7 +122,7 @@ static int write_file_filtered( error = git_odb_write(oid, odb, tgt.ptr, tgt.size, GIT_OBJ_BLOB); } - git_buffer_free(&tgt); + git_buf_free(&tgt); return error; } @@ -329,7 +329,7 @@ int git_blob_is_binary(git_blob *blob) } int git_blob_filtered_content( - git_buffer *out, + git_buf *out, git_blob *blob, const char *path, int check_for_binary_data) diff --git a/src/buffer.c b/src/buffer.c index 07725b9cc..f8d47d928 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -32,7 +32,8 @@ void git_buf_init(git_buf *buf, size_t initial_size) git_buf_grow(buf, initial_size); } -int git_buf_try_grow(git_buf *buf, size_t target_size, bool mark_oom) +int git_buf_try_grow( + git_buf *buf, size_t target_size, bool mark_oom, bool preserve_external) { char *new_ptr; size_t new_size; @@ -40,6 +41,9 @@ int git_buf_try_grow(git_buf *buf, size_t target_size, bool mark_oom) if (buf->ptr == git_buf__oom) return -1; + if (!target_size) + target_size = buf->size; + if (target_size <= buf->asize) return 0; @@ -67,6 +71,9 @@ int git_buf_try_grow(git_buf *buf, size_t target_size, bool mark_oom) return -1; } + if (preserve_external && !buf->asize && buf->ptr != NULL && buf->size > 0) + memcpy(new_ptr, buf->ptr, min(buf->size, new_size)); + buf->asize = new_size; buf->ptr = new_ptr; @@ -78,11 +85,16 @@ int git_buf_try_grow(git_buf *buf, size_t target_size, bool mark_oom) return 0; } +int git_buf_grow(git_buf *buffer, size_t target_size) +{ + return git_buf_try_grow(buffer, target_size, true, true); +} + void git_buf_free(git_buf *buf) { if (!buf) return; - if (buf->ptr != git_buf__initbuf && buf->ptr != git_buf__oom) + if (buf->asize > 0 && buf->ptr != NULL && buf->ptr != git_buf__oom) git__free(buf->ptr); git_buf_init(buf, 0); @@ -91,11 +103,15 @@ void git_buf_free(git_buf *buf) void git_buf_clear(git_buf *buf) { buf->size = 0; + + if (!buf->ptr) + buf->ptr = git_buf__initbuf; + if (buf->asize > 0) buf->ptr[0] = '\0'; } -int git_buf_set(git_buf *buf, const char *data, size_t len) +int git_buf_set(git_buf *buf, const void *data, size_t len) { if (len == 0 || data == NULL) { git_buf_clear(buf); @@ -485,74 +501,3 @@ int git_buf_splice( buf->ptr[buf->size] = '\0'; return 0; } - -/* - * Public buffers API - */ - -void git_buffer_free(git_buffer *buffer) -{ - if (!buffer) - return; - - if (buffer->ptr != NULL && buffer->available > 0) - git__free(buffer->ptr); - - git__memzero(buffer, sizeof(*buffer)); -} - -static int git_buffer__resize( - git_buffer *buffer, size_t want_size, int preserve_data) -{ - int non_allocated_buffer = 0; - char *new_ptr; - - assert(buffer); - - /* check if buffer->ptr points to memory owned elsewhere */ - non_allocated_buffer = (buffer->ptr != NULL && buffer->available == 0); - - if (non_allocated_buffer && !want_size) - want_size = buffer->size; - - if (buffer->available >= want_size) - return 0; - - if (non_allocated_buffer) { - new_ptr = NULL; - if (want_size < buffer->size) - want_size = buffer->size; - } else { - new_ptr = buffer->ptr; - } - - want_size = (want_size + 7) & ~7; /* round up to multiple of 8 */ - - new_ptr = git__realloc(new_ptr, want_size); - GITERR_CHECK_ALLOC(new_ptr); - - if (non_allocated_buffer && preserve_data) - memcpy(new_ptr, buffer->ptr, buffer->size); - - buffer->ptr = new_ptr; - buffer->available = want_size; - - return 0; -} - -int git_buffer_resize(git_buffer *buffer, size_t want_size) -{ - return git_buffer__resize(buffer, want_size, true); -} - -int git_buffer_copy( - git_buffer *buffer, const void *data, size_t datalen) -{ - if (git_buffer__resize(buffer, datalen + 1, false) < 0) - return -1; - memcpy(buffer->ptr, data, datalen); - buffer->ptr[datalen] = '\0'; - buffer->size = datalen; - return 0; -} - diff --git a/src/buffer.h b/src/buffer.h index e07f29131..4ca9d4d94 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -12,16 +12,23 @@ #include "git2/buffer.h" #include -typedef struct { - char *ptr; - size_t asize, size; -} git_buf; +/* typedef struct { + * char *ptr; + * size_t asize, size; + * } git_buf; + */ extern char git_buf__initbuf[]; extern char git_buf__oom[]; +/* Use to initialize buffer structure when git_buf is on stack */ #define GIT_BUF_INIT { git_buf__initbuf, 0, 0 } +GIT_INLINE(bool) git_buf_is_allocated(const git_buf *buf) +{ + return (buf->ptr != NULL && buf->asize > 0); +} + /** * Initialize a git_buf structure. * @@ -33,27 +40,16 @@ extern void git_buf_init(git_buf *buf, size_t initial_size); /** * Attempt to grow the buffer to hold at least `target_size` bytes. * - * If the allocation fails, this will return an error. If mark_oom is true, + * If the allocation fails, this will return an error. If `mark_oom` is true, * this will mark the buffer as invalid for future operations; if false, * existing buffer content will be preserved, but calling code must handle - * that buffer was not expanded. - */ -extern int git_buf_try_grow(git_buf *buf, size_t target_size, bool mark_oom); - -/** - * Grow the buffer to hold at least `target_size` bytes. - * - * If the allocation fails, this will return an error and the buffer will be - * marked as invalid for future operations, invaliding contents. - * - * @return 0 on success or -1 on failure + * that buffer was not expanded. If `preserve_external` is true, then any + * existing data pointed to be `ptr` even if `asize` is zero will be copied + * into the newly allocated buffer. */ -GIT_INLINE(int) git_buf_grow(git_buf *buf, size_t target_size) -{ - return git_buf_try_grow(buf, target_size, true); -} +extern int git_buf_try_grow( + git_buf *buf, size_t target_size, bool mark_oom, bool preserve_external); -extern void git_buf_free(git_buf *buf); extern void git_buf_swap(git_buf *buf_a, git_buf *buf_b); extern char *git_buf_detach(git_buf *buf); extern void git_buf_attach(git_buf *buf, char *ptr, size_t asize); @@ -82,7 +78,6 @@ GIT_INLINE(bool) git_buf_oom(const git_buf *buf) * return code of these functions and call them in a series then just call * git_buf_oom at the end. */ -int git_buf_set(git_buf *buf, const char *data, size_t len); int git_buf_sets(git_buf *buf, const char *string); int git_buf_putc(git_buf *buf, char c); int git_buf_put(git_buf *buf, const char *data, size_t len); @@ -175,30 +170,4 @@ int git_buf_splice( const char *data, size_t nb_to_insert); - -GIT_INLINE(bool) git_buffer_is_allocated(const git_buffer *buffer) -{ - return (buffer->ptr != NULL && buffer->available > 0); -} - -#define GIT_BUF_FROM_BUFFER(buffer) \ - { (buffer)->ptr, (buffer)->available, (buffer)->size } - -GIT_INLINE(void) git_buf_from_buffer(git_buf *buf, const git_buffer *buffer) -{ - buf->ptr = buffer->ptr; - buf->size = buffer->size; - buf->asize = buffer->available; -} - -#define GIT_BUFFER_FROM_BUF(buf) \ - { (buf)->ptr, (buf)->size, (buf)->asize } - -GIT_INLINE(void) git_buffer_from_buf(git_buffer *buffer, const git_buf *buf) -{ - buffer->ptr = buf->ptr; - buffer->size = buf->size; - buffer->available = buf->asize; -} - #endif diff --git a/src/checkout.c b/src/checkout.c index 7e79c9b5e..140544c77 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -678,20 +678,19 @@ fail: static int buffer_to_file( struct stat *st, - git_buffer *buffer, + git_buf *buf, const char *path, mode_t dir_mode, int file_open_flags, mode_t file_mode) { int error; - git_buf buf = GIT_BUF_FROM_BUFFER(buffer); if ((error = git_futils_mkpath2file(path, dir_mode)) < 0) return error; if ((error = git_futils_writebuffer( - &buf, path, file_open_flags, file_mode)) < 0) + buf, path, file_open_flags, file_mode)) < 0) return error; if (st != NULL && (error = p_stat(path, st)) < 0) @@ -713,7 +712,7 @@ static int blob_content_to_file( { int error = 0; mode_t file_mode = opts->file_mode ? opts->file_mode : entry_filemode; - git_buffer out = GIT_BUFFER_INIT; + git_buf out = GIT_BUF_INIT; git_filter_list *fl = NULL; if (!opts->disable_filters && !git_blob_is_binary(blob)) @@ -731,7 +730,7 @@ static int blob_content_to_file( st->st_mode = entry_filemode; - git_buffer_free(&out); + git_buf_free(&out); } return error; diff --git a/src/config_file.c b/src/config_file.c index bd4fa7471..d0910a26c 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -293,6 +293,8 @@ static int config_iterator_new( diskfile_backend *b = (diskfile_backend *)backend; git_config_file_iter *it = git__calloc(1, sizeof(git_config_file_iter)); + GIT_UNUSED(b); + GITERR_CHECK_ALLOC(it); it->parent.backend = backend; diff --git a/src/crlf.c b/src/crlf.c index f61a870da..bde85ca06 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -119,15 +119,12 @@ static int has_cr_in_index(const git_filter_source *src) static int crlf_apply_to_odb( struct crlf_attrs *ca, - git_buffer *to, - const git_buffer *from, + git_buf *to, + const git_buf *from, const git_filter_source *src) { - const git_buf from_buf = GIT_BUF_FROM_BUFFER(from); - git_buf to_buf = GIT_BUF_FROM_BUFFER(to); - /* Empty file? Nothing to do */ - if (!git_buf_len(&from_buf)) + if (!git_buf_len(from)) return 0; /* Heuristics to see if we can skip the conversion. @@ -137,7 +134,7 @@ static int crlf_apply_to_odb( git_buf_text_stats stats; /* Check heuristics for binary vs text... */ - if (git_buf_text_gather_stats(&stats, &from_buf, false)) + if (git_buf_text_gather_stats(&stats, from, false)) return -1; /* @@ -162,13 +159,7 @@ static int crlf_apply_to_odb( } /* Actually drop the carriage returns */ - if (git_buf_text_crlf_to_lf(&to_buf, &from_buf) < 0) - return -1; - - /* Overwrite "to" buffer in case data was resized */ - git_buffer_from_buf(to, &to_buf); - - return 0; + return git_buf_text_crlf_to_lf(to, from); } static const char *line_ending(struct crlf_attrs *ca) @@ -210,14 +201,12 @@ line_ending_error: } static int crlf_apply_to_workdir( - struct crlf_attrs *ca, git_buffer *to, const git_buffer *from) + struct crlf_attrs *ca, git_buf *to, const git_buf *from) { - const git_buf from_buf = GIT_BUF_FROM_BUFFER(from); - git_buf to_buf = GIT_BUF_FROM_BUFFER(to); const char *workdir_ending = NULL; /* Empty file? Nothing to do. */ - if (git_buf_len(&from_buf) == 0) + if (git_buf_len(from) == 0) return 0; /* Determine proper line ending */ @@ -229,22 +218,19 @@ static int crlf_apply_to_workdir( if (ca->crlf_action == GIT_CRLF_GUESS && ca->auto_crlf) return GIT_ENOTFOUND; - if (git_buf_find(&from_buf, '\r') < 0) + if (git_buf_find(from, '\r') < 0) return GIT_ENOTFOUND; - if (git_buf_text_crlf_to_lf(&to_buf, &from_buf) < 0) + if (git_buf_text_crlf_to_lf(to, from) < 0) return -1; } else { /* only other supported option is lf->crlf conversion */ assert(!strcmp("\r\n", workdir_ending)); - if (git_buf_text_lf_to_crlf(&to_buf, &from_buf) < 0) + if (git_buf_text_lf_to_crlf(to, from) < 0) return -1; } - /* Overwrite "to" buffer in case data was resized */ - git_buffer_from_buf(to, &to_buf); - return 0; } @@ -297,10 +283,10 @@ static int crlf_check( } static int crlf_apply( - git_filter *self, - void **payload, /* may be read and/or set */ - git_buffer *to, - const git_buffer *from, + git_filter *self, + void **payload, /* may be read and/or set */ + git_buf *to, + const git_buf *from, const git_filter_source *src) { /* initialize payload in case `check` was bypassed */ diff --git a/src/diff_file.c b/src/diff_file.c index d02787c75..5939ee8b8 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -327,11 +327,11 @@ static int diff_file_content_load_workdir_file( } if (!(error = git_futils_readbuffer_fd(&raw, fd, (size_t)fc->file->size))) { - git_buffer in = GIT_BUFFER_FROM_BUF(&raw), out = GIT_BUFFER_INIT; + git_buf out = GIT_BUF_INIT; - error = git_filter_list_apply_to_data(&out, fl, &in); + error = git_filter_list_apply_to_data(&out, fl, &raw); - git_buffer_free(&in); + git_buf_free(&raw); if (!error) { fc->map.len = out.size; diff --git a/src/filter.c b/src/filter.c index f20611471..08467a631 100644 --- a/src/filter.c +++ b/src/filter.c @@ -549,23 +549,28 @@ int git_filter_list_push( } static int filter_list_out_buffer_from_raw( - git_buffer *out, const void *ptr, size_t size) + git_buf *out, const void *ptr, size_t size) { - if (git_buffer_is_allocated(out)) - git_buffer_free(out); + if (git_buf_is_allocated(out)) + git_buf_free(out); + + if (!size) { + git_buf_init(out, 0); + } else { + out->ptr = (char *)ptr; + out->asize = 0; + out->size = size; + } - out->ptr = (char *)ptr; - out->size = size; - out->available = 0; return 0; } int git_filter_list_apply_to_data( - git_buffer *tgt, git_filter_list *fl, git_buffer *src) + git_buf *tgt, git_filter_list *fl, git_buf *src) { int error = 0; uint32_t i; - git_buffer *dbuffer[2], local = GIT_BUFFER_INIT; + git_buf *dbuffer[2], local = GIT_BUF_INIT; unsigned int si = 0; if (!fl) @@ -575,8 +580,8 @@ int git_filter_list_apply_to_data( dbuffer[1] = tgt; /* if `src` buffer is reallocable, then use it, otherwise copy it */ - if (!git_buffer_is_allocated(src)) { - if (git_buffer_copy(&local, src->ptr, src->size) < 0) + if (!git_buf_is_allocated(src)) { + if (git_buf_set(&local, src->ptr, src->size) < 0) return -1; dbuffer[0] = &local; } @@ -610,19 +615,16 @@ int git_filter_list_apply_to_data( } /* Ensure that the output ends up in dbuffer[1] (i.e. the dest) */ - if (si != 1) { - git_buffer sw = *dbuffer[1]; - *dbuffer[1] = *dbuffer[0]; - *dbuffer[0] = sw; - } + if (si != 1) + git_buf_swap(dbuffer[0], dbuffer[1]); - git_buffer_free(&local); /* don't leak if we allocated locally */ + git_buf_free(&local); /* don't leak if we allocated locally */ return 0; } int git_filter_list_apply_to_file( - git_buffer *out, + git_buf *out, git_filter_list *filters, git_repository *repo, const char *path) @@ -634,11 +636,9 @@ int git_filter_list_apply_to_file( if (!(error = git_path_join_unrooted(&abspath, path, base, NULL)) && !(error = git_futils_readbuffer(&raw, abspath.ptr))) { - git_buffer in = GIT_BUFFER_FROM_BUF(&raw); - - error = git_filter_list_apply_to_data(out, filters, &in); + error = git_filter_list_apply_to_data(out, filters, &raw); - git_buffer_free(&in); + git_buf_free(&raw); } git_buf_free(&abspath); @@ -646,12 +646,12 @@ int git_filter_list_apply_to_file( } int git_filter_list_apply_to_blob( - git_buffer *out, + git_buf *out, git_filter_list *filters, git_blob *blob) { - git_buffer in = { - (char *)git_blob_rawcontent(blob), git_blob_rawsize(blob), 0 + git_buf in = { + (char *)git_blob_rawcontent(blob), 0, git_blob_rawsize(blob) }; if (filters) diff --git a/src/ident.c b/src/ident.c index aedb973f9..3ea949859 100644 --- a/src/ident.c +++ b/src/ident.c @@ -9,7 +9,7 @@ #include "filter.h" #include "buffer.h" -int ident_find_id( +static int ident_find_id( const char **id_start, const char **id_end, const char *start, size_t len) { const char *found; @@ -36,12 +36,11 @@ int ident_find_id( } static int ident_insert_id( - git_buffer *to, const git_buffer *from, const git_filter_source *src) + git_buf *to, const git_buf *from, const git_filter_source *src) { char oid[GIT_OID_HEXSZ+1]; const char *id_start, *id_end, *from_end = from->ptr + from->size; size_t need_size; - git_buf to_buf = GIT_BUF_FROM_BUFFER(to); /* replace $Id$ with blob id */ @@ -57,28 +56,23 @@ static int ident_insert_id( 5 /* "$Id: " */ + GIT_OID_HEXSZ + 1 /* "$" */ + (size_t)(from_end - id_end); - if (git_buf_grow(&to_buf, need_size) < 0) + if (git_buf_grow(to, need_size) < 0) return -1; - git_buf_set(&to_buf, from->ptr, (size_t)(id_start - from->ptr)); - git_buf_put(&to_buf, "$Id: ", 5); - git_buf_put(&to_buf, oid, GIT_OID_HEXSZ); - git_buf_putc(&to_buf, '$'); - git_buf_put(&to_buf, id_end, (size_t)(from_end - id_end)); + git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr)); + git_buf_put(to, "$Id: ", 5); + git_buf_put(to, oid, GIT_OID_HEXSZ); + git_buf_putc(to, '$'); + git_buf_put(to, id_end, (size_t)(from_end - id_end)); - if (git_buf_oom(&to_buf)) - return -1; - - git_buffer_from_buf(to, &to_buf); - return 0; + return git_buf_oom(to) ? -1 : 0; } static int ident_remove_id( - git_buffer *to, const git_buffer *from) + git_buf *to, const git_buf *from) { const char *id_start, *id_end, *from_end = from->ptr + from->size; size_t need_size; - git_buf to_buf = GIT_BUF_FROM_BUFFER(to); if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0) return GIT_ENOTFOUND; @@ -86,25 +80,21 @@ static int ident_remove_id( need_size = (size_t)(id_start - from->ptr) + 4 /* "$Id$" */ + (size_t)(from_end - id_end); - if (git_buf_grow(&to_buf, need_size) < 0) + if (git_buf_grow(to, need_size) < 0) return -1; - git_buf_set(&to_buf, from->ptr, (size_t)(id_start - from->ptr)); - git_buf_put(&to_buf, "$Id$", 4); - git_buf_put(&to_buf, id_end, (size_t)(from_end - id_end)); + git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr)); + git_buf_put(to, "$Id$", 4); + git_buf_put(to, id_end, (size_t)(from_end - id_end)); - if (git_buf_oom(&to_buf)) - return -1; - - git_buffer_from_buf(to, &to_buf); - return 0; + return git_buf_oom(to) ? -1 : 0; } static int ident_apply( - git_filter *self, - void **payload, - git_buffer *to, - const git_buffer *from, + git_filter *self, + void **payload, + git_buf *to, + const git_buf *from, const git_filter_source *src) { GIT_UNUSED(self); GIT_UNUSED(payload); diff --git a/src/odb.c b/src/odb.c index b71b038bf..eef9748ca 100644 --- a/src/odb.c +++ b/src/odb.c @@ -192,16 +192,16 @@ int git_odb__hashfd_filtered( */ if (!(error = git_futils_readbuffer_fd(&raw, fd, size))) { - git_buffer pre = GIT_BUFFER_FROM_BUF(&raw), post = GIT_BUFFER_INIT; + git_buf post = GIT_BUF_INIT; - error = git_filter_list_apply_to_data(&post, fl, &pre); + error = git_filter_list_apply_to_data(&post, fl, &raw); - git_buffer_free(&pre); + git_buf_free(&raw); if (!error) error = git_odb_hash(out, post.ptr, post.size, type); - git_buffer_free(&post); + git_buf_free(&post); } return error; diff --git a/src/path.c b/src/path.c index 56b0b49ca..42b3d6f3e 100644 --- a/src/path.c +++ b/src/path.c @@ -565,7 +565,7 @@ static bool _check_dir_contents( size_t sub_size = strlen(sub); /* leave base valid even if we could not make space for subdir */ - if (git_buf_try_grow(dir, dir_size + sub_size + 2, false) < 0) + if (git_buf_try_grow(dir, dir_size + sub_size + 2, false, false) < 0) return false; /* save excursion */ diff --git a/src/util.c b/src/util.c index d0c326ae5..151782346 100644 --- a/src/util.c +++ b/src/util.c @@ -679,6 +679,9 @@ size_t git__unescape(char *str) { char *scan, *pos = str; + if (!str) + return 0; + for (scan = str; *scan; pos++, scan++) { if (*scan == '\\' && *(scan + 1) != '\0') scan++; /* skip '\' but include next char */ diff --git a/tests-clar/filter/blob.c b/tests-clar/filter/blob.c index c265ed67a..916721e12 100644 --- a/tests-clar/filter/blob.c +++ b/tests-clar/filter/blob.c @@ -23,7 +23,7 @@ void test_filter_blob__cleanup(void) void test_filter_blob__all_crlf(void) { git_blob *blob; - git_buffer buf = GIT_BUFFER_INIT; + git_buf buf = { 0 }; cl_git_pass(git_revparse_single( (git_object **)&blob, g_repo, "a9a2e891")); /* all-crlf */ @@ -43,7 +43,7 @@ void test_filter_blob__all_crlf(void) cl_assert_equal_s(ALL_CRLF_TEXT_AS_LF, buf.ptr); - git_buffer_free(&buf); + git_buf_free(&buf); git_blob_free(blob); } @@ -51,7 +51,7 @@ void test_filter_blob__ident(void) { git_oid id; git_blob *blob; - git_buffer buf = GIT_BUFFER_INIT; + git_buf buf = { 0 }; cl_git_mkfile("crlf/test.ident", "Some text\n$Id$\nGoes there\n"); cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "test.ident")); @@ -78,4 +78,7 @@ void test_filter_blob__ident(void) cl_assert_equal_s( "Some text\n$Id: 3164f585d548ac68027d22b104f2d8100b2b6845$\nGoes there\n", buf.ptr); + git_buf_free(&buf); + git_blob_free(blob); + } diff --git a/tests-clar/filter/crlf.c b/tests-clar/filter/crlf.c index 098a85d4c..ccd7ef450 100644 --- a/tests-clar/filter/crlf.c +++ b/tests-clar/filter/crlf.c @@ -20,7 +20,7 @@ void test_filter_crlf__to_worktree(void) { git_filter_list *fl; git_filter *crlf; - git_buffer in = GIT_BUFFER_INIT, out = GIT_BUFFER_INIT; + git_buf in = { 0 }, out = { 0 }; { git_config *cfg; @@ -48,14 +48,14 @@ void test_filter_crlf__to_worktree(void) #endif git_filter_list_free(fl); - git_buffer_free(&out); + git_buf_free(&out); } void test_filter_crlf__to_odb(void) { git_filter_list *fl; git_filter *crlf; - git_buffer in = GIT_BUFFER_INIT, out = GIT_BUFFER_INIT; + git_buf in = { 0 }, out = { 0 }; { git_config *cfg; @@ -79,5 +79,5 @@ void test_filter_crlf__to_odb(void) cl_assert_equal_s("Some text\nRight here\n", out.ptr); git_filter_list_free(fl); - git_buffer_free(&out); + git_buf_free(&out); } diff --git a/tests-clar/filter/ident.c b/tests-clar/filter/ident.c index 55774fbdd..2c8e6abea 100644 --- a/tests-clar/filter/ident.c +++ b/tests-clar/filter/ident.c @@ -20,7 +20,7 @@ static void add_blob_and_filter( { git_oid id; git_blob *blob; - git_buffer out = GIT_BUFFER_INIT; + git_buf out = { 0 }; cl_git_mkfile("crlf/identtest", data); cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "identtest")); @@ -31,7 +31,7 @@ static void add_blob_and_filter( cl_assert_equal_s(expected, out.ptr); git_blob_free(blob); - git_buffer_free(&out); + git_buf_free(&out); } void test_filter_ident__to_worktree(void) diff --git a/tests-clar/object/blob/filter.c b/tests-clar/object/blob/filter.c index 1e82b69cd..6dc7800db 100644 --- a/tests-clar/object/blob/filter.c +++ b/tests-clar/object/blob/filter.c @@ -104,7 +104,7 @@ void test_object_blob_filter__to_odb(void) git_config *cfg; int i; git_blob *blob; - git_buffer out = GIT_BUFFER_INIT; + git_buf out = GIT_BUF_INIT; cl_git_pass(git_repository_config(&cfg, g_repo)); cl_assert(cfg); @@ -129,7 +129,7 @@ void test_object_blob_filter__to_odb(void) } git_filter_list_free(fl); - git_buffer_free(&out); + git_buf_free(&out); git_config_free(cfg); } -- cgit v1.2.1 From 0e32635fcf9a874fe66f871e88c0bbc0511544f1 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 12 Sep 2013 14:47:15 -0700 Subject: Move binary check to CRLF filter itself Checkout should not reject binary files from filters, as a filter may actually wish to operate on binary files. The CRLF filter should reject binary files itself if it wishes to. Moreover, the CRLF filter requires this logic so that users can emulate the checkout data in their odb -> workdir filtering. Conflicts: src/checkout.c src/crlf.c --- src/checkout.c | 2 +- src/crlf.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/checkout.c b/src/checkout.c index 140544c77..0e9d11bff 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -715,7 +715,7 @@ static int blob_content_to_file( git_buf out = GIT_BUF_INIT; git_filter_list *fl = NULL; - if (!opts->disable_filters && !git_blob_is_binary(blob)) + if (!opts->disable_filters) error = git_filter_list_load( &fl, git_blob_owner(blob), blob, path, GIT_FILTER_TO_WORKTREE); diff --git a/src/crlf.c b/src/crlf.c index bde85ca06..6b1fe46a3 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -209,6 +209,10 @@ static int crlf_apply_to_workdir( if (git_buf_len(from) == 0) return 0; + /* Don't filter binary files */ + if (git_buf_text_is_binary(from)) + return GIT_ENOTFOUND; + /* Determine proper line ending */ workdir_ending = line_ending(ca); if (!workdir_ending) -- cgit v1.2.1 From b47349b8dc742943e063cb3d755b9db66203e3d9 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 12 Sep 2013 14:48:24 -0700 Subject: Port tests from PR 1683 This ports over some of the tests from https://github.com/libgit2/libgit2/pull/1683 by @yorah and @ethomson --- include/git2/buffer.h | 5 + include/git2/sys/filter.h | 13 +++ src/filter.c | 5 + tests-clar/filter/crlf.c | 20 +--- tests-clar/filter/crlf.h | 1 - tests-clar/filter/custom.c | 247 ++++++++++++++++++++++++++++++++++++++++ tests-clar/object/blob/filter.c | 90 ++++++++------- 7 files changed, 325 insertions(+), 56 deletions(-) create mode 100644 tests-clar/filter/custom.c diff --git a/include/git2/buffer.h b/include/git2/buffer.h index ae8681f13..36a61e6c9 100644 --- a/include/git2/buffer.h +++ b/include/git2/buffer.h @@ -54,6 +54,11 @@ typedef struct { size_t asize, size; } git_buf; +/** + * Static initializer for git_buf from static buffer + */ +#define GIT_BUF_INIT_CONST(STR,LEN) { (char *)(STR), 0, (size_t)(LEN) } + /** * Free the memory referred to by the git_buf. * diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h index 36e97fe91..9a6720a3e 100644 --- a/include/git2/sys/filter.h +++ b/include/git2/sys/filter.h @@ -59,6 +59,19 @@ GIT_EXTERN(int) git_filter_list_new( GIT_EXTERN(int) git_filter_list_push( git_filter_list *fl, git_filter *filter, void *payload); +/** + * Look up how many filters are in the list + * + * We will attempt to apply all of these filters to any data passed in, + * but note that the filter apply action still has the option of skipping + * data that is passed in (for example, the CRLF filter will skip data + * that appears to be binary). + * + * @param fl A filter list + * @return The number of filters in the list + */ +GIT_EXTERN(size_t) git_filter_list_length(const git_filter_list *fl); + /** * A filter source represents a file/blob to be processed */ diff --git a/src/filter.c b/src/filter.c index 08467a631..0375b8b0e 100644 --- a/src/filter.c +++ b/src/filter.c @@ -548,6 +548,11 @@ int git_filter_list_push( return 0; } +size_t git_filter_list_length(const git_filter_list *fl) +{ + return fl ? git_array_size(fl->filters) : 0; +} + static int filter_list_out_buffer_from_raw( git_buf *out, const void *ptr, size_t size) { diff --git a/tests-clar/filter/crlf.c b/tests-clar/filter/crlf.c index ccd7ef450..ece2e6e5e 100644 --- a/tests-clar/filter/crlf.c +++ b/tests-clar/filter/crlf.c @@ -5,10 +5,16 @@ static git_repository *g_repo = NULL; void test_filter_crlf__initialize(void) { + git_config *cfg; + g_repo = cl_git_sandbox_init("crlf"); cl_git_mkfile("crlf/.gitattributes", "*.txt text\n*.bin binary\n*.crlf text eol=crlf\n*.lf text eol=lf\n"); + + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_string(cfg, "core.autocrlf", "true")); + git_config_free(cfg); } void test_filter_crlf__cleanup(void) @@ -22,13 +28,6 @@ void test_filter_crlf__to_worktree(void) git_filter *crlf; git_buf in = { 0 }, out = { 0 }; - { - git_config *cfg; - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_set_string(cfg, "core.autocrlf", "true")); - git_config_free(cfg); - } - cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_WORKTREE)); crlf = git_filter_lookup(GIT_FILTER_CRLF); @@ -57,13 +56,6 @@ void test_filter_crlf__to_odb(void) git_filter *crlf; git_buf in = { 0 }, out = { 0 }; - { - git_config *cfg; - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_set_string(cfg, "core.autocrlf", "true")); - git_config_free(cfg); - } - cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_ODB)); crlf = git_filter_lookup(GIT_FILTER_CRLF); diff --git a/tests-clar/filter/crlf.h b/tests-clar/filter/crlf.h index 8fadee950..9cb98ad4c 100644 --- a/tests-clar/filter/crlf.h +++ b/tests-clar/filter/crlf.h @@ -22,5 +22,4 @@ #define MORE_CRLF_TEXT_AS_LF "crlf\ncrlf\nlf\ncrlf\ncrlf\n" #define MORE_LF_TEXT_AS_LF "lf\nlf\ncrlf\nlf\nlf\n" - #endif diff --git a/tests-clar/filter/custom.c b/tests-clar/filter/custom.c new file mode 100644 index 000000000..4a2ff9fc4 --- /dev/null +++ b/tests-clar/filter/custom.c @@ -0,0 +1,247 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "blob.h" +#include "filter.h" +#include "buf_text.h" +#include "git2/sys/filter.h" +#include "git2/sys/repository.h" + +#define BITFLIP_FILTER_PRIORITY 20 +#define REVERSE_FILTER_PRIORITY 25 + +#define VERY_SECURE_ENCRYPTION(b) ((b) ^ 0xff) + +#ifdef GIT_WIN32 +# define NEWLINE "\r\n" +#else +# define NEWLINE "\n" +#endif + +static char workdir_data[] = + "some simple" NEWLINE + "data" NEWLINE + "that will be" NEWLINE + "trivially" NEWLINE + "scrambled." NEWLINE; + +/* Represents the data above scrambled (bits flipped) after \r\n -> \n + * conversion, then bytewise reversed + */ +static unsigned char bitflipped_and_reversed_data[] = + { 0xf5, 0xd1, 0x9b, 0x9a, 0x93, 0x9d, 0x92, 0x9e, 0x8d, 0x9c, 0x8c, + 0xf5, 0x86, 0x93, 0x93, 0x9e, 0x96, 0x89, 0x96, 0x8d, 0x8b, 0xf5, + 0x9a, 0x9d, 0xdf, 0x93, 0x93, 0x96, 0x88, 0xdf, 0x8b, 0x9e, 0x97, + 0x8b, 0xf5, 0x9e, 0x8b, 0x9e, 0x9b, 0xf5, 0x9a, 0x93, 0x8f, 0x92, + 0x96, 0x8c, 0xdf, 0x9a, 0x92, 0x90, 0x8c }; + +#define BITFLIPPED_AND_REVERSED_DATA_LEN 51 + +static git_repository *g_repo = NULL; + +static void register_custom_filters(void); + +void test_filter_custom__initialize(void) +{ + register_custom_filters(); + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_mkfile( + "empty_standard_repo/.gitattributes", + "hero* bitflip reverse\n" + "herofile text\n" + "heroflip -reverse\n"); +} + +void test_filter_custom__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +static int bitflip_filter_apply( + git_filter *self, + void **payload, + git_buf *to, + const git_buf *from, + const git_filter_source *source) +{ + const unsigned char *src = (const unsigned char *)from->ptr; + unsigned char *dst; + size_t i; + + GIT_UNUSED(self); GIT_UNUSED(payload); + + /* verify that attribute path match worked as expected */ + cl_assert_equal_i( + 0, git__strncmp("hero", git_filter_source_path(source), 4)); + + if (!from->size) + return 0; + + cl_git_pass(git_buf_grow(to, from->size)); + + dst = (unsigned char *)to->ptr; + + for (i = 0; i < from->size; i++) + dst[i] = VERY_SECURE_ENCRYPTION(src[i]); + + to->size = from->size; + + return 0; +} + +static void bitflip_filter_free(git_filter *f) +{ + git__free(f); +} + +static git_filter *create_bitflip_filter(void) +{ + git_filter *filter = git__calloc(1, sizeof(git_filter)); + cl_assert(filter); + + filter->version = GIT_FILTER_VERSION; + filter->attributes = "+bitflip"; + filter->shutdown = bitflip_filter_free; + filter->apply = bitflip_filter_apply; + + return filter; +} + + +static int reverse_filter_apply( + git_filter *self, + void **payload, + git_buf *to, + const git_buf *from, + const git_filter_source *source) +{ + const unsigned char *src = (const unsigned char *)from->ptr; + const unsigned char *end = src + from->size; + unsigned char *dst; + + GIT_UNUSED(self); GIT_UNUSED(payload); GIT_UNUSED(source); + + /* verify that attribute path match worked as expected */ + cl_assert_equal_i( + 0, git__strncmp("hero", git_filter_source_path(source), 4)); + + if (!from->size) + return 0; + + cl_git_pass(git_buf_grow(to, from->size)); + + dst = (unsigned char *)to->ptr + from->size - 1; + + while (src < end) + *dst-- = *src++; + + to->size = from->size; + + return 0; +} + +static void reverse_filter_free(git_filter *f) +{ + git__free(f); +} + +static git_filter *create_reverse_filter(void) +{ + git_filter *filter = git__calloc(1, sizeof(git_filter)); + cl_assert(filter); + + filter->version = GIT_FILTER_VERSION; + filter->attributes = "+reverse"; + filter->shutdown = reverse_filter_free; + filter->apply = reverse_filter_apply; + + return filter; +} + +static void register_custom_filters(void) +{ + static int filters_registered = 0; + + if (!filters_registered) { + cl_git_pass(git_filter_register( + "bitflip", create_bitflip_filter(), BITFLIP_FILTER_PRIORITY)); + + cl_git_pass(git_filter_register( + "reverse", create_reverse_filter(), REVERSE_FILTER_PRIORITY)); + + filters_registered = 1; + } +} + + +void test_filter_custom__to_odb(void) +{ + git_filter_list *fl; + git_buf out = { 0 }; + git_buf in = GIT_BUF_INIT_CONST(workdir_data, strlen(workdir_data)); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "herofile", GIT_FILTER_TO_ODB)); + + cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); + + cl_assert_equal_i(BITFLIPPED_AND_REVERSED_DATA_LEN, out.size); + + cl_assert_equal_i( + 0, memcmp(bitflipped_and_reversed_data, out.ptr, out.size)); + + git_filter_list_free(fl); + git_buf_free(&out); +} + +void test_filter_custom__to_workdir(void) +{ + git_filter_list *fl; + git_buf out = { 0 }; + git_buf in = GIT_BUF_INIT_CONST( + bitflipped_and_reversed_data, BITFLIPPED_AND_REVERSED_DATA_LEN); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "herofile", GIT_FILTER_TO_WORKTREE)); + + cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); + + cl_assert_equal_i(strlen(workdir_data), out.size); + + cl_assert_equal_i( + 0, memcmp(workdir_data, out.ptr, out.size)); + + git_filter_list_free(fl); + git_buf_free(&out); +} + +void test_filter_custom__can_register_a_custom_filter_in_the_repository(void) +{ + git_filter_list *fl; + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "herofile", GIT_FILTER_TO_WORKTREE)); + /* expect: bitflip, reverse, crlf */ + cl_assert_equal_sz(3, git_filter_list_length(fl)); + git_filter_list_free(fl); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "herocorp", GIT_FILTER_TO_WORKTREE)); + /* expect: bitflip, reverse */ + cl_assert_equal_sz(2, git_filter_list_length(fl)); + git_filter_list_free(fl); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "heroflip", GIT_FILTER_TO_WORKTREE)); + /* expect: bitflip (because of -reverse) */ + cl_assert_equal_sz(1, git_filter_list_length(fl)); + git_filter_list_free(fl); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "doesntapplytome", GIT_FILTER_TO_WORKTREE)); + /* expect: none */ + cl_assert_equal_sz(0, git_filter_list_length(fl)); + git_filter_list_free(fl); +} diff --git a/tests-clar/object/blob/filter.c b/tests-clar/object/blob/filter.c index 6dc7800db..0b2d6bf9e 100644 --- a/tests-clar/object/blob/filter.c +++ b/tests-clar/object/blob/filter.c @@ -4,9 +4,10 @@ #include "buf_text.h" static git_repository *g_repo = NULL; -#define NUM_TEST_OBJECTS 9 -static git_oid g_oids[NUM_TEST_OBJECTS]; -static const char *g_raw[NUM_TEST_OBJECTS] = { + +#define CRLF_NUM_TEST_OBJECTS 9 + +static const char *g_crlf_raw[CRLF_NUM_TEST_OBJECTS] = { "", "foo\nbar\n", "foo\rbar\r", @@ -17,19 +18,14 @@ static const char *g_raw[NUM_TEST_OBJECTS] = { "\xEF\xBB\xBF\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\r\n\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\r\n", "\xFE\xFF\x00T\x00h\x00i\x00s\x00!" }; -static git_off_t g_len[NUM_TEST_OBJECTS] = { -1, -1, -1, -1, -1, 17, -1, -1, 12 }; -static git_buf_text_stats g_stats[NUM_TEST_OBJECTS] = { - { 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 2, 0, 6, 0 }, - { 0, 0, 2, 0, 0, 6, 0 }, - { 0, 0, 2, 2, 2, 6, 0 }, - { 0, 0, 4, 4, 1, 31, 0 }, - { 0, 1, 1, 2, 1, 9, 5 }, - { GIT_BOM_UTF8, 0, 0, 1, 0, 16, 0 }, - { GIT_BOM_UTF8, 0, 2, 2, 2, 27, 0 }, - { GIT_BOM_UTF16_BE, 5, 0, 0, 0, 7, 5 }, + +static git_off_t g_crlf_raw_len[CRLF_NUM_TEST_OBJECTS] = { + -1, -1, -1, -1, -1, 17, -1, -1, 12 }; -static git_buf g_crlf_filtered[NUM_TEST_OBJECTS] = { + +static git_oid g_crlf_oids[CRLF_NUM_TEST_OBJECTS]; + +static git_buf g_crlf_filtered[CRLF_NUM_TEST_OBJECTS] = { { "", 0, 0 }, { "foo\nbar\n", 0, 8 }, { "foo\rbar\r", 0, 8 }, @@ -41,30 +37,36 @@ static git_buf g_crlf_filtered[NUM_TEST_OBJECTS] = { { "\xFE\xFF\x00T\x00h\x00i\x00s\x00!", 0, 12 } }; +static git_buf_text_stats g_crlf_filtered_stats[CRLF_NUM_TEST_OBJECTS] = { + { 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 2, 0, 6, 0 }, + { 0, 0, 2, 0, 0, 6, 0 }, + { 0, 0, 2, 2, 2, 6, 0 }, + { 0, 0, 4, 4, 1, 31, 0 }, + { 0, 1, 1, 2, 1, 9, 5 }, + { GIT_BOM_UTF8, 0, 0, 1, 0, 16, 0 }, + { GIT_BOM_UTF8, 0, 2, 2, 2, 27, 0 }, + { GIT_BOM_UTF16_BE, 5, 0, 0, 0, 7, 5 }, +}; + void test_object_blob_filter__initialize(void) { int i; - cl_fixture_sandbox("empty_standard_repo"); - cl_git_pass(p_rename( - "empty_standard_repo/.gitted", "empty_standard_repo/.git")); - cl_git_pass(git_repository_open(&g_repo, "empty_standard_repo")); + g_repo = cl_git_sandbox_init("empty_standard_repo"); - for (i = 0; i < NUM_TEST_OBJECTS; i++) { - size_t len = (g_len[i] < 0) ? strlen(g_raw[i]) : (size_t)g_len[i]; - g_len[i] = (git_off_t)len; + for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) { + if (g_crlf_raw_len[i] < 0) + g_crlf_raw_len[i] = strlen(g_crlf_raw[i]); - cl_git_pass( - git_blob_create_frombuffer(&g_oids[i], g_repo, g_raw[i], len) - ); + cl_git_pass(git_blob_create_frombuffer( + &g_crlf_oids[i], g_repo, g_crlf_raw[i], (size_t)g_crlf_raw_len[i])); } } void test_object_blob_filter__cleanup(void) { - git_repository_free(g_repo); - g_repo = NULL; - cl_fixture_cleanup("empty_standard_repo"); + cl_git_sandbox_cleanup(); } void test_object_blob_filter__unfiltered(void) @@ -72,10 +74,15 @@ void test_object_blob_filter__unfiltered(void) int i; git_blob *blob; - for (i = 0; i < NUM_TEST_OBJECTS; i++) { - cl_git_pass(git_blob_lookup(&blob, g_repo, &g_oids[i])); - cl_assert(g_len[i] == git_blob_rawsize(blob)); - cl_assert(memcmp(git_blob_rawcontent(blob), g_raw[i], (size_t)g_len[i]) == 0); + for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) { + size_t raw_len = (size_t)g_crlf_raw_len[i]; + + cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i])); + + cl_assert_equal_sz(raw_len, (size_t)git_blob_rawsize(blob)); + cl_assert_equal_i( + 0, memcmp(g_crlf_raw[i], git_blob_rawcontent(blob), raw_len)); + git_blob_free(blob); } } @@ -87,11 +94,12 @@ void test_object_blob_filter__stats(void) git_buf buf = GIT_BUF_INIT; git_buf_text_stats stats; - for (i = 0; i < NUM_TEST_OBJECTS; i++) { - cl_git_pass(git_blob_lookup(&blob, g_repo, &g_oids[i])); + for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) { + cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i])); cl_git_pass(git_blob__getbuf(&buf, blob)); git_buf_text_gather_stats(&stats, &buf, false); - cl_assert(memcmp(&g_stats[i], &stats, sizeof(stats)) == 0); + cl_assert_equal_i( + 0, memcmp(&g_crlf_filtered_stats[i], &stats, sizeof(stats))); git_blob_free(blob); } @@ -116,14 +124,15 @@ void test_object_blob_filter__to_odb(void) &fl, g_repo, NULL, "filename.txt", GIT_FILTER_TO_ODB)); cl_assert(fl != NULL); - for (i = 0; i < NUM_TEST_OBJECTS; i++) { - cl_git_pass(git_blob_lookup(&blob, g_repo, &g_oids[i])); + for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) { + cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i])); cl_git_pass(git_filter_list_apply_to_blob(&out, fl, blob)); - cl_assert(!memcmp( - out.ptr, g_crlf_filtered[i].ptr, - min(out.size, g_crlf_filtered[i].size))); + cl_assert_equal_sz(g_crlf_filtered[i].size, out.size); + + cl_assert_equal_i( + 0, memcmp(out.ptr, g_crlf_filtered[i].ptr, out.size)); git_blob_free(blob); } @@ -132,4 +141,3 @@ void test_object_blob_filter__to_odb(void) git_buf_free(&out); git_config_free(cfg); } - -- cgit v1.2.1 From d5b1866cc363461c3ecc14412dcd26d2e4fa8b68 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 13 Sep 2013 09:26:26 -0700 Subject: Rearrange clar submodule cleanup code --- tests-clar/diff/submodules.c | 1 - tests-clar/status/submodules.c | 1 - tests-clar/submodule/status.c | 1 - tests-clar/submodule/submodule_helpers.c | 21 ++++++++++++--------- tests-clar/submodule/submodule_helpers.h | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index 9dcf8194e..167dedfc6 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -11,7 +11,6 @@ void test_diff_submodules__initialize(void) void test_diff_submodules__cleanup(void) { - cleanup_fixture_submodules(); } static void check_diff_patches_at_line( diff --git a/tests-clar/status/submodules.c b/tests-clar/status/submodules.c index 7bfef503f..ef2888f7d 100644 --- a/tests-clar/status/submodules.c +++ b/tests-clar/status/submodules.c @@ -13,7 +13,6 @@ void test_status_submodules__initialize(void) void test_status_submodules__cleanup(void) { - cleanup_fixture_submodules(); } void test_status_submodules__api(void) diff --git a/tests-clar/submodule/status.c b/tests-clar/submodule/status.c index 7b29ac288..f1227a575 100644 --- a/tests-clar/submodule/status.c +++ b/tests-clar/submodule/status.c @@ -14,7 +14,6 @@ void test_submodule_status__initialize(void) void test_submodule_status__cleanup(void) { - cleanup_fixture_submodules(); } void test_submodule_status__unchanged(void) diff --git a/tests-clar/submodule/submodule_helpers.c b/tests-clar/submodule/submodule_helpers.c index a7807522b..3e79c77fd 100644 --- a/tests-clar/submodule/submodule_helpers.c +++ b/tests-clar/submodule/submodule_helpers.c @@ -83,6 +83,14 @@ void rewrite_gitmodules(const char *workdir) git_buf_free(&path); } +static void cleanup_fixture_submodules(void *payload) +{ + cl_git_sandbox_cleanup(); /* either "submodules" or "submod2" */ + + if (payload) + cl_fixture_cleanup(payload); +} + git_repository *setup_fixture_submodules(void) { git_repository *repo = cl_git_sandbox_init("submodules"); @@ -92,6 +100,8 @@ git_repository *setup_fixture_submodules(void) rewrite_gitmodules(git_repository_workdir(repo)); p_rename("submodules/testrepo/.gitted", "submodules/testrepo/.git"); + cl_set_cleanup(cleanup_fixture_submodules, "testrepo.git"); + return repo; } @@ -106,14 +116,7 @@ git_repository *setup_fixture_submod2(void) p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git"); p_rename("submod2/not/.gitted", "submod2/not/.git"); - return repo; -} + cl_set_cleanup(cleanup_fixture_submodules, "submod2_target"); -void cleanup_fixture_submodules(void) -{ - cl_git_sandbox_cleanup(); - - /* just try to clean up both possible extras */ - cl_fixture_cleanup("testrepo.git"); - cl_fixture_cleanup("submod2_target"); + return repo; } diff --git a/tests-clar/submodule/submodule_helpers.h b/tests-clar/submodule/submodule_helpers.h index 1de15ca17..610c40720 100644 --- a/tests-clar/submodule/submodule_helpers.h +++ b/tests-clar/submodule/submodule_helpers.h @@ -1,5 +1,5 @@ extern void rewrite_gitmodules(const char *workdir); +/* these will automatically set a cleanup callback */ extern git_repository *setup_fixture_submodules(void); extern git_repository *setup_fixture_submod2(void); -extern void cleanup_fixture_submodules(void); -- cgit v1.2.1 From ad7417d7a13e910d548e3e07225ce8914cdb218e Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 13 Sep 2013 09:44:30 -0700 Subject: Make filter tests somewhat more robust The global and system config could interfere with the filter tests by imposing CRLF filtering where it was not anticipated. This better isolates the tests from the system settings. --- tests-clar/filter/blob.c | 2 +- tests-clar/filter/custom.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/tests-clar/filter/blob.c b/tests-clar/filter/blob.c index 916721e12..9600a9779 100644 --- a/tests-clar/filter/blob.c +++ b/tests-clar/filter/blob.c @@ -12,7 +12,7 @@ void test_filter_blob__initialize(void) "*.lf text eol=lf\n" "*.ident text ident\n" "*.identcrlf ident text eol=crlf\n" - "*.identlf ident text eol.lf\n"); + "*.identlf ident text eol=lf\n"); } void test_filter_blob__cleanup(void) diff --git a/tests-clar/filter/custom.c b/tests-clar/filter/custom.c index 4a2ff9fc4..a2752efa4 100644 --- a/tests-clar/filter/custom.c +++ b/tests-clar/filter/custom.c @@ -50,7 +50,8 @@ void test_filter_custom__initialize(void) "empty_standard_repo/.gitattributes", "hero* bitflip reverse\n" "herofile text\n" - "heroflip -reverse\n"); + "heroflip -reverse binary\n" + "*.bin binary\n"); } void test_filter_custom__cleanup(void) @@ -229,6 +230,15 @@ void test_filter_custom__can_register_a_custom_filter_in_the_repository(void) cl_git_pass(git_filter_list_load( &fl, g_repo, NULL, "herocorp", GIT_FILTER_TO_WORKTREE)); + /* expect: bitflip, reverse - possibly crlf depending on global config */ + { + size_t flen = git_filter_list_length(fl); + cl_assert(flen == 2 || flen == 3); + } + git_filter_list_free(fl); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "hero.bin", GIT_FILTER_TO_WORKTREE)); /* expect: bitflip, reverse */ cl_assert_equal_sz(2, git_filter_list_length(fl)); git_filter_list_free(fl); @@ -240,7 +250,7 @@ void test_filter_custom__can_register_a_custom_filter_in_the_repository(void) git_filter_list_free(fl); cl_git_pass(git_filter_list_load( - &fl, g_repo, NULL, "doesntapplytome", GIT_FILTER_TO_WORKTREE)); + &fl, g_repo, NULL, "doesntapplytome.bin", GIT_FILTER_TO_WORKTREE)); /* expect: none */ cl_assert_equal_sz(0, git_filter_list_length(fl)); git_filter_list_free(fl); -- cgit v1.2.1 From e399c7eee8dac02b7a79c6133ad4c761f05b7ba9 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 13 Sep 2013 09:50:05 -0700 Subject: Fix win32 warnings I wish MSVC understood that "const char **" is not a const ptr, but it a non-const pointer to an array of const ptrs. Does that seem like too much to ask. --- src/filter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/filter.c b/src/filter.c index 0375b8b0e..62aefb420 100644 --- a/src/filter.c +++ b/src/filter.c @@ -391,7 +391,7 @@ static int filter_list_check_attributes( /* if no values were found but no matches are needed, it's okay! */ if (error == GIT_ENOTFOUND && !fdef->nmatches) { giterr_clear(); - git__free(strs); + git__free((void *)strs); return 0; } @@ -411,7 +411,7 @@ static int filter_list_check_attributes( } if (error) - git__free(strs); + git__free((void *)strs); else *out = strs; @@ -474,7 +474,7 @@ int git_filter_list_load( error = fdef->filter->check( fdef->filter, &payload, &src, values); - git__free(values); + git__free((void *)values); if (error == GIT_ENOTFOUND) error = 0; -- cgit v1.2.1 From 8427757f78b1f0b018b1ccfe424a4c39e89ea024 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 13 Sep 2013 12:32:45 -0700 Subject: Fixing up some win32 issues with autocrlf --- tests-clar/diff/rename.c | 2 ++ tests-clar/filter/crlf.c | 6 +----- tests-clar/status/renames.c | 4 +++- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index b5a9935fd..9864c5896 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -7,6 +7,8 @@ static git_repository *g_repo = NULL; void test_diff_rename__initialize(void) { g_repo = cl_git_sandbox_init("renames"); + + cl_repo_set_bool(g_repo, "core.autocrlf", false); } void test_diff_rename__cleanup(void) diff --git a/tests-clar/filter/crlf.c b/tests-clar/filter/crlf.c index ece2e6e5e..c9fb9cd7f 100644 --- a/tests-clar/filter/crlf.c +++ b/tests-clar/filter/crlf.c @@ -5,16 +5,12 @@ static git_repository *g_repo = NULL; void test_filter_crlf__initialize(void) { - git_config *cfg; - g_repo = cl_git_sandbox_init("crlf"); cl_git_mkfile("crlf/.gitattributes", "*.txt text\n*.bin binary\n*.crlf text eol=crlf\n*.lf text eol=lf\n"); - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_set_string(cfg, "core.autocrlf", "true")); - git_config_free(cfg); + cl_repo_set_bool(g_repo, "core.autocrlf", true); } void test_filter_crlf__cleanup(void) diff --git a/tests-clar/status/renames.c b/tests-clar/status/renames.c index d72e563bf..de84a574d 100644 --- a/tests-clar/status/renames.c +++ b/tests-clar/status/renames.c @@ -11,6 +11,8 @@ static git_repository *g_repo = NULL; void test_status_renames__initialize(void) { g_repo = cl_git_sandbox_init("renames"); + + cl_repo_set_bool(g_repo, "core.autocrlf", false); } void test_status_renames__cleanup(void) @@ -67,7 +69,7 @@ static void test_status( actual = git_status_byindex(status_list, i); expected = &expected_list[i]; - cl_assert_equal_i((int)expected->status, (int)actual->status); + cl_assert_equal_i_fmt(expected->status, actual->status, "%04x"); oldname = actual->head_to_index ? actual->head_to_index->old_file.path : actual->index_to_workdir ? actual->index_to_workdir->old_file.path : NULL; -- cgit v1.2.1 From fa9cc14880cb50ea626c4bb0fcf1b68acdd73186 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 13 Sep 2013 13:41:33 -0700 Subject: Fix cleanup issues with new tests --- tests-clar/revwalk/simplify.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests-clar/revwalk/simplify.c b/tests-clar/revwalk/simplify.c index c94952105..81c19d366 100644 --- a/tests-clar/revwalk/simplify.c +++ b/tests-clar/revwalk/simplify.c @@ -1,5 +1,10 @@ #include "clar_libgit2.h" +void test_revwalk_simplify__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + /* * a4a7dce [0] Merge branch 'master' into br2 |\ @@ -47,5 +52,4 @@ void test_revwalk_simplify__first_parent(void) cl_assert_equal_i(error, GIT_ITEROVER); git_revwalk_free(walk); - git_repository_free(repo); } -- cgit v1.2.1 From 13f36ffb9e1c4fb70b44a477d716873fecfc0407 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 13 Sep 2013 16:30:21 -0700 Subject: Add clar helpers for testing file equality These are a couple of new clar helpers for testing that a file has expected contents that I extracted from the checkout code. Actually wrote this as part of an abandoned earlier attempt at a new filters API, but it will be useful now for some of the tests I'm going to write. --- src/fileops.c | 12 +------ tests-clar/checkout/checkout_helpers.c | 58 ---------------------------------- tests-clar/checkout/checkout_helpers.h | 13 ++------ tests-clar/clar_libgit2.c | 55 ++++++++++++++++++++++++++++++++ tests-clar/clar_libgit2.h | 14 ++++++++ 5 files changed, 72 insertions(+), 80 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 3b271e6f6..bd845e982 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -56,18 +56,8 @@ int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode int git_futils_creat_locked(const char *path, const mode_t mode) { - int fd; - -#ifdef GIT_WIN32 - git_win32_path buf; - - git_win32_path_from_c(buf, path); - fd = _wopen(buf, O_WRONLY | O_CREAT | O_TRUNC | + int fd = p_open(path, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY | O_CLOEXEC, mode); -#else - fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | - O_EXCL | O_BINARY | O_CLOEXEC, mode); -#endif if (fd < 0) { giterr_set(GITERR_OS, "Failed to create locked file '%s'", path); diff --git a/tests-clar/checkout/checkout_helpers.c b/tests-clar/checkout/checkout_helpers.c index f55f7b611..06b4e0682 100644 --- a/tests-clar/checkout/checkout_helpers.c +++ b/tests-clar/checkout/checkout_helpers.c @@ -3,22 +3,6 @@ #include "refs.h" #include "fileops.h" -/* this is essentially the code from git__unescape modified slightly */ -void strip_cr_from_buf(git_buf *buf) -{ - char *scan, *pos = buf->ptr, *end = pos + buf->size; - - for (scan = pos; scan < end; pos++, scan++) { - if (*scan == '\r') - scan++; /* skip '\r' */ - if (pos != scan) - *pos = *scan; - } - - *pos = '\0'; - buf->size = (pos - buf->ptr); -} - void assert_on_branch(git_repository *repo, const char *branch) { git_reference *head; @@ -50,48 +34,6 @@ void reset_index_to_treeish(git_object *treeish) git_index_free(index); } -static void check_file_contents_internal( - const char *path, - const char *expected_content, - bool strip_cr, - const char *file, - int line, - const char *msg) -{ - int fd; - char data[1024] = {0}; - git_buf buf = GIT_BUF_INIT; - size_t expected_len = expected_content ? strlen(expected_content) : 0; - - fd = p_open(path, O_RDONLY); - cl_assert(fd >= 0); - - buf.ptr = data; - buf.size = p_read(fd, buf.ptr, sizeof(data)); - - cl_git_pass(p_close(fd)); - - if (strip_cr) - strip_cr_from_buf(&buf); - - clar__assert_equal(file, line, "strlen(expected_content) != strlen(actual_content)", 1, PRIuZ, expected_len, (size_t)buf.size); - clar__assert_equal(file, line, msg, 1, "%s", expected_content, buf.ptr); -} - -void check_file_contents_at_line( - const char *path, const char *expected, - const char *file, int line, const char *msg) -{ - check_file_contents_internal(path, expected, false, file, line, msg); -} - -void check_file_contents_nocr_at_line( - const char *path, const char *expected, - const char *file, int line, const char *msg) -{ - check_file_contents_internal(path, expected, true, file, line, msg); -} - int checkout_count_callback( git_checkout_notify_t why, const char *path, diff --git a/tests-clar/checkout/checkout_helpers.h b/tests-clar/checkout/checkout_helpers.h index 0e8da31d1..705ee903d 100644 --- a/tests-clar/checkout/checkout_helpers.h +++ b/tests-clar/checkout/checkout_helpers.h @@ -2,23 +2,14 @@ #include "git2/object.h" #include "git2/repository.h" -extern void strip_cr_from_buf(git_buf *buf); extern void assert_on_branch(git_repository *repo, const char *branch); extern void reset_index_to_treeish(git_object *treeish); -extern void check_file_contents_at_line( - const char *path, const char *expected, - const char *file, int line, const char *msg); - -extern void check_file_contents_nocr_at_line( - const char *path, const char *expected, - const char *file, int line, const char *msg); - #define check_file_contents(PATH,EXP) \ - check_file_contents_at_line(PATH,EXP,__FILE__,__LINE__,"String mismatch: " #EXP " != " #PATH) + cl_assert_equal_file(EXP,0,PATH) #define check_file_contents_nocr(PATH,EXP) \ - check_file_contents_nocr_at_line(PATH,EXP,__FILE__,__LINE__,"String mismatch: " #EXP " != " #PATH) + cl_assert_equal_file_ignore_cr(EXP,0,PATH) typedef struct { int n_conflicts; diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 340943ca8..522f73634 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -354,3 +354,58 @@ int cl_repo_get_bool(git_repository *repo, const char *cfg) git_config_free(config); return val; } + +/* this is essentially the code from git__unescape modified slightly */ +static size_t strip_cr_from_buf(char *start, size_t len) +{ + char *scan, *trail, *end = start + len; + + for (scan = trail = start; scan < end; trail++, scan++) { + while (*scan == '\r') + scan++; /* skip '\r' */ + + if (trail != scan) + *trail = *scan; + } + + *trail = '\0'; + + return (trail - start); +} + +void clar__assert_equal_file( + const char *expected_data, + size_t expected_bytes, + int ignore_cr, + const char *path, + const char *file, + size_t line) +{ + char buf[4000]; + ssize_t bytes, total_bytes = 0; + int fd = p_open(path, O_RDONLY | O_BINARY); + cl_assert(fd >= 0); + + if (expected_data && !expected_bytes) + expected_bytes = strlen(expected_data); + + while ((bytes = p_read(fd, buf, sizeof(buf))) != 0) { + clar__assert( + bytes > 0, file, line, "error reading from file", path, 1); + + if (ignore_cr) + bytes = strip_cr_from_buf(buf, bytes); + + clar__assert(memcmp(expected_data, buf, bytes) == 0, + file, line, "file content mismatch", path, 1); + + expected_data += bytes; + total_bytes += bytes; + } + + p_close(fd); + + clar__assert(!bytes, file, line, "error reading from file", path, 1); + clar__assert_equal(file, line, "mismatched file length", 1, "%"PRIuZ, + (size_t)expected_bytes, (size_t)total_bytes); +} diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index 8dcfdee48..76299e4e3 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -46,6 +46,20 @@ GIT_INLINE(void) clar__assert_in_range( #define cl_assert_in_range(L,V,H) \ clar__assert_in_range((L),(V),(H),__FILE__,__LINE__,"Range check: " #V " in [" #L "," #H "]", 1) +#define cl_assert_equal_file(DATA,SIZE,PATH) \ + clar__assert_equal_file(DATA,SIZE,0,PATH,__FILE__,__LINE__) + +#define cl_assert_equal_file_ignore_cr(DATA,SIZE,PATH) \ + clar__assert_equal_file(DATA,SIZE,1,PATH,__FILE__,__LINE__) + +void clar__assert_equal_file( + const char *expected_data, + size_t expected_size, + int ignore_cr, + const char *path, + const char *file, + size_t line); + /* * Some utility macros for building long strings */ -- cgit v1.2.1 From 155fa2342d838bdb2aa873c95a42e091351bb69a Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 5 Sep 2013 15:06:42 -0700 Subject: Add clar helper to create new commit from index There were a lot of places in the test code base that were creating a commit from the index on the current branch. This just adds a helper to handle that case pretty easily. There was only one test where this change ended up tweaking the test data, so pretty easy and mostly just a cleanup. --- tests-clar/clar_libgit2.c | 59 ++++++++++++++++++++++++++++++++++++++++ tests-clar/clar_libgit2.h | 8 ++++++ tests-clar/diff/submodules.c | 25 ++--------------- tests-clar/index/addall.c | 35 ++---------------------- tests-clar/repo/init.c | 5 ++++ tests-clar/stash/drop.c | 16 ++++++----- tests-clar/stash/save.c | 5 ++-- tests-clar/stash/stash_helpers.c | 33 +--------------------- tests-clar/stash/stash_helpers.h | 5 ---- tests-clar/status/worktree.c | 25 +---------------- tests-clar/stress/diff.c | 24 ++-------------- 11 files changed, 93 insertions(+), 147 deletions(-) diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 522f73634..4cf682449 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -337,6 +337,65 @@ int cl_git_remove_placeholders(const char *directory_path, const char *filename) return error; } +#define CL_COMMIT_NAME "Libgit2 Tester" +#define CL_COMMIT_EMAIL "libgit2-test@github.com" +#define CL_COMMIT_MSG "Test commit of tree " + +void cl_repo_commit_from_index( + git_oid *out, + git_repository *repo, + git_signature *sig, + git_time_t time, + const char *msg) +{ + git_index *index; + git_oid commit_id, tree_id; + git_object *parent = NULL; + git_reference *ref = NULL; + git_tree *tree = NULL; + char buf[128]; + int free_sig = (sig == NULL); + + /* it is fine if looking up HEAD fails - we make this the first commit */ + git_revparse_ext(&parent, &ref, repo, "HEAD"); + + /* write the index content as a tree */ + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_write_tree(&tree_id, index)); + cl_git_pass(git_index_write(index)); + git_index_free(index); + + cl_git_pass(git_tree_lookup(&tree, repo, &tree_id)); + + if (sig) + cl_assert(sig->name && sig->email); + else if (!time) + cl_git_pass(git_signature_now(&sig, CL_COMMIT_NAME, CL_COMMIT_EMAIL)); + else + cl_git_pass(git_signature_new( + &sig, CL_COMMIT_NAME, CL_COMMIT_EMAIL, time, 0)); + + if (!msg) { + strcpy(buf, CL_COMMIT_MSG); + git_oid_tostr(buf + strlen(CL_COMMIT_MSG), + sizeof(buf) - strlen(CL_COMMIT_MSG), &tree_id); + msg = buf; + } + + cl_git_pass(git_commit_create_v( + &commit_id, repo, ref ? git_reference_name(ref) : "HEAD", + sig, sig, NULL, msg, tree, parent ? 1 : 0, parent)); + + if (out) + git_oid_cpy(out, &commit_id); + + git_object_free(parent); + git_reference_free(ref); + if (free_sig) + git_signature_free(sig); + git_tree_free(tree); +} + void cl_repo_set_bool(git_repository *repo, const char *cfg, int value) { git_config *config; diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index 76299e4e3..f2d9c4d0b 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -98,6 +98,14 @@ const char* cl_git_path_url(const char *path); /* Test repository cleaner */ int cl_git_remove_placeholders(const char *directory_path, const char *filename); +/* commit creation helpers */ +void cl_repo_commit_from_index( + git_oid *out, + git_repository *repo, + git_signature *sig, + git_time_t time, + const char *msg); + /* config setting helpers */ void cl_repo_set_bool(git_repository *repo, const char *cfg, int value); int cl_repo_get_bool(git_repository *repo, const char *cfg); diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index 167dedfc6..036ff09aa 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -228,11 +228,11 @@ void test_diff_submodules__invalid_cache(void) "" }; static const char *expected_moved[] = { - "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..0910a13 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 0910a13dfa2210496f6c590d75bc360dd11b2a1b\n", + "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..7002348 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 700234833f6ccc20d744b238612646be071acaae\n", "" }; static const char *expected_moved_dirty[] = { - "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..0910a13 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 0910a13dfa2210496f6c590d75bc360dd11b2a1b-dirty\n", + "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..7002348 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 700234833f6ccc20d744b238612646be071acaae-dirty\n", "" }; @@ -309,26 +309,7 @@ void test_diff_submodules__invalid_cache(void) git_diff_list_free(diff); /* commit changed index of submodule */ - { - git_object *parent; - git_oid tree_id, commit_id; - git_tree *tree; - git_signature *sig; - git_reference *ref; - - cl_git_pass(git_revparse_ext(&parent, &ref, smrepo, "HEAD")); - cl_git_pass(git_index_write_tree(&tree_id, smindex)); - cl_git_pass(git_index_write(smindex)); - cl_git_pass(git_tree_lookup(&tree, smrepo, &tree_id)); - cl_git_pass(git_signature_new(&sig, "Sm Test", "sm@tester.test", 1372350000, 480)); - cl_git_pass(git_commit_create_v( - &commit_id, smrepo, git_reference_name(ref), sig, sig, - NULL, "Move it", tree, 1, parent)); - git_object_free(parent); - git_tree_free(tree); - git_reference_free(ref); - git_signature_free(sig); - } + cl_repo_commit_from_index(NULL, smrepo, NULL, 1372350000, "Move it"); git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); diff --git a/tests-clar/index/addall.c b/tests-clar/index/addall.c index 00388ee00..f46a1e16c 100644 --- a/tests-clar/index/addall.c +++ b/tests-clar/index/addall.c @@ -120,37 +120,6 @@ static void check_stat_data(git_index *index, const char *path, bool match) } } -static void commit_index_to_head( - git_repository *repo, - const char *commit_message) -{ - git_index *index; - git_oid tree_id, commit_id; - git_tree *tree; - git_signature *sig; - git_commit *parent = NULL; - - git_revparse_single((git_object **)&parent, repo, "HEAD"); - /* it is okay if looking up the HEAD fails */ - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_write_tree(&tree_id, index)); - cl_git_pass(git_index_write(index)); /* not needed, but might as well */ - git_index_free(index); - - cl_git_pass(git_tree_lookup(&tree, repo, &tree_id)); - - cl_git_pass(git_signature_now(&sig, "Testy McTester", "tt@tester.test")); - - cl_git_pass(git_commit_create_v( - &commit_id, repo, "HEAD", sig, sig, - NULL, commit_message, tree, parent ? 1 : 0, parent)); - - git_commit_free(parent); - git_tree_free(tree); - git_signature_free(sig); -} - void test_index_addall__repo_lifecycle(void) { int error; @@ -197,7 +166,7 @@ void test_index_addall__repo_lifecycle(void) check_stat_data(index, "addall/file.zzz", true); check_status(g_repo, 2, 0, 0, 3, 0, 0, 1); - commit_index_to_head(g_repo, "first commit"); + cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "first commit"); check_status(g_repo, 0, 0, 0, 3, 0, 0, 1); /* attempt to add an ignored file - does nothing */ @@ -244,7 +213,7 @@ void test_index_addall__repo_lifecycle(void) cl_git_pass(git_index_add_bypath(index, "file.zzz")); check_status(g_repo, 1, 0, 1, 3, 0, 0, 0); - commit_index_to_head(g_repo, "second commit"); + cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "second commit"); check_status(g_repo, 0, 0, 0, 3, 0, 0, 0); cl_must_pass(p_unlink("addall/file.zzz")); diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index e3fc112b3..caa211e75 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -565,6 +565,11 @@ void test_repo_init__init_with_initial_commit(void) cl_git_pass(git_index_add_bypath(index, "file.txt")); cl_git_pass(git_index_write(index)); + /* Intentionally not using cl_repo_commit_from_index here so this code + * can be used as an example of how an initial commit is typically + * made to a repository... + */ + /* Make sure we're ready to use git_signature_default :-) */ { git_config *cfg, *local; diff --git a/tests-clar/stash/drop.c b/tests-clar/stash/drop.c index 60b3c72e0..59413f01e 100644 --- a/tests-clar/stash/drop.c +++ b/tests-clar/stash/drop.c @@ -36,25 +36,27 @@ static void push_three_states(void) cl_git_mkfile("stash/zero.txt", "content\n"); cl_git_pass(git_repository_index(&index, repo)); cl_git_pass(git_index_add_bypath(index, "zero.txt")); - commit_staged_files(&oid, index, signature); + cl_repo_commit_from_index(NULL, repo, signature, 0, "Initial commit"); cl_assert(git_path_exists("stash/zero.txt")); + git_index_free(index); cl_git_mkfile("stash/one.txt", "content\n"); - cl_git_pass(git_stash_save(&oid, repo, signature, "First", GIT_STASH_INCLUDE_UNTRACKED)); + cl_git_pass(git_stash_save( + &oid, repo, signature, "First", GIT_STASH_INCLUDE_UNTRACKED)); cl_assert(!git_path_exists("stash/one.txt")); cl_assert(git_path_exists("stash/zero.txt")); cl_git_mkfile("stash/two.txt", "content\n"); - cl_git_pass(git_stash_save(&oid, repo, signature, "Second", GIT_STASH_INCLUDE_UNTRACKED)); + cl_git_pass(git_stash_save( + &oid, repo, signature, "Second", GIT_STASH_INCLUDE_UNTRACKED)); cl_assert(!git_path_exists("stash/two.txt")); cl_assert(git_path_exists("stash/zero.txt")); cl_git_mkfile("stash/three.txt", "content\n"); - cl_git_pass(git_stash_save(&oid, repo, signature, "Third", GIT_STASH_INCLUDE_UNTRACKED)); + cl_git_pass(git_stash_save( + &oid, repo, signature, "Third", GIT_STASH_INCLUDE_UNTRACKED)); cl_assert(!git_path_exists("stash/three.txt")); cl_assert(git_path_exists("stash/zero.txt")); - - git_index_free(index); } void test_stash_drop__cannot_drop_a_non_existing_stashed_state(void) @@ -160,7 +162,7 @@ void test_stash_drop__dropping_the_top_stash_updates_the_stash_reference(void) retrieve_top_stash_id(&oid); cl_git_pass(git_revparse_single(&next_top_stash, repo, "stash@{1}")); - cl_assert_equal_i(false, git_oid_cmp(&oid, git_object_id(next_top_stash)) == 0); + cl_assert(git_oid_cmp(&oid, git_object_id(next_top_stash)) != 0); cl_git_pass(git_stash_drop(repo, 0)); diff --git a/tests-clar/stash/save.c b/tests-clar/stash/save.c index bb35a3d71..035b62279 100644 --- a/tests-clar/stash/save.c +++ b/tests-clar/stash/save.c @@ -241,7 +241,7 @@ void test_stash_save__stashing_updates_the_reflog(void) void test_stash_save__cannot_stash_when_there_are_no_local_change(void) { git_index *index; - git_oid commit_oid, stash_tip_oid; + git_oid stash_tip_oid; cl_git_pass(git_repository_index(&index, repo)); @@ -251,8 +251,7 @@ void test_stash_save__cannot_stash_when_there_are_no_local_change(void) */ cl_git_pass(git_index_add_bypath(index, "what")); cl_git_pass(git_index_add_bypath(index, "who")); - cl_git_pass(git_index_write(index)); - commit_staged_files(&commit_oid, index, signature); + cl_repo_commit_from_index(NULL, repo, signature, 0, "Initial commit"); git_index_free(index); cl_assert_equal_i(GIT_ENOTFOUND, diff --git a/tests-clar/stash/stash_helpers.c b/tests-clar/stash/stash_helpers.c index f462a1351..06b63f177 100644 --- a/tests-clar/stash/stash_helpers.c +++ b/tests-clar/stash/stash_helpers.c @@ -2,38 +2,8 @@ #include "fileops.h" #include "stash_helpers.h" -void commit_staged_files( - git_oid *commit_oid, - git_index *index, - git_signature *signature) -{ - git_tree *tree; - git_oid tree_oid; - git_repository *repo; - - repo = git_index_owner(index); - - cl_git_pass(git_index_write_tree(&tree_oid, index)); - - cl_git_pass(git_tree_lookup(&tree, repo, &tree_oid)); - - cl_git_pass(git_commit_create_v( - commit_oid, - repo, - "HEAD", - signature, - signature, - NULL, - "Initial commit", - tree, - 0)); - - git_tree_free(tree); -} - void setup_stash(git_repository *repo, git_signature *signature) { - git_oid commit_oid; git_index *index; cl_git_pass(git_repository_index(&index, repo)); @@ -50,9 +20,8 @@ void setup_stash(git_repository *repo, git_signature *signature) cl_git_pass(git_index_add_bypath(index, "how")); cl_git_pass(git_index_add_bypath(index, "who")); cl_git_pass(git_index_add_bypath(index, ".gitignore")); - cl_git_pass(git_index_write(index)); - commit_staged_files(&commit_oid, index, signature); + cl_repo_commit_from_index(NULL, repo, signature, 0, "Initial commit"); cl_git_rewritefile("stash/what", "goodbye\n"); /* dd7e1c6f0fefe118f0b63d9f10908c460aa317a6 */ cl_git_rewritefile("stash/how", "not so small and\n"); /* e6d64adb2c7f3eb8feb493b556cc8070dca379a3 */ diff --git a/tests-clar/stash/stash_helpers.h b/tests-clar/stash/stash_helpers.h index bb7fec4f5..7c3e13de3 100644 --- a/tests-clar/stash/stash_helpers.h +++ b/tests-clar/stash/stash_helpers.h @@ -1,8 +1,3 @@ void setup_stash( git_repository *repo, git_signature *signature); - -void commit_staged_files( - git_oid *commit_oid, - git_index *index, - git_signature *signature); \ No newline at end of file diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index be7398cb6..135a95871 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -632,35 +632,12 @@ void test_status_worktree__conflicted_item(void) static void stage_and_commit(git_repository *repo, const char *path) { - git_oid tree_oid, commit_oid; - git_tree *tree; - git_signature *signature; git_index *index; cl_git_pass(git_repository_index(&index, repo)); cl_git_pass(git_index_add_bypath(index, path)); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_index_write_tree(&tree_oid, index)); + cl_repo_commit_from_index(NULL, repo, NULL, 1323847743, "Initial commit\n"); git_index_free(index); - - cl_git_pass(git_tree_lookup(&tree, repo, &tree_oid)); - - cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); - - cl_git_pass(git_commit_create_v( - &commit_oid, - repo, - "HEAD", - signature, - signature, - NULL, - "Initial commit\n\0", - tree, - 0)); - - git_tree_free(tree); - git_signature_free(signature); } static void assert_ignore_case( diff --git a/tests-clar/stress/diff.c b/tests-clar/stress/diff.c index 0524aa108..1d319738e 100644 --- a/tests-clar/stress/diff.c +++ b/tests-clar/stress/diff.c @@ -54,27 +54,9 @@ static void test_with_many(int expected_new) git_diff_list_free(diff); - { - git_object *parent; - git_signature *sig; - git_oid tree_id, commit_id; - git_reference *ref; - - cl_git_pass(git_index_write_tree(&tree_id, index)); - cl_git_pass(git_tree_lookup(&new_tree, g_repo, &tree_id)); - - cl_git_pass(git_revparse_ext(&parent, &ref, g_repo, "HEAD")); - cl_git_pass(git_signature_new( - &sig, "Sm Test", "sm@tester.test", 1372350000, 480)); - - cl_git_pass(git_commit_create_v( - &commit_id, g_repo, git_reference_name(ref), sig, sig, - NULL, "yoyoyo", new_tree, 1, parent)); - - git_object_free(parent); - git_reference_free(ref); - git_signature_free(sig); - } + cl_repo_commit_from_index(NULL, g_repo, NULL, 1372350000, "yoyoyo"); + cl_git_pass(git_revparse_single( + (git_object **)&new_tree, g_repo, "HEAD^{tree}")); cl_git_pass(git_diff_tree_to_tree( &diff, g_repo, tree, new_tree, &diffopts)); -- cgit v1.2.1 From 37f9e4093999498a25641018da36245d6a7cb008 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 13 Sep 2013 21:43:00 -0700 Subject: Some tests with ident and crlf filters Fixed the filter order to match core Git, too. This test demonstrates an interesting behavior of core Git (which is totally reasonable and which libgit2 matches, although mostly by coincidence). If you use the ident filter and commit a file with a garbage ident in it, like '$Id: this is just garbage$' and then immediately do a 'git checkout-index' with the new file, Git will not consider the file out of date and will not overwrite the file with an updated $Id$. Libgit2 has the same behavior. If you remove the file and then do a checkout-index, it will be replaced with a filtered version that has injected the OID correctly. --- examples/showindex.c | 4 +++ src/filter.c | 2 +- tests-clar/checkout/crlf.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++ tests-clar/clar_libgit2.c | 11 ++++++-- 4 files changed, 79 insertions(+), 3 deletions(-) diff --git a/examples/showindex.c b/examples/showindex.c index e92a9c8de..93718c89b 100644 --- a/examples/showindex.c +++ b/examples/showindex.c @@ -12,6 +12,8 @@ int main (int argc, char** argv) char out[41]; out[40] = '\0'; + git_threads_init(); + if (argc > 1) dir = argv[1]; if (!dir || argc > 2) { @@ -62,6 +64,8 @@ int main (int argc, char** argv) git_index_free(index); git_repository_free(repo); + git_threads_shutdown(); + return 0; } diff --git a/src/filter.c b/src/filter.c index 62aefb420..378209800 100644 --- a/src/filter.c +++ b/src/filter.c @@ -593,7 +593,7 @@ int git_filter_list_apply_to_data( for (i = 0; i < git_array_size(fl->filters); ++i) { unsigned int di = 1 - si; - uint32_t fidx = (fl->source.mode == GIT_FILTER_TO_ODB) ? + uint32_t fidx = (fl->source.mode == GIT_FILTER_TO_WORKTREE) ? i : git_array_size(fl->filters) - 1 - i; git_filter_entry *fe = git_array_get(fl->filters, fidx); diff --git a/tests-clar/checkout/crlf.c b/tests-clar/checkout/crlf.c index 5f5f1b776..4953609cc 100644 --- a/tests-clar/checkout/crlf.c +++ b/tests-clar/checkout/crlf.c @@ -4,6 +4,7 @@ #include "git2/checkout.h" #include "repository.h" +#include "posix.h" static git_repository *g_repo; @@ -136,3 +137,67 @@ void test_checkout_crlf__autocrlf_true_index_size_is_filtered_size(void) git_index_free(index); } + +void test_checkout_crlf__with_ident(void) +{ + git_index *index; + git_blob *blob; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_git_mkfile("crlf/.gitattributes", + "*.txt text\n*.bin binary\n" + "*.crlf text eol=crlf\n" + "*.lf text eol=lf\n" + "*.ident text ident\n" + "*.identcrlf ident text eol=crlf\n" + "*.identlf ident text eol=lf\n"); + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + /* add files with $Id$ */ + + cl_git_mkfile("crlf/lf.ident", ALL_LF_TEXT_RAW "\n$Id: initial content$\n"); + cl_git_mkfile("crlf/crlf.ident", ALL_CRLF_TEXT_RAW "\r\n$Id$\r\n\r\n"); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_add_bypath(index, "lf.ident")); + cl_git_pass(git_index_add_bypath(index, "crlf.ident")); + cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "Some ident files\n"); + + git_checkout_head(g_repo, &opts); + + /* check that blob has $Id$ */ + + cl_git_pass(git_blob_lookup(&blob, g_repo, + & git_index_get_bypath(index, "lf.ident", 0)->oid)); + cl_assert_equal_s( + ALL_LF_TEXT_RAW "\n$Id$\n", git_blob_rawcontent(blob)); + + git_blob_free(blob); + + /* check that filesystem is initially untouched - matching core Git */ + + cl_assert_equal_file( + ALL_LF_TEXT_RAW "\n$Id: initial content$\n", 0, "crlf/lf.ident"); + + /* check that forced checkout rewrites correctly */ + + p_unlink("crlf/lf.ident"); + p_unlink("crlf/crlflf.ident"); + + git_checkout_head(g_repo, &opts); + + if (GIT_EOL_NATIVE == GIT_EOL_LF) + cl_assert_equal_file( + ALL_LF_TEXT_RAW + "\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467$\n", + 0, "crlf/lf.ident"); + else + cl_assert_equal_file( + ALL_LF_TEXT_AS_CRLF + "\r\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467$\r\n", + 0, "crlf/lf.ident"); + + git_index_free(index); +} diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 4cf682449..d7e28831f 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -455,8 +455,15 @@ void clar__assert_equal_file( if (ignore_cr) bytes = strip_cr_from_buf(buf, bytes); - clar__assert(memcmp(expected_data, buf, bytes) == 0, - file, line, "file content mismatch", path, 1); + if (memcmp(expected_data, buf, bytes) != 0) { + int pos; + for (pos = 0; pos < bytes && expected_data[pos] == buf[pos]; ++pos) + /* find differing byte offset */; + p_snprintf( + buf, sizeof(buf), "file content mismatch at byte %d", + (int)(total_bytes + pos)); + clar__fail(file, line, buf, path, 1); + } expected_data += bytes; total_bytes += bytes; -- cgit v1.2.1 From eab3746b3026950ed62842c1e5641556d7131a5b Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Sun, 15 Sep 2013 22:23:39 -0700 Subject: More filtering tests including order This adds more tests of filters, including the ident filter when mixed with custom filters. I was able to combine with the reverse filter and demonstrate that the order of filter application with the default priority constants matches the order of core Git. Also, this fixes two issues in the ident filter: preventing ident expansion on binary files and avoiding a NULL dereference when dollar sign characters are found without Id. --- include/git2/sys/filter.h | 14 ++++++++++ src/ident.c | 7 ++++- tests-clar/checkout/crlf.c | 36 +++++++++++++++++++++++--- tests-clar/filter/custom.c | 64 ++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 114 insertions(+), 7 deletions(-) diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h index 9a6720a3e..aa89c7b56 100644 --- a/include/git2/sys/filter.h +++ b/include/git2/sys/filter.h @@ -29,9 +29,23 @@ GIT_EXTERN(git_filter *) git_filter_lookup(const char *name); #define GIT_FILTER_CRLF "crlf" #define GIT_FILTER_IDENT "ident" +/** + * This is priority that the internal CRLF filter will be registered with + */ #define GIT_FILTER_CRLF_PRIORITY 0 + +/** + * This is priority that the internal ident filter will be registered with + */ #define GIT_FILTER_IDENT_PRIORITY 100 +/** + * This is priority to use with a custom filter to imitate a core Git + * filter driver, so that it will be run last on checkout and first on + * checkin. You do not have to use this, but it helps compatibility. + */ +#define GIT_FILTER_DRIVER_PRIORITY 200 + /** * Create a new empty filter list * diff --git a/src/ident.c b/src/ident.c index 3ea949859..23c407f16 100644 --- a/src/ident.c +++ b/src/ident.c @@ -8,6 +8,7 @@ #include "git2/sys/filter.h" #include "filter.h" #include "buffer.h" +#include "buf_text.h" static int ident_find_id( const char **id_start, const char **id_end, const char *start, size_t len) @@ -24,7 +25,7 @@ static int ident_find_id( len = remaining - 1; } - if (len < 3) + if (!found || len < 3) return GIT_ENOTFOUND; *id_start = found; @@ -99,6 +100,10 @@ static int ident_apply( { GIT_UNUSED(self); GIT_UNUSED(payload); + /* Don't filter binary files */ + if (git_buf_text_is_binary(from)) + return GIT_ENOTFOUND; + if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE) return ident_insert_id(to, from, src); else diff --git a/tests-clar/checkout/crlf.c b/tests-clar/checkout/crlf.c index 4953609cc..9a4cbd313 100644 --- a/tests-clar/checkout/crlf.c +++ b/tests-clar/checkout/crlf.c @@ -159,21 +159,30 @@ void test_checkout_crlf__with_ident(void) cl_git_mkfile("crlf/lf.ident", ALL_LF_TEXT_RAW "\n$Id: initial content$\n"); cl_git_mkfile("crlf/crlf.ident", ALL_CRLF_TEXT_RAW "\r\n$Id$\r\n\r\n"); + cl_git_mkfile("crlf/more1.identlf", "$Id$\n" MORE_LF_TEXT_RAW); + cl_git_mkfile("crlf/more2.identcrlf", "\r\n$Id: $\r\n" MORE_CRLF_TEXT_RAW); cl_git_pass(git_repository_index(&index, g_repo)); cl_git_pass(git_index_add_bypath(index, "lf.ident")); cl_git_pass(git_index_add_bypath(index, "crlf.ident")); + cl_git_pass(git_index_add_bypath(index, "more1.identlf")); + cl_git_pass(git_index_add_bypath(index, "more2.identcrlf")); cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "Some ident files\n"); git_checkout_head(g_repo, &opts); - /* check that blob has $Id$ */ + /* check that blobs have $Id$ */ cl_git_pass(git_blob_lookup(&blob, g_repo, & git_index_get_bypath(index, "lf.ident", 0)->oid)); cl_assert_equal_s( ALL_LF_TEXT_RAW "\n$Id$\n", git_blob_rawcontent(blob)); + git_blob_free(blob); + cl_git_pass(git_blob_lookup(&blob, g_repo, + & git_index_get_bypath(index, "more2.identcrlf", 0)->oid)); + cl_assert_equal_s( + "\n$Id$\n" MORE_CRLF_TEXT_AS_LF, git_blob_rawcontent(blob)); git_blob_free(blob); /* check that filesystem is initially untouched - matching core Git */ @@ -184,20 +193,39 @@ void test_checkout_crlf__with_ident(void) /* check that forced checkout rewrites correctly */ p_unlink("crlf/lf.ident"); - p_unlink("crlf/crlflf.ident"); + p_unlink("crlf/crlf.ident"); + p_unlink("crlf/more1.identlf"); + p_unlink("crlf/more2.identcrlf"); git_checkout_head(g_repo, &opts); - if (GIT_EOL_NATIVE == GIT_EOL_LF) + if (GIT_EOL_NATIVE == GIT_EOL_LF) { cl_assert_equal_file( ALL_LF_TEXT_RAW "\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467$\n", 0, "crlf/lf.ident"); - else + cl_assert_equal_file( + ALL_CRLF_TEXT_AS_LF + "\n$Id: f2c66ad9b2b5a734d9bf00d5000cc10a62b8a857$\n\n", + 0, "crlf/crlf.ident"); + } else { cl_assert_equal_file( ALL_LF_TEXT_AS_CRLF "\r\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467$\r\n", 0, "crlf/lf.ident"); + cl_assert_equal_file( + ALL_CRLF_TEXT_RAW + "\r\n$Id: f2c66ad9b2b5a734d9bf00d5000cc10a62b8a857$\r\n\r\n", + 0, "crlf/crlf.ident"); + } + + cl_assert_equal_file( + "$Id: f7830382dac1f1583422be5530fdfbd26289431b$\n" + MORE_LF_TEXT_AS_LF, 0, "crlf/more1.identlf"); + + cl_assert_equal_file( + "\r\n$Id: 74677a68413012ce8d7e7cfc3f12603df3a3eac4$\r\n" + MORE_CRLF_TEXT_AS_CRLF, 0, "crlf/more2.identcrlf"); git_index_free(index); } diff --git a/tests-clar/filter/custom.c b/tests-clar/filter/custom.c index a2752efa4..d6ad4b7a3 100644 --- a/tests-clar/filter/custom.c +++ b/tests-clar/filter/custom.c @@ -6,8 +6,9 @@ #include "git2/sys/filter.h" #include "git2/sys/repository.h" -#define BITFLIP_FILTER_PRIORITY 20 -#define REVERSE_FILTER_PRIORITY 25 +/* picked these to be >= GIT_FILTER_DRIVER_PRIORITY */ +#define BITFLIP_FILTER_PRIORITY 200 +#define REVERSE_FILTER_PRIORITY 250 #define VERY_SECURE_ENCRYPTION(b) ((b) ^ 0xff) @@ -255,3 +256,62 @@ void test_filter_custom__can_register_a_custom_filter_in_the_repository(void) cl_assert_equal_sz(0, git_filter_list_length(fl)); git_filter_list_free(fl); } + +void test_filter_custom__order_dependency(void) +{ + git_index *index; + git_blob *blob; + git_buf buf = { 0 }; + + /* so if ident and reverse are used together, an interesting thing + * happens - a reversed "$Id$" string is no longer going to trigger + * ident correctly. When checking out, the filters should be applied + * in order CLRF, then ident, then reverse, so ident expansion should + * work correctly. On check in, the content should be reversed, then + * ident, then CRLF filtered. Let's make sure that works... + */ + + cl_git_mkfile( + "empty_standard_repo/.gitattributes", + "hero.*.rev-ident text ident reverse eol=lf\n"); + + cl_git_mkfile( + "empty_standard_repo/hero.1.rev-ident", + "This is a test\n$Id$\nHave fun!\n"); + + cl_git_mkfile( + "empty_standard_repo/hero.2.rev-ident", + "Another test\n$dI$\nCrazy!\n"); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_add_bypath(index, "hero.1.rev-ident")); + cl_git_pass(git_index_add_bypath(index, "hero.2.rev-ident")); + cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "Filter chains\n"); + git_index_free(index); + + cl_git_pass(git_blob_lookup(&blob, g_repo, + & git_index_get_bypath(index, "hero.1.rev-ident", 0)->oid)); + cl_assert_equal_s( + "\n!nuf evaH\n$dI$\ntset a si sihT", git_blob_rawcontent(blob)); + cl_git_pass(git_blob_filtered_content(&buf, blob, "hero.1.rev-ident", 0)); + /* no expansion because id was reversed at checkin and now at ident + * time, reverse is not applied yet */ + cl_assert_equal_s( + "This is a test\n$Id$\nHave fun!\n", buf.ptr); + git_blob_free(blob); + + cl_git_pass(git_blob_lookup(&blob, g_repo, + & git_index_get_bypath(index, "hero.2.rev-ident", 0)->oid)); + cl_assert_equal_s( + "\n!yzarC\n$Id$\ntset rehtonA", git_blob_rawcontent(blob)); + cl_git_pass(git_blob_filtered_content(&buf, blob, "hero.2.rev-ident", 0)); + /* expansion because reverse was applied at checkin and at ident time, + * reverse is not applied yet */ + cl_assert_equal_s( + "Another test\n$59001fe193103b1016b27027c0c827d036fd0ac8 :dI$\nCrazy!\n", buf.ptr); + cl_assert_equal_i(0, git_oid_strcmp( + git_blob_id(blob), "8ca0df630d728c0c72072b6101b301391ef10095")); + git_blob_free(blob); + + git_buf_free(&buf); +} -- cgit v1.2.1 From eefc32d54944ead5a5e3041c1b1f6c8c946cc014 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 16 Sep 2013 12:54:40 -0700 Subject: Bug fixes and cleanups This contains a few bug fixes and some header and API cleanups. The main API change is that filters should now use GIT_PASSTHROUGH to indicate that they wish to skip processing a file instead of GIT_ENOTFOUND. The bug fixes include a possible out-of-range buffer access in the ident filter, a filter ordering problem I introduced into the custom filter tests on Windows, and a filter buf NUL termination issue that was coming up on Linux. --- include/git2/sys/filter.h | 101 ++++++++++++++++++++++++++++++--------------- src/array.h | 2 +- src/crlf.c | 18 ++++---- src/filter.c | 14 ++++--- src/ident.c | 26 ++++++------ src/win32/pthread.c | 1 + tests-clar/filter/custom.c | 34 +++++++++++---- 7 files changed, 128 insertions(+), 68 deletions(-) diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h index aa89c7b56..94ad3aed4 100644 --- a/include/git2/sys/filter.h +++ b/include/git2/sys/filter.h @@ -125,23 +125,54 @@ GIT_EXTERN(git_filter_mode_t) git_filter_source_mode(const git_filter_source *sr * The filter lifecycle: * - initialize - first use of filter * - shutdown - filter removed/unregistered from system - * - check - considering for file - * - apply - applied to file + * - check - considering filter for file + * - apply - apply filter to file contents * - cleanup - done with file */ /** * Initialize callback on filter + * + * Specified as `filter.initialize`, this is an optional callback invoked + * before a filter is first used. It will be called once at most. + * + * If non-NULL, the filter's `initialize` callback will be invoked right + * before the first use of the filter, so you can defer expensive + * initialization operations (in case libgit2 is being used in a way that + * doesn't need the filter). */ typedef int (*git_filter_init_fn)(git_filter *self); /** * Shutdown callback on filter + * + * Specified as `filter.shutdown`, this is an optional callback invoked + * when the filter is unregistered or when libgit2 is shutting down. It + * will be called once at most and should release resources as needed. + * + * Typically this function will free the `git_filter` object itself. */ typedef void (*git_filter_shutdown_fn)(git_filter *self); /** * Callback to decide if a given source needs this filter + * + * Specified as `filter.check`, this is an optional callback that checks + * if filtering is needed for a given source. + * + * It should return 0 if the filter should be applied (i.e. success), + * GIT_PASSTHROUGH if the filter should not be applied, or an error code + * to fail out of the filter processing pipeline and return to the caller. + * + * The `attr_values` will be set to the values of any attributes given in + * the filter definition. See `git_filter` below for more detail. + * + * The `payload` will be a pointer to a reference payload for the filter. + * This will start as NULL, but `check` can assign to this pointer for + * later use by the `apply` callback. Note that the value should be heap + * allocated (not stack), so that it doesn't go away before the `apply` + * callback can use it. If a filter allocates and assigns a value to the + * `payload`, it will need a `cleanup` callback to free the payload. */ typedef int (*git_filter_check_fn)( git_filter *self, @@ -151,6 +182,15 @@ typedef int (*git_filter_check_fn)( /** * Callback to actually perform the data filtering + * + * Specified as `filter.apply`, this is the callback that actually filters + * data. If it successfully writes the output, it should return 0. Like + * `check`, it can return GIT_PASSTHROUGH to indicate that the filter + * doesn't want to run. Other error codes will stop filter processing and + * return to the caller. + * + * The `payload` value will refer to any payload that was set by the + * `check` callback. It may be read from or written to as needed. */ typedef int (*git_filter_apply_fn)( git_filter *self, @@ -161,18 +201,22 @@ typedef int (*git_filter_apply_fn)( /** * Callback to clean up after filtering has been applied + * + * Specified as `filter.cleanup`, this is an optional callback invoked + * after the filter has been applied. If the `check` or `apply` callbacks + * allocated a `payload` to keep per-source filter state, use this + * callback to free that payload and release resources as required. */ typedef void (*git_filter_cleanup_fn)( git_filter *self, void *payload); /** - * Filter structure used to register a new filter. + * Filter structure used to register custom filters. * - * To associate extra data with a filter, simply allocate extra data - * and put the `git_filter` struct at the start of your data buffer, - * then cast the `self` pointer to your larger structure when your - * callback is invoked. + * To associate extra data with a filter, allocate extra data and put the + * `git_filter` struct at the start of your data buffer, then cast the + * `self` pointer to your larger structure when your callback is invoked. * * `version` should be set to GIT_FILTER_VERSION * @@ -182,28 +226,8 @@ typedef void (*git_filter_cleanup_fn)( * a value (i.e. "name=value"), the attribute must match that value for * the filter to be applied. * - * `initialize` is an optional callback invoked before a filter is first - * used. It will be called once at most. - * - * `shutdown` is an optional callback invoked when the filter is - * unregistered or when libgit2 is shutting down. It will be called once - * at most and should free any memory as needed. - * - * `check` is an optional callback that checks if filtering is needed for - * a given source. It should return 0 if the filter should be applied - * (i.e. success), GIT_ENOTFOUND if the filter should not be applied, or - * an other error code to fail out of the filter processing pipeline and - * return to the caller. - * - * `apply` is the callback that actually filters data. If it successfully - * writes the output, it should return 0. Like `check`, it can return - * GIT_ENOTFOUND to indicate that the filter doesn't actually want to run. - * Other error codes will stop filter processing and return to the caller. - * - * `cleanup` is an optional callback that is made after the filter has - * been applied. Both the `check` and `apply` callbacks are able to - * allocate a `payload` to keep per-source filter state, and this callback - * is given that value and can clean up as needed. + * The `initialize`, `shutdown`, `check`, `apply`, and `cleanup` callbacks + * are all documented above with the respective function pointer typedefs. */ struct git_filter { unsigned int version; @@ -222,9 +246,8 @@ struct git_filter { /** * Register a filter under a given name with a given priority. * - * If non-NULL, the filter's initialize callback will be invoked before - * the first use of the filter, so you can defer expensive operations (in - * case libgit2 is being used in a way that doesn't need the filter). + * As mentioned elsewhere, the initialize callback will not be invoked + * immediately. It is deferred until the filter is used in some way. * * A filter's attribute checks and `check` and `apply` callbacks will be * issued in order of `priority` on smudge (to workdir), and in reverse @@ -237,6 +260,14 @@ struct git_filter { * Currently the filter registry is not thread safe, so any registering or * deregistering of filters must be done outside of any possible usage of * the filters (i.e. during application setup or shutdown). + * + * @param name A name by which the filter can be referenced. Attempting + * to register with an in-use name will return GIT_EEXISTS. + * @param filter The filter definition. This pointer will be stored as is + * by libgit2 so it must be a durable allocation (either static + * or on the heap). + * @param priority The priority for filter application + * @return 0 on successful registry, error code <0 on failure */ GIT_EXTERN(int) git_filter_register( const char *name, git_filter *filter, int priority); @@ -244,11 +275,15 @@ GIT_EXTERN(int) git_filter_register( /** * Remove the filter with the given name * - * It is not allowed to remove the builtin libgit2 filters. + * Attempting to remove the builtin libgit2 filters is not permitted and + * will return an error. * * Currently the filter registry is not thread safe, so any registering or * deregistering of filters must be done outside of any possible usage of * the filters (i.e. during application setup or shutdown). + * + * @param name The name under which the filter was registered + * @return 0 on success, error code <0 on failure */ GIT_EXTERN(int) git_filter_unregister(const char *name); diff --git a/src/array.h b/src/array.h index b82079bd8..d7272d78c 100644 --- a/src/array.h +++ b/src/array.h @@ -59,7 +59,7 @@ GIT_INLINE(void *) git_array_grow(void *_a, size_t item_size) #define git_array_alloc(a) \ ((a).size >= (a).asize) ? \ git_array_grow(&(a), sizeof(*(a).ptr)) : \ - (a).ptr ? &(a).ptr[(a).size++] : NULL + ((a).ptr ? &(a).ptr[(a).size++] : NULL) #define git_array_last(a) ((a).size ? &(a).ptr[(a).size - 1] : NULL) diff --git a/src/crlf.c b/src/crlf.c index 6b1fe46a3..b4eda267b 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -143,7 +143,7 @@ static int crlf_apply_to_odb( * stuff? */ if (stats.cr != stats.crlf) - return GIT_ENOTFOUND; + return GIT_PASSTHROUGH; if (ca->crlf_action == GIT_CRLF_GUESS) { /* @@ -151,11 +151,11 @@ static int crlf_apply_to_odb( * This is the new safer autocrlf handling. */ if (has_cr_in_index(src)) - return GIT_ENOTFOUND; + return GIT_PASSTHROUGH; } if (!stats.cr) - return GIT_ENOTFOUND; + return GIT_PASSTHROUGH; } /* Actually drop the carriage returns */ @@ -211,7 +211,7 @@ static int crlf_apply_to_workdir( /* Don't filter binary files */ if (git_buf_text_is_binary(from)) - return GIT_ENOTFOUND; + return GIT_PASSTHROUGH; /* Determine proper line ending */ workdir_ending = line_ending(ca); @@ -220,10 +220,10 @@ static int crlf_apply_to_workdir( if (!strcmp("\n", workdir_ending)) { if (ca->crlf_action == GIT_CRLF_GUESS && ca->auto_crlf) - return GIT_ENOTFOUND; + return GIT_PASSTHROUGH; if (git_buf_find(from, '\r') < 0) - return GIT_ENOTFOUND; + return GIT_PASSTHROUGH; if (git_buf_text_crlf_to_lf(to, from) < 0) return -1; @@ -267,7 +267,7 @@ static int crlf_check( ca.crlf_action = crlf_input_action(&ca); if (ca.crlf_action == GIT_CRLF_BINARY) - return GIT_ENOTFOUND; + return GIT_PASSTHROUGH; if (ca.crlf_action == GIT_CRLF_GUESS) { error = git_repository__cvar( @@ -276,7 +276,7 @@ static int crlf_check( return error; if (ca.auto_crlf == GIT_AUTO_CRLF_FALSE) - return GIT_ENOTFOUND; + return GIT_PASSTHROUGH; } *payload = git__malloc(sizeof(ca)); @@ -296,7 +296,7 @@ static int crlf_apply( /* initialize payload in case `check` was bypassed */ if (!*payload) { int error = crlf_check(self, payload, src, NULL); - if (error < 0 && error != GIT_ENOTFOUND) + if (error < 0 && error != GIT_PASSTHROUGH) return error; } diff --git a/src/filter.c b/src/filter.c index 378209800..503f18555 100644 --- a/src/filter.c +++ b/src/filter.c @@ -235,7 +235,7 @@ int git_filter_register( if (!filter_registry_find(NULL, name)) { giterr_set( GITERR_FILTER, "Attempt to reregister existing filter '%s'", name); - return -1; + return GIT_EEXISTS; } if (filter_def_scan_attrs(&attrs, &nattr, &nmatch, filter->attributes) < 0) @@ -270,7 +270,7 @@ int git_filter_unregister(const char *name) git_filter_def *fdef; /* cannot unregister default filters */ - if (!strcmp(GIT_FILTER_CRLF, name)) { + if (!strcmp(GIT_FILTER_CRLF, name) || !strcmp(GIT_FILTER_IDENT, name)) { giterr_set(GITERR_FILTER, "Cannot unregister filter '%s'", name); return -1; } @@ -476,7 +476,7 @@ int git_filter_list_load( git__free((void *)values); - if (error == GIT_ENOTFOUND) + if (error == GIT_PASSTHROUGH) error = 0; else if (error < 0) break; @@ -609,11 +609,13 @@ int git_filter_list_apply_to_data( error = fe->filter->apply( fe->filter, &fe->payload, dbuffer[di], dbuffer[si], &fl->source); - if (error == GIT_ENOTFOUND) + if (error == GIT_PASSTHROUGH) { + /* PASSTHROUGH means filter decided not to process the buffer */ error = 0; - else if (!error) + } else if (!error) { + git_buf_shorten(dbuffer[di], 0); /* force NUL termination */ si = di; /* swap buffers */ - else { + } else { tgt->size = 0; return error; } diff --git a/src/ident.c b/src/ident.c index 23c407f16..51630879d 100644 --- a/src/ident.c +++ b/src/ident.c @@ -13,23 +13,25 @@ static int ident_find_id( const char **id_start, const char **id_end, const char *start, size_t len) { - const char *found; + const char *end = start + len, *found = NULL; - while (len > 0 && (found = memchr(start, '$', len)) != NULL) { - size_t remaining = len - (size_t)(found - start); + while (len > 3 && (found = memchr(start, '$', len)) != NULL) { + size_t remaining = (size_t)(end - found) - 1; if (remaining < 3) return GIT_ENOTFOUND; - if (found[1] == 'I' && found[2] == 'd') - break; + start = found + 1; - len = remaining - 1; + len = remaining; + + if (start[0] == 'I' && start[1] == 'd') + break; } - if (!found || len < 3) + if (len < 3 || !found) return GIT_ENOTFOUND; *id_start = found; - if ((found = memchr(found + 3, '$', len - 3)) == NULL) + if ((found = memchr(start + 2, '$', len - 2)) == NULL) return GIT_ENOTFOUND; *id_end = found + 1; @@ -46,12 +48,12 @@ static int ident_insert_id( /* replace $Id$ with blob id */ if (!git_filter_source_id(src)) - return GIT_ENOTFOUND; + return GIT_PASSTHROUGH; git_oid_tostr(oid, sizeof(oid), git_filter_source_id(src)); if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0) - return GIT_ENOTFOUND; + return GIT_PASSTHROUGH; need_size = (size_t)(id_start - from->ptr) + 5 /* "$Id: " */ + GIT_OID_HEXSZ + 1 /* "$" */ + @@ -76,7 +78,7 @@ static int ident_remove_id( size_t need_size; if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0) - return GIT_ENOTFOUND; + return GIT_PASSTHROUGH; need_size = (size_t)(id_start - from->ptr) + 4 /* "$Id$" */ + (size_t)(from_end - id_end); @@ -102,7 +104,7 @@ static int ident_apply( /* Don't filter binary files */ if (git_buf_text_is_binary(from)) - return GIT_ENOTFOUND; + return GIT_PASSTHROUGH; if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE) return ident_insert_id(to, from, src); diff --git a/src/win32/pthread.c b/src/win32/pthread.c index 8c7ef2856..db8927471 100644 --- a/src/win32/pthread.c +++ b/src/win32/pthread.c @@ -6,6 +6,7 @@ */ #include "pthread.h" +#include "../global.h" int pthread_create( pthread_t *GIT_RESTRICT thread, diff --git a/tests-clar/filter/custom.c b/tests-clar/filter/custom.c index d6ad4b7a3..a81885c28 100644 --- a/tests-clar/filter/custom.c +++ b/tests-clar/filter/custom.c @@ -6,9 +6,11 @@ #include "git2/sys/filter.h" #include "git2/sys/repository.h" -/* picked these to be >= GIT_FILTER_DRIVER_PRIORITY */ -#define BITFLIP_FILTER_PRIORITY 200 -#define REVERSE_FILTER_PRIORITY 250 +/* going TO_WORKDIR, filters are executed low to high + * going TO_ODB, filters are executed high to low + */ +#define BITFLIP_FILTER_PRIORITY -1 +#define REVERSE_FILTER_PRIORITY -2 #define VERY_SECURE_ENCRYPTION(b) ((b) ^ 0xff) @@ -149,13 +151,13 @@ static void reverse_filter_free(git_filter *f) git__free(f); } -static git_filter *create_reverse_filter(void) +static git_filter *create_reverse_filter(const char *attrs) { git_filter *filter = git__calloc(1, sizeof(git_filter)); cl_assert(filter); filter->version = GIT_FILTER_VERSION; - filter->attributes = "+reverse"; + filter->attributes = attrs; filter->shutdown = reverse_filter_free; filter->apply = reverse_filter_apply; @@ -171,7 +173,14 @@ static void register_custom_filters(void) "bitflip", create_bitflip_filter(), BITFLIP_FILTER_PRIORITY)); cl_git_pass(git_filter_register( - "reverse", create_reverse_filter(), REVERSE_FILTER_PRIORITY)); + "reverse", create_reverse_filter("+reverse"), + REVERSE_FILTER_PRIORITY)); + + /* re-register reverse filter with standard filter=xyz priority */ + cl_git_pass(git_filter_register( + "pre-reverse", + create_reverse_filter("+prereverse"), + GIT_FILTER_DRIVER_PRIORITY)); filters_registered = 1; } @@ -273,7 +282,7 @@ void test_filter_custom__order_dependency(void) cl_git_mkfile( "empty_standard_repo/.gitattributes", - "hero.*.rev-ident text ident reverse eol=lf\n"); + "hero.*.rev-ident text ident prereverse eol=lf\n"); cl_git_mkfile( "empty_standard_repo/hero.1.rev-ident", @@ -315,3 +324,14 @@ void test_filter_custom__order_dependency(void) git_buf_free(&buf); } + +void test_filter_custom__filter_registry_failure_cases(void) +{ + git_filter fake = { GIT_FILTER_VERSION, 0 }; + + cl_assert_equal_i(GIT_EEXISTS, git_filter_register("bitflip", &fake, 0)); + + cl_git_fail(git_filter_unregister(GIT_FILTER_CRLF)); + cl_git_fail(git_filter_unregister(GIT_FILTER_IDENT)); + cl_assert_equal_i(GIT_ENOTFOUND, git_filter_unregister("not-a-filter")); +} -- cgit v1.2.1 From f60ed4e6495b8bf68d0604335672e6f300330b3b Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 16 Sep 2013 15:08:35 -0700 Subject: Update clar and recreate cl_assert_equal_sz This updates clar to the version without cl_assert_equal_sz and then adds a new version of that macro the clar_libgit2.h. The new version works around a strange issue that seemed to be arising on release builds with VS 10 64-bit builds. --- tests-clar/clar.h | 1 - tests-clar/clar_libgit2.h | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests-clar/clar.h b/tests-clar/clar.h index c40bc7ac9..e1f244eba 100644 --- a/tests-clar/clar.h +++ b/tests-clar/clar.h @@ -68,7 +68,6 @@ void cl_fixture_cleanup(const char *fixture_name); #define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2)) -#define cl_assert_equal_sz(sz1,sz2) clar__assert_equal(__FILE__,__LINE__,#sz1 " != " #sz2, 1, "%"PRIuZ, (size_t)(sz1), (size_t)(sz2)) void clar__fail( const char *file, diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index f2d9c4d0b..c37306bc4 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -43,6 +43,11 @@ GIT_INLINE(void) clar__assert_in_range( } } +#define cl_assert_equal_sz(sz1,sz2) do { \ + size_t __sz1 = (sz1), __sz2 = (sz2); \ + clar__assert_equal(__FILE__,__LINE__,#sz1 " != " #sz2, 1, "%"PRIuZ, __sz1, __sz2); \ +} while (0) + #define cl_assert_in_range(L,V,H) \ clar__assert_in_range((L),(V),(H),__FILE__,__LINE__,"Range check: " #V " in [" #L "," #H "]", 1) -- cgit v1.2.1 From 0afe9996483387d282821958974320078923306c Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 17 Sep 2013 16:46:27 -0700 Subject: Check errors from libgit2 calls --- src/blame_git.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/blame_git.c b/src/blame_git.c index 0dae2d9c1..bff36c50c 100644 --- a/src/blame_git.c +++ b/src/blame_git.c @@ -374,9 +374,9 @@ static struct origin* find_origin(struct scoreboard *sb, git_commit *parent, git_tree *otree=NULL, *ptree=NULL; /* Get the trees from this commit and its parent */ - // TODO: check errors - git_commit_tree(&otree, origin->commit); - git_commit_tree(&ptree, parent); + if (0 != git_commit_tree(&otree, origin->commit) || + 0 != git_commit_tree(&ptree, parent)) + goto cleanup; /* Configure the diff */ diffopts.context_lines = 0; @@ -385,12 +385,11 @@ static struct origin* find_origin(struct scoreboard *sb, git_commit *parent, /* Check to see if files we're interested have changed */ diffopts.pathspec.count = sb->blame->paths.length; diffopts.pathspec.strings = (char**)sb->blame->paths.contents; - // TODO: check error - git_diff_tree_to_tree(&difflist, sb->blame->repository, ptree, otree, &diffopts); + if (0 != git_diff_tree_to_tree(&difflist, sb->blame->repository, ptree, otree, &diffopts)) + goto cleanup; if (!git_diff_num_deltas(difflist)) { /* No changes; copy data */ - // TODO: check error get_origin(&porigin, sb, parent, origin->path); } else { git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; @@ -399,13 +398,13 @@ static struct origin* find_origin(struct scoreboard *sb, git_commit *parent, /* Generate a full diff between the two trees */ git_diff_list_free(difflist); diffopts.pathspec.count = 0; - // TODO: check error - git_diff_tree_to_tree(&difflist, sb->blame->repository, ptree, otree, &diffopts); + if (0 != git_diff_tree_to_tree(&difflist, sb->blame->repository, ptree, otree, &diffopts)) + goto cleanup; /* Let diff find renames */ findopts.flags = GIT_DIFF_FIND_RENAMES; - // TODO: check error - git_diff_find_similar(difflist, &findopts); + if (0 != git_diff_find_similar(difflist, &findopts)) + goto cleanup; /* Find one that matches */ for (i=0; i<(int)git_diff_num_deltas(difflist); i++) { @@ -415,16 +414,15 @@ static struct origin* find_origin(struct scoreboard *sb, git_commit *parent, continue; git_vector_insert_sorted(&sb->blame->paths, (void*)git__strdup(delta->old_file.path), paths_on_dup); - // TODO: check error make_origin(&porigin, parent, delta->old_file.path); } } +cleanup: git_diff_list_free(difflist); git_tree_free(otree); git_tree_free(ptree); return porigin; - } /* @@ -472,7 +470,6 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, uint32_t op if (sg_origin[i]) continue; - // TODO: check error git_commit_parent(&p, origin->commit, i); porigin = find_origin(sb, p, origin); -- cgit v1.2.1 From 98eb2c59e829d56cf3ae5cf93ae197ee8f4a415b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 17 Sep 2013 17:44:05 +0200 Subject: indexer: check the packfile trailer for correctness The packfile trailer gets sent over and we should check whether it's correct as part of our sanity checks of the packfile. --- src/indexer.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 17 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index 09f962934..a1eeed71d 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -47,6 +47,11 @@ struct git_indexer_stream { git_transfer_progress_callback progress_cb; void *progress_payload; char objbuf[8*1024]; + + /* Fields for calculating the packfile trailer (hash of everything before it) */ + char inbuf[GIT_OID_RAWSZ]; + int inbuf_len; + git_hash_ctx trailer; }; struct delta_info { @@ -121,6 +126,7 @@ int git_indexer_stream_new( GITERR_CHECK_ALLOC(idx); idx->progress_cb = progress_cb; idx->progress_payload = progress_payload; + git_hash_ctx_init(&idx->trailer); error = git_buf_joinpath(&path, prefix, suff); if (error < 0) @@ -322,7 +328,6 @@ static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t ent entry->offset = (uint32_t)entry_start; } - /* FIXME: Parse the object instead of hashing it */ if (git_odb__hashobj(&oid, obj) < 0) { giterr_set(GITERR_INDEXER, "Failed to hash object"); goto on_error; @@ -370,6 +375,43 @@ static int do_progress_callback(git_indexer_stream *idx, git_transfer_progress * return idx->progress_cb(stats, idx->progress_payload); } +/* Hash everything but the last 20B of input */ +static void hash_partially(git_indexer_stream *idx, const void *data, size_t size) +{ + int to_expell, to_keep; + + if (size == 0) + return; + + /* Easy case, dump the buffer and the data minus the last 20 bytes */ + if (size >= 20) { + git_hash_update(&idx->trailer, idx->inbuf, idx->inbuf_len); + git_hash_update(&idx->trailer, data, size - GIT_OID_RAWSZ); + + data += size - GIT_OID_RAWSZ; + memcpy(idx->inbuf, data, GIT_OID_RAWSZ); + idx->inbuf_len = GIT_OID_RAWSZ; + return; + } + + /* We can just append */ + if (idx->inbuf_len + size <= GIT_OID_RAWSZ) { + memcpy(idx->inbuf + idx->inbuf_len, data, size); + idx->inbuf_len += size; + return; + } + + /* We need to partially drain the buffer and then append */ + to_expell = abs(size - (GIT_OID_RAWSZ - idx->inbuf_len)); + to_keep = abs(idx->inbuf_len - to_expell); + + git_hash_update(&idx->trailer, idx->inbuf, to_expell); + + memmove(idx->inbuf, idx->inbuf + to_expell, to_keep); + memcpy(idx->inbuf + to_keep, data, size); + idx->inbuf_len += size - to_expell; +} + int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_transfer_progress *stats) { int error = -1; @@ -384,6 +426,8 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz if (git_filebuf_write(&idx->pack_file, data, size) < 0) return -1; + hash_partially(idx, data, size); + /* Make sure we set the new size of the pack */ if (idx->opened_pack) { idx->pack->mwf.size += size; @@ -576,20 +620,36 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * struct git_pack_idx_header hdr; git_buf filename = GIT_BUF_INIT; struct entry *entry; - void *packfile_hash; - git_oid file_hash; + git_oid trailer_hash, file_hash; git_hash_ctx ctx; git_filebuf index_file = {0}; + void *packfile_trailer; if (git_hash_ctx_init(&ctx) < 0) return -1; /* Test for this before resolve_deltas(), as it plays with idx->off */ - if (idx->off < idx->pack->mwf.size - GIT_OID_RAWSZ) { + if (idx->off < idx->pack->mwf.size - 20) { giterr_set(GITERR_INDEXER, "Indexing error: unexpected data at the end of the pack"); return -1; } + packfile_trailer = git_mwindow_open(&idx->pack->mwf, &w, idx->pack->mwf.size - GIT_OID_RAWSZ, GIT_OID_RAWSZ, &left); + if (packfile_trailer == NULL) { + git_mwindow_close(&w); + goto on_error; + } + + /* Compare the packfile trailer as it was sent to us and what we calculated */ + git_oid_fromraw(&file_hash, packfile_trailer); + git_mwindow_close(&w); + + git_hash_final(&trailer_hash, &idx->trailer); + if (git_oid_cmp(&file_hash, &trailer_hash)) { + giterr_set(GITERR_INDEXER, "Indexing error: packfile trailer mismatch"); + return -1; + } + if (idx->deltas.length > 0) if (resolve_deltas(idx, stats) < 0) return -1; @@ -658,23 +718,15 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * git_filebuf_write(&index_file, &split, sizeof(uint32_t) * 2); } - /* Write out the packfile trailer */ - packfile_hash = git_mwindow_open(&idx->pack->mwf, &w, idx->pack->mwf.size - GIT_OID_RAWSZ, GIT_OID_RAWSZ, &left); - if (packfile_hash == NULL) { - git_mwindow_close(&w); + /* Write out the packfile trailer to the index */ + if (git_filebuf_write(&index_file, &trailer_hash, GIT_OID_RAWSZ) < 0) goto on_error; - } - - memcpy(&file_hash, packfile_hash, GIT_OID_RAWSZ); - git_mwindow_close(&w); - - git_filebuf_write(&index_file, &file_hash, sizeof(git_oid)); - /* Write out the packfile trailer to the idx file as well */ - if (git_filebuf_hash(&file_hash, &index_file) < 0) + /* Write out the hash of the idx */ + if (git_filebuf_hash(&trailer_hash, &index_file) < 0) goto on_error; - git_filebuf_write(&index_file, &file_hash, sizeof(git_oid)); + git_filebuf_write(&index_file, &trailer_hash, sizeof(git_oid)); /* Figure out what the final name should be */ if (index_path_stream(&filename, idx, ".idx") < 0) -- cgit v1.2.1 From e0aa6fc136c2e92b18ce1874e4bf5ec2e44ea928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 18 Sep 2013 02:20:17 +0200 Subject: indexer: don't reiterate the class in the message --- src/indexer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index a1eeed71d..aaaf093d1 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -630,7 +630,7 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * /* Test for this before resolve_deltas(), as it plays with idx->off */ if (idx->off < idx->pack->mwf.size - 20) { - giterr_set(GITERR_INDEXER, "Indexing error: unexpected data at the end of the pack"); + giterr_set(GITERR_INDEXER, "unexpected data at the end of the pack"); return -1; } @@ -646,7 +646,7 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * git_hash_final(&trailer_hash, &idx->trailer); if (git_oid_cmp(&file_hash, &trailer_hash)) { - giterr_set(GITERR_INDEXER, "Indexing error: packfile trailer mismatch"); + giterr_set(GITERR_INDEXER, "packfile trailer mismatch"); return -1; } @@ -655,7 +655,7 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * return -1; if (stats->indexed_objects != stats->total_objects) { - giterr_set(GITERR_INDEXER, "Indexing error: early EOF"); + giterr_set(GITERR_INDEXER, "early EOF"); return -1; } -- cgit v1.2.1 From 5a284edca42dd75cf62b3fe75020819fcfcea9f3 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 18 Sep 2013 03:54:17 +0200 Subject: msvc: No void* arithmetic on Windows --- src/indexer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/indexer.c b/src/indexer.c index aaaf093d1..ceb11f0b6 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -376,7 +376,7 @@ static int do_progress_callback(git_indexer_stream *idx, git_transfer_progress * } /* Hash everything but the last 20B of input */ -static void hash_partially(git_indexer_stream *idx, const void *data, size_t size) +static void hash_partially(git_indexer_stream *idx, const uint8_t *data, size_t size) { int to_expell, to_keep; -- cgit v1.2.1 From 0cd1c3bb066f67ac21f1ce8730eaefc5541c1082 Mon Sep 17 00:00:00 2001 From: Linquize Date: Wed, 18 Sep 2013 23:06:10 +0800 Subject: Make init.templatedir work --- src/repository.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/repository.c b/src/repository.c index d1b7d9131..b95ee8548 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1132,44 +1132,39 @@ static int repo_init_structure( /* Copy external template if requested */ if (external_tpl) { - git_config *cfg; - const char *tdir; + git_config *cfg = NULL; + const char *tdir = NULL; + bool default_template = false; git_buf template_buf = GIT_BUF_INIT; - git_futils_find_template_dir(&template_buf); - if (opts->template_path) tdir = opts->template_path; - else if ((error = git_config_open_default(&cfg)) < 0) - return error; - else { + else if ((error = git_config_open_default(&cfg)) >= 0) { error = git_config_get_string(&tdir, cfg, "init.templatedir"); - - git_config_free(cfg); - - if (error && error != GIT_ENOTFOUND) - return error; - giterr_clear(); + } + + if (!tdir) { + git_futils_find_template_dir(&template_buf); tdir = template_buf.ptr; + default_template = true; } error = git_futils_cp_r(tdir, repo_dir, GIT_CPDIR_COPY_SYMLINKS | GIT_CPDIR_CHMOD_DIRS | GIT_CPDIR_SIMPLE_TO_MODE, dmode); + git_buf_free(&template_buf); + git_config_free(cfg); if (error < 0) { - if (strcmp(tdir, template_buf.ptr) != 0) { - git_buf_free(&template_buf); + if (!default_template) return error; - } /* if template was default, ignore error and use internal */ giterr_clear(); external_tpl = false; error = 0; } - git_buf_free(&template_buf); } /* Copy internal template -- cgit v1.2.1 From 66566516ce5171111ea4c5a8160adb4b0b0dc675 Mon Sep 17 00:00:00 2001 From: Linquize Date: Sun, 8 Sep 2013 17:15:42 +0800 Subject: Fix warning --- include/git2/index.h | 2 +- src/attr_file.c | 2 +- src/buffer.c | 2 +- src/config_file.c | 4 ++-- src/diff.c | 3 ++- src/index.c | 10 +++++----- src/odb.c | 3 +-- src/oid.c | 2 +- src/remote.c | 4 ++-- src/transports/winhttp.c | 4 ++-- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/git2/index.h b/include/git2/index.h index b44535601..ba0bcc984 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -219,7 +219,7 @@ GIT_EXTERN(unsigned int) git_index_caps(const git_index *index); * @param caps A combination of GIT_INDEXCAP values * @return 0 on success, -1 on failure */ -GIT_EXTERN(int) git_index_set_caps(git_index *index, unsigned int caps); +GIT_EXTERN(int) git_index_set_caps(git_index *index, int caps); /** * Update the contents of an existing index object in memory diff --git a/src/attr_file.c b/src/attr_file.c index 92702df98..4eb732436 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -39,7 +39,7 @@ int git_attr_file__new( attrs->key = git_pool_malloc(attrs->pool, (uint32_t)len + 3); GITERR_CHECK_ALLOC(attrs->key); - attrs->key[0] = '0' + from; + attrs->key[0] = '0' + (char)from; attrs->key[1] = '#'; memcpy(&attrs->key[2], path, len); attrs->key[len + 2] = '\0'; diff --git a/src/buffer.c b/src/buffer.c index b5b2fd678..483ce4882 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -137,7 +137,7 @@ int git_buf_puts(git_buf *buf, const char *string) return git_buf_put(buf, string, strlen(string)); } -static const char b64str[64] = +static const char b64str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int git_buf_put_base64(git_buf *buf, const char *data, size_t len) diff --git a/src/config_file.c b/src/config_file.c index efc9df965..9087bfa56 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -125,7 +125,7 @@ int git_config_file_normalize_section(char *start, char *end) if (end && scan >= end) break; if (isalnum(*scan)) - *scan = tolower(*scan); + *scan = (char)tolower(*scan); else if (*scan != '-' || scan == start) return GIT_EINVALIDSPEC; } @@ -737,7 +737,7 @@ static int parse_section_header_ext(diskfile_backend *cfg, const char *line, con break; } - git_buf_putc(&buf, c); + git_buf_putc(&buf, (char)c); } while ((c = line[rpos++]) != ']'); *section_name = git_buf_detach(&buf); diff --git a/src/diff.c b/src/diff.c index 77dbbd8bc..28f5f93e3 100644 --- a/src/diff.c +++ b/src/diff.c @@ -440,7 +440,8 @@ static int diff_list_apply_options( /* If not given explicit `opts`, check `diff.xyz` configs */ if (!opts) { - diff->opts.context_lines = config_int(cfg, "diff.context", 3); + int context = config_int(cfg, "diff.context", 3); + diff->opts.context_lines = context >= 0 ? (uint16_t)context : 3; /* add other defaults here */ } diff --git a/src/index.c b/src/index.c index 9b32222a7..b4f2a3b6b 100644 --- a/src/index.c +++ b/src/index.c @@ -408,9 +408,9 @@ static int create_index_error(int error, const char *msg) return error; } -int git_index_set_caps(git_index *index, unsigned int caps) +int git_index_set_caps(git_index *index, int caps) { - int old_ignore_case; + unsigned int old_ignore_case; assert(index); @@ -438,7 +438,7 @@ int git_index_set_caps(git_index *index, unsigned int caps) } if (old_ignore_case != index->ignore_case) { - git_index__set_ignore_case(index, index->ignore_case); + git_index__set_ignore_case(index, (bool)index->ignore_case); } return 0; @@ -2092,7 +2092,7 @@ int git_index_add_all( /* check if path actually matches */ if (!git_pathspec__match( - &ps.pathspec, wd->path, no_fnmatch, ignorecase, &match, NULL)) + &ps.pathspec, wd->path, no_fnmatch, (bool)ignorecase, &match, NULL)) continue; /* skip ignored items that are not already in the index */ @@ -2184,7 +2184,7 @@ static int index_apply_to_all( /* check if path actually matches */ if (!git_pathspec__match( - &ps.pathspec, entry->path, false, index->ignore_case, + &ps.pathspec, entry->path, false, (bool)index->ignore_case, &match, NULL)) continue; diff --git a/src/odb.c b/src/odb.c index dfb252178..d2d92cb77 100644 --- a/src/odb.c +++ b/src/odb.c @@ -168,7 +168,6 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type) error = -1; goto done; - return -1; } error = git_hash_final(out, &ctx); @@ -621,7 +620,7 @@ int git_odb_exists(git_odb *db, const git_oid *id) git_odb_backend *b = internal->backend; if (b->exists != NULL) - found = b->exists(b, id); + found = (bool)b->exists(b, id); } return (int)found; diff --git a/src/oid.c b/src/oid.c index a70b7e099..d56b6af24 100644 --- a/src/oid.c +++ b/src/oid.c @@ -211,7 +211,7 @@ int git_oid_strcmp(const git_oid *oid_a, const char *str) for (a = oid_a->id; *str && (a - oid_a->id) < GIT_OID_RAWSZ; ++a) { if ((hexval = git__fromhex(*str++)) < 0) return -1; - strval = hexval << 4; + strval = (unsigned char)(hexval << 4); if (*str) { if ((hexval = git__fromhex(*str++)) < 0) return -1; diff --git a/src/remote.c b/src/remote.c index bdc8e0e67..e4452513a 100644 --- a/src/remote.c +++ b/src/remote.c @@ -362,7 +362,7 @@ cleanup: static int update_config_refspec(const git_remote *remote, git_config *config, int direction) { git_buf name = GIT_BUF_INIT; - int push; + unsigned int push; const char *dir; size_t i; int error = 0; @@ -1549,7 +1549,7 @@ int git_remote_add_push(git_remote *remote, const char *refspec) return add_refspec(remote, refspec, false); } -static int copy_refspecs(git_strarray *array, git_remote *remote, int push) +static int copy_refspecs(git_strarray *array, git_remote *remote, unsigned int push) { size_t i; git_vector refspecs; diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 29d4ba619..592460f2a 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -195,7 +195,7 @@ static int winhttp_stream_connect(winhttp_stream *s) } /* Set proxy if necessary */ - if (git_remote__get_http_proxy(t->owner->owner, t->use_ssl, &proxy_url) < 0) + if (git_remote__get_http_proxy(t->owner->owner, !!t->use_ssl, &proxy_url) < 0) goto on_error; if (proxy_url) { @@ -939,7 +939,7 @@ static int winhttp_connect( t->connection = WinHttpConnect( t->session, host, - port, + (INTERNET_PORT)port, 0); if (!t->connection) { -- cgit v1.2.1 From 3e0cf2a18057af11e7d8ba43bb43c4b399f89a27 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 19 Sep 2013 10:27:37 -0700 Subject: Stop being crazy about freeing memory --- src/blame.c | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/src/blame.c b/src/blame.c index 30d65f02c..33477d619 100644 --- a/src/blame.c +++ b/src/blame.c @@ -246,21 +246,6 @@ static git_blame_hunk* hunk_from_entry(struct blame_entry *e) return h; } -static void free_if_not_already_freed(git_vector *already, struct origin *o) -{ - size_t i; - - if (!o) return; - if (!git_vector_search(&i, already, o)) - return; - - git_vector_insert(already, o); - free_if_not_already_freed(already, o->previous); - git_blob_free(o->blob); - git_commit_free(o->commit); - git__free(o); -} - static int walk_and_mark(git_blame *blame) { int error; @@ -269,7 +254,6 @@ static int walk_and_mark(git_blame *blame) struct blame_entry *ent = NULL; git_blob *blob = NULL; struct origin *o; - git_vector already = GIT_VECTOR_INIT; if ((error = git_commit_lookup(&sb.final, blame->repository, &blame->options.newest_commit)) < 0 || (error = git_object_lookup_bypath((git_object**)&blob, (git_object*)sb.final, blame->path, GIT_OBJ_BLOB)) < 0) @@ -289,26 +273,18 @@ static int walk_and_mark(git_blame *blame) assign_blame(&sb, blame->options.flags); coalesce(&sb); - for (ent = sb.ent; ent; ) { - git_vector_insert(&blame->hunks, hunk_from_entry(ent)); - ent = ent->next; - } - cleanup: for (ent = sb.ent; ent; ) { struct blame_entry *e = ent->next; struct origin *o = ent->suspect; - /* Linkages might not be ordered, so we only free pointers we haven't - * seen before. */ - free_if_not_already_freed(&already, o); + git_vector_insert(&blame->hunks, hunk_from_entry(ent)); + origin_decref(o); git__free(ent); ent = e; } - git_vector_free(&already); - git_commit_free(sb.final); git_blob_free(blob); return error; } -- cgit v1.2.1 From 32b247d5e78135e8fbaf4c0b612532995201a3a2 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 19 Sep 2013 10:30:43 -0700 Subject: Suppress noise from running Valgrind on OSX 10.8 --- tests-clar/valgrind-supp-mac.txt | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests-clar/valgrind-supp-mac.txt b/tests-clar/valgrind-supp-mac.txt index fcc7ede86..99833d091 100644 --- a/tests-clar/valgrind-supp-mac.txt +++ b/tests-clar/valgrind-supp-mac.txt @@ -154,3 +154,31 @@ fun:printf fun:clar_print_init } +{ + molo-1 + Memcheck:Leak + fun:malloc_zone_malloc + ... + fun:_objc_init +} +{ + molo-2 + Memcheck:Leak + fun:malloc_zone_calloc + ... + fun:_objc_init +} +{ + molo-3 + Memcheck:Leak + fun:malloc + ... + fun:_objc_init +} +{ + molo-4 + Memcheck:Leak + fun:malloc + ... + fun:dyld_register_image_state_change_handler +} -- cgit v1.2.1 From d1228f1c8711edcb7f5fbb3a31c9018b57021ca6 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 19 Sep 2013 14:18:51 -0700 Subject: blame: allow restriction to line range --- src/blame.c | 11 ++++++++ tests-clar/blame/simple.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/blame.c b/src/blame.c index 33477d619..a4ac84fde 100644 --- a/src/blame.c +++ b/src/blame.c @@ -179,6 +179,10 @@ static void normalize_options( if (git_oid_iszero(&out->newest_commit)) { git_reference_name_to_id(&out->newest_commit, repo, "HEAD"); } + + /* min_line 0 really means 1 */ + if (!out->min_line) out->min_line = 1; + /* max_line 0 really means N, but we don't know N yet */ } static git_blame_hunk *split_hunk_in_vector( @@ -265,7 +269,14 @@ static int walk_and_mark(git_blame *blame) ent = git__calloc(1, sizeof(*ent)); ent->num_lines = prepare_lines(&sb); + ent->lno = blame->options.min_line - 1; + ent->num_lines = ent->num_lines - blame->options.min_line + 1; + if (blame->options.max_line > 0) { + ent->num_lines = blame->options.max_line - blame->options.min_line + 1; + } + ent->s_lno = ent->lno; ent->suspect = o; + sb.ent = ent; sb.path = blame->path; sb.blame = blame; diff --git a/tests-clar/blame/simple.c b/tests-clar/blame/simple.c index 4e2d88653..1de4a51d0 100644 --- a/tests-clar/blame/simple.c +++ b/tests-clar/blame/simple.c @@ -201,4 +201,72 @@ void test_blame_simple__trivial_libgit2(void) git_repository_free(repo); } + +/* + * $ git blame -n b.txt -L 8 + * orig line no final line no + * commit V author timestamp V + * 63d671eb 8 (Ben Straub 2013-02-12 15:13:04 -0800 8 + * 63d671eb 9 (Ben Straub 2013-02-12 15:13:04 -0800 9 + * 63d671eb 10 (Ben Straub 2013-02-12 15:13:04 -0800 10 + * aa06ecca 6 (Ben Straub 2013-02-12 15:14:46 -0800 11 + * aa06ecca 7 (Ben Straub 2013-02-12 15:14:46 -0800 12 + * aa06ecca 8 (Ben Straub 2013-02-12 15:14:46 -0800 13 + * aa06ecca 9 (Ben Straub 2013-02-12 15:14:46 -0800 14 + * aa06ecca 10 (Ben Straub 2013-02-12 15:14:46 -0800 15 + * + * $ git blame -n b.txt -L ,6 + * orig line no final line no + * commit V author timestamp V + * da237394 1 (Ben Straub 2013-02-12 15:11:30 -0800 1 + * da237394 2 (Ben Straub 2013-02-12 15:11:30 -0800 2 + * da237394 3 (Ben Straub 2013-02-12 15:11:30 -0800 3 + * da237394 4 (Ben Straub 2013-02-12 15:11:30 -0800 4 + * ^b99f7ac 1 (Ben Straub 2013-02-12 15:10:12 -0800 5 + * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 + * + * $ git blame -n b.txt -L 2,7 + * orig line no final line no + * commit V author timestamp V + * da237394 2 (Ben Straub 2013-02-12 15:11:30 -0800 2 + * da237394 3 (Ben Straub 2013-02-12 15:11:30 -0800 3 + * da237394 4 (Ben Straub 2013-02-12 15:11:30 -0800 4 + * ^b99f7ac 1 (Ben Straub 2013-02-12 15:10:12 -0800 5 + * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 + * 63d671eb 7 (Ben Straub 2013-02-12 15:13:04 -0800 7 + */ +void test_blame_simple__can_restrict_to_lines(void) +{ + git_blame *blame = NULL; + git_repository *repo; + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + cl_git_pass(git_repository_open(&repo, cl_fixture("blametest.git"))); + + opts.min_line = 8; + cl_git_pass(git_blame_file(&blame, repo, "b.txt", &opts)); + cl_assert_equal_i(2, git_blame_get_hunk_count(blame)); + check_blame_hunk_index(repo, blame, 0, 8, 3, "63d671eb", "b.txt"); + check_blame_hunk_index(repo, blame, 1, 11, 5, "aa06ecca", "b.txt"); + + opts.min_line = 0; + opts.max_line = 6; + cl_git_pass(git_blame_file(&blame, repo, "b.txt", &opts)); + cl_assert_equal_i(3, git_blame_get_hunk_count(blame)); + check_blame_hunk_index(repo, blame, 0, 1, 4, "da237394", "b.txt"); + check_blame_hunk_index(repo, blame, 1, 5, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(repo, blame, 2, 6, 1, "63d671eb", "b.txt"); + + opts.min_line = 2; + opts.max_line = 7; + cl_git_pass(git_blame_file(&blame, repo, "b.txt", &opts)); + cl_assert_equal_i(3, git_blame_get_hunk_count(blame)); + check_blame_hunk_index(repo, blame, 0, 2, 3, "da237394", "b.txt"); + check_blame_hunk_index(repo, blame, 1, 5, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(repo, blame, 2, 6, 2, "63d671eb", "b.txt"); + + git_blame_free(blame); + git_repository_free(repo); +} + /* TODO: no newline at end of file? */ -- cgit v1.2.1 From 9d42fcbef349c101d12410d62cda7ee9f23bdf8f Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 19 Sep 2013 14:27:44 -0700 Subject: Blame: fixturize tests --- tests-clar/blame/simple.c | 236 +++++++++++++++++++++++++--------------------- 1 file changed, 126 insertions(+), 110 deletions(-) diff --git a/tests-clar/blame/simple.c b/tests-clar/blame/simple.c index 1de4a51d0..ad5cf8fb4 100644 --- a/tests-clar/blame/simple.c +++ b/tests-clar/blame/simple.c @@ -1,5 +1,20 @@ #include "blame_helpers.h" +static git_repository *g_repo; +static git_blame *g_blame; + +void test_blame_simple__initialize(void) +{ + g_repo = NULL; + g_blame = NULL; +} + +void test_blame_simple__cleanup(void) +{ + git_blame_free(g_blame); + git_repository_free(g_repo); +} + /* * $ git blame -s branch_file.txt * orig line no final line no @@ -9,17 +24,12 @@ */ void test_blame_simple__trivial_testrepo(void) { - git_blame *blame = NULL; - git_repository *repo; - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo/.gitted"))); - cl_git_pass(git_blame_file(&blame, repo, "branch_file.txt", NULL)); - - cl_assert_equal_i(2, git_blame_get_hunk_count(blame)); - check_blame_hunk_index(repo, blame, 0, 1, 1, "c47800c7", "branch_file.txt"); - check_blame_hunk_index(repo, blame, 1, 2, 1, "a65fedf3", "branch_file.txt"); + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo/.gitted"))); + cl_git_pass(git_blame_file(&g_blame, g_repo, "branch_file.txt", NULL)); - git_blame_free(blame); - git_repository_free(repo); + cl_assert_equal_i(2, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, "c47800c7", "branch_file.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, "a65fedf3", "branch_file.txt"); } /* @@ -44,19 +54,14 @@ void test_blame_simple__trivial_testrepo(void) */ void test_blame_simple__trivial_blamerepo(void) { - git_blame *blame = NULL; - git_repository *repo; - cl_git_pass(git_repository_open(&repo, cl_fixture("blametest.git"))); - cl_git_pass(git_blame_file(&blame, repo, "b.txt", NULL)); + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); + cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", NULL)); - cl_assert_equal_i(4, git_blame_get_hunk_count(blame)); - check_blame_hunk_index(repo, blame, 0, 1, 4, "da237394", "b.txt"); - check_blame_hunk_index(repo, blame, 1, 5, 1, "b99f7ac0", "b.txt"); - check_blame_hunk_index(repo, blame, 2, 6, 5, "63d671eb", "b.txt"); - check_blame_hunk_index(repo, blame, 3, 11, 5, "aa06ecca", "b.txt"); - - git_blame_free(blame); - git_repository_free(repo); + cl_assert_equal_i(4, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, "da237394", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 2, 6, 5, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 3, 11, 5, "aa06ecca", "b.txt"); } @@ -127,78 +132,71 @@ void test_blame_simple__trivial_blamerepo(void) */ void test_blame_simple__trivial_libgit2(void) { - git_repository *repo; - git_blame *blame; git_blame_options opts = GIT_BLAME_OPTIONS_INIT; git_object *obj; - cl_git_pass(git_repository_open(&repo, cl_fixture("../.."))); + cl_git_pass(git_repository_open(&g_repo, cl_fixture("../.."))); /* This test can't work on a shallow clone */ - if (git_repository_is_shallow(repo)) { - git_repository_free(repo); + if (git_repository_is_shallow(g_repo)) return; - } - cl_git_pass(git_revparse_single(&obj, repo, "359fc2d")); + cl_git_pass(git_revparse_single(&obj, g_repo, "359fc2d")); git_oid_cpy(&opts.newest_commit, git_object_id(obj)); git_object_free(obj); - cl_git_pass(git_blame_file(&blame, repo, "include/git2.h", &opts)); - - check_blame_hunk_index(repo, blame, 0, 1, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(repo, blame, 1, 2, 1, "359fc2d2", "include/git2.h"); - check_blame_hunk_index(repo, blame, 2, 3, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(repo, blame, 3, 4, 2, "bb742ede", "include/git2.h"); - check_blame_hunk_index(repo, blame, 4, 6, 5, "d12299fe", "src/git.h"); - check_blame_hunk_index(repo, blame, 5, 11, 1, "96fab093", "include/git2.h"); - check_blame_hunk_index(repo, blame, 6, 12, 1, "9d1dcca2", "src/git2.h"); - check_blame_hunk_index(repo, blame, 7, 13, 1, "44908fe7", "src/git2.h"); - check_blame_hunk_index(repo, blame, 8, 14, 1, "a15c550d", "include/git2.h"); - check_blame_hunk_index(repo, blame, 9, 15, 1, "44908fe7", "src/git2.h"); - check_blame_hunk_index(repo, blame, 10, 16, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(repo, blame, 11, 17, 1, "44908fe7", "src/git2.h"); - check_blame_hunk_index(repo, blame, 12, 18, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(repo, blame, 13, 19, 1, "44908fe7", "src/git2.h"); - check_blame_hunk_index(repo, blame, 14, 20, 1, "638c2ca4", "src/git2.h"); - check_blame_hunk_index(repo, blame, 15, 21, 1, "44908fe7", "src/git2.h"); - check_blame_hunk_index(repo, blame, 16, 22, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(repo, blame, 17, 23, 2, "44908fe7", "src/git2.h"); - check_blame_hunk_index(repo, blame, 18, 25, 1, "bf787bd8", "include/git2.h"); - check_blame_hunk_index(repo, blame, 19, 26, 1, "0984c876", "include/git2.h"); - check_blame_hunk_index(repo, blame, 20, 27, 1, "2f8a8ab2", "src/git2.h"); - check_blame_hunk_index(repo, blame, 21, 28, 1, "27df4275", "include/git2.h"); - check_blame_hunk_index(repo, blame, 22, 29, 1, "a346992f", "include/git2.h"); - check_blame_hunk_index(repo, blame, 23, 30, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(repo, blame, 24, 31, 5, "44908fe7", "src/git2.h"); - check_blame_hunk_index(repo, blame, 25, 36, 1, "65b09b1d", "include/git2.h"); - check_blame_hunk_index(repo, blame, 26, 37, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(repo, blame, 27, 38, 1, "44908fe7", "src/git2.h"); - check_blame_hunk_index(repo, blame, 28, 39, 1, "5d4cd003", "include/git2.h"); - check_blame_hunk_index(repo, blame, 29, 40, 1, "41fb1ca0", "include/git2.h"); - check_blame_hunk_index(repo, blame, 30, 41, 1, "2dc31040", "include/git2.h"); - check_blame_hunk_index(repo, blame, 31, 42, 1, "764df57e", "include/git2.h"); - check_blame_hunk_index(repo, blame, 32, 43, 1, "5280f4e6", "include/git2.h"); - check_blame_hunk_index(repo, blame, 33, 44, 1, "613d5eb9", "include/git2.h"); - check_blame_hunk_index(repo, blame, 34, 45, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(repo, blame, 35, 46, 1, "111ee3fe", "include/git2.h"); - check_blame_hunk_index(repo, blame, 36, 47, 1, "f004c4a8", "include/git2.h"); - check_blame_hunk_index(repo, blame, 37, 48, 1, "111ee3fe", "include/git2.h"); - check_blame_hunk_index(repo, blame, 38, 49, 1, "9c82357b", "include/git2.h"); - check_blame_hunk_index(repo, blame, 39, 50, 1, "d6258deb", "include/git2.h"); - check_blame_hunk_index(repo, blame, 40, 51, 1, "b311e313", "include/git2.h"); - check_blame_hunk_index(repo, blame, 41, 52, 1, "3412391d", "include/git2.h"); - check_blame_hunk_index(repo, blame, 42, 53, 1, "bfc9ca59", "include/git2.h"); - check_blame_hunk_index(repo, blame, 43, 54, 1, "bf477ed4", "include/git2.h"); - check_blame_hunk_index(repo, blame, 44, 55, 1, "edebceff", "include/git2.h"); - check_blame_hunk_index(repo, blame, 45, 56, 1, "743a4b3b", "include/git2.h"); - check_blame_hunk_index(repo, blame, 46, 57, 1, "0a32dca5", "include/git2.h"); - check_blame_hunk_index(repo, blame, 47, 58, 1, "590fb68b", "include/git2.h"); - check_blame_hunk_index(repo, blame, 48, 59, 1, "bf477ed4", "include/git2.h"); - check_blame_hunk_index(repo, blame, 49, 60, 1, "d12299fe", "src/git.h"); + cl_git_pass(git_blame_file(&g_blame, g_repo, "include/git2.h", &opts)); - git_blame_free(blame); - git_repository_free(repo); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, "359fc2d2", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 2, 3, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 3, 4, 2, "bb742ede", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 4, 6, 5, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 5, 11, 1, "96fab093", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 6, 12, 1, "9d1dcca2", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 7, 13, 1, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 8, 14, 1, "a15c550d", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 9, 15, 1, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 10, 16, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 11, 17, 1, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 12, 18, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 13, 19, 1, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 14, 20, 1, "638c2ca4", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 15, 21, 1, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 16, 22, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 17, 23, 2, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 18, 25, 1, "bf787bd8", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 19, 26, 1, "0984c876", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 20, 27, 1, "2f8a8ab2", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 21, 28, 1, "27df4275", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 22, 29, 1, "a346992f", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 23, 30, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 24, 31, 5, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 25, 36, 1, "65b09b1d", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 26, 37, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 27, 38, 1, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 28, 39, 1, "5d4cd003", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 29, 40, 1, "41fb1ca0", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 30, 41, 1, "2dc31040", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 31, 42, 1, "764df57e", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 32, 43, 1, "5280f4e6", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 33, 44, 1, "613d5eb9", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 34, 45, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 35, 46, 1, "111ee3fe", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 36, 47, 1, "f004c4a8", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 37, 48, 1, "111ee3fe", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 38, 49, 1, "9c82357b", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 39, 50, 1, "d6258deb", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 40, 51, 1, "b311e313", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 41, 52, 1, "3412391d", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 42, 53, 1, "bfc9ca59", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 43, 54, 1, "bf477ed4", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 44, 55, 1, "edebceff", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 45, 56, 1, "743a4b3b", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 46, 57, 1, "0a32dca5", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 47, 58, 1, "590fb68b", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 48, 59, 1, "bf477ed4", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 49, 60, 1, "d12299fe", "src/git.h"); } @@ -214,7 +212,21 @@ void test_blame_simple__trivial_libgit2(void) * aa06ecca 8 (Ben Straub 2013-02-12 15:14:46 -0800 13 * aa06ecca 9 (Ben Straub 2013-02-12 15:14:46 -0800 14 * aa06ecca 10 (Ben Straub 2013-02-12 15:14:46 -0800 15 - * + */ +void test_blame_simple__can_restrict_lines_min(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); + + opts.min_line = 8; + cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); + cl_assert_equal_i(2, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 8, 3, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 11, 5, "aa06ecca", "b.txt"); +} + +/* * $ git blame -n b.txt -L ,6 * orig line no final line no * commit V author timestamp V @@ -235,38 +247,42 @@ void test_blame_simple__trivial_libgit2(void) * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 * 63d671eb 7 (Ben Straub 2013-02-12 15:13:04 -0800 7 */ -void test_blame_simple__can_restrict_to_lines(void) +void test_blame_simple__can_restrict_lines_max(void) { - git_blame *blame = NULL; - git_repository *repo; git_blame_options opts = GIT_BLAME_OPTIONS_INIT; - cl_git_pass(git_repository_open(&repo, cl_fixture("blametest.git"))); + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); - opts.min_line = 8; - cl_git_pass(git_blame_file(&blame, repo, "b.txt", &opts)); - cl_assert_equal_i(2, git_blame_get_hunk_count(blame)); - check_blame_hunk_index(repo, blame, 0, 8, 3, "63d671eb", "b.txt"); - check_blame_hunk_index(repo, blame, 1, 11, 5, "aa06ecca", "b.txt"); - - opts.min_line = 0; opts.max_line = 6; - cl_git_pass(git_blame_file(&blame, repo, "b.txt", &opts)); - cl_assert_equal_i(3, git_blame_get_hunk_count(blame)); - check_blame_hunk_index(repo, blame, 0, 1, 4, "da237394", "b.txt"); - check_blame_hunk_index(repo, blame, 1, 5, 1, "b99f7ac0", "b.txt"); - check_blame_hunk_index(repo, blame, 2, 6, 1, "63d671eb", "b.txt"); + cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); + cl_assert_equal_i(3, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, "da237394", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 2, 6, 1, "63d671eb", "b.txt"); +} + +/* + * $ git blame -n b.txt -L 2,7 + * orig line no final line no + * commit V author timestamp V + * da237394 2 (Ben Straub 2013-02-12 15:11:30 -0800 2 + * da237394 3 (Ben Straub 2013-02-12 15:11:30 -0800 3 + * da237394 4 (Ben Straub 2013-02-12 15:11:30 -0800 4 + * ^b99f7ac 1 (Ben Straub 2013-02-12 15:10:12 -0800 5 + * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 + * 63d671eb 7 (Ben Straub 2013-02-12 15:13:04 -0800 7 + */ +void test_blame_simple__can_restrict_lines_both(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); opts.min_line = 2; opts.max_line = 7; - cl_git_pass(git_blame_file(&blame, repo, "b.txt", &opts)); - cl_assert_equal_i(3, git_blame_get_hunk_count(blame)); - check_blame_hunk_index(repo, blame, 0, 2, 3, "da237394", "b.txt"); - check_blame_hunk_index(repo, blame, 1, 5, 1, "b99f7ac0", "b.txt"); - check_blame_hunk_index(repo, blame, 2, 6, 2, "63d671eb", "b.txt"); - - git_blame_free(blame); - git_repository_free(repo); + cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); + cl_assert_equal_i(3, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 2, 3, "da237394", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 2, 6, 2, "63d671eb", "b.txt"); } - -/* TODO: no newline at end of file? */ -- cgit v1.2.1 From 417472e317a8680123f2fa4f46e1e3c21315326d Mon Sep 17 00:00:00 2001 From: Linquize Date: Fri, 20 Sep 2013 09:02:58 +0800 Subject: Check error value from git_futils_find_template_dir --- src/repository.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/repository.c b/src/repository.c index b95ee8548..6dea48790 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1145,8 +1145,8 @@ static int repo_init_structure( } if (!tdir) { - git_futils_find_template_dir(&template_buf); - tdir = template_buf.ptr; + if ((error = git_futils_find_template_dir(&template_buf)) >= 0); + tdir = template_buf.ptr; default_template = true; } -- cgit v1.2.1 From 25c47aaee2c36d78a11dcddf066b82abb53819b9 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 20 Sep 2013 14:31:51 -0700 Subject: Detect boundaries, support limiting commit range --- include/git2/blame.h | 4 + src/blame.c | 1 + src/blame_git.c | 15 +++- src/blame_git.h | 4 + tests-clar/blame/blame_helpers.c | 8 +- tests-clar/blame/blame_helpers.h | 1 + tests-clar/blame/buffer.c | 24 +++--- tests-clar/blame/simple.c | 165 +++++++++++++++++++++------------------ 8 files changed, 132 insertions(+), 90 deletions(-) diff --git a/include/git2/blame.h b/include/git2/blame.h index fe1311362..652bc8180 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -93,6 +93,8 @@ typedef struct git_blame_options { * - `orig_start_line_number` is the 1-based line number where this hunk begins * in the file named by `orig_path` in the commit specified by * `orig_commit_id`. + * - `boundary` is 1 iff the hunk has been tracked to a boundary commit (the + * root, or the commit specified in git_blame_options.oldest_commit) */ typedef struct git_blame_hunk { uint16_t lines_in_hunk; @@ -103,6 +105,8 @@ typedef struct git_blame_hunk { git_oid orig_commit_id; const char *orig_path; uint16_t orig_start_line_number; + + char boundary; } git_blame_hunk; diff --git a/src/blame.c b/src/blame.c index a4ac84fde..b7886aa5c 100644 --- a/src/blame.c +++ b/src/blame.c @@ -247,6 +247,7 @@ static git_blame_hunk* hunk_from_entry(struct blame_entry *e) git_blame_hunk *h = new_hunk( e->lno+1, e->num_lines, e->s_lno+1, e->suspect->path); git_oid_cpy(&h->final_commit_id, git_commit_id(e->suspect->commit)); + h->boundary = e->is_boundary ? 1 : 0; return h; } diff --git a/src/blame_git.c b/src/blame_git.c index bff36c50c..02628c4ba 100644 --- a/src/blame_git.c +++ b/src/blame_git.c @@ -456,8 +456,12 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, uint32_t op GIT_UNUSED(opt); num_sg = git_commit_parentcount(commit); - if (!num_sg) + if (!git_oid_cmp(git_commit_id(commit), &sb->blame->options.oldest_commit)) + num_sg = 0; + if (!num_sg) { + git_oid_cpy(&sb->blame->options.oldest_commit, git_commit_id(commit)); goto finish; + } else if (num_sg < (int)ARRAY_SIZE(sg_buf)) memset(sg_buf, 0, sizeof(sg_buf)); else @@ -558,9 +562,14 @@ void assign_blame(struct scoreboard *sb, uint32_t opt) pass_blame(sb, suspect, opt); /* Take responsibility for the remaining entries */ - for (ent = sb->ent; ent; ent = ent->next) - if (same_suspect(ent->suspect, suspect)) + for (ent = sb->ent; ent; ent = ent->next) { + if (same_suspect(ent->suspect, suspect)) { ent->guilty = 1; + ent->is_boundary = !git_oid_cmp( + git_commit_id(suspect->commit), + &sb->blame->options.oldest_commit); + } + } origin_decref(suspect); } } diff --git a/src/blame_git.h b/src/blame_git.h index 89ebc3228..6af804db2 100644 --- a/src/blame_git.h +++ b/src/blame_git.h @@ -55,6 +55,10 @@ struct blame_entry { * scanning the lines over and over. */ unsigned score; + + /* Whether this entry has been tracked to a boundary commit. + */ + bool is_boundary; }; /* diff --git a/tests-clar/blame/blame_helpers.c b/tests-clar/blame/blame_helpers.c index 25c62a1ff..d64bb5c4c 100644 --- a/tests-clar/blame/blame_helpers.c +++ b/tests-clar/blame/blame_helpers.c @@ -15,7 +15,7 @@ void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...) } void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx, - int start_line, int len, const char *commit_id, const char *orig_path) + int start_line, int len, char boundary, const char *commit_id, const char *orig_path) { char expected[41] = {0}, actual[41] = {0}; const git_blame_hunk *hunk = git_blame_get_hunk_byindex(blame, idx); @@ -53,6 +53,12 @@ void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx, hunk->orig_path, orig_path); } cl_assert_equal_s(hunk->orig_path, orig_path); + + if (hunk->boundary != boundary) { + hunk_message(idx, hunk, "doesn't match boundary flag (got %d, expected %d)\n", + hunk->boundary, boundary); + } + cl_assert_equal_i(boundary, hunk->boundary); } diff --git a/tests-clar/blame/blame_helpers.h b/tests-clar/blame/blame_helpers.h index 15fa1c33e..94321a5b5 100644 --- a/tests-clar/blame/blame_helpers.h +++ b/tests-clar/blame/blame_helpers.h @@ -9,6 +9,7 @@ void check_blame_hunk_index( int idx, int start_line, int len, + char boundary, const char *commit_id, const char *orig_path); diff --git a/tests-clar/blame/buffer.c b/tests-clar/blame/buffer.c index 20435eb6c..69b2d5440 100644 --- a/tests-clar/blame/buffer.c +++ b/tests-clar/blame/buffer.c @@ -38,7 +38,7 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); cl_assert_equal_i(5, git_blame_get_hunk_count(g_bufferblame)); - check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, "000000", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "000000", "b.txt"); } void test_blame_buffer__deleted_line(void) @@ -59,9 +59,9 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); - check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 3, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 3, 9, 1, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 4, 10, 5, "aa06ecca", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 3, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 9, 1, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 4, 10, 5, 0, "aa06ecca", "b.txt"); } void test_blame_buffer__add_splits_hunk(void) @@ -84,9 +84,9 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); - check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 2, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 3, 8, 1, "00000000", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 4, 9, 3, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 2, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 8, 1, 0, "00000000", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 4, 9, 3, 0, "63d671eb", "b.txt"); } void test_blame_buffer__delete_crosses_hunk_boundary(void) @@ -101,8 +101,8 @@ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); - check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 2, "aa06ecca", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 2, 0, "aa06ecca", "b.txt"); } void test_blame_buffer__replace_line(void) @@ -124,7 +124,7 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); - check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 1, "00000000", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 4, 8, 3, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 1, 0, "00000000", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 4, 8, 3, 0, "63d671eb", "b.txt"); } diff --git a/tests-clar/blame/simple.c b/tests-clar/blame/simple.c index ad5cf8fb4..79bd56b83 100644 --- a/tests-clar/blame/simple.c +++ b/tests-clar/blame/simple.c @@ -28,8 +28,8 @@ void test_blame_simple__trivial_testrepo(void) cl_git_pass(git_blame_file(&g_blame, g_repo, "branch_file.txt", NULL)); cl_assert_equal_i(2, git_blame_get_hunk_count(g_blame)); - check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, "c47800c7", "branch_file.txt"); - check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, "a65fedf3", "branch_file.txt"); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, 0, "c47800c7", "branch_file.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, 0, "a65fedf3", "branch_file.txt"); } /* @@ -58,10 +58,10 @@ void test_blame_simple__trivial_blamerepo(void) cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", NULL)); cl_assert_equal_i(4, git_blame_get_hunk_count(g_blame)); - check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, "da237394", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, "b99f7ac0", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 2, 6, 5, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 3, 11, 5, "aa06ecca", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, 0, "da237394", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 2, 6, 5, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 3, 11, 5, 0, "aa06ecca", "b.txt"); } @@ -147,56 +147,56 @@ void test_blame_simple__trivial_libgit2(void) cl_git_pass(git_blame_file(&g_blame, g_repo, "include/git2.h", &opts)); - check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, "359fc2d2", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 2, 3, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 3, 4, 2, "bb742ede", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 4, 6, 5, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 5, 11, 1, "96fab093", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 6, 12, 1, "9d1dcca2", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 7, 13, 1, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 8, 14, 1, "a15c550d", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 9, 15, 1, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 10, 16, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 11, 17, 1, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 12, 18, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 13, 19, 1, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 14, 20, 1, "638c2ca4", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 15, 21, 1, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 16, 22, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 17, 23, 2, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 18, 25, 1, "bf787bd8", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 19, 26, 1, "0984c876", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 20, 27, 1, "2f8a8ab2", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 21, 28, 1, "27df4275", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 22, 29, 1, "a346992f", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 23, 30, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 24, 31, 5, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 25, 36, 1, "65b09b1d", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 26, 37, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 27, 38, 1, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 28, 39, 1, "5d4cd003", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 29, 40, 1, "41fb1ca0", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 30, 41, 1, "2dc31040", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 31, 42, 1, "764df57e", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 32, 43, 1, "5280f4e6", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 33, 44, 1, "613d5eb9", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 34, 45, 1, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 35, 46, 1, "111ee3fe", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 36, 47, 1, "f004c4a8", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 37, 48, 1, "111ee3fe", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 38, 49, 1, "9c82357b", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 39, 50, 1, "d6258deb", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 40, 51, 1, "b311e313", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 41, 52, 1, "3412391d", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 42, 53, 1, "bfc9ca59", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 43, 54, 1, "bf477ed4", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 44, 55, 1, "edebceff", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 45, 56, 1, "743a4b3b", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 46, 57, 1, "0a32dca5", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 47, 58, 1, "590fb68b", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 48, 59, 1, "bf477ed4", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 49, 60, 1, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, 0, "359fc2d2", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 2, 3, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 3, 4, 2, 0, "bb742ede", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 4, 6, 5, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 5, 11, 1, 0, "96fab093", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 6, 12, 1, 0, "9d1dcca2", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 7, 13, 1, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 8, 14, 1, 0, "a15c550d", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 9, 15, 1, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 10, 16, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 11, 17, 1, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 12, 18, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 13, 19, 1, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 14, 20, 1, 0, "638c2ca4", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 15, 21, 1, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 16, 22, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 17, 23, 2, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 18, 25, 1, 0, "bf787bd8", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 19, 26, 1, 0, "0984c876", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 20, 27, 1, 0, "2f8a8ab2", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 21, 28, 1, 0, "27df4275", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 22, 29, 1, 0, "a346992f", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 23, 30, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 24, 31, 5, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 25, 36, 1, 0, "65b09b1d", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 26, 37, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 27, 38, 1, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 28, 39, 1, 0, "5d4cd003", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 29, 40, 1, 0, "41fb1ca0", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 30, 41, 1, 0, "2dc31040", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 31, 42, 1, 0, "764df57e", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 32, 43, 1, 0, "5280f4e6", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 33, 44, 1, 0, "613d5eb9", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 34, 45, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 35, 46, 1, 0, "111ee3fe", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 36, 47, 1, 0, "f004c4a8", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 37, 48, 1, 0, "111ee3fe", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 38, 49, 1, 0, "9c82357b", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 39, 50, 1, 0, "d6258deb", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 40, 51, 1, 0, "b311e313", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 41, 52, 1, 0, "3412391d", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 42, 53, 1, 0, "bfc9ca59", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 43, 54, 1, 0, "bf477ed4", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 44, 55, 1, 0, "edebceff", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 45, 56, 1, 0, "743a4b3b", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 46, 57, 1, 0, "0a32dca5", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 47, 58, 1, 0, "590fb68b", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 48, 59, 1, 0, "bf477ed4", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 49, 60, 1, 0, "d12299fe", "src/git.h"); } @@ -222,8 +222,8 @@ void test_blame_simple__can_restrict_lines_min(void) opts.min_line = 8; cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); cl_assert_equal_i(2, git_blame_get_hunk_count(g_blame)); - check_blame_hunk_index(g_repo, g_blame, 0, 8, 3, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 1, 11, 5, "aa06ecca", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 0, 8, 3, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 11, 5, 0, "aa06ecca", "b.txt"); } /* @@ -236,16 +236,6 @@ void test_blame_simple__can_restrict_lines_min(void) * da237394 4 (Ben Straub 2013-02-12 15:11:30 -0800 4 * ^b99f7ac 1 (Ben Straub 2013-02-12 15:10:12 -0800 5 * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 - * - * $ git blame -n b.txt -L 2,7 - * orig line no final line no - * commit V author timestamp V - * da237394 2 (Ben Straub 2013-02-12 15:11:30 -0800 2 - * da237394 3 (Ben Straub 2013-02-12 15:11:30 -0800 3 - * da237394 4 (Ben Straub 2013-02-12 15:11:30 -0800 4 - * ^b99f7ac 1 (Ben Straub 2013-02-12 15:10:12 -0800 5 - * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 - * 63d671eb 7 (Ben Straub 2013-02-12 15:13:04 -0800 7 */ void test_blame_simple__can_restrict_lines_max(void) { @@ -256,9 +246,9 @@ void test_blame_simple__can_restrict_lines_max(void) opts.max_line = 6; cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); cl_assert_equal_i(3, git_blame_get_hunk_count(g_blame)); - check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, "da237394", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, "b99f7ac0", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 2, 6, 1, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, 0, "da237394", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 2, 6, 1, 0, "63d671eb", "b.txt"); } /* @@ -282,7 +272,34 @@ void test_blame_simple__can_restrict_lines_both(void) opts.max_line = 7; cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); cl_assert_equal_i(3, git_blame_get_hunk_count(g_blame)); - check_blame_hunk_index(g_repo, g_blame, 0, 2, 3, "da237394", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, "b99f7ac0", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 2, 6, 2, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 0, 2, 3, 0, "da237394", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 2, 6, 2, 0, "63d671eb", "b.txt"); +} + +/* + * $ git blame -n branch_file.txt be3563a..HEAD + * orig line no final line no + * commit V author timestamp V + * ^be3563a 1 (Scott Chacon 2010-05-25 11:58:27 -0700 1) hi + * a65fedf3 2 (Scott Chacon 2011-08-09 19:33:46 -0700 2) bye! + */ +void test_blame_simple__can_restrict_to_newish_commits(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); + + { + git_object *obj; + cl_git_pass(git_revparse_single(&obj, g_repo, "be3563a")); + git_oid_cpy(&opts.oldest_commit, git_object_id(obj)); + git_object_free(obj); + } + + cl_git_pass(git_blame_file(&g_blame, g_repo, "branch_file.txt", &opts)); + + cl_assert_equal_i(2, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, 1, "be3563a", "branch_file.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, 0, "a65fedf", "branch_file.txt"); } -- cgit v1.2.1 From a121e580113cb3206166b432ad8ebfd85c0c4d5f Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 20 Sep 2013 15:20:03 -0700 Subject: Add typedefs for internal structs --- src/blame.c | 14 ++++---- src/blame_git.c | 110 +++++++++++++++++++++++++++++--------------------------- src/blame_git.h | 36 +++++++++---------- 3 files changed, 82 insertions(+), 78 deletions(-) diff --git a/src/blame.c b/src/blame.c index b7886aa5c..3b9d3db3b 100644 --- a/src/blame.c +++ b/src/blame.c @@ -221,7 +221,7 @@ static git_blame_hunk *split_hunk_in_vector( * To allow quick access to the contents of nth line in the * final image, prepare an index in the scoreboard. */ -static int prepare_lines(struct scoreboard *sb) +static int prepare_lines(git_blame__scoreboard *sb) { const char *buf = sb->final_buf; git_off_t len = sb->final_buf_size; @@ -242,7 +242,7 @@ static int prepare_lines(struct scoreboard *sb) return sb->num_lines; } -static git_blame_hunk* hunk_from_entry(struct blame_entry *e) +static git_blame_hunk* hunk_from_entry(git_blame__entry *e) { git_blame_hunk *h = new_hunk( e->lno+1, e->num_lines, e->s_lno+1, e->suspect->path); @@ -255,10 +255,10 @@ static int walk_and_mark(git_blame *blame) { int error; - struct scoreboard sb = {0}; - struct blame_entry *ent = NULL; + git_blame__scoreboard sb = {0}; + git_blame__entry *ent = NULL; git_blob *blob = NULL; - struct origin *o; + git_blame__origin *o; if ((error = git_commit_lookup(&sb.final, blame->repository, &blame->options.newest_commit)) < 0 || (error = git_object_lookup_bypath((git_object**)&blob, (git_object*)sb.final, blame->path, GIT_OBJ_BLOB)) < 0) @@ -287,8 +287,8 @@ static int walk_and_mark(git_blame *blame) cleanup: for (ent = sb.ent; ent; ) { - struct blame_entry *e = ent->next; - struct origin *o = ent->suspect; + git_blame__entry *e = ent->next; + git_blame__origin *o = ent->suspect; git_vector_insert(&blame->hunks, hunk_from_entry(ent)); diff --git a/src/blame_git.c b/src/blame_git.c index 02628c4ba..8fd06dac3 100644 --- a/src/blame_git.c +++ b/src/blame_git.c @@ -11,13 +11,15 @@ /* * Locate an existing origin or create a new one. */ -int get_origin(struct origin **out, struct scoreboard *sb, git_commit *commit, const char *path) +int get_origin(git_blame__origin **out, git_blame__scoreboard *sb, git_commit *commit, const char *path) { - struct blame_entry *e; + git_blame__entry *e; - for (e = sb->ent; e; e = e->next) - if (e->suspect->commit == commit && !strcmp(e->suspect->path, path)) + for (e = sb->ent; e; e = e->next) { + if (e->suspect->commit == commit && !strcmp(e->suspect->path, path)) { *out = origin_incref(e->suspect); + } + } return make_origin(out, commit, path); } @@ -27,10 +29,11 @@ int get_origin(struct origin **out, struct scoreboard *sb, git_commit *commit, c * get_origin() to obtain shared, refcounted copy instead of calling * this function directly. */ -int make_origin(struct origin **out, git_commit *commit, const char *path) +int make_origin(git_blame__origin **out, git_commit *commit, const char *path) { int error = 0; - struct origin *o; + git_blame__origin *o; + o = git__calloc(1, sizeof(*o) + strlen(path) + 1); GITERR_CHECK_ALLOC(o); o->commit = commit; @@ -38,22 +41,23 @@ int make_origin(struct origin **out, git_commit *commit, const char *path) strcpy(o->path, path); if (!(error = git_object_lookup_bypath((git_object**)&o->blob, (git_object*)commit, - path, GIT_OBJ_BLOB))) + path, GIT_OBJ_BLOB))) { *out = o; - else + } else { origin_decref(o); + } return error; } struct blame_chunk_cb_data { - struct scoreboard *sb; - struct origin *target; - struct origin *parent; - long plno; + git_blame__scoreboard *sb; + git_blame__origin *target; + git_blame__origin *parent; long tlno; + long plno; }; -static bool same_suspect(struct origin *a, struct origin *b) +static bool same_suspect(git_blame__origin *a, git_blame__origin *b) { if (a == b) return true; @@ -63,9 +67,9 @@ static bool same_suspect(struct origin *a, struct origin *b) } /* Find the line number of the last line the target is suspected for */ -static int find_last_in_target(struct scoreboard *sb, struct origin *target) +static int find_last_in_target(git_blame__scoreboard *sb, git_blame__origin *target) { - struct blame_entry *e; + git_blame__entry *e; int last_in_target = -1; for (e=sb->ent; e; e=e->next) { @@ -91,8 +95,8 @@ static int find_last_in_target(struct scoreboard *sb, struct origin *target) * Split e into potentially three parts; before this chunk, the chunk * to be blamed for the parent, and after that portion. */ -static void split_overlap(struct blame_entry *split, struct blame_entry *e, - int tlno, int plno, int same, struct origin *parent) +static void split_overlap(git_blame__entry *split, git_blame__entry *e, + int tlno, int plno, int same, git_blame__origin *parent) { int chunk_end_lno; @@ -134,9 +138,9 @@ static void split_overlap(struct blame_entry *split, struct blame_entry *e, * Link in a new blame entry to the scoreboard. Entries that cover the same * line range have been removed from the scoreboard previously. */ -static void add_blame_entry(struct scoreboard *sb, struct blame_entry *e) +static void add_blame_entry(git_blame__scoreboard *sb, git_blame__entry *e) { - struct blame_entry *ent, *prev = NULL; + git_blame__entry *ent, *prev = NULL; origin_incref(e->suspect); @@ -161,9 +165,9 @@ static void add_blame_entry(struct scoreboard *sb, struct blame_entry *e) * a malloced blame_entry that is already on the linked list of the scoreboard. * The origin of dst loses a refcnt while the origin of src gains one. */ -static void dup_entry(struct blame_entry *dst, struct blame_entry *src) +static void dup_entry(git_blame__entry *dst, git_blame__entry *src) { - struct blame_entry *p, *n; + git_blame__entry *p, *n; p = dst->prev; n = dst->next; @@ -179,9 +183,9 @@ static void dup_entry(struct blame_entry *dst, struct blame_entry *src) * split_overlap() divided an existing blame e into up to three parts in split. * Adjust the linked list of blames in the scoreboard to reflect the split. */ -static void split_blame(struct scoreboard *sb, struct blame_entry *split, struct blame_entry *e) +static void split_blame(git_blame__scoreboard *sb, git_blame__entry *split, git_blame__entry *e) { - struct blame_entry *new_entry; + git_blame__entry *new_entry; if (split[0].suspect && split[2].suspect) { /* The first part (reuse storage for the existing entry e */ @@ -189,12 +193,12 @@ static void split_blame(struct scoreboard *sb, struct blame_entry *split, struct /* The last part -- me */ new_entry = git__malloc(sizeof(*new_entry)); - memcpy(new_entry, &(split[2]), sizeof(struct blame_entry)); + memcpy(new_entry, &(split[2]), sizeof(git_blame__entry)); add_blame_entry(sb, new_entry); /* ... and the middle part -- parent */ new_entry = git__malloc(sizeof(*new_entry)); - memcpy(new_entry, &(split[1]), sizeof(struct blame_entry)); + memcpy(new_entry, &(split[1]), sizeof(git_blame__entry)); add_blame_entry(sb, new_entry); } else if (!split[0].suspect && !split[2].suspect) { /* @@ -206,13 +210,13 @@ static void split_blame(struct scoreboard *sb, struct blame_entry *split, struct /* me and then parent */ dup_entry(e, &split[0]); new_entry = git__malloc(sizeof(*new_entry)); - memcpy(new_entry, &(split[1]), sizeof(struct blame_entry)); + memcpy(new_entry, &(split[1]), sizeof(git_blame__entry)); add_blame_entry(sb, new_entry); } else { /* parent and then me */ dup_entry(e, &split[1]); new_entry = git__malloc(sizeof(*new_entry)); - memcpy(new_entry, &(split[2]), sizeof(struct blame_entry)); + memcpy(new_entry, &(split[2]), sizeof(git_blame__entry)); add_blame_entry(sb, new_entry); } } @@ -221,7 +225,7 @@ static void split_blame(struct scoreboard *sb, struct blame_entry *split, struct * After splitting the blame, the origins used by the on-stack blame_entry * should lose one refcnt each. */ -static void decref_split(struct blame_entry *split) +static void decref_split(git_blame__entry *split) { int i; for (i=0; i<3; i++) @@ -232,9 +236,9 @@ static void decref_split(struct blame_entry *split) * Helper for blame_chunk(). blame_entry e is known to overlap with the patch * hunk; split it and pass blame to the parent. */ -static void blame_overlap(struct scoreboard *sb, struct blame_entry *e, int tlno, int plno, int same, struct origin *parent) +static void blame_overlap(git_blame__scoreboard *sb, git_blame__entry *e, int tlno, int plno, int same, git_blame__origin *parent) { - struct blame_entry split[3] = {{0}}; + git_blame__entry split[3] = {{0}}; split_overlap(split, e, tlno, plno, same, parent); if (split[1].suspect) @@ -247,9 +251,9 @@ static void blame_overlap(struct scoreboard *sb, struct blame_entry *e, int tlno * e and its parent. Find and split the overlap, and pass blame to the * overlapping part to the parent. */ -static void blame_chunk(struct scoreboard *sb, int tlno, int plno, int same, struct origin *target, struct origin *parent) +static void blame_chunk(git_blame__scoreboard *sb, int tlno, int plno, int same, git_blame__origin *target, git_blame__origin *parent) { - struct blame_entry *e; + git_blame__entry *e; for (e = sb->ent; e; e = e->next) { if (e->guilty || !same_suspect(e->suspect, target)) @@ -328,7 +332,7 @@ static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, void *cb_data) return xdi_diff(file_a, file_b, &xpp, &xecfg, &ecb); } -static void fill_origin_blob(struct origin *o, mmfile_t *file) +static void fill_origin_blob(git_blame__origin *o, mmfile_t *file) { memset(file, 0, sizeof(*file)); if (o->blob) { @@ -337,9 +341,9 @@ static void fill_origin_blob(struct origin *o, mmfile_t *file) } } -static int pass_blame_to_parent(struct scoreboard *sb, - struct origin *target, - struct origin *parent) +static int pass_blame_to_parent(git_blame__scoreboard *sb, + git_blame__origin *target, + git_blame__origin *parent) { int last_in_target; mmfile_t file_p, file_o; @@ -365,10 +369,10 @@ static int paths_on_dup(void **old, void *new) git__free(new); return -1; } -static struct origin* find_origin(struct scoreboard *sb, git_commit *parent, - struct origin *origin) +static git_blame__origin* find_origin(git_blame__scoreboard *sb, git_commit *parent, + git_blame__origin *origin) { - struct origin *porigin = NULL; + git_blame__origin *porigin = NULL; git_diff_list *difflist = NULL; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_tree *otree=NULL, *ptree=NULL; @@ -429,10 +433,10 @@ cleanup: * The blobs of origin and porigin exactly match, so everything origin is * suspected for can be blamed on the parent. */ -static void pass_whole_blame(struct scoreboard *sb, - struct origin *origin, struct origin *porigin) +static void pass_whole_blame(git_blame__scoreboard *sb, + git_blame__origin *origin, git_blame__origin *porigin) { - struct blame_entry *e; + git_blame__entry *e; if (!porigin->blob) git_object_lookup((git_object**)&porigin->blob, sb->blame->repository, git_blob_id(origin->blob), @@ -446,12 +450,12 @@ static void pass_whole_blame(struct scoreboard *sb, } } -static void pass_blame(struct scoreboard *sb, struct origin *origin, uint32_t opt) +static void pass_blame(git_blame__scoreboard *sb, git_blame__origin *origin, uint32_t opt) { git_commit *commit = origin->commit; int i, num_sg; - struct origin *sg_buf[16]; - struct origin *porigin, **sg_origin = sg_buf; + git_blame__origin *sg_buf[16]; + git_blame__origin *porigin, **sg_origin = sg_buf; GIT_UNUSED(opt); @@ -498,7 +502,7 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, uint32_t op } for (i=0; iprevious) { @@ -526,14 +530,14 @@ finish: * Origin is refcounted and usually we keep the blob contents to be * reused. */ -struct origin *origin_incref(struct origin *o) +git_blame__origin *origin_incref(git_blame__origin *o) { if (o) o->refcnt++; return o; } -void origin_decref(struct origin *o) +void origin_decref(git_blame__origin *o) { if (o && --o->refcnt <= 0) { if (o->previous) @@ -544,11 +548,11 @@ void origin_decref(struct origin *o) } } -void assign_blame(struct scoreboard *sb, uint32_t opt) +void assign_blame(git_blame__scoreboard *sb, uint32_t opt) { while (true) { - struct blame_entry *ent; - struct origin *suspect = NULL; + git_blame__entry *ent; + git_blame__origin *suspect = NULL; /* Find a suspect to break down */ for (ent = sb->ent; !suspect && ent; ent = ent->next) @@ -574,9 +578,9 @@ void assign_blame(struct scoreboard *sb, uint32_t opt) } } -void coalesce(struct scoreboard *sb) +void coalesce(git_blame__scoreboard *sb) { - struct blame_entry *ent, *next; + git_blame__entry *ent, *next; for (ent=sb->ent; ent && (next = ent->next); ent = next) { if (same_suspect(ent->suspect, next->suspect) && diff --git a/src/blame_git.h b/src/blame_git.h index 6af804db2..7d229c664 100644 --- a/src/blame_git.h +++ b/src/blame_git.h @@ -9,22 +9,22 @@ /* * One blob in a commit that is being suspected */ -struct origin { +typedef struct git_blame__origin { int refcnt; - struct origin *previous; + struct git_blame__origin *previous; git_commit *commit; git_blob *blob; char path[]; -}; +} git_blame__origin; /* - * Each group of lines is described by a blame_entry; it can be split + * Each group of lines is described by a git_blame__entry; it can be split * as we pass blame to the parents. They form a linked list in the * scoreboard structure, sorted by the target line number. */ -struct blame_entry { - struct blame_entry *prev; - struct blame_entry *next; +typedef struct git_blame__entry { + struct git_blame__entry *prev; + struct git_blame__entry *next; /* the first line of this group in the final image; * internally all line numbers are 0 based. @@ -35,7 +35,7 @@ struct blame_entry { int num_lines; /* the commit that introduced this group into the final image */ - struct origin *suspect; + git_blame__origin *suspect; /* true if the suspect is truly guilty; false while we have not * checked if the group came from one of its parents. @@ -59,12 +59,12 @@ struct blame_entry { /* Whether this entry has been tracked to a boundary commit. */ bool is_boundary; -}; +} git_blame__entry; /* * The current state of the blame assignment. */ -struct scoreboard { +typedef struct git_blame__scoreboard { /* the final commit (i.e. where we started digging from) */ git_commit *final; const char *path; @@ -78,20 +78,20 @@ struct scoreboard { git_off_t final_buf_size; /* linked list of blames */ - struct blame_entry *ent; + git_blame__entry *ent; /* look-up a line in the final buffer */ int num_lines; git_blame *blame; -}; +} git_blame__scoreboard; -int get_origin(struct origin **out, struct scoreboard *sb, git_commit *commit, const char *path); -int make_origin(struct origin **out, git_commit *commit, const char *path); -struct origin *origin_incref(struct origin *o); -void origin_decref(struct origin *o); -void assign_blame(struct scoreboard *sb, uint32_t flags); -void coalesce(struct scoreboard *sb); +int get_origin(git_blame__origin **out, git_blame__scoreboard *sb, git_commit *commit, const char *path); +int make_origin(git_blame__origin **out, git_commit *commit, const char *path); +git_blame__origin *origin_incref(git_blame__origin *o); +void origin_decref(git_blame__origin *o); +void assign_blame(git_blame__scoreboard *sb, uint32_t flags); +void coalesce(git_blame__scoreboard *sb); #endif -- cgit v1.2.1 From ef03d040cf6cc81d71d340cf3915735724a77449 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 20 Sep 2013 15:38:15 -0700 Subject: Trim fat from git_blame struct --- src/blame.c | 11 ----------- src/blame.h | 7 ------- tests-clar/blame/getters.c | 2 +- 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/src/blame.c b/src/blame.c index 3b9d3db3b..e3460ba3b 100644 --- a/src/blame.c +++ b/src/blame.c @@ -62,11 +62,6 @@ static git_blame_hunk* new_hunk(uint16_t start, uint16_t lines, uint16_t orig_st return hunk; } -git_blame_hunk* git_blame__alloc_hunk() -{ - return new_hunk(0,0,0,NULL); -} - static git_blame_hunk* dup_hunk(git_blame_hunk *hunk) { git_blame_hunk *newhunk = new_hunk(hunk->final_start_line_number, hunk->lines_in_hunk, hunk->orig_start_line_number, hunk->orig_path); @@ -106,13 +101,11 @@ git_blame* git_blame__alloc( return NULL; } git_vector_init(&gbr->hunks, 8, hunk_sort_cmp_by_start_line); - git_vector_init(&gbr->unclaimed_hunks, 8, hunk_sort_cmp_by_start_line); git_vector_init(&gbr->paths, 8, paths_cmp); gbr->repository = repo; gbr->options = opts; gbr->path = git__strdup(path); git_vector_insert(&gbr->paths, git__strdup(path)); - gbr->final_blob = NULL; return gbr; } @@ -128,10 +121,6 @@ void git_blame_free(git_blame *blame) free_hunk(hunk); git_vector_free(&blame->hunks); - git_vector_foreach(&blame->unclaimed_hunks, i, hunk) - free_hunk(hunk); - git_vector_free(&blame->unclaimed_hunks); - git_vector_foreach(&blame->paths, i, path) git__free(path); git_vector_free(&blame->paths); diff --git a/src/blame.h b/src/blame.h index 260d5b5a1..1b107320b 100644 --- a/src/blame.h +++ b/src/blame.h @@ -14,16 +14,11 @@ struct git_blame { git_blame_options options; git_vector hunks; - git_vector unclaimed_hunks; git_vector paths; git_blob *final_blob; - size_t num_lines; - git_oid current_commit; - git_oid parent_commit; size_t current_diff_line; - size_t current_blame_line; git_blame_hunk *current_hunk; }; @@ -32,6 +27,4 @@ git_blame *git_blame__alloc( git_blame_options opts, const char *path); -git_blame_hunk *git_blame__alloc_hunk(); - #endif diff --git a/tests-clar/blame/getters.c b/tests-clar/blame/getters.c index 82e0de59e..8d67e3e45 100644 --- a/tests-clar/blame/getters.c +++ b/tests-clar/blame/getters.c @@ -20,7 +20,7 @@ void test_blame_getters__initialize(void) g_blame = git_blame__alloc(NULL, opts, ""); for (i=0; i<5; i++) { - git_blame_hunk *h = git_blame__alloc_hunk(); + git_blame_hunk *h = git__calloc(1, sizeof(git_blame_hunk)); h->final_start_line_number = hunks[i].final_start_line_number; h->orig_path = git__strdup(hunks[i].orig_path); h->lines_in_hunk = hunks[i].lines_in_hunk; -- cgit v1.2.1 From 0a0f0558a44d3eb176c32bff57b84f135d65db7a Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 20 Sep 2013 15:51:22 -0700 Subject: git_blame is a scoreboard --- src/blame.c | 34 ++++++++++---------- src/blame.h | 62 ++++++++++++++++++++++++++++++++++++ src/blame_git.c | 99 +++++++++++++++++++++++++++++---------------------------- src/blame_git.h | 89 +++------------------------------------------------ 4 files changed, 132 insertions(+), 152 deletions(-) diff --git a/src/blame.c b/src/blame.c index e3460ba3b..c85aa7d30 100644 --- a/src/blame.c +++ b/src/blame.c @@ -210,10 +210,10 @@ static git_blame_hunk *split_hunk_in_vector( * To allow quick access to the contents of nth line in the * final image, prepare an index in the scoreboard. */ -static int prepare_lines(git_blame__scoreboard *sb) +static int prepare_lines(git_blame *blame) { - const char *buf = sb->final_buf; - git_off_t len = sb->final_buf_size; + const char *buf = blame->final_buf; + git_off_t len = blame->final_buf_size; int num = 0, incomplete = 0, bol = 1; if (len && buf[len-1] != '\n') @@ -227,8 +227,8 @@ static int prepare_lines(git_blame__scoreboard *sb) bol = 1; } } - sb->num_lines = num + incomplete; - return sb->num_lines; + blame->num_lines = num + incomplete; + return blame->num_lines; } static git_blame_hunk* hunk_from_entry(git_blame__entry *e) @@ -244,21 +244,20 @@ static int walk_and_mark(git_blame *blame) { int error; - git_blame__scoreboard sb = {0}; git_blame__entry *ent = NULL; git_blob *blob = NULL; git_blame__origin *o; - if ((error = git_commit_lookup(&sb.final, blame->repository, &blame->options.newest_commit)) < 0 || - (error = git_object_lookup_bypath((git_object**)&blob, (git_object*)sb.final, blame->path, GIT_OBJ_BLOB)) < 0) + if ((error = git_commit_lookup(&blame->final, blame->repository, &blame->options.newest_commit)) < 0 || + (error = git_object_lookup_bypath((git_object**)&blob, (git_object*)blame->final, blame->path, GIT_OBJ_BLOB)) < 0) goto cleanup; - sb.final_buf = git_blob_rawcontent(blob); - sb.final_buf_size = git_blob_rawsize(blob); - if ((error = get_origin(&o, &sb, sb.final, blame->path)) < 0) + blame->final_buf = git_blob_rawcontent(blob); + blame->final_buf_size = git_blob_rawsize(blob); + if ((error = get_origin(&o, blame, blame->final, blame->path)) < 0) goto cleanup; ent = git__calloc(1, sizeof(*ent)); - ent->num_lines = prepare_lines(&sb); + ent->num_lines = prepare_lines(blame); ent->lno = blame->options.min_line - 1; ent->num_lines = ent->num_lines - blame->options.min_line + 1; if (blame->options.max_line > 0) { @@ -267,15 +266,14 @@ static int walk_and_mark(git_blame *blame) ent->s_lno = ent->lno; ent->suspect = o; - sb.ent = ent; - sb.path = blame->path; - sb.blame = blame; + blame->ent = ent; + blame->path = blame->path; - assign_blame(&sb, blame->options.flags); - coalesce(&sb); + assign_blame(blame, blame->options.flags); + coalesce(blame); cleanup: - for (ent = sb.ent; ent; ) { + for (ent = blame->ent; ent; ) { git_blame__entry *e = ent->next; git_blame__origin *o = ent->suspect; diff --git a/src/blame.h b/src/blame.h index 1b107320b..d730cfb89 100644 --- a/src/blame.h +++ b/src/blame.h @@ -8,6 +8,61 @@ #include "array.h" #include "git2/oid.h" +/* + * One blob in a commit that is being suspected + */ +typedef struct git_blame__origin { + int refcnt; + struct git_blame__origin *previous; + git_commit *commit; + git_blob *blob; + char path[]; +} git_blame__origin; + +/* + * Each group of lines is described by a git_blame__entry; it can be split + * as we pass blame to the parents. They form a linked list in the + * scoreboard structure, sorted by the target line number. + */ +typedef struct git_blame__entry { + struct git_blame__entry *prev; + struct git_blame__entry *next; + + /* the first line of this group in the final image; + * internally all line numbers are 0 based. + */ + int lno; + + /* how many lines this group has */ + int num_lines; + + /* the commit that introduced this group into the final image */ + git_blame__origin *suspect; + + /* true if the suspect is truly guilty; false while we have not + * checked if the group came from one of its parents. + */ + char guilty; + + /* true if the entry has been scanned for copies in the current parent + */ + char scanned; + + /* the line number of the first line of this group in the + * suspect's file; internally all line numbers are 0 based. + */ + int s_lno; + + /* how significant this entry is -- cached to avoid + * scanning the lines over and over. + */ + unsigned score; + + /* Whether this entry has been tracked to a boundary commit. + */ + bool is_boundary; +} git_blame__entry; + struct git_blame { const char *path; git_repository *repository; @@ -20,6 +75,13 @@ struct git_blame { size_t current_diff_line; git_blame_hunk *current_hunk; + + /* Scoreboard fields */ + git_commit *final; + git_blame__entry *ent; + int num_lines; + const char *final_buf; + git_off_t final_buf_size; }; git_blame *git_blame__alloc( diff --git a/src/blame_git.c b/src/blame_git.c index 8fd06dac3..3f5fe8d3a 100644 --- a/src/blame_git.c +++ b/src/blame_git.c @@ -7,15 +7,16 @@ #include "blame_git.h" #include "commit.h" +#include "xdiff/xinclude.h" /* * Locate an existing origin or create a new one. */ -int get_origin(git_blame__origin **out, git_blame__scoreboard *sb, git_commit *commit, const char *path) +int get_origin(git_blame__origin **out, git_blame *blame, git_commit *commit, const char *path) { git_blame__entry *e; - for (e = sb->ent; e; e = e->next) { + for (e = blame->ent; e; e = e->next) { if (e->suspect->commit == commit && !strcmp(e->suspect->path, path)) { *out = origin_incref(e->suspect); } @@ -50,7 +51,7 @@ int make_origin(git_blame__origin **out, git_commit *commit, const char *path) } struct blame_chunk_cb_data { - git_blame__scoreboard *sb; + git_blame *blame; git_blame__origin *target; git_blame__origin *parent; long tlno; @@ -66,13 +67,13 @@ static bool same_suspect(git_blame__origin *a, git_blame__origin *b) return 0 == strcmp(a->path, b->path); } -/* Find the line number of the last line the target is suspected for */ -static int find_last_in_target(git_blame__scoreboard *sb, git_blame__origin *target) +/* find the line number of the last line the target is suspected for */ +static int find_last_in_target(git_blame *blame, git_blame__origin *target) { git_blame__entry *e; int last_in_target = -1; - for (e=sb->ent; e; e=e->next) { + for (e=blame->ent; e; e=e->next) { if (e->guilty || !same_suspect(e->suspect, target)) continue; if (last_in_target < e->s_lno + e->num_lines) @@ -138,13 +139,13 @@ static void split_overlap(git_blame__entry *split, git_blame__entry *e, * Link in a new blame entry to the scoreboard. Entries that cover the same * line range have been removed from the scoreboard previously. */ -static void add_blame_entry(git_blame__scoreboard *sb, git_blame__entry *e) +static void add_blame_entry(git_blame *blame, git_blame__entry *e) { git_blame__entry *ent, *prev = NULL; origin_incref(e->suspect); - for (ent = sb->ent; ent && ent->lno < e->lno; ent = ent->next) + for (ent = blame->ent; ent && ent->lno < e->lno; ent = ent->next) prev = ent; /* prev, if not NULL, is the last one that is below e */ @@ -153,8 +154,8 @@ static void add_blame_entry(git_blame__scoreboard *sb, git_blame__entry *e) e->next = prev->next; prev->next = e; } else { - e->next = sb->ent; - sb->ent = e; + e->next = blame->ent; + blame->ent = e; } if (e->next) e->next->prev = e; @@ -183,7 +184,7 @@ static void dup_entry(git_blame__entry *dst, git_blame__entry *src) * split_overlap() divided an existing blame e into up to three parts in split. * Adjust the linked list of blames in the scoreboard to reflect the split. */ -static void split_blame(git_blame__scoreboard *sb, git_blame__entry *split, git_blame__entry *e) +static void split_blame(git_blame *blame, git_blame__entry *split, git_blame__entry *e) { git_blame__entry *new_entry; @@ -194,12 +195,12 @@ static void split_blame(git_blame__scoreboard *sb, git_blame__entry *split, git_ /* The last part -- me */ new_entry = git__malloc(sizeof(*new_entry)); memcpy(new_entry, &(split[2]), sizeof(git_blame__entry)); - add_blame_entry(sb, new_entry); + add_blame_entry(blame, new_entry); /* ... and the middle part -- parent */ new_entry = git__malloc(sizeof(*new_entry)); memcpy(new_entry, &(split[1]), sizeof(git_blame__entry)); - add_blame_entry(sb, new_entry); + add_blame_entry(blame, new_entry); } else if (!split[0].suspect && !split[2].suspect) { /* * The parent covers the entire area; reuse storage for e and replace it @@ -211,13 +212,13 @@ static void split_blame(git_blame__scoreboard *sb, git_blame__entry *split, git_ dup_entry(e, &split[0]); new_entry = git__malloc(sizeof(*new_entry)); memcpy(new_entry, &(split[1]), sizeof(git_blame__entry)); - add_blame_entry(sb, new_entry); + add_blame_entry(blame, new_entry); } else { /* parent and then me */ dup_entry(e, &split[1]); new_entry = git__malloc(sizeof(*new_entry)); memcpy(new_entry, &(split[2]), sizeof(git_blame__entry)); - add_blame_entry(sb, new_entry); + add_blame_entry(blame, new_entry); } } @@ -236,13 +237,13 @@ static void decref_split(git_blame__entry *split) * Helper for blame_chunk(). blame_entry e is known to overlap with the patch * hunk; split it and pass blame to the parent. */ -static void blame_overlap(git_blame__scoreboard *sb, git_blame__entry *e, int tlno, int plno, int same, git_blame__origin *parent) +static void blame_overlap(git_blame *blame, git_blame__entry *e, int tlno, int plno, int same, git_blame__origin *parent) { git_blame__entry split[3] = {{0}}; split_overlap(split, e, tlno, plno, same, parent); if (split[1].suspect) - split_blame(sb, split, e); + split_blame(blame, split, e); decref_split(split); } @@ -251,17 +252,17 @@ static void blame_overlap(git_blame__scoreboard *sb, git_blame__entry *e, int tl * e and its parent. Find and split the overlap, and pass blame to the * overlapping part to the parent. */ -static void blame_chunk(git_blame__scoreboard *sb, int tlno, int plno, int same, git_blame__origin *target, git_blame__origin *parent) +static void blame_chunk(git_blame *blame, int tlno, int plno, int same, git_blame__origin *target, git_blame__origin *parent) { git_blame__entry *e; - for (e = sb->ent; e; e = e->next) { + for (e = blame->ent; e; e = e->next) { if (e->guilty || !same_suspect(e->suspect, target)) continue; if (same <= e->s_lno) continue; if (tlno < e->s_lno + e->num_lines) { - blame_overlap(sb, e, tlno, plno, same, parent); + blame_overlap(blame, e, tlno, plno, same, parent); } } } @@ -269,7 +270,7 @@ static void blame_chunk(git_blame__scoreboard *sb, int tlno, int plno, int same, static void blame_chunk_cb(long start_a, long count_a, long start_b, long count_b, void *data) { struct blame_chunk_cb_data *d = data; - blame_chunk(d->sb, d->tlno, d->plno, start_b, d->target, d->parent); + blame_chunk(d->blame, d->tlno, d->plno, start_b, d->target, d->parent); d->plno = start_a + count_a; d->tlno = start_b + count_b; } @@ -341,15 +342,15 @@ static void fill_origin_blob(git_blame__origin *o, mmfile_t *file) } } -static int pass_blame_to_parent(git_blame__scoreboard *sb, +static int pass_blame_to_parent(git_blame *blame, git_blame__origin *target, git_blame__origin *parent) { int last_in_target; mmfile_t file_p, file_o; - struct blame_chunk_cb_data d = { sb, target, parent, 0, 0 }; + struct blame_chunk_cb_data d = { blame, target, parent, 0, 0 }; - last_in_target = find_last_in_target(sb, target); + last_in_target = find_last_in_target(blame, target); if (last_in_target < 0) return 1; /* nothing remains for this target */ @@ -358,7 +359,7 @@ static int pass_blame_to_parent(git_blame__scoreboard *sb, diff_hunks(&file_p, &file_o, &d); /* The reset (i.e. anything after tlno) are the same as the parent */ - blame_chunk(sb, d.tlno, d.plno, last_in_target, target, parent); + blame_chunk(blame, d.tlno, d.plno, last_in_target, target, parent); return 0; } @@ -369,7 +370,7 @@ static int paths_on_dup(void **old, void *new) git__free(new); return -1; } -static git_blame__origin* find_origin(git_blame__scoreboard *sb, git_commit *parent, +static git_blame__origin* find_origin(git_blame *blame, git_commit *parent, git_blame__origin *origin) { git_blame__origin *porigin = NULL; @@ -387,14 +388,14 @@ static git_blame__origin* find_origin(git_blame__scoreboard *sb, git_commit *par diffopts.flags = GIT_DIFF_SKIP_BINARY_CHECK; /* Check to see if files we're interested have changed */ - diffopts.pathspec.count = sb->blame->paths.length; - diffopts.pathspec.strings = (char**)sb->blame->paths.contents; - if (0 != git_diff_tree_to_tree(&difflist, sb->blame->repository, ptree, otree, &diffopts)) + diffopts.pathspec.count = blame->paths.length; + diffopts.pathspec.strings = (char**)blame->paths.contents; + if (0 != git_diff_tree_to_tree(&difflist, blame->repository, ptree, otree, &diffopts)) goto cleanup; if (!git_diff_num_deltas(difflist)) { /* No changes; copy data */ - get_origin(&porigin, sb, parent, origin->path); + get_origin(&porigin, blame, parent, origin->path); } else { git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; int i; @@ -402,7 +403,7 @@ static git_blame__origin* find_origin(git_blame__scoreboard *sb, git_commit *par /* Generate a full diff between the two trees */ git_diff_list_free(difflist); diffopts.pathspec.count = 0; - if (0 != git_diff_tree_to_tree(&difflist, sb->blame->repository, ptree, otree, &diffopts)) + if (0 != git_diff_tree_to_tree(&difflist, blame->repository, ptree, otree, &diffopts)) goto cleanup; /* Let diff find renames */ @@ -414,10 +415,10 @@ static git_blame__origin* find_origin(git_blame__scoreboard *sb, git_commit *par for (i=0; i<(int)git_diff_num_deltas(difflist); i++) { const git_diff_delta *delta; git_diff_get_patch(NULL, &delta, difflist, i); - if (git_vector_bsearch(NULL, &sb->blame->paths, delta->new_file.path) != 0) + if (git_vector_bsearch(NULL, &blame->paths, delta->new_file.path) != 0) continue; - git_vector_insert_sorted(&sb->blame->paths, (void*)git__strdup(delta->old_file.path), paths_on_dup); + git_vector_insert_sorted(&blame->paths, (void*)git__strdup(delta->old_file.path), paths_on_dup); make_origin(&porigin, parent, delta->old_file.path); } } @@ -433,15 +434,15 @@ cleanup: * The blobs of origin and porigin exactly match, so everything origin is * suspected for can be blamed on the parent. */ -static void pass_whole_blame(git_blame__scoreboard *sb, +static void pass_whole_blame(git_blame *blame, git_blame__origin *origin, git_blame__origin *porigin) { git_blame__entry *e; if (!porigin->blob) - git_object_lookup((git_object**)&porigin->blob, sb->blame->repository, git_blob_id(origin->blob), + git_object_lookup((git_object**)&porigin->blob, blame->repository, git_blob_id(origin->blob), GIT_OBJ_BLOB); - for (e=sb->ent; e; e=e->next) { + for (e=blame->ent; e; e=e->next) { if (!same_suspect(e->suspect, origin)) continue; origin_incref(porigin); @@ -450,7 +451,7 @@ static void pass_whole_blame(git_blame__scoreboard *sb, } } -static void pass_blame(git_blame__scoreboard *sb, git_blame__origin *origin, uint32_t opt) +static void pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt) { git_commit *commit = origin->commit; int i, num_sg; @@ -460,10 +461,10 @@ static void pass_blame(git_blame__scoreboard *sb, git_blame__origin *origin, uin GIT_UNUSED(opt); num_sg = git_commit_parentcount(commit); - if (!git_oid_cmp(git_commit_id(commit), &sb->blame->options.oldest_commit)) + if (!git_oid_cmp(git_commit_id(commit), &blame->options.oldest_commit)) num_sg = 0; if (!num_sg) { - git_oid_cpy(&sb->blame->options.oldest_commit, git_commit_id(commit)); + git_oid_cpy(&blame->options.oldest_commit, git_commit_id(commit)); goto finish; } else if (num_sg < (int)ARRAY_SIZE(sg_buf)) @@ -479,13 +480,13 @@ static void pass_blame(git_blame__scoreboard *sb, git_blame__origin *origin, uin continue; git_commit_parent(&p, origin->commit, i); - porigin = find_origin(sb, p, origin); + porigin = find_origin(blame, p, origin); if (!porigin) continue; if (porigin->blob && origin->blob && !git_oid_cmp(git_blob_id(porigin->blob), git_blob_id(origin->blob))) { - pass_whole_blame(sb, origin, porigin); + pass_whole_blame(blame, origin, porigin); origin_decref(porigin); goto finish; } @@ -509,7 +510,7 @@ static void pass_blame(git_blame__scoreboard *sb, git_blame__origin *origin, uin origin_incref(porigin); origin->previous = porigin; } - if (pass_blame_to_parent(sb, origin, porigin)) + if (pass_blame_to_parent(blame, origin, porigin)) goto finish; } @@ -548,14 +549,14 @@ void origin_decref(git_blame__origin *o) } } -void assign_blame(git_blame__scoreboard *sb, uint32_t opt) +void assign_blame(git_blame *blame, uint32_t opt) { while (true) { git_blame__entry *ent; git_blame__origin *suspect = NULL; /* Find a suspect to break down */ - for (ent = sb->ent; !suspect && ent; ent = ent->next) + for (ent = blame->ent; !suspect && ent; ent = ent->next) if (!ent->guilty) suspect = ent->suspect; if (!suspect) @@ -563,26 +564,26 @@ void assign_blame(git_blame__scoreboard *sb, uint32_t opt) /* We'll use this suspect later in the loop, so hold on to it for now. */ origin_incref(suspect); - pass_blame(sb, suspect, opt); + pass_blame(blame, suspect, opt); /* Take responsibility for the remaining entries */ - for (ent = sb->ent; ent; ent = ent->next) { + for (ent = blame->ent; ent; ent = ent->next) { if (same_suspect(ent->suspect, suspect)) { ent->guilty = 1; ent->is_boundary = !git_oid_cmp( git_commit_id(suspect->commit), - &sb->blame->options.oldest_commit); + &blame->options.oldest_commit); } } origin_decref(suspect); } } -void coalesce(git_blame__scoreboard *sb) +void coalesce(git_blame *blame) { git_blame__entry *ent, *next; - for (ent=sb->ent; ent && (next = ent->next); ent = next) { + for (ent=blame->ent; ent && (next = ent->next); ent = next) { if (same_suspect(ent->suspect, next->suspect) && ent->guilty == next->guilty && ent->s_lno + ent->num_lines == next->s_lno) diff --git a/src/blame_git.h b/src/blame_git.h index 7d229c664..28d6422b2 100644 --- a/src/blame_git.h +++ b/src/blame_git.h @@ -3,95 +3,14 @@ #define INCLUDE_blame_git__ #include "git2.h" -#include "xdiff/xinclude.h" #include "blame.h" +#include "xdiff/xinclude.h" -/* - * One blob in a commit that is being suspected - */ -typedef struct git_blame__origin { - int refcnt; - struct git_blame__origin *previous; - git_commit *commit; - git_blob *blob; - char path[]; -} git_blame__origin; - -/* - * Each group of lines is described by a git_blame__entry; it can be split - * as we pass blame to the parents. They form a linked list in the - * scoreboard structure, sorted by the target line number. - */ -typedef struct git_blame__entry { - struct git_blame__entry *prev; - struct git_blame__entry *next; - - /* the first line of this group in the final image; - * internally all line numbers are 0 based. - */ - int lno; - - /* how many lines this group has */ - int num_lines; - - /* the commit that introduced this group into the final image */ - git_blame__origin *suspect; - - /* true if the suspect is truly guilty; false while we have not - * checked if the group came from one of its parents. - */ - char guilty; - - /* true if the entry has been scanned for copies in the current parent - */ - char scanned; - - /* the line number of the first line of this group in the - * suspect's file; internally all line numbers are 0 based. - */ - int s_lno; - - /* how significant this entry is -- cached to avoid - * scanning the lines over and over. - */ - unsigned score; - - /* Whether this entry has been tracked to a boundary commit. - */ - bool is_boundary; -} git_blame__entry; - -/* - * The current state of the blame assignment. - */ -typedef struct git_blame__scoreboard { - /* the final commit (i.e. where we started digging from) */ - git_commit *final; - const char *path; - - /* - * The contents in the final image. - * Used by many functions to obtain contents of the nth line, - * indexed with scoreboard.lineno[blame_entry.lno]. - */ - const char *final_buf; - git_off_t final_buf_size; - - /* linked list of blames */ - git_blame__entry *ent; - - /* look-up a line in the final buffer */ - int num_lines; - - git_blame *blame; -} git_blame__scoreboard; - - -int get_origin(git_blame__origin **out, git_blame__scoreboard *sb, git_commit *commit, const char *path); +int get_origin(git_blame__origin **out, git_blame *sb, git_commit *commit, const char *path); int make_origin(git_blame__origin **out, git_commit *commit, const char *path); git_blame__origin *origin_incref(git_blame__origin *o); void origin_decref(git_blame__origin *o); -void assign_blame(git_blame__scoreboard *sb, uint32_t flags); -void coalesce(git_blame__scoreboard *sb); +void assign_blame(git_blame *sb, uint32_t flags); +void coalesce(git_blame *sb); #endif -- cgit v1.2.1 From 1b57699a3a6245bce3b98f73286b7a904c4bbd66 Mon Sep 17 00:00:00 2001 From: Linquize Date: Sun, 22 Sep 2013 09:11:43 +0800 Subject: Fix typo in documentation --- include/git2/common.h | 2 +- src/posix.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/git2/common.h b/include/git2/common.h index bb2e63637..dca0c9c21 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -212,7 +212,7 @@ typedef enum { * > Get the current bytes in cache and the maximum that would be * > allowed in the cache. * - * * opts(GIT_OPT_GET_SEARCH_PATH, char *out, size_t len) + * * opts(GIT_OPT_GET_TEMPLATE_PATH, char *out, size_t len) * * > Get the default template path. * > The path is written to the `out` diff --git a/src/posix.h b/src/posix.h index de2aa0b73..14c92b93d 100644 --- a/src/posix.h +++ b/src/posix.h @@ -39,7 +39,7 @@ typedef int git_file; * * Some of the methods are slightly wrapped to provide * saner defaults. Some of these methods are emulated - * in Windows platforns. + * in Windows platforms. * * Use your manpages to check the docs on these. */ -- cgit v1.2.1 From 07fb67f90e79ecf35672008fed262a7db41d9790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sun, 22 Sep 2013 05:55:39 +0200 Subject: merge: reverse array and length parameter order Make it pair up with the one for commits. This fixes #1691. --- include/git2/merge.h | 6 +++--- src/merge.c | 2 +- tests-clar/revwalk/mergebase.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/git2/merge.h b/include/git2/merge.h index 3f21fb4c8..62fd7d723 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -85,15 +85,15 @@ GIT_EXTERN(int) git_merge_base( * * @param out the OID of a merge base considering all the commits * @param repo the repository where the commits exist - * @param input_array oids of the commits * @param length The number of commits in the provided `input_array` + * @param input_array oids of the commits * @return Zero on success; GIT_ENOTFOUND or -1 on failure. */ GIT_EXTERN(int) git_merge_base_many( git_oid *out, git_repository *repo, - const git_oid input_array[], - size_t length); + size_t length, + const git_oid input_array[]); /** * Creates a `git_merge_head` from the given reference diff --git a/src/merge.c b/src/merge.c index 2e94ce1cd..b07e8c52f 100644 --- a/src/merge.c +++ b/src/merge.c @@ -58,7 +58,7 @@ struct merge_diff_df_data { /* Merge base computation */ -int git_merge_base_many(git_oid *out, git_repository *repo, const git_oid input_array[], size_t length) +int git_merge_base_many(git_oid *out, git_repository *repo, size_t length, const git_oid input_array[]) { git_revwalk *walk; git_vector list; diff --git a/tests-clar/revwalk/mergebase.c b/tests-clar/revwalk/mergebase.c index a2dbbc738..2d01647fd 100644 --- a/tests-clar/revwalk/mergebase.c +++ b/tests-clar/revwalk/mergebase.c @@ -172,9 +172,9 @@ static void assert_mergebase_many(const char *expected_sha, int count, ...) va_end(ap); if (expected_sha == NULL) - cl_assert_equal_i(GIT_ENOTFOUND, git_merge_base_many(&oid, _repo, oids, count)); + cl_assert_equal_i(GIT_ENOTFOUND, git_merge_base_many(&oid, _repo, count, oids)); else { - cl_git_pass(git_merge_base_many(&oid, _repo, oids, count)); + cl_git_pass(git_merge_base_many(&oid, _repo, count, oids)); cl_git_pass(git_oid_fromstr(&expected, expected_sha)); cl_assert(git_oid_cmp(&expected, &oid) == 0); -- cgit v1.2.1 From f0c9d8ba1c7b9a5913248ea5228700da2eb76aaa Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Sat, 21 Sep 2013 21:19:33 -0700 Subject: Clean up old methods, format long lines Added back the line index. We'll need it later. --- src/blame.c | 125 ++++++++++++++++++++++++++++++++++-------------------------- src/blame.h | 1 + 2 files changed, 72 insertions(+), 54 deletions(-) diff --git a/src/blame.c b/src/blame.c index c85aa7d30..ccfbb1ee7 100644 --- a/src/blame.c +++ b/src/blame.c @@ -17,21 +17,20 @@ #include "blame_git.h" -static int hunk_search_cmp_helper(const void *key, size_t start_line, size_t num_lines) +static int hunk_byfinalline_search_cmp(const void *key, const void *entry) { uint32_t lineno = *(size_t*)key; - if (lineno < start_line) + git_blame_hunk *hunk = (git_blame_hunk*)entry; + + if (lineno < hunk->final_start_line_number) return -1; - if (lineno >= ((uint32_t)start_line + num_lines)) + if (lineno >= hunk->final_start_line_number + hunk->lines_in_hunk) return 1; return 0; } -static int hunk_byfinalline_search_cmp(const void *key, const void *entry) -{ - git_blame_hunk *hunk = (git_blame_hunk*)entry; - return hunk_search_cmp_helper(key, hunk->final_start_line_number, hunk->lines_in_hunk); -} -static int hunk_sort_cmp_by_start_line(const void *_a, const void *_b) + +static int paths_cmp(const void *a, const void *b) { return git__strcmp((char*)a, (char*)b); } +static int hunk_cmp(const void *_a, const void *_b) { git_blame_hunk *a = (git_blame_hunk*)_a, *b = (git_blame_hunk*)_b; @@ -49,7 +48,11 @@ static bool hunk_starts_at_or_after_line(git_blame_hunk *hunk, size_t line) return line <= hunk->final_start_line_number; } -static git_blame_hunk* new_hunk(uint16_t start, uint16_t lines, uint16_t orig_start, const char *path) +static git_blame_hunk* new_hunk( + uint16_t start, + uint16_t lines, + uint16_t orig_start, + const char *path) { git_blame_hunk *hunk = git__calloc(1, sizeof(git_blame_hunk)); if (!hunk) return NULL; @@ -64,7 +67,11 @@ static git_blame_hunk* new_hunk(uint16_t start, uint16_t lines, uint16_t orig_st static git_blame_hunk* dup_hunk(git_blame_hunk *hunk) { - git_blame_hunk *newhunk = new_hunk(hunk->final_start_line_number, hunk->lines_in_hunk, hunk->orig_start_line_number, hunk->orig_path); + git_blame_hunk *newhunk = new_hunk( + hunk->final_start_line_number, + hunk->lines_in_hunk, + hunk->orig_start_line_number, + hunk->orig_path); git_oid_cpy(&newhunk->orig_commit_id, &hunk->orig_commit_id); git_oid_cpy(&newhunk->final_commit_id, &hunk->final_commit_id); return newhunk; @@ -78,7 +85,7 @@ static void free_hunk(git_blame_hunk *hunk) /* Starting with the hunk that includes start_line, shift all following hunks' * final_start_line by shift_by lines */ -static void shift_hunks_by_final(git_vector *v, size_t start_line, int shift_by) +static void shift_hunks_by(git_vector *v, size_t start_line, int shift_by) { size_t i; @@ -89,7 +96,7 @@ static void shift_hunks_by_final(git_vector *v, size_t start_line, int shift_by) } } } -static int paths_cmp(const void *a, const void *b) { return git__strcmp((char*)a, (char*)b); } + git_blame* git_blame__alloc( git_repository *repo, git_blame_options opts, @@ -100,7 +107,7 @@ git_blame* git_blame__alloc( giterr_set_oom(); return NULL; } - git_vector_init(&gbr->hunks, 8, hunk_sort_cmp_by_start_line); + git_vector_init(&gbr->hunks, 8, hunk_cmp); git_vector_init(&gbr->paths, 8, paths_cmp); gbr->repository = repo; gbr->options = opts; @@ -125,6 +132,8 @@ void git_blame_free(git_blame *blame) git__free(path); git_vector_free(&blame->paths); + git_array_clear(blame->line_index); + git__free((void*)blame->path); git_blob_free(blame->final_blob); git__free(blame); @@ -205,32 +214,39 @@ static git_blame_hunk *split_hunk_in_vector( } } - /* - * To allow quick access to the contents of nth line in the - * final image, prepare an index in the scoreboard. + * Construct a list of char indices for where lines begin + * Adapted from core git: + * https://github.com/gitster/git/blob/be5c9fb9049ed470e7005f159bb923a5f4de1309/builtin/blame.c#L1760-L1789 */ -static int prepare_lines(git_blame *blame) +static int index_blob_lines(git_blame *blame) { - const char *buf = blame->final_buf; - git_off_t len = blame->final_buf_size; - int num = 0, incomplete = 0, bol = 1; - - if (len && buf[len-1] != '\n') - incomplete++; /* incomplete line at the end */ - while (len--) { - if (bol) { - bol = 0; - } - if (*buf++ == '\n') { - num++; - bol = 1; - } - } - blame->num_lines = num + incomplete; - return blame->num_lines; + const char *buf = blame->final_buf; + git_off_t len = blame->final_buf_size; + int num = 0, incomplete = 0, bol = 1; + size_t *i; + + if (len && buf[len-1] != '\n') + incomplete++; /* incomplete line at the end */ + while (len--) { + if (bol) { + i = git_array_alloc(blame->line_index); + GITERR_CHECK_ALLOC(i); + *i = buf - blame->final_buf; + bol = 0; + } + if (*buf++ == '\n') { + num++; + bol = 1; + } + } + i = git_array_alloc(blame->line_index); + GITERR_CHECK_ALLOC(i); + *i = buf - blame->final_buf; + blame->num_lines = num + incomplete; + return blame->num_lines; } - + static git_blame_hunk* hunk_from_entry(git_blame__entry *e) { git_blame_hunk *h = new_hunk( @@ -240,29 +256,31 @@ static git_blame_hunk* hunk_from_entry(git_blame__entry *e) return h; } -static int walk_and_mark(git_blame *blame) +static int blame_internal(git_blame *blame) { int error; - git_blame__entry *ent = NULL; git_blob *blob = NULL; git_blame__origin *o; - if ((error = git_commit_lookup(&blame->final, blame->repository, &blame->options.newest_commit)) < 0 || - (error = git_object_lookup_bypath((git_object**)&blob, (git_object*)blame->final, blame->path, GIT_OBJ_BLOB)) < 0) + if ((error = git_commit_lookup(&blame->final, blame->repository, + &blame->options.newest_commit)) + < 0 || + (error = git_object_lookup_bypath((git_object**)&blob, (git_object*)blame->final, + blame->path, GIT_OBJ_BLOB)) + < 0) goto cleanup; blame->final_buf = git_blob_rawcontent(blob); blame->final_buf_size = git_blob_rawsize(blob); if ((error = get_origin(&o, blame, blame->final, blame->path)) < 0) goto cleanup; - ent = git__calloc(1, sizeof(*ent)); - ent->num_lines = prepare_lines(blame); + ent = git__calloc(1, sizeof(git_blame__entry)); + ent->num_lines = index_blob_lines(blame); ent->lno = blame->options.min_line - 1; ent->num_lines = ent->num_lines - blame->options.min_line + 1; - if (blame->options.max_line > 0) { + if (blame->options.max_line > 0) ent->num_lines = blame->options.max_line - blame->options.min_line + 1; - } ent->s_lno = ent->lno; ent->suspect = o; @@ -275,11 +293,10 @@ static int walk_and_mark(git_blame *blame) cleanup: for (ent = blame->ent; ent; ) { git_blame__entry *e = ent->next; - git_blame__origin *o = ent->suspect; git_vector_insert(&blame->hunks, hunk_from_entry(ent)); - origin_decref(o); + origin_decref(ent->suspect); git__free(ent); ent = e; } @@ -288,6 +305,10 @@ cleanup: return error; } +/******************************************************************************* + * File blaming + ******************************************************************************/ + static int load_blob(git_blame *blame, git_repository *repo, git_oid *commit_id, const char *path) { int retval = -1; @@ -309,10 +330,6 @@ cleanup: return retval; } -/******************************************************************************* - * File blaming - ******************************************************************************/ - int git_blame_file( git_blame **out, git_repository *repo, @@ -332,7 +349,7 @@ int git_blame_file( if ((error = load_blob(blame, repo, &normOptions.newest_commit, path)) < 0) goto on_error; - if ((error = walk_and_mark(blame)) < 0) + if ((error = blame_internal(blame)) < 0) goto on_error; *out = blame; @@ -407,10 +424,10 @@ static int buffer_line_cb( hunk_ends_at_or_before_line(blame->current_hunk, blame->current_diff_line)) { /* Append to the current buffer-blame hunk */ blame->current_hunk->lines_in_hunk++; - shift_hunks_by_final(&blame->hunks, blame->current_diff_line+1, 1); + shift_hunks_by(&blame->hunks, blame->current_diff_line+1, 1); } else { /* Create a new buffer-blame hunk with this line */ - shift_hunks_by_final(&blame->hunks, blame->current_diff_line, 1); + shift_hunks_by(&blame->hunks, blame->current_diff_line, 1); blame->current_hunk = new_hunk(blame->current_diff_line, 1, 0, blame->path); git_vector_insert_sorted(&blame->hunks, blame->current_hunk, NULL); } @@ -430,7 +447,7 @@ static int buffer_line_cb( blame->current_hunk = (git_blame_hunk*)git_blame_get_hunk_byindex(blame, i); } } - shift_hunks_by_final(&blame->hunks, shift_base, -1); + shift_hunks_by(&blame->hunks, shift_base, -1); } return 0; } diff --git a/src/blame.h b/src/blame.h index d730cfb89..09d349d7b 100644 --- a/src/blame.h +++ b/src/blame.h @@ -72,6 +72,7 @@ struct git_blame { git_vector paths; git_blob *final_blob; + git_array_t(size_t) line_index; size_t current_diff_line; git_blame_hunk *current_hunk; -- cgit v1.2.1 From 77db6ff5c7b5a233b6dae24347b660f2752c1359 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Sat, 21 Sep 2013 22:01:53 -0700 Subject: Simplify blob loading logic --- src/blame.c | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/blame.c b/src/blame.c index ccfbb1ee7..ed816da52 100644 --- a/src/blame.c +++ b/src/blame.c @@ -256,6 +256,22 @@ static git_blame_hunk* hunk_from_entry(git_blame__entry *e) return h; } +static int load_blob(git_blame *blame) +{ + int error; + + error = git_commit_lookup(&blame->final, blame->repository, &blame->options.newest_commit); + if (error < 0) + goto cleanup; + error = git_object_lookup_bypath((git_object**)&blame->final_blob, + (git_object*)blame->final, blame->path, GIT_OBJ_BLOB); + if (error < 0) + goto cleanup; + +cleanup: + return error; +} + static int blame_internal(git_blame *blame) { int error; @@ -309,27 +325,6 @@ cleanup: * File blaming ******************************************************************************/ -static int load_blob(git_blame *blame, git_repository *repo, git_oid *commit_id, const char *path) -{ - int retval = -1; - git_commit *commit = NULL; - git_tree *tree = NULL; - git_tree_entry *tree_entry = NULL; - git_object *obj = NULL; - - if (((retval = git_commit_lookup(&commit, repo, commit_id)) < 0) || - ((retval = git_object_lookup_bypath(&obj, (git_object*)commit, path, GIT_OBJ_BLOB)) < 0) || - ((retval = git_object_type(obj)) != GIT_OBJ_BLOB)) - goto cleanup; - blame->final_blob = (git_blob*)obj; - -cleanup: - git_tree_entry_free(tree_entry); - git_tree_free(tree); - git_commit_free(commit); - return retval; -} - int git_blame_file( git_blame **out, git_repository *repo, @@ -346,7 +341,7 @@ int git_blame_file( blame = git_blame__alloc(repo, normOptions, path); GITERR_CHECK_ALLOC(blame); - if ((error = load_blob(blame, repo, &normOptions.newest_commit, path)) < 0) + if ((error = load_blob(blame)) < 0) goto on_error; if ((error = blame_internal(blame)) < 0) -- cgit v1.2.1 From b6f60a4d964d66b562092fdeb8f76e902bf05fa4 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Sat, 21 Sep 2013 22:02:23 -0700 Subject: Clean up ported code --- src/blame.c | 24 ++---- src/blame_git.c | 223 ++++++++++++++++++++++++++++++-------------------------- src/blame_git.h | 21 ++++-- 3 files changed, 142 insertions(+), 126 deletions(-) diff --git a/src/blame.c b/src/blame.c index ed816da52..0722ba005 100644 --- a/src/blame.c +++ b/src/blame.c @@ -260,6 +260,8 @@ static int load_blob(git_blame *blame) { int error; + if (blame->final_blob) return 0; + error = git_commit_lookup(&blame->final, blame->repository, &blame->options.newest_commit); if (error < 0) goto cleanup; @@ -276,20 +278,13 @@ static int blame_internal(git_blame *blame) { int error; git_blame__entry *ent = NULL; - git_blob *blob = NULL; git_blame__origin *o; - if ((error = git_commit_lookup(&blame->final, blame->repository, - &blame->options.newest_commit)) - < 0 || - (error = git_object_lookup_bypath((git_object**)&blob, (git_object*)blame->final, - blame->path, GIT_OBJ_BLOB)) - < 0) - goto cleanup; - blame->final_buf = git_blob_rawcontent(blob); - blame->final_buf_size = git_blob_rawsize(blob); - if ((error = get_origin(&o, blame, blame->final, blame->path)) < 0) + if ((error = load_blob(blame)) < 0 || + (error = git_blame__get_origin(&o, blame, blame->final, blame->path)) < 0) goto cleanup; + blame->final_buf = git_blob_rawcontent(blame->final_blob); + blame->final_buf_size = git_blob_rawsize(blame->final_blob); ent = git__calloc(1, sizeof(git_blame__entry)); ent->num_lines = index_blob_lines(blame); @@ -303,8 +298,7 @@ static int blame_internal(git_blame *blame) blame->ent = ent; blame->path = blame->path; - assign_blame(blame, blame->options.flags); - coalesce(blame); + git_blame__like_git(blame, blame->options.flags); cleanup: for (ent = blame->ent; ent; ) { @@ -312,12 +306,10 @@ cleanup: git_vector_insert(&blame->hunks, hunk_from_entry(ent)); - origin_decref(ent->suspect); - git__free(ent); + git_blame__free_entry(ent); ent = e; } - git_blob_free(blob); return error; } diff --git a/src/blame_git.c b/src/blame_git.c index 3f5fe8d3a..94e13f8ef 100644 --- a/src/blame_git.c +++ b/src/blame_git.c @@ -7,30 +7,32 @@ #include "blame_git.h" #include "commit.h" -#include "xdiff/xinclude.h" +#include "blob.h" /* - * Locate an existing origin or create a new one. + * Origin is refcounted and usually we keep the blob contents to be + * reused. */ -int get_origin(git_blame__origin **out, git_blame *blame, git_commit *commit, const char *path) +static git_blame__origin *origin_incref(git_blame__origin *o) { - git_blame__entry *e; + if (o) + o->refcnt++; + return o; +} - for (e = blame->ent; e; e = e->next) { - if (e->suspect->commit == commit && !strcmp(e->suspect->path, path)) { - *out = origin_incref(e->suspect); - } +static void origin_decref(git_blame__origin *o) +{ + if (o && --o->refcnt <= 0) { + if (o->previous) + origin_decref(o->previous); + git_blob_free(o->blob); + git_commit_free(o->commit); + git__free(o); } - return make_origin(out, commit, path); } -/* - * Given a commit and a path in it, create a new origin structure. - * The callers that add blame to the scoreboard should use - * get_origin() to obtain shared, refcounted copy instead of calling - * this function directly. - */ -int make_origin(git_blame__origin **out, git_commit *commit, const char *path) +/* Given a commit and a path in it, create a new origin structure. */ +static int make_origin(git_blame__origin **out, git_commit *commit, const char *path) { int error = 0; git_blame__origin *o; @@ -50,13 +52,30 @@ int make_origin(git_blame__origin **out, git_commit *commit, const char *path) return error; } -struct blame_chunk_cb_data { +/* Locate an existing origin or create a new one. */ +int git_blame__get_origin( + git_blame__origin **out, + git_blame *blame, + git_commit *commit, + const char *path) +{ + git_blame__entry *e; + + for (e = blame->ent; e; e = e->next) { + if (e->suspect->commit == commit && !strcmp(e->suspect->path, path)) { + *out = origin_incref(e->suspect); + } + } + return make_origin(out, commit, path); +} + +typedef struct blame_chunk_cb_data { git_blame *blame; git_blame__origin *target; git_blame__origin *parent; long tlno; long plno; -}; +}blame_chunk_cb_data; static bool same_suspect(git_blame__origin *a, git_blame__origin *b) { @@ -88,10 +107,10 @@ static int find_last_in_target(git_blame *blame, git_blame__origin *target) * line plno corresponds to e's line tlno. * * <---- e -----> - * <------> - * <------------> - * <------------> - * <------------------> + * <------> (entirely within) + * <------------> (overlaps after) + * <------------> (overlaps before) + * <------------------> (overlaps both) * * Split e into potentially three parts; before this chunk, the chunk * to be blamed for the parent, and after that portion. @@ -237,7 +256,13 @@ static void decref_split(git_blame__entry *split) * Helper for blame_chunk(). blame_entry e is known to overlap with the patch * hunk; split it and pass blame to the parent. */ -static void blame_overlap(git_blame *blame, git_blame__entry *e, int tlno, int plno, int same, git_blame__origin *parent) +static void blame_overlap( + git_blame *blame, + git_blame__entry *e, + int tlno, + int plno, + int same, + git_blame__origin *parent) { git_blame__entry split[3] = {{0}}; @@ -252,7 +277,13 @@ static void blame_overlap(git_blame *blame, git_blame__entry *e, int tlno, int p * e and its parent. Find and split the overlap, and pass blame to the * overlapping part to the parent. */ -static void blame_chunk(git_blame *blame, int tlno, int plno, int same, git_blame__origin *target, git_blame__origin *parent) +static void blame_chunk( + git_blame *blame, + int tlno, + int plno, + int same, + git_blame__origin *target, + git_blame__origin *parent) { git_blame__entry *e; @@ -267,21 +298,20 @@ static void blame_chunk(git_blame *blame, int tlno, int plno, int same, git_blam } } -static void blame_chunk_cb(long start_a, long count_a, long start_b, long count_b, void *data) -{ - struct blame_chunk_cb_data *d = data; - blame_chunk(d->blame, d->tlno, d->plno, start_b, d->target, d->parent); - d->plno = start_a + count_a; - d->tlno = start_b + count_b; -} - -static int my_emit_func(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg) +static int my_emit( + xdfenv_t *xe, + xdchange_t *xscr, + xdemitcb_t *ecb, + xdemitconf_t const *xecfg) { xdchange_t *xch = xscr; GIT_UNUSED(xe); GIT_UNUSED(xecfg); while (xch) { - blame_chunk_cb(xch->i1, xch->chg1, xch->i2, xch->chg2, ecb->priv); + blame_chunk_cb_data *d = ecb->priv; + blame_chunk(d->blame, d->tlno, d->plno, xch->i2, d->target, d->parent); + d->plno = xch->i1 + xch->chg1; + d->tlno = xch->i2 + xch->chg2; xch = xch->next; } return 0; @@ -311,26 +341,17 @@ static void trim_common_tail(mmfile_t *a, mmfile_t *b, long ctx) b->size -= trimmed - recovered; } -static int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *xecb) -{ - mmfile_t a = *mf1; - mmfile_t b = *mf2; - - trim_common_tail(&a, &b, xecfg->ctxlen); - - return xdl_diff(&a, &b, xpp, xecfg, xecb); -} - - -static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, void *cb_data) +static int diff_hunks(mmfile_t file_a, mmfile_t file_b, void *cb_data) { xpparam_t xpp = {0}; xdemitconf_t xecfg = {0}; xdemitcb_t ecb = {0}; - xecfg.emit_func = (void(*)(void))my_emit_func; + xecfg.emit_func = (void(*)(void))my_emit; ecb.priv = cb_data; - return xdi_diff(file_a, file_b, &xpp, &xecfg, &ecb); + + trim_common_tail(&file_a, &file_b, 0); + return xdl_diff(&file_a, &file_b, &xpp, &xecfg, &ecb); } static void fill_origin_blob(git_blame__origin *o, mmfile_t *file) @@ -342,13 +363,14 @@ static void fill_origin_blob(git_blame__origin *o, mmfile_t *file) } } -static int pass_blame_to_parent(git_blame *blame, - git_blame__origin *target, - git_blame__origin *parent) +static int pass_blame_to_parent( + git_blame *blame, + git_blame__origin *target, + git_blame__origin *parent) { int last_in_target; mmfile_t file_p, file_o; - struct blame_chunk_cb_data d = { blame, target, parent, 0, 0 }; + blame_chunk_cb_data d = { blame, target, parent, 0, 0 }; last_in_target = find_last_in_target(blame, target); if (last_in_target < 0) @@ -357,7 +379,7 @@ static int pass_blame_to_parent(git_blame *blame, fill_origin_blob(parent, &file_p); fill_origin_blob(target, &file_o); - diff_hunks(&file_p, &file_o, &d); + diff_hunks(file_p, file_o, &d); /* The reset (i.e. anything after tlno) are the same as the parent */ blame_chunk(blame, d.tlno, d.plno, last_in_target, target, parent); @@ -370,7 +392,10 @@ static int paths_on_dup(void **old, void *new) git__free(new); return -1; } -static git_blame__origin* find_origin(git_blame *blame, git_commit *parent, + +static git_blame__origin* find_origin( + git_blame *blame, + git_commit *parent, git_blame__origin *origin) { git_blame__origin *porigin = NULL; @@ -395,7 +420,7 @@ static git_blame__origin* find_origin(git_blame *blame, git_commit *parent, if (!git_diff_num_deltas(difflist)) { /* No changes; copy data */ - get_origin(&porigin, blame, parent, origin->path); + git_blame__get_origin(&porigin, blame, parent, origin->path); } else { git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; int i; @@ -418,7 +443,8 @@ static git_blame__origin* find_origin(git_blame *blame, git_commit *parent, if (git_vector_bsearch(NULL, &blame->paths, delta->new_file.path) != 0) continue; - git_vector_insert_sorted(&blame->paths, (void*)git__strdup(delta->old_file.path), paths_on_dup); + git_vector_insert_sorted(&blame->paths, (void*)git__strdup(delta->old_file.path), + paths_on_dup); make_origin(&porigin, parent, delta->old_file.path); } } @@ -440,8 +466,8 @@ static void pass_whole_blame(git_blame *blame, git_blame__entry *e; if (!porigin->blob) - git_object_lookup((git_object**)&porigin->blob, blame->repository, git_blob_id(origin->blob), - GIT_OBJ_BLOB); + git_object_lookup((git_object**)&porigin->blob, blame->repository, + git_blob_id(origin->blob), GIT_OBJ_BLOB); for (e=blame->ent; e; e=e->next) { if (!same_suspect(e->suspect, origin)) continue; @@ -454,25 +480,26 @@ static void pass_whole_blame(git_blame *blame, static void pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt) { git_commit *commit = origin->commit; - int i, num_sg; + int i, num_parents; git_blame__origin *sg_buf[16]; git_blame__origin *porigin, **sg_origin = sg_buf; GIT_UNUSED(opt); - num_sg = git_commit_parentcount(commit); + num_parents = git_commit_parentcount(commit); if (!git_oid_cmp(git_commit_id(commit), &blame->options.oldest_commit)) - num_sg = 0; - if (!num_sg) { + /* Stop at oldest specified commit */ + num_parents = 0; + if (!num_parents) { git_oid_cpy(&blame->options.oldest_commit, git_commit_id(commit)); goto finish; } - else if (num_sg < (int)ARRAY_SIZE(sg_buf)) + else if (num_parents < (int)ARRAY_SIZE(sg_buf)) memset(sg_buf, 0, sizeof(sg_buf)); else - sg_origin = git__calloc(num_sg, sizeof(*sg_origin)); + sg_origin = git__calloc(num_parents, sizeof(*sg_origin)); - for (i=0; i pair), + * merge them together. */ -git_blame__origin *origin_incref(git_blame__origin *o) +static void coalesce(git_blame *blame) { - if (o) - o->refcnt++; - return o; -} + git_blame__entry *ent, *next; -void origin_decref(git_blame__origin *o) -{ - if (o && --o->refcnt <= 0) { - if (o->previous) - origin_decref(o->previous); - git_blob_free(o->blob); - git_commit_free(o->commit); - git__free(o); + for (ent=blame->ent; ent && (next = ent->next); ent = next) { + if (same_suspect(ent->suspect, next->suspect) && + ent->guilty == next->guilty && + ent->s_lno + ent->num_lines == next->s_lno) + { + ent->num_lines += next->num_lines; + ent->next = next->next; + if (ent->next) + ent->next->prev = ent; + origin_decref(next->suspect); + git__free(next); + ent->score = 0; + next = ent; /* again */ + } } } -void assign_blame(git_blame *blame, uint32_t opt) +void git_blame__like_git(git_blame *blame, uint32_t opt) { while (true) { git_blame__entry *ent; @@ -577,26 +609,13 @@ void assign_blame(git_blame *blame, uint32_t opt) } origin_decref(suspect); } + + coalesce(blame); } -void coalesce(git_blame *blame) +void git_blame__free_entry(git_blame__entry *ent) { - git_blame__entry *ent, *next; - - for (ent=blame->ent; ent && (next = ent->next); ent = next) { - if (same_suspect(ent->suspect, next->suspect) && - ent->guilty == next->guilty && - ent->s_lno + ent->num_lines == next->s_lno) - { - ent->num_lines += next->num_lines; - ent->next = next->next; - if (ent->next) - ent->next->prev = ent; - origin_decref(next->suspect); - git__free(next); - ent->score = 0; - next = ent; /* again */ - } - } + if (!ent) return; + origin_decref(ent->suspect); + git__free(ent); } - diff --git a/src/blame_git.h b/src/blame_git.h index 28d6422b2..2b780116b 100644 --- a/src/blame_git.h +++ b/src/blame_git.h @@ -1,16 +1,21 @@ - +/* + * 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_blame_git__ #define INCLUDE_blame_git__ -#include "git2.h" #include "blame.h" #include "xdiff/xinclude.h" -int get_origin(git_blame__origin **out, git_blame *sb, git_commit *commit, const char *path); -int make_origin(git_blame__origin **out, git_commit *commit, const char *path); -git_blame__origin *origin_incref(git_blame__origin *o); -void origin_decref(git_blame__origin *o); -void assign_blame(git_blame *sb, uint32_t flags); -void coalesce(git_blame *sb); +int git_blame__get_origin( + git_blame__origin **out, + git_blame *sb, + git_commit *commit, + const char *path); +void git_blame__free_entry(git_blame__entry *ent); +void git_blame__like_git(git_blame *sb, uint32_t flags); #endif -- cgit v1.2.1 From 106c12f11873d270eb2c8b25bd82eaade0092e31 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 23 Sep 2013 13:31:15 -0700 Subject: Remove regex usage from places that don't need it In revwalk, we are doing a very simple check to see if a string contains wildcard characters, so a full regular expression match is not needed. In remote listing, now that we have git_config_foreach_match with full regular expression matching, we can take advantage of that and eliminate the regex here, replacing it with much simpler string manipulation. --- src/remote.c | 44 +++++++++++++++----------------------------- src/revwalk.c | 43 ++++++++++++++----------------------------- 2 files changed, 29 insertions(+), 58 deletions(-) diff --git a/src/remote.c b/src/remote.c index 1540f10d9..95b907ff1 100644 --- a/src/remote.c +++ b/src/remote.c @@ -18,8 +18,6 @@ #include "refspec.h" #include "fetchhead.h" -#include - static int add_refspec(git_remote *remote, const char *string, bool is_fetch) { git_refspec *spec; @@ -1075,35 +1073,28 @@ void git_remote_free(git_remote *remote) git__free(remote); } -struct cb_data { - git_vector *list; - regex_t *preg; -}; - -static int remote_list_cb(const git_config_entry *entry, void *data_) +static int remote_list_cb(const git_config_entry *entry, void *payload) { - struct cb_data *data = (struct cb_data *)data_; - size_t nmatch = 2; - regmatch_t pmatch[2]; - const char *name = entry->name; + git_vector *list = payload; + const char *name = entry->name + strlen("remote."); + size_t namelen = strlen(name); + char *remote_name; - if (!regexec(data->preg, name, nmatch, pmatch, 0)) { - char *remote_name = git__strndup(&name[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); - GITERR_CHECK_ALLOC(remote_name); + /* we know name matches "remote..(push)?url" */ - if (git_vector_insert(data->list, remote_name) < 0) - return -1; - } + if (!strcmp(&name[namelen - 4], ".url")) + remote_name = git__strndup(name, namelen - 4); /* strip ".url" */ + else + remote_name = git__strndup(name, namelen - 8); /* strip ".pushurl" */ + GITERR_CHECK_ALLOC(remote_name); - return 0; + return git_vector_insert(list, remote_name); } int git_remote_list(git_strarray *remotes_list, git_repository *repo) { git_config *cfg; git_vector list; - regex_t preg; - struct cb_data data; int error; if (git_repository_config__weakptr(&cfg, repo) < 0) @@ -1112,18 +1103,13 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo) if (git_vector_init(&list, 4, git__strcmp_cb) < 0) return -1; - if (regcomp(&preg, "^remote\\.(.*)\\.(push)?url$", REG_EXTENDED) < 0) { - giterr_set(GITERR_OS, "Remote catch regex failed to compile"); - return -1; - } + error = git_config_foreach_match( + cfg, "^remote\\..*\\.(push)?url$", remote_list_cb, &list); - data.list = &list; - data.preg = &preg; - error = git_config_foreach(cfg, remote_list_cb, &data); - regfree(&preg); if (error < 0) { size_t i; char *elem; + git_vector_foreach(&list, i, elem) { git__free(elem); } diff --git a/src/revwalk.c b/src/revwalk.c index 9e1e39ca4..3dd14b419 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -14,8 +14,6 @@ #include "git2/revparse.h" #include "merge.h" -#include - git_commit_list_node *git_revwalk__commit_lookup( git_revwalk *walk, const git_oid *oid) { @@ -181,48 +179,35 @@ static int push_glob_cb(const char *refname, void *data_) static int push_glob(git_revwalk *walk, const char *glob, int hide) { + int error = 0; git_buf buf = GIT_BUF_INIT; struct push_cb_data data; - regex_t preg; + size_t wildcard; assert(walk && glob); /* refs/ is implied if not given in the glob */ - if (strncmp(glob, GIT_REFS_DIR, strlen(GIT_REFS_DIR))) { - git_buf_printf(&buf, GIT_REFS_DIR "%s", glob); - } else { + if (git__prefixcmp(glob, GIT_REFS_DIR) != 0) + git_buf_joinpath(&buf, GIT_REFS_DIR, glob); + else git_buf_puts(&buf, glob); - } /* If no '?', '*' or '[' exist, we append '/ *' to the glob */ - memset(&preg, 0x0, sizeof(regex_t)); - if (regcomp(&preg, "[?*[]", REG_EXTENDED)) { - giterr_set(GITERR_OS, "Regex failed to compile"); - git_buf_free(&buf); - return -1; - } - - if (regexec(&preg, glob, 0, NULL, 0)) - git_buf_puts(&buf, "/*"); - - if (git_buf_oom(&buf)) - goto on_error; + wildcard = strcspn(glob, "?*["); + if (!glob[wildcard]) + git_buf_put(&buf, "/*", 2); data.walk = walk; data.hide = hide; - if (git_reference_foreach_glob( - walk->repo, git_buf_cstr(&buf), push_glob_cb, &data) < 0) - goto on_error; - - regfree(&preg); - git_buf_free(&buf); - return 0; + if (git_buf_oom(&buf)) + error = -1; + else + error = git_reference_foreach_glob( + walk->repo, git_buf_cstr(&buf), push_glob_cb, &data); -on_error: - regfree(&preg); git_buf_free(&buf); - return -1; + return error; } int git_revwalk_push_glob(git_revwalk *walk, const char *glob) -- cgit v1.2.1 From 1ca3e49f889a3732922e6f2b303dfe0d9f74300a Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 23 Sep 2013 13:34:01 -0700 Subject: Clean up newly introduced warnings The attempt to "clean up warnings" seems to have introduced some new warnings on compliant compilers. This fixes those in a way that I suspect will also be okay for the non-compliant compilers. Also this fixes what appears to be an extra semicolon in the repo initialization template dir handling (and as part of that fix, handles the case where an error occurs correctly). --- include/git2/index.h | 8 ++++---- src/index.c | 2 +- src/repository.c | 10 ++++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/git2/index.h b/include/git2/index.h index ba0bcc984..131d04945 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -120,9 +120,9 @@ typedef struct git_index_entry { /** Capabilities of system that affect index actions. */ typedef enum { - GIT_INDEXCAP_IGNORE_CASE = 1, - GIT_INDEXCAP_NO_FILEMODE = 2, - GIT_INDEXCAP_NO_SYMLINKS = 4, + GIT_INDEXCAP_IGNORE_CASE = 1u, + GIT_INDEXCAP_NO_FILEMODE = 2u, + GIT_INDEXCAP_NO_SYMLINKS = 4u, GIT_INDEXCAP_FROM_OWNER = ~0u } git_indexcap_t; @@ -219,7 +219,7 @@ GIT_EXTERN(unsigned int) git_index_caps(const git_index *index); * @param caps A combination of GIT_INDEXCAP values * @return 0 on success, -1 on failure */ -GIT_EXTERN(int) git_index_set_caps(git_index *index, int caps); +GIT_EXTERN(int) git_index_set_caps(git_index *index, unsigned int caps); /** * Update the contents of an existing index object in memory diff --git a/src/index.c b/src/index.c index b4f2a3b6b..21a8d31d1 100644 --- a/src/index.c +++ b/src/index.c @@ -408,7 +408,7 @@ static int create_index_error(int error, const char *msg) return error; } -int git_index_set_caps(git_index *index, int caps) +int git_index_set_caps(git_index *index, unsigned int caps) { unsigned int old_ignore_case; diff --git a/src/repository.c b/src/repository.c index 6dea48790..0d7c09484 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1145,17 +1145,19 @@ static int repo_init_structure( } if (!tdir) { - if ((error = git_futils_find_template_dir(&template_buf)) >= 0); + if (!(error = git_futils_find_template_dir(&template_buf))) tdir = template_buf.ptr; default_template = true; } - error = git_futils_cp_r(tdir, repo_dir, - GIT_CPDIR_COPY_SYMLINKS | GIT_CPDIR_CHMOD_DIRS | - GIT_CPDIR_SIMPLE_TO_MODE, dmode); + if (tdir) + error = git_futils_cp_r(tdir, repo_dir, + GIT_CPDIR_COPY_SYMLINKS | GIT_CPDIR_CHMOD_DIRS | + GIT_CPDIR_SIMPLE_TO_MODE, dmode); git_buf_free(&template_buf); git_config_free(cfg); + if (error < 0) { if (!default_template) return error; -- cgit v1.2.1 From 713793133f65569561c6ca518f61acdddd1d3b65 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 23 Sep 2013 13:40:23 -0700 Subject: Fix warnings on Windows 64-bit build --- src/filter.c | 14 +++++++++++--- tests-clar/repo/init.c | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/filter.c b/src/filter.c index 503f18555..9f866fe88 100644 --- a/src/filter.c +++ b/src/filter.c @@ -657,9 +657,17 @@ int git_filter_list_apply_to_blob( git_filter_list *filters, git_blob *blob) { - git_buf in = { - (char *)git_blob_rawcontent(blob), 0, git_blob_rawsize(blob) - }; + git_buf in = GIT_BUF_INIT; + git_off_t rawsize = git_blob_rawsize(blob); + + if (!git__is_sizet(rawsize)) { + giterr_set(GITERR_OS, "Blob is too large to filter"); + return -1; + } + + in.ptr = (char *)git_blob_rawcontent(blob); + in.asize = 0; + in.size = (size_t)rawsize; if (filters) git_oid_cpy(&filters->source.oid, git_blob_id(blob)); diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index caa211e75..392be205b 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -382,7 +382,7 @@ static void assert_hooks_match( cl_git_pass(git_buf_joinpath(&actual, repo_dir, hook_path)); cl_git_pass(git_path_lstat(actual.ptr, &st)); - cl_assert_equal_sz(expected_st.st_size, st.st_size); + cl_assert(expected_st.st_size == st.st_size); if (GIT_MODE_TYPE(expected_st.st_mode) != GIT_FILEMODE_LINK) { mode_t expected_mode = -- cgit v1.2.1 From 00e859279e361734aa38adfbbb16d25af0be8bda Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 23 Sep 2013 21:52:42 -0700 Subject: Clean up unnecessary git_buf_printf calls This replaces some git_buf_printf calls with simple calls to git_buf_put instead. Also, it fixes a missing va_end inside the git_buf_vprintf implementation. --- src/buffer.c | 2 ++ src/diff_print.c | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 1371607fe..20682322e 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -211,6 +211,8 @@ int git_buf_vprintf(git_buf *buf, const char *format, va_list ap) format, args ); + va_end(args); + if (len < 0) { git__free(buf->ptr); buf->ptr = git_buf__oom; diff --git a/src/diff_print.c b/src/diff_print.c index ee4b5fc17..fd18b67e3 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -336,7 +336,7 @@ static int diff_print_patch_hunk( return 0; git_buf_clear(pi->buf); - if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) < 0) + if (git_buf_put(pi->buf, header, header_len) < 0) return -1; if (pi->print_cb(d, r, GIT_DIFF_LINE_HUNK_HDR, @@ -360,13 +360,14 @@ static int diff_print_patch_line( return 0; git_buf_clear(pi->buf); + git_buf_grow(pi->buf, content_len + 2); if (line_origin == GIT_DIFF_LINE_ADDITION || line_origin == GIT_DIFF_LINE_DELETION || line_origin == GIT_DIFF_LINE_CONTEXT) - git_buf_printf(pi->buf, "%c%.*s", line_origin, (int)content_len, content); - else if (content_len > 0) - git_buf_printf(pi->buf, "%.*s", (int)content_len, content); + git_buf_putc(pi->buf, line_origin); + + git_buf_put(pi->buf, content, content_len); if (git_buf_oom(pi->buf)) return -1; -- cgit v1.2.1 From a3c2d916d8ad67196d2211b0a88dcbab7a433764 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 23 Sep 2013 21:59:32 -0700 Subject: Fix warnings in Makefile.embed --- Makefile.embed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.embed b/Makefile.embed index 2f3b057c7..eb8a78ebf 100644 --- a/Makefile.embed +++ b/Makefile.embed @@ -31,7 +31,7 @@ CC:=$(PREFIX)$(CC) INCLUDES= -I. -Isrc -Iinclude -Ideps/http-parser -Ideps/zlib DEFINES= $(INCLUDES) -DNO_VIZ -DSTDC -DNO_GZIP -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE $(EXTRA_DEFINES) -CFLAGS= -g $(DEFINES) -Wall -Wextra -O2 $(EXTRA_CFLAGS) +CFLAGS= -g $(DEFINES) -Wall -Wextra -Wno-missing-field-initializers -O2 $(EXTRA_CFLAGS) SRCS = $(wildcard src/*.c) $(wildcard src/transports/*.c) $(wildcard src/xdiff/*.c) $(wildcard deps/http-parser/*.c) $(wildcard deps/zlib/*.c) src/hash/hash_generic.c -- cgit v1.2.1 From e3f3868a1c4ced6109cbd4644cb1e3e8e9d8a5e9 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 24 Sep 2013 11:04:14 -0400 Subject: 'del' instead of 'delete' for the poor C++ users --- include/git2/sys/refdb_backend.h | 2 +- src/refdb.c | 2 +- src/refdb_fs.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/git2/sys/refdb_backend.h b/include/git2/sys/refdb_backend.h index 9b457b074..e0a24f433 100644 --- a/include/git2/sys/refdb_backend.h +++ b/include/git2/sys/refdb_backend.h @@ -103,7 +103,7 @@ struct git_refdb_backend { * Deletes the given reference from the refdb. A refdb implementation * must provide this function. */ - int (*delete)(git_refdb_backend *backend, const char *ref_name); + int (*del)(git_refdb_backend *backend, const char *ref_name); /** * Suggests that the given refdb compress or optimize its references. diff --git a/src/refdb.c b/src/refdb.c index 4de7188b2..7df61a577 100644 --- a/src/refdb.c +++ b/src/refdb.c @@ -201,5 +201,5 @@ int git_refdb_rename( int git_refdb_delete(struct git_refdb *db, const char *ref_name) { assert(db && db->backend); - return db->backend->delete(db->backend, ref_name); + return db->backend->del(db->backend, ref_name); } diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 894ff7c84..0ba711eb7 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -1096,7 +1096,7 @@ int git_refdb_backend_fs( backend->parent.lookup = &refdb_fs_backend__lookup; backend->parent.iterator = &refdb_fs_backend__iterator; backend->parent.write = &refdb_fs_backend__write; - backend->parent.delete = &refdb_fs_backend__delete; + backend->parent.del = &refdb_fs_backend__delete; backend->parent.rename = &refdb_fs_backend__rename; backend->parent.compress = &refdb_fs_backend__compress; backend->parent.free = &refdb_fs_backend__free; -- cgit v1.2.1 From 634f10f69090b325a50c8bca6cb303397576305e Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 24 Sep 2013 10:11:20 -0700 Subject: Fix incorrect return code in crlf filter The git_buf_text_gather_stats call returns a boolean indicating if the file looks like binary data. That shouldn't be an error; it should be used to skip CRLF processing though. --- src/crlf.c | 4 ++-- tests-clar/clar_libgit2.c | 22 ++++++++++++---------- tests-clar/clar_libgit2.h | 3 ++- tests-clar/diff/workdir.c | 25 +++++++++++++++++++++++++ tests-clar/index/filemodes.c | 11 ++++++----- 5 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/crlf.c b/src/crlf.c index b4eda267b..b25c02cce 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -133,9 +133,9 @@ static int crlf_apply_to_odb( if (ca->crlf_action == GIT_CRLF_AUTO || ca->crlf_action == GIT_CRLF_GUESS) { git_buf_text_stats stats; - /* Check heuristics for binary vs text... */ + /* Check heuristics for binary vs text - returns true if binary */ if (git_buf_text_gather_stats(&stats, from, false)) - return -1; + return GIT_PASSTHROUGH; /* * We're currently not going to even try to convert stuff diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index d7e28831f..555af38db 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -30,24 +30,26 @@ void cl_git_mkfile(const char *filename, const char *content) } void cl_git_write2file( - const char *filename, const char *new_content, int flags, unsigned int mode) + const char *path, const char *content, size_t content_len, + int flags, unsigned int mode) { - int fd = p_open(filename, flags, mode); - cl_assert(fd >= 0); - if (!new_content) - new_content = "\n"; - cl_must_pass(p_write(fd, new_content, strlen(new_content))); + int fd; + cl_assert(path && content); + cl_assert((fd = p_open(path, flags, mode)) >= 0); + if (!content_len) + content_len = strlen(content); + cl_must_pass(p_write(fd, content, content_len)); cl_must_pass(p_close(fd)); } -void cl_git_append2file(const char *filename, const char *new_content) +void cl_git_append2file(const char *path, const char *content) { - cl_git_write2file(filename, new_content, O_WRONLY | O_CREAT | O_APPEND, 0644); + cl_git_write2file(path, content, 0, O_WRONLY | O_CREAT | O_APPEND, 0644); } -void cl_git_rewritefile(const char *filename, const char *new_content) +void cl_git_rewritefile(const char *path, const char *content) { - cl_git_write2file(filename, new_content, O_WRONLY | O_CREAT | O_TRUNC, 0644); + cl_git_write2file(path, content, 0, O_WRONLY | O_CREAT | O_TRUNC, 0644); } #ifdef GIT_WIN32 diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index c37306bc4..9d4d63e6c 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -78,7 +78,8 @@ void clar__assert_equal_file( void cl_git_mkfile(const char *filename, const char *content); void cl_git_append2file(const char *filename, const char *new_content); void cl_git_rewritefile(const char *filename, const char *new_content); -void cl_git_write2file(const char *filename, const char *new_content, int flags, unsigned int mode); +void cl_git_write2file(const char *path, const char *data, + size_t datalen, int flags, unsigned int mode); bool cl_toggle_filemode(const char *filename); bool cl_is_chmod_supported(void); diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index c7fac1e48..6c17b41c6 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -1266,3 +1266,28 @@ void test_diff_workdir__untracked_directory_comes_last(void) git_diff_list_free(diff); } + +void test_diff_workdir__untracked_with_bom(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff_list *diff = NULL; + const git_diff_delta *delta; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + cl_git_write2file("empty_standard_repo/bom.txt", + "\xFF\xFE\x31\x00\x32\x00\x33\x00\x34\x00", 10, O_WRONLY|O_CREAT, 0664); + + opts.flags = + GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_INCLUDE_UNTRACKED_CONTENT; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_assert_equal_i(1, git_diff_num_deltas(diff)); + cl_git_pass(git_diff_get_patch(NULL, &delta, diff, 0)); + cl_assert_equal_i(GIT_DELTA_UNTRACKED, delta->status); + cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); + + git_diff_list_free(diff); +} diff --git a/tests-clar/index/filemodes.c b/tests-clar/index/filemodes.c index e56a9c069..02f83efba 100644 --- a/tests-clar/index/filemodes.c +++ b/tests-clar/index/filemodes.c @@ -44,7 +44,8 @@ static void replace_file_with_mode( cl_git_pass(p_rename(path.ptr, backup)); cl_git_write2file( - path.ptr, content.ptr, O_WRONLY|O_CREAT|O_TRUNC, create_mode); + path.ptr, content.ptr, content.size, + O_WRONLY|O_CREAT|O_TRUNC, create_mode); git_buf_free(&path); git_buf_free(&content); @@ -91,7 +92,7 @@ void test_index_filemodes__untrusted(void) add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); /* 5 - add new 0644 -> expect 0644 */ - cl_git_write2file("filemodes/new_off", "blah", + cl_git_write2file("filemodes/new_off", "blah", 0, O_WRONLY | O_CREAT | O_TRUNC, 0644); add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); @@ -100,7 +101,7 @@ void test_index_filemodes__untrusted(void) */ if (can_filemode) { /* 6 - add 0755 -> expect 0755 */ - cl_git_write2file("filemodes/new_on", "blah", + cl_git_write2file("filemodes/new_on", "blah", 0, O_WRONLY | O_CREAT | O_TRUNC, 0755); add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE); } @@ -140,12 +141,12 @@ void test_index_filemodes__trusted(void) add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); /* 5 - add new 0644 -> expect 0644 */ - cl_git_write2file("filemodes/new_off", "blah", + cl_git_write2file("filemodes/new_off", "blah", 0, O_WRONLY | O_CREAT | O_TRUNC, 0644); add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); /* 6 - add 0755 -> expect 0755 */ - cl_git_write2file("filemodes/new_on", "blah", + cl_git_write2file("filemodes/new_on", "blah", 0, O_WRONLY | O_CREAT | O_TRUNC, 0755); add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE); -- cgit v1.2.1 From d005885f0a7184629290dfcebed025b061551b40 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 24 Sep 2013 10:20:16 -0700 Subject: Fix up filebuf tests a bit --- tests-clar/core/filebuf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests-clar/core/filebuf.c b/tests-clar/core/filebuf.c index 4451c01c7..bf2167057 100644 --- a/tests-clar/core/filebuf.c +++ b/tests-clar/core/filebuf.c @@ -24,18 +24,16 @@ void test_core_filebuf__0(void) void test_core_filebuf__1(void) { git_filebuf file = GIT_FILEBUF_INIT; - int fd; char test[] = "test"; - fd = p_creat(test, 0666); //-V536 - cl_must_pass(fd); - cl_must_pass(p_write(fd, "libgit2 rocks\n", 14)); - cl_must_pass(p_close(fd)); + cl_git_mkfile(test, "libgit2 rocks\n"); cl_git_pass(git_filebuf_open(&file, test, GIT_FILEBUF_APPEND)); cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks")); cl_git_pass(git_filebuf_commit(&file, 0666)); + cl_assert_equal_file("libgit2 rocks\nlibgit2 rocks\n", 0, test); + cl_must_pass(p_unlink(test)); } @@ -53,6 +51,8 @@ void test_core_filebuf__2(void) cl_git_pass(git_filebuf_write(&file, buf, sizeof(buf))); cl_git_pass(git_filebuf_commit(&file, 0666)); + cl_assert_equal_file((char *)buf, sizeof(buf), test); + cl_must_pass(p_unlink(test)); } -- cgit v1.2.1 From 210d5325262fb8d5ae553fcdba6f3c045db3e1de Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 23 Sep 2013 12:09:23 -0700 Subject: Allow redirects to use same host --- src/transports/http.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/transports/http.c b/src/transports/http.c index eca06ead2..ab42a3c08 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -303,15 +303,28 @@ static int on_headers_complete(http_parser *parser) parser->status_code == 307) && t->location) { + char *host=NULL, *port=NULL, *user=NULL, *pass=NULL; + if (s->redirect_count >= 7) { giterr_set(GITERR_NET, "Too many redirects"); return t->parse_error = PARSE_ERROR_GENERIC; } - if (t->location[0] != '/') { - giterr_set(GITERR_NET, "Only relative redirects are supported"); + if (gitno_extract_url_parts(&host, &port, &user, &pass, t->location, "") < 0) { + giterr_set(GITERR_NET, "Redirect to unparseable url '%s'", t->location); + return t->parse_error = PARSE_ERROR_GENERIC; + } + git__free(port); + git__free(user); + git__free(pass); + + /* Allow '/'-led urls, or a change of protocol */ + if (strcmp(t->host, host) && t->location[0] != '/') { + git__free(host); + giterr_set(GITERR_NET, "Only same-host redirects are supported"); return t->parse_error = PARSE_ERROR_GENERIC; } + git__free(host); /* Set the redirect URL on the stream. This is a transfer of * ownership of the memory. */ -- cgit v1.2.1 From c91444055ab76f0f638a7926d8be8418fef2db0d Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 23 Sep 2013 11:37:35 -0700 Subject: Properly parse urls that include protocol:// --- src/netops.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/netops.c b/src/netops.c index 803c2696a..6777ee51b 100644 --- a/src/netops.c +++ b/src/netops.c @@ -581,7 +581,7 @@ int gitno_extract_url_parts( const char *url, const char *default_port) { - char *colon, *slash, *at, *end; + char *colon, *dblslash, *slash, *at, *end; const char *start; /* @@ -589,6 +589,9 @@ int gitno_extract_url_parts( * ==> [user[:pass]@]hostname.tld[:port]/resource */ + dblslash = strstr(url, "://"); + if (dblslash) url = dblslash+3; + colon = strchr(url, ':'); slash = strchr(url, '/'); at = strchr(url, '@'); -- cgit v1.2.1 From 5c3b8ef48bcbf0843cdc7272fec7a32819998f58 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 24 Sep 2013 14:52:58 -0400 Subject: Ignore files that disappear while iterating On occasion, files can disappear while we're iterating the filesystem, between calls to readdir and stat. Let's pretend those didn't exist in the first place. --- src/path.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/path.c b/src/path.c index 42b3d6f3e..9d8e90361 100644 --- a/src/path.c +++ b/src/path.c @@ -902,8 +902,16 @@ int git_path_dirload_with_stat( git_buf_truncate(&full, prefix_len); if ((error = git_buf_joinpath(&full, full.ptr, ps->path)) < 0 || - (error = git_path_lstat(full.ptr, &ps->st)) < 0) + (error = git_path_lstat(full.ptr, &ps->st)) < 0) { + if (error == GIT_ENOTFOUND) { + giterr_clear(); + error = 0; + git_vector_remove(contents, i--); + continue; + } + break; + } if (S_ISDIR(ps->st.st_mode)) { if ((error = git_buf_joinpath(&full, full.ptr, ".git")) < 0) -- cgit v1.2.1 From eb0ff1307106c4fefc4042b7b7014e44e422b33e Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 24 Sep 2013 14:07:08 -0700 Subject: Disconnect path string to preserve after redirect The subtransport path was relying on pointing to data owned by the remote which meant that after a redirect, the updated path was getting lost for future requests. This updates the http transport to strdup the path and maintain its own lifetime. This also pulls responsibility for parsing the URL back into the http transport and isolates the functions that parse and free that connection data so that they can be reused between the initial parsing and the redirect parsing. --- src/netops.c | 6 +- src/transports/http.c | 177 +++++++++++++++++++++++++++------------------- tests-clar/online/fetch.c | 5 ++ 3 files changed, 109 insertions(+), 79 deletions(-) diff --git a/src/netops.c b/src/netops.c index 6777ee51b..c1e74546f 100644 --- a/src/netops.c +++ b/src/netops.c @@ -581,17 +581,13 @@ int gitno_extract_url_parts( const char *url, const char *default_port) { - char *colon, *dblslash, *slash, *at, *end; + char *colon, *slash, *at, *end; const char *start; /* - * * ==> [user[:pass]@]hostname.tld[:port]/resource */ - dblslash = strstr(url, "://"); - if (dblslash) url = dblslash+3; - colon = strchr(url, ':'); slash = strchr(url, '/'); at = strchr(url, '@'); diff --git a/src/transports/http.c b/src/transports/http.c index ab42a3c08..aca8c5d8b 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -59,7 +59,7 @@ typedef struct { git_smart_subtransport parent; transport_smart *owner; gitno_socket socket; - const char *path; + char *path; char *host; char *port; char *user_from_url; @@ -125,15 +125,9 @@ static int gen_request( size_t content_length) { http_subtransport *t = OWNING_SUBTRANSPORT(s); + const char *path = t->path ? t->path : "/"; - if (!t->path) - t->path = "/"; - - /* If we were redirected, make sure to respect that here */ - if (s->redirect_url) - git_buf_printf(buf, "%s %s HTTP/1.1\r\n", s->verb, s->redirect_url); - else - git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n", s->verb, t->path, s->service_url); + git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n", s->verb, path, s->service_url); git_buf_puts(buf, "User-Agent: git/1.0 (libgit2 " LIBGIT2_VERSION ")\r\n"); git_buf_printf(buf, "Host: %s\r\n", t->host); @@ -209,7 +203,7 @@ static int on_header_ready(http_subtransport *t) } else if (!strcasecmp("Location", git_buf_cstr(name))) { if (!t->location) { - t->location= git__strdup(git_buf_cstr(value)); + t->location = git__strdup(git_buf_cstr(value)); GITERR_CHECK_ALLOC(t->location); } } @@ -255,6 +249,93 @@ static int on_header_value(http_parser *parser, const char *str, size_t len) return 0; } +static void free_connection_data(http_subtransport *t) +{ + if (t->host) { + git__free(t->host); + t->host = NULL; + } + + if (t->port) { + git__free(t->port); + t->port = NULL; + } + + if (t->user_from_url) { + git__free(t->user_from_url); + t->user_from_url = NULL; + } + + if (t->pass_from_url) { + git__free(t->pass_from_url); + t->pass_from_url = NULL; + } + + if (t->path) { + git__free(t->path); + t->path = NULL; + } +} + +static int set_connection_data_from_url( + http_subtransport *t, const char *url, const char *service_suffix) +{ + int error = 0; + const char *default_port = NULL; + char *original_host = NULL; + + if (!git__prefixcmp(url, prefix_http)) { + url = url + strlen(prefix_http); + default_port = "80"; + } + + if (!git__prefixcmp(url, prefix_https)) { + url += strlen(prefix_https); + default_port = "443"; + t->use_ssl = 1; + } + + if (!default_port) { + giterr_set(GITERR_NET, "Unrecognized URL prefix"); + return -1; + } + + /* preserve original host name for checking */ + original_host = t->host; + t->host = NULL; + + free_connection_data(t); + + error = gitno_extract_url_parts( + &t->host, &t->port, &t->user_from_url, &t->pass_from_url, + url, default_port); + + if (!error) { + const char *path = strchr(url, '/'); + size_t pathlen = strlen(path); + size_t suffixlen = service_suffix ? strlen(service_suffix) : 0; + + if (suffixlen && + !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen)) + t->path = git__strndup(path, pathlen - suffixlen); + else + t->path = git__strdup(path); + + /* Allow '/'-led urls, or a change of protocol */ + if (original_host != NULL) { + if (strcmp(original_host, t->host) && t->location[0] != '/') { + giterr_set(GITERR_NET, "Only same-host redirects are supported"); + error = -1; + } + + git__free(original_host); + } + } + + return error; +} + + static int on_headers_complete(http_parser *parser) { parser_context *ctx = (parser_context *) parser->data; @@ -303,28 +384,13 @@ static int on_headers_complete(http_parser *parser) parser->status_code == 307) && t->location) { - char *host=NULL, *port=NULL, *user=NULL, *pass=NULL; - if (s->redirect_count >= 7) { giterr_set(GITERR_NET, "Too many redirects"); return t->parse_error = PARSE_ERROR_GENERIC; } - if (gitno_extract_url_parts(&host, &port, &user, &pass, t->location, "") < 0) { - giterr_set(GITERR_NET, "Redirect to unparseable url '%s'", t->location); + if (set_connection_data_from_url(t, t->location, s->service_url) < 0) return t->parse_error = PARSE_ERROR_GENERIC; - } - git__free(port); - git__free(user); - git__free(pass); - - /* Allow '/'-led urls, or a change of protocol */ - if (strcmp(t->host, host) && t->location[0] != '/') { - git__free(host); - giterr_set(GITERR_NET, "Only same-host redirects are supported"); - return t->parse_error = PARSE_ERROR_GENERIC; - } - git__free(host); /* Set the redirect URL on the stream. This is a transfer of * ownership of the memory. */ @@ -835,50 +901,31 @@ static int http_action( git_smart_service_t action) { http_subtransport *t = (http_subtransport *)subtransport; - const char *default_port = NULL; int ret; if (!stream) return -1; if (!t->host || !t->port || !t->path) { - if (!git__prefixcmp(url, prefix_http)) { - url = url + strlen(prefix_http); - default_port = "80"; - } - - if (!git__prefixcmp(url, prefix_https)) { - url += strlen(prefix_https); - default_port = "443"; - t->use_ssl = 1; - } - - if (!default_port) - return -1; - - if ((ret = gitno_extract_url_parts(&t->host, &t->port, - &t->user_from_url, &t->pass_from_url, url, default_port)) < 0) + if ((ret = set_connection_data_from_url(t, url, NULL)) < 0) return ret; - - t->path = strchr(url, '/'); } if (http_connect(t) < 0) return -1; - switch (action) - { - case GIT_SERVICE_UPLOADPACK_LS: - return http_uploadpack_ls(t, stream); + switch (action) { + case GIT_SERVICE_UPLOADPACK_LS: + return http_uploadpack_ls(t, stream); - case GIT_SERVICE_UPLOADPACK: - return http_uploadpack(t, stream); + case GIT_SERVICE_UPLOADPACK: + return http_uploadpack(t, stream); - case GIT_SERVICE_RECEIVEPACK_LS: - return http_receivepack_ls(t, stream); + case GIT_SERVICE_RECEIVEPACK_LS: + return http_receivepack_ls(t, stream); - case GIT_SERVICE_RECEIVEPACK: - return http_receivepack(t, stream); + case GIT_SERVICE_RECEIVEPACK: + return http_receivepack(t, stream); } *stream = NULL; @@ -906,25 +953,7 @@ static int http_close(git_smart_subtransport *subtransport) t->url_cred = NULL; } - if (t->host) { - git__free(t->host); - t->host = NULL; - } - - if (t->port) { - git__free(t->port); - t->port = NULL; - } - - if (t->user_from_url) { - git__free(t->user_from_url); - t->user_from_url = NULL; - } - - if (t->pass_from_url) { - git__free(t->pass_from_url); - t->pass_from_url = NULL; - } + free_connection_data(t); return 0; } diff --git a/tests-clar/online/fetch.c b/tests-clar/online/fetch.c index bfa1eb972..f76c6cff9 100644 --- a/tests-clar/online/fetch.c +++ b/tests-clar/online/fetch.c @@ -64,6 +64,11 @@ void test_online_fetch__default_http(void) do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); } +void test_online_fetch__default_https(void) +{ + do_fetch("https://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); +} + void test_online_fetch__no_tags_git(void) { do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3); -- cgit v1.2.1 From 46fbc88ee5d4b40786ef48cb5da9c8af28577b55 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 24 Sep 2013 14:50:06 -0700 Subject: Prevent HTTPS to HTTP redirect --- src/transports/http.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/transports/http.c b/src/transports/http.c index aca8c5d8b..ab2f9a47f 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -287,6 +287,11 @@ static int set_connection_data_from_url( if (!git__prefixcmp(url, prefix_http)) { url = url + strlen(prefix_http); default_port = "80"; + + if (t->use_ssl) { + giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP not allowed"); + return -1; + } } if (!git__prefixcmp(url, prefix_https)) { @@ -324,7 +329,7 @@ static int set_connection_data_from_url( /* Allow '/'-led urls, or a change of protocol */ if (original_host != NULL) { if (strcmp(original_host, t->host) && t->location[0] != '/') { - giterr_set(GITERR_NET, "Only same-host redirects are supported"); + giterr_set(GITERR_NET, "Cross host redirect not allowed"); error = -1; } -- cgit v1.2.1 From 1c8de38004466392b855b81991aa4d698862755b Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 20 Sep 2013 16:58:04 -0700 Subject: Make tests pass if XDG config exists --- tests-clar/config/global.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/tests-clar/config/global.c b/tests-clar/config/global.c index 2ecdf97d8..d5f95f504 100644 --- a/tests-clar/config/global.c +++ b/tests-clar/config/global.c @@ -6,18 +6,21 @@ void test_config_global__initialize(void) { git_buf path = GIT_BUF_INIT; - cl_must_pass(p_mkdir("home", 0777)); + cl_assert_equal_i(0, p_mkdir("home", 0777)); cl_git_pass(git_path_prettify(&path, "home", NULL)); cl_git_pass(git_libgit2_opts( GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); - cl_must_pass(p_mkdir("xdg", 0777)); - cl_git_pass(git_path_prettify(&path, "xdg", NULL)); + cl_assert_equal_i(0, p_mkdir("xdg", 0777)); + cl_assert_equal_i(0, p_mkdir("xdg/git", 0777)); + cl_git_pass(git_path_prettify(&path, "xdg/git", NULL)); cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); + cl_assert_equal_i(0, p_mkdir("etc", 0777)); + cl_git_pass(git_path_prettify(&path, "etc", NULL)); cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, NULL)); + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); git_buf_free(&path); } @@ -26,6 +29,11 @@ void test_config_global__cleanup(void) { cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES)); cl_git_pass(git_futils_rmdir_r("xdg", NULL, GIT_RMDIR_REMOVE_FILES)); + cl_git_pass(git_futils_rmdir_r("etc", NULL, GIT_RMDIR_REMOVE_FILES)); + + git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, NULL); + git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, NULL); + git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, NULL); } void test_config_global__open_global(void) @@ -48,10 +56,7 @@ void test_config_global__open_xdg(void) const char *val, *str = "teststring"; const char *key = "this.variable"; - p_setenv("XDG_CONFIG_HOME", "xdg", 1); - - cl_must_pass(p_mkdir("xdg/git/", 0777)); - cl_git_mkfile("xdg/git/config", ""); + cl_git_mkfile("xdg/git/config", "# XDG config\n[core]\n test = 1\n"); cl_git_pass(git_config_open_default(&cfg)); cl_git_pass(git_config_open_level(&xdg, cfg, GIT_CONFIG_LEVEL_XDG)); -- cgit v1.2.1 From 53e0636cbd5cc709c7658223917598000df8e376 Mon Sep 17 00:00:00 2001 From: Mike Anderson Date: Tue, 24 Sep 2013 16:43:06 +0800 Subject: Cleaned up some tables in checkout-internals doc The markdown wasn't rendering correctly. --- docs/checkout-internals.md | 189 +++++++++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 94 deletions(-) diff --git a/docs/checkout-internals.md b/docs/checkout-internals.md index cb646da5d..6147ffdd8 100644 --- a/docs/checkout-internals.md +++ b/docs/checkout-internals.md @@ -71,19 +71,19 @@ Key Diff with 2 non-workdir iterators --------------------------------- - Old New - --- --- - 0 x x - nothing - 1 x B1 - added blob - 2 x T1 - added tree - 3 B1 x - removed blob - 4 B1 B1 - unmodified blob - 5 B1 B2 - modified blob - 6 B1 T1 - typechange blob -> tree - 7 T1 x - removed tree - 8 T1 B1 - typechange tree -> blob - 9 T1 T1 - unmodified tree - 10 T1 T2 - modified tree (implies modified/added/removed blob inside) +| | Old | New | | +|----|-----|-----|------------------------------------------------------------| +| 0 | x | x | nothing | +| 1 | x | B1 | added blob | +| 2 | x | T1 | added tree | +| 3 | B1 | x | removed blob | +| 4 | B1 | B1 | unmodified blob | +| 5 | B1 | B2 | modified blob | +| 6 | B1 | T1 | typechange blob -> tree | +| 7 | T1 | x | removed tree | +| 8 | T1 | B1 | typechange tree -> blob | +| 9 | T1 | T1 | unmodified tree | +| 10 | T1 | T2 | modified tree (implies modified/added/removed blob inside) | Now, let's make the "New" iterator into a working directory iterator, so @@ -92,23 +92,23 @@ we replace "added" items with either untracked or ignored, like this: Diff with non-work & workdir iterators -------------------------------------- - Old New-WD - --- ------ - 0 x x - nothing - 1 x B1 - untracked blob - 2 x Bi - ignored file - 3 x T1 - untracked tree - 4 x Ti - ignored tree - 5 B1 x - removed blob - 6 B1 B1 - unmodified blob - 7 B1 B2 - modified blob - 8 B1 T1 - typechange blob -> tree - 9 B1 Ti - removed blob AND ignored tree as separate items - 10 T1 x - removed tree - 11 T1 B1 - typechange tree -> blob - 12 T1 Bi - removed tree AND ignored blob as separate items - 13 T1 T1 - unmodified tree - 14 T1 T2 - modified tree (implies modified/added/removed blob inside) +| | Old | New | | +|----|-----|-----|------------------------------------------------------------| +| 0 | x | x | nothing | +| 1 | x | B1 | untracked blob | +| 2 | x | Bi | ignored file | +| 3 | x | T1 | untracked tree | +| 4 | x | Ti | ignored tree | +| 5 | B1 | x | removed blob | +| 6 | B1 | B1 | unmodified blob | +| 7 | B1 | B2 | modified blob | +| 8 | B1 | T1 | typechange blob -> tree | +| 9 | B1 | Ti | removed blob AND ignored tree as separate items | +| 10 | T1 | x | removed tree | +| 11 | T1 | B1 | typechange tree -> blob | +| 12 | T1 | Bi | removed tree AND ignored blob as separate items | +| 13 | T1 | T1 | unmodified tree | +| 14 | T1 | T2 | modified tree (implies modified/added/removed blob inside) | Note: if there is a corresponding entry in the old tree, then a working directory item won't be ignored (i.e. no Bi or Ti for tracked items). @@ -122,46 +122,47 @@ Checkout From 3 Iterators (2 not workdir, 1 workdir) (base == old HEAD; target == what to checkout; actual == working dir) - base target actual/workdir - ---- ------ ------ - 0 x x x - nothing - 1 x x B1/Bi/T1/Ti - untracked/ignored blob/tree (SAFE) - 2+ x B1 x - add blob (SAFE) - 3 x B1 B1 - independently added blob (FORCEABLE-2) - 4* x B1 B2/Bi/T1/Ti - add blob with content conflict (FORCEABLE-2) - 5+ x T1 x - add tree (SAFE) - 6* x T1 B1/Bi - add tree with blob conflict (FORCEABLE-2) - 7 x T1 T1/i - independently added tree (SAFE+MISSING) - 8 B1 x x - independently deleted blob (SAFE+MISSING) - 9- B1 x B1 - delete blob (SAFE) - 10- B1 x B2 - delete of modified blob (FORCEABLE-1) - 11 B1 x T1/Ti - independently deleted blob AND untrack/ign tree (SAFE+MISSING !!!) - 12 B1 B1 x - locally deleted blob (DIRTY || SAFE+CREATE) - 13+ B1 B2 x - update to deleted blob (SAFE+MISSING) - 14 B1 B1 B1 - unmodified file (SAFE) - 15 B1 B1 B2 - locally modified file (DIRTY) - 16+ B1 B2 B1 - update unmodified blob (SAFE) - 17 B1 B2 B2 - independently updated blob (FORCEABLE-1) - 18+ B1 B2 B3 - update to modified blob (FORCEABLE-1) - 19 B1 B1 T1/Ti - locally deleted blob AND untrack/ign tree (DIRTY) - 20* B1 B2 T1/Ti - update to deleted blob AND untrack/ign tree (F-1) - 21+ B1 T1 x - add tree with locally deleted blob (SAFE+MISSING) - 22* B1 T1 B1 - add tree AND deleted blob (SAFE) - 23* B1 T1 B2 - add tree with delete of modified blob (F-1) - 24 B1 T1 T1 - add tree with deleted blob (F-1) - 25 T1 x x - independently deleted tree (SAFE+MISSING) - 26 T1 x B1/Bi - independently deleted tree AND untrack/ign blob (F-1) - 27- T1 x T1 - deleted tree (MAYBE SAFE) - 28+ T1 B1 x - deleted tree AND added blob (SAFE+MISSING) - 29 T1 B1 B1 - independently typechanged tree -> blob (F-1) - 30+ T1 B1 B2 - typechange tree->blob with conflicting blob (F-1) - 31* T1 B1 T1/T2 - typechange tree->blob (MAYBE SAFE) - 32+ T1 T1 x - restore locally deleted tree (SAFE+MISSING) - 33 T1 T1 B1/Bi - locally typechange tree->untrack/ign blob (DIRTY) - 34 T1 T1 T1/T2 - unmodified tree (MAYBE SAFE) - 35+ T1 T2 x - update locally deleted tree (SAFE+MISSING) - 36* T1 T2 B1/Bi - update to tree with typechanged tree->blob conflict (F-1) - 37 T1 T2 T1/T2/T3 - update to existing tree (MAYBE SAFE) +| |base | target | actual/workdir | | +|-----|-----|------- |----------------|--------------------------------------------------------------------| +| 0 | x | x | x | nothing | +| 1 | x | x | B1/Bi/T1/Ti | untracked/ignored blob/tree (SAFE) | +| 2+ | x | B1 | x | add blob (SAFE) | +| 3 | x | B1 | B1 | independently added blob (FORCEABLE-2) | +| 4* | x | B1 | B2/Bi/T1/Ti | add blob with content conflict (FORCEABLE-2) | +| 5+ | x | T1 | x | add tree (SAFE) | +| 6* | x | T1 | B1/Bi | add tree with blob conflict (FORCEABLE-2) | +| 7 | x | T1 | T1/i | independently added tree (SAFE+MISSING) | +| 8 | B1 | x | x | independently deleted blob (SAFE+MISSING) | +| 9- | B1 | x | B1 | delete blob (SAFE) | +| 10- | B1 | x | B2 | delete of modified blob (FORCEABLE-1) | +| 11 | B1 | x | T1/Ti | independently deleted blob AND untrack/ign tree (SAFE+MISSING !!!) | +| 12 | B1 | B1 | x | locally deleted blob (DIRTY || SAFE+CREATE) | +| 13+ | B1 | B2 | x | update to deleted blob (SAFE+MISSING) | +| 14 | B1 | B1 | B1 | unmodified file (SAFE) | +| 15 | B1 | B1 | B2 | locally modified file (DIRTY) | +| 16+ | B1 | B2 | B1 | update unmodified blob (SAFE) | +| 17 | B1 | B2 | B2 | independently updated blob (FORCEABLE-1) | +| 18+ | B1 | B2 | B3 | update to modified blob (FORCEABLE-1) | +| 19 | B1 | B1 | T1/Ti | locally deleted blob AND untrack/ign tree (DIRTY) | +| 20* | B1 | B2 | T1/Ti | update to deleted blob AND untrack/ign tree (F-1) | +| 21+ | B1 | T1 | x | add tree with locally deleted blob (SAFE+MISSING) | +| 22* | B1 | T1 | B1 | add tree AND deleted blob (SAFE) | +| 23* | B1 | T1 | B2 | add tree with delete of modified blob (F-1) | +| 24 | B1 | T1 | T1 | add tree with deleted blob (F-1) | +| 25 | T1 | x | x | independently deleted tree (SAFE+MISSING) | +| 26 | T1 | x | B1/Bi | independently deleted tree AND untrack/ign blob (F-1) | +| 27- | T1 | x | T1 | deleted tree (MAYBE SAFE) | +| 28+ | T1 | B1 | x | deleted tree AND added blob (SAFE+MISSING) | +| 29 | T1 | B1 | B1 | independently typechanged tree -> blob (F-1) | +| 30+ | T1 | B1 | B2 | typechange tree->blob with conflicting blob (F-1) | +| 31* | T1 | B1 | T1/T2 | typechange tree->blob (MAYBE SAFE) | +| 32+ | T1 | T1 | x | restore locally deleted tree (SAFE+MISSING) | +| 33 | T1 | T1 | B1/Bi | locally typechange tree->untrack/ign blob (DIRTY) | +| 34 | T1 | T1 | T1/T2 | unmodified tree (MAYBE SAFE) | +| 35+ | T1 | T2 | x | update locally deleted tree (SAFE+MISSING) | +| 36* | T1 | T2 | B1/Bi | update to tree with typechanged tree->blob conflict (F-1) | +| 37 | T1 | T2 | T1/T2/T3 | update to existing tree (MAYBE SAFE) | + The number is followed by ' ' if no change is needed or '+' if the case needs to write to disk or '-' if something must be deleted and '*' if @@ -169,34 +170,34 @@ there should be a delete followed by an write. There are four tiers of safe cases: -- SAFE == completely safe to update -- SAFE+MISSING == safe except the workdir is missing the expect content -- MAYBE SAFE == safe if workdir tree matches (or is missing) baseline +* SAFE == completely safe to update +* SAFE+MISSING == safe except the workdir is missing the expect content +* MAYBE SAFE == safe if workdir tree matches (or is missing) baseline content, which is unknown at this point -- FORCEABLE == conflict unless FORCE is given -- DIRTY == no conflict but change is not applied unless FORCE +* FORCEABLE == conflict unless FORCE is given +* DIRTY == no conflict but change is not applied unless FORCE Some slightly unusual circumstances: - 8 - parent dir is only deleted when file is, so parent will be left if - empty even though it would be deleted if the file were present - 11 - core git does not consider this a conflict but attempts to delete T1 - and gives "unable to unlink file" error yet does not skip the rest - of the operation - 12 - without FORCE file is left deleted (i.e. not restored) so new wd is - dirty (and warning message "D file" is printed), with FORCE, file is - restored. - 24 - This should be considered MAYBE SAFE since effectively it is 7 and 8 - combined, but core git considers this a conflict unless forced. - 26 - This combines two cases (1 & 25) (and also implied 8 for tree content) - which are ok on their own, but core git treat this as a conflict. - If not forced, this is a conflict. If forced, this actually doesn't - have to write anything and leaves the new blob as an untracked file. - 32 - This is the only case where the baseline and target values match - and yet we will still write to the working directory. In all other - cases, if baseline == target, we don't touch the workdir (it is - either already right or is "dirty"). However, since this case also - implies that a ?/B1/x case will exist as well, it can be skipped. +* 8 - parent dir is only deleted when file is, so parent will be left if + empty even though it would be deleted if the file were present +* 11 - core git does not consider this a conflict but attempts to delete T1 + and gives "unable to unlink file" error yet does not skip the rest + of the operation +* 12 - without FORCE file is left deleted (i.e. not restored) so new wd is + dirty (and warning message "D file" is printed), with FORCE, file is + restored. +* 24 - This should be considered MAYBE SAFE since effectively it is 7 and 8 + combined, but core git considers this a conflict unless forced. +* 26 - This combines two cases (1 & 25) (and also implied 8 for tree content) + which are ok on their own, but core git treat this as a conflict. + If not forced, this is a conflict. If forced, this actually doesn't + have to write anything and leaves the new blob as an untracked file. +* 32 - This is the only case where the baseline and target values match + and yet we will still write to the working directory. In all other + cases, if baseline == target, we don't touch the workdir (it is + either already right or is "dirty"). However, since this case also + implies that a ?/B1/x case will exist as well, it can be skipped. Cases 3, 17, 24, 26, and 29 are all considered conflicts even though none of them will require making any updates to the working directory. -- cgit v1.2.1 From 6918d81e2c7a778d789bb35af7dae96e4e89ce03 Mon Sep 17 00:00:00 2001 From: Mike Anderson Date: Wed, 25 Sep 2013 11:14:06 +0800 Subject: Fixed formatting of diff-internals.md Indentation for lists was not working correctly. --- docs/diff-internals.md | 66 ++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/docs/diff-internals.md b/docs/diff-internals.md index 53e71f5b5..cf8ad5383 100644 --- a/docs/diff-internals.md +++ b/docs/diff-internals.md @@ -45,44 +45,48 @@ Internal Objects * `git_diff_file_content` is an internal structure that represents the data on one side of an item to be diffed; it is an augmented `git_diff_file` with more flags and the actual file data. -** it is created from a repository plus a) a git_diff_file, b) a git_blob, + + * it is created from a repository plus a) a git_diff_file, b) a git_blob, or c) raw data and size -** there are three main operations on git_diff_file_content: -*** _initialization_ sets up the data structure and does what it can up to, - but not including loading and looking at the actual data -*** _loading_ loads the data, preprocesses it (i.e. applies filters) and - potentially analyzes it (to decide if binary) -*** _free_ releases loaded data and frees any allocated memory + * there are three main operations on git_diff_file_content: + + * _initialization_ sets up the data structure and does what it can up to, + but not including loading and looking at the actual data + * _loading_ loads the data, preprocesses it (i.e. applies filters) and + potentially analyzes it (to decide if binary) + * _free_ releases loaded data and frees any allocated memory * The internal structure of a `git_diff_patch` stores the actual diff between a pair of `git_diff_file_content` items -** it may be "unset" if the items are not diffable -** "empty" if the items are the same -** otherwise it will consist of a set of hunks each of which covers some - number of lines of context, additions and deletions -** a patch is created from two git_diff_file_content items -** a patch is fully instantiated in three phases: -*** initial creation and initialization -*** loading of data and preliminary data examination -*** diffing of data and optional storage of diffs -** (TBD) if a patch is asked to store the diffs and the size of the diff - is significantly smaller than the raw data of the two sides, then the - patch may be flattened using a pool of string data + + * it may be "unset" if the items are not diffable + * "empty" if the items are the same + * otherwise it will consist of a set of hunks each of which covers some + number of lines of context, additions and deletions + * a patch is created from two git_diff_file_content items + * a patch is fully instantiated in three phases: + + * initial creation and initialization + * loading of data and preliminary data examination + * diffing of data and optional storage of diffs + * (TBD) if a patch is asked to store the diffs and the size of the diff + is significantly smaller than the raw data of the two sides, then the + patch may be flattened using a pool of string data * `git_diff_output` is an internal structure that represents an output target for a `git_diff_patch` -** It consists of file, hunk, and line callbacks, plus a payload -** There is a standard flattened output that can be used for plain text output -** Typically we use a `git_xdiff_output` which drives the callbacks via the - xdiff code taken from core Git. + * It consists of file, hunk, and line callbacks, plus a payload + * There is a standard flattened output that can be used for plain text output + * Typically we use a `git_xdiff_output` which drives the callbacks via the + xdiff code taken from core Git. * `git_diff_driver` is an internal structure that encapsulates the logic for a given type of file -** a driver is looked up based on the name and mode of a file. -** the driver can then be used to: -*** determine if a file is binary (by attributes, by git_diff_options - settings, or by examining the content) -*** give you a function pointer that is used to evaluate function context - for hunk headers -** At some point, the logic for getting a filtered version of file content - or calculating the OID of a file may be moved into the driver. + * a driver is looked up based on the name and mode of a file. + * the driver can then be used to: + * determine if a file is binary (by attributes, by git_diff_options + settings, or by examining the content) + * give you a function pointer that is used to evaluate function context + for hunk headers + * At some point, the logic for getting a filtered version of file content + or calculating the OID of a file may be moved into the driver. -- cgit v1.2.1 From e0b267afa841d89ed2258714f1a6fb444f43d33d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 25 Sep 2013 10:49:25 -0400 Subject: That's the refdb, it's not the odb... --- include/git2/sys/refdb_backend.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/git2/sys/refdb_backend.h b/include/git2/sys/refdb_backend.h index e0a24f433..addaa86fd 100644 --- a/include/git2/sys/refdb_backend.h +++ b/include/git2/sys/refdb_backend.h @@ -121,8 +121,8 @@ struct git_refdb_backend { void (*free)(git_refdb_backend *backend); }; -#define GIT_ODB_BACKEND_VERSION 1 -#define GIT_ODB_BACKEND_INIT {GIT_ODB_BACKEND_VERSION} +#define GIT_REFDB_BACKEND_VERSION 1 +#define GIT_REFDB_BACKEND_INIT {GIT_REFDB_BACKEND_VERSION} /** * Constructors for default filesystem-based refdb backend -- cgit v1.2.1 From aa94acf0bcf42450af419e5398a85558d3d8bd24 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 25 Sep 2013 11:53:02 -0700 Subject: The error handling docs are out of date The error handling docs date back to the early error redesign work and don't match up with the route we actually took. This brings them in line with actual practice both for external users and internal implementors, and notes some of the exceptions and possible bugs. --- docs/error-handling.md | 283 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 221 insertions(+), 62 deletions(-) diff --git a/docs/error-handling.md b/docs/error-handling.md index 655afeba8..2dbe64a71 100644 --- a/docs/error-handling.md +++ b/docs/error-handling.md @@ -1,111 +1,270 @@ Error reporting in libgit2 ========================== -Error reporting is performed on an explicit `git_error **` argument, which appears at the end of all API calls that can return an error. Yes, this does clutter the API. - -When a function fails, an error is set on the error variable **and** returns one of the generic error codes. +Libgit2 tries to follow the POSIX style: functions return an `int` value +with 0 (zero) indicating success and negative values indicating an error. +There are specific negative error codes for each "expected failure" +(e.g. `GIT_ENOTFOUND` for files that take a path which might be missing) +and a generic error code (-1) for all critical or non-specific failures +(e.g. running out of memory or system corruption). + +When a negative value is returned, an error message is also set. The +message can be accessed via the `giterr_last` function which will return a +pointer to a `git_error` structure containing the error message text and +the class of error (i.e. what part of the library generated the error). + +For instance: An object lookup by SHA prefix (`git_object_lookup_prefix`) +has two expected failure cases: the SHA is not found at all which returns +`GIT_ENOTFOUND` or the SHA prefix is ambiguous (i.e. two or more objects +share the prefix) which returns `GIT_EAMBIGUOUS`. There are any number of +critical failures (such as a packfile being corrupted, a loose object +having the wrong access permissions, etc.) all of which will return -1. +When the object lookup is successful, it will return 0. + +If libgit2 was compiled with threads enabled (`-DTHREADSAFE=ON` when using +CMake), then the error message will be kept in thread-local storage, so it +will not be modified by other threads. If threads are not enabled, then +the error message is in global data. + +All of the error return codes, the `git_error` type, the error access +functions, and the error classes are defined in `include/git2/errors.h`. +See the documentation there for details on the APIs for accessing, +clearing, and even setting error codes. + +When writing libgit2 code, please be smart and conservative when returning +error codes. Functions usually have a maximum of two or three "expected +errors" and in most cases only one. If you feel there are more possible +expected error scenarios, then the API you are writing may be at too high +a level for core libgit2. + +Example usage +------------- + +When using libgit2, you will typically capture the return value from +functions using an `int` variable and check to see if it is negative. +When that happens, you can, if you wish, look at the specific value or +look at the error message that was generated. ~~~c -int git_repository_open(git_repository **repository, const char *path, git_error **error) { - // perform some opening - if (p_exists(path) < 0) { - giterr_set(error, GITERR_REPOSITORY, "The path '%s' doesn't exist", path); - return GIT_ENOTFOUND; - } + git_repository *repo; + int error = git_repository_open(&repo, "path/to/repo"); - ... + if (error < 0) { + fprintf(stderr, "Could not open repository: %s\n", giterr_last()->message); + exit(1); + } - if (try_to_parse(path, error) < 0) - return GIT_ERROR; + ... use `repo` here ... - ... + git_repository_free(repo); /* void function - no error return code */ } ~~~ -The simple error API --------------------- +Some of the error return values do have meaning. Optionally, you can look +at the specific error values to decide what to do. + +~~~c +{ + git_repository *repo; + const char *path = "path/to/repo"; + int error = git_repository_open(&repo, path); + + if (error < 0) { + if (error == GIT_ENOTFOUND) + fprintf(stderr, "Could not find repository at path '%s'\n", path); + else + fprintf(stderr, "Unable to open repository: %s\n", + giterr_last()->message); + exit(1); + } -- `void giterr_set(git_error **, int, const char *, ...)`: the main function used to set an error. It allocates a new error object and stores it in the passed error pointer. It has no return value. The arguments for `giterr_set` are as follows: + ... happy ... +} +~~~ - - `git_error **error_ptr`: the pointer where the error will be created. - - `int error_class`: the class for the error. This is **not** an error code: this is an specific enum that specifies the error family. The point is to map these families 1-1 with Exception types on higher level languages (e.g. GitRepositoryException) - - `const char *error_str, ...`: the error string, with optional formatting arguments +Some of the higher-level language bindings may use a range of information +from libgit2 to convert error return codes into exceptions, including the +specific error return codes and even the class of error and the error +message returned by `giterr_last`, but the full range of that logic is +beyond the scope of this document. -- `void giterr_free(git_error *)`: takes an error and frees it. This function is available in the external API. +Example internal implementation +------------------------------- -- `void giterr_clear(git_error **)`: clears an error previously set in an error pointer, setting it to NULL and calling `giterr_free` on it. +Internally, libgit2 detects error scenarios, records error messages, and +returns error values. Errors from low-level functions are generally +passed upwards (unless the higher level can either handle the error or +wants to translate the error into something more meaningful). -- `void giterr_propagate(git_error **, git_error *)`: moves an error to a given error pointer, handling the case when the error pointer is NULL (in that case the error gets freed, because it cannot be propagated). +~~~c +int git_repository_open(git_repository **repository, const char *path) +{ + /* perform some logic to open the repository */ + if (p_exists(path) < 0) { + giterr_set(GITERR_REPOSITORY, "The path '%s' doesn't exist", path); + return GIT_ENOTFOUND; + } -The new error code return values --------------------------------- + ... +} +~~~ -We are doing this the POSIX way: one error code for each "expected failure", and a generic error code for all the critical failures. +The public error API +-------------------- -For instance: A reference lookup can have an expected failure (which is when the reference cannot be found), and a critical failure (which could be any of a long list of things that could go wrong, such as the refs packfile being corrupted, a loose ref being written with the wrong permissions, etc). We cannot have distinct error codes for every single error in the library, hence `git_reference_lookup` would return GIT_SUCCESS if the operation was successful, GIT_ENOTFOUND when the reference doesn't exist, and GIT_ERROR when an error happens -- **the error is then detailed in the `git_error` parameter**. +- `const git_error *giterr_last(void)`: The main function used to look up + the last error. This may return NULL if no error has occurred. + Otherwise this should return a `git_error` object indicating the class + of error and the error message that was generated by the library. + + The last error is stored in thread-local storage when libgit2 is + compiled with thread support, so you do not have to worry about another + thread overwriting the value. When thread support is off, the last + error is a global value. + + _Note_ There are some known bugs in the library where this may return + NULL even when an error code was generated. Please report these as + bugs, but in the meantime, please code defensively and check for NULL + when calling this function. + +- `void geterr_clear(void)`: This function clears the last error. The + library will call this when an error is generated by low level function + and the higher level function handles the error. + + _Note_ There are some known bugs in the library where a low level + function's error message is not cleared by higher level code that + handles the error and returns zero. Please report these as bugs, but in + the meantime, a zero return value from a libgit2 API does not guarantee + that `giterr_last()` will return NULL. + +- `void giterr_set_str(int error_class, const char *message)`: This + function can be used when writing a custom backend module to set the + libgit2 error message. See the documentation on this function for its + use. Normal usage of libgit2 will probably never need to call this API. + +- `void giterr_set_oom(void)`: This is a standard function for reporting + an out-of-memory error. It is written in a manner that it doesn't have + to allocate any extra memory in order to record the error, so this is + the best way to report that scenario. + +Deviations from the standard +---------------------------- + +There are some public functions that do not return `int` values. There +are two primary cases: + +* `void` return values: If a function has a `void` return, then it will + never fail. This primary will be used for object destructors. + +* `git_xyz *` return values: These are simple accessor functions where the + only meaningful error would typically be looking something up by index + and having the index be out of bounds. In those cases, the function + will typically return NULL. + +* Boolean return values: There are some cases where a function cannot fail + and wants to return a boolean value. In those cases, we try to return 1 + for true and 0 for false. These cases are rare and the return value for + the function should probably be an `unsigned int` to denote these cases. + If you find an exception, please open an issue and let's fix it. + +There are a few other exceptions to these rules here and there in the +library, but those are extremely rare and should probably be converted +over to other to more standard patterns for usage. Feel free to open +issues pointing these out. + +There are some known bugs in the library where some functions may return a +negative value but not set an error message and some other functions may +return zero (no error) and yet leave an error message set. Please report +these cases as issues and they will be fixed. In the meanwhile, please +code defensively, checking that the return value of `giterr_last` is not +NULL before using it, and not relying on `giterr_last` to return NULL when +a function returns 0 for success. + +The internal error API +---------------------- -Please be smart when returning error codes. Functions have max two "expected errors", and in most cases only one. +- `void giterr_set(int error_class, const char *fmt, ...)`: This is the + main internal function for setting an error. It works like `printf` to + format the error message. See the notes of `giterr_set_str` for a + general description of how error messages are stored (and also about + special handling for `error_class` of `GITERR_OS`). Writing error messages ---------------------- Here are some guidelines when writing error messages: -- Use proper English, and an impersonal or past tenses: *The given path does not exist*, *Failed to lookup object in ODB* +- Use proper English, and an impersonal or past tenses: *The given path + does not exist*, *Failed to lookup object in ODB* -- Use short, direct and objective messages. **One line, max**. libgit2 is a low level library: think that all the messages reported will be thrown as Ruby or Python exceptions. Think how long are common exception messages in those languages. +- Use short, direct and objective messages. **One line, max**. libgit2 is + a low level library: think that all the messages reported will be thrown + as Ruby or Python exceptions. Think how long are common exception + messages in those languages. -- **Do not add redundant information to the error message**, specially information that can be inferred from the context. +- **Do not add redundant information to the error message**, specially + information that can be inferred from the context. - E.g. in `git_repository_open`, do not report a message like "Failed to open repository: path not found". Somebody is - calling that function. If it fails, he already knows that the repository failed to open! + E.g. in `git_repository_open`, do not report a message like "Failed to + open repository: path not found". Somebody is calling that + function. If it fails, they already know that the repository failed to + open! General guidelines for error reporting -------------------------------------- -- We never handle programming errors with these functions. Programming errors are `assert`ed, and when their source is internal, fixed as soon as possible. This is C, people. - - Example of programming errors that would **not** be handled: passing NULL to a function that expects a valid pointer; passing a `git_tree` to a function that expects a `git_commit`. All these cases need to be identified with `assert` and fixed asap. +- Libgit2 does not handle programming errors with these + functions. Programming errors are `assert`ed, and when their source is + internal, fixed as soon as possible. This is C, people. - Example of a runtime error: failing to parse a `git_tree` because it contains invalid data. Failing to open a file because it doesn't exist on disk. These errors would be handled, and a `git_error` would be set. + Example of programming errors that would **not** be handled: passing + NULL to a function that expects a valid pointer; passing a `git_tree` + to a function that expects a `git_commit`. All these cases need to be + identified with `assert` and fixed asap. -- The `git_error **` argument is always the last in the signature of all API calls. No exceptions. + Example of a runtime error: failing to parse a `git_tree` because it + contains invalid data. Failing to open a file because it doesn't exist + on disk. These errors are handled, a meaningful error message is set, + and an error code is returned. -- When the programmer (or us, internally) doesn't need error handling, he can pass `NULL` to the `git_error **` param. This means that the errors won't be *reported*, but obviously they still will be handled (i.e. the failing function will interrupt and return cleanly). This is transparently handled by `giterr_set` +- In general, *do not* try to overwrite errors internally and *do* + propagate error codes from lower level functions to the higher level. + There are some cases where propagating an error code will be more + confusing rather than less, so there are some exceptions to this rule, + but the default behavior should be to simply clean up and pass the error + on up to the caller. -- `git_error *` **must be initialized to `NULL` before passing its value to a function!!** + **WRONG** ~~~c - git_error *err; - git_error *good_error = NULL; - - git_foo_func(arg1, arg2, &error); // invalid: `error` is not initialized - git_foo_func2(arg1, arg2, &good_error); // OK! - git_foo_func3(arg1, arg2, NULL); // OK! But no error reporting! - ~~~ - -- Piling up errors is an error! Don't do this! Errors must always be free'd when a function returns. + int git_commit_parent(...) + { + ... - ~~~c - git_error *error = NULL; + if (git_commit_lookup(parent, repo, parent_id) < 0) { + giterr_set(GITERR_COMMIT, "Overwrite lookup error message"); + return -1; /* mask error code */ + } - git_foo_func1(arg1, &error); - git_foo_func2(arg2, &error); // WRONG! What if func1 failed? `error` would leak! + ... + } ~~~ -- Likewise: do not rethrow errors internally! + **RIGHT** ~~~c - int git_commit_create(..., git_error **error) + int git_commit_parent(...) { - if (git_reference_exists("HEAD", error) < 0) { - /* HEAD does not exist; create it so we can commit... */ - if (git_reference_create("HEAD", error) < 0) { - /* error could be rethrown */ - } - } + ... -- Remember that errors are now allocated, and hence they need to be free'd after they've been used. Failure to do so internally (e.g. in the already seen examples of error piling) will be reported by Valgrind, so we can easily find where are we rethrowing errors. + error = git_commit_lookup(parent, repo, parent_id); + if (error < 0) { + /* cleanup intermediate objects if necessary */ + /* leave error message and propagate error code */ + return error; + } -- Remember that any function that fails **will set an error object**, and that object will be freed. + ... + } + ~~~ -- cgit v1.2.1 From 4a88eb20b9f2471eeb13d47afd946b4c66b72669 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 25 Sep 2013 12:13:09 -0700 Subject: Win32: handle http->https redirects --- src/transports/winhttp.c | 316 ++++++++++++++++++++++++++++------------------- 1 file changed, 192 insertions(+), 124 deletions(-) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 592460f2a..da257ed4c 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -73,7 +73,7 @@ typedef struct { typedef struct { git_smart_subtransport parent; transport_smart *owner; - const char *path; + char *path; char *host; char *port; char *user_from_url; @@ -152,6 +152,7 @@ static int winhttp_stream_connect(winhttp_stream *s) wchar_t *types[] = { L"*/*", NULL }; BOOL peerdist = FALSE; int error = -1, wide_len; + unsigned long disable_redirects = WINHTTP_DISABLE_REDIRECTS; /* Prepare URL */ git_buf_printf(&buf, "%s%s", t->path, s->service_url); @@ -244,6 +245,14 @@ static int winhttp_stream_connect(winhttp_stream *s) git__free(proxy_wide); } + if (!WinHttpSetOption(s->request, + WINHTTP_OPTION_DISABLE_FEATURE, + &disable_redirects, + sizeof(disable_redirects))) { + giterr_set(GITERR_OS, "Failed to disable redirects"); + goto on_error; + } + /* Strip unwanted headers (X-P2P-PeerDist, X-P2P-PeerDistEx) that WinHTTP * adds itself. This option may not be supported by the underlying * platform, so we do not error-check it */ @@ -380,6 +389,142 @@ static int write_chunk(HINTERNET request, const char *buffer, size_t len) return 0; } +static void free_connection_data(winhttp_subtransport *t) +{ + if (t->host) { + git__free(t->host); + t->host = NULL; + } + + if (t->port) { + git__free(t->port); + t->port = NULL; + } + + if (t->user_from_url) { + git__free(t->user_from_url); + t->user_from_url = NULL; + } + + if (t->pass_from_url) { + git__free(t->pass_from_url); + t->pass_from_url = NULL; + } + + if (t->path) { + git__free(t->path); + t->path = NULL; + } +} + +static int set_connection_data_from_url( + winhttp_subtransport *t, const char *url, const char *service_suffix) +{ + int error = 0; + const char *default_port = NULL; + char *original_host = NULL; + const char *original_url = url; + + if (!git__prefixcmp(url, prefix_http)) { + url += strlen(prefix_http); + default_port = "80"; + + if (t->use_ssl) { + giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP not allowed"); + return -1; + } + } + + if (!git__prefixcmp(url, prefix_https)) { + url += strlen(prefix_https); + default_port = "443"; + t->use_ssl = 1; + } + + if (!default_port) { + giterr_set(GITERR_NET, "Unrecognized URL prefix"); + return -1; + } + + /* preserve original host name for checking */ + original_host = t->host; + t->host = NULL; + + free_connection_data(t); + + error = gitno_extract_url_parts( + &t->host, &t->port, &t->user_from_url, &t->pass_from_url, + url, default_port); + + if (!error) { + const char *path = strchr(url, '/'); + size_t pathlen = strlen(path); + size_t suffixlen = service_suffix ? strlen(service_suffix) : 0; + + if (suffixlen && + !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen)) + t->path = git__strndup(path, pathlen - suffixlen); + else + t->path = git__strdup(path); + + /* Allow '/'-led urls, or a change of protocol */ + if (original_host != NULL) { + if (strcmp(original_host, t->host) && original_url[0] != '/') { + giterr_set(GITERR_NET, "Cross host redirect not allowed"); + error = -1; + } + + git__free(original_host); + } + } + + return error; +} + +static int winhttp_connect( + winhttp_subtransport *t, + const char *url) +{ + wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")"; + git_win32_path host; + int32_t port; + const char *default_port = "80"; + + /* Prepare port */ + if (git__strtol32(&port, t->port, NULL, 10) < 0) + return -1; + + /* Prepare host */ + git_win32_path_from_c(host, t->host); + + /* Establish session */ + t->session = WinHttpOpen( + ua, + WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, + WINHTTP_NO_PROXY_NAME, + WINHTTP_NO_PROXY_BYPASS, + 0); + + if (!t->session) { + giterr_set(GITERR_OS, "Failed to init WinHTTP"); + return -1; + } + + /* Establish connection */ + t->connection = WinHttpConnect( + t->session, + host, + (INTERNET_PORT) port, + 0); + + if (!t->connection) { + giterr_set(GITERR_OS, "Failed to connect to host"); + return -1; + } + + return 0; +} + static int winhttp_stream_read( git_smart_subtransport_stream *stream, char *buffer, @@ -511,50 +656,52 @@ replay: /* Check for Windows 7. This workaround is only necessary on * Windows Vista and earlier. Windows 7 is version 6.1. */ - if (!git_has_win32_version(6, 1, 0)) { - wchar_t *location; - DWORD location_length; - int redirect_cmp; - - /* OK, fetch the Location header from the redirect. */ - if (WinHttpQueryHeaders(s->request, - WINHTTP_QUERY_LOCATION, - WINHTTP_HEADER_NAME_BY_INDEX, - WINHTTP_NO_OUTPUT_BUFFER, - &location_length, - WINHTTP_NO_HEADER_INDEX) || - GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - giterr_set(GITERR_OS, "Failed to read Location header"); - return -1; - } - - location = git__malloc(location_length); - GITERR_CHECK_ALLOC(location); - - if (!WinHttpQueryHeaders(s->request, - WINHTTP_QUERY_LOCATION, - WINHTTP_HEADER_NAME_BY_INDEX, - location, - &location_length, - WINHTTP_NO_HEADER_INDEX)) { - giterr_set(GITERR_OS, "Failed to read Location header"); - git__free(location); - return -1; - } + wchar_t *location; + DWORD location_length; + char *location8; + + /* OK, fetch the Location header from the redirect. */ + if (WinHttpQueryHeaders(s->request, + WINHTTP_QUERY_LOCATION, + WINHTTP_HEADER_NAME_BY_INDEX, + WINHTTP_NO_OUTPUT_BUFFER, + &location_length, + WINHTTP_NO_HEADER_INDEX) || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + giterr_set(GITERR_OS, "Failed to read Location header"); + return -1; + } - /* Compare the Location header with the request URI */ - redirect_cmp = wcscmp(location, s->request_uri); + location = git__malloc(location_length); + location8 = git__malloc(location_length); + GITERR_CHECK_ALLOC(location); + + if (!WinHttpQueryHeaders(s->request, + WINHTTP_QUERY_LOCATION, + WINHTTP_HEADER_NAME_BY_INDEX, + location, + &location_length, + WINHTTP_NO_HEADER_INDEX)) { + giterr_set(GITERR_OS, "Failed to read Location header"); git__free(location); - - if (!redirect_cmp) { - /* Replay the request */ - WinHttpCloseHandle(s->request); - s->request = NULL; - s->sent_request = 0; - - goto replay; - } + return -1; + } + git__utf16_to_8(location8, location_length, location); + git__free(location); + + /* Replay the request */ + WinHttpCloseHandle(s->request); + s->request = NULL; + s->sent_request = 0; + + if (!git__prefixcmp_icase(location8, prefix_https)) { + /* Upgrade to secure connection; disconnect and start over */ + set_connection_data_from_url(t, location8, s->service_url); + winhttp_connect(t, location8); } + + git__free(location8); + goto replay; } /* Handle authentication failures */ @@ -888,68 +1035,6 @@ static int winhttp_stream_alloc(winhttp_subtransport *t, winhttp_stream **stream return 0; } -static int winhttp_connect( - winhttp_subtransport *t, - const char *url) -{ - wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")"; - git_win32_path host; - int32_t port; - const char *default_port = "80"; - int ret; - - if (!git__prefixcmp(url, prefix_http)) { - url = url + strlen(prefix_http); - default_port = "80"; - } - - if (!git__prefixcmp(url, prefix_https)) { - url += strlen(prefix_https); - default_port = "443"; - t->use_ssl = 1; - } - - if ((ret = gitno_extract_url_parts(&t->host, &t->port, &t->user_from_url, - &t->pass_from_url, url, default_port)) < 0) - return ret; - - t->path = strchr(url, '/'); - - /* Prepare port */ - if (git__strtol32(&port, t->port, NULL, 10) < 0) - return -1; - - /* Prepare host */ - git_win32_path_from_c(host, t->host); - - /* Establish session */ - t->session = WinHttpOpen( - ua, - WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, - WINHTTP_NO_PROXY_NAME, - WINHTTP_NO_PROXY_BYPASS, - 0); - - if (!t->session) { - giterr_set(GITERR_OS, "Failed to init WinHTTP"); - return -1; - } - - /* Establish connection */ - t->connection = WinHttpConnect( - t->session, - host, - (INTERNET_PORT)port, - 0); - - if (!t->connection) { - giterr_set(GITERR_OS, "Failed to connect to host"); - return -1; - } - - return 0; -} - static int winhttp_uploadpack_ls( winhttp_subtransport *t, winhttp_stream *s) @@ -1014,7 +1099,8 @@ static int winhttp_action( int ret = -1; if (!t->connection && - winhttp_connect(t, url) < 0) + (set_connection_data_from_url(t, url, NULL) < 0 || + winhttp_connect(t, url) < 0)) return -1; if (winhttp_stream_alloc(t, &s) < 0) @@ -1056,25 +1142,7 @@ static int winhttp_close(git_smart_subtransport *subtransport) winhttp_subtransport *t = (winhttp_subtransport *)subtransport; int ret = 0; - if (t->host) { - git__free(t->host); - t->host = NULL; - } - - if (t->port) { - git__free(t->port); - t->port = NULL; - } - - if (t->user_from_url) { - git__free(t->user_from_url); - t->user_from_url = NULL; - } - - if (t->pass_from_url) { - git__free(t->pass_from_url); - t->pass_from_url = NULL; - } + free_connection_data(t); if (t->cred) { t->cred->free(t->cred); -- cgit v1.2.1 From ac316e743878908df762cc0ea07a71cbee5c5802 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 25 Sep 2013 14:25:38 -0700 Subject: Why are we disabling redirects? --- src/transports/winhttp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index da257ed4c..377f2ef97 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -245,6 +245,9 @@ static int winhttp_stream_connect(winhttp_stream *s) git__free(proxy_wide); } + /* Disable WinHTTP redirects so we can handle them manually. Why, you ask? + * http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/b2ff8879-ab9f-4218-8f09-16d25dff87ae + */ if (!WinHttpSetOption(s->request, WINHTTP_OPTION_DISABLE_FEATURE, &disable_redirects, -- cgit v1.2.1 From 49781a03f0ea2d33b465010c5533b6026cbc1141 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 25 Sep 2013 14:40:19 -0700 Subject: Blame: minor cleanup --- include/git2/object.h | 2 +- src/blame_git.c | 7 ++++--- src/blame_git.h | 1 - 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/git2/object.h b/include/git2/object.h index 7ec17cd8e..c40631fa6 100644 --- a/include/git2/object.h +++ b/include/git2/object.h @@ -36,7 +36,7 @@ GIT_BEGIN_DECL * @param repo the repository to look up the object * @param id the unique identifier for the object * @param type the type of the object - * @return a reference to the object + * @return 0 or an error code */ GIT_EXTERN(int) git_object_lookup( git_object **object, diff --git a/src/blame_git.c b/src/blame_git.c index 94e13f8ef..4df65139a 100644 --- a/src/blame_git.c +++ b/src/blame_git.c @@ -8,6 +8,7 @@ #include "blame_git.h" #include "commit.h" #include "blob.h" +#include "xdiff/xinclude.h" /* * Origin is refcounted and usually we keep the blob contents to be @@ -108,9 +109,9 @@ static int find_last_in_target(git_blame *blame, git_blame__origin *target) * * <---- e -----> * <------> (entirely within) - * <------------> (overlaps after) - * <------------> (overlaps before) - * <------------------> (overlaps both) + * <------------> (extends past) + * <------------> (starts before) + * <------------------> (entirely encloses) * * Split e into potentially three parts; before this chunk, the chunk * to be blamed for the parent, and after that portion. diff --git a/src/blame_git.h b/src/blame_git.h index 2b780116b..3ec2710b8 100644 --- a/src/blame_git.h +++ b/src/blame_git.h @@ -8,7 +8,6 @@ #define INCLUDE_blame_git__ #include "blame.h" -#include "xdiff/xinclude.h" int git_blame__get_origin( git_blame__origin **out, -- cgit v1.2.1 From f7db1b6f26837b44a5cb8956c23bbbdff28ba4f7 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 25 Sep 2013 14:46:59 -0700 Subject: Trim API, document which parts aren't done --- include/git2/blame.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/git2/blame.h b/include/git2/blame.h index 652bc8180..ba3580fcf 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -26,18 +26,20 @@ GIT_BEGIN_DECL typedef enum { /** Normal blame, the default */ GIT_BLAME_NORMAL = 0, - /** Track lines that have moved within a file (like `git blame -M`) */ + /** Track lines that have moved within a file (like `git blame -M`). + * NOT IMPLEMENTED. */ GIT_BLAME_TRACK_COPIES_SAME_FILE = (1<<0), - /** Track lines that have moved across files in the same commit (like `git blame -C`) */ + /** Track lines that have moved across files in the same commit (like `git blame -C`). + * NOT IMPLEMENTED. */ GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES = (1<<1), /** Track lines that have been copied from another file that exists in the - * same commit (like `git blame -CC`) */ + * same commit (like `git blame -CC`). + * NOT IMPLEMENTED. */ GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES = (1<<1 | 1<<2), /** Track lines that have been copied from another file that exists in *any* - * commit (like `git blame -CCC`) */ + * commit (like `git blame -CCC`). + * NOT IMPLEMENTED. */ GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<1 | 1<<2 | 1<<3), - /** Track through file renames */ - GIT_BLAME_TRACK_FILE_RENAMES = (1<<4), } git_blame_flag_t; /** -- cgit v1.2.1 From 8988688c479c6e511432187c7e7e746aefb23c08 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 25 Sep 2013 20:41:56 -0700 Subject: Migrate redirect URL handling to common utility --- src/netops.c | 75 +++++++++++++++++++++++++++++++ src/netops.h | 25 +++++++++++ src/transports/http.c | 102 +++++++++++++----------------------------- tests-clar/network/urlparse.c | 42 +++++++++++++++++ 4 files changed, 172 insertions(+), 72 deletions(-) diff --git a/src/netops.c b/src/netops.c index c1e74546f..bda064cfb 100644 --- a/src/netops.c +++ b/src/netops.c @@ -573,6 +573,81 @@ int gitno_select_in(gitno_buffer *buf, long int sec, long int usec) return select((int)buf->socket->socket + 1, &fds, NULL, NULL, &tv); } +static const char *prefix_http = "http://"; +static const char *prefix_https = "https://"; + +int gitno_connection_data_from_url( + gitno_connection_data *data, + const char *url, + const char *service_suffix, + const char *original_host, + bool original_use_ssl) +{ + int error = 0; + const char *default_port = NULL; + + /* service_suffix is optional */ + assert(data && url); + + if (!git__prefixcmp(url, prefix_http)) { + url = url + strlen(prefix_http); + default_port = "80"; + + if (data->use_ssl) { + giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP is not allowed"); + return -1; + } + } + + if (!git__prefixcmp(url, prefix_https)) { + url += strlen(prefix_https); + default_port = "443"; + data->use_ssl = true; + } + + if (!default_port) { + giterr_set(GITERR_NET, "Unrecognized URL prefix"); + return -1; + } + + error = gitno_extract_url_parts( + &data->host, &data->port, &data->user, &data->pass, + url, default_port); + + if (!error) { + const char *path = strchr(url, '/'); + size_t pathlen = strlen(path); + size_t suffixlen = service_suffix ? strlen(service_suffix) : 0; + + if (suffixlen && + !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen)) + data->path = git__strndup(path, pathlen - suffixlen); + else + data->path = git__strdup(path); + + /* Check for errors in the resulting data */ + if (original_use_ssl && !data->use_ssl) { + giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP not allowed"); + error = -1; + } + if (original_host && url[0] != '/' && strcmp(original_host, data->host)) { + giterr_set(GITERR_NET, "Cross host redirect not allowed"); + error = -1; + } + } + + return error; +} + +void gitno_connection_data_free_ptrs(gitno_connection_data *d) +{ + git__free(d->host); d->host = NULL; + git__free(d->port); d->port = NULL; + git__free(d->path); d->path = NULL; + git__free(d->user); d->user = NULL; + git__free(d->pass); d->pass = NULL; +} + int gitno_extract_url_parts( char **host, char **port, diff --git a/src/netops.h b/src/netops.h index d352bf3b6..0c6e571d9 100644 --- a/src/netops.h +++ b/src/netops.h @@ -66,6 +66,31 @@ int gitno_send(gitno_socket *socket, const char *msg, size_t len, int flags); int gitno_close(gitno_socket *s); int gitno_select_in(gitno_buffer *buf, long int sec, long int usec); +typedef struct gitno_connection_data { + char *host; + char *port; + char *path; + char *user; + char *pass; + bool use_ssl; +} gitno_connection_data; + +/* + * This replaces all the pointers in `data` with freshly-allocated strings, + * that the caller is responsible for freeing. + * `gitno_connection_data_free_ptrs` is good for this. + */ + +int gitno_connection_data_from_url( + gitno_connection_data *data, + const char *url, + const char *service_suffix, + const char *original_host, + bool original_use_ssl); + +/* This frees all the pointers IN the struct, but not the struct itself. */ +void gitno_connection_data_free_ptrs(gitno_connection_data *data); + int gitno_extract_url_parts( char **host, char **port, diff --git a/src/transports/http.c b/src/transports/http.c index ab2f9a47f..8d28d5b47 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -67,8 +67,8 @@ typedef struct { git_cred *cred; git_cred *url_cred; http_authmechanism_t auth_mechanism; - unsigned connected : 1, - use_ssl : 1; + bool connected, + use_ssl; /* Parser structures */ http_parser parser; @@ -277,70 +277,6 @@ static void free_connection_data(http_subtransport *t) } } -static int set_connection_data_from_url( - http_subtransport *t, const char *url, const char *service_suffix) -{ - int error = 0; - const char *default_port = NULL; - char *original_host = NULL; - - if (!git__prefixcmp(url, prefix_http)) { - url = url + strlen(prefix_http); - default_port = "80"; - - if (t->use_ssl) { - giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP not allowed"); - return -1; - } - } - - if (!git__prefixcmp(url, prefix_https)) { - url += strlen(prefix_https); - default_port = "443"; - t->use_ssl = 1; - } - - if (!default_port) { - giterr_set(GITERR_NET, "Unrecognized URL prefix"); - return -1; - } - - /* preserve original host name for checking */ - original_host = t->host; - t->host = NULL; - - free_connection_data(t); - - error = gitno_extract_url_parts( - &t->host, &t->port, &t->user_from_url, &t->pass_from_url, - url, default_port); - - if (!error) { - const char *path = strchr(url, '/'); - size_t pathlen = strlen(path); - size_t suffixlen = service_suffix ? strlen(service_suffix) : 0; - - if (suffixlen && - !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen)) - t->path = git__strndup(path, pathlen - suffixlen); - else - t->path = git__strdup(path); - - /* Allow '/'-led urls, or a change of protocol */ - if (original_host != NULL) { - if (strcmp(original_host, t->host) && t->location[0] != '/') { - giterr_set(GITERR_NET, "Cross host redirect not allowed"); - error = -1; - } - - git__free(original_host); - } - } - - return error; -} - - static int on_headers_complete(http_parser *parser) { parser_context *ctx = (parser_context *) parser->data; @@ -384,18 +320,30 @@ static int on_headers_complete(http_parser *parser) /* Check for a redirect. * Right now we only permit a redirect to the same hostname. */ if ((parser->status_code == 301 || - parser->status_code == 302 || - (parser->status_code == 303 && get_verb == s->verb) || - parser->status_code == 307) && - t->location) { + parser->status_code == 302 || + (parser->status_code == 303 && get_verb == s->verb) || + parser->status_code == 307) && + t->location) { + gitno_connection_data connection_data = {0}; if (s->redirect_count >= 7) { giterr_set(GITERR_NET, "Too many redirects"); return t->parse_error = PARSE_ERROR_GENERIC; } - if (set_connection_data_from_url(t, t->location, s->service_url) < 0) + if (gitno_connection_data_from_url(&connection_data, t->location, + s->service_url, t->host, t->use_ssl) < 0) { + gitno_connection_data_free_ptrs(&connection_data); return t->parse_error = PARSE_ERROR_GENERIC; + } + + free_connection_data(t); + t->host = connection_data.host; + t->port = connection_data.port; + t->path = connection_data.path; + t->user_from_url = connection_data.user; + t->pass_from_url = connection_data.pass; + t->use_ssl = connection_data.use_ssl; /* Set the redirect URL on the stream. This is a transfer of * ownership of the memory. */ @@ -912,8 +860,18 @@ static int http_action( return -1; if (!t->host || !t->port || !t->path) { - if ((ret = set_connection_data_from_url(t, url, NULL)) < 0) + gitno_connection_data data = {0}; + if ((ret = gitno_connection_data_from_url(&data, + url, NULL, NULL, false)) < 0) { + gitno_connection_data_free_ptrs(&data); return ret; + } + t->host = data.host; + t->port = data.port; + t->path = data.path; + t->user_from_url = data.user; + t->pass_from_url = data.pass; + t->use_ssl = data.use_ssl; } if (http_connect(t) < 0) diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c index 173e57d0f..66f714823 100644 --- a/tests-clar/network/urlparse.c +++ b/tests-clar/network/urlparse.c @@ -2,10 +2,12 @@ #include "netops.h" char *host, *port, *user, *pass; +gitno_connection_data conndata; void test_network_urlparse__initialize(void) { host = port = user = pass = NULL; + memset(&conndata, 0, sizeof(conndata)); } void test_network_urlparse__cleanup(void) @@ -15,6 +17,8 @@ void test_network_urlparse__cleanup(void) FREE_AND_NULL(port); FREE_AND_NULL(user); FREE_AND_NULL(pass); + + gitno_connection_data_free_ptrs(&conndata); } void test_network_urlparse__trivial(void) @@ -80,3 +84,41 @@ void test_network_urlparse__user_pass_port(void) cl_assert_equal_s(user, "user"); cl_assert_equal_s(pass, "pass"); } + +void test_network_urlparse__connection_data_http(void) +{ + cl_git_pass(gitno_connection_data_from_url(&conndata, + "http://example.com/foo/bar/baz", "bar/baz", NULL, false)); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/foo/"); + cl_assert_equal_p(conndata.user, NULL); + cl_assert_equal_p(conndata.pass, NULL); + cl_assert_equal_i(conndata.use_ssl, false); +} + +void test_network_urlparse__connection_data_ssl(void) +{ + cl_git_pass(gitno_connection_data_from_url(&conndata, + "https://example.com/foo/bar/baz", "bar/baz", NULL, false)); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/foo/"); + cl_assert_equal_p(conndata.user, NULL); + cl_assert_equal_p(conndata.pass, NULL); + cl_assert_equal_i(conndata.use_ssl, true); +} + +void test_network_urlparse__connection_data_cross_host_redirect(void) +{ + cl_git_fail_with(gitno_connection_data_from_url(&conndata, + "https://foo.com/bar/baz", NULL, "bar.com", true), + -1); +} + +void test_network_urlparse__connection_data_http_downgrade(void) +{ + cl_git_fail_with(gitno_connection_data_from_url(&conndata, + "http://foo.com/bar/baz", NULL, NULL, true), + -1); +} -- cgit v1.2.1 From f30d91ce48f444031b1c65749758008c6f204130 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 26 Sep 2013 11:03:27 -0700 Subject: Refactor URL handling to use library call --- src/transports/winhttp.c | 97 ++++++++++++++---------------------------------- 1 file changed, 28 insertions(+), 69 deletions(-) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 377f2ef97..7ec936d69 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -420,70 +420,6 @@ static void free_connection_data(winhttp_subtransport *t) } } -static int set_connection_data_from_url( - winhttp_subtransport *t, const char *url, const char *service_suffix) -{ - int error = 0; - const char *default_port = NULL; - char *original_host = NULL; - const char *original_url = url; - - if (!git__prefixcmp(url, prefix_http)) { - url += strlen(prefix_http); - default_port = "80"; - - if (t->use_ssl) { - giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP not allowed"); - return -1; - } - } - - if (!git__prefixcmp(url, prefix_https)) { - url += strlen(prefix_https); - default_port = "443"; - t->use_ssl = 1; - } - - if (!default_port) { - giterr_set(GITERR_NET, "Unrecognized URL prefix"); - return -1; - } - - /* preserve original host name for checking */ - original_host = t->host; - t->host = NULL; - - free_connection_data(t); - - error = gitno_extract_url_parts( - &t->host, &t->port, &t->user_from_url, &t->pass_from_url, - url, default_port); - - if (!error) { - const char *path = strchr(url, '/'); - size_t pathlen = strlen(path); - size_t suffixlen = service_suffix ? strlen(service_suffix) : 0; - - if (suffixlen && - !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen)) - t->path = git__strndup(path, pathlen - suffixlen); - else - t->path = git__strdup(path); - - /* Allow '/'-led urls, or a change of protocol */ - if (original_host != NULL) { - if (strcmp(original_host, t->host) && original_url[0] != '/') { - giterr_set(GITERR_NET, "Cross host redirect not allowed"); - error = -1; - } - - git__free(original_host); - } - } - - return error; -} - static int winhttp_connect( winhttp_subtransport *t, const char *url) @@ -699,7 +635,18 @@ replay: if (!git__prefixcmp_icase(location8, prefix_https)) { /* Upgrade to secure connection; disconnect and start over */ - set_connection_data_from_url(t, location8, s->service_url); + gitno_connection_data data = { 0 }; + if (gitno_connection_data_from_url(&data, location8, s->service_url, t->host, t->use_ssl) < 0) { + gitno_connection_data_free_ptrs(&data); + return -1; + } + free_connection_data(t); + t->host = data.host; + t->port = data.port; + t->path = data.path; + t->user_from_url = data.user; + t->pass_from_url = data.pass; + t->use_ssl = data.use_ssl; winhttp_connect(t, location8); } @@ -1101,10 +1048,22 @@ static int winhttp_action( winhttp_stream *s; int ret = -1; - if (!t->connection && - (set_connection_data_from_url(t, url, NULL) < 0 || - winhttp_connect(t, url) < 0)) - return -1; + if (!t->connection) { + gitno_connection_data data = { 0 }; + if (gitno_connection_data_from_url(&data, url, NULL, NULL, false) < 0) { + gitno_connection_data_free_ptrs(&data); + return -1; + } + free_connection_data(t); + t->host = data.host; + t->port = data.port; + t->path = data.path; + t->user_from_url = data.user; + t->pass_from_url = data.pass; + t->use_ssl = data.use_ssl; + if (winhttp_connect(t, url) < 0) + return -1; + } if (winhttp_stream_alloc(t, &s) < 0) return -1; -- cgit v1.2.1 From 8a1e925dde2f7deaf640757b1c309fcc6be1b0e1 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Thu, 26 Sep 2013 12:00:35 +0200 Subject: Fix warnings --- src/indexer.c | 2 +- tests-clar/clar_libgit2.c | 2 +- tests-clar/clar_libgit2.h | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index ceb11f0b6..3b160df5d 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -426,7 +426,7 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz if (git_filebuf_write(&idx->pack_file, data, size) < 0) return -1; - hash_partially(idx, data, size); + hash_partially(idx, data, (int)size); /* Make sure we set the new size of the pack */ if (idx->opened_pack) { diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 555af38db..6063bf91c 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -440,7 +440,7 @@ void clar__assert_equal_file( int ignore_cr, const char *path, const char *file, - size_t line) + int line) { char buf[4000]; ssize_t bytes, total_bytes = 0; diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index 9d4d63e6c..b9ef5627e 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -44,7 +44,7 @@ GIT_INLINE(void) clar__assert_in_range( } #define cl_assert_equal_sz(sz1,sz2) do { \ - size_t __sz1 = (sz1), __sz2 = (sz2); \ + size_t __sz1 = (size_t)(sz1), __sz2 = (size_t)(sz2); \ clar__assert_equal(__FILE__,__LINE__,#sz1 " != " #sz2, 1, "%"PRIuZ, __sz1, __sz2); \ } while (0) @@ -52,10 +52,10 @@ GIT_INLINE(void) clar__assert_in_range( clar__assert_in_range((L),(V),(H),__FILE__,__LINE__,"Range check: " #V " in [" #L "," #H "]", 1) #define cl_assert_equal_file(DATA,SIZE,PATH) \ - clar__assert_equal_file(DATA,SIZE,0,PATH,__FILE__,__LINE__) + clar__assert_equal_file(DATA,SIZE,0,PATH,__FILE__,(int)__LINE__) #define cl_assert_equal_file_ignore_cr(DATA,SIZE,PATH) \ - clar__assert_equal_file(DATA,SIZE,1,PATH,__FILE__,__LINE__) + clar__assert_equal_file(DATA,SIZE,1,PATH,__FILE__,(int)__LINE__) void clar__assert_equal_file( const char *expected_data, @@ -63,7 +63,7 @@ void clar__assert_equal_file( int ignore_cr, const char *path, const char *file, - size_t line); + int line); /* * Some utility macros for building long strings -- cgit v1.2.1 From 83fbd36869e9126bd0fd2139af4d8f4c45865266 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 26 Sep 2013 15:58:41 -0700 Subject: Deploy gitno_connection_data into transport --- src/transports/http.c | 89 +++++++++------------------------------------------ 1 file changed, 16 insertions(+), 73 deletions(-) diff --git a/src/transports/http.c b/src/transports/http.c index 8d28d5b47..81157889e 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -12,8 +12,6 @@ #include "netops.h" #include "smart.h" -static const char *prefix_http = "http://"; -static const char *prefix_https = "https://"; static const char *upload_pack_service = "upload-pack"; static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack"; static const char *upload_pack_service_url = "/git-upload-pack"; @@ -59,16 +57,11 @@ typedef struct { git_smart_subtransport parent; transport_smart *owner; gitno_socket socket; - char *path; - char *host; - char *port; - char *user_from_url; - char *pass_from_url; + gitno_connection_data connection_data; git_cred *cred; git_cred *url_cred; http_authmechanism_t auth_mechanism; - bool connected, - use_ssl; + bool connected; /* Parser structures */ http_parser parser; @@ -125,12 +118,12 @@ static int gen_request( size_t content_length) { http_subtransport *t = OWNING_SUBTRANSPORT(s); - const char *path = t->path ? t->path : "/"; + const char *path = t->connection_data.path ? t->connection_data.path : "/"; git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n", s->verb, path, s->service_url); git_buf_puts(buf, "User-Agent: git/1.0 (libgit2 " LIBGIT2_VERSION ")\r\n"); - git_buf_printf(buf, "Host: %s\r\n", t->host); + git_buf_printf(buf, "Host: %s\r\n", t->connection_data.host); if (s->chunked || content_length > 0) { git_buf_printf(buf, "Accept: application/x-git-%s-result\r\n", s->service); @@ -150,9 +143,9 @@ static int gen_request( return -1; /* Use url-parsed basic auth if username and password are both provided */ - if (!t->cred && t->user_from_url && t->pass_from_url) { - if (!t->url_cred && - git_cred_userpass_plaintext_new(&t->url_cred, t->user_from_url, t->pass_from_url) < 0) + if (!t->cred && t->connection_data.user && t->connection_data.pass) { + if (!t->url_cred && git_cred_userpass_plaintext_new(&t->url_cred, + t->connection_data.user, t->connection_data.pass) < 0) return -1; if (apply_basic_credential(buf, t->url_cred) < 0) return -1; } @@ -249,34 +242,6 @@ static int on_header_value(http_parser *parser, const char *str, size_t len) return 0; } -static void free_connection_data(http_subtransport *t) -{ - if (t->host) { - git__free(t->host); - t->host = NULL; - } - - if (t->port) { - git__free(t->port); - t->port = NULL; - } - - if (t->user_from_url) { - git__free(t->user_from_url); - t->user_from_url = NULL; - } - - if (t->pass_from_url) { - git__free(t->pass_from_url); - t->pass_from_url = NULL; - } - - if (t->path) { - git__free(t->path); - t->path = NULL; - } -} - static int on_headers_complete(http_parser *parser) { parser_context *ctx = (parser_context *) parser->data; @@ -305,7 +270,7 @@ static int on_headers_complete(http_parser *parser) if (t->owner->cred_acquire_cb(&t->cred, t->owner->url, - t->user_from_url, + t->connection_data.user, allowed_types, t->owner->cred_acquire_payload) < 0) return PARSE_ERROR_GENERIC; @@ -324,26 +289,15 @@ static int on_headers_complete(http_parser *parser) (parser->status_code == 303 && get_verb == s->verb) || parser->status_code == 307) && t->location) { - gitno_connection_data connection_data = {0}; if (s->redirect_count >= 7) { giterr_set(GITERR_NET, "Too many redirects"); return t->parse_error = PARSE_ERROR_GENERIC; } - if (gitno_connection_data_from_url(&connection_data, t->location, - s->service_url, t->host, t->use_ssl) < 0) { - gitno_connection_data_free_ptrs(&connection_data); + if (gitno_connection_data_from_url(&t->connection_data, t->location, + s->service_url, t->connection_data.host, t->connection_data.use_ssl) < 0) return t->parse_error = PARSE_ERROR_GENERIC; - } - - free_connection_data(t); - t->host = connection_data.host; - t->port = connection_data.port; - t->path = connection_data.path; - t->user_from_url = connection_data.user; - t->pass_from_url = connection_data.pass; - t->use_ssl = connection_data.use_ssl; /* Set the redirect URL on the stream. This is a transfer of * ownership of the memory. */ @@ -500,7 +454,7 @@ static int http_connect(http_subtransport *t) if (t->socket.socket) gitno_close(&t->socket); - if (t->use_ssl) { + if (t->connection_data.use_ssl) { int tflags; if (t->owner->parent.read_flags(&t->owner->parent, &tflags) < 0) @@ -512,7 +466,7 @@ static int http_connect(http_subtransport *t) flags |= GITNO_CONNECT_SSL_NO_CHECK_CERT; } - if (gitno_connect(&t->socket, t->host, t->port, flags) < 0) + if (gitno_connect(&t->socket, t->connection_data.host, t->connection_data.port, flags) < 0) return -1; t->connected = 1; @@ -859,20 +813,9 @@ static int http_action( if (!stream) return -1; - if (!t->host || !t->port || !t->path) { - gitno_connection_data data = {0}; - if ((ret = gitno_connection_data_from_url(&data, - url, NULL, NULL, false)) < 0) { - gitno_connection_data_free_ptrs(&data); - return ret; - } - t->host = data.host; - t->port = data.port; - t->path = data.path; - t->user_from_url = data.user; - t->pass_from_url = data.pass; - t->use_ssl = data.use_ssl; - } + if ((!t->connection_data.host || !t->connection_data.port || !t->connection_data.path) && + (ret = gitno_connection_data_from_url(&t->connection_data, url, NULL, NULL, false)) < 0) + return ret; if (http_connect(t) < 0) return -1; @@ -916,7 +859,7 @@ static int http_close(git_smart_subtransport *subtransport) t->url_cred = NULL; } - free_connection_data(t); + gitno_connection_data_free_ptrs(&t->connection_data); return 0; } -- cgit v1.2.1 From ea59f6597707107940d2a615b5fc4621d62149d3 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 26 Sep 2013 16:20:30 -0700 Subject: Deploy gitno_connection_data into transport (winhttp) ...and have that call manage replaced memory in the output structure. --- src/netops.c | 22 +++++++---- src/netops.h | 4 +- src/transports/winhttp.c | 85 ++++++++----------------------------------- tests-clar/network/urlparse.c | 10 +++-- 4 files changed, 38 insertions(+), 83 deletions(-) diff --git a/src/netops.c b/src/netops.c index bda064cfb..aca46245d 100644 --- a/src/netops.c +++ b/src/netops.c @@ -579,23 +579,29 @@ static const char *prefix_https = "https://"; int gitno_connection_data_from_url( gitno_connection_data *data, const char *url, - const char *service_suffix, - const char *original_host, - bool original_use_ssl) + const char *service_suffix) { - int error = 0; + int error = -1; const char *default_port = NULL; + char *original_host = NULL; + bool original_use_ssl; /* service_suffix is optional */ assert(data && url); + /* Save these for comparison later */ + if (data->host) + original_host = git__strdup(data->host); + original_use_ssl = data->use_ssl; + gitno_connection_data_free_ptrs(data); + if (!git__prefixcmp(url, prefix_http)) { url = url + strlen(prefix_http); default_port = "80"; if (data->use_ssl) { giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP is not allowed"); - return -1; + goto cleanup; } } @@ -607,7 +613,7 @@ int gitno_connection_data_from_url( if (!default_port) { giterr_set(GITERR_NET, "Unrecognized URL prefix"); - return -1; + goto cleanup; } error = gitno_extract_url_parts( @@ -620,7 +626,7 @@ int gitno_connection_data_from_url( size_t suffixlen = service_suffix ? strlen(service_suffix) : 0; if (suffixlen && - !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen)) + !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen)) data->path = git__strndup(path, pathlen - suffixlen); else data->path = git__strdup(path); @@ -636,6 +642,8 @@ int gitno_connection_data_from_url( } } +cleanup: + if (original_host) git__free(original_host); return error; } diff --git a/src/netops.h b/src/netops.h index 0c6e571d9..5c105d6e3 100644 --- a/src/netops.h +++ b/src/netops.h @@ -84,9 +84,7 @@ typedef struct gitno_connection_data { int gitno_connection_data_from_url( gitno_connection_data *data, const char *url, - const char *service_suffix, - const char *original_host, - bool original_use_ssl); + const char *service_suffix); /* This frees all the pointers IN the struct, but not the struct itself. */ void gitno_connection_data_free_ptrs(gitno_connection_data *data); diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 7ec936d69..e2a4acf61 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -73,17 +73,12 @@ typedef struct { typedef struct { git_smart_subtransport parent; transport_smart *owner; - char *path; - char *host; - char *port; - char *user_from_url; - char *pass_from_url; + gitno_connection_data connection_data; git_cred *cred; git_cred *url_cred; int auth_mechanism; HINTERNET session; HINTERNET connection; - unsigned use_ssl : 1; } winhttp_subtransport; static int apply_basic_credential(HINTERNET request, git_cred *cred) @@ -155,7 +150,7 @@ static int winhttp_stream_connect(winhttp_stream *s) unsigned long disable_redirects = WINHTTP_DISABLE_REDIRECTS; /* Prepare URL */ - git_buf_printf(&buf, "%s%s", t->path, s->service_url); + git_buf_printf(&buf, "%s%s", t->connection_data.path, s->service_url); if (git_buf_oom(&buf)) return -1; @@ -188,7 +183,7 @@ static int winhttp_stream_connect(winhttp_stream *s) NULL, WINHTTP_NO_REFERER, types, - t->use_ssl ? WINHTTP_FLAG_SECURE : 0); + t->connection_data.use_ssl ? WINHTTP_FLAG_SECURE : 0); if (!s->request) { giterr_set(GITERR_OS, "Failed to open request"); @@ -196,7 +191,7 @@ static int winhttp_stream_connect(winhttp_stream *s) } /* Set proxy if necessary */ - if (git_remote__get_http_proxy(t->owner->owner, !!t->use_ssl, &proxy_url) < 0) + if (git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &proxy_url) < 0) goto on_error; if (proxy_url) { @@ -285,7 +280,7 @@ static int winhttp_stream_connect(winhttp_stream *s) } /* If requested, disable certificate validation */ - if (t->use_ssl) { + if (t->connection_data.use_ssl) { int flags; if (t->owner->parent.read_flags(&t->owner->parent, &flags) < 0) @@ -308,9 +303,9 @@ static int winhttp_stream_connect(winhttp_stream *s) /* If no other credentials have been applied and the URL has username and * password, use those */ - if (!t->cred && t->user_from_url && t->pass_from_url) { + if (!t->cred && t->connection_data.user && t->connection_data.pass) { if (!t->url_cred && - git_cred_userpass_plaintext_new(&t->url_cred, t->user_from_url, t->pass_from_url) < 0) + 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) goto on_error; @@ -392,34 +387,6 @@ static int write_chunk(HINTERNET request, const char *buffer, size_t len) return 0; } -static void free_connection_data(winhttp_subtransport *t) -{ - if (t->host) { - git__free(t->host); - t->host = NULL; - } - - if (t->port) { - git__free(t->port); - t->port = NULL; - } - - if (t->user_from_url) { - git__free(t->user_from_url); - t->user_from_url = NULL; - } - - if (t->pass_from_url) { - git__free(t->pass_from_url); - t->pass_from_url = NULL; - } - - if (t->path) { - git__free(t->path); - t->path = NULL; - } -} - static int winhttp_connect( winhttp_subtransport *t, const char *url) @@ -430,11 +397,11 @@ static int winhttp_connect( const char *default_port = "80"; /* Prepare port */ - if (git__strtol32(&port, t->port, NULL, 10) < 0) + if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0) return -1; /* Prepare host */ - git_win32_path_from_c(host, t->host); + git_win32_path_from_c(host, t->connection_data.host); /* Establish session */ t->session = WinHttpOpen( @@ -636,17 +603,8 @@ replay: if (!git__prefixcmp_icase(location8, prefix_https)) { /* Upgrade to secure connection; disconnect and start over */ gitno_connection_data data = { 0 }; - if (gitno_connection_data_from_url(&data, location8, s->service_url, t->host, t->use_ssl) < 0) { - gitno_connection_data_free_ptrs(&data); + if (gitno_connection_data_from_url(&data, location8, s->service_url) < 0) return -1; - } - free_connection_data(t); - t->host = data.host; - t->port = data.port; - t->path = data.path; - t->user_from_url = data.user; - t->pass_from_url = data.pass; - t->use_ssl = data.use_ssl; winhttp_connect(t, location8); } @@ -665,7 +623,8 @@ replay: if (allowed_types && (!t->cred || 0 == (t->cred->credtype & allowed_types))) { - if (t->owner->cred_acquire_cb(&t->cred, t->owner->url, t->user_from_url, allowed_types, t->owner->cred_acquire_payload) < 0) + if (t->owner->cred_acquire_cb(&t->cred, t->owner->url, t->connection_data.user, allowed_types, + t->owner->cred_acquire_payload) < 0) return -1; assert(t->cred); @@ -1048,22 +1007,10 @@ static int winhttp_action( winhttp_stream *s; int ret = -1; - if (!t->connection) { - gitno_connection_data data = { 0 }; - if (gitno_connection_data_from_url(&data, url, NULL, NULL, false) < 0) { - gitno_connection_data_free_ptrs(&data); - return -1; - } - free_connection_data(t); - t->host = data.host; - t->port = data.port; - t->path = data.path; - t->user_from_url = data.user; - t->pass_from_url = data.pass; - t->use_ssl = data.use_ssl; - if (winhttp_connect(t, url) < 0) + if (!t->connection) + if (gitno_connection_data_from_url(&t->connection_data, url, NULL) < 0 || + winhttp_connect(t, url) < 0) return -1; - } if (winhttp_stream_alloc(t, &s) < 0) return -1; @@ -1104,7 +1051,7 @@ static int winhttp_close(git_smart_subtransport *subtransport) winhttp_subtransport *t = (winhttp_subtransport *)subtransport; int ret = 0; - free_connection_data(t); + gitno_connection_data_free_ptrs(&t->connection_data); if (t->cred) { t->cred->free(t->cred); diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c index 66f714823..679197d6c 100644 --- a/tests-clar/network/urlparse.c +++ b/tests-clar/network/urlparse.c @@ -88,7 +88,7 @@ void test_network_urlparse__user_pass_port(void) void test_network_urlparse__connection_data_http(void) { cl_git_pass(gitno_connection_data_from_url(&conndata, - "http://example.com/foo/bar/baz", "bar/baz", NULL, false)); + "http://example.com/foo/bar/baz", "bar/baz")); cl_assert_equal_s(conndata.host, "example.com"); cl_assert_equal_s(conndata.port, "80"); cl_assert_equal_s(conndata.path, "/foo/"); @@ -100,7 +100,7 @@ void test_network_urlparse__connection_data_http(void) void test_network_urlparse__connection_data_ssl(void) { cl_git_pass(gitno_connection_data_from_url(&conndata, - "https://example.com/foo/bar/baz", "bar/baz", NULL, false)); + "https://example.com/foo/bar/baz", "bar/baz")); cl_assert_equal_s(conndata.host, "example.com"); cl_assert_equal_s(conndata.port, "443"); cl_assert_equal_s(conndata.path, "/foo/"); @@ -111,14 +111,16 @@ void test_network_urlparse__connection_data_ssl(void) void test_network_urlparse__connection_data_cross_host_redirect(void) { + conndata.host = git__strdup("bar.com"); cl_git_fail_with(gitno_connection_data_from_url(&conndata, - "https://foo.com/bar/baz", NULL, "bar.com", true), + "https://foo.com/bar/baz", NULL), -1); } void test_network_urlparse__connection_data_http_downgrade(void) { + conndata.use_ssl = true; cl_git_fail_with(gitno_connection_data_from_url(&conndata, - "http://foo.com/bar/baz", NULL, NULL, true), + "http://foo.com/bar/baz", NULL), -1); } -- cgit v1.2.1 From 1b02baf40be4913a4f3044987eea85c72ce4b0a7 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 26 Sep 2013 16:25:05 -0700 Subject: Adjust to new utility signature --- src/transports/http.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/transports/http.c b/src/transports/http.c index 81157889e..ace0d97d0 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -295,8 +295,7 @@ static int on_headers_complete(http_parser *parser) return t->parse_error = PARSE_ERROR_GENERIC; } - if (gitno_connection_data_from_url(&t->connection_data, t->location, - s->service_url, t->connection_data.host, t->connection_data.use_ssl) < 0) + if (gitno_connection_data_from_url(&t->connection_data, t->location, s->service_url) < 0) return t->parse_error = PARSE_ERROR_GENERIC; /* Set the redirect URL on the stream. This is a transfer of @@ -814,7 +813,7 @@ static int http_action( return -1; if ((!t->connection_data.host || !t->connection_data.port || !t->connection_data.path) && - (ret = gitno_connection_data_from_url(&t->connection_data, url, NULL, NULL, false)) < 0) + (ret = gitno_connection_data_from_url(&t->connection_data, url, NULL)) < 0) return ret; if (http_connect(t) < 0) -- cgit v1.2.1 From 0049d4d1d2dd4cb6d65ea81ecdc8611a41f0bace Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 26 Sep 2013 16:25:34 -0700 Subject: Make sure utility doesn't leak memory --- tests-clar/network/urlparse.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c index 679197d6c..8892781ad 100644 --- a/tests-clar/network/urlparse.c +++ b/tests-clar/network/urlparse.c @@ -124,3 +124,12 @@ void test_network_urlparse__connection_data_http_downgrade(void) "http://foo.com/bar/baz", NULL), -1); } + +/* Run this under valgrind */ +void test_network_urlparse__connection_data_cleanup(void) +{ + cl_git_pass(gitno_connection_data_from_url(&conndata, + "http://foo.com/bar/baz/biff", "baz/biff")); + cl_git_pass(gitno_connection_data_from_url(&conndata, + "https://foo.com/bar/baz/biff", "baz/biff")); +} -- cgit v1.2.1 From 256961e45d574ace62a7a7d13b697aa05e8a9466 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 26 Sep 2013 16:36:05 -0700 Subject: WHOOPS --- src/transports/winhttp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index e2a4acf61..067d6fcc3 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -602,8 +602,7 @@ replay: if (!git__prefixcmp_icase(location8, prefix_https)) { /* Upgrade to secure connection; disconnect and start over */ - gitno_connection_data data = { 0 }; - if (gitno_connection_data_from_url(&data, location8, s->service_url) < 0) + if (gitno_connection_data_from_url(&t->connection_data, location8, s->service_url) < 0) return -1; winhttp_connect(t, location8); } -- cgit v1.2.1 From b59344bf83049a5639c32ab52efceea2eec9484b Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 26 Sep 2013 16:48:08 -0700 Subject: Tighten up url-connection utility --- src/netops.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/netops.c b/src/netops.c index aca46245d..3257e7749 100644 --- a/src/netops.c +++ b/src/netops.c @@ -584,15 +584,13 @@ int gitno_connection_data_from_url( int error = -1; const char *default_port = NULL; char *original_host = NULL; - bool original_use_ssl; /* service_suffix is optional */ assert(data && url); /* Save these for comparison later */ - if (data->host) - original_host = git__strdup(data->host); - original_use_ssl = data->use_ssl; + original_host = data->host; + data->host = NULL; gitno_connection_data_free_ptrs(data); if (!git__prefixcmp(url, prefix_http)) { @@ -632,10 +630,6 @@ int gitno_connection_data_from_url( data->path = git__strdup(path); /* Check for errors in the resulting data */ - if (original_use_ssl && !data->use_ssl) { - giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP not allowed"); - error = -1; - } if (original_host && url[0] != '/' && strcmp(original_host, data->host)) { giterr_set(GITERR_NET, "Cross host redirect not allowed"); error = -1; -- cgit v1.2.1 From 7d6924541508b453c22fac2ac3bc76fadc0a58ba Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 27 Sep 2013 16:08:24 -0400 Subject: Add refdb.h to git2.h, reorder git2.h sanely --- include/git2.h | 81 +++++++++++++++++++++++++++------------------------------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/include/git2.h b/include/git2.h index 73c11ad83..93049aad9 100644 --- a/include/git2.h +++ b/include/git2.h @@ -8,57 +8,50 @@ #ifndef INCLUDE_git_git_h__ #define INCLUDE_git_git_h__ -#include "git2/version.h" - -#include "git2/common.h" -#include "git2/threads.h" -#include "git2/errors.h" - -#include "git2/types.h" - -#include "git2/oid.h" -#include "git2/signature.h" -#include "git2/odb.h" - -#include "git2/repository.h" -#include "git2/revwalk.h" -#include "git2/merge.h" -#include "git2/graph.h" -#include "git2/refs.h" -#include "git2/reflog.h" -#include "git2/revparse.h" - -#include "git2/object.h" +#include "git2/attr.h" #include "git2/blob.h" +#include "git2/branch.h" +#include "git2/buffer.h" +#include "git2/checkout.h" +#include "git2/clone.h" #include "git2/commit.h" -#include "git2/tag.h" -#include "git2/tree.h" -#include "git2/diff.h" - -#include "git2/index.h" +#include "git2/common.h" #include "git2/config.h" -#include "git2/transport.h" -#include "git2/remote.h" -#include "git2/clone.h" -#include "git2/checkout.h" -#include "git2/push.h" - -#include "git2/attr.h" +#include "git2/diff.h" +#include "git2/errors.h" +#include "git2/filter.h" +#include "git2/graph.h" #include "git2/ignore.h" -#include "git2/branch.h" -#include "git2/refspec.h" -#include "git2/net.h" -#include "git2/status.h" +#include "git2/index.h" #include "git2/indexer.h" -#include "git2/submodule.h" -#include "git2/notes.h" -#include "git2/reset.h" +#include "git2/merge.h" #include "git2/message.h" +#include "git2/net.h" +#include "git2/notes.h" +#include "git2/object.h" +#include "git2/odb.h" +#include "git2/oid.h" #include "git2/pack.h" -#include "git2/stash.h" #include "git2/pathspec.h" - -#include "git2/buffer.h" -#include "git2/filter.h" +#include "git2/push.h" +#include "git2/refdb.h" +#include "git2/reflog.h" +#include "git2/refs.h" +#include "git2/refspec.h" +#include "git2/remote.h" +#include "git2/repository.h" +#include "git2/reset.h" +#include "git2/revparse.h" +#include "git2/revwalk.h" +#include "git2/signature.h" +#include "git2/stash.h" +#include "git2/status.h" +#include "git2/submodule.h" +#include "git2/tag.h" +#include "git2/threads.h" +#include "git2/transport.h" +#include "git2/tree.h" +#include "git2/types.h" +#include "git2/version.h" #endif -- cgit v1.2.1 From 4fe0b0b34b3700d6da681498f0077a455d14812b Mon Sep 17 00:00:00 2001 From: Justin Spahr-Summers Date: Fri, 27 Sep 2013 17:07:06 -0700 Subject: Never consider submodules for stashing --- src/stash.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/stash.c b/src/stash.c index ab4a68575..7742eee19 100644 --- a/src/stash.c +++ b/src/stash.c @@ -316,6 +316,8 @@ static int build_workdir_tree( struct cb_data data = {0}; int error; + opts.flags = GIT_DIFF_IGNORE_SUBMODULES; + if ((error = git_commit_tree(&b_tree, b_commit)) < 0) goto cleanup; @@ -474,12 +476,14 @@ static int ensure_there_are_changes_to_stash( git_status_options opts = GIT_STATUS_OPTIONS_INIT; opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; + opts.flags = GIT_STATUS_OPT_EXCLUDE_SUBMODULES; + if (include_untracked_files) - opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; if (include_ignored_files) - opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED; + opts.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED; error = git_status_foreach_ext(repo, &opts, is_dirty_cb, NULL); -- cgit v1.2.1 From 526d4c949c4b87c01e74a19ab47171ee08c9673a Mon Sep 17 00:00:00 2001 From: Justin Spahr-Summers Date: Fri, 27 Sep 2013 21:39:28 -0700 Subject: Test that submodules don't affect stashing --- tests-clar/stash/save.c | 68 +++++++++++++++------------------------- tests-clar/stash/stash_helpers.c | 19 +++++++++++ tests-clar/stash/stash_helpers.h | 5 +++ tests-clar/stash/submodules.c | 68 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 43 deletions(-) create mode 100644 tests-clar/stash/submodules.c diff --git a/tests-clar/stash/save.c b/tests-clar/stash/save.c index 035b62279..3d92b26bd 100644 --- a/tests-clar/stash/save.c +++ b/tests-clar/stash/save.c @@ -113,33 +113,15 @@ $ git status --short cl_assert_equal_i(GIT_STATUS_WT_NEW, status); } -static void assert_status( - const char *path, - int status_flags) -{ - unsigned int status; - int error; - - error = git_status_file(&status, repo, path); - - if (status_flags < 0) { - cl_assert_equal_i(status_flags, error); - return; - } - - cl_assert_equal_i(0, error); - cl_assert_equal_i((unsigned int)status_flags, status); -} - void test_stash_save__can_keep_index(void) { cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_KEEP_INDEX)); - assert_status("what", GIT_STATUS_INDEX_MODIFIED); - assert_status("how", GIT_STATUS_INDEX_MODIFIED); - assert_status("who", GIT_STATUS_CURRENT); - assert_status("when", GIT_STATUS_WT_NEW); - assert_status("just.ignore", GIT_STATUS_IGNORED); + assert_status(repo, "what", GIT_STATUS_INDEX_MODIFIED); + assert_status(repo, "how", GIT_STATUS_INDEX_MODIFIED); + assert_status(repo, "who", GIT_STATUS_CURRENT); + assert_status(repo, "when", GIT_STATUS_WT_NEW); + assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); } static void assert_commit_message_contains(const char *revision, const char *fragment) @@ -308,25 +290,25 @@ void test_stash_save__can_stage_normal_then_stage_untracked(void) * 100644 blob b6ed15e81e2593d7bb6265eb4a991d29dc3e628b when */ - assert_status("what", GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED); - assert_status("how", GIT_STATUS_INDEX_MODIFIED); - assert_status("who", GIT_STATUS_WT_MODIFIED); - assert_status("when", GIT_STATUS_WT_NEW); - assert_status("just.ignore", GIT_STATUS_IGNORED); + assert_status(repo, "what", GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED); + assert_status(repo, "how", GIT_STATUS_INDEX_MODIFIED); + assert_status(repo, "who", GIT_STATUS_WT_MODIFIED); + assert_status(repo, "when", GIT_STATUS_WT_NEW); + assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); - assert_status("what", GIT_STATUS_CURRENT); - assert_status("how", GIT_STATUS_CURRENT); - assert_status("who", GIT_STATUS_CURRENT); - assert_status("when", GIT_STATUS_WT_NEW); - assert_status("just.ignore", GIT_STATUS_IGNORED); + assert_status(repo, "what", GIT_STATUS_CURRENT); + assert_status(repo, "how", GIT_STATUS_CURRENT); + assert_status(repo, "who", GIT_STATUS_CURRENT); + assert_status(repo, "when", GIT_STATUS_WT_NEW); + assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); - assert_status("what", GIT_STATUS_CURRENT); - assert_status("how", GIT_STATUS_CURRENT); - assert_status("who", GIT_STATUS_CURRENT); - assert_status("when", GIT_ENOTFOUND); - assert_status("just.ignore", GIT_STATUS_IGNORED); + assert_status(repo, "what", GIT_STATUS_CURRENT); + assert_status(repo, "how", GIT_STATUS_CURRENT); + assert_status(repo, "who", GIT_STATUS_CURRENT); + assert_status(repo, "when", GIT_ENOTFOUND); + assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); assert_blob_oid("stash@{1}^0:what", "bc99dc98b3eba0e9157e94769cd4d49cb49de449"); /* see you later */ @@ -360,11 +342,11 @@ void test_stash_save__including_untracked_without_any_untracked_file_creates_an_ { cl_git_pass(p_unlink("stash/when")); - assert_status("what", GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED); - assert_status("how", GIT_STATUS_INDEX_MODIFIED); - assert_status("who", GIT_STATUS_WT_MODIFIED); - assert_status("when", GIT_ENOTFOUND); - assert_status("just.ignore", GIT_STATUS_IGNORED); + assert_status(repo, "what", GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED); + assert_status(repo, "how", GIT_STATUS_INDEX_MODIFIED); + assert_status(repo, "who", GIT_STATUS_WT_MODIFIED); + assert_status(repo, "when", GIT_ENOTFOUND); + assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); diff --git a/tests-clar/stash/stash_helpers.c b/tests-clar/stash/stash_helpers.c index 06b63f177..8b7d685f8 100644 --- a/tests-clar/stash/stash_helpers.c +++ b/tests-clar/stash/stash_helpers.c @@ -35,3 +35,22 @@ void setup_stash(git_repository *repo, git_signature *signature) git_index_free(index); } + +void assert_status( + git_repository *repo, + const char *path, + int status_flags) +{ + unsigned int status; + int error; + + error = git_status_file(&status, repo, path); + + if (status_flags < 0) { + cl_assert_equal_i(status_flags, error); + return; + } + + cl_assert_equal_i(0, error); + cl_assert_equal_i((unsigned int)status_flags, status); +} diff --git a/tests-clar/stash/stash_helpers.h b/tests-clar/stash/stash_helpers.h index 7c3e13de3..66d758fe2 100644 --- a/tests-clar/stash/stash_helpers.h +++ b/tests-clar/stash/stash_helpers.h @@ -1,3 +1,8 @@ void setup_stash( git_repository *repo, git_signature *signature); + +void assert_status( + git_repository *repo, + const char *path, + int status_flags); diff --git a/tests-clar/stash/submodules.c b/tests-clar/stash/submodules.c new file mode 100644 index 000000000..60dbbad2e --- /dev/null +++ b/tests-clar/stash/submodules.c @@ -0,0 +1,68 @@ +#include "clar_libgit2.h" +#include "stash_helpers.h" +#include "../submodule/submodule_helpers.h" + +static git_repository *repo; +static git_signature *signature; +static git_oid stash_tip_oid; + +static git_index *smindex; +static git_submodule *sm; +static git_repository *smrepo; + +void test_stash_submodules__initialize(void) +{ + cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ + + repo = setup_fixture_submodules(); + + cl_git_pass(git_submodule_lookup(&sm, repo, "testrepo")); + cl_git_pass(git_submodule_open(&smrepo, sm)); + cl_git_pass(git_repository_index(&smindex, smrepo)); +} + +void test_stash_submodules__cleanup(void) +{ + git_signature_free(signature); + signature = NULL; +} + +void test_stash_submodules__does_not_stash_modified_submodules(void) +{ + assert_status(repo, "modified", GIT_STATUS_WT_MODIFIED); + + /* modify file in submodule */ + cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); + assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); + + /* add file to index in submodule */ + cl_git_pass(git_index_add_bypath(smindex, "README")); + + /* commit changed index of submodule */ + cl_repo_commit_from_index(NULL, smrepo, NULL, 1372350000, "Modify it"); + assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); + + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); + + assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); + assert_status(repo, "modified", GIT_STATUS_CURRENT); +} + +void test_stash_submodules__stash_is_empty_with_modified_submodules(void) +{ + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); + assert_status(repo, "modified", GIT_STATUS_CURRENT); + + /* modify file in submodule */ + cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); + assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); + + /* add file to index in submodule */ + cl_git_pass(git_index_add_bypath(smindex, "README")); + + /* commit changed index of submodule */ + cl_repo_commit_from_index(NULL, smrepo, NULL, 1372350000, "Modify it"); + assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); + + cl_git_fail_with(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT), GIT_ENOTFOUND); +} -- cgit v1.2.1 From de8fe729efd350ae5cb1ef25ffb08f92c6f706b9 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Sun, 29 Sep 2013 10:46:41 -0700 Subject: Fix typo --- examples/blame.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/blame.c b/examples/blame.c index 1b08ec487..6f6a2749d 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -21,7 +21,7 @@ static void usage(const char *msg, const char *arg) fprintf(stderr, "\n"); fprintf(stderr, " example: `HEAD~10..HEAD`, or `1234abcd`\n"); fprintf(stderr, " -L process only line range n-m, counting from 1\n"); - fprintf(stderr, " -M fine line moves within and across files\n"); + fprintf(stderr, " -M find line moves within and across files\n"); fprintf(stderr, " -C find line copies within and across files\n"); fprintf(stderr, "\n"); exit(1); -- cgit v1.2.1 From 27c8eb2a1a881be12e281b606730ff15a8382ab1 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Mon, 30 Sep 2013 11:18:06 +0200 Subject: Tabify indentations --- tests-clar/commit/parse.c | 164 +++++++++++++++++++++++----------------------- 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/tests-clar/commit/parse.c b/tests-clar/commit/parse.c index 415860a6e..e91815def 100644 --- a/tests-clar/commit/parse.c +++ b/tests-clar/commit/parse.c @@ -7,77 +7,77 @@ static git_repository *g_repo; void test_commit_parse__initialize(void) { - g_repo = cl_git_sandbox_init("testrepo"); + g_repo = cl_git_sandbox_init("testrepo"); } void test_commit_parse__cleanup(void) { - cl_git_sandbox_cleanup(); + cl_git_sandbox_cleanup(); } // Header parsing typedef struct { - const char *line; - const char *header; + const char *line; + const char *header; } parse_test_case; static parse_test_case passing_header_cases[] = { - { "parent 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "parent " }, - { "tree 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree " }, - { "random_heading 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "random_heading " }, - { "stuck_heading05452d6349abcd67aa396dfb28660d765d8b2a36\n", "stuck_heading" }, - { "tree 5F4BEFFC0759261D015AA63A3A85613FF2F235DE\n", "tree " }, - { "tree 1A669B8AB81B5EB7D9DB69562D34952A38A9B504\n", "tree " }, - { "tree 5B20DCC6110FCC75D31C6CEDEBD7F43ECA65B503\n", "tree " }, - { "tree 173E7BF00EA5C33447E99E6C1255954A13026BE4\n", "tree " }, - { NULL, NULL } + { "parent 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "parent " }, + { "tree 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree " }, + { "random_heading 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "random_heading " }, + { "stuck_heading05452d6349abcd67aa396dfb28660d765d8b2a36\n", "stuck_heading" }, + { "tree 5F4BEFFC0759261D015AA63A3A85613FF2F235DE\n", "tree " }, + { "tree 1A669B8AB81B5EB7D9DB69562D34952A38A9B504\n", "tree " }, + { "tree 5B20DCC6110FCC75D31C6CEDEBD7F43ECA65B503\n", "tree " }, + { "tree 173E7BF00EA5C33447E99E6C1255954A13026BE4\n", "tree " }, + { NULL, NULL } }; static parse_test_case failing_header_cases[] = { - { "parent 05452d6349abcd67aa396dfb28660d765d8b2a36", "parent " }, - { "05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree " }, - { "parent05452d6349abcd67aa396dfb28660d765d8b2a6a\n", "parent " }, - { "parent 05452d6349abcd67aa396dfb280d765d8b2a6\n", "parent " }, - { "tree 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree " }, - { "parent 0545xd6349abcd67aa396dfb28660d765d8b2a36\n", "parent " }, - { "parent 0545xd6349abcd67aa396dfb28660d765d8b2a36FF\n", "parent " }, - { "", "tree " }, - { "", "" }, - { NULL, NULL } + { "parent 05452d6349abcd67aa396dfb28660d765d8b2a36", "parent " }, + { "05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree " }, + { "parent05452d6349abcd67aa396dfb28660d765d8b2a6a\n", "parent " }, + { "parent 05452d6349abcd67aa396dfb280d765d8b2a6\n", "parent " }, + { "tree 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree " }, + { "parent 0545xd6349abcd67aa396dfb28660d765d8b2a36\n", "parent " }, + { "parent 0545xd6349abcd67aa396dfb28660d765d8b2a36FF\n", "parent " }, + { "", "tree " }, + { "", "" }, + { NULL, NULL } }; void test_commit_parse__header(void) { - git_oid oid; + git_oid oid; - parse_test_case *testcase; - for (testcase = passing_header_cases; testcase->line != NULL; testcase++) - { - const char *line = testcase->line; - const char *line_end = line + strlen(line); + parse_test_case *testcase; + for (testcase = passing_header_cases; testcase->line != NULL; testcase++) + { + const char *line = testcase->line; + const char *line_end = line + strlen(line); - cl_git_pass(git_oid__parse(&oid, &line, line_end, testcase->header)); - cl_assert(line == line_end); - } + cl_git_pass(git_oid__parse(&oid, &line, line_end, testcase->header)); + cl_assert(line == line_end); + } - for (testcase = failing_header_cases; testcase->line != NULL; testcase++) - { - const char *line = testcase->line; - const char *line_end = line + strlen(line); + for (testcase = failing_header_cases; testcase->line != NULL; testcase++) + { + const char *line = testcase->line; + const char *line_end = line + strlen(line); - cl_git_fail(git_oid__parse(&oid, &line, line_end, testcase->header)); - } + cl_git_fail(git_oid__parse(&oid, &line, line_end, testcase->header)); + } } // Signature parsing typedef struct { - const char *string; - const char *header; - const char *name; - const char *email; - git_time_t time; - int offset; + const char *string; + const char *header; + const char *name; + const char *email; + git_time_t time; + int offset; } passing_signature_test_case; passing_signature_test_case passing_signature_cases[] = { @@ -122,12 +122,12 @@ passing_signature_test_case passing_signature_cases[] = { {"author Vicent Marti 4294967296 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 4294967296, 0}, {"author Vicent Marti 8589934592 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 8589934592, 0}, - {NULL,NULL,NULL,NULL,0,0} + {NULL,NULL,NULL,NULL,0,0} }; typedef struct { - const char *string; - const char *header; + const char *string; + const char *header; } failing_signature_test_case; failing_signature_test_case failing_signature_cases[] = { @@ -143,31 +143,31 @@ failing_signature_test_case failing_signature_cases[] = { void test_commit_parse__signature(void) { - passing_signature_test_case *passcase; - failing_signature_test_case *failcase; - - for (passcase = passing_signature_cases; passcase->string != NULL; passcase++) - { - const char *str = passcase->string; - size_t len = strlen(passcase->string); - struct git_signature person = {0}; - - cl_git_pass(git_signature__parse(&person, &str, str + len, passcase->header, '\n')); - cl_assert_equal_s(passcase->name, person.name); - cl_assert_equal_s(passcase->email, person.email); - cl_assert_equal_i((int)passcase->time, (int)person.when.time); - cl_assert_equal_i(passcase->offset, person.when.offset); - git__free(person.name); git__free(person.email); - } - - for (failcase = failing_signature_cases; failcase->string != NULL; failcase++) - { - const char *str = failcase->string; - size_t len = strlen(failcase->string); - git_signature person = {0}; - cl_git_fail(git_signature__parse(&person, &str, str + len, failcase->header, '\n')); - git__free(person.name); git__free(person.email); - } + passing_signature_test_case *passcase; + failing_signature_test_case *failcase; + + for (passcase = passing_signature_cases; passcase->string != NULL; passcase++) + { + const char *str = passcase->string; + size_t len = strlen(passcase->string); + struct git_signature person = {0}; + + cl_git_pass(git_signature__parse(&person, &str, str + len, passcase->header, '\n')); + cl_assert_equal_s(passcase->name, person.name); + cl_assert_equal_s(passcase->email, person.email); + cl_assert_equal_i((int)passcase->time, (int)person.when.time); + cl_assert_equal_i(passcase->offset, person.when.offset); + git__free(person.name); git__free(person.email); + } + + for (failcase = failing_signature_cases; failcase->string != NULL; failcase++) + { + const char *str = failcase->string; + size_t len = strlen(failcase->string); + git_signature person = {0}; + cl_git_fail(git_signature__parse(&person, &str, str + len, failcase->header, '\n')); + git__free(person.name); git__free(person.email); + } } @@ -312,17 +312,17 @@ void test_commit_parse__entire_commit(void) // query the details on a parsed commit void test_commit_parse__details0(void) { - static const char *commit_ids[] = { - "a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */ - "9fd738e8f7967c078dceed8190330fc8648ee56a", /* 1 */ - "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", /* 2 */ - "c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */ - "8496071c1b46c854b31185ea97743be6a8774479", /* 4 */ - "5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */ - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", /* 6 */ - }; + static const char *commit_ids[] = { + "a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */ + "9fd738e8f7967c078dceed8190330fc8648ee56a", /* 1 */ + "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", /* 2 */ + "c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */ + "8496071c1b46c854b31185ea97743be6a8774479", /* 4 */ + "5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */ + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", /* 6 */ + }; const size_t commit_count = sizeof(commit_ids) / sizeof(const char *); - unsigned int i; + unsigned int i; for (i = 0; i < commit_count; ++i) { git_oid id; -- cgit v1.2.1 From d27a441ddefff8934e43a546b23f582437ba4399 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Mon, 30 Sep 2013 11:30:28 +0200 Subject: commit: Trim message leading newlines Fix libgit2/libgit2sharp#522 --- src/commit.c | 2 +- tests-clar/commit/parse.c | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/commit.c b/src/commit.c index 15a195fe5..ab475a8f8 100644 --- a/src/commit.c +++ b/src/commit.c @@ -240,7 +240,7 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj) buffer_end = buffer + git_odb_object_size(odb_obj); buffer += header_len; - if (*buffer == '\n') + while (buffer < buffer_end && *buffer == '\n') ++buffer; /* extract commit message */ diff --git a/tests-clar/commit/parse.c b/tests-clar/commit/parse.c index e91815def..c191b3421 100644 --- a/tests-clar/commit/parse.c +++ b/tests-clar/commit/parse.c @@ -349,7 +349,6 @@ void test_commit_parse__details0(void) { cl_assert_equal_s("Scott Chacon", committer->name); cl_assert_equal_s("schacon@gmail.com", committer->email); cl_assert(message != NULL); - cl_assert(strchr(message, '\n') != NULL); cl_assert(commit_time > 0); cl_assert(parents <= 2); for (p = 0;p < parents;p++) { @@ -382,9 +381,25 @@ committer Vicent Marti 1273848544 +0200\n\ \n\ This commit has a few LF at the start of the commit message"; const char *message = -"\n\ +"This commit has a few LF at the start of the commit message"; + + cl_git_pass(parse_commit(&commit, buffer)); + cl_assert_equal_s(message, git_commit_message(commit)); + git_commit__free(commit); +} + +void test_commit_parse__only_lf(void) +{ + git_commit *commit; + const char *buffer = +"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ +parent e90810b8df3e80c413d903f631643c716887138d\n\ +author Vicent Marti 1273848544 +0200\n\ +committer Vicent Marti 1273848544 +0200\n\ \n\ -This commit has a few LF at the start of the commit message"; +\n\ +\n"; + const char *message = ""; cl_git_pass(parse_commit(&commit, buffer)); cl_assert_equal_s(message, git_commit_message(commit)); -- cgit v1.2.1 From b176ededb7d226ac85809b3ec594d185e7e3e866 Mon Sep 17 00:00:00 2001 From: Jameson Miller Date: Thu, 19 Sep 2013 14:52:57 -0400 Subject: Initial Implementation of progress reports during push This adds the basics of progress reporting during push. While progress for all aspects of a push operation are not reported with this change, it lays the foundation to add these later. Push progress reporting can be improved in the future - and consumers of the API should just get more accurate information at that point. The main areas where this is lacking are: 1) packbuilding progress: does not report progress during deltafication, as this involves coordinating progress from multiple threads. 2) network progress: reports progress as objects and bytes are going to be written to the subtransport (instead of as client gets confirmation that they have been received by the server) and leaves out some of the bytes that are transfered as part of the push protocol. Basically, this reports the pack bytes that are written to the subtransport. It does not report the bytes sent on the wire that are received by the server. This should be a good estimate of progress (and an improvement over no progress). --- CMakeLists.txt | 2 + include/git2/pack.h | 30 +++++++++++++++ include/git2/push.h | 29 ++++++++++++++ src/pack-objects.c | 30 +++++++++++++++ src/pack-objects.h | 5 +++ src/push.c | 23 +++++++++++ src/push.h | 5 +++ src/transports/smart_protocol.c | 51 ++++++++++++++++++++++--- src/util.h | 61 ++++++++++++++++++++++++++++++ tests-clar/online/push.c | 84 ++++++++++++++++++++++++++--------------- 10 files changed, 283 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c09b4178..df3936496 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,8 @@ FUNCTION(TARGET_OS_LIBRARIES target) TARGET_LINK_LIBRARIES(${target} ws2_32) ELSEIF(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") TARGET_LINK_LIBRARIES(${target} socket nsl) + ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux") + TARGET_LINK_LIBRARIES(${target} rt) ENDIF () IF(THREADSAFE) TARGET_LINK_LIBRARIES(${target} ${CMAKE_THREAD_LIBS_INIT}) diff --git a/include/git2/pack.h b/include/git2/pack.h index 976e39cb4..7ebdd5cf3 100644 --- a/include/git2/pack.h +++ b/include/git2/pack.h @@ -45,6 +45,14 @@ */ GIT_BEGIN_DECL +/** + * Stages that are reported by the packbuilder progress callback. + */ +typedef enum { + GIT_PACKBUILDER_ADDING_OBJECTS = 0, + GIT_PACKBUILDER_DELTAFICATION = 1, +} git_packbuilder_stage_t; + /** * Initialize a new packbuilder * @@ -149,6 +157,28 @@ GIT_EXTERN(uint32_t) git_packbuilder_object_count(git_packbuilder *pb); */ GIT_EXTERN(uint32_t) git_packbuilder_written(git_packbuilder *pb); +/** Packbuilder progress notification function */ +typedef void (*git_packbuilder_progress)( + int stage, + unsigned int current, + unsigned int total, + void *payload); + +/** + * Set the callbacks for a packbuilder + * + * @param pb The packbuilder object + * @param progress_cb Function to call with progress information during + * pack building. Be aware that this is called inline with pack building + * operations, so performance may be affected. + * @param progress_cb_payload Payload for progress callback. + * @return 0 or an error code + */ +GIT_EXTERN(int) git_packbuilder_set_callbacks( + git_packbuilder *pb, + git_packbuilder_progress progress_cb, + void *progress_cb_payload); + /** * Free the packbuilder and all associated data * diff --git a/include/git2/push.h b/include/git2/push.h index ed6253afb..ecfd862d4 100644 --- a/include/git2/push.h +++ b/include/git2/push.h @@ -8,6 +8,7 @@ #define INCLUDE_git_push_h__ #include "common.h" +#include "pack.h" /** * @file git2/push.h @@ -38,6 +39,13 @@ typedef struct { #define GIT_PUSH_OPTIONS_VERSION 1 #define GIT_PUSH_OPTIONS_INIT { GIT_PUSH_OPTIONS_VERSION } +/** Push network progress notification function */ +typedef void (*git_push_transfer_progress)( + unsigned int current, + unsigned int total, + size_t bytes, + void* payload); + /** * Create a new push object * @@ -60,6 +68,27 @@ GIT_EXTERN(int) git_push_set_options( git_push *push, const git_push_options *opts); +/** + * Set the callbacks for a push + * + * @param push The push object + * @param pack_progress_cb Function to call with progress information during + * pack building. Be aware that this is called inline with pack building + * operations, so performance may be affected. + * @param pack_progress_cb_payload Payload for the pack progress callback. + * @param transfer_progress_cb Function to call with progress information during + * the upload portion of a push. Be aware that this is called inline with + * pack building operations, so performance may be affected. + * @param transfer_progress_cb_payload Payload for the network progress callback. + * @return 0 or an error code + */ +GIT_EXTERN(int) git_push_set_callbacks( + git_push *push, + git_packbuilder_progress pack_progress_cb, + void *pack_progress_cb_payload, + git_push_transfer_progress transfer_progress_cb, + void *transfer_progress_cb_payload); + /** * Add a refspec to be pushed * diff --git a/src/pack-objects.c b/src/pack-objects.c index 7f427e3bd..2a2f36223 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -14,6 +14,7 @@ #include "pack.h" #include "thread-utils.h" #include "tree.h" +#include "util.h" #include "git2/pack.h" #include "git2/commit.h" @@ -57,6 +58,9 @@ struct pack_write_context { #define git_packbuilder__progress_lock(pb) GIT_PACKBUILDER__MUTEX_OP(pb, progress_mutex, lock) #define git_packbuilder__progress_unlock(pb) GIT_PACKBUILDER__MUTEX_OP(pb, progress_mutex, unlock) +/* The minimal interval between progress updates (in seconds). */ +#define MIN_PROGRESS_UPDATE_INTERVAL 0.5 + static unsigned name_hash(const char *name) { unsigned c, hash = 0; @@ -212,6 +216,14 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, assert(ret != 0); kh_value(pb->object_ix, pos) = po; + if (pb->progress_cb) { + double current_time = git__timer(); + if ((current_time - pb->last_progress_report_time) >= MIN_PROGRESS_UPDATE_INTERVAL) { + pb->last_progress_report_time = current_time; + pb->progress_cb(GIT_PACKBUILDER_ADDING_OBJECTS, pb->nr_objects, 0, pb->progress_cb_payload); + } + } + pb->done = false; return 0; } @@ -1207,6 +1219,13 @@ static int prepare_pack(git_packbuilder *pb) if (pb->nr_objects == 0 || pb->done) return 0; /* nothing to do */ + /* + * Although we do not report progress during deltafication, we + * at least report that we are in the deltafication stage + */ + if (pb->progress_cb) + pb->progress_cb(GIT_PACKBUILDER_DELTAFICATION, 0, pb->nr_objects, pb->progress_cb_payload); + delta_list = git__malloc(pb->nr_objects * sizeof(*delta_list)); GITERR_CHECK_ALLOC(delta_list); @@ -1348,6 +1367,17 @@ uint32_t git_packbuilder_written(git_packbuilder *pb) return pb->nr_written; } +int git_packbuilder_set_callbacks(git_packbuilder *pb, git_packbuilder_progress progress_cb, void *progress_cb_payload) +{ + if (!pb) + return -1; + + pb->progress_cb = progress_cb; + pb->progress_cb_payload = progress_cb_payload; + + return 0; +} + void git_packbuilder_free(git_packbuilder *pb) { if (pb == NULL) diff --git a/src/pack-objects.h b/src/pack-objects.h index 8e7ba7f78..0c94a5a7a 100644 --- a/src/pack-objects.h +++ b/src/pack-objects.h @@ -16,6 +16,7 @@ #include "netops.h" #include "git2/oid.h" +#include "git2/pack.h" #define GIT_PACK_WINDOW 10 /* number of objects to possibly delta against */ #define GIT_PACK_DEPTH 50 /* max delta depth */ @@ -79,6 +80,10 @@ struct git_packbuilder { int nr_threads; /* nr of threads to use */ + git_packbuilder_progress progress_cb; + void *progress_cb_payload; + double last_progress_report_time; /* the time progress was last reported */ + bool done; }; diff --git a/src/push.c b/src/push.c index eaaa46248..698079253 100644 --- a/src/push.c +++ b/src/push.c @@ -70,6 +70,25 @@ int git_push_set_options(git_push *push, const git_push_options *opts) return 0; } +int git_push_set_callbacks( + git_push *push, + git_packbuilder_progress pack_progress_cb, + void *pack_progress_cb_payload, + git_push_transfer_progress transfer_progress_cb, + void *transfer_progress_cb_payload) +{ + if (!push) + return -1; + + push->pack_progress_cb = pack_progress_cb; + push->pack_progress_cb_payload = pack_progress_cb_payload; + + push->transfer_progress_cb = transfer_progress_cb; + push->transfer_progress_cb_payload = transfer_progress_cb_payload; + + return 0; +} + static void free_refspec(push_spec *spec) { if (spec == NULL) @@ -583,6 +602,10 @@ static int do_push(git_push *push) git_packbuilder_set_threads(push->pb, push->pb_parallelism); + if (push->pack_progress_cb) + if ((error = git_packbuilder_set_callbacks(push->pb, push->pack_progress_cb, push->pack_progress_cb_payload)) < 0) + goto on_error; + if ((error = calculate_work(push)) < 0 || (error = queue_objects(push)) < 0 || (error = transport->push(transport, push)) < 0) diff --git a/src/push.h b/src/push.h index e982b8385..6c8bf7229 100644 --- a/src/push.h +++ b/src/push.h @@ -39,6 +39,11 @@ struct git_push { /* options */ unsigned pb_parallelism; + + git_packbuilder_progress pack_progress_cb; + void *pack_progress_cb_payload; + git_push_transfer_progress transfer_progress_cb; + void *transfer_progress_cb_payload; }; /** diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 0cd5e831d..156b69e1f 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -13,8 +13,11 @@ #include "push.h" #include "pack-objects.h" #include "remote.h" +#include "util.h" #define NETWORK_XFER_THRESHOLD (100*1024) +/* The minimal interval between progress updates (in seconds). */ +#define MIN_PROGRESS_UPDATE_INTERVAL 0.5 int git_smart__store_refs(transport_smart *t, int flushes) { @@ -801,22 +804,53 @@ static int update_refs_from_report( return 0; } +struct push_packbuilder_payload +{ + git_smart_subtransport_stream *stream; + git_packbuilder *pb; + git_push_transfer_progress cb; + void *cb_payload; + size_t last_bytes; + double last_progress_report_time; +}; + static int stream_thunk(void *buf, size_t size, void *data) { - git_smart_subtransport_stream *s = (git_smart_subtransport_stream *)data; + int error = 0; + struct push_packbuilder_payload *payload = data; + + if ((error = payload->stream->write(payload->stream, (const char *)buf, size)) < 0) + return error; + + if (payload->cb) { + double current_time = git__timer(); + payload->last_bytes += size; - return s->write(s, (const char *)buf, size); + if ((current_time - payload->last_progress_report_time) >= MIN_PROGRESS_UPDATE_INTERVAL) { + payload->last_progress_report_time = current_time; + payload->cb(payload->pb->nr_written, payload->pb->nr_objects, payload->last_bytes, payload->cb_payload); + } + } + + return error; } int git_smart__push(git_transport *transport, git_push *push) { transport_smart *t = (transport_smart *)transport; - git_smart_subtransport_stream *s; + struct push_packbuilder_payload packbuilder_payload = {0}; git_buf pktline = GIT_BUF_INIT; int error = -1, need_pack = 0; push_spec *spec; unsigned int i; + packbuilder_payload.pb = push->pb; + + if (push->transfer_progress_cb) { + packbuilder_payload.cb = push->transfer_progress_cb; + packbuilder_payload.cb_payload = push->transfer_progress_cb_payload; + } + #ifdef PUSH_DEBUG { git_remote_head *head; @@ -848,12 +882,12 @@ int git_smart__push(git_transport *transport, git_push *push) } } - if (git_smart__get_push_stream(t, &s) < 0 || + if (git_smart__get_push_stream(t, &packbuilder_payload.stream) < 0 || gen_pktline(&pktline, push) < 0 || - s->write(s, git_buf_cstr(&pktline), git_buf_len(&pktline)) < 0) + packbuilder_payload.stream->write(packbuilder_payload.stream, git_buf_cstr(&pktline), git_buf_len(&pktline)) < 0) goto on_error; - if (need_pack && git_packbuilder_foreach(push->pb, &stream_thunk, s) < 0) + if (need_pack && git_packbuilder_foreach(push->pb, &stream_thunk, &packbuilder_payload) < 0) goto on_error; /* If we sent nothing or the server doesn't support report-status, then @@ -863,6 +897,11 @@ int git_smart__push(git_transport *transport, git_push *push) else if (parse_report(&t->buffer, push) < 0) goto on_error; + /* If progress is being reported write the final report */ + if (push->transfer_progress_cb) { + push->transfer_progress_cb(push->pb->nr_written, push->pb->nr_objects, packbuilder_payload.last_bytes, push->transfer_progress_cb_payload); + } + if (push->status.length && update_refs_from_report(&t->refs, &push->specs, &push->status) < 0) goto on_error; diff --git a/src/util.h b/src/util.h index bd93b46b5..78e2f2e79 100644 --- a/src/util.h +++ b/src/util.h @@ -353,4 +353,65 @@ GIT_INLINE(void) git__memzero(void *data, size_t size) #endif } +#ifdef GIT_WIN32 + +GIT_INLINE(double) git__timer(void) +{ + /* We need the initial tick count to detect if the tick + * count has rolled over. */ + static DWORD initial_tick_count = 0; + + /* GetTickCount returns the number of milliseconds that have + * elapsed since the system was started. */ + DWORD count = GetTickCount(); + + if(initial_tick_count == 0) { + initial_tick_count = count; + } else if (count < initial_tick_count) { + /* The tick count has rolled over - adjust for it. */ + count = (0xFFFFFFFF - initial_tick_count) + count; + } + + return (double) count / (double) 1000; +} + +#elif __APPLE__ + +#include + +double git__timer(void) +{ + uint64_t time = mach_absolute_time(); + static double scaling_factor = 0; + + if (scaling_factor == 0) { + mach_timebase_info_data_t info; + (void)mach_timebase_info(&info); + scaling_factor = (double)info.numer / (double)info.denom; + } + + return (double)time * scaling_factor / 1.0E-9; +} + +#else + +#include + +GIT_INLINE(double) git__timer(void) +{ + struct timespec tp; + + if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) { + return (double) tp.tv_sec + (double) tp.tv_nsec / 1E-9; + } else { + /* Fall back to using gettimeofday */ + struct timeval tv; + struct timezone tz; + gettimeofday(&tv, &tz); + return (double)tv.tv_sec + (double)tv.tv_usec / 1E-6; + } +} + +#endif + #endif /* INCLUDE_util_h__ */ diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 4c0a28c1c..6a4a9b281 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -348,6 +348,18 @@ void test_online_push__cleanup(void) cl_git_sandbox_cleanup(); } +static void push_pack_progress_cb(int stage, unsigned int current, unsigned int total, void* payload) +{ + int *was_called = (int *) payload; + *was_called = 1; +} + +static void push_transfer_progress_cb(unsigned int current, unsigned int total, size_t bytes, void* payload) +{ + int *was_called = (int *) payload; + *was_called = 1; +} + /** * Calls push and relists refs on remote to verify success. * @@ -356,15 +368,17 @@ void test_online_push__cleanup(void) * @param expected_refs expected remote refs after push * @param expected_refs_len length of expected_refs * @param expected_ret expected return value from git_push_finish() + * @param check_progress_cb Check that the push progress callbacks are called */ static void do_push(const char *refspecs[], size_t refspecs_len, push_status expected_statuses[], size_t expected_statuses_len, - expected_ref expected_refs[], size_t expected_refs_len, int expected_ret) + expected_ref expected_refs[], size_t expected_refs_len, int expected_ret, int check_progress_cb) { git_push *push; git_push_options opts = GIT_PUSH_OPTIONS_INIT; size_t i; int ret; + int pack_progress_called = 0, transfer_progress_called = 0; if (_remote) { /* Auto-detect the number of threads to use */ @@ -375,6 +389,9 @@ static void do_push(const char *refspecs[], size_t refspecs_len, cl_git_pass(git_push_new(&push, _remote)); cl_git_pass(git_push_set_options(push, &opts)); + if (check_progress_cb) + cl_git_pass(git_push_set_callbacks(push, push_pack_progress_cb, &pack_progress_called, push_transfer_progress_cb, &transfer_progress_called)); + for (i = 0; i < refspecs_len; i++) cl_git_pass(git_push_add_refspec(push, refspecs[i])); @@ -387,6 +404,11 @@ static void do_push(const char *refspecs[], size_t refspecs_len, cl_assert_equal_i(1, git_push_unpack_ok(push)); } + if (check_progress_cb) { + cl_assert_equal_i(1, pack_progress_called); + cl_assert_equal_i(1, transfer_progress_called); + } + do_verify_push_status(push, expected_statuses, expected_statuses_len); cl_assert_equal_i(expected_ret, ret); @@ -405,7 +427,7 @@ static void do_push(const char *refspecs[], size_t refspecs_len, /* Call push_finish() without ever calling git_push_add_refspec() */ void test_online_push__noop(void) { - do_push(NULL, 0, NULL, 0, NULL, 0, 0); + do_push(NULL, 0, NULL, 0, NULL, 0, 0, 0); } void test_online_push__b1(void) @@ -415,7 +437,7 @@ void test_online_push__b1(void) expected_ref exp_refs[] = { { "refs/heads/b1", &_oid_b1 } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0); + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); } void test_online_push__b2(void) @@ -425,7 +447,7 @@ void test_online_push__b2(void) expected_ref exp_refs[] = { { "refs/heads/b2", &_oid_b2 } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0); + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); } void test_online_push__b3(void) @@ -435,7 +457,7 @@ void test_online_push__b3(void) expected_ref exp_refs[] = { { "refs/heads/b3", &_oid_b3 } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0); + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); } void test_online_push__b4(void) @@ -445,7 +467,7 @@ void test_online_push__b4(void) expected_ref exp_refs[] = { { "refs/heads/b4", &_oid_b4 } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0); + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); } void test_online_push__b5(void) @@ -455,7 +477,7 @@ void test_online_push__b5(void) expected_ref exp_refs[] = { { "refs/heads/b5", &_oid_b5 } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0); + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); } void test_online_push__multi(void) @@ -483,7 +505,7 @@ void test_online_push__multi(void) }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0); + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); } void test_online_push__implicit_tgt(void) @@ -501,10 +523,10 @@ void test_online_push__implicit_tgt(void) do_push(specs1, ARRAY_SIZE(specs1), exp_stats1, ARRAY_SIZE(exp_stats1), - exp_refs1, ARRAY_SIZE(exp_refs1), 0); + exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1); do_push(specs2, ARRAY_SIZE(specs2), exp_stats2, ARRAY_SIZE(exp_stats2), - exp_refs2, ARRAY_SIZE(exp_refs2), 0); + exp_refs2, ARRAY_SIZE(exp_refs2), 0, 0); } void test_online_push__fast_fwd(void) @@ -526,19 +548,19 @@ void test_online_push__fast_fwd(void) do_push(specs_init, ARRAY_SIZE(specs_init), exp_stats_init, ARRAY_SIZE(exp_stats_init), - exp_refs_init, ARRAY_SIZE(exp_refs_init), 0); + exp_refs_init, ARRAY_SIZE(exp_refs_init), 0, 1); do_push(specs_ff, ARRAY_SIZE(specs_ff), exp_stats_ff, ARRAY_SIZE(exp_stats_ff), - exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0); + exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0, 0); do_push(specs_reset, ARRAY_SIZE(specs_reset), exp_stats_init, ARRAY_SIZE(exp_stats_init), - exp_refs_init, ARRAY_SIZE(exp_refs_init), 0); + exp_refs_init, ARRAY_SIZE(exp_refs_init), 0, 0); do_push(specs_ff_force, ARRAY_SIZE(specs_ff_force), exp_stats_ff, ARRAY_SIZE(exp_stats_ff), - exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0); + exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0, 0); } void test_online_push__tag_commit(void) @@ -548,7 +570,7 @@ void test_online_push__tag_commit(void) expected_ref exp_refs[] = { { "refs/tags/tag-commit", &_tag_commit } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0); + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); } void test_online_push__tag_tree(void) @@ -558,7 +580,7 @@ void test_online_push__tag_tree(void) expected_ref exp_refs[] = { { "refs/tags/tag-tree", &_tag_tree } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0); + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); } void test_online_push__tag_blob(void) @@ -568,7 +590,7 @@ void test_online_push__tag_blob(void) expected_ref exp_refs[] = { { "refs/tags/tag-blob", &_tag_blob } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0); + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); } void test_online_push__tag_lightweight(void) @@ -578,7 +600,7 @@ void test_online_push__tag_lightweight(void) expected_ref exp_refs[] = { { "refs/tags/tag-lightweight", &_tag_lightweight } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0); + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); } void test_online_push__tag_to_tag(void) @@ -588,7 +610,7 @@ void test_online_push__tag_to_tag(void) expected_ref exp_refs[] = { { "refs/tags/tag-tag", &_tag_tag } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0); + exp_refs, ARRAY_SIZE(exp_refs), 0, 0); } void test_online_push__force(void) @@ -605,16 +627,16 @@ void test_online_push__force(void) do_push(specs1, ARRAY_SIZE(specs1), exp_stats1, ARRAY_SIZE(exp_stats1), - exp_refs1, ARRAY_SIZE(exp_refs1), 0); + exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1); do_push(specs2, ARRAY_SIZE(specs2), NULL, 0, - exp_refs1, ARRAY_SIZE(exp_refs1), GIT_ENONFASTFORWARD); + exp_refs1, ARRAY_SIZE(exp_refs1), GIT_ENONFASTFORWARD, 0); /* Non-fast-forward update with force should pass. */ do_push(specs2_force, ARRAY_SIZE(specs2_force), exp_stats2_force, ARRAY_SIZE(exp_stats2_force), - exp_refs2_force, ARRAY_SIZE(exp_refs2_force), 0); + exp_refs2_force, ARRAY_SIZE(exp_refs2_force), 0, 1); } void test_online_push__delete(void) @@ -645,7 +667,7 @@ void test_online_push__delete(void) do_push(specs1, ARRAY_SIZE(specs1), exp_stats1, ARRAY_SIZE(exp_stats1), - exp_refs1, ARRAY_SIZE(exp_refs1), 0); + exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1); /* When deleting a non-existent branch, the git client sends zero for both * the old and new commit id. This should succeed on the server with the @@ -655,23 +677,23 @@ void test_online_push__delete(void) */ do_push(specs_del_fake, ARRAY_SIZE(specs_del_fake), exp_stats_fake, 1, - exp_refs1, ARRAY_SIZE(exp_refs1), 0); + exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0); do_push(specs_del_fake_force, ARRAY_SIZE(specs_del_fake_force), exp_stats_fake, 1, - exp_refs1, ARRAY_SIZE(exp_refs1), 0); + exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0); /* Delete one of the pushed branches. */ do_push(specs_delete, ARRAY_SIZE(specs_delete), exp_stats_delete, ARRAY_SIZE(exp_stats_delete), - exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0); + exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0, 0); /* Re-push branches and retry delete with force. */ do_push(specs1, ARRAY_SIZE(specs1), exp_stats1, ARRAY_SIZE(exp_stats1), - exp_refs1, ARRAY_SIZE(exp_refs1), 0); + exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0); do_push(specs_delete_force, ARRAY_SIZE(specs_delete_force), exp_stats_delete, ARRAY_SIZE(exp_stats_delete), - exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0); + exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0, 0); } void test_online_push__bad_refspecs(void) @@ -703,11 +725,11 @@ void test_online_push__expressions(void) /* TODO: Find a more precise way of checking errors than a exit code of -1. */ do_push(specs_left_expr, ARRAY_SIZE(specs_left_expr), NULL, 0, - NULL, 0, -1); + NULL, 0, -1, 0); do_push(specs_right_expr, ARRAY_SIZE(specs_right_expr), exp_stats_right_expr, ARRAY_SIZE(exp_stats_right_expr), - NULL, 0, 0); + NULL, 0, 0, 1); } void test_online_push__notes(void) @@ -727,7 +749,7 @@ void test_online_push__notes(void) do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0); + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); git_signature_free(signature); } -- cgit v1.2.1 From ae5a935290c695d721f69b8836f891a639c0aff3 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 30 Sep 2013 14:47:56 -0700 Subject: Ensure submodule repos and indices are freed ...before the helper's cleanup method tries to delete their files. --- tests-clar/stash/submodules.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tests-clar/stash/submodules.c b/tests-clar/stash/submodules.c index 60dbbad2e..137c4408c 100644 --- a/tests-clar/stash/submodules.c +++ b/tests-clar/stash/submodules.c @@ -6,9 +6,7 @@ static git_repository *repo; static git_signature *signature; static git_oid stash_tip_oid; -static git_index *smindex; static git_submodule *sm; -static git_repository *smrepo; void test_stash_submodules__initialize(void) { @@ -17,8 +15,6 @@ void test_stash_submodules__initialize(void) repo = setup_fixture_submodules(); cl_git_pass(git_submodule_lookup(&sm, repo, "testrepo")); - cl_git_pass(git_submodule_open(&smrepo, sm)); - cl_git_pass(git_repository_index(&smindex, smrepo)); } void test_stash_submodules__cleanup(void) @@ -29,6 +25,9 @@ void test_stash_submodules__cleanup(void) void test_stash_submodules__does_not_stash_modified_submodules(void) { + static git_index *smindex; + static git_repository *smrepo; + assert_status(repo, "modified", GIT_STATUS_WT_MODIFIED); /* modify file in submodule */ @@ -36,6 +35,8 @@ void test_stash_submodules__does_not_stash_modified_submodules(void) assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); /* add file to index in submodule */ + cl_git_pass(git_submodule_open(&smrepo, sm)); + cl_git_pass(git_repository_index(&smindex, smrepo)); cl_git_pass(git_index_add_bypath(smindex, "README")); /* commit changed index of submodule */ @@ -46,10 +47,16 @@ void test_stash_submodules__does_not_stash_modified_submodules(void) assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); assert_status(repo, "modified", GIT_STATUS_CURRENT); + + git_index_free(smindex); + git_repository_free(smrepo); } void test_stash_submodules__stash_is_empty_with_modified_submodules(void) { + static git_index *smindex; + static git_repository *smrepo; + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); assert_status(repo, "modified", GIT_STATUS_CURRENT); @@ -58,6 +65,8 @@ void test_stash_submodules__stash_is_empty_with_modified_submodules(void) assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); /* add file to index in submodule */ + cl_git_pass(git_submodule_open(&smrepo, sm)); + cl_git_pass(git_repository_index(&smindex, smrepo)); cl_git_pass(git_index_add_bypath(smindex, "README")); /* commit changed index of submodule */ @@ -65,4 +74,7 @@ void test_stash_submodules__stash_is_empty_with_modified_submodules(void) assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); cl_git_fail_with(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT), GIT_ENOTFOUND); + + git_index_free(smindex); + git_repository_free(smrepo); } -- cgit v1.2.1 From 566dd8cec06e511490c6473d2440c39ff1b2851c Mon Sep 17 00:00:00 2001 From: Linquize Date: Mon, 30 Sep 2013 23:38:22 +0800 Subject: Config subsection name should allow to have ']' and '\\' should allow to escape any characters --- src/config_file.c | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 1a845d8ba..8fb43b990 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -712,7 +712,6 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con int c, rpos; char *first_quote, *last_quote; git_buf buf = GIT_BUF_INIT; - int quote_marks; /* * base_name is what came before the space. We should be at the * first quotation mark, except for now, line isn't being kept in @@ -731,21 +730,15 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con git_buf_printf(&buf, "%s.", base_name); rpos = 0; - quote_marks = 0; line = first_quote; - c = line[rpos++]; + c = line[++rpos]; /* * At the end of each iteration, whatever is stored in c will be * added to the string. In case of error, jump to out */ do { - if (quote_marks == 2) { - set_parse_error(reader, rpos, "Unexpected text after closing quotes"); - git_buf_free(&buf); - return -1; - } switch (c) { case 0: @@ -754,25 +747,13 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con return -1; case '"': - ++quote_marks; - continue; + goto end_parse; case '\\': - c = line[rpos++]; - - switch (c) { - case '"': - if (&line[rpos-1] == last_quote) { - set_parse_error(reader, 0, "Missing closing quotation mark in section header"); - git_buf_free(&buf); - return -1; - } - - case '\\': - break; + c = line[++rpos]; - default: - set_parse_error(reader, rpos, "Unsupported escape sequence"); + if (c == 0) { + set_parse_error(reader, rpos, "Unexpected end-of-line in section header"); git_buf_free(&buf); return -1; } @@ -782,7 +763,15 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con } git_buf_putc(&buf, (char)c); - } while ((c = line[rpos++]) != ']'); + c = line[++rpos]; + } while (line + rpos < last_quote); + +end_parse: + if (line[rpos] != '"' || line[rpos + 1] != ']') { + set_parse_error(reader, rpos, "Unexpected text after closing quotes"); + git_buf_free(&buf); + return -1; + } *section_name = git_buf_detach(&buf); return 0; @@ -800,7 +789,7 @@ static int parse_section_header(struct reader *reader, char **section_out) return -1; /* find the end of the variable's name */ - name_end = strchr(line, ']'); + name_end = strrchr(line, ']'); if (name_end == NULL) { git__free(line); set_parse_error(reader, 0, "Missing ']' in section header"); -- cgit v1.2.1 From d52a93fab330dbbe1271c10b527d333261638fe3 Mon Sep 17 00:00:00 2001 From: Linquize Date: Mon, 30 Sep 2013 23:58:58 +0800 Subject: Add test case to test ']' and '\\' characters in config subsection --- tests-clar/config/read.c | 7 +++++++ tests-clar/resources/config/config20 | 11 +++++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests-clar/resources/config/config20 diff --git a/tests-clar/config/read.c b/tests-clar/config/read.c index 722a15a71..ab068eaa7 100644 --- a/tests-clar/config/read.c +++ b/tests-clar/config/read.c @@ -164,6 +164,13 @@ void test_config_read__empty_files(void) git_config_free(cfg); } +void test_config_read__symbol_headers(void) +{ + git_config *cfg; + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config20"))); + git_config_free(cfg); +} + void test_config_read__header_in_last_line(void) { git_config *cfg; diff --git a/tests-clar/resources/config/config20 b/tests-clar/resources/config/config20 new file mode 100644 index 000000000..8f0f12c4c --- /dev/null +++ b/tests-clar/resources/config/config20 @@ -0,0 +1,11 @@ +[valid "[subsection]"] + something = a +; we don't allow anything after closing " +[sec "[subsec]/child"] + parent = grand +[sec2 "[subsec2]/child2"] + type = dvcs +[sec3 "escape\"quote"] + vcs = git +[sec4 "escaping\\slash"] + lib = git2 -- cgit v1.2.1 From 8d741253849c5e377e50490818326adc56be9fce Mon Sep 17 00:00:00 2001 From: Linquize Date: Tue, 1 Oct 2013 09:46:56 +0800 Subject: Add negative test cases for config header with invalid characters --- tests-clar/config/read.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests-clar/config/read.c b/tests-clar/config/read.c index ab068eaa7..abc088d59 100644 --- a/tests-clar/config/read.c +++ b/tests-clar/config/read.c @@ -531,6 +531,28 @@ void test_config_read__corrupt_header(void) git_config_free(cfg); } +void test_config_read__corrupt_header2(void) +{ + git_config *cfg; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "[unclosed \"bracket\"\n lib = git2\n"); + cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); + + git_config_free(cfg); +} + +void test_config_read__corrupt_header3(void) +{ + git_config *cfg; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "[unclosed \"slash\\\"]\n lib = git2\n"); + cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); + + git_config_free(cfg); +} + void test_config_read__override_variable(void) { git_config *cfg; -- cgit v1.2.1 From 816d28e7bc9473482664d374786dac484c0e1156 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 1 Oct 2013 12:56:47 -0700 Subject: Mark git__timer as inline on OSX --- src/util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.h b/src/util.h index 78e2f2e79..f9de909e9 100644 --- a/src/util.h +++ b/src/util.h @@ -379,7 +379,7 @@ GIT_INLINE(double) git__timer(void) #include -double git__timer(void) +GIT_INLINE(double) git__timer(void) { uint64_t time = mach_absolute_time(); static double scaling_factor = 0; -- cgit v1.2.1 From 8378695671cec5d45464cea65aa5199ecf242212 Mon Sep 17 00:00:00 2001 From: Philip Kelley Date: Fri, 4 Jan 2013 14:39:05 -0500 Subject: Add git_transport_register, git_transport_unregister --- include/git2/transport.h | 34 +++++++++++++++++++++++++ src/transport.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/include/git2/transport.h b/include/git2/transport.h index e61b10423..9901b15de 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -253,6 +253,40 @@ GIT_EXTERN(int) git_transport_new(git_transport **out, git_remote *owner, const /* Signature of a function which creates a transport */ typedef int (*git_transport_cb)(git_transport **out, git_remote *owner, void *param); +/** + * Add a custom transport definition, to be used in addition to the built-in + * set of transports that come with libgit2. + * + * The caller is responsible for synchronizing calls to git_transport_register + * and git_transport_unregister with other calls to the library that + * instantiate transports. + * + * @param prefix The scheme (ending in "://") to match, i.e. "git://" + * @param priority The priority of this transport relative to others with + * the same prefix. Built-in transports have a priority of 1. + * @param cb The callback used to create an instance of the transport + * @param param A fixed parameter to pass to cb at creation time + * @return 0 or an error code + */ +GIT_EXTERN(int) git_transport_register( + const char *prefix, + unsigned priority, + git_transport_cb cb, + void *param); + +/** + * + * Unregister a custom transport definition which was previously registered + * with git_transport_register. + * + * @param prefix From the previous call to git_transport_register + * @param priority From the previous call to git_transport_register + * @return 0 or an error code + */ +GIT_EXTERN(int) git_transport_unregister( + const char *prefix, + unsigned priority); + /* Transports which come with libgit2 (match git_transport_cb). The expected * value for "param" is listed in-line below. */ diff --git a/src/transport.c b/src/transport.c index 354789db1..ff926b1be 100644 --- a/src/transport.c +++ b/src/transport.c @@ -42,6 +42,8 @@ static transport_definition transports[] = { {NULL, 0, 0} }; +static git_vector additional_transports = GIT_VECTOR_INIT; + #define GIT_TRANSPORT_COUNT (sizeof(transports)/sizeof(transports[0])) - 1 static int transport_find_fn(const char *url, git_transport_cb *callback, void **param) @@ -61,6 +63,14 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void * definition = definition_iter; } + git_vector_foreach(&additional_transports, i, definition_iter) { + if (strncasecmp(url, definition_iter->prefix, strlen(definition_iter->prefix))) + continue; + + if (definition_iter->priority > priority) + definition = definition_iter; + } + #ifdef GIT_WIN32 /* On Windows, it might not be possible to discern between absolute local * and ssh paths - first check if this is a valid local path that points @@ -135,6 +145,62 @@ int git_transport_new(git_transport **out, git_remote *owner, const char *url) return 0; } +int git_transport_register( + const char *prefix, + unsigned priority, + git_transport_cb cb, + void *param) +{ + transport_definition *d; + + d = git__calloc(sizeof(transport_definition), 1); + GITERR_CHECK_ALLOC(d); + + d->prefix = git__strdup(prefix); + + if (!d->prefix) + goto on_error; + + d->priority = priority; + d->fn = cb; + d->param = param; + + if (git_vector_insert(&additional_transports, d) < 0) + goto on_error; + + return 0; + +on_error: + git__free(d->prefix); + git__free(d); + return -1; +} + +int git_transport_unregister( + const char *prefix, + unsigned priority) +{ + transport_definition *d; + unsigned i; + + git_vector_foreach(&additional_transports, i, d) { + if (d->priority == priority && !strcasecmp(d->prefix, prefix)) { + if (git_vector_remove(&additional_transports, i) < 0) + return -1; + + git__free(d->prefix); + git__free(d); + + if (!additional_transports.length) + git_vector_free(&additional_transports); + + return 0; + } + } + + return GIT_ENOTFOUND; +} + /* from remote.h */ int git_remote_valid_url(const char *url) { -- cgit v1.2.1 From d31402a3fc4aa1b7d48ba43fd3bb072e7d69a527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 16 Sep 2013 04:20:05 +0200 Subject: remote: put the _download() callback with the others The text progress and update_tips callbacks are already part of the struct, which was meant to unify the callback setup, but the download one was left out. --- examples/network/clone.c | 6 ++++-- examples/network/fetch.c | 2 +- include/git2/clone.h | 2 -- include/git2/remote.h | 11 ++--------- src/clone.c | 3 +-- src/fetch.c | 8 +++----- src/fetch.h | 5 +---- src/remote.c | 7 ++----- tests-clar/network/fetchlocal.c | 14 ++++++++++++-- tests-clar/network/remote/local.c | 10 +++++----- tests-clar/online/clone.c | 20 +++++++++++++++++--- tests-clar/online/fetch.c | 18 +++++++++++++++--- tests-clar/online/fetchhead.c | 2 +- tests-clar/online/push.c | 2 +- tests-clar/online/push_util.h | 2 +- 15 files changed, 66 insertions(+), 46 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index a09a94728..f1002656c 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -57,6 +57,7 @@ int do_clone(git_repository *repo, int argc, char **argv) git_repository *cloned_repo = NULL; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; const char *url = argv[1]; const char *path = argv[2]; int error; @@ -74,8 +75,9 @@ int do_clone(git_repository *repo, int argc, char **argv) checkout_opts.progress_cb = checkout_progress; checkout_opts.progress_payload = &pd; clone_opts.checkout_opts = checkout_opts; - clone_opts.fetch_progress_cb = &fetch_progress; - clone_opts.fetch_progress_payload = &pd; + callbacks.transfer_progress = &fetch_progress; + callbacks.payload = &pd; + clone_opts.remote_callbacks = &callbacks; clone_opts.cred_acquire_cb = cred_acquire_cb; // Do the clone diff --git a/examples/network/fetch.c b/examples/network/fetch.c index ce016ce0b..1de223373 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -35,7 +35,7 @@ static void *download(void *ptr) // Download the packfile and index it. This function updates the // amount of received data and the indexer stats which lets you // inform the user about progress. - if (git_remote_download(data->remote, NULL, NULL) < 0) { + if (git_remote_download(data->remote) < 0) { data->ret = -1; goto exit; } diff --git a/include/git2/clone.h b/include/git2/clone.h index 580352ac1..122806ad5 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -69,8 +69,6 @@ typedef struct git_clone_options { git_checkout_opts checkout_opts; git_repository_init_options *init_options; int bare; - git_transfer_progress_callback fetch_progress_cb; - void *fetch_progress_payload; const char *remote_name; const char *pushurl; diff --git a/include/git2/remote.h b/include/git2/remote.h index fa8b378c6..2bde5e365 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -257,17 +257,9 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void * The .idx file will be created and both it and the packfile with be * renamed to their final name. * - * @param remote the remote to download from - * @param progress_cb function to call with progress information. Be aware that - * this is called inline with network and indexing operations, so performance - * may be affected. - * @param payload payload for the progress callback * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_download( - git_remote *remote, - git_transfer_progress_callback progress_cb, - void *payload); +GIT_EXTERN(int) git_remote_download(git_remote *remote); /** * Check whether the remote is connected @@ -403,6 +395,7 @@ struct git_remote_callbacks { unsigned int version; void (*progress)(const char *str, int len, void *data); int (*completion)(git_remote_completion_type type, void *data); + int (*transfer_progress)(const git_transfer_progress *stats, void *data); int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data); void *payload; }; diff --git a/src/clone.c b/src/clone.c index ff251be1b..90d677bbb 100644 --- a/src/clone.c +++ b/src/clone.c @@ -380,8 +380,7 @@ static int setup_remotes_and_fetch( if ((retcode = git_remote_connect(origin, GIT_DIRECTION_FETCH)) < 0) goto on_error; - if ((retcode = git_remote_download(origin, options->fetch_progress_cb, - options->fetch_progress_payload)) < 0) + if ((retcode = git_remote_download(origin)) < 0) goto on_error; /* Create "origin/foo" branches for all remote branches */ diff --git a/src/fetch.c b/src/fetch.c index 03fad5fec..5d97913e8 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -119,15 +119,13 @@ int git_fetch_negotiate(git_remote *remote) remote->refs.length); } -int git_fetch_download_pack( - git_remote *remote, - git_transfer_progress_callback progress_cb, - void *progress_payload) +int git_fetch_download_pack(git_remote *remote) { git_transport *t = remote->transport; if(!remote->need_pack) return 0; - return t->download_pack(t, remote->repo, &remote->stats, progress_cb, progress_payload); + return t->download_pack(t, remote->repo, &remote->stats, + remote->callbacks.transfer_progress, remote->callbacks.payload); } diff --git a/src/fetch.h b/src/fetch.h index 059251d04..9605da1b5 100644 --- a/src/fetch.h +++ b/src/fetch.h @@ -11,10 +11,7 @@ int git_fetch_negotiate(git_remote *remote); -int git_fetch_download_pack( - git_remote *remote, - git_transfer_progress_callback progress_cb, - void *progress_payload); +int git_fetch_download_pack(git_remote *remote); int git_fetch__download_pack( git_transport *t, diff --git a/src/remote.c b/src/remote.c index 95b907ff1..e4696c4ec 100644 --- a/src/remote.c +++ b/src/remote.c @@ -742,10 +742,7 @@ static int remote_head_cmp(const void *_a, const void *_b) return git__strcmp_cb(a->name, b->name); } -int git_remote_download( - git_remote *remote, - git_transfer_progress_callback progress_cb, - void *progress_payload) +int git_remote_download(git_remote *remote) { int error; git_vector refs; @@ -767,7 +764,7 @@ int git_remote_download( if ((error = git_fetch_negotiate(remote)) < 0) return error; - return git_fetch_download_pack(remote, progress_cb, progress_payload); + return git_fetch_download_pack(remote); } static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *update_heads, const char *fetchspec_src) diff --git a/tests-clar/network/fetchlocal.c b/tests-clar/network/fetchlocal.c index 09335b3df..28c7115bf 100644 --- a/tests-clar/network/fetchlocal.c +++ b/tests-clar/network/fetchlocal.c @@ -25,13 +25,18 @@ void test_network_fetchlocal__complete(void) git_strarray refnames = {0}; const char *url = cl_git_fixture_url("testrepo.git"); + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + callbacks.transfer_progress = transfer_cb; + callbacks.payload = &callcount; cl_set_cleanup(&cleanup_local_repo, "foo"); cl_git_pass(git_repository_init(&repo, "foo", true)); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); + git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(origin, transfer_cb, &callcount)); + cl_git_pass(git_remote_download(origin)); cl_git_pass(git_remote_update_tips(origin)); cl_git_pass(git_reference_list(&refnames, repo)); @@ -56,6 +61,10 @@ void test_network_fetchlocal__partial(void) int callcount = 0; git_strarray refnames = {0}; const char *url; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + callbacks.transfer_progress = transfer_cb; + callbacks.payload = &callcount; cl_set_cleanup(&cleanup_sandbox, NULL); cl_git_pass(git_reference_list(&refnames, repo)); @@ -63,8 +72,9 @@ void test_network_fetchlocal__partial(void) url = cl_git_fixture_url("testrepo.git"); cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); + git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(origin, transfer_cb, &callcount)); + cl_git_pass(git_remote_download(origin)); cl_git_pass(git_remote_update_tips(origin)); git_strarray_free(&refnames); diff --git a/tests-clar/network/remote/local.c b/tests-clar/network/remote/local.c index c8edd37f5..6d658a2e4 100644 --- a/tests-clar/network/remote/local.c +++ b/tests-clar/network/remote/local.c @@ -123,7 +123,7 @@ void test_network_remote_local__shorthand_fetch_refspec0(void) cl_git_pass(git_remote_add_fetch(remote, refspec)); cl_git_pass(git_remote_add_fetch(remote, refspec2)); - cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/sloppy/master")); @@ -145,7 +145,7 @@ void test_network_remote_local__shorthand_fetch_refspec1(void) cl_git_pass(git_remote_add_fetch(remote, refspec)); cl_git_pass(git_remote_add_fetch(remote, refspec2)); - cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/master")); @@ -160,7 +160,7 @@ void test_network_remote_local__tagopt(void) connect_to_local_repository(cl_fixture("testrepo.git")); git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL); - cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); @@ -179,7 +179,7 @@ void test_network_remote_local__push_to_bare_remote(void) /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_add_fetch(remote, "master:master")); - cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); git_remote_disconnect(remote); @@ -215,7 +215,7 @@ void test_network_remote_local__push_to_non_bare_remote(void) /* Get some commits */ connect_to_local_repository(cl_fixture("testrepo.git")); cl_git_pass(git_remote_add_fetch(remote, "master:master")); - cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); git_remote_disconnect(remote); diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index dc5aa4150..bda260858 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -100,11 +100,15 @@ void test_online_clone__can_checkout_a_cloned_repo(void) bool checkout_progress_cb_was_called = false, fetch_progress_cb_was_called = false; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; g_options.checkout_opts.progress_cb = &checkout_progress; g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called; - g_options.fetch_progress_cb = &fetch_progress; - g_options.fetch_progress_payload = &fetch_progress_cb_was_called; + + callbacks.transfer_progress = &fetch_progress; + callbacks.payload = &fetch_progress_cb_was_called; + g_options.remote_callbacks = &callbacks; cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); @@ -199,6 +203,16 @@ static int cancel_at_half(const git_transfer_progress *stats, void *payload) void test_online_clone__can_cancel(void) { - g_options.fetch_progress_cb = cancel_at_half; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + callbacks.transfer_progress = cancel_at_half; + g_options.remote_callbacks = &callbacks; + cl_git_fail_with(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), GIT_EUSER); } + + + + + + diff --git a/tests-clar/online/fetch.c b/tests-clar/online/fetch.c index f76c6cff9..df1b2e288 100644 --- a/tests-clar/online/fetch.c +++ b/tests-clar/online/fetch.c @@ -38,14 +38,16 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; size_t bytes_received = 0; + callbacks.transfer_progress = progress; callbacks.update_tips = update_tips; + callbacks.payload = &bytes_received; counter = 0; cl_git_pass(git_remote_create(&remote, _repo, "test", url)); git_remote_set_callbacks(remote, &callbacks); git_remote_set_autotag(remote, flag); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(remote, progress, &bytes_received)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); git_remote_disconnect(remote); cl_assert_equal_i(counter, n); @@ -93,6 +95,7 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date git_repository *_repository; bool invoked = false; git_remote *remote; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; git_clone_options opts = GIT_CLONE_OPTIONS_INIT; opts.bare = true; @@ -107,7 +110,10 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date cl_assert_equal_i(false, invoked); - cl_git_pass(git_remote_download(remote, &transferProgressCallback, &invoked)); + callbacks.transfer_progress = &transferProgressCallback; + callbacks.payload = &invoked; + git_remote_set_callbacks(remote, &callbacks); + cl_git_pass(git_remote_download(remote)); cl_assert_equal_i(false, invoked); @@ -131,11 +137,17 @@ void test_online_fetch__can_cancel(void) { git_remote *remote; size_t bytes_received = 0; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; cl_git_pass(git_remote_create(&remote, _repo, "test", "http://github.com/libgit2/TestGitRepository.git")); + + callbacks.transfer_progress = cancel_at_half; + callbacks.payload = &bytes_received; + git_remote_set_callbacks(remote, &callbacks); + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_fail_with(git_remote_download(remote, cancel_at_half, &bytes_received), GIT_EUSER); + cl_git_fail_with(git_remote_download(remote), GIT_EUSER); git_remote_disconnect(remote); git_remote_free(remote); } diff --git a/tests-clar/online/fetchhead.c b/tests-clar/online/fetchhead.c index 58717eef8..5d9eb1318 100644 --- a/tests-clar/online/fetchhead.c +++ b/tests-clar/online/fetchhead.c @@ -48,7 +48,7 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet } cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(remote, NULL, NULL)); + cl_git_pass(git_remote_download(remote)); cl_git_pass(git_remote_update_tips(remote)); git_remote_disconnect(remote); git_remote_free(remote); diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 6a4a9b281..d0d4ed05b 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -326,7 +326,7 @@ void test_online_push__initialize(void) /* Now that we've deleted everything, fetch from the remote */ cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(_remote, NULL, NULL)); + cl_git_pass(git_remote_download(_remote)); cl_git_pass(git_remote_update_tips(_remote)); git_remote_disconnect(_remote); } else diff --git a/tests-clar/online/push_util.h b/tests-clar/online/push_util.h index 759122aa6..659c6dd54 100644 --- a/tests-clar/online/push_util.h +++ b/tests-clar/online/push_util.h @@ -12,7 +12,7 @@ extern const git_oid OID_ZERO; * @param data pointer to a record_callbacks_data instance */ #define RECORD_CALLBACKS_INIT(data) \ - { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, record_update_tips_cb, data } + { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, NULL, record_update_tips_cb, data } typedef struct { char *name; -- cgit v1.2.1 From e3c131c544bc79573ebefab4931b5ca89836ace1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 16 Sep 2013 05:02:25 +0200 Subject: remote: move the credentials callback to the struct Move this one as well, letting us have a single way of setting the callbacks for the remote, and removing fields from the clone options. --- examples/network/clone.c | 2 +- examples/network/fetch.c | 2 +- examples/network/ls-remote.c | 4 +++- include/git2/clone.h | 5 ----- include/git2/remote.h | 1 + src/clone.c | 2 -- src/remote.c | 13 +------------ src/remote.h | 2 -- src/transports/local.c | 2 +- tests-clar/online/clone.c | 13 +++++++++---- tests-clar/online/push.c | 3 ++- tests-clar/online/push_util.h | 2 +- 12 files changed, 20 insertions(+), 31 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index f1002656c..f553c4077 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -76,9 +76,9 @@ int do_clone(git_repository *repo, int argc, char **argv) checkout_opts.progress_payload = &pd; clone_opts.checkout_opts = checkout_opts; callbacks.transfer_progress = &fetch_progress; + callbacks.credentials = cred_acquire_cb; callbacks.payload = &pd; clone_opts.remote_callbacks = &callbacks; - clone_opts.cred_acquire_cb = cred_acquire_cb; // Do the clone error = git_clone(&cloned_repo, url, path, &clone_opts); diff --git a/examples/network/fetch.c b/examples/network/fetch.c index 1de223373..0c545ad7e 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -91,8 +91,8 @@ int fetch(git_repository *repo, int argc, char **argv) // Set up the callbacks (only update_tips for now) callbacks.update_tips = &update_cb; callbacks.progress = &progress_cb; + callbacks.credentials = cred_acquire_cb; git_remote_set_callbacks(remote, &callbacks); - git_remote_set_cred_acquire_cb(remote, &cred_acquire_cb, NULL); // Set up the information for the background worker thread data.remote = remote; diff --git a/examples/network/ls-remote.c b/examples/network/ls-remote.c index b22ac47a0..b65759ed3 100644 --- a/examples/network/ls-remote.c +++ b/examples/network/ls-remote.c @@ -18,6 +18,7 @@ static int use_remote(git_repository *repo, char *name) { git_remote *remote = NULL; int error; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; // Find the remote by name error = git_remote_load(&remote, repo, name); @@ -27,7 +28,8 @@ static int use_remote(git_repository *repo, char *name) goto cleanup; } - git_remote_set_cred_acquire_cb(remote, &cred_acquire_cb, NULL); + callbacks.credentials = cred_acquire_cb; + git_remote_set_callbacks(remote, &callbacks); error = git_remote_connect(remote, GIT_DIRECTION_FETCH); if (error < 0) diff --git a/include/git2/clone.h b/include/git2/clone.h index 122806ad5..38c759f6e 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -48,9 +48,6 @@ GIT_BEGIN_DECL * results in the same behavior as GIT_REMOTE_DEFAULT_FETCH. * - `push_spec` is the fetch specification to be used for pushing. NULL means * use the same spec as for fetching. - * - `cred_acquire_cb` is a callback to be used if credentials are required - * during the initial fetch. - * - `cred_acquire_payload` is the payload for the above callback. * - `transport_flags` is flags used to create transport if no transport is * provided. * - `transport` is a custom transport to be used for the initial fetch. NULL @@ -74,8 +71,6 @@ typedef struct git_clone_options { const char *pushurl; const char *fetch_spec; const char *push_spec; - git_cred_acquire_cb cred_acquire_cb; - void *cred_acquire_payload; git_transport_flags_t transport_flags; git_transport *transport; git_remote_callbacks *remote_callbacks; diff --git a/include/git2/remote.h b/include/git2/remote.h index 2bde5e365..83ad195f4 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -395,6 +395,7 @@ struct git_remote_callbacks { unsigned int version; void (*progress)(const char *str, int len, void *data); int (*completion)(git_remote_completion_type type, void *data); + int (*credentials)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data); int (*transfer_progress)(const git_transfer_progress *stats, void *data); int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data); void *payload; diff --git a/src/clone.c b/src/clone.c index 90d677bbb..8385fb264 100644 --- a/src/clone.c +++ b/src/clone.c @@ -310,8 +310,6 @@ static int create_and_configure_origin( if ((error = git_remote_create(&origin, repo, options->remote_name, url)) < 0) goto on_error; - git_remote_set_cred_acquire_cb(origin, options->cred_acquire_cb, - options->cred_acquire_payload); git_remote_set_autotag(origin, options->remote_autotag); /* * Don't write FETCH_HEAD, we'll check out the remote tracking diff --git a/src/remote.c b/src/remote.c index e4696c4ec..2d0321eb3 100644 --- a/src/remote.c +++ b/src/remote.c @@ -591,7 +591,7 @@ int git_remote_connect(git_remote *remote, git_direction direction) if (!remote->check_cert) flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT; - if (t->connect(t, url, remote->cred_acquire_cb, remote->cred_acquire_payload, direction, flags) < 0) + if (t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags) < 0) goto on_error; remote->transport = t; @@ -1152,17 +1152,6 @@ int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks return 0; } -void git_remote_set_cred_acquire_cb( - git_remote *remote, - git_cred_acquire_cb cred_acquire_cb, - void *payload) -{ - assert(remote); - - remote->cred_acquire_cb = cred_acquire_cb; - remote->cred_acquire_payload = payload; -} - int git_remote_set_transport(git_remote *remote, git_transport *transport) { assert(remote && transport); diff --git a/src/remote.h b/src/remote.h index dce4803ed..269584d96 100644 --- a/src/remote.h +++ b/src/remote.h @@ -21,8 +21,6 @@ struct git_remote { char *pushurl; git_vector refs; git_vector refspecs; - git_cred_acquire_cb cred_acquire_cb; - void *cred_acquire_payload; git_transport *transport; git_repository *repo; git_remote_callbacks callbacks; diff --git a/src/transports/local.c b/src/transports/local.c index 9ebea979c..3c1f98804 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -434,7 +434,7 @@ static int local_push( if (!url || t->parent.close(&t->parent) < 0 || t->parent.connect(&t->parent, url, - push->remote->cred_acquire_cb, NULL, GIT_DIRECTION_PUSH, flags)) + push->remote->callbacks.credentials, NULL, GIT_DIRECTION_PUSH, flags)) goto on_error; } diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index bda260858..b82cbcd46 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -155,11 +155,13 @@ void test_online_clone__credentials(void) cl_getenv("GITTEST_REMOTE_USER"), cl_getenv("GITTEST_REMOTE_PASS") }; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; if (!remote_url) return; - g_options.cred_acquire_cb = git_cred_userpass; - g_options.cred_acquire_payload = &user_pass; + callbacks.credentials = git_cred_userpass; + callbacks.payload = &user_pass; + g_options.remote_callbacks = &callbacks; cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options)); git_repository_free(g_repo); g_repo = NULL; @@ -172,8 +174,11 @@ void test_online_clone__bitbucket_style(void) "libgit2", "libgit2" }; - g_options.cred_acquire_cb = git_cred_userpass; - g_options.cred_acquire_payload = &user_pass; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + callbacks.credentials = git_cred_userpass; + callbacks.payload = &user_pass; + g_options.remote_callbacks = &callbacks; cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options)); git_repository_free(g_repo); g_repo = NULL; diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index d0d4ed05b..05cef56e7 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -17,6 +17,8 @@ static char *_remote_url; static char *_remote_user; static char *_remote_pass; +static int cred_acquire_cb(git_cred **, const char *, const char *, unsigned int, void *); + static git_remote *_remote; static bool _cred_acquire_called; static record_callbacks_data _record_cbs_data = {{ 0 }}; @@ -294,7 +296,6 @@ void test_online_push__initialize(void) if (_remote_url) { cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url)); - git_remote_set_cred_acquire_cb(_remote, cred_acquire_cb, &_cred_acquire_called); record_callbacks_data_clear(&_record_cbs_data); git_remote_set_callbacks(_remote, &_record_cbs); diff --git a/tests-clar/online/push_util.h b/tests-clar/online/push_util.h index 659c6dd54..64f02cf2f 100644 --- a/tests-clar/online/push_util.h +++ b/tests-clar/online/push_util.h @@ -12,7 +12,7 @@ extern const git_oid OID_ZERO; * @param data pointer to a record_callbacks_data instance */ #define RECORD_CALLBACKS_INIT(data) \ - { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, NULL, record_update_tips_cb, data } + { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, record_update_tips_cb, data } typedef struct { char *name; -- cgit v1.2.1 From d19870d947eef17008ae0b4b7ebc9e9d0038a770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 16 Sep 2013 05:10:55 +0200 Subject: clone: implement git_clone_into This allows you to set up the repository and remote as you which to have them before performing the clone operation. --- include/git2/clone.h | 16 ++++++++++ src/clone.c | 78 ++++++++++++++++++++++++++++++++++++++--------- tests-clar/online/clone.c | 39 ++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 15 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index 38c759f6e..c3936f6b0 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -99,6 +99,22 @@ GIT_EXTERN(int) git_clone( const char *local_path, const git_clone_options *options); +/** + * Clone into a repository + * + * After creating the repository and remote and configuring them for + * paths and callbacks respectively, you can call this function to + * perform the clone operation and optionally checkout files. + * + * @param repo the repository to use + * @param remote the remote repository to clone from + * @param co_opts options to use during checkout + * @param branch the branch to checkout after the clone, pass NULL for the remote's + * default branch + * @return 0 on success or an error code + */ +GIT_EXTERN(int) git_clone_into(git_repository *repo, git_remote *remote, git_checkout_opts *co_opts, const char *branch); + /** @} */ GIT_END_DECL #endif diff --git a/src/clone.c b/src/clone.c index 8385fb264..436fdff43 100644 --- a/src/clone.c +++ b/src/clone.c @@ -270,23 +270,23 @@ cleanup: static int update_head_to_branch( git_repository *repo, - const git_clone_options *options) + const char *remote_name, + const char *branch) { int retcode; git_buf remote_branch_name = GIT_BUF_INIT; git_reference* remote_ref = NULL; - assert(options->checkout_branch); + assert(remote_name && branch); if ((retcode = git_buf_printf(&remote_branch_name, GIT_REFS_REMOTES_DIR "%s/%s", - options->remote_name, options->checkout_branch)) < 0 ) + remote_name, branch)) < 0 ) goto cleanup; if ((retcode = git_reference_lookup(&remote_ref, repo, git_buf_cstr(&remote_branch_name))) < 0) goto cleanup; - retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), - options->checkout_branch); + retcode = update_head_to_new_branch(repo, git_reference_target(remote_ref), branch); cleanup: git_reference_free(remote_ref); @@ -350,6 +350,23 @@ on_error: return error; } +static int do_fetch(git_remote *origin) +{ + int retcode; + + /* Connect and download everything */ + if ((retcode = git_remote_connect(origin, GIT_DIRECTION_FETCH)) < 0) + return retcode; + + if ((retcode = git_remote_download(origin)) < 0) + return retcode; + + /* Create "origin/foo" branches for all remote branches */ + if ((retcode = git_remote_update_tips(origin)) < 0) + return retcode; + + return 0; +} static int setup_remotes_and_fetch( git_repository *repo, @@ -374,20 +391,12 @@ static int setup_remotes_and_fetch( ((retcode = git_remote_add_fetch(origin, "refs/tags/*:refs/tags/*")) < 0)) goto on_error; - /* Connect and download everything */ - if ((retcode = git_remote_connect(origin, GIT_DIRECTION_FETCH)) < 0) - goto on_error; - - if ((retcode = git_remote_download(origin)) < 0) - goto on_error; - - /* Create "origin/foo" branches for all remote branches */ - if ((retcode = git_remote_update_tips(origin)) < 0) + if ((retcode = do_fetch(origin)) < 0) goto on_error; /* Point HEAD to the requested branch */ if (options->checkout_branch) - retcode = update_head_to_branch(repo, options); + retcode = update_head_to_branch(repo, options->remote_name, options->checkout_branch); /* Point HEAD to the same ref as the remote's head */ else retcode = update_head_to_remote(repo, origin); @@ -432,6 +441,45 @@ static void normalize_options(git_clone_options *dst, const git_clone_options *s } } +int git_clone_into(git_repository *repo, git_remote *remote, git_checkout_opts *co_opts, const char *branch) +{ + int error = 0, old_fetchhead; + size_t nspecs; + + assert(repo && remote); + + if (!git_repository_is_empty(repo)) { + giterr_set(GITERR_INVALID, "the repository is not empty"); + return -1; + } + + if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0) + return error; + + old_fetchhead = git_remote_update_fetchhead(remote); + git_remote_set_update_fetchhead(remote, 0); + + if ((error = do_fetch(remote)) < 0) + goto cleanup; + + if (branch) + error = update_head_to_branch(repo, git_remote_name(remote), branch); + /* Point HEAD to the same ref as the remote's head */ + else + error = update_head_to_remote(repo, remote); + + if (!error && should_checkout(repo, git_repository_is_bare(repo), co_opts)) + error = git_checkout_head(repo, co_opts); + +cleanup: + git_remote_set_update_fetchhead(remote, old_fetchhead); + /* Remove the tags refspec */ + nspecs = git_remote_refspec_count(remote); + git_remote_remove_refspec(remote, nspecs); + + return error; +} + int git_clone( git_repository **out, const char *url, diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index b82cbcd46..9a64ba166 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -126,6 +126,45 @@ void test_online_clone__can_checkout_a_cloned_repo(void) git_buf_free(&path); } +void test_online_clone__clone_into(void) +{ + git_buf path = GIT_BUF_INIT; + git_remote *remote; + git_reference *head; + git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + bool checkout_progress_cb_was_called = false, + fetch_progress_cb_was_called = false; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + checkout_opts.progress_cb = &checkout_progress; + checkout_opts.progress_payload = &checkout_progress_cb_was_called; + + cl_git_pass(git_repository_init(&g_repo, "./foo", false)); + cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL)); + + callbacks.transfer_progress = &fetch_progress; + callbacks.payload = &fetch_progress_cb_was_called; + git_remote_set_callbacks(remote, &callbacks); + + cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL)); + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); + cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path))); + + cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); + cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); + cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); + + cl_assert_equal_i(true, checkout_progress_cb_was_called); + cl_assert_equal_i(true, fetch_progress_cb_was_called); + + git_remote_free(remote); + git_reference_free(head); + git_buf_free(&path); +} + static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *payload) { int *callcount = (int*)payload; -- cgit v1.2.1 From fe3a40a4ff056400cde6e456211d6b5f2ec1008e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 16 Sep 2013 16:54:37 +0200 Subject: remote: add a convenience 'fetch' function. --- include/git2/remote.h | 11 +++++++++++ src/clone.c | 22 ++-------------------- src/remote.c | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 83ad195f4..8c21870de 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -310,6 +310,17 @@ GIT_EXTERN(void) git_remote_free(git_remote *remote); */ GIT_EXTERN(int) git_remote_update_tips(git_remote *remote); +/** + * Download new data and update tips + * + * Convenience function to connect to a remote, download the data, + * disconnect and update the remote-tracking branches. + * + * @param remote the remote to fetch from + * @return 0 or an error code + */ +GIT_EXTERN(int) git_remote_fetch(git_remote *remote); + /** * Return whether a string is a valid remote URL * diff --git a/src/clone.c b/src/clone.c index 436fdff43..13f2a8eea 100644 --- a/src/clone.c +++ b/src/clone.c @@ -350,24 +350,6 @@ on_error: return error; } -static int do_fetch(git_remote *origin) -{ - int retcode; - - /* Connect and download everything */ - if ((retcode = git_remote_connect(origin, GIT_DIRECTION_FETCH)) < 0) - return retcode; - - if ((retcode = git_remote_download(origin)) < 0) - return retcode; - - /* Create "origin/foo" branches for all remote branches */ - if ((retcode = git_remote_update_tips(origin)) < 0) - return retcode; - - return 0; -} - static int setup_remotes_and_fetch( git_repository *repo, const char *url, @@ -391,7 +373,7 @@ static int setup_remotes_and_fetch( ((retcode = git_remote_add_fetch(origin, "refs/tags/*:refs/tags/*")) < 0)) goto on_error; - if ((retcode = do_fetch(origin)) < 0) + if ((retcode = git_remote_fetch(origin)) < 0) goto on_error; /* Point HEAD to the requested branch */ @@ -459,7 +441,7 @@ int git_clone_into(git_repository *repo, git_remote *remote, git_checkout_opts * old_fetchhead = git_remote_update_fetchhead(remote); git_remote_set_update_fetchhead(remote, 0); - if ((error = do_fetch(remote)) < 0) + if ((error = git_remote_fetch(remote)) < 0) goto cleanup; if (branch) diff --git a/src/remote.c b/src/remote.c index 2d0321eb3..ace886502 100644 --- a/src/remote.c +++ b/src/remote.c @@ -767,6 +767,24 @@ int git_remote_download(git_remote *remote) return git_fetch_download_pack(remote); } +int git_remote_fetch(git_remote *remote) +{ + int error; + + /* Connect and download everything */ + if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH)) < 0) + return error; + + if ((error = git_remote_download(remote)) < 0) + return error; + + /* We don't need to be connected anymore */ + git_remote_disconnect(remote); + + /* Create "remote/foo" branches for all remote branches */ + return git_remote_update_tips(remote); +} + static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *update_heads, const char *fetchspec_src) { unsigned int i; -- cgit v1.2.1 From c8dbec4803aa7d8300f19a97431bbf631ac5a392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 16 Sep 2013 18:42:53 +0200 Subject: clone: remove the autotag option Downloading all tags is part of what makes it a clone instead of simply a fetch. --- include/git2/clone.h | 3 --- src/clone.c | 13 +++++-------- tests-clar/clone/nonetwork.c | 33 --------------------------------- 3 files changed, 5 insertions(+), 44 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index c3936f6b0..c80bf9baa 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -54,8 +54,6 @@ GIT_BEGIN_DECL * means use the transport autodetected from the URL. * - `remote_callbacks` may be used to specify custom progress callbacks for * the origin remote before the fetch is initiated. - * - `remote_autotag` may be used to specify the autotag setting before the - * initial fetch. The default is GIT_REMOTE_DOWNLOAD_TAGS_ALL. * - `checkout_branch` gives the name of the branch to checkout. NULL means * use the remote's HEAD. */ @@ -74,7 +72,6 @@ typedef struct git_clone_options { git_transport_flags_t transport_flags; git_transport *transport; git_remote_callbacks *remote_callbacks; - git_remote_autotag_option_t remote_autotag; const char* checkout_branch; } git_clone_options; diff --git a/src/clone.c b/src/clone.c index 13f2a8eea..d720907cc 100644 --- a/src/clone.c +++ b/src/clone.c @@ -310,7 +310,6 @@ static int create_and_configure_origin( if ((error = git_remote_create(&origin, repo, options->remote_name, url)) < 0) goto on_error; - git_remote_set_autotag(origin, options->remote_autotag); /* * Don't write FETCH_HEAD, we'll check out the remote tracking * branch ourselves based on the server's default. @@ -364,13 +363,11 @@ static int setup_remotes_and_fetch( git_remote_set_update_fetchhead(origin, 0); - /* If the download_tags value has not been specified, then make sure to - * download tags as well. It is set here because we want to download tags - * on the initial clone, but do not want to persist the value in the - * configuration file. - */ - if (origin->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_AUTO && - ((retcode = git_remote_add_fetch(origin, "refs/tags/*:refs/tags/*")) < 0)) + /* Make sure to download all tags as well. It is set here because + * we want to download tags on the initial clone, but do not + * want to persist the value in the configuration file. + */ + if((retcode = git_remote_add_fetch(origin, "refs/tags/*:refs/tags/*")) < 0) goto on_error; if ((retcode = git_remote_fetch(origin)) < 0) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 5b9faa645..382491610 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -171,39 +171,6 @@ void test_clone_nonetwork__custom_push_spec(void) cl_assert_equal_s("refs/heads/foo", git_refspec_dst(actual_fs)); } -void test_clone_nonetwork__custom_autotag(void) -{ - git_remote *origin; - git_strarray tags = {0}; - - g_options.remote_autotag = GIT_REMOTE_DOWNLOAD_TAGS_NONE; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_tag_list(&tags, g_repo)); - cl_assert_equal_sz(0, tags.count); - - cl_git_pass(git_remote_load(&origin, g_repo, "origin")); - cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_NONE, origin->download_tags); - - git_strarray_free(&tags); - git_remote_free(origin); -} - -void test_clone_nonetwork__custom_autotag_tags_all(void) -{ - git_strarray tags = {0}; - git_remote *origin; - - g_options.remote_autotag = GIT_REMOTE_DOWNLOAD_TAGS_ALL; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_remote_load(&origin, g_repo, "origin")); - cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_ALL, origin->download_tags); - - git_strarray_free(&tags); - git_remote_free(origin); -} - void test_clone_nonetwork__cope_with_already_existing_directory(void) { p_mkdir("./foo", GIT_DIR_MODE); -- cgit v1.2.1 From e3a92f0dfc28e423a2f06688338f81b8d17abaf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 17 Sep 2013 05:31:34 +0200 Subject: clone: implement git_clone on top of git_clone_into Unify the code bases. --- src/clone.c | 77 +++++++++++++++---------------------------------------------- 1 file changed, 19 insertions(+), 58 deletions(-) diff --git a/src/clone.c b/src/clone.c index d720907cc..3df317045 100644 --- a/src/clone.c +++ b/src/clone.c @@ -310,12 +310,6 @@ static int create_and_configure_origin( if ((error = git_remote_create(&origin, repo, options->remote_name, url)) < 0) goto on_error; - /* - * Don't write FETCH_HEAD, we'll check out the remote tracking - * branch ourselves based on the server's default. - */ - git_remote_set_update_fetchhead(origin, 0); - if (options->remote_callbacks && (error = git_remote_set_callbacks(origin, options->remote_callbacks)) < 0) goto on_error; @@ -349,43 +343,6 @@ on_error: return error; } -static int setup_remotes_and_fetch( - git_repository *repo, - const char *url, - const git_clone_options *options) -{ - int retcode = GIT_ERROR; - git_remote *origin = NULL; - - /* Construct an origin remote */ - if ((retcode = create_and_configure_origin(&origin, repo, url, options)) < 0) - goto on_error; - - git_remote_set_update_fetchhead(origin, 0); - - /* Make sure to download all tags as well. It is set here because - * we want to download tags on the initial clone, but do not - * want to persist the value in the configuration file. - */ - if((retcode = git_remote_add_fetch(origin, "refs/tags/*:refs/tags/*")) < 0) - goto on_error; - - if ((retcode = git_remote_fetch(origin)) < 0) - goto on_error; - - /* Point HEAD to the requested branch */ - if (options->checkout_branch) - retcode = update_head_to_branch(repo, options->remote_name, options->checkout_branch); - /* Point HEAD to the same ref as the remote's head */ - else - retcode = update_head_to_remote(repo, origin); - -on_error: - git_remote_free(origin); - return retcode; -} - - static bool should_checkout( git_repository *repo, bool is_bare, @@ -467,6 +424,7 @@ int git_clone( { int retcode = GIT_ERROR; git_repository *repo = NULL; + git_remote *origin; git_clone_options normOptions; int remove_directory_on_failure = 0; git_repository_init_options initOptions = GIT_REPOSITORY_INIT_OPTIONS_INIT; @@ -486,24 +444,27 @@ int git_clone( /* Only remove the directory on failure if we create it */ remove_directory_on_failure = !git_path_exists(local_path); - if (!(retcode = git_repository_init_ext(&repo, local_path, normOptions.init_options))) { - if ((retcode = setup_remotes_and_fetch(repo, url, &normOptions)) < 0) { - /* Failed to fetch; clean up */ - git_repository_free(repo); + if ((retcode = git_repository_init_ext(&repo, local_path, normOptions.init_options)) < 0) + return retcode; + + if ((retcode = create_and_configure_origin(&origin, repo, url, &normOptions)) < 0) + goto cleanup; - if (remove_directory_on_failure) - git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES); - else - git_futils_cleanupdir_r(local_path); + retcode = git_clone_into(repo, origin, &normOptions.checkout_opts, normOptions.checkout_branch); + git_remote_free(origin); - } else { - *out = repo; - retcode = 0; - } - } + if (retcode < 0) + goto cleanup; - if (!retcode && should_checkout(repo, normOptions.bare, &normOptions.checkout_opts)) - retcode = git_checkout_head(*out, &normOptions.checkout_opts); + *out = repo; + return 0; + +cleanup: + git_repository_free(repo); + if (remove_directory_on_failure) + git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES); + else + git_futils_cleanupdir_r(local_path); return retcode; } -- cgit v1.2.1 From 6ac15eff6d173674d9f17e9d5ddb98997eb97cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 22:34:05 +0200 Subject: clone: remove more options from basic clone The basic clone function is there to make it easy to create a "normal" clone. Remove a bunch of options that are about changing the remote's configuration. --- include/git2/clone.h | 7 ------- src/clone.c | 48 +++++-------------------------------------- tests-clar/clone/nonetwork.c | 49 -------------------------------------------- 3 files changed, 5 insertions(+), 99 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index c80bf9baa..0a89b5712 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -62,15 +62,8 @@ typedef struct git_clone_options { unsigned int version; git_checkout_opts checkout_opts; - git_repository_init_options *init_options; int bare; - const char *remote_name; - const char *pushurl; - const char *fetch_spec; - const char *push_spec; - git_transport_flags_t transport_flags; - git_transport *transport; git_remote_callbacks *remote_callbacks; const char* checkout_branch; } git_clone_options; diff --git a/src/clone.c b/src/clone.c index 3df317045..abea0bd8f 100644 --- a/src/clone.c +++ b/src/clone.c @@ -307,31 +307,13 @@ static int create_and_configure_origin( int error; git_remote *origin = NULL; - if ((error = git_remote_create(&origin, repo, options->remote_name, url)) < 0) + if ((error = git_remote_create(&origin, repo, "origin", url)) < 0) goto on_error; if (options->remote_callbacks && (error = git_remote_set_callbacks(origin, options->remote_callbacks)) < 0) goto on_error; - if (options->fetch_spec) { - git_remote_clear_refspecs(origin); - if ((error = git_remote_add_fetch(origin, options->fetch_spec)) < 0) - goto on_error; - } - - if (options->push_spec && - (error = git_remote_add_push(origin, options->push_spec)) < 0) - goto on_error; - - if (options->pushurl && - (error = git_remote_set_pushurl(origin, options->pushurl)) < 0) - goto on_error; - - if (options->transport_flags == GIT_TRANSPORTFLAGS_NO_CHECK_CERT) { - git_remote_check_cert(origin, 0); - } - if ((error = git_remote_save(origin)) < 0) goto on_error; @@ -360,23 +342,6 @@ static bool should_checkout( return !git_repository_head_unborn(repo); } -static void normalize_options(git_clone_options *dst, const git_clone_options *src, git_repository_init_options *initOptions) -{ - git_clone_options default_options = GIT_CLONE_OPTIONS_INIT; - if (!src) src = &default_options; - - *dst = *src; - - /* Provide defaults for null pointers */ - if (!dst->remote_name) dst->remote_name = "origin"; - if (!dst->init_options) { - dst->init_options = initOptions; - initOptions->flags = GIT_REPOSITORY_INIT_MKPATH; - if (dst->bare) - initOptions->flags |= GIT_REPOSITORY_INIT_BARE; - } -} - int git_clone_into(git_repository *repo, git_remote *remote, git_checkout_opts *co_opts, const char *branch) { int error = 0, old_fetchhead; @@ -425,14 +390,11 @@ int git_clone( int retcode = GIT_ERROR; git_repository *repo = NULL; git_remote *origin; - git_clone_options normOptions; int remove_directory_on_failure = 0; - git_repository_init_options initOptions = GIT_REPOSITORY_INIT_OPTIONS_INIT; assert(out && url && local_path); - normalize_options(&normOptions, options, &initOptions); - GITERR_CHECK_VERSION(&normOptions, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); + GITERR_CHECK_VERSION(options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); /* Only clone to a new directory or an empty directory */ if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) { @@ -444,13 +406,13 @@ int git_clone( /* Only remove the directory on failure if we create it */ remove_directory_on_failure = !git_path_exists(local_path); - if ((retcode = git_repository_init_ext(&repo, local_path, normOptions.init_options)) < 0) + if ((retcode = git_repository_init(&repo, local_path, options->bare)) < 0) return retcode; - if ((retcode = create_and_configure_origin(&origin, repo, url, &normOptions)) < 0) + if ((retcode = create_and_configure_origin(&origin, repo, url, options)) < 0) goto cleanup; - retcode = git_clone_into(repo, origin, &normOptions.checkout_opts, normOptions.checkout_branch); + retcode = git_clone_into(repo, origin, &options->checkout_opts, options->checkout_branch); git_remote_free(origin); if (retcode < 0) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 382491610..84654fa5a 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -122,55 +122,6 @@ void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(vo cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); } -void test_clone_nonetwork__custom_origin_name(void) -{ - g_options.remote_name = "my_origin"; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin")); -} - -void test_clone_nonetwork__custom_push_url(void) -{ - const char *url = "http://example.com"; - - g_options.pushurl = url; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_remote_load(&g_remote, g_repo, "origin")); - cl_assert_equal_s(url, git_remote_pushurl(g_remote)); -} - -void test_clone_nonetwork__custom_fetch_spec(void) -{ - const git_refspec *actual_fs; - const char *spec = "+refs/heads/master:refs/heads/foo"; - - g_options.fetch_spec = spec; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_remote_load(&g_remote, g_repo, "origin")); - actual_fs = git_remote_get_refspec(g_remote, 0); - cl_assert_equal_s("refs/heads/master", git_refspec_src(actual_fs)); - cl_assert_equal_s("refs/heads/foo", git_refspec_dst(actual_fs)); - - cl_git_pass(git_reference_lookup(&g_ref, g_repo, "refs/heads/foo")); -} - -void test_clone_nonetwork__custom_push_spec(void) -{ - const git_refspec *actual_fs; - const char *spec = "+refs/heads/master:refs/heads/foo"; - - g_options.push_spec = spec; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_remote_load(&g_remote, g_repo, "origin")); - actual_fs = git_remote_get_refspec(g_remote, git_remote_refspec_count(g_remote) - 1); - cl_assert_equal_s("refs/heads/master", git_refspec_src(actual_fs)); - cl_assert_equal_s("refs/heads/foo", git_refspec_dst(actual_fs)); -} - void test_clone_nonetwork__cope_with_already_existing_directory(void) { p_mkdir("./foo", GIT_DIR_MODE); -- cgit v1.2.1 From b9bf5d701dd6dfcfcb41d2655f59f7669cd50ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 22:46:32 +0200 Subject: clone: re-add a way to ignore certificate errors This used to be done via transport flags, which was removed in a previous commit. --- include/git2/clone.h | 1 + src/clone.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/include/git2/clone.h b/include/git2/clone.h index 0a89b5712..cf759ab5c 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -63,6 +63,7 @@ typedef struct git_clone_options { git_checkout_opts checkout_opts; int bare; + int ignore_cert_errors; git_remote_callbacks *remote_callbacks; const char* checkout_branch; diff --git a/src/clone.c b/src/clone.c index abea0bd8f..904be1b57 100644 --- a/src/clone.c +++ b/src/clone.c @@ -310,6 +310,9 @@ static int create_and_configure_origin( if ((error = git_remote_create(&origin, repo, "origin", url)) < 0) goto on_error; + if (options->ignore_cert_errors) + git_remote_check_cert(origin, 0); + if (options->remote_callbacks && (error = git_remote_set_callbacks(origin, options->remote_callbacks)) < 0) goto on_error; -- cgit v1.2.1 From eec1c1fe1e9a12b57c4014be25ce4ed390c8e199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 22:49:20 +0200 Subject: clone: const-ify checkout options The removal of many options which lead to the direct usage of the user's checkout options means we should make sure they remain const. --- include/git2/checkout.h | 2 +- include/git2/clone.h | 2 +- src/checkout.c | 6 +++--- src/checkout.h | 2 +- src/clone.c | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/git2/checkout.h b/include/git2/checkout.h index aa48069cd..844f0a9e2 100644 --- a/include/git2/checkout.h +++ b/include/git2/checkout.h @@ -255,7 +255,7 @@ typedef struct git_checkout_opts { */ GIT_EXTERN(int) git_checkout_head( git_repository *repo, - git_checkout_opts *opts); + const git_checkout_opts *opts); /** * Updates files in the working tree to match the content of the index. diff --git a/include/git2/clone.h b/include/git2/clone.h index cf759ab5c..a59de1bc7 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -104,7 +104,7 @@ GIT_EXTERN(int) git_clone( * default branch * @return 0 on success or an error code */ -GIT_EXTERN(int) git_clone_into(git_repository *repo, git_remote *remote, git_checkout_opts *co_opts, const char *branch); +GIT_EXTERN(int) git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch); /** @} */ GIT_END_DECL diff --git a/src/checkout.c b/src/checkout.c index 0e9d11bff..5d741d393 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -1119,7 +1119,7 @@ static void checkout_data_clear(checkout_data *data) static int checkout_data_init( checkout_data *data, git_iterator *target, - git_checkout_opts *proposed) + const git_checkout_opts *proposed) { int error = 0; git_repository *repo = git_iterator_owner(target); @@ -1229,7 +1229,7 @@ cleanup: int git_checkout_iterator( git_iterator *target, - git_checkout_opts *opts) + const git_checkout_opts *opts) { int error = 0; git_iterator *baseline = NULL, *workdir = NULL; @@ -1404,7 +1404,7 @@ int git_checkout_tree( int git_checkout_head( git_repository *repo, - git_checkout_opts *opts) + const git_checkout_opts *opts) { int error; git_tree *head = NULL; diff --git a/src/checkout.h b/src/checkout.h index b1dc80c38..6d7186860 100644 --- a/src/checkout.h +++ b/src/checkout.h @@ -19,6 +19,6 @@ */ extern int git_checkout_iterator( git_iterator *target, - git_checkout_opts *opts); + const git_checkout_opts *opts); #endif diff --git a/src/clone.c b/src/clone.c index 904be1b57..60525939f 100644 --- a/src/clone.c +++ b/src/clone.c @@ -331,7 +331,7 @@ on_error: static bool should_checkout( git_repository *repo, bool is_bare, - git_checkout_opts *opts) + const git_checkout_opts *opts) { if (is_bare) return false; @@ -345,7 +345,7 @@ static bool should_checkout( return !git_repository_head_unborn(repo); } -int git_clone_into(git_repository *repo, git_remote *remote, git_checkout_opts *co_opts, const char *branch) +int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch) { int error = 0, old_fetchhead; size_t nspecs; -- cgit v1.2.1 From c833893c64d28d4c017fdbf90bbeb714314a8dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 22:57:01 +0200 Subject: clone: re-allow using a custom remote name This is a small thing that by itself doesn't quite justify making the user use clone_into. --- include/git2/clone.h | 22 +++++----------------- src/clone.c | 4 +++- tests-clar/clone/nonetwork.c | 9 +++++++++ 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index a59de1bc7..bd602fb7a 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -35,25 +35,12 @@ GIT_BEGIN_DECL * set the `checkout_strategy` to GIT_CHECKOUT_DEFAULT. * - `bare` should be set to zero to create a standard repo, non-zero for * a bare repo - * - `fetch_progress_cb` is optional callback for fetch progress. Be aware that - * this is called inline with network and indexing operations, so performance - * may be affected. - * - `fetch_progress_payload` is payload for fetch_progress_cb + * - `ignore_cert_errors` should be set to 1 if errors validating the remote host's + * certificate should be ignored. * * ** "origin" remote options: ** * - `remote_name` is the name given to the "origin" remote. The default is * "origin". - * - `pushurl` is a URL to be used for pushing. NULL means use the fetch url. - * - `fetch_spec` is the fetch specification to be used for fetching. NULL - * results in the same behavior as GIT_REMOTE_DEFAULT_FETCH. - * - `push_spec` is the fetch specification to be used for pushing. NULL means - * use the same spec as for fetching. - * - `transport_flags` is flags used to create transport if no transport is - * provided. - * - `transport` is a custom transport to be used for the initial fetch. NULL - * means use the transport autodetected from the URL. - * - `remote_callbacks` may be used to specify custom progress callbacks for - * the origin remote before the fetch is initiated. * - `checkout_branch` gives the name of the branch to checkout. NULL means * use the remote's HEAD. */ @@ -62,10 +49,11 @@ typedef struct git_clone_options { unsigned int version; git_checkout_opts checkout_opts; + git_remote_callbacks *remote_callbacks; + int bare; int ignore_cert_errors; - - git_remote_callbacks *remote_callbacks; + const char *remote_name; const char* checkout_branch; } git_clone_options; diff --git a/src/clone.c b/src/clone.c index 60525939f..cad9ea1dc 100644 --- a/src/clone.c +++ b/src/clone.c @@ -306,8 +306,10 @@ static int create_and_configure_origin( { int error; git_remote *origin = NULL; + const char *name; - if ((error = git_remote_create(&origin, repo, "origin", url)) < 0) + name = options->remote_name ? options->remote_name : "origin"; + if ((error = git_remote_create(&origin, repo, name, url)) < 0) goto on_error; if (options->ignore_cert_errors) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 84654fa5a..c7a219259 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -122,6 +122,15 @@ void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(vo cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); } +void test_clone_nonetwork__custom_origin_name(void) +{ + g_options.remote_name = "my_origin"; + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); + + cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin")); +} + + void test_clone_nonetwork__cope_with_already_existing_directory(void) { p_mkdir("./foo", GIT_DIR_MODE); -- cgit v1.2.1 From fdc7e5e35efa072a145cf318457055f60c9b21eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 23:14:12 +0200 Subject: clone: bring back NULL as defaults This wasremoved as part of the large culling a few commits ago. --- src/clone.c | 14 +++++++++----- tests-clar/clone/nonetwork.c | 6 ++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/clone.c b/src/clone.c index cad9ea1dc..1af6e393f 100644 --- a/src/clone.c +++ b/src/clone.c @@ -390,16 +390,20 @@ int git_clone( git_repository **out, const char *url, const char *local_path, - const git_clone_options *options) + const git_clone_options *_options) { int retcode = GIT_ERROR; git_repository *repo = NULL; git_remote *origin; + git_clone_options options = GIT_CLONE_OPTIONS_INIT; int remove_directory_on_failure = 0; assert(out && url && local_path); - GITERR_CHECK_VERSION(options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); + if (_options) + memcpy(&options, _options, sizeof(git_clone_options)); + + GITERR_CHECK_VERSION(&options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options"); /* Only clone to a new directory or an empty directory */ if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) { @@ -411,13 +415,13 @@ int git_clone( /* Only remove the directory on failure if we create it */ remove_directory_on_failure = !git_path_exists(local_path); - if ((retcode = git_repository_init(&repo, local_path, options->bare)) < 0) + if ((retcode = git_repository_init(&repo, local_path, options.bare)) < 0) return retcode; - if ((retcode = create_and_configure_origin(&origin, repo, url, options)) < 0) + if ((retcode = create_and_configure_origin(&origin, repo, url, &options)) < 0) goto cleanup; - retcode = git_clone_into(repo, origin, &options->checkout_opts, options->checkout_branch); + retcode = git_clone_into(repo, origin, &options.checkout_opts, options.checkout_branch); git_remote_free(origin); if (retcode < 0) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index c7a219259..9b666b3f7 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -130,6 +130,12 @@ void test_clone_nonetwork__custom_origin_name(void) cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin")); } +void test_clone_nonetwork__defaults(void) +{ + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", NULL)); + cl_assert(g_repo); + cl_git_pass(git_remote_load(&g_remote, g_repo, "origin")); +} void test_clone_nonetwork__cope_with_already_existing_directory(void) { -- cgit v1.2.1 From 36a241acbb39aa46cf5f7807aebd92e45f2f5eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 23:14:52 +0200 Subject: clone: mention clone_into in the clone documentation Make the difference more explicit. --- include/git2/clone.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index bd602fb7a..a341a413c 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -61,8 +61,11 @@ typedef struct git_clone_options { #define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTS_VERSION, GIT_CHECKOUT_SAFE_CREATE}} /** - * Clone a remote repository, and checkout the branch pointed to by the remote - * HEAD. + * Clone a remote repository. + * + * This version handles the simple case. If you'd like to create the + * repository or remote with non-default settings, you can create and + * configure them and then use `git_clone_into()`. * * @param out pointer that will receive the resulting repository object * @param url the remote repository to clone -- cgit v1.2.1 From ffc97d51264f8af435ccf52d33a62a6925b174c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 20 Sep 2013 23:23:42 +0200 Subject: remote: add some comments to the callback struct Hopefully clear up what they're for. --- include/git2/remote.h | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 8c21870de..8145de180 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -400,15 +400,47 @@ typedef enum git_remote_completion_type { /** * The callback settings structure * - * Set the calbacks to be called by the remote. + * Set the callbacks to be called by the remote when informing the user + * about the progress of the network operations. */ struct git_remote_callbacks { unsigned int version; + /** + * Textual progress from the remote. Text send over the + * progress side-band will be passed to this function (this is + * the 'counting objects' output. + */ void (*progress)(const char *str, int len, void *data); + + /** + * Completion is called when different parts of the download + * process are done (currently unused). + */ int (*completion)(git_remote_completion_type type, void *data); + + /** + * This will be called if the remote host requires + * authentication in order to connect to it. + */ int (*credentials)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data); + + /** + * During the download of new data, this will be regularly + * called with the current count of progress done by the + * indexer. + */ int (*transfer_progress)(const git_transfer_progress *stats, void *data); + + /** + * Each time a reference is updated locally, this function + * will be called with information about it. + */ int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data); + + /** + * This will be passed to each of the callbacks in this struct + * as the last parameter. + */ void *payload; }; -- cgit v1.2.1 From b976f3c2c228413d124be8fea3280a44bd5e3136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 19 Aug 2013 13:01:49 +0200 Subject: reflog: move the reflog implementation into refdb_fs References and their logs are logically coupled, let's make it so in the code by moving the fs-based reflog implementation to live next to the fs-based refs one. As part of the change, make the function take names rather than references, as only the names are relevant when looking up and handling reflogs. --- include/git2/reflog.h | 19 +- include/git2/sys/refdb_backend.h | 32 +++ include/git2/sys/reflog.h | 21 ++ src/refdb.c | 16 ++ src/refdb.h | 4 + src/refdb_fs.c | 448 +++++++++++++++++++++++++++++++++++++++ src/reflog.c | 437 ++++---------------------------------- src/reflog.h | 7 +- src/refs.c | 2 +- src/revparse.c | 4 +- src/stash.c | 11 +- tests-clar/refs/reflog/drop.c | 13 +- tests-clar/refs/reflog/reflog.c | 23 +- tests-clar/stash/drop.c | 4 +- 14 files changed, 595 insertions(+), 446 deletions(-) create mode 100644 include/git2/sys/reflog.h diff --git a/include/git2/reflog.h b/include/git2/reflog.h index 4944530af..b31472c37 100644 --- a/include/git2/reflog.h +++ b/include/git2/reflog.h @@ -31,10 +31,11 @@ GIT_BEGIN_DECL * git_reflog_free(). * * @param out pointer to reflog - * @param ref reference to read the reflog for + * @param repo the repostiory + * @param name reference to look up * @return 0 or an error code */ -GIT_EXTERN(int) git_reflog_read(git_reflog **out, const git_reference *ref); +GIT_EXTERN(int) git_reflog_read(git_reflog **out, git_repository *repo, const char *name); /** * Write an existing in-memory reflog object back to disk @@ -59,26 +60,28 @@ GIT_EXTERN(int) git_reflog_write(git_reflog *reflog); GIT_EXTERN(int) git_reflog_append(git_reflog *reflog, const git_oid *id, const git_signature *committer, const char *msg); /** - * Rename the reflog for the given reference + * Rename a reflog * * The reflog to be renamed is expected to already exist * * The new name will be checked for validity. * See `git_reference_create_symbolic()` for rules about valid names. * - * @param ref the reference - * @param name the new name of the reference + * @param repo the repository + * @param old_name the old name of the reference + * @param new_name the new name of the reference * @return 0 on success, GIT_EINVALIDSPEC or an error code */ -GIT_EXTERN(int) git_reflog_rename(git_reference *ref, const char *name); +GIT_EXTERN(int) git_reflog_rename(git_repository *repo, const char *old_name, const char *name); /** * Delete the reflog for the given reference * - * @param ref the reference + * @param repo the repository + * @param name the reflog to delete * @return 0 or an error code */ -GIT_EXTERN(int) git_reflog_delete(git_reference *ref); +GIT_EXTERN(int) git_reflog_delete(git_repository *repo, const char *name); /** * Get the number of log entries in a reflog diff --git a/include/git2/sys/refdb_backend.h b/include/git2/sys/refdb_backend.h index addaa86fd..93c4a521a 100644 --- a/include/git2/sys/refdb_backend.h +++ b/include/git2/sys/refdb_backend.h @@ -119,6 +119,38 @@ struct git_refdb_backend { * provide this function; if it is not provided, nothing will be done. */ void (*free)(git_refdb_backend *backend); + + /** + * Read the reflog for the given reference name. + */ + int (*reflog_read)(git_reflog **out, git_refdb_backend *backend, const char *name); + + /** + * Write a reflog to disk. + */ + int (*reflog_write)(git_refdb_backend *backend, git_reflog *reflog); + + /** + * Append an entry to the given reflog + */ + int (*reflog_append)(git_refdb_backend *backend, git_reflog *reflog, + const git_oid *new_oid, const git_signature *committer, + const char *msg); + + /** + * Rename a reflog + */ + int (*reflog_rename)(git_refdb_backend *_backend, const char *old_name, const char *new_name); + + /** + * Drop an entry from the reflog + */ + int (*reflog_drop)(git_refdb_backend *_backend, git_reflog *reflog, + size_t idx, int rewrite_previous_entry); + /** + * Remove a reflog. + */ + int (*reflog_delete)(git_refdb_backend *backend, const char *name); }; #define GIT_REFDB_BACKEND_VERSION 1 diff --git a/include/git2/sys/reflog.h b/include/git2/sys/reflog.h new file mode 100644 index 000000000..c9d0041b9 --- /dev/null +++ b/include/git2/sys/reflog.h @@ -0,0 +1,21 @@ +/* + * 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_sys_git_reflog_h__ +#define INCLUDE_sys_git_reflog_h__ + +#include "git2/common.h" +#include "git2/types.h" +#include "git2/oid.h" + +GIT_BEGIN_DECL + +GIT_EXTERN(git_reflog_entry *) git_reflog_entry__alloc(void); +GIT_EXTERN(void) git_reflog_entry__free(git_reflog_entry *entry); + +GIT_END_DECL + +#endif diff --git a/src/refdb.c b/src/refdb.c index 7df61a577..adb58806e 100644 --- a/src/refdb.c +++ b/src/refdb.c @@ -16,6 +16,7 @@ #include "hash.h" #include "refdb.h" #include "refs.h" +#include "reflog.h" int git_refdb_new(git_refdb **out, git_repository *repo) { @@ -203,3 +204,18 @@ int git_refdb_delete(struct git_refdb *db, const char *ref_name) assert(db && db->backend); return db->backend->del(db->backend, ref_name); } + +int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name) +{ + int error; + + assert(db && db->backend); + + if ((error = db->backend->reflog_read(out, db->backend, name)) < 0) + return error; + + GIT_REFCOUNT_INC(db); + (*out)->db = db; + + return 0; +} diff --git a/src/refdb.h b/src/refdb.h index 3aea37b62..0ee60d911 100644 --- a/src/refdb.h +++ b/src/refdb.h @@ -43,4 +43,8 @@ void git_refdb_iterator_free(git_reference_iterator *iter); int git_refdb_write(git_refdb *refdb, git_reference *ref, int force); int git_refdb_delete(git_refdb *refdb, const char *ref_name); +int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name); +int git_refdb_reflog_write(git_reflog *reflog); + + #endif diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 0ba711eb7..4d695721d 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -16,12 +16,14 @@ #include "refdb_fs.h" #include "iterator.h" #include "sortedcache.h" +#include "signature.h" #include #include #include #include #include +#include GIT__USE_STRMAP; @@ -1067,6 +1069,446 @@ static int setup_namespace(git_buf *path, git_repository *repo) return 0; } +static int reflog_alloc(git_reflog **reflog, const char *name) +{ + git_reflog *log; + + *reflog = NULL; + + log = git__calloc(1, sizeof(git_reflog)); + GITERR_CHECK_ALLOC(log); + + log->ref_name = git__strdup(name); + GITERR_CHECK_ALLOC(log->ref_name); + + if (git_vector_init(&log->entries, 0, NULL) < 0) { + git__free(log->ref_name); + git__free(log); + return -1; + } + + *reflog = log; + + return 0; +} + +static int reflog_parse(git_reflog *log, const char *buf, size_t buf_size) +{ + const char *ptr; + git_reflog_entry *entry; + +#define seek_forward(_increase) do { \ + if (_increase >= buf_size) { \ + giterr_set(GITERR_INVALID, "Ran out of data while parsing reflog"); \ + goto fail; \ + } \ + buf += _increase; \ + buf_size -= _increase; \ + } while (0) + + while (buf_size > GIT_REFLOG_SIZE_MIN) { + entry = git__calloc(1, sizeof(git_reflog_entry)); + GITERR_CHECK_ALLOC(entry); + + entry->committer = git__malloc(sizeof(git_signature)); + GITERR_CHECK_ALLOC(entry->committer); + + if (git_oid_fromstrn(&entry->oid_old, buf, GIT_OID_HEXSZ) < 0) + goto fail; + seek_forward(GIT_OID_HEXSZ + 1); + + if (git_oid_fromstrn(&entry->oid_cur, buf, GIT_OID_HEXSZ) < 0) + goto fail; + seek_forward(GIT_OID_HEXSZ + 1); + + ptr = buf; + + /* Seek forward to the end of the signature. */ + while (*buf && *buf != '\t' && *buf != '\n') + seek_forward(1); + + if (git_signature__parse(entry->committer, &ptr, buf + 1, NULL, *buf) < 0) + goto fail; + + if (*buf == '\t') { + /* We got a message. Read everything till we reach LF. */ + seek_forward(1); + ptr = buf; + + while (*buf && *buf != '\n') + seek_forward(1); + + entry->msg = git__strndup(ptr, buf - ptr); + GITERR_CHECK_ALLOC(entry->msg); + } else + entry->msg = NULL; + + while (*buf && *buf == '\n' && buf_size > 1) + seek_forward(1); + + if (git_vector_insert(&log->entries, entry) < 0) + goto fail; + } + + return 0; + +#undef seek_forward + +fail: + if (entry) + git_reflog_entry__free(entry); + + return -1; +} + +static int create_new_reflog_file(const char *filepath) +{ + int fd, error; + + if ((error = git_futils_mkpath2file(filepath, GIT_REFLOG_DIR_MODE)) < 0) + return error; + + if ((fd = p_open(filepath, + O_WRONLY | O_CREAT | O_TRUNC, + GIT_REFLOG_FILE_MODE)) < 0) + return -1; + + return p_close(fd); +} + +GIT_INLINE(int) retrieve_reflog_path(git_buf *path, git_repository *repo, const char *name) +{ + return git_buf_join_n(path, '/', 3, repo->path_repository, GIT_REFLOG_DIR, name); +} + +static int refdb_reflog_fs__read(git_reflog **out, git_refdb_backend *_backend, const char *name) +{ + int error = -1; + git_buf log_path = GIT_BUF_INIT; + git_buf log_file = GIT_BUF_INIT; + git_reflog *log = NULL; + git_repository *repo; + refdb_fs_backend *backend; + + assert(out && _backend && name); + + backend = (refdb_fs_backend *) _backend; + repo = backend->repo; + + if (reflog_alloc(&log, name) < 0) + return -1; + + if (retrieve_reflog_path(&log_path, repo, name) < 0) + goto cleanup; + + error = git_futils_readbuffer(&log_file, git_buf_cstr(&log_path)); + if (error < 0 && error != GIT_ENOTFOUND) + goto cleanup; + + if ((error == GIT_ENOTFOUND) && + ((error = create_new_reflog_file(git_buf_cstr(&log_path))) < 0)) + goto cleanup; + + if ((error = reflog_parse(log, + git_buf_cstr(&log_file), git_buf_len(&log_file))) < 0) + goto cleanup; + + *out = log; + goto success; + +cleanup: + git_reflog_free(log); + +success: + git_buf_free(&log_file); + git_buf_free(&log_path); + + return error; +} + +static int serialize_reflog_entry( + git_buf *buf, + const git_oid *oid_old, + const git_oid *oid_new, + const git_signature *committer, + const char *msg) +{ + char raw_old[GIT_OID_HEXSZ+1]; + char raw_new[GIT_OID_HEXSZ+1]; + + git_oid_tostr(raw_old, GIT_OID_HEXSZ+1, oid_old); + git_oid_tostr(raw_new, GIT_OID_HEXSZ+1, oid_new); + + git_buf_clear(buf); + + git_buf_puts(buf, raw_old); + git_buf_putc(buf, ' '); + git_buf_puts(buf, raw_new); + + git_signature__writebuf(buf, " ", committer); + + /* drop trailing LF */ + git_buf_rtrim(buf); + + if (msg) { + git_buf_putc(buf, '\t'); + git_buf_puts(buf, msg); + } + + git_buf_putc(buf, '\n'); + + return git_buf_oom(buf); +} + +static int refdb_reflog_fs__write(git_refdb_backend *_backend, git_reflog *reflog) +{ + int error = -1; + unsigned int i; + git_reflog_entry *entry; + git_repository *repo; + refdb_fs_backend *backend; + git_buf log_path = GIT_BUF_INIT; + git_buf log = GIT_BUF_INIT; + git_filebuf fbuf = GIT_FILEBUF_INIT; + + assert(_backend && reflog); + + backend = (refdb_fs_backend *) _backend; + repo = backend->repo; + + if (retrieve_reflog_path(&log_path, repo, reflog->ref_name) < 0) + return -1; + + if (!git_path_isfile(git_buf_cstr(&log_path))) { + giterr_set(GITERR_INVALID, + "Log file for reference '%s' doesn't exist.", reflog->ref_name); + goto cleanup; + } + + if ((error = git_filebuf_open(&fbuf, git_buf_cstr(&log_path), 0)) < 0) + goto cleanup; + + git_vector_foreach(&reflog->entries, i, entry) { + if (serialize_reflog_entry(&log, &(entry->oid_old), &(entry->oid_cur), entry->committer, entry->msg) < 0) + goto cleanup; + + if ((error = git_filebuf_write(&fbuf, log.ptr, log.size)) < 0) + goto cleanup; + } + + error = git_filebuf_commit(&fbuf, GIT_REFLOG_FILE_MODE); + goto success; + +cleanup: + git_filebuf_cleanup(&fbuf); + +success: + git_buf_free(&log); + git_buf_free(&log_path); + return error; +} + +static int refdb_reflog_fs__append(git_refdb_backend *_backend, git_reflog *reflog, + const git_oid *new_oid, const git_signature *committer, const char *msg) +{ + git_reflog_entry *entry; + const git_reflog_entry *previous; + const char *newline; + + assert(_backend && reflog && new_oid && committer); + + entry = git__calloc(1, sizeof(git_reflog_entry)); + GITERR_CHECK_ALLOC(entry); + + if ((entry->committer = git_signature_dup(committer)) == NULL) + goto cleanup; + + if (msg != NULL) { + if ((entry->msg = git__strdup(msg)) == NULL) + goto cleanup; + + newline = strchr(msg, '\n'); + + if (newline) { + if (newline[1] != '\0') { + giterr_set(GITERR_INVALID, "Reflog message cannot contain newline"); + goto cleanup; + } + + entry->msg[newline - msg] = '\0'; + } + } + + previous = git_reflog_entry_byindex(reflog, 0); + + if (previous == NULL) + git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO); + else + git_oid_cpy(&entry->oid_old, &previous->oid_cur); + + git_oid_cpy(&entry->oid_cur, new_oid); + + if (git_vector_insert(&reflog->entries, entry) < 0) + goto cleanup; + + return 0; + +cleanup: + git_reflog_entry__free(entry); + return -1; +} + +static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_name, const char *new_name) +{ + int error = 0, fd; + git_buf old_path = GIT_BUF_INIT; + git_buf new_path = GIT_BUF_INIT; + git_buf temp_path = GIT_BUF_INIT; + git_buf normalized = GIT_BUF_INIT; + git_repository *repo; + refdb_fs_backend *backend; + + assert(_backend && old_name && new_name); + + backend = (refdb_fs_backend *) _backend; + repo = backend->repo; + + if ((error = git_reference__normalize_name( + &normalized, new_name, GIT_REF_FORMAT_ALLOW_ONELEVEL)) < 0) + return error; + + if (git_buf_joinpath(&temp_path, repo->path_repository, GIT_REFLOG_DIR) < 0) + return -1; + + if (git_buf_joinpath(&old_path, git_buf_cstr(&temp_path), old_name) < 0) + return -1; + + if (git_buf_joinpath(&new_path, git_buf_cstr(&temp_path), git_buf_cstr(&normalized)) < 0) + return -1; + + /* + * Move the reflog to a temporary place. This two-phase renaming is required + * in order to cope with funny renaming use cases when one tries to move a reference + * to a partially colliding namespace: + * - a/b -> a/b/c + * - a/b/c/d -> a/b/c + */ + if (git_buf_joinpath(&temp_path, git_buf_cstr(&temp_path), "temp_reflog") < 0) + return -1; + + if ((fd = git_futils_mktmp(&temp_path, git_buf_cstr(&temp_path))) < 0) { + error = -1; + goto cleanup; + } + + 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); + error = -1; + goto cleanup; + } + + if (git_path_isdir(git_buf_cstr(&new_path)) && + (git_futils_rmdir_r(git_buf_cstr(&new_path), NULL, GIT_RMDIR_SKIP_NONEMPTY) < 0)) { + error = -1; + goto cleanup; + } + + if (git_futils_mkpath2file(git_buf_cstr(&new_path), GIT_REFLOG_DIR_MODE) < 0) { + error = -1; + goto cleanup; + } + + 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); + error = -1; + } + +cleanup: + git_buf_free(&temp_path); + git_buf_free(&old_path); + git_buf_free(&new_path); + git_buf_free(&normalized); + + return error; +} + +static int refdb_reflog_fs__drop(git_refdb_backend *_backend, git_reflog *reflog, + size_t idx, int rewrite_previous_entry) +{ + size_t entrycount; + git_reflog_entry *entry, *previous; + + assert(_backend && reflog); + + entrycount = git_reflog_entrycount(reflog); + + entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); + + if (entry == NULL) { + giterr_set(GITERR_REFERENCE, "No reflog entry at index "PRIuZ, idx); + return GIT_ENOTFOUND; + } + + git_reflog_entry__free(entry); + + if (git_vector_remove( + &reflog->entries, reflog_inverse_index(idx, entrycount)) < 0) + return -1; + + if (!rewrite_previous_entry) + return 0; + + /* No need to rewrite anything when removing the most recent entry */ + if (idx == 0) + return 0; + + /* Have the latest entry just been dropped? */ + if (entrycount == 1) + return 0; + + entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx - 1); + + /* If the oldest entry has just been removed... */ + if (idx == entrycount - 1) { + /* ...clear the oid_old member of the "new" oldest entry */ + if (git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO) < 0) + return -1; + + return 0; + } + + previous = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); + git_oid_cpy(&entry->oid_old, &previous->oid_cur); + + return 0; +} + +static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name) +{ + int error; + git_buf path = GIT_BUF_INIT; + + git_repository *repo; + refdb_fs_backend *backend; + + assert(_backend && name); + + backend = (refdb_fs_backend *) _backend; + repo = backend->repo; + + error = retrieve_reflog_path(&path, repo, name); + + if (!error && git_path_exists(path.ptr)) + error = p_unlink(path.ptr); + + git_buf_free(&path); + + return error; + +} + int git_refdb_backend_fs( git_refdb_backend **backend_out, git_repository *repository) @@ -1100,6 +1542,12 @@ int git_refdb_backend_fs( backend->parent.rename = &refdb_fs_backend__rename; backend->parent.compress = &refdb_fs_backend__compress; backend->parent.free = &refdb_fs_backend__free; + backend->parent.reflog_read = &refdb_reflog_fs__read; + backend->parent.reflog_write = &refdb_reflog_fs__write; + backend->parent.reflog_append = &refdb_reflog_fs__append; + backend->parent.reflog_rename = &refdb_reflog_fs__rename; + backend->parent.reflog_drop = &refdb_reflog_fs__drop; + backend->parent.reflog_delete = &refdb_reflog_fs__delete; *backend_out = (git_refdb_backend *)backend; return 0; diff --git a/src/reflog.c b/src/reflog.c index a6752f618..c10ae9fd4 100644 --- a/src/reflog.c +++ b/src/reflog.c @@ -9,82 +9,16 @@ #include "repository.h" #include "filebuf.h" #include "signature.h" +#include "refdb.h" -static int reflog_init(git_reflog **reflog, const git_reference *ref) -{ - git_reflog *log; - - *reflog = NULL; - - log = git__calloc(1, sizeof(git_reflog)); - GITERR_CHECK_ALLOC(log); - - log->ref_name = git__strdup(ref->name); - GITERR_CHECK_ALLOC(log->ref_name); - - if (git_vector_init(&log->entries, 0, NULL) < 0) { - git__free(log->ref_name); - git__free(log); - return -1; - } - - log->owner = git_reference_owner(ref); - *reflog = log; - - return 0; -} +#include -static int serialize_reflog_entry( - git_buf *buf, - const git_oid *oid_old, - const git_oid *oid_new, - const git_signature *committer, - const char *msg) +git_reflog_entry *git_reflog_entry__alloc(void) { - char raw_old[GIT_OID_HEXSZ+1]; - char raw_new[GIT_OID_HEXSZ+1]; - - git_oid_tostr(raw_old, GIT_OID_HEXSZ+1, oid_old); - git_oid_tostr(raw_new, GIT_OID_HEXSZ+1, oid_new); - - git_buf_clear(buf); - - git_buf_puts(buf, raw_old); - git_buf_putc(buf, ' '); - git_buf_puts(buf, raw_new); - - git_signature__writebuf(buf, " ", committer); - - /* drop trailing LF */ - git_buf_rtrim(buf); - - if (msg) { - git_buf_putc(buf, '\t'); - git_buf_puts(buf, msg); - } - - git_buf_putc(buf, '\n'); - - return git_buf_oom(buf); + return git__calloc(1, sizeof(git_reflog_entry)); } -static int reflog_entry_new(git_reflog_entry **entry) -{ - git_reflog_entry *e; - - assert(entry); - - e = git__malloc(sizeof(git_reflog_entry)); - GITERR_CHECK_ALLOC(e); - - memset(e, 0, sizeof(git_reflog_entry)); - - *entry = e; - - return 0; -} - -static void reflog_entry_free(git_reflog_entry *entry) +void git_reflog_entry__free(git_reflog_entry *entry) { git_signature_free(entry->committer); @@ -92,75 +26,6 @@ static void reflog_entry_free(git_reflog_entry *entry) git__free(entry); } -static int reflog_parse(git_reflog *log, const char *buf, size_t buf_size) -{ - const char *ptr; - git_reflog_entry *entry; - -#define seek_forward(_increase) do { \ - if (_increase >= buf_size) { \ - giterr_set(GITERR_INVALID, "Ran out of data while parsing reflog"); \ - goto fail; \ - } \ - buf += _increase; \ - buf_size -= _increase; \ - } while (0) - - while (buf_size > GIT_REFLOG_SIZE_MIN) { - if (reflog_entry_new(&entry) < 0) - return -1; - - entry->committer = git__malloc(sizeof(git_signature)); - GITERR_CHECK_ALLOC(entry->committer); - - if (git_oid_fromstrn(&entry->oid_old, buf, GIT_OID_HEXSZ) < 0) - goto fail; - seek_forward(GIT_OID_HEXSZ + 1); - - if (git_oid_fromstrn(&entry->oid_cur, buf, GIT_OID_HEXSZ) < 0) - goto fail; - seek_forward(GIT_OID_HEXSZ + 1); - - ptr = buf; - - /* Seek forward to the end of the signature. */ - while (*buf && *buf != '\t' && *buf != '\n') - seek_forward(1); - - if (git_signature__parse(entry->committer, &ptr, buf + 1, NULL, *buf) < 0) - goto fail; - - if (*buf == '\t') { - /* We got a message. Read everything till we reach LF. */ - seek_forward(1); - ptr = buf; - - while (*buf && *buf != '\n') - seek_forward(1); - - entry->msg = git__strndup(ptr, buf - ptr); - GITERR_CHECK_ALLOC(entry->msg); - } else - entry->msg = NULL; - - while (*buf && *buf == '\n' && buf_size > 1) - seek_forward(1); - - if (git_vector_insert(&log->entries, entry) < 0) - goto fail; - } - - return 0; - -#undef seek_forward - -fail: - if (entry) - reflog_entry_free(entry); - - return -1; -} - void git_reflog_free(git_reflog *reflog) { size_t i; @@ -169,10 +34,13 @@ void git_reflog_free(git_reflog *reflog) if (reflog == NULL) return; + if (reflog->db) + GIT_REFCOUNT_DEC(reflog->db, git_refdb__free); + for (i=0; i < reflog->entries.length; i++) { entry = git_vector_get(&reflog->entries, i); - reflog_entry_free(entry); + git_reflog_entry__free(entry); } git_vector_free(&reflog->entries); @@ -180,247 +48,61 @@ void git_reflog_free(git_reflog *reflog) git__free(reflog); } -static int retrieve_reflog_path(git_buf *path, const git_reference *ref) +int git_reflog_read(git_reflog **reflog, git_repository *repo, const char *name) { - return git_buf_join_n(path, '/', 3, - git_reference_owner(ref)->path_repository, GIT_REFLOG_DIR, ref->name); -} + git_refdb *refdb; + int error; -static int create_new_reflog_file(const char *filepath) -{ - int fd, error; + assert(reflog && repo && name); - if ((error = git_futils_mkpath2file(filepath, GIT_REFLOG_DIR_MODE)) < 0) + if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) return error; - if ((fd = p_open(filepath, - O_WRONLY | O_CREAT | O_TRUNC, - GIT_REFLOG_FILE_MODE)) < 0) - return -1; - - return p_close(fd); -} - -int git_reflog_read(git_reflog **reflog, const git_reference *ref) -{ - int error = -1; - git_buf log_path = GIT_BUF_INIT; - git_buf log_file = GIT_BUF_INIT; - git_reflog *log = NULL; - - assert(reflog && ref); - - *reflog = NULL; - - if (reflog_init(&log, ref) < 0) - return -1; - - if (retrieve_reflog_path(&log_path, ref) < 0) - goto cleanup; - - error = git_futils_readbuffer(&log_file, git_buf_cstr(&log_path)); - if (error < 0 && error != GIT_ENOTFOUND) - goto cleanup; - - if ((error == GIT_ENOTFOUND) && - ((error = create_new_reflog_file(git_buf_cstr(&log_path))) < 0)) - goto cleanup; - - if ((error = reflog_parse(log, - git_buf_cstr(&log_file), git_buf_len(&log_file))) < 0) - goto cleanup; - - *reflog = log; - goto success; - -cleanup: - git_reflog_free(log); - -success: - git_buf_free(&log_file); - git_buf_free(&log_path); - - return error; + return git_refdb_reflog_read(reflog, refdb, name); } int git_reflog_write(git_reflog *reflog) { - int error = -1; - unsigned int i; - git_reflog_entry *entry; - git_buf log_path = GIT_BUF_INIT; - git_buf log = GIT_BUF_INIT; - git_filebuf fbuf = GIT_FILEBUF_INIT; - - assert(reflog); - - if (git_buf_join_n(&log_path, '/', 3, - git_repository_path(reflog->owner), GIT_REFLOG_DIR, reflog->ref_name) < 0) - return -1; - - if (!git_path_isfile(git_buf_cstr(&log_path))) { - giterr_set(GITERR_INVALID, - "Log file for reference '%s' doesn't exist.", reflog->ref_name); - goto cleanup; - } - - if ((error = git_filebuf_open(&fbuf, git_buf_cstr(&log_path), 0)) < 0) - goto cleanup; + git_refdb *db; - git_vector_foreach(&reflog->entries, i, entry) { - if (serialize_reflog_entry(&log, &(entry->oid_old), &(entry->oid_cur), entry->committer, entry->msg) < 0) - goto cleanup; + assert(reflog && reflog->db); - if ((error = git_filebuf_write(&fbuf, log.ptr, log.size)) < 0) - goto cleanup; - } - - error = git_filebuf_commit(&fbuf, GIT_REFLOG_FILE_MODE); - goto success; - -cleanup: - git_filebuf_cleanup(&fbuf); - -success: - git_buf_free(&log); - git_buf_free(&log_path); - return error; + db = reflog->db; + return db->backend->reflog_write(db->backend, reflog); } int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_signature *committer, const char *msg) { - git_reflog_entry *entry; - const git_reflog_entry *previous; - const char *newline; - - assert(reflog && new_oid && committer); - - if (reflog_entry_new(&entry) < 0) - return -1; - - if ((entry->committer = git_signature_dup(committer)) == NULL) - goto cleanup; + git_refdb *db; - if (msg != NULL) { - if ((entry->msg = git__strdup(msg)) == NULL) - goto cleanup; + assert(reflog && reflog->db && new_oid && committer); - newline = strchr(msg, '\n'); + db = reflog->db; - if (newline) { - if (newline[1] != '\0') { - giterr_set(GITERR_INVALID, "Reflog message cannot contain newline"); - goto cleanup; - } - - entry->msg[newline - msg] = '\0'; - } - } - - previous = git_reflog_entry_byindex(reflog, 0); - - if (previous == NULL) - git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO); - else - git_oid_cpy(&entry->oid_old, &previous->oid_cur); - - git_oid_cpy(&entry->oid_cur, new_oid); - - if (git_vector_insert(&reflog->entries, entry) < 0) - goto cleanup; - - return 0; - -cleanup: - reflog_entry_free(entry); - return -1; + return db->backend->reflog_append(db->backend, reflog, new_oid, committer, msg); } -int git_reflog_rename(git_reference *ref, const char *new_name) +int git_reflog_rename(git_repository *repo, const char *old_name, const char *new_name) { - int error = 0, fd; - git_buf old_path = GIT_BUF_INIT; - git_buf new_path = GIT_BUF_INIT; - git_buf temp_path = GIT_BUF_INIT; - git_buf normalized = GIT_BUF_INIT; - - assert(ref && new_name); - - if ((error = git_reference__normalize_name( - &normalized, new_name, GIT_REF_FORMAT_ALLOW_ONELEVEL)) < 0) - return error; - - if (git_buf_joinpath(&temp_path, git_reference_owner(ref)->path_repository, GIT_REFLOG_DIR) < 0) - return -1; - - if (git_buf_joinpath(&old_path, git_buf_cstr(&temp_path), ref->name) < 0) - return -1; - - if (git_buf_joinpath(&new_path, git_buf_cstr(&temp_path), git_buf_cstr(&normalized)) < 0) - return -1; + git_refdb *refdb; + int error; - /* - * Move the reflog to a temporary place. This two-phase renaming is required - * in order to cope with funny renaming use cases when one tries to move a reference - * to a partially colliding namespace: - * - a/b -> a/b/c - * - a/b/c/d -> a/b/c - */ - if (git_buf_joinpath(&temp_path, git_buf_cstr(&temp_path), "temp_reflog") < 0) + if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) return -1; - if ((fd = git_futils_mktmp(&temp_path, git_buf_cstr(&temp_path))) < 0) { - error = -1; - goto cleanup; - } - - 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); - error = -1; - goto cleanup; - } - - if (git_path_isdir(git_buf_cstr(&new_path)) && - (git_futils_rmdir_r(git_buf_cstr(&new_path), NULL, GIT_RMDIR_SKIP_NONEMPTY) < 0)) { - error = -1; - goto cleanup; - } - - if (git_futils_mkpath2file(git_buf_cstr(&new_path), GIT_REFLOG_DIR_MODE) < 0) { - error = -1; - goto cleanup; - } - - 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); - error = -1; - } - -cleanup: - git_buf_free(&temp_path); - git_buf_free(&old_path); - git_buf_free(&new_path); - git_buf_free(&normalized); - - return error; + return refdb->backend->reflog_rename(refdb->backend, old_name, new_name); } -int git_reflog_delete(git_reference *ref) +int git_reflog_delete(git_repository *repo, const char *name) { + git_refdb *refdb; int error; - git_buf path = GIT_BUF_INIT; - - error = retrieve_reflog_path(&path, ref); - if (!error && git_path_exists(path.ptr)) - error = p_unlink(path.ptr); - - git_buf_free(&path); + if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) + return -1; - return error; + return refdb->backend->reflog_delete(refdb->backend, name); } size_t git_reflog_entrycount(git_reflog *reflog) @@ -429,11 +111,6 @@ size_t git_reflog_entrycount(git_reflog *reflog) return reflog->entries.length; } -GIT_INLINE(size_t) reflog_inverse_index(size_t idx, size_t total) -{ - return (total - 1) - idx; -} - const git_reflog_entry * git_reflog_entry_byindex(git_reflog *reflog, size_t idx) { assert(reflog); @@ -474,50 +151,10 @@ int git_reflog_drop( size_t idx, int rewrite_previous_entry) { - size_t entrycount; - git_reflog_entry *entry, *previous; - - assert(reflog); - - entrycount = git_reflog_entrycount(reflog); - - entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); - - if (entry == NULL) { - giterr_set(GITERR_REFERENCE, "No reflog entry at index %"PRIuZ, idx); - return GIT_ENOTFOUND; - } - - reflog_entry_free(entry); - - if (git_vector_remove( - &reflog->entries, reflog_inverse_index(idx, entrycount)) < 0) - return -1; - - if (!rewrite_previous_entry) - return 0; - - /* No need to rewrite anything when removing the most recent entry */ - if (idx == 0) - return 0; - - /* Have the latest entry just been dropped? */ - if (entrycount == 1) - return 0; - - entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx - 1); - - /* If the oldest entry has just been removed... */ - if (idx == entrycount - 1) { - /* ...clear the oid_old member of the "new" oldest entry */ - if (git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO) < 0) - return -1; - - return 0; - } + git_refdb *db; - previous = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); - git_oid_cpy(&entry->oid_old, &previous->oid_cur); + assert(reflog && reflog->db); - return 0; + db = reflog->db; + return db->backend->reflog_drop(db->backend, reflog, idx, rewrite_previous_entry); } diff --git a/src/reflog.h b/src/reflog.h index 9444ebd10..2d31ae47d 100644 --- a/src/reflog.h +++ b/src/reflog.h @@ -27,9 +27,14 @@ struct git_reflog_entry { }; struct git_reflog { + git_refdb *db; char *ref_name; - git_repository *owner; git_vector entries; }; +GIT_INLINE(size_t) reflog_inverse_index(size_t idx, size_t total) +{ + return (total - 1) - idx; +} + #endif /* INCLUDE_reflog_h__ */ diff --git a/src/refs.c b/src/refs.c index c045ab9dc..abec356b5 100644 --- a/src/refs.c +++ b/src/refs.c @@ -467,7 +467,7 @@ int git_reference_rename( if (reference_has_log < 0) return reference_has_log; - if (reference_has_log && (error = git_reflog_rename(ref, new_name)) < 0) + if (reference_has_log && (error = git_reflog_rename(git_reference_owner(ref), git_reference_name(ref), new_name)) < 0) return error; return 0; diff --git a/src/revparse.c b/src/revparse.c index e470a954d..c120b466f 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -160,7 +160,7 @@ static int retrieve_previously_checked_out_branch_or_revision(git_object **out, if (git_reference_lookup(&ref, repo, GIT_HEAD_FILE) < 0) goto cleanup; - if (git_reflog_read(&reflog, ref) < 0) + if (git_reflog_read(&reflog, repo, GIT_HEAD_FILE) < 0) goto cleanup; numentries = git_reflog_entrycount(reflog); @@ -208,7 +208,7 @@ static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, size_t ide const git_reflog_entry *entry; bool search_by_pos = (identifier <= 100000000); - if (git_reflog_read(&reflog, ref) < 0) + if (git_reflog_read(&reflog, git_reference_owner(ref), git_reference_name(ref)) < 0) return -1; numentries = git_reflog_entrycount(reflog); diff --git a/src/stash.c b/src/stash.c index 7742eee19..ffdbd2e29 100644 --- a/src/stash.c +++ b/src/stash.c @@ -436,14 +436,16 @@ static int update_reflog( const git_signature *stasher, const char *message) { - git_reference *stash = NULL; + git_reference *stash; git_reflog *reflog = NULL; int error; if ((error = git_reference_create(&stash, repo, GIT_REFS_STASH_FILE, w_commit_oid, 1)) < 0) goto cleanup; - if ((error = git_reflog_read(&reflog, stash)) < 0) + git_reference_free(stash); + + if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE) < 0)) goto cleanup; if ((error = git_reflog_append(reflog, w_commit_oid, stasher, message)) < 0) @@ -453,7 +455,6 @@ static int update_reflog( goto cleanup; cleanup: - git_reference_free(stash); git_reflog_free(reflog); return error; } @@ -599,7 +600,7 @@ int git_stash_foreach( if (error < 0) goto cleanup; - if ((error = git_reflog_read(&reflog, stash)) < 0) + if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)) < 0) goto cleanup; max = git_reflog_entrycount(reflog); @@ -633,7 +634,7 @@ int git_stash_drop( if ((error = git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE)) < 0) return error; - if ((error = git_reflog_read(&reflog, stash)) < 0) + if ((error = git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)) < 0) goto cleanup; max = git_reflog_entrycount(reflog); diff --git a/tests-clar/refs/reflog/drop.c b/tests-clar/refs/reflog/drop.c index 21cc847bf..916bd9933 100644 --- a/tests-clar/refs/reflog/drop.c +++ b/tests-clar/refs/reflog/drop.c @@ -8,15 +8,10 @@ static size_t entrycount; void test_refs_reflog_drop__initialize(void) { - git_reference *ref; - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_git_pass(git_reference_lookup(&ref, g_repo, "HEAD")); - git_reflog_read(&g_reflog, ref); + git_reflog_read(&g_reflog, g_repo, "HEAD"); entrycount = git_reflog_entrycount(g_reflog); - - git_reference_free(ref); } void test_refs_reflog_drop__cleanup(void) @@ -106,19 +101,15 @@ void test_refs_reflog_drop__can_drop_all_the_entries(void) void test_refs_reflog_drop__can_persist_deletion_on_disk(void) { - git_reference *ref; - cl_assert(entrycount > 2); - cl_git_pass(git_reference_lookup(&ref, g_repo, g_reflog->ref_name)); cl_git_pass(git_reflog_drop(g_reflog, 0, 1)); cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); cl_git_pass(git_reflog_write(g_reflog)); git_reflog_free(g_reflog); - git_reflog_read(&g_reflog, ref); - git_reference_free(ref); + git_reflog_read(&g_reflog, g_repo, "HEAD"); cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); } diff --git a/tests-clar/refs/reflog/reflog.c b/tests-clar/refs/reflog/reflog.c index 095cabf04..327c85799 100644 --- a/tests-clar/refs/reflog/reflog.c +++ b/tests-clar/refs/reflog/reflog.c @@ -50,7 +50,7 @@ void test_refs_reflog_reflog__append_then_read(void) cl_git_pass(git_signature_now(&committer, "foo", "foo@bar")); - cl_git_pass(git_reflog_read(&reflog, ref)); + cl_git_pass(git_reflog_read(&reflog, g_repo, new_ref)); cl_git_fail(git_reflog_append(reflog, &oid, committer, "no inner\nnewline")); cl_git_pass(git_reflog_append(reflog, &oid, committer, NULL)); @@ -65,7 +65,7 @@ void test_refs_reflog_reflog__append_then_read(void) cl_git_pass(git_reference_lookup(&lookedup_ref, repo2, new_ref)); /* Read and parse the reflog for this branch */ - cl_git_pass(git_reflog_read(&reflog, lookedup_ref)); + cl_git_pass(git_reflog_read(&reflog, repo2, new_ref)); cl_assert_equal_i(2, (int)git_reflog_entrycount(reflog)); entry = git_reflog_entry_byindex(reflog, 1); @@ -133,21 +133,18 @@ void test_refs_reflog_reflog__reference_has_reflog(void) void test_refs_reflog_reflog__reading_the_reflog_from_a_reference_with_no_log_returns_an_empty_one(void) { - git_reference *subtrees; git_reflog *reflog; + const char *refname = "refs/heads/subtrees"; git_buf subtrees_log_path = GIT_BUF_INIT; - cl_git_pass(git_reference_lookup(&subtrees, g_repo, "refs/heads/subtrees")); - - git_buf_join_n(&subtrees_log_path, '/', 3, git_repository_path(g_repo), GIT_REFLOG_DIR, git_reference_name(subtrees)); + git_buf_join_n(&subtrees_log_path, '/', 3, git_repository_path(g_repo), GIT_REFLOG_DIR, refname); cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&subtrees_log_path))); - cl_git_pass(git_reflog_read(&reflog, subtrees)); + cl_git_pass(git_reflog_read(&reflog, g_repo, refname)); cl_assert_equal_i(0, (int)git_reflog_entrycount(reflog)); git_reflog_free(reflog); - git_reference_free(subtrees); git_buf_free(&subtrees_log_path); } @@ -158,7 +155,7 @@ void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void) git_reflog *reflog; cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master")); - cl_git_pass(git_reflog_read(&reflog, master)); + cl_git_pass(git_reflog_read(&reflog, g_repo, "refs/heads/master")); cl_git_pass(git_reflog_write(reflog)); @@ -175,12 +172,6 @@ void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void) void test_refs_reflog_reflog__renaming_with_an_invalid_name_returns_EINVALIDSPEC(void) { - git_reference *master; - - cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master")); - cl_assert_equal_i(GIT_EINVALIDSPEC, - git_reflog_rename(master, "refs/heads/Inv@{id")); - - git_reference_free(master); + git_reflog_rename(g_repo, "refs/heads/master", "refs/heads/Inv@{id")); } diff --git a/tests-clar/stash/drop.c b/tests-clar/stash/drop.c index 59413f01e..63ff0377c 100644 --- a/tests-clar/stash/drop.c +++ b/tests-clar/stash/drop.c @@ -102,7 +102,7 @@ void test_stash_drop__dropping_an_entry_rewrites_reflog_history(void) cl_git_pass(git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE)); - cl_git_pass(git_reflog_read(&reflog, stash)); + cl_git_pass(git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)); entry = git_reflog_entry_byindex(reflog, 1); git_oid_cpy(&oid, git_reflog_entry_id_old(entry)); @@ -112,7 +112,7 @@ void test_stash_drop__dropping_an_entry_rewrites_reflog_history(void) cl_git_pass(git_stash_drop(repo, 1)); - cl_git_pass(git_reflog_read(&reflog, stash)); + cl_git_pass(git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)); entry = git_reflog_entry_byindex(reflog, 0); cl_assert_equal_i(0, git_oid_cmp(&oid, git_reflog_entry_id_old(entry))); -- cgit v1.2.1 From d274deea23a2c2a70ee1695e8f917dbca50c76b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 20 Aug 2013 11:12:34 +0200 Subject: reflog: add a convenience append function Provide a function that reads a reflog, performs an append and writes back to the backend in one call. --- include/git2/reflog.h | 17 +++++++++ src/reflog.c | 19 ++++++++++ tests-clar/refs/reflog/reflog.c | 82 ++++++++++++++++++++++++++++------------- 3 files changed, 93 insertions(+), 25 deletions(-) diff --git a/include/git2/reflog.h b/include/git2/reflog.h index b31472c37..2d1b6eeaa 100644 --- a/include/git2/reflog.h +++ b/include/git2/reflog.h @@ -59,6 +59,23 @@ GIT_EXTERN(int) git_reflog_write(git_reflog *reflog); */ GIT_EXTERN(int) git_reflog_append(git_reflog *reflog, const git_oid *id, const git_signature *committer, const char *msg); +/** + * Add a new entry to the named reflog. + * + * This utility function loads the named reflog, appends to it and + * writes it back out to the backend. + * + * `msg` is optional and can be NULL. + * + * @param repo the repository to act on + * @param name the reflog's name + * @param id the OID the reference is now pointing to + * @param committer the signature of the committer + * @param msg the reflog message + * @return 0 or an error code + */ +GIT_EXTERN(int) git_reflog_append_to(git_repository *repo, const char *name, const git_oid *id, const git_signature *committer, const char *msg); + /** * Rename a reflog * diff --git a/src/reflog.c b/src/reflog.c index c10ae9fd4..923d5a32d 100644 --- a/src/reflog.c +++ b/src/reflog.c @@ -158,3 +158,22 @@ int git_reflog_drop( db = reflog->db; return db->backend->reflog_drop(db->backend, reflog, idx, rewrite_previous_entry); } + +int git_reflog_append_to(git_repository *repo, const char *name, const git_oid *id, + const git_signature *committer, const char *msg) +{ + int error; + git_reflog *reflog; + + if ((error = git_reflog_read(&reflog, repo, name)) < 0) + return error; + + if ((error = git_reflog_append(reflog, id, committer, msg)) < 0) + goto cleanup; + + error = git_reflog_write(reflog); + +cleanup: + git_reflog_free(reflog); + return error; +} diff --git a/tests-clar/refs/reflog/reflog.c b/tests-clar/refs/reflog/reflog.c index 327c85799..bcd224270 100644 --- a/tests-clar/refs/reflog/reflog.c +++ b/tests-clar/refs/reflog/reflog.c @@ -13,7 +13,7 @@ static git_repository *g_repo; // helpers -static void assert_signature(git_signature *expected, git_signature *actual) +static void assert_signature(const git_signature *expected, const git_signature *actual) { cl_assert(actual); cl_assert_equal_s(expected->name, actual->name); @@ -34,30 +34,13 @@ void test_refs_reflog_reflog__cleanup(void) cl_git_sandbox_cleanup(); } -void test_refs_reflog_reflog__append_then_read(void) +static void assert_appends(const git_signature *committer, const git_oid *oid) { - // write a reflog for a given reference and ensure it can be read back git_repository *repo2; - git_reference *ref, *lookedup_ref; - git_oid oid; - git_signature *committer; + git_reference *lookedup_ref; git_reflog *reflog; const git_reflog_entry *entry; - /* Create a new branch pointing at the HEAD */ - git_oid_fromstr(&oid, current_master_tip); - cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &oid, 0)); - - cl_git_pass(git_signature_now(&committer, "foo", "foo@bar")); - - cl_git_pass(git_reflog_read(&reflog, g_repo, new_ref)); - - cl_git_fail(git_reflog_append(reflog, &oid, committer, "no inner\nnewline")); - cl_git_pass(git_reflog_append(reflog, &oid, committer, NULL)); - cl_git_pass(git_reflog_append(reflog, &oid, committer, commit_msg "\n")); - cl_git_pass(git_reflog_write(reflog)); - git_reflog_free(reflog); - /* Reopen a new instance of the repository */ cl_git_pass(git_repository_open(&repo2, "testrepo.git")); @@ -71,23 +54,72 @@ void test_refs_reflog_reflog__append_then_read(void) entry = git_reflog_entry_byindex(reflog, 1); assert_signature(committer, entry->committer); cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) == 0); - cl_assert(git_oid_cmp(&oid, &entry->oid_cur) == 0); + cl_assert(git_oid_cmp(oid, &entry->oid_cur) == 0); cl_assert(entry->msg == NULL); entry = git_reflog_entry_byindex(reflog, 0); assert_signature(committer, entry->committer); - cl_assert(git_oid_cmp(&oid, &entry->oid_old) == 0); - cl_assert(git_oid_cmp(&oid, &entry->oid_cur) == 0); + cl_assert(git_oid_cmp(oid, &entry->oid_old) == 0); + cl_assert(git_oid_cmp(oid, &entry->oid_cur) == 0); cl_assert_equal_s(commit_msg, entry->msg); - git_signature_free(committer); git_reflog_free(reflog); git_repository_free(repo2); - git_reference_free(ref); git_reference_free(lookedup_ref); } +void test_refs_reflog_reflog__append_then_read(void) +{ + /* write a reflog for a given reference and ensure it can be read back */ + git_reference *ref; + git_oid oid; + git_signature *committer; + git_reflog *reflog; + + /* Create a new branch pointing at the HEAD */ + git_oid_fromstr(&oid, current_master_tip); + cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &oid, 0)); + git_reference_free(ref); + + cl_git_pass(git_signature_now(&committer, "foo", "foo@bar")); + + cl_git_pass(git_reflog_read(&reflog, g_repo, new_ref)); + + cl_git_fail(git_reflog_append(reflog, &oid, committer, "no inner\nnewline")); + cl_git_pass(git_reflog_append(reflog, &oid, committer, NULL)); + cl_git_pass(git_reflog_append(reflog, &oid, committer, commit_msg "\n")); + cl_git_pass(git_reflog_write(reflog)); + git_reflog_free(reflog); + + assert_appends(committer, &oid); + + git_signature_free(committer); +} + +void test_refs_reflog_reflog__append_to_then_read(void) +{ + /* write a reflog for a given reference and ensure it can be read back */ + git_reference *ref; + git_oid oid; + git_signature *committer; + + /* Create a new branch pointing at the HEAD */ + git_oid_fromstr(&oid, current_master_tip); + cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &oid, 0)); + git_reference_free(ref); + + cl_git_pass(git_signature_now(&committer, "foo", "foo@bar")); + + cl_git_fail(git_reflog_append_to(g_repo, new_ref, &oid, committer, "no inner\nnewline")); + cl_git_pass(git_reflog_append_to(g_repo, new_ref, &oid, committer, NULL)); + cl_git_pass(git_reflog_append_to(g_repo, new_ref, &oid, committer, commit_msg "\n")); + + assert_appends(committer, &oid); + + git_signature_free(committer); +} + void test_refs_reflog_reflog__renaming_the_reference_moves_the_reflog(void) { git_reference *master, *new_master; -- cgit v1.2.1 From 0174794a955dbec1e2d9ecf581833fc23c7e844c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 21 Aug 2013 05:12:49 +0200 Subject: reflog: bring _append and _drop back to the frontend These functions act purely on the reflog data structure. --- include/git2/sys/refdb_backend.h | 12 ----- src/refdb_fs.c | 103 --------------------------------------- src/reflog.c | 100 +++++++++++++++++++++++++++++++------ 3 files changed, 86 insertions(+), 129 deletions(-) diff --git a/include/git2/sys/refdb_backend.h b/include/git2/sys/refdb_backend.h index 93c4a521a..9cf5073fb 100644 --- a/include/git2/sys/refdb_backend.h +++ b/include/git2/sys/refdb_backend.h @@ -130,23 +130,11 @@ struct git_refdb_backend { */ int (*reflog_write)(git_refdb_backend *backend, git_reflog *reflog); - /** - * Append an entry to the given reflog - */ - int (*reflog_append)(git_refdb_backend *backend, git_reflog *reflog, - const git_oid *new_oid, const git_signature *committer, - const char *msg); - /** * Rename a reflog */ int (*reflog_rename)(git_refdb_backend *_backend, const char *old_name, const char *new_name); - /** - * Drop an entry from the reflog - */ - int (*reflog_drop)(git_refdb_backend *_backend, git_reflog *reflog, - size_t idx, int rewrite_previous_entry); /** * Remove a reflog. */ diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 4d695721d..f52a66a40 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -1308,56 +1308,6 @@ success: return error; } -static int refdb_reflog_fs__append(git_refdb_backend *_backend, git_reflog *reflog, - const git_oid *new_oid, const git_signature *committer, const char *msg) -{ - git_reflog_entry *entry; - const git_reflog_entry *previous; - const char *newline; - - assert(_backend && reflog && new_oid && committer); - - entry = git__calloc(1, sizeof(git_reflog_entry)); - GITERR_CHECK_ALLOC(entry); - - if ((entry->committer = git_signature_dup(committer)) == NULL) - goto cleanup; - - if (msg != NULL) { - if ((entry->msg = git__strdup(msg)) == NULL) - goto cleanup; - - newline = strchr(msg, '\n'); - - if (newline) { - if (newline[1] != '\0') { - giterr_set(GITERR_INVALID, "Reflog message cannot contain newline"); - goto cleanup; - } - - entry->msg[newline - msg] = '\0'; - } - } - - previous = git_reflog_entry_byindex(reflog, 0); - - if (previous == NULL) - git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO); - else - git_oid_cpy(&entry->oid_old, &previous->oid_cur); - - git_oid_cpy(&entry->oid_cur, new_oid); - - if (git_vector_insert(&reflog->entries, entry) < 0) - goto cleanup; - - return 0; - -cleanup: - git_reflog_entry__free(entry); - return -1; -} - static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_name, const char *new_name) { int error = 0, fd; @@ -1434,57 +1384,6 @@ cleanup: return error; } -static int refdb_reflog_fs__drop(git_refdb_backend *_backend, git_reflog *reflog, - size_t idx, int rewrite_previous_entry) -{ - size_t entrycount; - git_reflog_entry *entry, *previous; - - assert(_backend && reflog); - - entrycount = git_reflog_entrycount(reflog); - - entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); - - if (entry == NULL) { - giterr_set(GITERR_REFERENCE, "No reflog entry at index "PRIuZ, idx); - return GIT_ENOTFOUND; - } - - git_reflog_entry__free(entry); - - if (git_vector_remove( - &reflog->entries, reflog_inverse_index(idx, entrycount)) < 0) - return -1; - - if (!rewrite_previous_entry) - return 0; - - /* No need to rewrite anything when removing the most recent entry */ - if (idx == 0) - return 0; - - /* Have the latest entry just been dropped? */ - if (entrycount == 1) - return 0; - - entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx - 1); - - /* If the oldest entry has just been removed... */ - if (idx == entrycount - 1) { - /* ...clear the oid_old member of the "new" oldest entry */ - if (git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO) < 0) - return -1; - - return 0; - } - - previous = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); - git_oid_cpy(&entry->oid_old, &previous->oid_cur); - - return 0; -} - static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name) { int error; @@ -1544,9 +1443,7 @@ int git_refdb_backend_fs( backend->parent.free = &refdb_fs_backend__free; backend->parent.reflog_read = &refdb_reflog_fs__read; backend->parent.reflog_write = &refdb_reflog_fs__write; - backend->parent.reflog_append = &refdb_reflog_fs__append; backend->parent.reflog_rename = &refdb_reflog_fs__rename; - backend->parent.reflog_drop = &refdb_reflog_fs__drop; backend->parent.reflog_delete = &refdb_reflog_fs__delete; *backend_out = (git_refdb_backend *)backend; diff --git a/src/reflog.c b/src/reflog.c index 923d5a32d..cebb87d86 100644 --- a/src/reflog.c +++ b/src/reflog.c @@ -71,16 +71,53 @@ int git_reflog_write(git_reflog *reflog) return db->backend->reflog_write(db->backend, reflog); } -int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, - const git_signature *committer, const char *msg) +int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_signature *committer, const char *msg) { - git_refdb *db; + git_reflog_entry *entry; + const git_reflog_entry *previous; + const char *newline; - assert(reflog && reflog->db && new_oid && committer); + assert(reflog && new_oid && committer); - db = reflog->db; + entry = git__calloc(1, sizeof(git_reflog_entry)); + GITERR_CHECK_ALLOC(entry); + + if ((entry->committer = git_signature_dup(committer)) == NULL) + goto cleanup; - return db->backend->reflog_append(db->backend, reflog, new_oid, committer, msg); + if (msg != NULL) { + if ((entry->msg = git__strdup(msg)) == NULL) + goto cleanup; + + newline = strchr(msg, '\n'); + + if (newline) { + if (newline[1] != '\0') { + giterr_set(GITERR_INVALID, "Reflog message cannot contain newline"); + goto cleanup; + } + + entry->msg[newline - msg] = '\0'; + } + } + + previous = git_reflog_entry_byindex(reflog, 0); + + if (previous == NULL) + git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO); + else + git_oid_cpy(&entry->oid_old, &previous->oid_cur); + + git_oid_cpy(&entry->oid_cur, new_oid); + + if (git_vector_insert(&reflog->entries, entry) < 0) + goto cleanup; + + return 0; + +cleanup: + git_reflog_entry__free(entry); + return -1; } int git_reflog_rename(git_repository *repo, const char *old_name, const char *new_name) @@ -146,17 +183,52 @@ const char * git_reflog_entry_message(const git_reflog_entry *entry) return entry->msg; } -int git_reflog_drop( - git_reflog *reflog, - size_t idx, - int rewrite_previous_entry) +int git_reflog_drop(git_reflog *reflog, size_t idx, int rewrite_previous_entry) { - git_refdb *db; + size_t entrycount; + git_reflog_entry *entry, *previous; - assert(reflog && reflog->db); + entrycount = git_reflog_entrycount(reflog); - db = reflog->db; - return db->backend->reflog_drop(db->backend, reflog, idx, 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); + return GIT_ENOTFOUND; + } + + git_reflog_entry__free(entry); + + if (git_vector_remove( + &reflog->entries, reflog_inverse_index(idx, entrycount)) < 0) + return -1; + + if (!rewrite_previous_entry) + return 0; + + /* No need to rewrite anything when removing the most recent entry */ + if (idx == 0) + return 0; + + /* Have the latest entry just been dropped? */ + if (entrycount == 1) + return 0; + + entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx - 1); + + /* If the oldest entry has just been removed... */ + if (idx == entrycount - 1) { + /* ...clear the oid_old member of the "new" oldest entry */ + if (git_oid_fromstr(&entry->oid_old, GIT_OID_HEX_ZERO) < 0) + return -1; + + return 0; + } + + previous = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); + git_oid_cpy(&entry->oid_old, &previous->oid_cur); + + return 0; } int git_reflog_append_to(git_repository *repo, const char *name, const git_oid *id, -- cgit v1.2.1 From 0e0cf78773bea0d06298ba3bf981a3be839041df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 2 Oct 2013 14:04:44 +0200 Subject: clone: put the callbacks struct directly in the clone options There's no need for this to be a pointer to somewhere else. --- examples/network/clone.c | 8 +++----- include/git2/clone.h | 4 ++-- include/git2/remote.h | 2 +- src/clone.c | 3 +-- src/remote.c | 4 ++-- tests-clar/clone/empty.c | 2 ++ tests-clar/clone/nonetwork.c | 2 ++ tests-clar/online/clone.c | 34 +++++++++++----------------------- tests-clar/online/fetchhead.c | 2 ++ 9 files changed, 26 insertions(+), 35 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index f553c4077..db35bd7db 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -57,7 +57,6 @@ int do_clone(git_repository *repo, int argc, char **argv) git_repository *cloned_repo = NULL; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; const char *url = argv[1]; const char *path = argv[2]; int error; @@ -75,10 +74,9 @@ int do_clone(git_repository *repo, int argc, char **argv) checkout_opts.progress_cb = checkout_progress; checkout_opts.progress_payload = &pd; clone_opts.checkout_opts = checkout_opts; - callbacks.transfer_progress = &fetch_progress; - callbacks.credentials = cred_acquire_cb; - callbacks.payload = &pd; - clone_opts.remote_callbacks = &callbacks; + clone_opts.remote_callbacks.transfer_progress = &fetch_progress; + clone_opts.remote_callbacks.credentials = cred_acquire_cb; + clone_opts.remote_callbacks.payload = &pd; // Do the clone error = git_clone(&cloned_repo, url, path, &clone_opts); diff --git a/include/git2/clone.h b/include/git2/clone.h index a341a413c..331cf92e7 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -49,7 +49,7 @@ typedef struct git_clone_options { unsigned int version; git_checkout_opts checkout_opts; - git_remote_callbacks *remote_callbacks; + git_remote_callbacks remote_callbacks; int bare; int ignore_cert_errors; @@ -58,7 +58,7 @@ typedef struct git_clone_options { } git_clone_options; #define GIT_CLONE_OPTIONS_VERSION 1 -#define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTS_VERSION, GIT_CHECKOUT_SAFE_CREATE}} +#define GIT_CLONE_OPTIONS_INIT {GIT_CLONE_OPTIONS_VERSION, {GIT_CHECKOUT_OPTS_VERSION, GIT_CHECKOUT_SAFE_CREATE}, GIT_REMOTE_CALLBACKS_INIT} /** * Clone a remote repository. diff --git a/include/git2/remote.h b/include/git2/remote.h index 8145de180..9858634cc 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -457,7 +457,7 @@ struct git_remote_callbacks { * @param callbacks a pointer to the user's callback settings * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks); +GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks); /** * Get the statistics structure that is filled in by the fetch operation. diff --git a/src/clone.c b/src/clone.c index 1af6e393f..f3e365c07 100644 --- a/src/clone.c +++ b/src/clone.c @@ -315,8 +315,7 @@ static int create_and_configure_origin( if (options->ignore_cert_errors) git_remote_check_cert(origin, 0); - if (options->remote_callbacks && - (error = git_remote_set_callbacks(origin, options->remote_callbacks)) < 0) + if ((error = git_remote_set_callbacks(origin, &options->remote_callbacks)) < 0) goto on_error; if ((error = git_remote_save(origin)) < 0) diff --git a/src/remote.c b/src/remote.c index ace886502..ccedf2386 100644 --- a/src/remote.c +++ b/src/remote.c @@ -1153,7 +1153,7 @@ void git_remote_check_cert(git_remote *remote, int check) remote->check_cert = check; } -int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks) +int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks) { assert(remote && callbacks); @@ -1162,7 +1162,7 @@ int git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks memcpy(&remote->callbacks, callbacks, sizeof(git_remote_callbacks)); if (remote->transport && remote->transport->set_callbacks) - remote->transport->set_callbacks(remote->transport, + return remote->transport->set_callbacks(remote->transport, remote->callbacks.progress, NULL, remote->callbacks.payload); diff --git a/tests-clar/clone/empty.c b/tests-clar/clone/empty.c index d9dc24fde..6d19244cc 100644 --- a/tests-clar/clone/empty.c +++ b/tests-clar/clone/empty.c @@ -10,12 +10,14 @@ static git_repository *g_repo_cloned; void test_clone_empty__initialize(void) { git_repository *sandbox = cl_git_sandbox_init("empty_bare.git"); + git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; cl_git_remove_placeholders(git_repository_path(sandbox), "dummy-marker.txt"); g_repo = NULL; memset(&g_options, 0, sizeof(git_clone_options)); g_options.version = GIT_CLONE_OPTIONS_VERSION; + g_options.remote_callbacks = dummy_callbacks; } void test_clone_empty__cleanup(void) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 9b666b3f7..4bcb5be1e 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -15,6 +15,7 @@ static git_remote* g_remote; void test_clone_nonetwork__initialize(void) { git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT; + git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; g_repo = NULL; @@ -22,6 +23,7 @@ void test_clone_nonetwork__initialize(void) g_options.version = GIT_CLONE_OPTIONS_VERSION; g_options.checkout_opts = dummy_opts; g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + g_options.remote_callbacks = dummy_callbacks; } void test_clone_nonetwork__cleanup(void) diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index 9a64ba166..4a6ade52d 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -18,6 +18,7 @@ static git_clone_options g_options; void test_online_clone__initialize(void) { git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT; + git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; g_repo = NULL; @@ -25,6 +26,7 @@ void test_online_clone__initialize(void) g_options.version = GIT_CLONE_OPTIONS_VERSION; g_options.checkout_opts = dummy_opts; g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + g_options.remote_callbacks = dummy_callbacks; } void test_online_clone__cleanup(void) @@ -100,15 +102,11 @@ void test_online_clone__can_checkout_a_cloned_repo(void) bool checkout_progress_cb_was_called = false, fetch_progress_cb_was_called = false; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; g_options.checkout_opts.progress_cb = &checkout_progress; g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called; - - callbacks.transfer_progress = &fetch_progress; - callbacks.payload = &fetch_progress_cb_was_called; - g_options.remote_callbacks = &callbacks; + g_options.remote_callbacks.transfer_progress = &fetch_progress; + g_options.remote_callbacks.payload = &fetch_progress_cb_was_called; cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); @@ -175,12 +173,10 @@ static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void test_online_clone__custom_remote_callbacks(void) { - git_remote_callbacks remote_callbacks = GIT_REMOTE_CALLBACKS_INIT; int callcount = 0; - g_options.remote_callbacks = &remote_callbacks; - remote_callbacks.update_tips = update_tips; - remote_callbacks.payload = &callcount; + g_options.remote_callbacks.update_tips = update_tips; + g_options.remote_callbacks.payload = &callcount; cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); cl_assert(callcount > 0); @@ -194,13 +190,11 @@ void test_online_clone__credentials(void) cl_getenv("GITTEST_REMOTE_USER"), cl_getenv("GITTEST_REMOTE_PASS") }; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; if (!remote_url) return; - callbacks.credentials = git_cred_userpass; - callbacks.payload = &user_pass; - g_options.remote_callbacks = &callbacks; + g_options.remote_callbacks.credentials = git_cred_userpass; + g_options.remote_callbacks.payload = &user_pass; cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options)); git_repository_free(g_repo); g_repo = NULL; @@ -213,11 +207,8 @@ void test_online_clone__bitbucket_style(void) "libgit2", "libgit2" }; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - - callbacks.credentials = git_cred_userpass; - callbacks.payload = &user_pass; - g_options.remote_callbacks = &callbacks; + g_options.remote_callbacks.credentials = git_cred_userpass; + g_options.remote_callbacks.payload = &user_pass; cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options)); git_repository_free(g_repo); g_repo = NULL; @@ -247,10 +238,7 @@ static int cancel_at_half(const git_transfer_progress *stats, void *payload) void test_online_clone__can_cancel(void) { - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - - callbacks.transfer_progress = cancel_at_half; - g_options.remote_callbacks = &callbacks; + g_options.remote_callbacks.transfer_progress = cancel_at_half; cl_git_fail_with(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), GIT_EUSER); } diff --git a/tests-clar/online/fetchhead.c b/tests-clar/online/fetchhead.c index 5d9eb1318..57b183f88 100644 --- a/tests-clar/online/fetchhead.c +++ b/tests-clar/online/fetchhead.c @@ -12,10 +12,12 @@ static git_clone_options g_options; void test_online_fetchhead__initialize(void) { + git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; g_repo = NULL; memset(&g_options, 0, sizeof(git_clone_options)); g_options.version = GIT_CLONE_OPTIONS_VERSION; + g_options.remote_callbacks = dummy_callbacks; } void test_online_fetchhead__cleanup(void) -- cgit v1.2.1 From 5b1882254551cc9031d919c2f31c05153a665762 Mon Sep 17 00:00:00 2001 From: Jameson Miller Date: Wed, 2 Oct 2013 13:45:32 -0400 Subject: Support cancellation in push operation This commit adds cancellation for the push operation. This work consists of: 1) Support cancellation during push operation - During object counting phase - During network transfer phase - Propagate GIT_EUSER error code out to caller 2) Improve cancellation support during fetch - Handle cancellation request during network transfer phase - Clear error string when cancelled during indexing 3) Fix error handling in git_smart__download_pack Cancellation during push is still only handled in the pack building and network transfer stages of push (and not during packbuilding). --- include/git2/pack.h | 2 +- include/git2/push.h | 2 +- src/indexer.c | 1 + src/pack-objects.c | 43 ++++++++++++---------- src/push.c | 4 +- src/transports/smart.c | 9 ++++- src/transports/smart.h | 2 +- src/transports/smart_protocol.c | 81 +++++++++++++++++++++++------------------ tests-clar/online/push.c | 6 ++- 9 files changed, 85 insertions(+), 65 deletions(-) diff --git a/include/git2/pack.h b/include/git2/pack.h index 7ebdd5cf3..748817666 100644 --- a/include/git2/pack.h +++ b/include/git2/pack.h @@ -158,7 +158,7 @@ GIT_EXTERN(uint32_t) git_packbuilder_object_count(git_packbuilder *pb); GIT_EXTERN(uint32_t) git_packbuilder_written(git_packbuilder *pb); /** Packbuilder progress notification function */ -typedef void (*git_packbuilder_progress)( +typedef int (*git_packbuilder_progress)( int stage, unsigned int current, unsigned int total, diff --git a/include/git2/push.h b/include/git2/push.h index ecfd862d4..77ef74039 100644 --- a/include/git2/push.h +++ b/include/git2/push.h @@ -40,7 +40,7 @@ typedef struct { #define GIT_PUSH_OPTIONS_INIT { GIT_PUSH_OPTIONS_VERSION } /** Push network progress notification function */ -typedef void (*git_push_transfer_progress)( +typedef int (*git_push_transfer_progress)( unsigned int current, unsigned int total, size_t bytes, diff --git a/src/indexer.c b/src/indexer.c index 3b160df5d..4ce69fc8d 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -556,6 +556,7 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz stats->received_objects++; if (do_progress_callback(idx, stats) != 0) { + giterr_clear(); error = GIT_EUSER; goto on_error; } diff --git a/src/pack-objects.c b/src/pack-objects.c index 2a2f36223..821f292b9 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -216,15 +216,19 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, assert(ret != 0); kh_value(pb->object_ix, pos) = po; + pb->done = false; + if (pb->progress_cb) { double current_time = git__timer(); if ((current_time - pb->last_progress_report_time) >= MIN_PROGRESS_UPDATE_INTERVAL) { pb->last_progress_report_time = current_time; - pb->progress_cb(GIT_PACKBUILDER_ADDING_OBJECTS, pb->nr_objects, 0, pb->progress_cb_payload); + if (pb->progress_cb(GIT_PACKBUILDER_ADDING_OBJECTS, pb->nr_objects, 0, pb->progress_cb_payload)) { + giterr_clear(); + return GIT_EUSER; + } } } - pb->done = false; return 0; } @@ -591,49 +595,50 @@ static int write_pack(git_packbuilder *pb, enum write_one_status status; struct git_pack_header ph; unsigned int i = 0; + int error = 0; write_order = compute_write_order(pb); - if (write_order == NULL) - goto on_error; + if (write_order == NULL) { + error = -1; + goto done; + } /* Write pack header */ ph.hdr_signature = htonl(PACK_SIGNATURE); ph.hdr_version = htonl(PACK_VERSION); ph.hdr_entries = htonl(pb->nr_objects); - if (cb(&ph, sizeof(ph), data) < 0) - goto on_error; + if ((error = cb(&ph, sizeof(ph), data)) < 0) + goto done; - if (git_hash_update(&pb->ctx, &ph, sizeof(ph)) < 0) - goto on_error; + if ((error = git_hash_update(&pb->ctx, &ph, sizeof(ph))) < 0) + goto done; pb->nr_remaining = pb->nr_objects; do { pb->nr_written = 0; for ( ; i < pb->nr_objects; ++i) { po = write_order[i]; - if (write_one(&buf, pb, po, &status) < 0) - goto on_error; - if (cb(buf.ptr, buf.size, data) < 0) - goto on_error; + if ((error = write_one(&buf, pb, po, &status)) < 0) + goto done; + if ((error = cb(buf.ptr, buf.size, data)) < 0) + goto done; git_buf_clear(&buf); } pb->nr_remaining -= pb->nr_written; } while (pb->nr_remaining && i < pb->nr_objects); - git__free(write_order); - git_buf_free(&buf); - if (git_hash_final(&pb->pack_oid, &pb->ctx) < 0) - goto on_error; + if ((error = git_hash_final(&pb->pack_oid, &pb->ctx)) < 0) + goto done; - return cb(pb->pack_oid.id, GIT_OID_RAWSZ, data); + error = cb(pb->pack_oid.id, GIT_OID_RAWSZ, data); -on_error: +done: git__free(write_order); git_buf_free(&buf); - return -1; + return error; } static int write_pack_buf(void *buf, size_t size, void *data) diff --git a/src/push.c b/src/push.c index 698079253..a799db8d0 100644 --- a/src/push.c +++ b/src/push.c @@ -582,7 +582,7 @@ static int calculate_work(git_push *push) static int do_push(git_push *push) { - int error; + int error = 0; git_transport *transport = push->remote->transport; if (!transport->push) { @@ -611,8 +611,6 @@ static int do_push(git_push *push) (error = transport->push(transport, push)) < 0) goto on_error; - error = 0; - on_error: git_packbuilder_free(push->pb); return error; diff --git a/src/transports/smart.c b/src/transports/smart.c index 416eb221f..a681d5f40 100644 --- a/src/transports/smart.c +++ b/src/transports/smart.c @@ -23,8 +23,13 @@ static int git_smart__recv_cb(gitno_buffer *buf) buf->offset += bytes_read; - if (t->packetsize_cb) - t->packetsize_cb(bytes_read, t->packetsize_payload); + if (t->packetsize_cb && !t->cancelled.val) + if (t->packetsize_cb(bytes_read, t->packetsize_payload)) { + git_atomic_set(&t->cancelled, 1); + + giterr_clear(); + return GIT_EUSER; + } return (int)(buf->offset - old_len); } diff --git a/src/transports/smart.h b/src/transports/smart.h index c52401a3c..3519477da 100644 --- a/src/transports/smart.h +++ b/src/transports/smart.h @@ -119,7 +119,7 @@ typedef struct transport_smart_caps { report_status:1; } transport_smart_caps; -typedef void (*packetsize_cb)(size_t received, void *payload); +typedef int (*packetsize_cb)(size_t received, void *payload); typedef struct { git_transport parent; diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 156b69e1f..87e807ea3 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -425,7 +425,7 @@ struct network_packetsize_payload size_t last_fired_bytes; }; -static void network_packetsize(size_t received, void *payload) +static int network_packetsize(size_t received, void *payload) { struct network_packetsize_payload *npp = (struct network_packetsize_payload*)payload; @@ -435,8 +435,12 @@ static void network_packetsize(size_t received, void *payload) /* Fire notification if the threshold is reached */ if ((npp->stats->received_bytes - npp->last_fired_bytes) > NETWORK_XFER_THRESHOLD) { npp->last_fired_bytes = npp->stats->received_bytes; - npp->callback(npp->stats, npp->payload); + + if(npp->callback(npp->stats, npp->payload)) + return GIT_EUSER; } + + return 0; } int git_smart__download_pack( @@ -450,7 +454,7 @@ int git_smart__download_pack( gitno_buffer *buf = &t->buffer; git_odb *odb; struct git_odb_writepack *writepack = NULL; - int error = -1; + int error = 0; struct network_packetsize_payload npp = {0}; memset(stats, 0, sizeof(git_transfer_progress)); @@ -463,13 +467,14 @@ int git_smart__download_pack( t->packetsize_payload = &npp; /* We might have something in the buffer already from negotiate_fetch */ - if (t->buffer.offset > 0) - t->packetsize_cb(t->buffer.offset, t->packetsize_payload); + if (t->buffer.offset > 0 && !t->cancelled.val) + if(t->packetsize_cb(t->buffer.offset, t->packetsize_payload)) + git_atomic_set(&t->cancelled, 1); } if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 || ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) < 0)) - goto on_error; + goto done; /* * If the remote doesn't support the side-band, we can feed @@ -477,23 +482,29 @@ int git_smart__download_pack( * check which one belongs there. */ if (!t->caps.side_band && !t->caps.side_band_64k) { - if (no_sideband(t, writepack, buf, stats) < 0) - goto on_error; - - goto on_success; + error = no_sideband(t, writepack, buf, stats); + goto done; } do { git_pkt *pkt; + /* Check cancellation before network call */ if (t->cancelled.val) { giterr_set(GITERR_NET, "The fetch was cancelled by the user"); error = GIT_EUSER; - goto on_error; + goto done; } - if (recv_pkt(&pkt, buf) < 0) - goto on_error; + if ((error = recv_pkt(&pkt, buf)) < 0) + goto done; + + /* Check cancellation after network call */ + if (t->cancelled.val) { + giterr_set(GITERR_NET, "The fetch was cancelled by the user"); + error = GIT_EUSER; + goto done; + } if (pkt->type == GIT_PKT_PROGRESS) { if (t->progress_cb) { @@ -507,7 +518,7 @@ int git_smart__download_pack( git__free(pkt); if (error < 0) - goto on_error; + goto done; } else if (pkt->type == GIT_PKT_FLUSH) { /* A flush indicates the end of the packfile */ git__free(pkt); @@ -515,13 +526,10 @@ int git_smart__download_pack( } } while (1); - if (writepack->commit(writepack, stats) < 0) - goto on_error; - -on_success: - error = 0; + if ((error = writepack->commit(writepack, stats)) < 0) + goto done; -on_error: +done: if (writepack) writepack->free(writepack); @@ -828,7 +836,10 @@ static int stream_thunk(void *buf, size_t size, void *data) if ((current_time - payload->last_progress_report_time) >= MIN_PROGRESS_UPDATE_INTERVAL) { payload->last_progress_report_time = current_time; - payload->cb(payload->pb->nr_written, payload->pb->nr_objects, payload->last_bytes, payload->cb_payload); + if(payload->cb(payload->pb->nr_written, payload->pb->nr_objects, payload->last_bytes, payload->cb_payload)) { + giterr_clear(); + error = GIT_EUSER; + } } } @@ -840,7 +851,7 @@ int git_smart__push(git_transport *transport, git_push *push) transport_smart *t = (transport_smart *)transport; struct push_packbuilder_payload packbuilder_payload = {0}; git_buf pktline = GIT_BUF_INIT; - int error = -1, need_pack = 0; + int error = 0, need_pack = 0; push_spec *spec; unsigned int i; @@ -882,20 +893,21 @@ int git_smart__push(git_transport *transport, git_push *push) } } - if (git_smart__get_push_stream(t, &packbuilder_payload.stream) < 0 || - gen_pktline(&pktline, push) < 0 || - packbuilder_payload.stream->write(packbuilder_payload.stream, git_buf_cstr(&pktline), git_buf_len(&pktline)) < 0) - goto on_error; + if ((error = git_smart__get_push_stream(t, &packbuilder_payload.stream)) < 0 || + (error = gen_pktline(&pktline, push)) < 0 || + (error = packbuilder_payload.stream->write(packbuilder_payload.stream, git_buf_cstr(&pktline), git_buf_len(&pktline))) < 0) + goto done; - if (need_pack && git_packbuilder_foreach(push->pb, &stream_thunk, &packbuilder_payload) < 0) - goto on_error; + if (need_pack && + (error = git_packbuilder_foreach(push->pb, &stream_thunk, &packbuilder_payload)) < 0) + goto done; /* If we sent nothing or the server doesn't support report-status, then * we consider the pack to have been unpacked successfully */ if (!push->specs.length || !push->report_status) push->unpack_ok = 1; - else if (parse_report(&t->buffer, push) < 0) - goto on_error; + else if ((error = parse_report(&t->buffer, push)) < 0) + goto done; /* If progress is being reported write the final report */ if (push->transfer_progress_cb) { @@ -903,13 +915,10 @@ int git_smart__push(git_transport *transport, git_push *push) } if (push->status.length && - update_refs_from_report(&t->refs, &push->specs, &push->status) < 0) - goto on_error; + (error = update_refs_from_report(&t->refs, &push->specs, &push->status)) < 0) + goto done; - error = 0; - -on_error: +done: git_buf_free(&pktline); - return error; } diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 05cef56e7..dabeb2c87 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -349,16 +349,18 @@ void test_online_push__cleanup(void) cl_git_sandbox_cleanup(); } -static void push_pack_progress_cb(int stage, unsigned int current, unsigned int total, void* payload) +static int push_pack_progress_cb(int stage, unsigned int current, unsigned int total, void* payload) { int *was_called = (int *) payload; *was_called = 1; + return 0; } -static void push_transfer_progress_cb(unsigned int current, unsigned int total, size_t bytes, void* payload) +static int push_transfer_progress_cb(unsigned int current, unsigned int total, size_t bytes, void* payload) { int *was_called = (int *) payload; *was_called = 1; + return 0; } /** -- cgit v1.2.1 From 83db7e09e2e9e81668704c21be26c917dea18fbd Mon Sep 17 00:00:00 2001 From: Jameson Miller Date: Wed, 2 Oct 2013 15:10:39 -0400 Subject: Fix broken online push tests --- tests-clar/online/push.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index dabeb2c87..cef39595c 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -20,7 +20,6 @@ static char *_remote_pass; static int cred_acquire_cb(git_cred **, const char *, const char *, unsigned int, void *); static git_remote *_remote; -static bool _cred_acquire_called; static record_callbacks_data _record_cbs_data = {{ 0 }}; static git_remote_callbacks _record_cbs = RECORD_CALLBACKS_INIT(&_record_cbs_data); @@ -47,8 +46,6 @@ static int cred_acquire_cb( GIT_UNUSED(url); GIT_UNUSED(user_from_url); - *((bool*)payload) = true; - if (GIT_CREDTYPE_SSH_PUBLICKEY & allowed_types) return git_cred_ssh_keyfile_passphrase_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase); @@ -251,7 +248,6 @@ void test_online_push__initialize(void) git_vector delete_specs = GIT_VECTOR_INIT; size_t i; char *curr_del_spec; - _cred_acquire_called = false; _repo = cl_git_sandbox_init("push_src"); -- cgit v1.2.1 From 41a6de289fecbec426d2d977c4d02da5456701ac Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 2 Oct 2013 14:45:57 -0700 Subject: HTTP: handle "relative" redirects --- src/netops.c | 10 ++++++++++ tests-clar/network/urlparse.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/netops.c b/src/netops.c index 3257e7749..7a61ef820 100644 --- a/src/netops.c +++ b/src/netops.c @@ -609,6 +609,9 @@ int gitno_connection_data_from_url( data->use_ssl = true; } + if (url[0] == '/') + default_port = data->use_ssl ? "443" : "80"; + if (!default_port) { giterr_set(GITERR_NET, "Unrecognized URL prefix"); goto cleanup; @@ -618,6 +621,13 @@ int gitno_connection_data_from_url( &data->host, &data->port, &data->user, &data->pass, url, default_port); + if (url[0] == '/') { + /* Relative redirect; reuse original host name and port */ + git__free(data->host); + data->host = original_host; + original_host = NULL; + } + if (!error) { const char *path = strchr(url, '/'); size_t pathlen = strlen(path); diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c index 8892781ad..274d7e900 100644 --- a/tests-clar/network/urlparse.c +++ b/tests-clar/network/urlparse.c @@ -125,6 +125,34 @@ void test_network_urlparse__connection_data_http_downgrade(void) -1); } +void test_network_urlparse__connection_data_relative_redirect(void) +{ + cl_git_pass(gitno_connection_data_from_url(&conndata, + "http://foo.com/bar/baz/biff", NULL)); + cl_git_pass(gitno_connection_data_from_url(&conndata, + "/zap/baz/biff?bam", NULL)); + cl_assert_equal_s(conndata.host, "foo.com"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam"); + cl_assert_equal_p(conndata.user, NULL); + cl_assert_equal_p(conndata.pass, NULL); + cl_assert_equal_i(conndata.use_ssl, false); +} + +void test_network_urlparse__connection_data_relative_redirect_ssl(void) +{ + cl_git_pass(gitno_connection_data_from_url(&conndata, + "https://foo.com/bar/baz/biff", NULL)); + cl_git_pass(gitno_connection_data_from_url(&conndata, + "/zap/baz/biff?bam", NULL)); + cl_assert_equal_s(conndata.host, "foo.com"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam"); + cl_assert_equal_p(conndata.user, NULL); + cl_assert_equal_p(conndata.pass, NULL); + cl_assert_equal_i(conndata.use_ssl, true); +} + /* Run this under valgrind */ void test_network_urlparse__connection_data_cleanup(void) { -- cgit v1.2.1 From 598f069b998c42c12439f3f353b6d075905becba Mon Sep 17 00:00:00 2001 From: nulltoken Date: Wed, 2 Oct 2013 12:42:41 +0200 Subject: commit: Introduce git_commit_message_raw() --- include/git2/commit.h | 11 +++++++++++ src/commit.c | 23 ++++++++++++++++++----- src/commit.h | 2 +- tests-clar/commit/parse.c | 8 +++++++- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/include/git2/commit.h b/include/git2/commit.h index 0eaf917bd..a08cf1c6c 100644 --- a/include/git2/commit.h +++ b/include/git2/commit.h @@ -100,11 +100,22 @@ GIT_EXTERN(const char *) git_commit_message_encoding(const git_commit *commit); /** * Get the full message of a commit. * + * The returned message will be slightly prettified by removing any + * potential leading newlines. + * * @param commit a previously loaded commit. * @return the message of a commit */ GIT_EXTERN(const char *) git_commit_message(const git_commit *commit); +/** + * Get the full raw message of a commit. + * + * @param commit a previously loaded commit. + * @return the raw message of a commit + */ +GIT_EXTERN(const char *) git_commit_message_raw(const git_commit *commit); + /** * Get the commit time (i.e. committer time) of a commit. * diff --git a/src/commit.c b/src/commit.c index ab475a8f8..91b60bbb2 100644 --- a/src/commit.c +++ b/src/commit.c @@ -29,7 +29,7 @@ void git_commit__free(void *_commit) git_signature_free(commit->committer); git__free(commit->raw_header); - git__free(commit->message); + git__free(commit->raw_message); git__free(commit->message_encoding); git__free(commit); @@ -240,13 +240,13 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj) buffer_end = buffer + git_odb_object_size(odb_obj); buffer += header_len; - while (buffer < buffer_end && *buffer == '\n') + if (*buffer == '\n') ++buffer; /* extract commit message */ if (buffer <= buffer_end) { - commit->message = git__strndup(buffer, buffer_end - buffer); - GITERR_CHECK_ALLOC(commit->message); + commit->raw_message = git__strndup(buffer, buffer_end - buffer); + GITERR_CHECK_ALLOC(commit->raw_message); } return 0; @@ -265,7 +265,7 @@ bad_buffer: GIT_COMMIT_GETTER(const git_signature *, author, commit->author) GIT_COMMIT_GETTER(const git_signature *, committer, commit->committer) -GIT_COMMIT_GETTER(const char *, message, commit->message) +GIT_COMMIT_GETTER(const char *, message_raw, commit->raw_message) GIT_COMMIT_GETTER(const char *, message_encoding, commit->message_encoding) GIT_COMMIT_GETTER(const char *, raw_header, commit->raw_header) GIT_COMMIT_GETTER(git_time_t, time, commit->committer->when.time) @@ -273,6 +273,19 @@ GIT_COMMIT_GETTER(int, time_offset, commit->committer->when.offset) GIT_COMMIT_GETTER(unsigned int, parentcount, (unsigned int)git_array_size(commit->parent_ids)) GIT_COMMIT_GETTER(const git_oid *, tree_id, &commit->tree_id); +const char *git_commit_message(const git_commit *commit) +{ + const char *message = commit->raw_message; + + assert(commit); + + /* trim leading newlines from raw message */ + while (*message && *message == '\n') + ++message; + + return message; +} + int git_commit_tree(git_tree **tree_out, const git_commit *commit) { assert(commit); diff --git a/src/commit.h b/src/commit.h index 22fc898a1..d452e2975 100644 --- a/src/commit.h +++ b/src/commit.h @@ -24,7 +24,7 @@ struct git_commit { git_signature *committer; char *message_encoding; - char *message; + char *raw_message; char *raw_header; }; diff --git a/tests-clar/commit/parse.c b/tests-clar/commit/parse.c index c191b3421..41e162440 100644 --- a/tests-clar/commit/parse.c +++ b/tests-clar/commit/parse.c @@ -382,9 +382,13 @@ committer Vicent Marti 1273848544 +0200\n\ This commit has a few LF at the start of the commit message"; const char *message = "This commit has a few LF at the start of the commit message"; - + const char *raw_message = +"\n\ +\n\ +This commit has a few LF at the start of the commit message"; cl_git_pass(parse_commit(&commit, buffer)); cl_assert_equal_s(message, git_commit_message(commit)); + cl_assert_equal_s(raw_message, git_commit_message_raw(commit)); git_commit__free(commit); } @@ -400,8 +404,10 @@ committer Vicent Marti 1273848544 +0200\n\ \n\ \n"; const char *message = ""; + const char *raw_message = "\n\n"; cl_git_pass(parse_commit(&commit, buffer)); cl_assert_equal_s(message, git_commit_message(commit)); + cl_assert_equal_s(raw_message, git_commit_message_raw(commit)); git_commit__free(commit); } -- cgit v1.2.1 From 7baa7631eab48fba1427b0c7b4b109da09dd050b Mon Sep 17 00:00:00 2001 From: Jameson Miller Date: Wed, 2 Oct 2013 15:39:18 -0400 Subject: Style tweaks and changes for code review feedback --- src/transports/smart_protocol.c | 14 ++++++-------- tests-clar/online/push.c | 2 ++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 87e807ea3..24677908e 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -436,7 +436,7 @@ static int network_packetsize(size_t received, void *payload) if ((npp->stats->received_bytes - npp->last_fired_bytes) > NETWORK_XFER_THRESHOLD) { npp->last_fired_bytes = npp->stats->received_bytes; - if(npp->callback(npp->stats, npp->payload)) + if (npp->callback(npp->stats, npp->payload)) return GIT_EUSER; } @@ -468,7 +468,7 @@ int git_smart__download_pack( /* We might have something in the buffer already from negotiate_fetch */ if (t->buffer.offset > 0 && !t->cancelled.val) - if(t->packetsize_cb(t->buffer.offset, t->packetsize_payload)) + if (t->packetsize_cb(t->buffer.offset, t->packetsize_payload)) git_atomic_set(&t->cancelled, 1); } @@ -526,8 +526,7 @@ int git_smart__download_pack( } } while (1); - if ((error = writepack->commit(writepack, stats)) < 0) - goto done; + error = writepack->commit(writepack, stats); done: if (writepack) @@ -836,7 +835,7 @@ static int stream_thunk(void *buf, size_t size, void *data) if ((current_time - payload->last_progress_report_time) >= MIN_PROGRESS_UPDATE_INTERVAL) { payload->last_progress_report_time = current_time; - if(payload->cb(payload->pb->nr_written, payload->pb->nr_objects, payload->last_bytes, payload->cb_payload)) { + if (payload->cb(payload->pb->nr_written, payload->pb->nr_objects, payload->last_bytes, payload->cb_payload)) { giterr_clear(); error = GIT_EUSER; } @@ -914,9 +913,8 @@ int git_smart__push(git_transport *transport, git_push *push) push->transfer_progress_cb(push->pb->nr_written, push->pb->nr_objects, packbuilder_payload.last_bytes, push->transfer_progress_cb_payload); } - if (push->status.length && - (error = update_refs_from_report(&t->refs, &push->specs, &push->status)) < 0) - goto done; + if (push->status.length) + error = update_refs_from_report(&t->refs, &push->specs, &push->status); done: git_buf_free(&pktline); diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index cef39595c..4c2bec7ca 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -348,6 +348,7 @@ void test_online_push__cleanup(void) static int push_pack_progress_cb(int stage, unsigned int current, unsigned int total, void* payload) { int *was_called = (int *) payload; + GIT_UNUSED(stage); GIT_UNUSED(current); GIT_UNUSED(total); *was_called = 1; return 0; } @@ -355,6 +356,7 @@ static int push_pack_progress_cb(int stage, unsigned int current, unsigned int t static int push_transfer_progress_cb(unsigned int current, unsigned int total, size_t bytes, void* payload) { int *was_called = (int *) payload; + GIT_UNUSED(current); GIT_UNUSED(total); GIT_UNUSED(bytes); *was_called = 1; return 0; } -- cgit v1.2.1 From 6b7991e264b2fb0448e3dc47f972bafabf38c1fa Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 30 Sep 2013 16:13:53 -0700 Subject: Add check if we need to precompose unicode on Mac This adds initialization of core.precomposeunicode to repo init on Mac. This is necessary because when a Mac accesses a repo on a VFAT or SAMBA file system, it will return directory entries in decomposed unicode even if the filesystem entry is precomposed. This also removes caching of a number of repo properties from the repo init pipeline because these are properties of the specific filesystem on which the repo is created, not of the system as a whole. --- src/repository.c | 101 +++++++++++++++++++++++++++++++++---------------- tests-clar/repo/init.c | 10 +++++ 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/src/repository.c b/src/repository.c index 0d7c09484..64f13978d 100644 --- a/src/repository.c +++ b/src/repository.c @@ -843,10 +843,6 @@ fail: static bool is_chmod_supported(const char *file_path) { struct stat st1, st2; - static int _is_supported = -1; - - if (_is_supported > -1) - return _is_supported; if (p_stat(file_path, &st1) < 0) return false; @@ -857,27 +853,19 @@ static bool is_chmod_supported(const char *file_path) if (p_stat(file_path, &st2) < 0) return false; - _is_supported = (st1.st_mode != st2.st_mode); - - return _is_supported; + return (st1.st_mode != st2.st_mode); } static bool is_filesystem_case_insensitive(const char *gitdir_path) { git_buf path = GIT_BUF_INIT; - static int _is_insensitive = -1; - - if (_is_insensitive > -1) - return _is_insensitive; - - if (git_buf_joinpath(&path, gitdir_path, "CoNfIg") < 0) - goto cleanup; + int is_insensitive = -1; - _is_insensitive = git_path_exists(git_buf_cstr(&path)); + if (!git_buf_joinpath(&path, gitdir_path, "CoNfIg")) + is_insensitive = git_path_exists(git_buf_cstr(&path)); -cleanup: git_buf_free(&path); - return _is_insensitive; + return is_insensitive; } static bool are_symlinks_supported(const char *wd_path) @@ -885,24 +873,69 @@ static bool are_symlinks_supported(const char *wd_path) git_buf path = GIT_BUF_INIT; int fd; struct stat st; - static int _symlinks_supported = -1; - - if (_symlinks_supported > -1) - return _symlinks_supported; + int symlinks_supported = -1; if ((fd = git_futils_mktmp(&path, wd_path)) < 0 || p_close(fd) < 0 || p_unlink(path.ptr) < 0 || p_symlink("testing", path.ptr) < 0 || p_lstat(path.ptr, &st) < 0) - _symlinks_supported = false; + symlinks_supported = false; else - _symlinks_supported = (S_ISLNK(st.st_mode) != 0); + symlinks_supported = (S_ISLNK(st.st_mode) != 0); (void)p_unlink(path.ptr); git_buf_free(&path); - return _symlinks_supported; + return symlinks_supported; +} + +static const char *nfc_file = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D.XXXXXX"; +static const char *nfd_file = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D.XXXXXX"; + +/* On Mac, HDFS always stores files using decomposed unicode, but when + * writing to VFAT or SAMBA file systems, filenames may be kept as + * precomposed unicode, but will be converted to decomposed form when + * reading the directory entries. This can cause file name mismatches. + * The solution is to convert directory entries to precomposed form if we + * cannot look up the file from the decomposed path. + */ +static bool should_precompose_unicode_paths(const char *wd_path) +{ + git_buf path = GIT_BUF_INIT; + int fd; + bool need_precompose = false; + char tmp[6]; + + /* Create a file using a precomposed path and then try to find it + * using the decomposed name. If the lookup fails, then we will mark + * that we should precompose unicode for this repository. + */ + if (git_buf_joinpath(&path, wd_path, nfc_file) < 0 || + (fd = p_mkstemp(path.ptr)) < 0) + goto fail; + p_close(fd); + + /* record trailing digits generated by mkstemp */ + memcpy(tmp, path.ptr + path.size - sizeof(tmp), sizeof(tmp)); + + /* try to look up as NFD path */ + if (git_buf_joinpath(&path, wd_path, nfd_file) < 0) + goto fail; + memcpy(path.ptr + path.size - sizeof(tmp), tmp, sizeof(tmp)); + + need_precompose = !git_path_exists(path.ptr); + + /* remove temporary file */ + if (git_buf_joinpath(&path, wd_path, nfc_file) < 0) + goto fail; + memcpy(path.ptr + path.size - sizeof(tmp), tmp, sizeof(tmp)); + + (void)p_unlink(path.ptr); + +fail: + git_buf_free(&path); + return need_precompose; } static int create_empty_file(const char *path, mode_t mode) @@ -930,6 +963,7 @@ static int repo_init_config( int error = 0; git_buf cfg_path = GIT_BUF_INIT; git_config *config = NULL; + bool is_bare = ((opts->flags & GIT_REPOSITORY_INIT_BARE) != 0); #define SET_REPO_CONFIG(TYPE, NAME, VAL) do {\ if ((error = git_config_set_##TYPE(config, NAME, VAL)) < 0) \ @@ -954,17 +988,23 @@ static int repo_init_config( goto cleanup; SET_REPO_CONFIG( - bool, "core.bare", (opts->flags & GIT_REPOSITORY_INIT_BARE) != 0); + bool, "core.bare", is_bare); SET_REPO_CONFIG( int32, "core.repositoryformatversion", GIT_REPO_VERSION); SET_REPO_CONFIG( bool, "core.filemode", is_chmod_supported(git_buf_cstr(&cfg_path))); - if (!(opts->flags & GIT_REPOSITORY_INIT_BARE)) { - SET_REPO_CONFIG(bool, "core.logallrefupdates", true); +#if __APPLE__ + SET_REPO_CONFIG( + bool, "core.precomposeunicode", + should_precompose_unicode_paths(is_bare ? repo_dir : work_dir)); +#endif - if (!are_symlinks_supported(work_dir)) - SET_REPO_CONFIG(bool, "core.symlinks", false); + if (!are_symlinks_supported(is_bare ? repo_dir : work_dir)) + SET_REPO_CONFIG(bool, "core.symlinks", false); + + if (!is_bare) { + SET_REPO_CONFIG(bool, "core.logallrefupdates", true); if (!(opts->flags & GIT_REPOSITORY_INIT__NATURAL_WD)) { SET_REPO_CONFIG(string, "core.worktree", work_dir); @@ -973,9 +1013,6 @@ static int repo_init_config( if (git_config_delete_entry(config, "core.worktree") < 0) giterr_clear(); } - } else { - if (!are_symlinks_supported(repo_dir)) - SET_REPO_CONFIG(bool, "core.symlinks", false); } if (!(opts->flags & GIT_REPOSITORY_INIT__IS_REINIT) && diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index 392be205b..6f3c84175 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -241,6 +241,16 @@ void test_repo_init__detect_ignorecase(void) #endif } +void test_repo_init__detect_precompose_unicode_required(void) +{ +#ifdef __APPLE__ + /* hard to test "true" case without SAMBA or VFAT file system available */ + assert_config_entry_on_init("core.precomposeunicode", false); +#else + assert_config_entry_on_init("core.precomposeunicode", GIT_ENOTFOUND); +#endif +} + void test_repo_init__reinit_doesnot_overwrite_ignorecase(void) { git_config *config; -- cgit v1.2.1 From 2fe54afa2a8f87d03d2d550dcde7718f27e40967 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 30 Sep 2013 16:58:33 -0700 Subject: Put hooks in place for precompose in dirload fn This doesn't actual do string precompose but it puts the hooks in place into the iterators and the git_path_dirload function so that the actual precompose work is ready to go. --- src/config_cache.c | 1 + src/iterator.c | 14 +++++++++++++- src/iterator.h | 10 ++++++---- src/path.c | 14 +++++++++++--- src/path.h | 10 ++++++++-- src/refdb_fs.c | 10 ++++++++-- src/repository.h | 3 +++ 7 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/config_cache.c b/src/config_cache.c index 84de3a5ed..6808521a3 100644 --- a/src/config_cache.c +++ b/src/config_cache.c @@ -67,6 +67,7 @@ static struct map_data _cvar_maps[] = { {"core.ignorestat", NULL, 0, GIT_IGNORESTAT_DEFAULT }, {"core.trustctime", NULL, 0, GIT_TRUSTCTIME_DEFAULT }, {"core.abbrev", _cvar_map_int, 1, GIT_ABBREV_DEFAULT }, + {"core.precomposeunicode", NULL, 0, GIT_PRECOMPOSE_DEFAULT }, }; int git_repository__cvar(int *out, git_repository *repo, git_cvar_cached cvar) diff --git a/src/iterator.c b/src/iterator.c index bdc98d22b..946790449 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -986,7 +986,10 @@ static int fs_iterator__expand_dir(fs_iterator *fi) GITERR_CHECK_ALLOC(ff); error = git_path_dirload_with_stat( - fi->path.ptr, fi->root_len, iterator__ignore_case(fi), + fi->path.ptr, fi->root_len, + (iterator__ignore_case(fi) ? GIT_PATH_DIRLOAD_IGNORE_CASE : 0) | + (iterator__flag(fi, PRECOMPOSE_UNICODE) ? + GIT_PATH_DIRLOAD_PRECOMPOSE_UNICODE : 0), fi->base.start, fi->base.end, &ff->entries); if (error < 0) { @@ -1356,6 +1359,15 @@ int git_iterator_for_workdir_ext( return error; } + /* try to look up precompose and set flag if appropriate */ + { + int precompose = 0; + if (git_repository__cvar(&precompose, repo, GIT_CVAR_PRECOMPOSE) < 0) + giterr_clear(); + else if (precompose) + wi->fi.base.flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE; + } + return fs_iterator__initialize(out, &wi->fi, repo_workdir); } diff --git a/src/iterator.h b/src/iterator.h index ea88fa6a2..751e139d0 100644 --- a/src/iterator.h +++ b/src/iterator.h @@ -24,13 +24,15 @@ typedef enum { typedef enum { /** ignore case for entry sort order */ - GIT_ITERATOR_IGNORE_CASE = (1 << 0), + GIT_ITERATOR_IGNORE_CASE = (1u << 0), /** force case sensitivity for entry sort order */ - GIT_ITERATOR_DONT_IGNORE_CASE = (1 << 1), + GIT_ITERATOR_DONT_IGNORE_CASE = (1u << 1), /** return tree items in addition to blob items */ - GIT_ITERATOR_INCLUDE_TREES = (1 << 2), + GIT_ITERATOR_INCLUDE_TREES = (1u << 2), /** don't flatten trees, requiring advance_into (implies INCLUDE_TREES) */ - GIT_ITERATOR_DONT_AUTOEXPAND = (1 << 3), + GIT_ITERATOR_DONT_AUTOEXPAND = (1u << 3), + /** convert precomposed unicode to decomposed unicode */ + GIT_ITERATOR_PRECOMPOSE_UNICODE = (1u << 4), } git_iterator_flag_t; typedef struct { diff --git a/src/path.c b/src/path.c index 9d8e90361..c4ab57136 100644 --- a/src/path.c +++ b/src/path.c @@ -781,6 +781,7 @@ int git_path_dirload( const char *path, size_t prefix_len, size_t alloc_extra, + unsigned int flags, git_vector *contents) { int error, need_slash; @@ -816,6 +817,12 @@ int git_path_dirload( entry_len = strlen(de->d_name); + /* if we read decomposed unicode and precompose flag is set, + * then precompose it now so app code sees it as precomposed + */ + if ((flags & GIT_PATH_DIRLOAD_PRECOMPOSE_UNICODE) != 0) { + } + entry_path = git__malloc( path_len + need_slash + entry_len + 1 + alloc_extra); GITERR_CHECK_ALLOC(entry_path); @@ -858,7 +865,7 @@ int git_path_with_stat_cmp_icase(const void *a, const void *b) int git_path_dirload_with_stat( const char *path, size_t prefix_len, - bool ignore_case, + unsigned int flags, const char *start_stat, const char *end_stat, git_vector *contents) @@ -875,13 +882,14 @@ int git_path_dirload_with_stat( return -1; error = git_path_dirload( - path, prefix_len, sizeof(git_path_with_stat) + 1, contents); + path, prefix_len, sizeof(git_path_with_stat) + 1, flags, contents); if (error < 0) { git_buf_free(&full); return error; } - strncomp = ignore_case ? git__strncasecmp : git__strncmp; + strncomp = (flags & GIT_PATH_DIRLOAD_IGNORE_CASE) != 0 ? + git__strncasecmp : git__strncmp; /* stat struct at start of git_path_with_stat, so shift path text */ git_vector_foreach(contents, i, ps) { diff --git a/src/path.h b/src/path.h index b2899e97f..feacc99d0 100644 --- a/src/path.h +++ b/src/path.h @@ -290,6 +290,11 @@ extern int git_path_walk_up( int (*fn)(void *state, git_buf *), void *state); +enum { + GIT_PATH_DIRLOAD_IGNORE_CASE = (1u << 0), + GIT_PATH_DIRLOAD_PRECOMPOSE_UNICODE = (1u << 1), +}; + /** * Load all directory entries (except '.' and '..') into a vector. * @@ -310,6 +315,7 @@ extern int git_path_dirload( const char *path, size_t prefix_len, size_t alloc_extra, + unsigned int flags, git_vector *contents); @@ -336,7 +342,7 @@ extern int git_path_with_stat_cmp_icase(const void *a, const void *b); * * @param path The directory to read from * @param prefix_len The trailing part of path to prefix to entry paths - * @param ignore_case How to sort and compare paths with start/end limits + * @param flags GIT_PATH_DIRLOAD flags from above * @param start_stat As optimization, only stat values after this prefix * @param end_stat As optimization, only stat values before this prefix * @param contents Vector to fill with git_path_with_stat structures @@ -344,7 +350,7 @@ extern int git_path_with_stat_cmp_icase(const void *a, const void *b); extern int git_path_dirload_with_stat( const char *path, size_t prefix_len, - bool ignore_case, + unsigned int flags, const char *start_stat, const char *end_stat, git_vector *contents); diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 0ba711eb7..715b311a4 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -458,17 +458,23 @@ static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter) static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) { - int error = 0; + int error = 0, t; git_buf path = GIT_BUF_INIT; + git_iterator_flag_t flags = 0; git_iterator *fsit = NULL; const git_index_entry *entry = NULL; if (!backend->path) /* do nothing if no path for loose refs */ return 0; + if (!git_repository__cvar(&t, backend->repo, GIT_CVAR_IGNORECASE) && t) + flags |= GIT_ITERATOR_IGNORE_CASE; + if (!git_repository__cvar(&t, backend->repo, GIT_CVAR_PRECOMPOSE) && t) + flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE; + if ((error = git_buf_printf(&path, "%s/refs", backend->path)) < 0 || (error = git_iterator_for_filesystem( - &fsit, git_buf_cstr(&path), 0, NULL, NULL)) < 0) { + &fsit, git_buf_cstr(&path), flags, NULL, NULL)) < 0) { git_buf_free(&path); return error; } diff --git a/src/repository.h b/src/repository.h index 12dc50d51..832df3bd2 100644 --- a/src/repository.h +++ b/src/repository.h @@ -37,6 +37,7 @@ typedef enum { GIT_CVAR_IGNORESTAT, /* core.ignorestat */ GIT_CVAR_TRUSTCTIME, /* core.trustctime */ GIT_CVAR_ABBREV, /* core.abbrev */ + GIT_CVAR_PRECOMPOSE, /* core.precomposeunicode */ GIT_CVAR_CACHE_MAX } git_cvar_cached; @@ -86,6 +87,8 @@ typedef enum { GIT_TRUSTCTIME_DEFAULT = GIT_CVAR_TRUE, /* core.abbrev */ GIT_ABBREV_DEFAULT = 7, + /* core.precomposeunicode */ + GIT_PRECOMPOSE_DEFAULT = GIT_CVAR_FALSE, } git_cvar_value; -- cgit v1.2.1 From 219d3457324e8c2652e3462cedaf648912b40281 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 1 Oct 2013 16:12:15 -0700 Subject: Initial iconv hookup for precomposed unicode This hooks up git_path_direach and git_path_dirload so that they will take a flag indicating if directory entry names should be tested and converted from decomposed unicode to precomposed form. This code will only come into play on the Apple platform and even then, only when certain types of filesystems are used. This involved adding a flag to these functions which involved changing a lot of places in the code. This was an opportunity to do a bit of code cleanup here and there, for example, getting rid of the git_futils_cleanupdir_r function in favor of a simple flag to git_futils_rmdir_r to not remove the top level entry. That ended up adding depth tracking during rmdir_r which led to a safety check for infinite directory recursion. Yay. This hasn't actually been tested on the Mac filesystems where the issue occurs. I still need to get test environment for that. --- CMakeLists.txt | 5 +- src/clone.c | 42 ++++----- src/fileops.c | 73 ++++++--------- src/fileops.h | 16 +--- src/iterator.c | 24 ++--- src/odb_loose.c | 6 +- src/odb_pack.c | 2 +- src/path.c | 186 +++++++++++++++++++++++++++++---------- src/path.h | 49 ++++++----- src/refdb_fs.c | 28 +++--- tests-clar/clar_libgit2.c | 2 +- tests-clar/clone/nonetwork.c | 29 +++--- tests-clar/core/dirent.c | 24 ++--- tests-clar/merge/merge_helpers.c | 2 +- tests-clar/status/worktree.c | 2 +- 15 files changed, 273 insertions(+), 217 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index df3936496..62ebbf4e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,10 @@ FUNCTION(TARGET_OS_LIBRARIES target) TARGET_LINK_LIBRARIES(${target} socket nsl) ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux") TARGET_LINK_LIBRARIES(${target} rt) - ENDIF () + ELSEIF(APPLE) + TARGET_LINK_LIBRARIES(${target} iconv) + ENDIF() + IF(THREADSAFE) TARGET_LINK_LIBRARIES(${target} ${CMAKE_THREAD_LIBS_INIT}) ENDIF() diff --git a/src/clone.c b/src/clone.c index f3e365c07..657243945 100644 --- a/src/clone.c +++ b/src/clone.c @@ -391,11 +391,11 @@ int git_clone( const char *local_path, const git_clone_options *_options) { - int retcode = GIT_ERROR; + int error = 0; git_repository *repo = NULL; git_remote *origin; git_clone_options options = GIT_CLONE_OPTIONS_INIT; - int remove_directory_on_failure = 0; + uint32_t rmdir_flags = GIT_RMDIR_REMOVE_FILES; assert(out && url && local_path); @@ -408,33 +408,29 @@ int git_clone( if (git_path_exists(local_path) && !git_path_is_empty_dir(local_path)) { giterr_set(GITERR_INVALID, "'%s' exists and is not an empty directory", local_path); - return GIT_ERROR; + return GIT_EEXISTS; } - /* Only remove the directory on failure if we create it */ - remove_directory_on_failure = !git_path_exists(local_path); + /* Only remove the root directory on failure if we create it */ + if (git_path_exists(local_path)) + rmdir_flags |= GIT_RMDIR_SKIP_ROOT; - if ((retcode = git_repository_init(&repo, local_path, options.bare)) < 0) - return retcode; + if ((error = git_repository_init(&repo, local_path, options.bare)) < 0) + return error; - if ((retcode = create_and_configure_origin(&origin, repo, url, &options)) < 0) - goto cleanup; + if (!(error = create_and_configure_origin(&origin, repo, url, &options))) { + error = git_clone_into( + repo, origin, &options.checkout_opts, options.checkout_branch); - retcode = git_clone_into(repo, origin, &options.checkout_opts, options.checkout_branch); - git_remote_free(origin); + git_remote_free(origin); + } - if (retcode < 0) - goto cleanup; + if (error < 0) { + git_repository_free(repo); + repo = NULL; + (void)git_futils_rmdir_r(local_path, NULL, rmdir_flags); + } *out = repo; - return 0; - -cleanup: - git_repository_free(repo); - if (remove_directory_on_failure) - git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES); - else - git_futils_cleanupdir_r(local_path); - - return retcode; + return error; } diff --git a/src/fileops.c b/src/fileops.c index 5a5041cc3..be2e53ca8 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -398,8 +398,11 @@ typedef struct { size_t baselen; uint32_t flags; int error; + int depth; } futils__rmdir_data; +#define FUTILS_MAX_DEPTH 100 + static int futils__error_cannot_rmdir(const char *path, const char *filemsg) { if (filemsg) @@ -441,7 +444,12 @@ static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path) struct stat st; futils__rmdir_data *data = opaque; - if ((data->error = p_lstat_posixly(path->ptr, &st)) < 0) { + if (data->depth > FUTILS_MAX_DEPTH) { + data->error = + futils__error_cannot_rmdir(path->ptr, "directory nesting too deep"); + } + + else if ((data->error = p_lstat_posixly(path->ptr, &st)) < 0) { if (errno == ENOENT) data->error = 0; else if (errno == ENOTDIR) { @@ -457,9 +465,19 @@ static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path) } else if (S_ISDIR(st.st_mode)) { - int error = git_path_direach(path, futils__rmdir_recurs_foreach, data); - if (error < 0) - return (error == GIT_EUSER) ? data->error : error; + data->depth++; + + { + int error = + git_path_direach(path, 0, futils__rmdir_recurs_foreach, data); + if (error < 0) + return (error == GIT_EUSER) ? data->error : error; + } + + data->depth--; + + if (data->depth == 0 && (data->flags & GIT_RMDIR_SKIP_ROOT) != 0) + return data->error; data->error = p_rmdir(path->ptr); @@ -517,7 +535,7 @@ int git_futils_rmdir_r( { int error; git_buf fullpath = GIT_BUF_INIT; - futils__rmdir_data data; + futils__rmdir_data data = { 0 }; /* build path and find "root" where we should start calling mkdir */ if (git_path_join_unrooted(&fullpath, path, base, NULL) < 0) @@ -526,7 +544,6 @@ int git_futils_rmdir_r( data.base = base ? base : ""; data.baselen = base ? strlen(base) : 0; data.flags = flags; - data.error = 0; error = futils__rmdir_recurs_foreach(&data, &fullpath); @@ -544,41 +561,6 @@ int git_futils_rmdir_r( return error; } -int git_futils_cleanupdir_r(const char *path) -{ - int error; - git_buf fullpath = GIT_BUF_INIT; - futils__rmdir_data data; - - if ((error = git_buf_put(&fullpath, path, strlen(path))) < 0) - goto clean_up; - - data.base = ""; - data.baselen = 0; - data.flags = GIT_RMDIR_REMOVE_FILES; - data.error = 0; - - if (!git_path_exists(path)) { - giterr_set(GITERR_OS, "Path does not exist: %s" , path); - error = GIT_ERROR; - goto clean_up; - } - - if (!git_path_isdir(path)) { - giterr_set(GITERR_OS, "Path is not a directory: %s" , path); - error = GIT_ERROR; - goto clean_up; - } - - error = git_path_direach(&fullpath, futils__rmdir_recurs_foreach, &data); - if (error == GIT_EUSER) - error = data.error; - -clean_up: - git_buf_free(&fullpath); - return error; -} - static int git_futils_guess_system_dirs(git_buf *out) { @@ -948,9 +930,12 @@ static int _cp_r_callback(void *ref, git_buf *from) error = _cp_r_mkdir(info, from); /* recurse onto target directory */ - if (!error && (!exists || S_ISDIR(to_st.st_mode)) && - ((error = git_path_direach(from, _cp_r_callback, info)) == GIT_EUSER)) - error = info->error; + if (!error && (!exists || S_ISDIR(to_st.st_mode))) { + error = git_path_direach(from, 0, _cp_r_callback, info); + + if (error == GIT_EUSER) + error = info->error; + } if (oldmode != 0) info->dirmode = oldmode; diff --git a/src/fileops.h b/src/fileops.h index 6bd693b99..1b2728e58 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -115,12 +115,7 @@ extern int git_futils_mkpath2file(const char *path, const mode_t mode); * * GIT_RMDIR_EMPTY_PARENTS - remove containing directories up to base * if removing this item leaves them empty * * GIT_RMDIR_REMOVE_BLOCKERS - remove blocking file that causes ENOTDIR - * - * The old values translate into the new as follows: - * - * * GIT_DIRREMOVAL_EMPTY_HIERARCHY == GIT_RMDIR_EMPTY_HIERARCHY - * * GIT_DIRREMOVAL_FILES_AND_DIRS ~= GIT_RMDIR_REMOVE_FILES - * * GIT_DIRREMOVAL_ONLY_EMPTY_DIRS == GIT_RMDIR_SKIP_NONEMPTY + * * GIT_RMDIR_SKIP_ROOT - don't remove root directory itself */ typedef enum { GIT_RMDIR_EMPTY_HIERARCHY = 0, @@ -128,6 +123,7 @@ typedef enum { GIT_RMDIR_SKIP_NONEMPTY = (1 << 1), GIT_RMDIR_EMPTY_PARENTS = (1 << 2), GIT_RMDIR_REMOVE_BLOCKERS = (1 << 3), + GIT_RMDIR_SKIP_ROOT = (1 << 4), } git_futils_rmdir_flags; /** @@ -140,14 +136,6 @@ typedef enum { */ extern int git_futils_rmdir_r(const char *path, const char *base, uint32_t flags); -/** - * Remove all files and directories beneath the specified path. - * - * @param path Path to the top level directory to process. - * @return 0 on success; -1 on error. - */ -extern int git_futils_cleanupdir_r(const char *path); - /** * Create and open a temporary file with a `_git2_` suffix. * Writes the filename into path_out. diff --git a/src/iterator.c b/src/iterator.c index 946790449..ea6b45e88 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -893,6 +893,7 @@ struct fs_iterator { git_index_entry entry; git_buf path; size_t root_len; + uint32_t dirload_flags; int depth; int (*enter_dir_cb)(fs_iterator *self); @@ -986,10 +987,7 @@ static int fs_iterator__expand_dir(fs_iterator *fi) GITERR_CHECK_ALLOC(ff); error = git_path_dirload_with_stat( - fi->path.ptr, fi->root_len, - (iterator__ignore_case(fi) ? GIT_PATH_DIRLOAD_IGNORE_CASE : 0) | - (iterator__flag(fi, PRECOMPOSE_UNICODE) ? - GIT_PATH_DIRLOAD_PRECOMPOSE_UNICODE : 0), + fi->path.ptr, fi->root_len, fi->dirload_flags, fi->base.start, fi->base.end, &ff->entries); if (error < 0) { @@ -1210,6 +1208,11 @@ static int fs_iterator__initialize( } fi->root_len = fi->path.size; + fi->dirload_flags = + (iterator__ignore_case(fi) ? GIT_PATH_DIR_IGNORE_CASE : 0) | + (iterator__flag(fi, PRECOMPOSE_UNICODE) ? + GIT_PATH_DIR_PRECOMPOSE_UNICODE : 0); + if ((error = fs_iterator__expand_dir(fi)) < 0) { if (error == GIT_ENOTFOUND || error == GIT_ITEROVER) { giterr_clear(); @@ -1332,7 +1335,7 @@ int git_iterator_for_workdir_ext( const char *start, const char *end) { - int error; + int error, precompose = 0; workdir_iterator *wi; if (!repo_workdir) { @@ -1360,13 +1363,10 @@ int git_iterator_for_workdir_ext( } /* try to look up precompose and set flag if appropriate */ - { - int precompose = 0; - if (git_repository__cvar(&precompose, repo, GIT_CVAR_PRECOMPOSE) < 0) - giterr_clear(); - else if (precompose) - wi->fi.base.flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE; - } + if (git_repository__cvar(&precompose, repo, GIT_CVAR_PRECOMPOSE) < 0) + giterr_clear(); + else if (precompose) + wi->fi.base.flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE; return fs_iterator__initialize(out, &wi->fi, repo_workdir); } diff --git a/src/odb_loose.c b/src/odb_loose.c index 4ff57158d..07dfae539 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -544,7 +544,7 @@ static int locate_object_short_oid( /* Explore directory to find a unique object matching short_oid */ error = git_path_direach( - object_location, fn_locate_object_short_oid, &state); + object_location, 0, fn_locate_object_short_oid, &state); if (error && error != GIT_EUSER) return error; @@ -745,7 +745,7 @@ static int foreach_cb(void *_state, git_buf *path) { struct foreach_state *state = (struct foreach_state *) _state; - return git_path_direach(path, foreach_object_dir_cb, state); + return git_path_direach(path, 0, foreach_object_dir_cb, state); } static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb cb, void *data) @@ -768,7 +768,7 @@ static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb state.data = data; state.dir_len = git_buf_len(&buf); - error = git_path_direach(&buf, foreach_cb, &state); + error = git_path_direach(&buf, 0, foreach_cb, &state); git_buf_free(&buf); diff --git a/src/odb_pack.c b/src/odb_pack.c index cadc93a65..897bddf32 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -331,7 +331,7 @@ static int pack_backend__refresh(git_odb_backend *_backend) git_buf_sets(&path, backend->pack_folder); /* reload all packs */ - error = git_path_direach(&path, packfile_load__cb, (void *)backend); + error = git_path_direach(&path, 0, packfile_load__cb, backend); git_buf_free(&path); diff --git a/src/path.c b/src/path.c index c4ab57136..857cdfb5d 100644 --- a/src/path.c +++ b/src/path.c @@ -18,6 +18,12 @@ #define LOOKS_LIKE_DRIVE_PREFIX(S) (git__isalpha((S)[0]) && (S)[1] == ':') +#if __APPLE__ +#include +#endif +#define ICONV_REPO_ENCODING "UTF-8" +#define ICONV_PATH_ENCODING "UTF-8-MAC" + #ifdef GIT_WIN32 static bool looks_like_network_computer_name(const char *path, int pos) { @@ -724,14 +730,83 @@ int git_path_cmp( return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0; } +static bool path_has_non_ascii(const char *path, size_t pathlen) +{ + const uint8_t *scan = (const uint8_t *)path, *end; + + for (end = scan + pathlen; scan < end; ++scan) + if (*scan & 0x80) + return true; + + return false; +} + +#ifdef __APPLE__ +static int path_iconv(iconv_t map, git_buf *out, char **in, size_t *inlen) +{ + char *nfd = *in, *nfc; + size_t nfdlen = *inlen, nfclen, wantlen = nfdlen, rv; + int retry = 1; + + if (!path_has_non_ascii(*in, *inlen)) + return 0; + + while (1) { + if (git_buf_grow(out, wantlen) < 0) + return -1; + + nfc = out->ptr + out->size; + nfclen = out->asize - out->size; + + rv = iconv(map, &nfd, &nfdlen, &nfc, &nfclen); + + out->size = (nfc - out->ptr); + + if (rv != (size_t)-1) + break; + + if (errno != E2BIG) + return -1; + + /* make space for 2x the remaining data to be converted + * (with per retry overhead to avoid infinite loops) + */ + wantlen = out->size + max(nfclen, nfdlen) * 2 + (size_t)(retry * 4); + + if (retry++ > 4) + return -1; + } + + out->ptr[out->size] = '\0'; + + *in = out->ptr; + *inlen = out->size; + + return 0; +} +#endif + +#if defined(__sun) || defined(__GNU__) +typedef char path_dirent_data[sizeof(struct dirent) + FILENAME_MAX + 1]; +#else +typedef struct dirent path_dirent_data; +#endif + int git_path_direach( git_buf *path, + uint32_t flags, int (*fn)(void *, git_buf *), void *arg) { + int error = 0; ssize_t wd_len; DIR *dir; - struct dirent *de, *de_buf; + path_dirent_data de_data; + struct dirent *de, *de_buf = (struct dirent *)&de_data; +#ifdef __APPLE__ + iconv_t nfd2nfc = (iconv_t)-1; + git_buf nfc_path = GIT_BUF_INIT; +#endif if (git_path_to_dir(path) < 0) return -1; @@ -743,38 +818,46 @@ int git_path_direach( return -1; } -#if defined(__sun) || defined(__GNU__) - de_buf = git__malloc(sizeof(struct dirent) + FILENAME_MAX + 1); -#else - de_buf = git__malloc(sizeof(struct dirent)); +#ifdef __APPLE__ + if ((flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0) + nfd2nfc = iconv_open(ICONV_REPO_ENCODING, ICONV_PATH_ENCODING); #endif while (p_readdir_r(dir, de_buf, &de) == 0 && de != NULL) { - int result; + char *de_path = de->d_name; + size_t de_len = strlen(de_path); - if (git_path_is_dot_or_dotdot(de->d_name)) + if (git_path_is_dot_or_dotdot(de_path)) continue; - if (git_buf_puts(path, de->d_name) < 0) { - closedir(dir); - git__free(de_buf); - return -1; - } +#if __APPLE__ + if (nfd2nfc != (iconv_t)-1 && + (error = path_iconv(nfd2nfc, &nfc_path, &de_path, &de_len)) < 0) + break; +#endif - result = fn(arg, path); + if ((error = git_buf_put(path, de_path, de_len)) < 0) + break; + + error = fn(arg, path); git_buf_truncate(path, wd_len); /* restore path */ - if (result) { - closedir(dir); - git__free(de_buf); - return GIT_EUSER; + if (error) { + error = GIT_EUSER; + break; } } closedir(dir); - git__free(de_buf); - return 0; + +#ifdef __APPLE__ + if (nfd2nfc != (iconv_t)-1) + iconv_close(nfd2nfc); + git_buf_free(&nfc_path); +#endif + + return error; } int git_path_dirload( @@ -786,22 +869,30 @@ int git_path_dirload( { int error, need_slash; DIR *dir; - struct dirent *de, *de_buf; size_t path_len; + path_dirent_data de_data; + struct dirent *de, *de_buf = (struct dirent *)&de_data; +#ifdef __APPLE__ + iconv_t nfd2nfc = (iconv_t)-1; + git_buf nfc_path = GIT_BUF_INIT; +#endif + + assert(path && contents); - assert(path != NULL && contents != NULL); path_len = strlen(path); - assert(path_len > 0 && path_len >= prefix_len); + if (!path_len || path_len < prefix_len) { + giterr_set(GITERR_INVALID, "Invalid directory path '%s'", path); + return -1; + } if ((dir = opendir(path)) == NULL) { giterr_set(GITERR_OS, "Failed to open directory '%s'", path); return -1; } -#if defined(__sun) || defined(__GNU__) - de_buf = git__malloc(sizeof(struct dirent) + FILENAME_MAX + 1); -#else - de_buf = git__malloc(sizeof(struct dirent)); +#ifdef __APPLE__ + if ((flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0) + nfd2nfc = iconv_open(ICONV_REPO_ENCODING, ICONV_PATH_ENCODING); #endif path += prefix_len; @@ -809,40 +900,41 @@ int git_path_dirload( need_slash = (path_len > 0 && path[path_len-1] != '/') ? 1 : 0; while ((error = p_readdir_r(dir, de_buf, &de)) == 0 && de != NULL) { - char *entry_path; - size_t entry_len; + char *entry_path, *de_path = de->d_name; + size_t alloc_size, de_len = strlen(de_path); - if (git_path_is_dot_or_dotdot(de->d_name)) + if (git_path_is_dot_or_dotdot(de_path)) continue; - entry_len = strlen(de->d_name); +#if __APPLE__ + if (nfd2nfc != (iconv_t)-1 && + (error = path_iconv(nfd2nfc, &nfc_path, &de_path, &de_len)) < 0) + break; +#endif - /* if we read decomposed unicode and precompose flag is set, - * then precompose it now so app code sees it as precomposed - */ - if ((flags & GIT_PATH_DIRLOAD_PRECOMPOSE_UNICODE) != 0) { + alloc_size = path_len + need_slash + de_len + 1 + alloc_extra; + if ((entry_path = git__calloc(alloc_size, 1)) == NULL) { + error = -1; + break; } - entry_path = git__malloc( - path_len + need_slash + entry_len + 1 + alloc_extra); - GITERR_CHECK_ALLOC(entry_path); - if (path_len) memcpy(entry_path, path, path_len); if (need_slash) entry_path[path_len] = '/'; - memcpy(&entry_path[path_len + need_slash], de->d_name, entry_len); - entry_path[path_len + need_slash + entry_len] = '\0'; + memcpy(&entry_path[path_len + need_slash], de_path, de_len); - if (git_vector_insert(contents, entry_path) < 0) { - closedir(dir); - git__free(de_buf); - return -1; - } + if ((error = git_vector_insert(contents, entry_path)) < 0) + break; } closedir(dir); - git__free(de_buf); + +#ifdef __APPLE__ + if (nfd2nfc != (iconv_t)-1) + iconv_close(nfd2nfc); + git_buf_free(&nfc_path); +#endif if (error != 0) giterr_set(GITERR_OS, "Failed to process directory entry in '%s'", path); @@ -888,7 +980,7 @@ int git_path_dirload_with_stat( return error; } - strncomp = (flags & GIT_PATH_DIRLOAD_IGNORE_CASE) != 0 ? + strncomp = (flags & GIT_PATH_DIR_IGNORE_CASE) != 0 ? git__strncasecmp : git__strncmp; /* stat struct at start of git_path_with_stat, so shift path text */ diff --git a/src/path.h b/src/path.h index feacc99d0..534cfe50b 100644 --- a/src/path.h +++ b/src/path.h @@ -242,21 +242,28 @@ extern int git_path_resolve_relative(git_buf *path, size_t ceiling); */ extern int git_path_apply_relative(git_buf *target, const char *relpath); +enum { + GIT_PATH_DIR_IGNORE_CASE = (1u << 0), + GIT_PATH_DIR_PRECOMPOSE_UNICODE = (1u << 1), +}; + /** * Walk each directory entry, except '.' and '..', calling fn(state). * - * @param pathbuf buffer the function reads the initial directory + * @param pathbuf Buffer the function reads the initial directory * path from, and updates with each successive entry's name. - * @param fn function to invoke with each entry. The first arg is - * the input state and the second arg is pathbuf. The function - * may modify the pathbuf, but only by appending new text. - * @param state to pass to fn as the first arg. + * @param flags Combination of GIT_PATH_DIR flags. + * @param callback Callback for each entry. Passed the `payload` and each + * successive path inside the directory as a full path. This may + * safely append text to the pathbuf if needed. + * @param payload Passed to callback as first argument. * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ extern int git_path_direach( git_buf *pathbuf, - int (*fn)(void *, git_buf *), - void *state); + uint32_t flags, + int (*callback)(void *payload, git_buf *path), + void *payload); /** * Sort function to order two paths @@ -276,24 +283,19 @@ extern int git_path_cmp( * @param pathbuf Buffer the function reads the directory from and * and updates with each successive name. * @param ceiling Prefix of path at which to stop walking up. If NULL, - * this will walk all the way up to the root. If not a prefix of - * pathbuf, the callback will be invoked a single time on the - * original input path. - * @param fn Function to invoke on each path. The first arg is the - * input satte and the second arg is the pathbuf. The function - * should not modify the pathbuf. + * this will walk all the way up to the root. If not a prefix of + * pathbuf, the callback will be invoked a single time on the + * original input path. + * @param callback Function to invoke on each path. Passed the `payload` + * and the buffer containing the current path. The path should not + * be modified in any way. * @param state Passed to fn as the first ath. */ extern int git_path_walk_up( git_buf *pathbuf, const char *ceiling, - int (*fn)(void *state, git_buf *), - void *state); - -enum { - GIT_PATH_DIRLOAD_IGNORE_CASE = (1u << 0), - GIT_PATH_DIRLOAD_PRECOMPOSE_UNICODE = (1u << 1), -}; + int (*callback)(void *payload, git_buf *path), + void *payload); /** * Load all directory entries (except '.' and '..') into a vector. @@ -309,13 +311,14 @@ enum { * prefix_len 3, the entries will look like "b/e1", "b/e2", etc. * @param alloc_extra Extra bytes to add to each string allocation in * case you want to append anything funny. + * @param flags Combination of GIT_PATH_DIR flags. * @param contents Vector to fill with directory entry names. */ extern int git_path_dirload( const char *path, size_t prefix_len, size_t alloc_extra, - unsigned int flags, + uint32_t flags, git_vector *contents); @@ -342,7 +345,7 @@ extern int git_path_with_stat_cmp_icase(const void *a, const void *b); * * @param path The directory to read from * @param prefix_len The trailing part of path to prefix to entry paths - * @param flags GIT_PATH_DIRLOAD flags from above + * @param flags GIT_PATH_DIR flags from above * @param start_stat As optimization, only stat values after this prefix * @param end_stat As optimization, only stat values before this prefix * @param contents Vector to fill with git_path_with_stat structures @@ -350,7 +353,7 @@ extern int git_path_with_stat_cmp_icase(const void *a, const void *b); extern int git_path_dirload_with_stat( const char *path, size_t prefix_len, - unsigned int flags, + uint32_t flags, const char *start_stat, const char *end_stat, git_vector *contents); diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 715b311a4..afe1a2a42 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -56,6 +56,8 @@ typedef struct refdb_fs_backend { git_sortedcache *refcache; int peeling_mode; + git_iterator_flag_t iterator_flags; + uint32_t direach_flags; } refdb_fs_backend; static int packref_cmp(const void *a_, const void *b_) @@ -269,7 +271,8 @@ static int _dirent_loose_load(void *data, git_buf *full_path) return 0; if (git_path_isdir(full_path->ptr)) - return git_path_direach(full_path, _dirent_loose_load, backend); + return git_path_direach( + full_path, backend->direach_flags, _dirent_loose_load, backend); file_path = full_path->ptr + strlen(backend->path); @@ -295,7 +298,8 @@ static int packed_loadloose(refdb_fs_backend *backend) * This will overwrite any old packed entries with their * updated loose versions */ - error = git_path_direach(&refs_path, _dirent_loose_load, backend); + error = git_path_direach( + &refs_path, backend->direach_flags, _dirent_loose_load, backend); git_buf_free(&refs_path); @@ -458,23 +462,17 @@ static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter) static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) { - int error = 0, t; + int error = 0; git_buf path = GIT_BUF_INIT; - git_iterator_flag_t flags = 0; git_iterator *fsit = NULL; const git_index_entry *entry = NULL; if (!backend->path) /* do nothing if no path for loose refs */ return 0; - if (!git_repository__cvar(&t, backend->repo, GIT_CVAR_IGNORECASE) && t) - flags |= GIT_ITERATOR_IGNORE_CASE; - if (!git_repository__cvar(&t, backend->repo, GIT_CVAR_PRECOMPOSE) && t) - flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE; - if ((error = git_buf_printf(&path, "%s/refs", backend->path)) < 0 || (error = git_iterator_for_filesystem( - &fsit, git_buf_cstr(&path), flags, NULL, NULL)) < 0) { + &fsit, path.ptr, backend->iterator_flags, NULL, NULL)) < 0) { git_buf_free(&path); return error; } @@ -1077,6 +1075,7 @@ int git_refdb_backend_fs( git_refdb_backend **backend_out, git_repository *repository) { + int t = 0; git_buf path = GIT_BUF_INIT; refdb_fs_backend *backend; @@ -1098,6 +1097,15 @@ int git_refdb_backend_fs( git_buf_free(&path); + if (!git_repository__cvar(&t, backend->repo, GIT_CVAR_IGNORECASE) && t) { + backend->iterator_flags |= GIT_ITERATOR_IGNORE_CASE; + backend->direach_flags |= GIT_PATH_DIR_IGNORE_CASE; + } + if (!git_repository__cvar(&t, backend->repo, GIT_CVAR_PRECOMPOSE) && t) { + backend->iterator_flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE; + backend->direach_flags |= GIT_PATH_DIR_PRECOMPOSE_UNICODE; + } + backend->parent.exists = &refdb_fs_backend__exists; backend->parent.lookup = &refdb_fs_backend__lookup; backend->parent.iterator = &refdb_fs_backend__iterator; diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 6063bf91c..0f8f26efb 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -301,7 +301,7 @@ static int remove_placeholders_recurs(void *_data, git_buf *path) size_t pathlen; if (git_path_isdir(path->ptr) == true) - return git_path_direach(path, remove_placeholders_recurs, data); + return git_path_direach(path, 0, remove_placeholders_recurs, data); pathlen = path->size; diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 4bcb5be1e..c4d75a8dc 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -63,34 +63,27 @@ static int dont_call_me(void *state, git_buf *path) return GIT_ERROR; } -void test_clone_nonetwork__do_not_clean_existing_directory(void) +static void assert_empty_directory(const char *path) { - git_buf path_buf = GIT_BUF_INIT; - - git_buf_put(&path_buf, "./foo", 5); + git_buf buf = GIT_BUF_INIT; + cl_assert(git_path_exists(path)); + cl_git_pass(git_buf_sets(&buf, path)); + cl_git_pass(git_path_direach(&buf, 0, dont_call_me, NULL)); + git_buf_free(&buf); +} +void test_clone_nonetwork__do_not_clean_existing_directory(void) +{ /* Clone should not remove the directory if it already exists, but * Should clean up entries it creates. */ p_mkdir("./foo", GIT_DIR_MODE); cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); - cl_assert(git_path_exists("./foo")); - - /* Make sure the directory is empty. */ - cl_git_pass(git_path_direach(&path_buf, - dont_call_me, - NULL)); + assert_empty_directory("./foo"); /* Try again with a bare repository. */ g_options.bare = true; cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); - cl_assert(git_path_exists("./foo")); - - /* Make sure the directory is empty. */ - cl_git_pass(git_path_direach(&path_buf, - dont_call_me, - NULL)); - - git_buf_free(&path_buf); + assert_empty_directory("./foo"); } void test_clone_nonetwork__local(void) diff --git a/tests-clar/core/dirent.c b/tests-clar/core/dirent.c index 5a7859d1b..a9a83e827 100644 --- a/tests-clar/core/dirent.c +++ b/tests-clar/core/dirent.c @@ -115,9 +115,7 @@ void test_core_dirent__dont_traverse_dot(void) cl_set_cleanup(&dirent_cleanup__cb, &dot); setup(&dot); - cl_git_pass(git_path_direach(&dot.path, - one_entry, - &dot)); + cl_git_pass(git_path_direach(&dot.path, 0, one_entry, &dot)); check_counts(&dot); } @@ -141,9 +139,7 @@ void test_core_dirent__traverse_subfolder(void) cl_set_cleanup(&dirent_cleanup__cb, &sub); setup(&sub); - cl_git_pass(git_path_direach(&sub.path, - one_entry, - &sub)); + cl_git_pass(git_path_direach(&sub.path, 0, one_entry, &sub)); check_counts(&sub); } @@ -161,9 +157,7 @@ void test_core_dirent__traverse_slash_terminated_folder(void) cl_set_cleanup(&dirent_cleanup__cb, &sub_slash); setup(&sub_slash); - cl_git_pass(git_path_direach(&sub_slash.path, - one_entry, - &sub_slash)); + cl_git_pass(git_path_direach(&sub_slash.path, 0, one_entry, &sub_slash)); check_counts(&sub_slash); } @@ -184,16 +178,12 @@ void test_core_dirent__dont_traverse_empty_folders(void) cl_set_cleanup(&dirent_cleanup__cb, &empty); setup(&empty); - cl_git_pass(git_path_direach(&empty.path, - one_entry, - &empty)); + cl_git_pass(git_path_direach(&empty.path, 0, one_entry, &empty)); check_counts(&empty); /* make sure callback not called */ - cl_git_pass(git_path_direach(&empty.path, - dont_call_me, - &empty)); + cl_git_pass(git_path_direach(&empty.path, 0, dont_call_me, &empty)); } static name_data odd_names[] = { @@ -216,9 +206,7 @@ void test_core_dirent__traverse_weird_filenames(void) cl_set_cleanup(&dirent_cleanup__cb, &odd); setup(&odd); - cl_git_pass(git_path_direach(&odd.path, - one_entry, - &odd)); + cl_git_pass(git_path_direach(&odd.path, 0, one_entry, &odd)); check_counts(&odd); } diff --git a/tests-clar/merge/merge_helpers.c b/tests-clar/merge/merge_helpers.c index e4092787c..ddcb93ff6 100644 --- a/tests-clar/merge/merge_helpers.c +++ b/tests-clar/merge/merge_helpers.c @@ -291,7 +291,7 @@ int merge_test_workdir(git_repository *repo, const struct merge_index_entry expe git_buf wd = GIT_BUF_INIT; git_buf_puts(&wd, repo->workdir); - git_path_direach(&wd, dircount, &actual_len); + git_path_direach(&wd, 0, dircount, &actual_len); if (actual_len != expected_len) return 0; diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index 135a95871..3b569c7ba 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -119,7 +119,7 @@ void test_status_worktree__purged_worktree(void) /* first purge the contents of the worktree */ cl_git_pass(git_buf_sets(&workdir, git_repository_workdir(repo))); - cl_git_pass(git_path_direach(&workdir, remove_file_cb, NULL)); + cl_git_pass(git_path_direach(&workdir, 0, remove_file_cb, NULL)); git_buf_free(&workdir); /* now get status */ -- cgit v1.2.1 From 966bb17a57d0c1128261b7575db245f5bc3cf41d Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 1 Oct 2013 16:41:07 -0700 Subject: Add to Git authors who have agreed to relicense MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In email, Torsten Bögershausen agreed that we could use his code from core Git in libgit2 under the modified license. Also, since his work is the basis for much of the precompose unicode support, I have added him to the AUTHORS file as well. --- AUTHORS | 1 + git.git-authors | 1 + 2 files changed, 2 insertions(+) diff --git a/AUTHORS b/AUTHORS index 587da249d..f3a03ee74 100644 --- a/AUTHORS +++ b/AUTHORS @@ -68,5 +68,6 @@ Sven Strickroth Tim Branyen Tim Clem Tim Harder +Torsten Bögershausen Trent Mick Vicent Marti diff --git a/git.git-authors b/git.git-authors index 3fcf27ffc..7d4c95bb3 100644 --- a/git.git-authors +++ b/git.git-authors @@ -68,3 +68,4 @@ ok Sebastian Schuberth ok Shawn O. Pearce ok Steffen Prohaska ok Sven Verdoolaege +ok Torsten Bögershausen -- cgit v1.2.1 From d0849f830f494445e4ef9f04d32be1a2d10b89b3 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 2 Oct 2013 11:07:18 -0700 Subject: Simplify git_path_is_empty_dir implementation This simplifies git_path_is_empty_dir on both Windows (getting rid of git_buf allocation inside the function) and other platforms (by just using git_path_direach), and adds tests for the function, and uses the function to simplify some existing tests. --- src/path.c | 51 ++++++++++++++++++++------------------------ tests-clar/clone/nonetwork.c | 20 ++--------------- tests-clar/core/dirent.c | 31 +++++++++++++++++++-------- 3 files changed, 47 insertions(+), 55 deletions(-) diff --git a/src/path.c b/src/path.c index 857cdfb5d..c8d6efb30 100644 --- a/src/path.c +++ b/src/path.c @@ -489,23 +489,23 @@ bool git_path_isfile(const char *path) bool git_path_is_empty_dir(const char *path) { - git_buf pathbuf = GIT_BUF_INIT; HANDLE hFind = INVALID_HANDLE_VALUE; git_win32_path wbuf; + int wbufsz; WIN32_FIND_DATAW ffd; bool retval = true; - if (!git_path_isdir(path)) return false; + if (!git_path_isdir(path)) + return false; - git_buf_printf(&pathbuf, "%s\\*", path); - git_win32_path_from_c(wbuf, git_buf_cstr(&pathbuf)); + wbufsz = git_win32_path_from_c(wbuf, path); + if (!wbufsz || wbufsz + 2 > GIT_WIN_PATH_UTF16) + return false; + memcpy(&wbuf[wbufsz - 1], L"\\*", 3 * sizeof(wchar_t)); hFind = FindFirstFileW(wbuf, &ffd); - if (INVALID_HANDLE_VALUE == hFind) { - giterr_set(GITERR_OS, "Couldn't open '%s'", path); - git_buf_free(&pathbuf); + if (INVALID_HANDLE_VALUE == hFind) return false; - } do { if (!git_path_is_dot_or_dotdotW(ffd.cFileName)) { @@ -515,38 +515,33 @@ bool git_path_is_empty_dir(const char *path) } while (FindNextFileW(hFind, &ffd) != 0); FindClose(hFind); - git_buf_free(&pathbuf); return retval; } #else -bool git_path_is_empty_dir(const char *path) +static int path_found_entry(void *payload, git_buf *path) { - DIR *dir = NULL; - struct dirent *e; - bool retval = true; + GIT_UNUSED(payload); + return !git_path_is_dot_or_dotdot(path->ptr); +} - if (!git_path_isdir(path)) return false; +bool git_path_is_empty_dir(const char *path) +{ + int error; + git_buf dir = GIT_BUF_INIT; - dir = opendir(path); - if (!dir) { - giterr_set(GITERR_OS, "Couldn't open '%s'", path); + if (!git_path_isdir(path)) return false; - } - while ((e = readdir(dir)) != NULL) { - if (!git_path_is_dot_or_dotdot(e->d_name)) { - giterr_set(GITERR_INVALID, - "'%s' exists and is not an empty directory", path); - retval = false; - break; - } - } - closedir(dir); + if (!(error = git_buf_sets(&dir, path))) + error = git_path_direach(&dir, 0, path_found_entry, NULL); - return retval; + git_buf_free(&dir); + + return !error; } + #endif int git_path_lstat(const char *path, struct stat *st) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index c4d75a8dc..071e3d09f 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -56,34 +56,18 @@ void test_clone_nonetwork__bad_url(void) cl_assert(!git_path_exists("./foo")); } -static int dont_call_me(void *state, git_buf *path) -{ - GIT_UNUSED(state); - GIT_UNUSED(path); - return GIT_ERROR; -} - -static void assert_empty_directory(const char *path) -{ - git_buf buf = GIT_BUF_INIT; - cl_assert(git_path_exists(path)); - cl_git_pass(git_buf_sets(&buf, path)); - cl_git_pass(git_path_direach(&buf, 0, dont_call_me, NULL)); - git_buf_free(&buf); -} - void test_clone_nonetwork__do_not_clean_existing_directory(void) { /* Clone should not remove the directory if it already exists, but * Should clean up entries it creates. */ p_mkdir("./foo", GIT_DIR_MODE); cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); - assert_empty_directory("./foo"); + cl_assert(git_path_is_empty_dir("./foo")); /* Try again with a bare repository. */ g_options.bare = true; cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); - assert_empty_directory("./foo"); + cl_assert(git_path_is_empty_dir("./foo")); } void test_clone_nonetwork__local(void) diff --git a/tests-clar/core/dirent.c b/tests-clar/core/dirent.c index a9a83e827..f17260362 100644 --- a/tests-clar/core/dirent.c +++ b/tests-clar/core/dirent.c @@ -88,14 +88,6 @@ static int one_entry(void *state, git_buf *path) return GIT_ERROR; } -static int dont_call_me(void *state, git_buf *path) -{ - GIT_UNUSED(state); - GIT_UNUSED(path); - return GIT_ERROR; -} - - static name_data dot_names[] = { { 0, "./a" }, @@ -183,7 +175,7 @@ void test_core_dirent__dont_traverse_empty_folders(void) check_counts(&empty); /* make sure callback not called */ - cl_git_pass(git_path_direach(&empty.path, 0, dont_call_me, &empty)); + cl_assert(git_path_is_empty_dir(empty.path.ptr)); } static name_data odd_names[] = { @@ -219,5 +211,26 @@ void test_core_dirent__length_limits(void) big_filename[FILENAME_MAX] = 0; cl_must_fail(p_creat(big_filename, 0666)); + git__free(big_filename); } + +void test_core_dirent__empty_dir(void) +{ + cl_must_pass(p_mkdir("empty_dir", 0777)); + cl_assert(git_path_is_empty_dir("empty_dir")); + + cl_git_mkfile("empty_dir/content", "whatever\n"); + cl_assert(!git_path_is_empty_dir("empty_dir")); + cl_assert(!git_path_is_empty_dir("empty_dir/content")); + + cl_must_pass(p_unlink("empty_dir/content")); + + cl_must_pass(p_mkdir("empty_dir/content", 0777)); + cl_assert(!git_path_is_empty_dir("empty_dir")); + cl_assert(git_path_is_empty_dir("empty_dir/content")); + + cl_must_pass(p_rmdir("empty_dir/content")); + + cl_must_pass(p_rmdir("empty_dir")); +} -- cgit v1.2.1 From 618b7689e1cdd4ebd956949a95038fd49592a187 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 2 Oct 2013 12:06:26 -0700 Subject: Wrap iconv stuff and write tests This adds a simple wrapper around the iconv APIs and uses it instead of the old code that was inlining the iconv stuff. This makes it possible for me to test the iconv logic in isolation. A "no iconv" version of the API was defined with macros so that I could have fewer ifdefs in the code itself. --- src/path.c | 105 ++++++++++++++++++++++-------------------------- src/path.h | 52 ++++++++++++++++++++++++ tests-clar/core/iconv.c | 57 ++++++++++++++++++++++++++ tests-clar/core/path.c | 2 +- 4 files changed, 157 insertions(+), 59 deletions(-) create mode 100644 tests-clar/core/iconv.c diff --git a/src/path.c b/src/path.c index c8d6efb30..27abd062b 100644 --- a/src/path.c +++ b/src/path.c @@ -18,12 +18,6 @@ #define LOOKS_LIKE_DRIVE_PREFIX(S) (git__isalpha((S)[0]) && (S)[1] == ':') -#if __APPLE__ -#include -#endif -#define ICONV_REPO_ENCODING "UTF-8" -#define ICONV_PATH_ENCODING "UTF-8-MAC" - #ifdef GIT_WIN32 static bool looks_like_network_computer_name(const char *path, int pos) { @@ -725,7 +719,7 @@ int git_path_cmp( return (c1 < c2) ? -1 : (c1 > c2) ? 1 : 0; } -static bool path_has_non_ascii(const char *path, size_t pathlen) +bool git_path_has_non_ascii(const char *path, size_t pathlen) { const uint8_t *scan = (const uint8_t *)path, *end; @@ -736,49 +730,72 @@ static bool path_has_non_ascii(const char *path, size_t pathlen) return false; } -#ifdef __APPLE__ -static int path_iconv(iconv_t map, git_buf *out, char **in, size_t *inlen) +#ifdef GIT_USE_ICONV + +int git_path_iconv_init_precompose(git_path_iconv_t *ic) +{ + git_buf_init(&ic->buf, 0); + ic->map = iconv_open(GIT_PATH_REPO_ENCODING, GIT_PATH_NATIVE_ENCODING); + return 0; +} + +void git_path_iconv_clear(git_path_iconv_t *ic) +{ + if (ic) { + if (ic->map != (iconv_t)-1) + iconv_close(ic->map); + git_buf_free(&ic->buf); + } +} + +int git_path_iconv(git_path_iconv_t *ic, char **in, size_t *inlen) { char *nfd = *in, *nfc; size_t nfdlen = *inlen, nfclen, wantlen = nfdlen, rv; int retry = 1; - if (!path_has_non_ascii(*in, *inlen)) + if (!ic || ic->map == (iconv_t)-1 || + !git_path_has_non_ascii(*in, *inlen)) return 0; while (1) { - if (git_buf_grow(out, wantlen) < 0) + if (git_buf_grow(&ic->buf, wantlen) < 0) return -1; - nfc = out->ptr + out->size; - nfclen = out->asize - out->size; + nfc = ic->buf.ptr + ic->buf.size; + nfclen = ic->buf.asize - ic->buf.size; - rv = iconv(map, &nfd, &nfdlen, &nfc, &nfclen); + rv = iconv(ic->map, &nfd, &nfdlen, &nfc, &nfclen); - out->size = (nfc - out->ptr); + ic->buf.size = (nfc - ic->buf.ptr); if (rv != (size_t)-1) break; if (errno != E2BIG) - return -1; + goto fail; /* make space for 2x the remaining data to be converted * (with per retry overhead to avoid infinite loops) */ - wantlen = out->size + max(nfclen, nfdlen) * 2 + (size_t)(retry * 4); + wantlen = ic->buf.size + max(nfclen, nfdlen) * 2 + (size_t)(retry * 4); if (retry++ > 4) - return -1; + goto fail; } - out->ptr[out->size] = '\0'; + ic->buf.ptr[ic->buf.size] = '\0'; - *in = out->ptr; - *inlen = out->size; + *in = ic->buf.ptr; + *inlen = ic->buf.size; return 0; + +fail: + giterr_set(GITERR_OS, "Unable to convert unicode path data"); + return -1; } + #endif #if defined(__sun) || defined(__GNU__) @@ -798,10 +815,7 @@ int git_path_direach( DIR *dir; path_dirent_data de_data; struct dirent *de, *de_buf = (struct dirent *)&de_data; -#ifdef __APPLE__ - iconv_t nfd2nfc = (iconv_t)-1; - git_buf nfc_path = GIT_BUF_INIT; -#endif + git_path_iconv_t ic = GIT_PATH_ICONV_INIT; if (git_path_to_dir(path) < 0) return -1; @@ -813,10 +827,8 @@ int git_path_direach( return -1; } -#ifdef __APPLE__ if ((flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0) - nfd2nfc = iconv_open(ICONV_REPO_ENCODING, ICONV_PATH_ENCODING); -#endif + (void)git_path_iconv_init_precompose(&ic); while (p_readdir_r(dir, de_buf, &de) == 0 && de != NULL) { char *de_path = de->d_name; @@ -825,13 +837,8 @@ int git_path_direach( if (git_path_is_dot_or_dotdot(de_path)) continue; -#if __APPLE__ - if (nfd2nfc != (iconv_t)-1 && - (error = path_iconv(nfd2nfc, &nfc_path, &de_path, &de_len)) < 0) - break; -#endif - - if ((error = git_buf_put(path, de_path, de_len)) < 0) + if ((error = git_path_iconv(&ic, &de_path, &de_len)) < 0 || + (error = git_buf_put(path, de_path, de_len)) < 0) break; error = fn(arg, path); @@ -845,12 +852,7 @@ int git_path_direach( } closedir(dir); - -#ifdef __APPLE__ - if (nfd2nfc != (iconv_t)-1) - iconv_close(nfd2nfc); - git_buf_free(&nfc_path); -#endif + git_path_iconv_clear(&ic); return error; } @@ -867,10 +869,7 @@ int git_path_dirload( size_t path_len; path_dirent_data de_data; struct dirent *de, *de_buf = (struct dirent *)&de_data; -#ifdef __APPLE__ - iconv_t nfd2nfc = (iconv_t)-1; - git_buf nfc_path = GIT_BUF_INIT; -#endif + git_path_iconv_t ic = GIT_PATH_ICONV_INIT; assert(path && contents); @@ -885,10 +884,8 @@ int git_path_dirload( return -1; } -#ifdef __APPLE__ if ((flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0) - nfd2nfc = iconv_open(ICONV_REPO_ENCODING, ICONV_PATH_ENCODING); -#endif + (void)git_path_iconv_init_precompose(&ic); path += prefix_len; path_len -= prefix_len; @@ -901,11 +898,8 @@ int git_path_dirload( if (git_path_is_dot_or_dotdot(de_path)) continue; -#if __APPLE__ - if (nfd2nfc != (iconv_t)-1 && - (error = path_iconv(nfd2nfc, &nfc_path, &de_path, &de_len)) < 0) + if ((error = git_path_iconv(&ic, &de_path, &de_len)) < 0) break; -#endif alloc_size = path_len + need_slash + de_len + 1 + alloc_extra; if ((entry_path = git__calloc(alloc_size, 1)) == NULL) { @@ -924,12 +918,7 @@ int git_path_dirload( } closedir(dir); - -#ifdef __APPLE__ - if (nfd2nfc != (iconv_t)-1) - iconv_close(nfd2nfc); - git_buf_free(&nfc_path); -#endif + git_path_iconv_clear(&ic); if (error != 0) giterr_set(GITERR_OS, "Failed to process directory entry in '%s'", path); diff --git a/src/path.h b/src/path.h index 534cfe50b..2cfd714cd 100644 --- a/src/path.h +++ b/src/path.h @@ -358,4 +358,56 @@ extern int git_path_dirload_with_stat( const char *end_stat, git_vector *contents); +/* check if non-ascii characters are present in filename */ +extern bool git_path_has_non_ascii(const char *path, size_t pathlen); + +/* only enable iconv on Mac for now */ +#ifdef __APPLE__ +#define GIT_USE_ICONV 1 +#endif + +#define GIT_PATH_REPO_ENCODING "UTF-8" + +#ifdef __APPLE__ +#define GIT_PATH_NATIVE_ENCODING "UTF-8-MAC" +#else +#define GIT_PATH_NATIVE_ENCODING "UTF-8" +#endif + +#ifdef GIT_USE_ICONV + +#include + +typedef struct { + iconv_t map; + git_buf buf; +} git_path_iconv_t; + +#define GIT_PATH_ICONV_INIT { (iconv_t)-1, GIT_BUF_INIT } + +/* Init iconv data for converting decomposed UTF-8 to precomposed */ +extern int git_path_iconv_init_precompose(git_path_iconv_t *ic); + +/* Clear allocated iconv data */ +extern void git_path_iconv_clear(git_path_iconv_t *ic); + +/* + * Rewrite `in` buffer using iconv map if necessary, replacing `in` + * pointer internal iconv buffer if rewrite happened. The `in` pointer + * will be left unchanged if no rewrite was needed. + */ +extern int git_path_iconv(git_path_iconv_t *ic, char **in, size_t *inlen); + +#else + +typedef struct { + int unused; +} git_path_iconv_t; +#define GIT_PATH_ICONV_INIT { 0 } +#define git_path_iconv_init_precompose(X) 0 +#define git_path_iconv_clear(X) (void)(X) +#define git_path_iconv(X,Y,Z) 0 + +#endif /* GIT_USE_ICONV */ + #endif diff --git a/tests-clar/core/iconv.c b/tests-clar/core/iconv.c new file mode 100644 index 000000000..5a3e1dee0 --- /dev/null +++ b/tests-clar/core/iconv.c @@ -0,0 +1,57 @@ +#include "clar_libgit2.h" +#include "path.h" + +static git_path_iconv_t ic; +static char *nfc = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D"; +static char *nfd = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D"; + +void test_core_iconv__initialize(void) +{ + cl_git_pass(git_path_iconv_init_precompose(&ic)); +} + +void test_core_iconv__cleanup(void) +{ + git_path_iconv_clear(&ic); +} + +void test_core_iconv__unchanged(void) +{ + char *data = "Ascii data", *original = data; + size_t datalen = strlen(data); + + cl_git_pass(git_path_iconv(&ic, &data, &datalen)); + + /* There are no high bits set, so this should leave data untouched */ + cl_assert(data == original); +} + +void test_core_iconv__decomposed_to_precomposed(void) +{ + char *data = nfd; + size_t datalen = strlen(nfd); + + cl_git_pass(git_path_iconv(&ic, &data, &datalen)); + + /* The decomposed nfd string should be transformed to the nfc form + * (on platforms where iconv is enabled, of course). + */ +#ifdef GIT_USE_ICONV + cl_assert_equal_s(nfc, data); +#else + cl_assert_equal_s(nfd, data); +#endif +} + +void test_core_iconv__precomposed_is_unmodified(void) +{ + char *data = nfc; + size_t datalen = strlen(nfc); + + cl_git_pass(git_path_iconv(&ic, &data, &datalen)); + + /* data is already in precomposed form, so even though some bytes have + * the high-bit set, the iconv transform should result in no change. + */ + cl_assert_equal_s(nfc, data); +} diff --git a/tests-clar/core/path.c b/tests-clar/core/path.c index e584d6115..cf2d5e944 100644 --- a/tests-clar/core/path.c +++ b/tests-clar/core/path.c @@ -1,5 +1,5 @@ #include "clar_libgit2.h" -#include +#include "fileops.h" static void check_dirname(const char *A, const char *B) -- cgit v1.2.1 From af302acaee95ff2ca3379b93cd886ebe96adff10 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 2 Oct 2013 14:13:11 -0700 Subject: Clean up annoying warnings The indexer code was generating warnings on Windows 64-bit. I looked closely at the logic and was able to simplify it a bit. Also this fixes some other Windows and Linux warnings. --- src/indexer.c | 10 +++++----- src/repository.c | 6 +++++- tests-clar/core/iconv.c | 3 +++ tests-clar/online/push.c | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index 4ce69fc8d..1270488f0 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -50,7 +50,7 @@ struct git_indexer_stream { /* Fields for calculating the packfile trailer (hash of everything before it) */ char inbuf[GIT_OID_RAWSZ]; - int inbuf_len; + size_t inbuf_len; git_hash_ctx trailer; }; @@ -378,13 +378,13 @@ static int do_progress_callback(git_indexer_stream *idx, git_transfer_progress * /* Hash everything but the last 20B of input */ static void hash_partially(git_indexer_stream *idx, const uint8_t *data, size_t size) { - int to_expell, to_keep; + size_t to_expell, to_keep; if (size == 0) return; /* Easy case, dump the buffer and the data minus the last 20 bytes */ - if (size >= 20) { + if (size >= GIT_OID_RAWSZ) { git_hash_update(&idx->trailer, idx->inbuf, idx->inbuf_len); git_hash_update(&idx->trailer, data, size - GIT_OID_RAWSZ); @@ -402,8 +402,8 @@ static void hash_partially(git_indexer_stream *idx, const uint8_t *data, size_t } /* We need to partially drain the buffer and then append */ - to_expell = abs(size - (GIT_OID_RAWSZ - idx->inbuf_len)); - to_keep = abs(idx->inbuf_len - to_expell); + to_keep = GIT_OID_RAWSZ - size; + to_expell = idx->inbuf_len - to_keep; git_hash_update(&idx->trailer, idx->inbuf, to_expell); diff --git a/src/repository.c b/src/repository.c index 64f13978d..51cc76db4 100644 --- a/src/repository.c +++ b/src/repository.c @@ -890,6 +890,8 @@ static bool are_symlinks_supported(const char *wd_path) return symlinks_supported; } +#ifdef GIT_USE_ICONV + static const char *nfc_file = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D.XXXXXX"; static const char *nfd_file = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D.XXXXXX"; @@ -938,6 +940,8 @@ fail: return need_precompose; } +#endif + static int create_empty_file(const char *path, mode_t mode) { int fd; @@ -994,7 +998,7 @@ static int repo_init_config( SET_REPO_CONFIG( bool, "core.filemode", is_chmod_supported(git_buf_cstr(&cfg_path))); -#if __APPLE__ +#ifdef GIT_USE_ICONV SET_REPO_CONFIG( bool, "core.precomposeunicode", should_precompose_unicode_paths(is_bare ? repo_dir : work_dir)); diff --git a/tests-clar/core/iconv.c b/tests-clar/core/iconv.c index 5a3e1dee0..73bc99a23 100644 --- a/tests-clar/core/iconv.c +++ b/tests-clar/core/iconv.c @@ -21,6 +21,7 @@ void test_core_iconv__unchanged(void) size_t datalen = strlen(data); cl_git_pass(git_path_iconv(&ic, &data, &datalen)); + GIT_UNUSED(datalen); /* There are no high bits set, so this should leave data untouched */ cl_assert(data == original); @@ -32,6 +33,7 @@ void test_core_iconv__decomposed_to_precomposed(void) size_t datalen = strlen(nfd); cl_git_pass(git_path_iconv(&ic, &data, &datalen)); + GIT_UNUSED(datalen); /* The decomposed nfd string should be transformed to the nfc form * (on platforms where iconv is enabled, of course). @@ -49,6 +51,7 @@ void test_core_iconv__precomposed_is_unmodified(void) size_t datalen = strlen(nfc); cl_git_pass(git_path_iconv(&ic, &data, &datalen)); + GIT_UNUSED(datalen); /* data is already in precomposed form, so even though some bytes have * the high-bit set, the iconv transform should result in no change. diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 4c2bec7ca..957cef7ca 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -356,7 +356,7 @@ static int push_pack_progress_cb(int stage, unsigned int current, unsigned int t static int push_transfer_progress_cb(unsigned int current, unsigned int total, size_t bytes, void* payload) { int *was_called = (int *) payload; - GIT_UNUSED(current); GIT_UNUSED(total); GIT_UNUSED(bytes); + GIT_UNUSED(current); GIT_UNUSED(total); GIT_UNUSED(bytes); *was_called = 1; return 0; } -- cgit v1.2.1 From 840fb4fc4346580a6398856b3fa2f1226b3a365d Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 3 Oct 2013 14:42:37 -0700 Subject: Update repo init with fewer platform assumptions The repo init code was assuming Windows == no filemode, and Mac or Windows == no case sensitivity. Those assumptions are not consistently true depending on the mounted file system. This is a first step to removing those assumptions. It focuses on the repo init code and the tests of that code. There are still many other tests that are broken when those assumptions don't hold true, but this clears up one area of the code. Also, this moves the core.precomposeunicode logic to be closer to the current logic in core Git where it will be set to true on any filesystem where composed unicode is decomposed when read back. --- src/repository.c | 34 ++++++++++--------- tests-clar/repo/init.c | 92 ++++++++++++++++++++++++++------------------------ 2 files changed, 66 insertions(+), 60 deletions(-) diff --git a/src/repository.c b/src/repository.c index 51cc76db4..f609e5779 100644 --- a/src/repository.c +++ b/src/repository.c @@ -895,18 +895,20 @@ static bool are_symlinks_supported(const char *wd_path) static const char *nfc_file = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D.XXXXXX"; static const char *nfd_file = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D.XXXXXX"; -/* On Mac, HDFS always stores files using decomposed unicode, but when - * writing to VFAT or SAMBA file systems, filenames may be kept as - * precomposed unicode, but will be converted to decomposed form when - * reading the directory entries. This can cause file name mismatches. - * The solution is to convert directory entries to precomposed form if we - * cannot look up the file from the decomposed path. +/* Check if the platform is decomposing unicode data for us. We will + * emulate core Git and prefer to use precomposed unicode data internally + * on these platforms, composing the decomposed unicode on the fly. + * + * This mainly happens on the Mac where HDFS stores filenames as + * decomposed unicode. Even on VFAT and SAMBA file systems, the Mac will + * return decomposed unicode from readdir() even when the actual + * filesystem is storing precomposed unicode. */ -static bool should_precompose_unicode_paths(const char *wd_path) +static bool does_fs_decompose_unicode_paths(const char *wd_path) { git_buf path = GIT_BUF_INIT; int fd; - bool need_precompose = false; + bool found_decomposed = false; char tmp[6]; /* Create a file using a precomposed path and then try to find it @@ -915,7 +917,7 @@ static bool should_precompose_unicode_paths(const char *wd_path) */ if (git_buf_joinpath(&path, wd_path, nfc_file) < 0 || (fd = p_mkstemp(path.ptr)) < 0) - goto fail; + goto done; p_close(fd); /* record trailing digits generated by mkstemp */ @@ -923,21 +925,21 @@ static bool should_precompose_unicode_paths(const char *wd_path) /* try to look up as NFD path */ if (git_buf_joinpath(&path, wd_path, nfd_file) < 0) - goto fail; + goto done; memcpy(path.ptr + path.size - sizeof(tmp), tmp, sizeof(tmp)); - need_precompose = !git_path_exists(path.ptr); + found_decomposed = git_path_exists(path.ptr); - /* remove temporary file */ + /* remove temporary file (using original precomposed path) */ if (git_buf_joinpath(&path, wd_path, nfc_file) < 0) - goto fail; + goto done; memcpy(path.ptr + path.size - sizeof(tmp), tmp, sizeof(tmp)); (void)p_unlink(path.ptr); -fail: +done: git_buf_free(&path); - return need_precompose; + return found_decomposed; } #endif @@ -1001,7 +1003,7 @@ static int repo_init_config( #ifdef GIT_USE_ICONV SET_REPO_CONFIG( bool, "core.precomposeunicode", - should_precompose_unicode_paths(is_bare ? repo_dir : work_dir)); + does_fs_decompose_unicode_paths(is_bare ? repo_dir : work_dir)); #endif if (!are_symlinks_supported(is_bare ? repo_dir : work_dir)) diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index 6f3c84175..061e444b5 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -179,41 +179,32 @@ void test_repo_init__additional_templates(void) git_buf_free(&path); } -static void assert_config_entry_on_init_bytype(const char *config_key, int expected_value, bool is_bare) +static void assert_config_entry_on_init_bytype( + const char *config_key, int expected_value, bool is_bare) { git_config *config; - int current_value; - git_buf repo_path = GIT_BUF_INIT; + int error, current_value; + const char *repo_path = is_bare ? + "config_entry/test.bare.git" : "config_entry/test.non.bare.git"; cl_set_cleanup(&cleanup_repository, "config_entry"); - cl_git_pass(git_buf_puts(&repo_path, "config_entry/test.")); - - if (!is_bare) - cl_git_pass(git_buf_puts(&repo_path, "non.")); - - cl_git_pass(git_buf_puts(&repo_path, "bare.git")); - - cl_git_pass(git_repository_init(&_repo, git_buf_cstr(&repo_path), is_bare)); - - git_buf_free(&repo_path); + cl_git_pass(git_repository_init(&_repo, repo_path, is_bare)); - git_repository_config(&config, _repo); + cl_git_pass(git_repository_config(&config, _repo)); + error = git_config_get_bool(¤t_value, config, config_key); + git_config_free(config); if (expected_value >= 0) { - cl_git_pass(git_config_get_bool(¤t_value, config, config_key)); - + cl_assert_equal_i(0, error); cl_assert_equal_i(expected_value, current_value); } else { - int error = git_config_get_bool(¤t_value, config, config_key); - cl_assert_equal_i(expected_value, error); } - - git_config_free(config); } -static void assert_config_entry_on_init(const char *config_key, int expected_value) +static void assert_config_entry_on_init( + const char *config_key, int expected_value) { assert_config_entry_on_init_bytype(config_key, expected_value, true); git_repository_free(_repo); @@ -221,31 +212,47 @@ static void assert_config_entry_on_init(const char *config_key, int expected_val assert_config_entry_on_init_bytype(config_key, expected_value, false); } -void test_repo_init__detect_filemode(void) +static int expect_filemode_support(void) { -#ifdef GIT_WIN32 - assert_config_entry_on_init("core.filemode", false); -#else - assert_config_entry_on_init("core.filemode", true); -#endif + struct stat st; + + cl_git_write2file("testmode", "whatever\n", 0, O_CREAT | O_WRONLY, 0767); + cl_must_pass(p_stat("testmode", &st)); + cl_must_pass(p_unlink("testmode")); + + return (st.st_mode & 0111) == 0101; } -#define CASE_INSENSITIVE_FILESYSTEM (defined GIT_WIN32 || defined __APPLE__) +void test_repo_init__detect_filemode(void) +{ + assert_config_entry_on_init("core.filemode", expect_filemode_support()); +} void test_repo_init__detect_ignorecase(void) { -#if CASE_INSENSITIVE_FILESYSTEM - assert_config_entry_on_init("core.ignorecase", true); -#else - assert_config_entry_on_init("core.ignorecase", GIT_ENOTFOUND); -#endif + struct stat st; + bool found_without_match; + + cl_git_write2file("testCAPS", "whatever\n", 0, O_CREAT | O_WRONLY, 0666); + found_without_match = (p_stat("Testcaps", &st) == 0); + cl_must_pass(p_unlink("testCAPS")); + + assert_config_entry_on_init( + "core.ignorecase", found_without_match ? true : GIT_ENOTFOUND); } void test_repo_init__detect_precompose_unicode_required(void) { -#ifdef __APPLE__ - /* hard to test "true" case without SAMBA or VFAT file system available */ - assert_config_entry_on_init("core.precomposeunicode", false); + char *composed = "ḱṷṓn", *decomposed = "ḱṷṓn"; + struct stat st; + bool found_with_nfd; + + cl_git_write2file(composed, "whatever\n", 0, O_CREAT | O_WRONLY, 0666); + found_with_nfd = (p_stat(decomposed, &st) == 0); + cl_must_pass(p_unlink(composed)); + +#ifdef GIT_USE_ICONV + assert_config_entry_on_init("core.precomposeunicode", found_with_nfd); #else assert_config_entry_on_init("core.precomposeunicode", GIT_ENOTFOUND); #endif @@ -280,13 +287,7 @@ void test_repo_init__reinit_doesnot_overwrite_ignorecase(void) void test_repo_init__reinit_overwrites_filemode(void) { - int expected, current_value; - -#ifdef GIT_WIN32 - expected = false; -#else - expected = true; -#endif + int expected = expect_filemode_support(), current_value; /* Init a new repo */ cl_set_cleanup(&cleanup_repository, "overwrite.git"); @@ -358,7 +359,10 @@ void test_repo_init__extended_1(void) cl_git_pass(git_path_lstat(git_repository_path(_repo), &st)); cl_assert(S_ISDIR(st.st_mode)); - cl_assert((S_ISGID & st.st_mode) == S_ISGID); + if (expect_filemode_support()) + cl_assert((S_ISGID & st.st_mode) == S_ISGID); + else + cl_assert((S_ISGID & st.st_mode) == 0); cl_git_pass(git_reference_lookup(&ref, _repo, "HEAD")); cl_assert(git_reference_type(ref) == GIT_REF_SYMBOLIC); -- cgit v1.2.1 From b8f9059d6330d1b0113910eb4c6f049ea5a150a4 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 3 Oct 2013 15:16:06 -0700 Subject: More cleanups to remove WIN assumptions This cleans up more of the test suite to check actual filesystem behavior instead of relying on Windows vs. Mac vs. Linux to test. --- tests-clar/checkout/index.c | 10 ++++++---- tests-clar/core/mkdir.c | 20 +++++++++++++------- tests-clar/repo/init.c | 17 +++-------------- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/tests-clar/checkout/index.c b/tests-clar/checkout/index.c index 73050d08e..48d6d79f9 100644 --- a/tests-clar/checkout/index.c +++ b/tests-clar/checkout/index.c @@ -224,13 +224,15 @@ void test_checkout_index__options_disable_filters(void) void test_checkout_index__options_dir_modes(void) { -#ifndef GIT_WIN32 git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; struct stat st; git_oid oid; git_commit *commit; mode_t um; + if (!cl_is_chmod_supported()) + return; + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); @@ -252,15 +254,16 @@ void test_checkout_index__options_dir_modes(void) cl_assert_equal_i_fmt(st.st_mode, GIT_FILEMODE_BLOB_EXECUTABLE, "%07o"); git_commit_free(commit); -#endif } void test_checkout_index__options_override_file_modes(void) { -#ifndef GIT_WIN32 git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; struct stat st; + if (!cl_is_chmod_supported()) + return; + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; opts.file_mode = 0700; @@ -268,7 +271,6 @@ void test_checkout_index__options_override_file_modes(void) cl_git_pass(p_stat("./testrepo/new.txt", &st)); cl_assert_equal_i_fmt(st.st_mode & GIT_MODE_PERMS_MASK, 0700, "%07o"); -#endif } void test_checkout_index__options_open_flags(void) diff --git a/tests-clar/core/mkdir.c b/tests-clar/core/mkdir.c index a969e4de2..a8c5b10ae 100644 --- a/tests-clar/core/mkdir.c +++ b/tests-clar/core/mkdir.c @@ -111,14 +111,20 @@ static void cleanup_chmod_root(void *ref) git_futils_rmdir_r("r", NULL, GIT_RMDIR_EMPTY_HIERARCHY); } -static void check_mode(mode_t expected, mode_t actual) +#define check_mode(X,A) check_mode_at_line((X), (A), __FILE__, __LINE__) + +static void check_mode_at_line( + mode_t expected, mode_t actual, const char *file, int line) { -#ifdef GIT_WIN32 - /* chmod on Win32 doesn't support exec bit, not group/world bits */ - cl_assert_equal_i_fmt((expected & 0600), (actual & 0777), "%07o"); -#else - cl_assert_equal_i_fmt(expected, (actual & 0777), "%07o"); -#endif + /* FAT filesystems don't support exec bit, nor group/world bits */ + if (!cl_is_chmod_supported()) { + expected &= 0600; + actual &= 0600; + } + + clar__assert_equal( + file, line, "expected_mode != actual_mode", 1, + "%07o", (int)expected, (int)(actual & 0777)); } void test_core_mkdir__chmods(void) diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index 061e444b5..617fdf879 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -212,20 +212,9 @@ static void assert_config_entry_on_init( assert_config_entry_on_init_bytype(config_key, expected_value, false); } -static int expect_filemode_support(void) -{ - struct stat st; - - cl_git_write2file("testmode", "whatever\n", 0, O_CREAT | O_WRONLY, 0767); - cl_must_pass(p_stat("testmode", &st)); - cl_must_pass(p_unlink("testmode")); - - return (st.st_mode & 0111) == 0101; -} - void test_repo_init__detect_filemode(void) { - assert_config_entry_on_init("core.filemode", expect_filemode_support()); + assert_config_entry_on_init("core.filemode", cl_is_chmod_supported()); } void test_repo_init__detect_ignorecase(void) @@ -287,7 +276,7 @@ void test_repo_init__reinit_doesnot_overwrite_ignorecase(void) void test_repo_init__reinit_overwrites_filemode(void) { - int expected = expect_filemode_support(), current_value; + int expected = cl_is_chmod_supported(), current_value; /* Init a new repo */ cl_set_cleanup(&cleanup_repository, "overwrite.git"); @@ -359,7 +348,7 @@ void test_repo_init__extended_1(void) cl_git_pass(git_path_lstat(git_repository_path(_repo), &st)); cl_assert(S_ISDIR(st.st_mode)); - if (expect_filemode_support()) + if (cl_is_chmod_supported()) cl_assert((S_ISGID & st.st_mode) == S_ISGID); else cl_assert((S_ISGID & st.st_mode) == 0); -- cgit v1.2.1 From cf0582b43ce591e7923637d2c8925028aaa5977b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 2 Oct 2013 12:22:54 +0200 Subject: indexer: do multiple passes over the delta list Though unusual, a packfile may contain a delta whose base is a delta that comes later. In order index such a packfile, we must not give up on the first failure to resolve a delta, but keep it around. If there is a pass which makes no progress, this indicates that the packfile is broken, so fail accordingly. --- src/indexer.c | 42 ++++++++++++++++++++++++++++++------------ tests-clar/pack/indexer.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 12 deletions(-) create mode 100644 tests-clar/pack/indexer.c diff --git a/src/indexer.c b/src/indexer.c index 3b160df5d..10b6929ee 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -594,20 +594,38 @@ static int resolve_deltas(git_indexer_stream *idx, git_transfer_progress *stats) { unsigned int i; struct delta_info *delta; + int progressed = 0; + + while (idx->deltas.length > 0) { + progressed = 0; + git_vector_foreach(&idx->deltas, i, delta) { + git_rawobj obj; + + idx->off = delta->delta_off; + if (git_packfile_unpack(&obj, idx->pack, &idx->off) < 0) + continue; + + if (hash_and_save(idx, &obj, delta->delta_off) < 0) + continue; + + git__free(obj.data); + stats->indexed_objects++; + progressed = 1; + do_progress_callback(idx, stats); + + /* + * Remove this delta from the list and + * decrease i so we don't skip over the next + * delta. + */ + git_vector_remove(&idx->deltas, i); + i--; + } - git_vector_foreach(&idx->deltas, i, delta) { - git_rawobj obj; - - idx->off = delta->delta_off; - if (git_packfile_unpack(&obj, idx->pack, &idx->off) < 0) - return -1; - - if (hash_and_save(idx, &obj, delta->delta_off) < 0) + if (!progressed) { + giterr_set(GITERR_INDEXER, "the packfile is missing bases"); return -1; - - git__free(obj.data); - stats->indexed_objects++; - do_progress_callback(idx, stats); + } } return 0; diff --git a/tests-clar/pack/indexer.c b/tests-clar/pack/indexer.c new file mode 100644 index 000000000..5394d32fd --- /dev/null +++ b/tests-clar/pack/indexer.c @@ -0,0 +1,40 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "hash.h" +#include "iterator.h" +#include "vector.h" +#include "posix.h" + +/* + * This is a packfile with three objects. The second is a delta which + * depends on the third, which is also a delta. + */ +unsigned char out_of_order_pack[] = { + 0x50, 0x41, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, + 0x32, 0x78, 0x9c, 0x63, 0x67, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x76, + 0xe6, 0x8f, 0xe8, 0x12, 0x9b, 0x54, 0x6b, 0x10, 0x1a, 0xee, 0x95, 0x10, + 0xc5, 0x32, 0x8e, 0x7f, 0x21, 0xca, 0x1d, 0x18, 0x78, 0x9c, 0x63, 0x62, + 0x66, 0x4e, 0xcb, 0xcf, 0x07, 0x00, 0x02, 0xac, 0x01, 0x4d, 0x75, 0x01, + 0xd7, 0x71, 0x36, 0x66, 0xf4, 0xde, 0x82, 0x27, 0x76, 0xc7, 0x62, 0x2c, + 0x10, 0xf1, 0xb0, 0x7d, 0xe2, 0x80, 0xdc, 0x78, 0x9c, 0x63, 0x62, 0x62, + 0x62, 0xb7, 0x03, 0x00, 0x00, 0x69, 0x00, 0x4c, 0xde, 0x7d, 0xaa, 0xe4, + 0x19, 0x87, 0x58, 0x80, 0x61, 0x09, 0x9a, 0x33, 0xca, 0x7a, 0x31, 0x92, + 0x6f, 0xae, 0x66, 0x75 +}; +unsigned int out_of_order_pack_len = 112; + +void test_pack_indexer__out_of_order(void) +{ + git_indexer_stream *idx; + git_transfer_progress stats; + + cl_git_pass(git_indexer_stream_new(&idx, ".", NULL, NULL, NULL)); + cl_git_pass(git_indexer_stream_add(idx, out_of_order_pack, out_of_order_pack_len, &stats)); + cl_git_pass(git_indexer_stream_finalize(idx, &stats)); + + cl_assert_equal_i(stats.total_objects, 3); + cl_assert_equal_i(stats.received_objects, 3); + cl_assert_equal_i(stats.indexed_objects, 3); + + git_indexer_stream_free(idx); +} -- cgit v1.2.1 From 51e82492ef5206767e176952733914275d0e3bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 3 Oct 2013 16:54:25 +0200 Subject: pack: move the object header function here --- src/pack-objects.c | 36 +----------------------------------- src/pack.c | 32 ++++++++++++++++++++++++++++++++ src/pack.h | 2 ++ 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/pack-objects.c b/src/pack-objects.c index 2a2f36223..4d79ad95b 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -228,40 +228,6 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, return 0; } -/* - * The per-object header is a pretty dense thing, which is - * - first byte: low four bits are "size", - * then three bits of "type", - * with the high bit being "size continues". - * - each byte afterwards: low seven bits are size continuation, - * with the high bit being "size continues" - */ -static int gen_pack_object_header( - unsigned char *hdr, - unsigned long size, - git_otype type) -{ - unsigned char *hdr_base; - unsigned char c; - - assert(type >= GIT_OBJ_COMMIT && type <= GIT_OBJ_REF_DELTA); - - /* TODO: add support for chunked objects; see git.git 6c0d19b1 */ - - c = (unsigned char)((type << 4) | (size & 15)); - size >>= 4; - hdr_base = hdr; - - while (size) { - *hdr++ = c | 0x80; - c = size & 0x7f; - size >>= 7; - } - *hdr++ = c; - - return (int)(hdr - hdr_base); -} - static int get_delta(void **out, git_odb *odb, git_pobject *po) { git_odb_object *src = NULL, *trg = NULL; @@ -323,7 +289,7 @@ static int write_object(git_buf *buf, git_packbuilder *pb, git_pobject *po) } /* Write header */ - hdr_len = gen_pack_object_header(hdr, size, type); + hdr_len = git_packfile__object_header(hdr, size, type); if (git_buf_put(buf, (char *)hdr, hdr_len) < 0) goto on_error; diff --git a/src/pack.c b/src/pack.c index e7fb9f1ae..5df0f50b9 100644 --- a/src/pack.c +++ b/src/pack.c @@ -364,6 +364,38 @@ static unsigned char *pack_window_open( return git_mwindow_open(&p->mwf, w_cursor, offset, 20, left); } +/* + * The per-object header is a pretty dense thing, which is + * - first byte: low four bits are "size", + * then three bits of "type", + * with the high bit being "size continues". + * - each byte afterwards: low seven bits are size continuation, + * with the high bit being "size continues" + */ +int git_packfile__object_header(unsigned char *hdr, unsigned long size, git_otype type) +{ + unsigned char *hdr_base; + unsigned char c; + + assert(type >= GIT_OBJ_COMMIT && type <= GIT_OBJ_REF_DELTA); + + /* TODO: add support for chunked objects; see git.git 6c0d19b1 */ + + c = (unsigned char)((type << 4) | (size & 15)); + size >>= 4; + hdr_base = hdr; + + while (size) { + *hdr++ = c | 0x80; + c = size & 0x7f; + size >>= 7; + } + *hdr++ = c; + + return (int)(hdr - hdr_base); +} + + static int packfile_unpack_header1( unsigned long *usedp, size_t *sizep, diff --git a/src/pack.h b/src/pack.h index aeeac9ce1..ddeefea1d 100644 --- a/src/pack.h +++ b/src/pack.h @@ -112,6 +112,8 @@ typedef struct git_packfile_stream { git_mwindow *mw; } git_packfile_stream; +int git_packfile__object_header(unsigned char *hdr, unsigned long size, git_otype type); + int git_packfile_unpack_header( size_t *size_p, git_otype *type_p, -- cgit v1.2.1 From 34b8eafcaea7fc12f91691195c9b7289038c4abb Mon Sep 17 00:00:00 2001 From: nulltoken Date: Fri, 4 Oct 2013 11:36:40 +0200 Subject: Tabify indentations --- tests-clar/index/tests.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests-clar/index/tests.c b/tests-clar/index/tests.c index 9090d4d8a..0528eb110 100644 --- a/tests-clar/index/tests.c +++ b/tests-clar/index/tests.c @@ -99,11 +99,11 @@ void test_index_tests__default_test_index(void) entries = (git_index_entry **)index->entries.contents; for (i = 0; i < ARRAY_SIZE(test_entries); ++i) { - git_index_entry *e = entries[test_entries[i].index]; + git_index_entry *e = entries[test_entries[i].index]; - cl_assert_equal_s(e->path, test_entries[i].path); - cl_assert(e->mtime.seconds == test_entries[i].mtime); - cl_assert(e->file_size == test_entries[i].file_size); + cl_assert_equal_s(e->path, test_entries[i].path); + cl_assert(e->mtime.seconds == test_entries[i].mtime); + cl_assert(e->file_size == test_entries[i].file_size); } git_index_free(index); @@ -131,10 +131,10 @@ void test_index_tests__find_in_existing(void) cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); for (i = 0; i < ARRAY_SIZE(test_entries); ++i) { - size_t idx; + size_t idx; - cl_assert(!git_index_find(&idx, index, test_entries[i].path)); - cl_assert(idx == test_entries[i].index); + cl_assert(!git_index_find(&idx, index, test_entries[i].path)); + cl_assert(idx == test_entries[i].index); } git_index_free(index); @@ -148,7 +148,7 @@ void test_index_tests__find_in_empty(void) cl_git_pass(git_index_open(&index, "fake-index")); for (i = 0; i < ARRAY_SIZE(test_entries); ++i) { - cl_assert(GIT_ENOTFOUND == git_index_find(NULL, index, test_entries[i].path)); + cl_assert(GIT_ENOTFOUND == git_index_find(NULL, index, test_entries[i].path)); } git_index_free(index); -- cgit v1.2.1 From 6445ae994c8be706c58e441c1af2cddd0632b96e Mon Sep 17 00:00:00 2001 From: nulltoken Date: Fri, 4 Oct 2013 13:49:26 +0200 Subject: index: Enhance documentation --- include/git2/index.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/git2/index.h b/include/git2/index.h index 131d04945..8064a62ff 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -225,6 +225,9 @@ GIT_EXTERN(int) git_index_set_caps(git_index *index, unsigned int caps); * Update the contents of an existing index object in memory * by reading from the hard disk. * + * If the file doesn't exist on the filesystem, the index + * will be cleared from its current content. + * * @param index an existing index object * @return 0 or an error code */ -- cgit v1.2.1 From 0b33fca03e030c7e807f0c75d7332e7fe2d3c0bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 2 Oct 2013 13:39:35 +0200 Subject: indexer: fix thin packs When given an ODB from which to read objects, the indexer will attempt to inject the missing bases at the end of the pack and update the header and trailer to reflect the new contents. --- examples/network/index-pack.c | 2 +- include/git2/indexer.h | 4 + include/git2/sys/odb_backend.h | 2 +- include/git2/types.h | 1 + src/indexer.c | 276 +++++++++++++++++++++++++++++++++++------ src/odb.c | 2 +- src/odb_pack.c | 3 +- src/pack-objects.c | 2 +- tests-clar/pack/indexer.c | 88 +++++++++++++ tests-clar/pack/packbuilder.c | 4 +- 10 files changed, 340 insertions(+), 44 deletions(-) diff --git a/examples/network/index-pack.c b/examples/network/index-pack.c index 889305da8..08b45c58c 100644 --- a/examples/network/index-pack.c +++ b/examples/network/index-pack.c @@ -46,7 +46,7 @@ int index_pack(git_repository *repo, int argc, char **argv) return EXIT_FAILURE; } - if (git_indexer_stream_new(&idx, ".", NULL, NULL) < 0) { + if (git_indexer_stream_new(&idx, ".", NULL, NULL, NULL) < 0) { puts("bad idx"); return -1; } diff --git a/include/git2/indexer.h b/include/git2/indexer.h index 4db072c9b..0858b6ea1 100644 --- a/include/git2/indexer.h +++ b/include/git2/indexer.h @@ -20,12 +20,16 @@ typedef struct git_indexer_stream git_indexer_stream; * * @param out where to store the indexer instance * @param path to the directory where the packfile should be stored + * @param odb object database from which to read base objects when + * fixing thin packs. Pass NULL if no thin pack is expected (an error + * will be returned if there are bases missing) * @param progress_cb function to call with progress information * @param progress_cb_payload payload for the progress callback */ GIT_EXTERN(int) git_indexer_stream_new( git_indexer_stream **out, const char *path, + git_odb *odb, git_transfer_progress_callback progress_cb, void *progress_cb_payload); diff --git a/include/git2/sys/odb_backend.h b/include/git2/sys/odb_backend.h index 4365906d4..8039a5b82 100644 --- a/include/git2/sys/odb_backend.h +++ b/include/git2/sys/odb_backend.h @@ -80,7 +80,7 @@ struct git_odb_backend { git_odb_backend *, git_odb_foreach_cb cb, void *payload); int (* writepack)( - git_odb_writepack **, git_odb_backend *, + git_odb_writepack **, git_odb_backend *, git_odb *odb, git_transfer_progress_callback progress_cb, void *progress_payload); void (* free)(git_odb_backend *); diff --git a/include/git2/types.h b/include/git2/types.h index b500c986d..3939353ee 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -217,6 +217,7 @@ typedef struct git_transfer_progress { unsigned int total_objects; unsigned int indexed_objects; unsigned int received_objects; + unsigned int local_objects; size_t received_bytes; } git_transfer_progress; diff --git a/src/indexer.c b/src/indexer.c index 10b6929ee..21b993a28 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -18,6 +18,7 @@ #include "filebuf.h" #include "oid.h" #include "oidmap.h" +#include "compress.h" #define UINT31_MAX (0x7FFFFFFF) @@ -33,6 +34,7 @@ struct git_indexer_stream { opened_pack :1, have_stream :1, have_delta :1; + struct git_pack_header hdr; struct git_pack_file *pack; git_filebuf pack_file; git_off_t off; @@ -48,6 +50,9 @@ struct git_indexer_stream { void *progress_payload; char objbuf[8*1024]; + /* Needed to look up objects which we want to inject to fix a thin pack */ + git_odb *odb; + /* Fields for calculating the packfile trailer (hash of everything before it) */ char inbuf[GIT_OID_RAWSZ]; int inbuf_len; @@ -114,6 +119,7 @@ static int objects_cmp(const void *a, const void *b) int git_indexer_stream_new( git_indexer_stream **out, const char *prefix, + git_odb *odb, git_transfer_progress_callback progress_cb, void *progress_payload) { @@ -124,6 +130,7 @@ int git_indexer_stream_new( idx = git__calloc(1, sizeof(git_indexer_stream)); GITERR_CHECK_ALLOC(idx); + idx->odb = odb; idx->progress_cb = progress_cb; idx->progress_payload = progress_payload; git_hash_ctx_init(&idx->trailer); @@ -309,17 +316,10 @@ on_error: return -1; } -static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t entry_start) +static int save_entry(git_indexer_stream *idx, struct entry *entry, struct git_pack_entry *pentry, git_off_t entry_start) { int i, error; khiter_t k; - git_oid oid; - size_t entry_size; - struct entry *entry; - struct git_pack_entry *pentry; - - entry = git__calloc(1, sizeof(*entry)); - GITERR_CHECK_ALLOC(entry); if (entry_start > UINT31_MAX) { entry->offset = UINT32_MAX; @@ -328,6 +328,34 @@ static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t ent entry->offset = (uint32_t)entry_start; } + pentry->offset = entry_start; + k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error); + if (!error) + return -1; + + kh_value(idx->pack->idx_cache, k) = pentry; + + /* Add the object to the list */ + if (git_vector_insert(&idx->objects, entry) < 0) + return -1; + + for (i = entry->oid.id[0]; i < 256; ++i) { + idx->fanout[i]++; + } + + return 0; +} + +static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t entry_start) +{ + git_oid oid; + size_t entry_size; + struct entry *entry; + struct git_pack_entry *pentry; + + entry = git__calloc(1, sizeof(*entry)); + GITERR_CHECK_ALLOC(entry); + if (git_odb__hashobj(&oid, obj) < 0) { giterr_set(GITERR_INDEXER, "Failed to hash object"); goto on_error; @@ -337,15 +365,6 @@ static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t ent GITERR_CHECK_ALLOC(pentry); git_oid_cpy(&pentry->sha1, &oid); - pentry->offset = entry_start; - k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error); - if (!error) { - git__free(pentry); - goto on_error; - } - - kh_value(idx->pack->idx_cache, k) = pentry; - git_oid_cpy(&entry->oid, &oid); entry->crc = crc32(0L, Z_NULL, 0); @@ -353,15 +372,7 @@ static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t ent if (crc_object(&entry->crc, &idx->pack->mwf, entry_start, entry_size) < 0) goto on_error; - /* Add the object to the list */ - if (git_vector_insert(&idx->objects, entry) < 0) - goto on_error; - - for (i = oid.id[0]; i < 256; ++i) { - idx->fanout[i]++; - } - - return 0; + return save_entry(idx, entry, pentry, entry_start); on_error: git__free(entry); @@ -415,8 +426,8 @@ static void hash_partially(git_indexer_stream *idx, const uint8_t *data, size_t int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_transfer_progress *stats) { int error = -1; - struct git_pack_header hdr; size_t processed; + struct git_pack_header *hdr = &idx->hdr; git_mwindow_file *mwf = &idx->pack->mwf; assert(idx && data && stats); @@ -443,14 +454,14 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz if (!idx->parsed_header) { unsigned int total_objects; - if ((unsigned)idx->pack->mwf.size < sizeof(hdr)) + if ((unsigned)idx->pack->mwf.size < sizeof(struct git_pack_header)) return 0; - if (parse_header(&hdr, idx->pack) < 0) + if (parse_header(&idx->hdr, idx->pack) < 0) return -1; idx->parsed_header = 1; - idx->nr_objects = ntohl(hdr.hdr_entries); + idx->nr_objects = ntohl(hdr->hdr_entries); idx->off = sizeof(struct git_pack_header); /* for now, limit to 2^32 objects */ @@ -471,6 +482,7 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz return -1; stats->received_objects = 0; + stats->local_objects = 0; processed = stats->indexed_objects = 0; stats->total_objects = total_objects; do_progress_callback(idx, stats); @@ -590,6 +602,135 @@ static int index_path_stream(git_buf *path, git_indexer_stream *idx, const char return git_buf_oom(path) ? -1 : 0; } +/** + * Rewind the packfile by the trailer, as we might need to fix the + * packfile by injecting objects at the tail and must overwrite it. + */ +static git_off_t seek_back_trailer(git_indexer_stream *idx) +{ + git_off_t off; + + if ((off = p_lseek(idx->pack_file.fd, -GIT_OID_RAWSZ, SEEK_CUR)) < 0) + return -1; + + idx->pack->mwf.size -= GIT_OID_RAWSZ; + git_mwindow_free_all(&idx->pack->mwf); + + return off; +} + +static int inject_object(git_indexer_stream *idx, git_oid *id) +{ + git_odb_object *obj; + struct entry *entry; + struct git_pack_entry *pentry; + git_oid foo = {{0}}; + unsigned char hdr[64]; + git_buf buf = GIT_BUF_INIT; + git_off_t entry_start; + const void *data; + size_t len, hdr_len; + int error; + + entry = git__calloc(1, sizeof(*entry)); + GITERR_CHECK_ALLOC(entry); + + entry_start = seek_back_trailer(idx); + + if (git_odb_read(&obj, idx->odb, id) < 0) + return -1; + + data = git_odb_object_data(obj); + len = git_odb_object_size(obj); + + entry->crc = crc32(0L, Z_NULL, 0); + + /* Write out the object header */ + hdr_len = git_packfile__object_header(hdr, len, git_odb_object_type(obj)); + git_filebuf_write(&idx->pack_file, hdr, hdr_len); + idx->pack->mwf.size += hdr_len; + entry->crc = crc32(entry->crc, hdr, hdr_len); + + if ((error = git__compress(&buf, data, len)) < 0) + goto cleanup; + + /* And then the compressed object */ + git_filebuf_write(&idx->pack_file, buf.ptr, buf.size); + idx->pack->mwf.size += buf.size; + entry->crc = htonl(crc32(entry->crc, (unsigned char *)buf.ptr, buf.size)); + git_buf_free(&buf); + + /* Write a fake trailer so the pack functions play ball */ + if ((error = git_filebuf_write(&idx->pack_file, &foo, GIT_OID_RAWSZ)) < 0) + goto cleanup; + + idx->pack->mwf.size += GIT_OID_RAWSZ; + + pentry = git__calloc(1, sizeof(struct git_pack_entry)); + GITERR_CHECK_ALLOC(pentry); + + git_oid_cpy(&pentry->sha1, id); + git_oid_cpy(&entry->oid, id); + idx->off = entry_start + hdr_len + len; + + if ((error = save_entry(idx, entry, pentry, entry_start)) < 0) + git__free(pentry); + +cleanup: + git_odb_object_free(obj); + return error; +} + +static int fix_thin_pack(git_indexer_stream *idx, git_transfer_progress *stats) +{ + int error; + unsigned int i; + struct delta_info *delta; + + if (idx->odb == NULL) { + giterr_set(GITERR_INDEXER, "cannot fix a thin pack without an ODB"); + return -1; + } + + git_vector_foreach(&idx->deltas, i, delta) { + size_t size; + git_otype type; + git_mwindow *w = NULL; + git_off_t curpos = delta->delta_off; + unsigned char *base_info; + unsigned int left = 0; + git_oid base; + + error = git_packfile_unpack_header(&size, &type, &idx->pack->mwf, &w, &curpos); + git_mwindow_close(&w); + if (error < 0) + return error; + + if (type != GIT_OBJ_REF_DELTA) { + giterr_set(GITERR_INDEXER, "delta with missing base is not REF_DELTA"); + return -1; + } + + /* curpos now points to the base information, which is an OID */ + base_info = git_mwindow_open(&idx->pack->mwf, &w, curpos, GIT_OID_RAWSZ, &left); + if (base_info == NULL) { + giterr_set(GITERR_INDEXER, "failed to map delta information"); + return -1; + } + + git_oid_fromraw(&base, base_info); + git_mwindow_close(&w); + + if (inject_object(idx, &base) < 0) + return -1; + + stats->total_objects++; + stats->local_objects++; + } + + return 0; +} + static int resolve_deltas(git_indexer_stream *idx, git_transfer_progress *stats) { unsigned int i; @@ -619,13 +760,61 @@ static int resolve_deltas(git_indexer_stream *idx, git_transfer_progress *stats) * delta. */ git_vector_remove(&idx->deltas, i); + git__free(delta); i--; } - if (!progressed) { - giterr_set(GITERR_INDEXER, "the packfile is missing bases"); + if (!progressed && (fix_thin_pack(idx, stats) < 0)) + return -1; + } + + return 0; +} + +static int update_header_and_rehash(git_indexer_stream *idx, git_transfer_progress *stats) +{ + void *ptr; + size_t chunk = 1024*1024; + git_off_t hashed = 0; + git_mwindow *w = NULL; + git_mwindow_file *mwf; + unsigned int left; + git_hash_ctx *ctx; + + mwf = &idx->pack->mwf; + ctx = &idx->trailer; + + git_hash_ctx_init(ctx); + git_mwindow_free_all(mwf); + + /* Update the header to include the numer of local objects we injected */ + idx->hdr.hdr_entries = htonl(stats->total_objects); + if (p_lseek(idx->pack_file.fd, 0, SEEK_SET) < 0) { + giterr_set(GITERR_OS, "failed to seek to the beginning of the pack"); + return -1; + } + + if (p_write(idx->pack_file.fd, &idx->hdr, sizeof(struct git_pack_header)) < 0) { + giterr_set(GITERR_OS, "failed to update the pack header"); + return -1; + } + + /* + * We now use the same technique as before to determine the + * hash. We keep reading up to the end and let + * hash_partially() keep the existing trailer out of the + * calculation. + */ + idx->inbuf_len = 0; + while (hashed < mwf->size) { + ptr = git_mwindow_open(mwf, &w, hashed, chunk, &left); + if (ptr == NULL) return -1; - } + + hash_partially(idx, ptr, left); + hashed += left; + + git_mwindow_close(&w); } return 0; @@ -668,15 +857,28 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * return -1; } - if (idx->deltas.length > 0) - if (resolve_deltas(idx, stats) < 0) - return -1; + if (resolve_deltas(idx, stats) < 0) + return -1; - if (stats->indexed_objects != stats->total_objects) { + if (stats->indexed_objects + stats->local_objects != stats->total_objects) { giterr_set(GITERR_INDEXER, "early EOF"); return -1; } + if (stats->local_objects > 0) { + if (update_header_and_rehash(idx, stats) < 0) + return -1; + + git_hash_final(&trailer_hash, &idx->trailer); + if (p_lseek(idx->pack_file.fd, -GIT_OID_RAWSZ, SEEK_END) < 0) + return -1; + + if (p_write(idx->pack_file.fd, &trailer_hash, GIT_OID_RAWSZ) < 0) { + giterr_set(GITERR_OS, "failed to update pack trailer"); + return -1; + } + } + git_vector_sort(&idx->objects); git_buf_sets(&filename, idx->pack->pack_name); diff --git a/src/odb.c b/src/odb.c index b2c138aae..0137641de 100644 --- a/src/odb.c +++ b/src/odb.c @@ -988,7 +988,7 @@ int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_transfer if (b->writepack != NULL) { ++writes; - error = b->writepack(out, b, progress_cb, progress_payload); + error = b->writepack(out, b, db, progress_cb, progress_payload); } } diff --git a/src/odb_pack.c b/src/odb_pack.c index cadc93a65..edf94c967 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -541,6 +541,7 @@ static void pack_backend__writepack_free(struct git_odb_writepack *_writepack) static int pack_backend__writepack(struct git_odb_writepack **out, git_odb_backend *_backend, + git_odb *odb, git_transfer_progress_callback progress_cb, void *progress_payload) { @@ -557,7 +558,7 @@ static int pack_backend__writepack(struct git_odb_writepack **out, GITERR_CHECK_ALLOC(writepack); if (git_indexer_stream_new(&writepack->indexer_stream, - backend->pack_folder, progress_cb, progress_payload) < 0) { + backend->pack_folder, odb, progress_cb, progress_payload) < 0) { git__free(writepack); return -1; } diff --git a/src/pack-objects.c b/src/pack-objects.c index 4d79ad95b..6a18d4be4 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -1253,7 +1253,7 @@ int git_packbuilder_write( PREPARE_PACK; if (git_indexer_stream_new( - &indexer, path, progress_cb, progress_cb_payload) < 0) + &indexer, path, pb->odb, progress_cb, progress_cb_payload) < 0) return -1; ctx.indexer = indexer; diff --git a/tests-clar/pack/indexer.c b/tests-clar/pack/indexer.c index 5394d32fd..fd1616034 100644 --- a/tests-clar/pack/indexer.c +++ b/tests-clar/pack/indexer.c @@ -1,10 +1,12 @@ #include "clar_libgit2.h" +#include #include "fileops.h" #include "hash.h" #include "iterator.h" #include "vector.h" #include "posix.h" + /* * This is a packfile with three objects. The second is a delta which * depends on the third, which is also a delta. @@ -23,6 +25,24 @@ unsigned char out_of_order_pack[] = { }; unsigned int out_of_order_pack_len = 112; +/* + * Packfile with two objects. The second is a delta against an object + * which is not in the packfile + */ +unsigned char thin_pack[] = { + 0x50, 0x41, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x32, 0x78, 0x9c, 0x63, 0x67, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x76, + 0xe6, 0x8f, 0xe8, 0x12, 0x9b, 0x54, 0x6b, 0x10, 0x1a, 0xee, 0x95, 0x10, + 0xc5, 0x32, 0x8e, 0x7f, 0x21, 0xca, 0x1d, 0x18, 0x78, 0x9c, 0x63, 0x62, + 0x66, 0x4e, 0xcb, 0xcf, 0x07, 0x00, 0x02, 0xac, 0x01, 0x4d, 0x42, 0x52, + 0x3a, 0x6f, 0x39, 0xd1, 0xfe, 0x66, 0x68, 0x6b, 0xa5, 0xe5, 0xe2, 0x97, + 0xac, 0x94, 0x6c, 0x76, 0x0b, 0x04 +}; +unsigned int thin_pack_len = 78; + +unsigned char base_obj[] = { 07, 076 }; +unsigned int base_obj_len = 2; + void test_pack_indexer__out_of_order(void) { git_indexer_stream *idx; @@ -38,3 +58,71 @@ void test_pack_indexer__out_of_order(void) git_indexer_stream_free(idx); } + +void test_pack_indexer__fix_thin(void) +{ + git_indexer_stream *idx; + git_transfer_progress stats; + git_repository *repo; + git_odb *odb; + git_oid id, should_id; + + cl_git_pass(git_repository_init(&repo, "thin.git", true)); + cl_git_pass(git_repository_odb(&odb, repo)); + + /* Store the missing base into your ODB so the indexer can fix the pack */ + cl_git_pass(git_odb_write(&id, odb, base_obj, base_obj_len, GIT_OBJ_BLOB)); + git_oid_fromstr(&should_id, "e68fe8129b546b101aee9510c5328e7f21ca1d18"); + cl_assert(!git_oid_cmp(&id, &should_id)); + + cl_git_pass(git_indexer_stream_new(&idx, ".", odb, NULL, NULL)); + cl_git_pass(git_indexer_stream_add(idx, thin_pack, thin_pack_len, &stats)); + cl_git_pass(git_indexer_stream_finalize(idx, &stats)); + + cl_assert_equal_i(stats.total_objects, 3); + cl_assert_equal_i(stats.received_objects, 2); + cl_assert_equal_i(stats.indexed_objects, 2); + cl_assert_equal_i(stats.local_objects, 1); + + git_oid_fromstr(&should_id, "11f0f69b334728fdd8bc86b80499f22f29d85b15"); + cl_assert(!git_oid_cmp(git_indexer_stream_hash(idx), &should_id)); + + git_indexer_stream_free(idx); + git_odb_free(odb); + git_repository_free(repo); + + /* + * The pack's name/hash only tells us what objects there are, + * so we need to go through the packfile again in order to + * figure out whether we calculated the trailer correctly. + */ + { + unsigned char buffer[128]; + int fd; + ssize_t read; + git_off_t left; + struct stat st; + const char *name = "pack-11f0f69b334728fdd8bc86b80499f22f29d85b15.pack"; + + fd = p_open(name, O_RDONLY); + cl_assert(fd != -1); + + cl_git_pass(p_stat(name, &st)); + left = st.st_size; + + cl_git_pass(git_indexer_stream_new(&idx, ".", NULL, NULL, NULL)); + read = p_read(fd, buffer, sizeof(buffer)); + cl_assert(read != -1); + p_close(fd); + + cl_git_pass(git_indexer_stream_add(idx, buffer, read, &stats)); + cl_git_pass(git_indexer_stream_finalize(idx, &stats)); + + cl_assert_equal_i(stats.total_objects, 3); + cl_assert_equal_i(stats.received_objects, 3); + cl_assert_equal_i(stats.indexed_objects, 3); + cl_assert_equal_i(stats.local_objects, 0); + + git_indexer_stream_free(idx); + } +} diff --git a/tests-clar/pack/packbuilder.c b/tests-clar/pack/packbuilder.c index 764fba213..69292567e 100644 --- a/tests-clar/pack/packbuilder.c +++ b/tests-clar/pack/packbuilder.c @@ -92,7 +92,7 @@ void test_pack_packbuilder__create_pack(void) seed_packbuilder(); - cl_git_pass(git_indexer_stream_new(&_indexer, ".", NULL, NULL)); + cl_git_pass(git_indexer_stream_new(&_indexer, ".", NULL, NULL, NULL)); cl_git_pass(git_packbuilder_foreach(_packbuilder, feed_indexer, &stats)); cl_git_pass(git_indexer_stream_finalize(_indexer, &stats)); @@ -141,7 +141,7 @@ void test_pack_packbuilder__foreach(void) git_indexer_stream *idx; seed_packbuilder(); - cl_git_pass(git_indexer_stream_new(&idx, ".", NULL, NULL)); + cl_git_pass(git_indexer_stream_new(&idx, ".", NULL, NULL, NULL)); cl_git_pass(git_packbuilder_foreach(_packbuilder, foreach_cb, idx)); cl_git_pass(git_indexer_stream_finalize(idx, &stats)); git_indexer_stream_free(idx); -- cgit v1.2.1 From b4342b116d98ba439d958c374eb4d49b06488f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 4 Oct 2013 10:27:45 +0200 Subject: net: advertise our support for fixing thin packs --- src/transports/smart.h | 4 +++- src/transports/smart_pkt.c | 3 +++ src/transports/smart_protocol.c | 6 ++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/transports/smart.h b/src/transports/smart.h index c52401a3c..5e31ebd92 100644 --- a/src/transports/smart.h +++ b/src/transports/smart.h @@ -21,6 +21,7 @@ #define GIT_CAP_INCLUDE_TAG "include-tag" #define GIT_CAP_DELETE_REFS "delete-refs" #define GIT_CAP_REPORT_STATUS "report-status" +#define GIT_CAP_THIN_PACK "thin-pack" enum git_pkt_type { GIT_PKT_CMD, @@ -116,7 +117,8 @@ typedef struct transport_smart_caps { side_band_64k:1, include_tag:1, delete_refs:1, - report_status:1; + report_status:1, + thin_pack:1; } transport_smart_caps; typedef void (*packetsize_cb)(size_t received, void *payload); diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c index 99da37567..a1f623c78 100644 --- a/src/transports/smart_pkt.c +++ b/src/transports/smart_pkt.c @@ -472,6 +472,9 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca if (caps->include_tag) git_buf_puts(&str, GIT_CAP_INCLUDE_TAG " "); + if (caps->thin_pack) + git_buf_puts(&str, GIT_CAP_THIN_PACK " "); + if (git_buf_oom(&str)) return -1; diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 156b69e1f..407101a81 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -128,6 +128,12 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps) continue; } + if (!git__prefixcmp(ptr, GIT_CAP_THIN_PACK)) { + caps->common = caps->thin_pack = 1; + ptr += strlen(GIT_CAP_THIN_PACK); + continue; + } + /* We don't know this capability, so skip it */ ptr = strchr(ptr, ' '); } -- cgit v1.2.1 From da7b78fa446b31e7e197d51129d9bd005acc69da Mon Sep 17 00:00:00 2001 From: nulltoken Date: Fri, 4 Oct 2013 14:03:12 +0200 Subject: index: Make _read() cope with index file creation --- src/index.c | 5 +++-- tests-clar/index/tests.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/index.c b/src/index.c index 21a8d31d1..c923f1675 100644 --- a/src/index.c +++ b/src/index.c @@ -461,9 +461,10 @@ int git_index_read(git_index *index) return create_index_error(-1, "Failed to read index: The index is in-memory only"); - if (!index->on_disk || git_path_exists(index->index_file_path) == false) { + index->on_disk = git_path_exists(index->index_file_path); + + if (!index->on_disk) { git_index_clear(index); - index->on_disk = 0; return 0; } diff --git a/tests-clar/index/tests.c b/tests-clar/index/tests.c index 0528eb110..009d393d7 100644 --- a/tests-clar/index/tests.c +++ b/tests-clar/index/tests.c @@ -484,3 +484,53 @@ void test_index_tests__elocked(void) git_index_free(index); git_repository_free(repo); } + +void test_index_tests__reload_from_disk(void) +{ + git_repository *repo; + git_index *read_index; + git_index *write_index; + + cl_set_cleanup(&cleanup_myrepo, NULL); + + cl_git_pass(git_futils_mkdir("./myrepo", NULL, 0777, GIT_MKDIR_PATH)); + cl_git_mkfile("./myrepo/a.txt", "a\n"); + cl_git_mkfile("./myrepo/b.txt", "b\n"); + + cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); + cl_git_pass(git_repository_index(&write_index, repo)); + cl_assert_equal_i(false, write_index->on_disk); + + cl_git_pass(git_index_open(&read_index, write_index->index_file_path)); + cl_assert_equal_i(false, read_index->on_disk); + + /* Stage two new files agaisnt the write_index */ + cl_git_pass(git_index_add_bypath(write_index, "a.txt")); + cl_git_pass(git_index_add_bypath(write_index, "b.txt")); + + cl_assert_equal_sz(2, git_index_entrycount(write_index)); + + /* Persist the index changes to disk */ + cl_git_pass(git_index_write(write_index)); + cl_assert_equal_i(true, write_index->on_disk); + + /* Sync the changes back into the read_index */ + cl_assert_equal_sz(0, git_index_entrycount(read_index)); + + cl_git_pass(git_index_read(read_index)); + cl_assert_equal_i(true, read_index->on_disk); + + cl_assert_equal_sz(2, git_index_entrycount(read_index)); + + /* Remove the index file from the filesystem */ + cl_git_pass(p_unlink(write_index->index_file_path)); + + /* Sync the changes back into the read_index */ + cl_git_pass(git_index_read(read_index)); + cl_assert_equal_i(false, read_index->on_disk); + cl_assert_equal_sz(0, git_index_entrycount(read_index)); + + git_index_free(read_index); + git_index_free(write_index); + git_repository_free(repo); +} -- cgit v1.2.1 From 5173ea921d4ccbbe7d61ddce9a0920c2e1c82035 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 4 Oct 2013 16:32:16 -0700 Subject: Add git_repository_reset_filesystem and fix tests When a repository is transferred from one file system to another, many of the config settings that represent the properties of the file system may be wrong. This adds a new public API that will refresh the config settings of the repository to account for the change of file system. This doesn't do a full "reinitialize" and operates on a existing git_repository object refreshing the config when done. This commit then makes use of the new API in clar as each test repository is set up. This commit also has a number of other clar test fixes where we were making assumptions about the type of filesystem, either based on outdated config data or based on the OS instead of the FS. --- include/git2/repository.h | 17 +++++++ src/config.h | 2 +- src/repository.c | 100 +++++++++++++++++++++++++++++------------ tests-clar/clar_libgit2.c | 3 ++ tests-clar/diff/diff_helpers.c | 43 +++++++++++++++--- tests-clar/diff/diffiter.c | 10 ++--- tests-clar/diff/drivers.c | 7 +++ tests-clar/diff/patch.c | 8 +++- tests-clar/index/filemodes.c | 30 ++++++++----- 9 files changed, 167 insertions(+), 53 deletions(-) diff --git a/include/git2/repository.h b/include/git2/repository.h index b4d561992..74ab65bf7 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -287,6 +287,23 @@ GIT_EXTERN(int) git_repository_init_ext( const char *repo_path, git_repository_init_options *opts); +/** + * Update the filesystem config settings for an open repository + * + * When a repository is initialized, config values are set based on the + * properties of the filesystem that the repository is on, such as + * "core.ignorecase", "core.filemode", "core.symlinks", etc. If the + * repository is moved to a new filesystem, these properties may no + * longer be correct and API calls may not behave as expected. This + * call reruns the phase of repository initialization that sets those + * properties to compensate for the current filesystem of the repo. + * + * @param repo A repository object + * @returrn 0 on success, < 0 on error + */ +GIT_EXTERN(int) git_repository_reset_filesystem( + git_repository *repo); + /** * Retrieve and resolve the reference pointed at by HEAD. * diff --git a/src/config.h b/src/config.h index 85db5e3e1..01e8465cc 100644 --- a/src/config.h +++ b/src/config.h @@ -47,7 +47,7 @@ extern int git_config_rename_section( * @param out the new backend * @param path where the config file is located */ -extern int git_config_file__ondisk(struct git_config_backend **out, const char *path); +extern int git_config_file__ondisk(git_config_backend **out, const char *path); extern int git_config__normalize_name(const char *in, char **out); diff --git a/src/repository.c b/src/repository.c index f609e5779..52509ffc1 100644 --- a/src/repository.c +++ b/src/repository.c @@ -962,34 +962,46 @@ static int create_empty_file(const char *path, mode_t mode) } static int repo_init_config( + git_config *parent, const char *repo_dir, const char *work_dir, - git_repository_init_options *opts) + uint32_t flags, + uint32_t mode) { int error = 0; - git_buf cfg_path = GIT_BUF_INIT; + git_buf buf = GIT_BUF_INIT; + const char *cfg_path = NULL; git_config *config = NULL; - bool is_bare = ((opts->flags & GIT_REPOSITORY_INIT_BARE) != 0); + bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0); #define SET_REPO_CONFIG(TYPE, NAME, VAL) do {\ if ((error = git_config_set_##TYPE(config, NAME, VAL)) < 0) \ goto cleanup; } while (0) - if (git_buf_joinpath(&cfg_path, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0) + if (git_buf_joinpath(&buf, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0) return -1; + cfg_path = git_buf_cstr(&buf); - if (!git_path_isfile(git_buf_cstr(&cfg_path)) && - create_empty_file(git_buf_cstr(&cfg_path), GIT_CONFIG_FILE_MODE) < 0) { - git_buf_free(&cfg_path); - return -1; - } + if (!git_path_isfile(cfg_path) && + (error = create_empty_file(cfg_path, GIT_CONFIG_FILE_MODE)) < 0) + goto cleanup; - if (git_config_open_ondisk(&config, git_buf_cstr(&cfg_path)) < 0) { - git_buf_free(&cfg_path); - return -1; + if (!parent) + error = git_config_open_ondisk(&config, cfg_path); + else if ((error = git_config_open_level( + &config, parent, GIT_CONFIG_LEVEL_LOCAL)) < 0) + { + giterr_clear(); + + if (!(error = git_config_add_file_ondisk( + parent, cfg_path, GIT_CONFIG_LEVEL_LOCAL, false))) + error = git_config_open_level( + &config, parent, GIT_CONFIG_LEVEL_LOCAL); } + if (error < 0) + goto cleanup; - if ((opts->flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0 && + if ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0 && (error = check_repositoryformatversion(config)) < 0) goto cleanup; @@ -998,7 +1010,7 @@ static int repo_init_config( SET_REPO_CONFIG( int32, "core.repositoryformatversion", GIT_REPO_VERSION); SET_REPO_CONFIG( - bool, "core.filemode", is_chmod_supported(git_buf_cstr(&cfg_path))); + bool, "core.filemode", is_chmod_supported(cfg_path)); #ifdef GIT_USE_ICONV SET_REPO_CONFIG( @@ -1009,38 +1021,70 @@ static int repo_init_config( if (!are_symlinks_supported(is_bare ? repo_dir : work_dir)) SET_REPO_CONFIG(bool, "core.symlinks", false); + /* core git does not do this on a reinit, but it is a property of + * the filesystem, so I think we should... + */ + if (!(flags & GIT_REPOSITORY_INIT__IS_REINIT) && + is_filesystem_case_insensitive(repo_dir)) + SET_REPO_CONFIG(bool, "core.ignorecase", true); + if (!is_bare) { SET_REPO_CONFIG(bool, "core.logallrefupdates", true); - if (!(opts->flags & GIT_REPOSITORY_INIT__NATURAL_WD)) { + if (!(flags & GIT_REPOSITORY_INIT__NATURAL_WD)) { SET_REPO_CONFIG(string, "core.worktree", work_dir); } - else if ((opts->flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0) { + else if ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0) { if (git_config_delete_entry(config, "core.worktree") < 0) giterr_clear(); } } - if (!(opts->flags & GIT_REPOSITORY_INIT__IS_REINIT) && - is_filesystem_case_insensitive(repo_dir)) - SET_REPO_CONFIG(bool, "core.ignorecase", true); - - if (opts->mode == GIT_REPOSITORY_INIT_SHARED_GROUP) { + if (mode == GIT_REPOSITORY_INIT_SHARED_GROUP) { SET_REPO_CONFIG(int32, "core.sharedrepository", 1); SET_REPO_CONFIG(bool, "receive.denyNonFastforwards", true); } - else if (opts->mode == GIT_REPOSITORY_INIT_SHARED_ALL) { + else if (mode == GIT_REPOSITORY_INIT_SHARED_ALL) { SET_REPO_CONFIG(int32, "core.sharedrepository", 2); SET_REPO_CONFIG(bool, "receive.denyNonFastforwards", true); } cleanup: - git_buf_free(&cfg_path); + git_buf_free(&buf); git_config_free(config); return error; } +int git_repository_reset_filesystem(git_repository *repo) +{ + int error = 0; + uint32_t flags = 0; + const char *repo_dir, *work_dir; + git_config *cfg; + + assert(repo); + + repo_dir = git_repository_path(repo); + work_dir = git_repository_workdir(repo); + + if (git_repository_is_bare(repo)) + flags |= GIT_REPOSITORY_INIT_BARE; + else if (!git__prefixcmp(repo_dir, work_dir) && + !strcmp(repo_dir + strlen(work_dir), DOT_GIT "/")) + flags |= GIT_REPOSITORY_INIT__NATURAL_WD; + + if ((error = git_repository_config(&cfg, repo)) < 0) + return error; + + error = repo_init_config(cfg, repo_dir, work_dir, flags, 0); + + git_config_free(cfg); + git_repository__cvar_cache_clear(repo); + + return error; +} + static int repo_write_template( const char *git_dir, bool allow_overwrite, @@ -1429,22 +1473,22 @@ int git_repository_init_ext( opts->flags |= GIT_REPOSITORY_INIT__IS_REINIT; error = repo_init_config( - git_buf_cstr(&repo_path), git_buf_cstr(&wd_path), opts); + NULL, repo_path.ptr, wd_path.ptr, opts->flags, opts->mode); /* TODO: reinitialize the templates */ } else { if (!(error = repo_init_structure( - git_buf_cstr(&repo_path), git_buf_cstr(&wd_path), opts)) && + repo_path.ptr, wd_path.ptr, opts)) && !(error = repo_init_config( - git_buf_cstr(&repo_path), git_buf_cstr(&wd_path), opts))) + NULL, repo_path.ptr, wd_path.ptr, opts->flags, opts->mode))) error = repo_init_create_head( - git_buf_cstr(&repo_path), opts->initial_head); + repo_path.ptr, opts->initial_head); } if (error < 0) goto cleanup; - error = git_repository_open(out, git_buf_cstr(&repo_path)); + error = git_repository_open(out, repo_path.ptr); if (!error && opts->origin_url) error = repo_init_create_origin(*out, opts->origin_url); diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 0f8f26efb..c3abc1f95 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -190,6 +190,9 @@ git_repository *cl_git_sandbox_init(const char *sandbox) /* Now open the sandbox repository and make it available for tests */ cl_git_pass(git_repository_open(&_cl_repo, sandbox)); + /* Adjust configs after copying to new filesystem */ + cl_git_pass(git_repository_reset_filesystem(_cl_repo)); + return _cl_repo; } diff --git a/tests-clar/diff/diff_helpers.c b/tests-clar/diff/diff_helpers.c index a5c322b4d..3452f231d 100644 --- a/tests-clar/diff/diff_helpers.c +++ b/tests-clar/diff/diff_helpers.c @@ -21,6 +21,35 @@ git_tree *resolve_commit_oid_to_tree( return tree; } +static char diff_pick_suffix(int mode) +{ + if (S_ISDIR(mode)) + return '/'; + else if (GIT_PERMS_IS_EXEC(mode)) + return '*'; + else + return ' '; +} + +static void fprintf_delta(FILE *fp, const git_diff_delta *delta, float progress) +{ + char code = git_diff_status_char(delta->status); + char old_suffix = diff_pick_suffix(delta->old_file.mode); + char new_suffix = diff_pick_suffix(delta->new_file.mode); + + fprintf(fp, "%c\t%s", code, delta->old_file.path); + + if ((delta->old_file.path != delta->new_file.path && + strcmp(delta->old_file.path, delta->new_file.path) != 0) || + (delta->old_file.mode != delta->new_file.mode && + delta->old_file.mode != 0 && delta->new_file.mode != 0)) + fprintf(fp, "%c %s%c", old_suffix, delta->new_file.path, new_suffix); + else if (old_suffix != ' ') + fprintf(fp, "%c", old_suffix); + + fprintf(fp, "\t[%.2f]\n", progress); +} + int diff_file_cb( const git_diff_delta *delta, float progress, @@ -29,9 +58,7 @@ int diff_file_cb( diff_expects *e = payload; if (e->debug) - fprintf(stderr, "%c %s (%.3f)\n", - git_diff_status_char(delta->status), - delta->old_file.path, progress); + fprintf_delta(stderr, delta, progress); if (e->names) cl_assert_equal_s(e->names[e->files], delta->old_file.path); @@ -55,8 +82,14 @@ int diff_print_file_cb( float progress, void *payload) { - fprintf(stderr, "%c %s\n", - git_diff_status_char(delta->status), delta->old_file.path); + if (!payload) { + fprintf_delta(stderr, delta, progress); + return 0; + } + + if (!((diff_expects *)payload)->debug) + fprintf_delta(stderr, delta, progress); + return diff_file_cb(delta, progress, payload); } diff --git a/tests-clar/diff/diffiter.c b/tests-clar/diff/diffiter.c index 932d720f2..ea5908475 100644 --- a/tests-clar/diff/diffiter.c +++ b/tests-clar/diff/diffiter.c @@ -27,25 +27,25 @@ void test_diff_diffiter__create(void) git_diff_list_free(diff); } -void test_diff_diffiter__iterate_files(void) +void test_diff_diffiter__iterate_files_1(void) { git_repository *repo = cl_git_sandbox_init("attr"); git_diff_list *diff; size_t d, num_d; - int count = 0; + diff_expects exp = { 0 }; cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); num_d = git_diff_num_deltas(diff); - cl_assert_equal_i(6, (int)num_d); for (d = 0; d < num_d; ++d) { const git_diff_delta *delta; cl_git_pass(git_diff_get_patch(NULL, &delta, diff, d)); cl_assert(delta != NULL); - count++; + + diff_file_cb(delta, (float)d / (float)num_d, &exp); } - cl_assert_equal_i(6, count); + cl_assert_equal_sz(6, exp.files); git_diff_list_free(diff); } diff --git a/tests-clar/diff/drivers.c b/tests-clar/diff/drivers.c index e02dd5c68..719d229fc 100644 --- a/tests-clar/diff/drivers.c +++ b/tests-clar/diff/drivers.c @@ -147,6 +147,13 @@ void test_diff_drivers__long_lines(void) cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); cl_git_pass(git_diff_patch_to_str(&actual, patch)); + /* if chmod not supported, overwrite mode bits since anything is possible */ + if (!cl_is_chmod_supported()) { + size_t actual_len = strlen(actual); + if (actual_len > 72 && memcmp(&actual[66], "100644", 6) != 0) + memcpy(&actual[66], "100644", 6); + } + cl_assert_equal_s(expected, actual); free(actual); diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c index 6a33fa990..7aab8f409 100644 --- a/tests-clar/diff/patch.c +++ b/tests-clar/diff/patch.c @@ -238,6 +238,9 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_git_pass(git_config_new(&cfg)); git_repository_set_config(g_repo, cfg); + git_config_free(cfg); + + git_repository_reset_filesystem(g_repo); cl_git_pass( git_futils_readbuffer(&old_content, "renames/songof7cities.txt")); @@ -408,7 +411,6 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) git_buf_free(&actual); git_buf_free(&old_content); git_tree_free(head); - git_config_free(cfg); } static void check_single_patch_stats( @@ -520,6 +522,9 @@ void test_diff_patch__line_counts_with_eofnl(void) cl_git_pass(git_config_new(&cfg)); git_repository_set_config(g_repo, cfg); + git_config_free(cfg); + + git_repository_reset_filesystem(g_repo); cl_git_pass(git_futils_readbuffer(&content, "renames/songof7cities.txt")); @@ -574,5 +579,4 @@ void test_diff_patch__line_counts_with_eofnl(void) g_repo, 1, 1, 1, 6, expected_sizes, expected); git_buf_free(&content); - git_config_free(cfg); } diff --git a/tests-clar/index/filemodes.c b/tests-clar/index/filemodes.c index 02f83efba..8cbd6ff3a 100644 --- a/tests-clar/index/filemodes.c +++ b/tests-clar/index/filemodes.c @@ -51,18 +51,24 @@ static void replace_file_with_mode( git_buf_free(&content); } -static void add_and_check_mode( - git_index *index, const char *filename, unsigned int expect_mode) +#define add_and_check_mode(I,F,X) add_and_check_mode_(I,F,X,__FILE__,__LINE__) + +static void add_and_check_mode_( + git_index *index, const char *filename, unsigned int expect_mode, + const char *file, int line) { size_t pos; const git_index_entry *entry; cl_git_pass(git_index_add_bypath(index, filename)); - cl_assert(!git_index_find(&pos, index, filename)); + clar__assert(!git_index_find(&pos, index, filename), + file, line, "Cannot find index entry", NULL, 1); entry = git_index_get_byindex(index, pos); - cl_assert(entry->mode == expect_mode); + + clar__assert_equal(file, line, "Expected mode does not match index", + 1, "%07o", (unsigned int)entry->mode, (unsigned int)expect_mode); } void test_index_filemodes__untrusted(void) @@ -91,16 +97,16 @@ void test_index_filemodes__untrusted(void) replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755); add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); - /* 5 - add new 0644 -> expect 0644 */ - cl_git_write2file("filemodes/new_off", "blah", 0, - O_WRONLY | O_CREAT | O_TRUNC, 0644); - add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); - - /* this test won't give predictable results on a platform - * that doesn't support filemodes correctly, so skip it. + /* these tests of newly added files won't give predictable results on + * filesystems without actual filemode support, so skip them. */ if (can_filemode) { - /* 6 - add 0755 -> expect 0755 */ + /* 5 - add new 0644 -> expect 0644 */ + cl_git_write2file("filemodes/new_off", "blah", 0, + O_WRONLY | O_CREAT | O_TRUNC, 0644); + add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); + + /* 6 - add new 0755 -> expect 0755 */ cl_git_write2file("filemodes/new_on", "blah", 0, O_WRONLY | O_CREAT | O_TRUNC, 0755); add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE); -- cgit v1.2.1 From cfd192b0140f004404a208cde967ac8eef16cdff Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 3 Oct 2013 12:44:34 -0700 Subject: Add test for multiple thread init/shutdown --- tests-clar/threads/basic.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests-clar/threads/basic.c b/tests-clar/threads/basic.c index a15c53140..a329ee7f9 100644 --- a/tests-clar/threads/basic.c +++ b/tests-clar/threads/basic.c @@ -21,3 +21,16 @@ void test_threads_basic__cache(void) // run several threads polling the cache at the same time cl_assert(1 == 1); } + +void test_threads_basic__multiple_init(void) +{ + git_repository *nested_repo; + + git_threads_init(); + cl_git_pass(git_repository_open(&nested_repo, cl_fixture("testrepo.git"))); + git_repository_free(nested_repo); + + git_threads_shutdown(); + cl_git_pass(git_repository_open(&nested_repo, cl_fixture("testrepo.git"))); + git_repository_free(nested_repo); +} -- cgit v1.2.1 From e411b74ebdb0ec528dbd0296746bd8a573f4045d Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 4 Oct 2013 19:33:48 -0700 Subject: Posix synchronized init, prototype win32 version --- src/global.c | 123 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 89 insertions(+), 34 deletions(-) diff --git a/src/global.c b/src/global.c index 4f024f17e..fe3a3c8b8 100644 --- a/src/global.c +++ b/src/global.c @@ -18,6 +18,7 @@ git_mutex git__mwindow_mutex; git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB]; git_atomic git__n_shutdown_callbacks; +git_atomic git__n_inits; void git__on_shutdown(git_global_shutdown_fn callback) { @@ -73,47 +74,99 @@ static void git__shutdown(void) #if defined(GIT_THREADS) && defined(GIT_WIN32) static DWORD _tls_index; -static int _tls_init = 0; +static HANDLE _init_mutex = NULL; +static HANDLE _initialized_event = NULL; -int git_threads_init(void) +static int synchronized_init_and_claim_mutex(volatile HANDLE *m) +{ + if (*m == NULL) { + HANDLE nm = CreateMutex(NULL, FALSE, NULL); + if (InterlockedCompareExchangePointer(m, nm, NULL) != NULL) { + CloseHandle(nm); + } + } + return WaitForSingleObject(*m, INFINITE) == WAIT_FAILED; +} + +static int synchronized_threads_init() { int error; - if (_tls_init) - return 0; + if (synchronized_init_and_claim_mutex(&_init_mutex) != WAIT_OBJECT_0) { + giterr_set(GITERR_OS, "git_threads_init: WaitForSingleObject failed"); + return -1; + } + + if (!_initialized_event) { + _initialized_event = CreateEvent(NULL, TRUE, FALSE, NULL); + } _tls_index = TlsAlloc(); if (git_mutex_init(&git__mwindow_mutex)) return -1; /* Initialize any other subsystems that have global state */ - if ((error = git_hash_global_init()) >= 0 && - (error = git_futils_dirs_global_init()) >= 0) - _tls_init = 1; - - GIT_MEMORY_BARRIER; + if ((error = git_hash_global_init()) >= 0) + error = git_futils_dirs_global_init(); win32_pthread_initialize(); + SetEvent(_initialized_event); + ReleaseMutex(_init_mutex); + return error; +} + +int git_threads_init(void) +{ + int error = -1, + n_inits = git_atomic_inc(&git__n_inits); + + if (n_inits == 1) + error = synchronized_threads_init(); + else { + while (!_initialized_event); /* SPIN */ + error = (WaitForSingleObject(_initialized_event, INFINITE) == WAIT_OBJECT_0) ? 0 : -1; + } + GIT_MEMORY_BARRIER; return error; } -void git_threads_shutdown(void) +static void synchronized_threads_shutdown() { + if (WaitForSingleObject(_init_mutex, INFINITE) != WAIT_OBJECT_0) { + giterr_set(GITERR_OS, "git_threads_shutdown: WaitForSingleObject failed"); + return; + } + + if (git__n_inits.val != 0) { + /* Someone else initialized while we were waiting */ + ReleaseMutex(_init_mutex); + return; + } + ResetEvent(_initialized_event); + /* Shut down any subsystems that have global state */ git__shutdown(); - TlsFree(_tls_index); - _tls_init = 0; - git_mutex_free(&git__mwindow_mutex); + + ReleaseMutex(_init_mutex); +} + +void git_threads_shutdown(void) +{ + int n_inits = git_atomic_dec(&git__n_inits); + + if (n_inits == 0) + synchronized_threads_shutdown(); + GIT_MEMORY_BARRIER; } git_global_st *git__global_state(void) { void *ptr; - assert(_tls_init); + assert(git__n_inits.val); if ((ptr = TlsGetValue(_tls_index)) != NULL) return ptr; @@ -130,55 +183,57 @@ git_global_st *git__global_state(void) #elif defined(GIT_THREADS) && defined(_POSIX_THREADS) static pthread_key_t _tls_key; -static int _tls_init = 0; +static pthread_once_t _once_init = PTHREAD_ONCE_INIT; +int init_error = 0; static void cb__free_status(void *st) { git__free(st); } -int git_threads_init(void) +static void init_once(void) { - int error = 0; - - if (_tls_init) - return 0; - - if (git_mutex_init(&git__mwindow_mutex)) - return -1; + if ((init_error = git_mutex_init(&git__mwindow_mutex)) != 0) + return; pthread_key_create(&_tls_key, &cb__free_status); /* Initialize any other subsystems that have global state */ - if ((error = git_hash_global_init()) >= 0 && - (error = git_futils_dirs_global_init()) >= 0) - _tls_init = 1; + if ((init_error = git_hash_global_init()) >= 0) + init_error = git_futils_dirs_global_init(); GIT_MEMORY_BARRIER; +} - return error; +int git_threads_init(void) +{ + pthread_once(&_once_init, init_once); + git_atomic_inc(&git__n_inits); + return init_error; } void git_threads_shutdown(void) { + pthread_once_t new_once = PTHREAD_ONCE_INIT; + + if (git_atomic_dec(&git__n_inits) > 0) return; + /* Shut down any subsystems that have global state */ git__shutdown(); - if (_tls_init) { - void *ptr = pthread_getspecific(_tls_key); - pthread_setspecific(_tls_key, NULL); - git__free(ptr); - } + void *ptr = pthread_getspecific(_tls_key); + pthread_setspecific(_tls_key, NULL); + git__free(ptr); pthread_key_delete(_tls_key); - _tls_init = 0; git_mutex_free(&git__mwindow_mutex); + _once_init = new_once; } git_global_st *git__global_state(void) { void *ptr; - assert(_tls_init); + assert(git__n_inits.val); if ((ptr = pthread_getspecific(_tls_key)) != NULL) return ptr; -- cgit v1.2.1 From cdc95a0d93aa3b515f9c4fe30f47d52e8e7f3dde Mon Sep 17 00:00:00 2001 From: Philip Kelley Date: Fri, 4 Oct 2013 18:38:37 -0400 Subject: Use InterlockedCompareExchange for the lock --- src/global.c | 67 ++++++++++++++++-------------------------------------------- 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/src/global.c b/src/global.c index fe3a3c8b8..33a760c54 100644 --- a/src/global.c +++ b/src/global.c @@ -74,33 +74,12 @@ static void git__shutdown(void) #if defined(GIT_THREADS) && defined(GIT_WIN32) static DWORD _tls_index; -static HANDLE _init_mutex = NULL; -static HANDLE _initialized_event = NULL; - -static int synchronized_init_and_claim_mutex(volatile HANDLE *m) -{ - if (*m == NULL) { - HANDLE nm = CreateMutex(NULL, FALSE, NULL); - if (InterlockedCompareExchangePointer(m, nm, NULL) != NULL) { - CloseHandle(nm); - } - } - return WaitForSingleObject(*m, INFINITE) == WAIT_FAILED; -} +static DWORD _mutex = 0; static int synchronized_threads_init() { int error; - if (synchronized_init_and_claim_mutex(&_init_mutex) != WAIT_OBJECT_0) { - giterr_set(GITERR_OS, "git_threads_init: WaitForSingleObject failed"); - return -1; - } - - if (!_initialized_event) { - _initialized_event = CreateEvent(NULL, TRUE, FALSE, NULL); - } - _tls_index = TlsAlloc(); if (git_mutex_init(&git__mwindow_mutex)) return -1; @@ -110,56 +89,46 @@ static int synchronized_threads_init() error = git_futils_dirs_global_init(); win32_pthread_initialize(); - SetEvent(_initialized_event); - ReleaseMutex(_init_mutex); + return error; } int git_threads_init(void) { - int error = -1, - n_inits = git_atomic_inc(&git__n_inits); + int error = 0; + + /* Enter the lock */ + while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); } - if (n_inits == 1) + /* Only do work on a 0 -> 1 transition of the refcount */ + if (1 == ++git__n_inits.val) error = synchronized_threads_init(); - else { - while (!_initialized_event); /* SPIN */ - error = (WaitForSingleObject(_initialized_event, INFINITE) == WAIT_OBJECT_0) ? 0 : -1; - } - GIT_MEMORY_BARRIER; + /* Exit the lock */ + InterlockedExchange(&_mutex, 0); + return error; } static void synchronized_threads_shutdown() { - if (WaitForSingleObject(_init_mutex, INFINITE) != WAIT_OBJECT_0) { - giterr_set(GITERR_OS, "git_threads_shutdown: WaitForSingleObject failed"); - return; - } - - if (git__n_inits.val != 0) { - /* Someone else initialized while we were waiting */ - ReleaseMutex(_init_mutex); - return; - } - ResetEvent(_initialized_event); - /* Shut down any subsystems that have global state */ git__shutdown(); TlsFree(_tls_index); git_mutex_free(&git__mwindow_mutex); - - ReleaseMutex(_init_mutex); } void git_threads_shutdown(void) { - int n_inits = git_atomic_dec(&git__n_inits); + /* Enter the lock */ + while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); } - if (n_inits == 0) + /* Only do work on a 1 -> 0 transition of the refcount */ + if (0 == --git__n_inits.val) synchronized_threads_shutdown(); - GIT_MEMORY_BARRIER; + + /* Exit the lock */ + InterlockedExchange(&_mutex, 0); } git_global_st *git__global_state(void) -- cgit v1.2.1 From 22661448973e3c46f2a71a75364630a5111f7c14 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 4 Oct 2013 19:35:32 -0700 Subject: Don't use git_atomic as an integer --- src/global.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/global.c b/src/global.c index 33a760c54..7d39c6fa8 100644 --- a/src/global.c +++ b/src/global.c @@ -18,7 +18,6 @@ git_mutex git__mwindow_mutex; git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB]; git_atomic git__n_shutdown_callbacks; -git_atomic git__n_inits; void git__on_shutdown(git_global_shutdown_fn callback) { @@ -75,6 +74,7 @@ static void git__shutdown(void) static DWORD _tls_index; static DWORD _mutex = 0; +static DWORD _n_inits = 0; static int synchronized_threads_init() { @@ -101,7 +101,7 @@ int git_threads_init(void) while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); } /* Only do work on a 0 -> 1 transition of the refcount */ - if (1 == ++git__n_inits.val) + if (1 == ++_n_inits) error = synchronized_threads_init(); /* Exit the lock */ @@ -124,7 +124,7 @@ void git_threads_shutdown(void) while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); } /* Only do work on a 1 -> 0 transition of the refcount */ - if (0 == --git__n_inits.val) + if (0 == --_n_inits) synchronized_threads_shutdown(); /* Exit the lock */ @@ -135,7 +135,7 @@ git_global_st *git__global_state(void) { void *ptr; - assert(git__n_inits.val); + assert(_n_inits); if ((ptr = TlsGetValue(_tls_index)) != NULL) return ptr; @@ -153,6 +153,7 @@ git_global_st *git__global_state(void) static pthread_key_t _tls_key; static pthread_once_t _once_init = PTHREAD_ONCE_INIT; +static git_atomic git__n_inits; int init_error = 0; static void cb__free_status(void *st) -- cgit v1.2.1 From 13f670a5d9d86629f4879f6df9494356e4f28832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 15 Apr 2013 09:07:57 +0200 Subject: tree: allow retrieval of raw attributes When a tool needs to recreate the tree object (for example an interface to another VCS), it needs to use the raw attributes, forgoing any normalization. --- include/git2/tree.h | 11 +++++++++++ src/tree.c | 9 ++++++--- tests-clar/object/tree/attributes.c | 3 ++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/include/git2/tree.h b/include/git2/tree.h index f1e7d0899..d94b446c2 100644 --- a/include/git2/tree.h +++ b/include/git2/tree.h @@ -198,6 +198,17 @@ GIT_EXTERN(git_otype) git_tree_entry_type(const git_tree_entry *entry); */ GIT_EXTERN(git_filemode_t) git_tree_entry_filemode(const git_tree_entry *entry); +/** + * Get the raw UNIX file attributes of a tree entry + * + * This function does not perform any normalization and is only useful + * if you need to be able to recreate the original tree object. + * + * @param entry a tree entry + * @return filemode as an integer + */ + +GIT_EXTERN(git_filemode_t) git_tree_entry_filemode_raw(const git_tree_entry *entry); /** * Compare two tree entries * diff --git a/src/tree.c b/src/tree.c index 0bdf9a93e..bb59ff82b 100644 --- a/src/tree.c +++ b/src/tree.c @@ -237,7 +237,12 @@ void git_tree__free(void *_tree) git_filemode_t git_tree_entry_filemode(const git_tree_entry *entry) { - return (git_filemode_t)entry->attr; + return normalize_filemode(entry->attr); +} + +git_filemode_t git_tree_entry_filemode_raw(const git_tree_entry *entry) +{ + return entry->attr; } const char *git_tree_entry_name(const git_tree_entry *entry) @@ -386,8 +391,6 @@ int git_tree__parse(void *_tree, git_odb_object *odb_obj) if (git__strtol32(&attr, buffer, &buffer, 8) < 0 || !buffer) return tree_error("Failed to parse tree. Can't parse filemode", NULL); - attr = normalize_filemode(attr); /* make sure to normalize the filemode */ - if (*buffer++ != ' ') return tree_error("Failed to parse tree. Object is corrupted", NULL); diff --git a/tests-clar/object/tree/attributes.c b/tests-clar/object/tree/attributes.c index cc93b45d2..85216cd1b 100644 --- a/tests-clar/object/tree/attributes.c +++ b/tests-clar/object/tree/attributes.c @@ -107,7 +107,8 @@ void test_object_tree_attributes__normalize_600(void) cl_git_pass(git_tree_lookup(&tree, repo, &id)); entry = git_tree_entry_byname(tree, "ListaTeste.xml"); - cl_assert_equal_i(entry->attr, GIT_FILEMODE_BLOB); + cl_assert_equal_i(git_tree_entry_filemode(entry), GIT_FILEMODE_BLOB); + cl_assert_equal_i(git_tree_entry_filemode_raw(entry), 0100600); git_tree_free(tree); cl_git_sandbox_cleanup(); -- cgit v1.2.1 From 7fb6eb278b350f9f4caab5a3f72bfb70353fc40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 8 Oct 2013 11:54:50 +0200 Subject: indexer: inject one base at a time There may be multiple deltas referencing the same base as well as OFS deltas which rely on a thin delta. Deal with both at the same time by injecting a single object and going back up to the main delta-resolving loop. --- src/indexer.c | 64 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index 21b993a28..2cda1a629 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -683,50 +683,58 @@ cleanup: static int fix_thin_pack(git_indexer_stream *idx, git_transfer_progress *stats) { - int error; + int error, found_ref_delta = 0; unsigned int i; struct delta_info *delta; + size_t size; + git_otype type; + git_mwindow *w = NULL; + git_off_t curpos; + unsigned char *base_info; + unsigned int left = 0; + git_oid base; + + assert(git_vector_length(&idx->deltas) > 0); if (idx->odb == NULL) { giterr_set(GITERR_INDEXER, "cannot fix a thin pack without an ODB"); return -1; } + /* Loop until we find the first REF delta */ git_vector_foreach(&idx->deltas, i, delta) { - size_t size; - git_otype type; - git_mwindow *w = NULL; - git_off_t curpos = delta->delta_off; - unsigned char *base_info; - unsigned int left = 0; - git_oid base; - + curpos = delta->delta_off; error = git_packfile_unpack_header(&size, &type, &idx->pack->mwf, &w, &curpos); git_mwindow_close(&w); if (error < 0) return error; - if (type != GIT_OBJ_REF_DELTA) { - giterr_set(GITERR_INDEXER, "delta with missing base is not REF_DELTA"); - return -1; + if (type == GIT_OBJ_REF_DELTA) { + found_ref_delta = 1; + break; } + } - /* curpos now points to the base information, which is an OID */ - base_info = git_mwindow_open(&idx->pack->mwf, &w, curpos, GIT_OID_RAWSZ, &left); - if (base_info == NULL) { - giterr_set(GITERR_INDEXER, "failed to map delta information"); - return -1; - } + if (!found_ref_delta) { + giterr_set(GITERR_INDEXER, "no REF_DELTA found, cannot inject object"); + return -1; + } - git_oid_fromraw(&base, base_info); - git_mwindow_close(&w); + /* curpos now points to the base information, which is an OID */ + base_info = git_mwindow_open(&idx->pack->mwf, &w, curpos, GIT_OID_RAWSZ, &left); + if (base_info == NULL) { + giterr_set(GITERR_INDEXER, "failed to map delta information"); + return -1; + } - if (inject_object(idx, &base) < 0) - return -1; + git_oid_fromraw(&base, base_info); + git_mwindow_close(&w); - stats->total_objects++; - stats->local_objects++; - } + if (inject_object(idx, &base) < 0) + return -1; + + stats->total_objects++; + stats->local_objects++; return 0; } @@ -764,8 +772,10 @@ static int resolve_deltas(git_indexer_stream *idx, git_transfer_progress *stats) i--; } - if (!progressed && (fix_thin_pack(idx, stats) < 0)) - return -1; + if (!progressed && (fix_thin_pack(idx, stats) < 0)) { + giterr_set(GITERR_INDEXER, "missing delta bases"); + return -1; + } } return 0; -- cgit v1.2.1 From 14997dc5f69e7ceebe502b32087d809a8482bf78 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 8 Oct 2013 12:45:43 -0700 Subject: More filemode cleanups for FAT on MacOS This cleans up some additional issues. The main change is that on a filesystem that doesn't support mode bits, libgit2 will now create new blobs with GIT_FILEMODE_BLOB always instead of being at the mercy to the filesystem driver to report executable or not. This means that if "core.filemode" lies and claims that filemode is not supported, then we will ignore the executable bit from the filesystem. Previously we would have allowed it. This adds an option to the new git_repository_reset_filesystem to recurse through submodules if desired. There may be other types of APIs that would like a "recurse submodules" option, but this one is particularly useful. This also has a number of cleanups, etc., for related things including trying to give better error messages when problems come up from the filesystem. For example, the FAT filesystem driver on MacOS appears to return errno EINVAL if you attempt to write a filename with invalid UTF-8 in it. We try to capture that with a better error message now. --- include/git2/repository.h | 4 +- src/checkout.c | 3 +- src/errors.c | 1 - src/fileops.c | 85 ++++++-------- src/index.c | 8 +- src/index.h | 2 +- src/iterator.c | 2 +- src/path.c | 33 ++++-- src/path.h | 4 + src/repository.c | 185 +++++++++++++++++++------------ src/submodule.c | 3 +- src/win32/posix_w32.c | 4 +- tests-clar/clar_libgit2.c | 2 +- tests-clar/diff/patch.c | 4 +- tests-clar/diff/workdir.c | 11 +- tests-clar/index/addall.c | 5 +- tests-clar/index/filemodes.c | 24 ++-- tests-clar/refs/unicode.c | 23 +++- tests-clar/submodule/lookup.c | 15 +-- tests-clar/submodule/modify.c | 15 +-- tests-clar/submodule/submodule_helpers.c | 4 + 21 files changed, 236 insertions(+), 201 deletions(-) diff --git a/include/git2/repository.h b/include/git2/repository.h index 74ab65bf7..28d8400f2 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -299,10 +299,12 @@ GIT_EXTERN(int) git_repository_init_ext( * properties to compensate for the current filesystem of the repo. * * @param repo A repository object + * @param recurse_submodules Should submodules be reset recursively * @returrn 0 on success, < 0 on error */ GIT_EXTERN(int) git_repository_reset_filesystem( - git_repository *repo); + git_repository *repo, + int recurse_submodules); /** * Retrieve and resolve the reference pointed at by HEAD. diff --git a/src/checkout.c b/src/checkout.c index 5d741d393..d3f673d40 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -783,7 +783,8 @@ static int checkout_update_index( memset(&entry, 0, sizeof(entry)); entry.path = (char *)file->path; /* cast to prevent warning */ - git_index_entry__init_from_stat(&entry, st); + git_index_entry__init_from_stat( + &entry, st, !(git_index_caps(data->index) & GIT_INDEXCAP_NO_FILEMODE)); git_oid_cpy(&entry.oid, &file->oid); return git_index_add(data->index, &entry); diff --git a/src/errors.c b/src/errors.c index e2629f69e..c9d9e4e37 100644 --- a/src/errors.c +++ b/src/errors.c @@ -116,4 +116,3 @@ const git_error *giterr_last(void) { return GIT_GLOBAL->last_error; } - diff --git a/src/fileops.c b/src/fileops.c index be2e53ca8..63aedc6d0 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -78,11 +78,8 @@ int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, con int git_futils_open_ro(const char *path) { int fd = p_open(path, O_RDONLY); - if (fd < 0) { - if (errno == ENOENT || errno == ENOTDIR) - fd = GIT_ENOTFOUND; - giterr_set(GITERR_OS, "Failed to open '%s'", path); - } + if (fd < 0) + return git_path_set_error(errno, path, "open"); return fd; } @@ -138,7 +135,6 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len) int git_futils_readbuffer_updated( git_buf *buf, const char *path, time_t *mtime, size_t *size, int *updated) { - int error = 0; git_file fd; struct stat st; bool changed = false; @@ -148,13 +144,8 @@ int git_futils_readbuffer_updated( if (updated != NULL) *updated = 0; - if (p_stat(path, &st) < 0) { - error = errno; - giterr_set(GITERR_OS, "Failed to stat '%s'", path); - if (error == ENOENT || error == ENOTDIR) - return GIT_ENOTFOUND; - return -1; - } + if (p_stat(path, &st) < 0) + return git_path_set_error(errno, path, "stat"); if (S_ISDIR(st.st_mode) || !git__is_sizet(st.st_size+1)) { giterr_set(GITERR_OS, "Invalid regular file stat for '%s'", path); @@ -441,66 +432,60 @@ static int futils__rm_first_parent(git_buf *path, const char *ceiling) static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path) { - struct stat st; futils__rmdir_data *data = opaque; + int error = data->error; + struct stat st; - if (data->depth > FUTILS_MAX_DEPTH) { - data->error = - futils__error_cannot_rmdir(path->ptr, "directory nesting too deep"); - } + if (data->depth > FUTILS_MAX_DEPTH) + error = futils__error_cannot_rmdir( + path->ptr, "directory nesting too deep"); - else if ((data->error = p_lstat_posixly(path->ptr, &st)) < 0) { + else if ((error = p_lstat_posixly(path->ptr, &st)) < 0) { if (errno == ENOENT) - data->error = 0; + error = 0; else if (errno == ENOTDIR) { /* asked to remove a/b/c/d/e and a/b is a normal file */ if ((data->flags & GIT_RMDIR_REMOVE_BLOCKERS) != 0) - data->error = futils__rm_first_parent(path, data->base); + error = futils__rm_first_parent(path, data->base); else futils__error_cannot_rmdir( path->ptr, "parent is not directory"); } else - futils__error_cannot_rmdir(path->ptr, "cannot access"); + error = git_path_set_error(errno, path->ptr, "rmdir"); } else if (S_ISDIR(st.st_mode)) { data->depth++; - { - int error = - git_path_direach(path, 0, futils__rmdir_recurs_foreach, data); - if (error < 0) - return (error == GIT_EUSER) ? data->error : error; - } + error = git_path_direach(path, 0, futils__rmdir_recurs_foreach, data); + if (error < 0) + return (error == GIT_EUSER) ? data->error : error; data->depth--; if (data->depth == 0 && (data->flags & GIT_RMDIR_SKIP_ROOT) != 0) return data->error; - data->error = p_rmdir(path->ptr); - - if (data->error < 0) { + if ((error = p_rmdir(path->ptr)) < 0) { if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) != 0 && (errno == ENOTEMPTY || errno == EEXIST || errno == EBUSY)) - data->error = 0; + error = 0; else - futils__error_cannot_rmdir(path->ptr, NULL); + error = git_path_set_error(errno, path->ptr, "rmdir"); } } else if ((data->flags & GIT_RMDIR_REMOVE_FILES) != 0) { - data->error = p_unlink(path->ptr); - - if (data->error < 0) - futils__error_cannot_rmdir(path->ptr, "cannot be removed"); + if (p_unlink(path->ptr) < 0) + error = git_path_set_error(errno, path->ptr, "remove"); } else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0) - data->error = futils__error_cannot_rmdir(path->ptr, "still present"); + error = futils__error_cannot_rmdir(path->ptr, "still present"); - return data->error; + data->error = error; + return error; } static int futils__rmdir_empty_parent(void *opaque, git_buf *path) @@ -523,7 +508,7 @@ static int futils__rmdir_empty_parent(void *opaque, git_buf *path) giterr_clear(); error = GIT_ITEROVER; } else { - futils__error_cannot_rmdir(git_buf_cstr(path), NULL); + error = git_path_set_error(errno, git_buf_cstr(path), "rmdir"); } } @@ -818,11 +803,8 @@ int git_futils_cp(const char *from, const char *to, mode_t filemode) return ifd; if ((ofd = p_open(to, O_WRONLY | O_CREAT | O_EXCL, filemode)) < 0) { - if (errno == ENOENT || errno == ENOTDIR) - ofd = GIT_ENOTFOUND; - giterr_set(GITERR_OS, "Failed to open '%s' for writing", to); p_close(ifd); - return ofd; + return git_path_set_error(errno, to, "open for writing"); } return cp_by_fd(ifd, ofd, true); @@ -905,15 +887,14 @@ static int _cp_r_callback(void *ref, git_buf *from) goto exit; } - if (p_lstat(info->to.ptr, &to_st) < 0) { - if (errno != ENOENT && errno != ENOTDIR) { - giterr_set(GITERR_OS, - "Could not access %s while copying files", info->to.ptr); - error = -1; - goto exit; - } - } else + if (!(error = git_path_lstat(info->to.ptr, &to_st))) exists = true; + else if (error != GIT_ENOTFOUND) + goto exit; + else { + giterr_clear(); + error = 0; + } if ((error = git_path_lstat(from->ptr, &from_st)) < 0) goto exit; diff --git a/src/index.c b/src/index.c index 21a8d31d1..06394e6db 100644 --- a/src/index.c +++ b/src/index.c @@ -579,7 +579,8 @@ const git_index_entry *git_index_get_bypath( return git_index_get_byindex(index, pos); } -void git_index_entry__init_from_stat(git_index_entry *entry, struct stat *st) +void git_index_entry__init_from_stat( + git_index_entry *entry, struct stat *st, bool trust_mode) { entry->ctime.seconds = (git_time_t)st->st_ctime; entry->mtime.seconds = (git_time_t)st->st_mtime; @@ -587,7 +588,8 @@ void git_index_entry__init_from_stat(git_index_entry *entry, struct stat *st) /* entry->ctime.nanoseconds = st->st_ctimensec; */ entry->dev = st->st_rdev; entry->ino = st->st_ino; - entry->mode = index_create_mode(st->st_mode); + entry->mode = (!trust_mode && S_ISREG(st->st_mode)) ? + index_create_mode(0666) : index_create_mode(st->st_mode); entry->uid = st->st_uid; entry->gid = st->st_gid; entry->file_size = st->st_size; @@ -631,7 +633,7 @@ static int index_entry_init( entry = git__calloc(1, sizeof(git_index_entry)); GITERR_CHECK_ALLOC(entry); - git_index_entry__init_from_stat(entry, &st); + git_index_entry__init_from_stat(entry, &st, !index->distrust_filemode); entry->oid = oid; entry->path = git__strdup(rel_path); diff --git a/src/index.h b/src/index.h index 40577e105..4c448fabf 100644 --- a/src/index.h +++ b/src/index.h @@ -48,7 +48,7 @@ struct git_index_conflict_iterator { }; extern void git_index_entry__init_from_stat( - git_index_entry *entry, struct stat *st); + git_index_entry *entry, struct stat *st, bool trust_mode); extern size_t git_index__prefix_position(git_index *index, const char *path); diff --git a/src/iterator.c b/src/iterator.c index ea6b45e88..c0d7862ff 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -1175,7 +1175,7 @@ static int fs_iterator__update_entry(fs_iterator *fi) return GIT_ITEROVER; fi->entry.path = ps->path; - git_index_entry__init_from_stat(&fi->entry, &ps->st); + git_index_entry__init_from_stat(&fi->entry, &ps->st, true); /* need different mode here to keep directories during iteration */ fi->entry.mode = git_futils_canonical_mode(ps->st.st_mode); diff --git a/src/path.c b/src/path.c index 27abd062b..d45751cd1 100644 --- a/src/path.c +++ b/src/path.c @@ -538,16 +538,35 @@ bool git_path_is_empty_dir(const char *path) #endif -int git_path_lstat(const char *path, struct stat *st) +int git_path_set_error(int errno_value, const char *path, const char *action) { - int err = 0; - - if (p_lstat(path, st) < 0) { - err = (errno == ENOENT) ? GIT_ENOTFOUND : -1; - giterr_set(GITERR_OS, "Failed to stat file '%s'", path); + switch (errno_value) { + case ENOENT: + case ENOTDIR: + 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); + return GIT_EINVALIDSPEC; + + case EEXIST: + giterr_set(GITERR_OS, "Failed %s - '%s' already exists", action, path); + return GIT_EEXISTS; + + default: + giterr_set(GITERR_OS, "Could not %s '%s'", action, path); + return -1; } +} + +int git_path_lstat(const char *path, struct stat *st) +{ + if (p_lstat(path, st) == 0) + return 0; - return err; + return git_path_set_error(errno, path, "stat"); } static bool _check_dir_contents( diff --git a/src/path.h b/src/path.h index 2cfd714cd..175756938 100644 --- a/src/path.h +++ b/src/path.h @@ -358,6 +358,10 @@ extern int git_path_dirload_with_stat( const char *end_stat, git_vector *contents); +/* translate errno to libgit2 error code and set error message */ +extern int git_path_set_error( + int errno_value, const char *path, const char *action); + /* check if non-ascii characters are present in filename */ extern bool git_path_has_non_ascii(const char *path, size_t pathlen); diff --git a/src/repository.c b/src/repository.c index 52509ffc1..23cafe05a 100644 --- a/src/repository.c +++ b/src/repository.c @@ -961,80 +961,121 @@ static int create_empty_file(const char *path, mode_t mode) return 0; } -static int repo_init_config( - git_config *parent, - const char *repo_dir, - const char *work_dir, - uint32_t flags, - uint32_t mode) +static int repo_local_config( + git_config **out, + git_buf *config_dir, + git_repository *repo, + const char *repo_dir) { int error = 0; - git_buf buf = GIT_BUF_INIT; - const char *cfg_path = NULL; - git_config *config = NULL; - bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0); + git_config *parent; + const char *cfg_path; -#define SET_REPO_CONFIG(TYPE, NAME, VAL) do {\ - if ((error = git_config_set_##TYPE(config, NAME, VAL)) < 0) \ - goto cleanup; } while (0) - - if (git_buf_joinpath(&buf, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0) + if (git_buf_joinpath(config_dir, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0) return -1; - cfg_path = git_buf_cstr(&buf); + cfg_path = git_buf_cstr(config_dir); + /* make LOCAL config if missing */ if (!git_path_isfile(cfg_path) && (error = create_empty_file(cfg_path, GIT_CONFIG_FILE_MODE)) < 0) - goto cleanup; + return error; - if (!parent) - error = git_config_open_ondisk(&config, cfg_path); - else if ((error = git_config_open_level( - &config, parent, GIT_CONFIG_LEVEL_LOCAL)) < 0) - { + /* if no repo, just open that file directly */ + if (!repo) + return git_config_open_ondisk(out, cfg_path); + + /* otherwise, open parent config and get that level */ + if ((error = git_repository_config__weakptr(&parent, repo)) < 0) + return error; + + if (git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL) < 0) { giterr_clear(); if (!(error = git_config_add_file_ondisk( parent, cfg_path, GIT_CONFIG_LEVEL_LOCAL, false))) - error = git_config_open_level( - &config, parent, GIT_CONFIG_LEVEL_LOCAL); + error = git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL); } - if (error < 0) - goto cleanup; - if ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0 && - (error = check_repositoryformatversion(config)) < 0) - goto cleanup; + git_config_free(parent); + + return error; +} + +static int repo_init_fs_configs( + git_config *cfg, + const char *cfg_path, + const char *repo_dir, + const char *work_dir, + bool update_ignorecase) +{ + int error = 0; + + if (!work_dir) + work_dir = repo_dir; + + if ((error = git_config_set_bool( + cfg, "core.filemode", is_chmod_supported(cfg_path))) < 0) + return error; + + if (!are_symlinks_supported(work_dir)) { + if ((error = git_config_set_bool(cfg, "core.symlinks", false)) < 0) + return error; + } else if (git_config_delete_entry(cfg, "core.symlinks") < 0) + giterr_clear(); - SET_REPO_CONFIG( - bool, "core.bare", is_bare); - SET_REPO_CONFIG( - int32, "core.repositoryformatversion", GIT_REPO_VERSION); - SET_REPO_CONFIG( - bool, "core.filemode", is_chmod_supported(cfg_path)); + if (update_ignorecase) { + if (is_filesystem_case_insensitive(repo_dir)) { + if ((error = git_config_set_bool(cfg, "core.ignorecase", true)) < 0) + return error; + } else if (git_config_delete_entry(cfg, "core.ignorecase") < 0) + giterr_clear(); + } #ifdef GIT_USE_ICONV - SET_REPO_CONFIG( - bool, "core.precomposeunicode", - does_fs_decompose_unicode_paths(is_bare ? repo_dir : work_dir)); + if ((error = git_config_set_bool( + cfg, "core.precomposeunicode", + does_fs_decompose_unicode_paths(work_dir))) < 0) + return error; #endif - if (!are_symlinks_supported(is_bare ? repo_dir : work_dir)) - SET_REPO_CONFIG(bool, "core.symlinks", false); + return 0; +} - /* core git does not do this on a reinit, but it is a property of - * the filesystem, so I think we should... - */ - if (!(flags & GIT_REPOSITORY_INIT__IS_REINIT) && - is_filesystem_case_insensitive(repo_dir)) - SET_REPO_CONFIG(bool, "core.ignorecase", true); +static int repo_init_config( + const char *repo_dir, + const char *work_dir, + uint32_t flags, + uint32_t mode) +{ + int error = 0; + git_buf cfg_path = GIT_BUF_INIT; + git_config *config = NULL; + bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0); + bool is_reinit = ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0); + + if ((error = repo_local_config(&config, &cfg_path, NULL, repo_dir)) < 0) + goto cleanup; + + if (is_reinit && (error = check_repositoryformatversion(config)) < 0) + goto cleanup; + +#define SET_REPO_CONFIG(TYPE, NAME, VAL) do { \ + if ((error = git_config_set_##TYPE(config, NAME, VAL)) < 0) \ + goto cleanup; } while (0) + + SET_REPO_CONFIG(bool, "core.bare", is_bare); + SET_REPO_CONFIG(int32, "core.repositoryformatversion", GIT_REPO_VERSION); + + if ((error = repo_init_fs_configs( + config, cfg_path.ptr, repo_dir, work_dir, !is_reinit)) < 0) + goto cleanup; if (!is_bare) { SET_REPO_CONFIG(bool, "core.logallrefupdates", true); - if (!(flags & GIT_REPOSITORY_INIT__NATURAL_WD)) { + if (!(flags & GIT_REPOSITORY_INIT__NATURAL_WD)) SET_REPO_CONFIG(string, "core.worktree", work_dir); - } - else if ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0) { + else if (is_reinit) { if (git_config_delete_entry(config, "core.worktree") < 0) giterr_clear(); } @@ -1050,38 +1091,44 @@ static int repo_init_config( } cleanup: - git_buf_free(&buf); + git_buf_free(&cfg_path); git_config_free(config); return error; } -int git_repository_reset_filesystem(git_repository *repo) +static int repo_reset_submodule_fs(git_submodule *sm, const char *n, void *p) { - int error = 0; - uint32_t flags = 0; - const char *repo_dir, *work_dir; - git_config *cfg; + git_repository *smrepo = NULL; + GIT_UNUSED(n); GIT_UNUSED(p); - assert(repo); + if (git_submodule_open(&smrepo, sm) < 0 || + git_repository_reset_filesystem(smrepo, true) < 0) + giterr_clear(); + git_repository_free(smrepo); - repo_dir = git_repository_path(repo); - work_dir = git_repository_workdir(repo); + return 0; +} - if (git_repository_is_bare(repo)) - flags |= GIT_REPOSITORY_INIT_BARE; - else if (!git__prefixcmp(repo_dir, work_dir) && - !strcmp(repo_dir + strlen(work_dir), DOT_GIT "/")) - flags |= GIT_REPOSITORY_INIT__NATURAL_WD; +int git_repository_reset_filesystem(git_repository *repo, int recurse) +{ + int error = 0; + git_buf path = GIT_BUF_INIT; + git_config *config = NULL; + const char *repo_dir = git_repository_path(repo); - if ((error = git_repository_config(&cfg, repo)) < 0) - return error; + if (!(error = repo_local_config(&config, &path, repo, repo_dir))) + error = repo_init_fs_configs( + config, path.ptr, repo_dir, git_repository_workdir(repo), true); - error = repo_init_config(cfg, repo_dir, work_dir, flags, 0); + git_config_free(config); + git_buf_free(&path); - git_config_free(cfg); git_repository__cvar_cache_clear(repo); + if (!repo->is_bare && recurse) + (void)git_submodule_foreach(repo, repo_reset_submodule_fs, NULL); + return error; } @@ -1473,7 +1520,7 @@ int git_repository_init_ext( opts->flags |= GIT_REPOSITORY_INIT__IS_REINIT; error = repo_init_config( - NULL, repo_path.ptr, wd_path.ptr, opts->flags, opts->mode); + repo_path.ptr, wd_path.ptr, opts->flags, opts->mode); /* TODO: reinitialize the templates */ } @@ -1481,7 +1528,7 @@ int git_repository_init_ext( if (!(error = repo_init_structure( repo_path.ptr, wd_path.ptr, opts)) && !(error = repo_init_config( - NULL, repo_path.ptr, wd_path.ptr, opts->flags, opts->mode))) + repo_path.ptr, wd_path.ptr, opts->flags, opts->mode))) error = repo_init_create_head( repo_path.ptr, opts->initial_head); } diff --git a/src/submodule.c b/src/submodule.c index 121383b9c..12ade83fe 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -372,7 +372,8 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index) memset(&entry, 0, sizeof(entry)); entry.path = sm->path; - git_index_entry__init_from_stat(&entry, &st); + git_index_entry__init_from_stat( + &entry, &st, !(git_index_caps(index) & GIT_INDEXCAP_NO_FILEMODE)); /* calling git_submodule_open will have set sm->wd_oid if possible */ if ((sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) == 0) { diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 2f490529c..18f717b0f 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -125,8 +125,8 @@ static int do_lstat( errno = ENOENT; - /* We need POSIX behavior, then ENOTDIR must set when any of the folders in the - * file path is a regular file,otherwise ENOENT must be set. + /* To match POSIX behavior, set ENOTDIR when any of the folders in the + * file path is a regular file, otherwise set ENOENT. */ if (posix_enotdir) { /* scan up path until we find an existing item */ diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index c3abc1f95..82ec5c065 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -191,7 +191,7 @@ git_repository *cl_git_sandbox_init(const char *sandbox) cl_git_pass(git_repository_open(&_cl_repo, sandbox)); /* Adjust configs after copying to new filesystem */ - cl_git_pass(git_repository_reset_filesystem(_cl_repo)); + cl_git_pass(git_repository_reset_filesystem(_cl_repo, 0)); return _cl_repo; } diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c index 7aab8f409..1dbfc9ac5 100644 --- a/tests-clar/diff/patch.c +++ b/tests-clar/diff/patch.c @@ -240,7 +240,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) git_repository_set_config(g_repo, cfg); git_config_free(cfg); - git_repository_reset_filesystem(g_repo); + git_repository_reset_filesystem(g_repo, false); cl_git_pass( git_futils_readbuffer(&old_content, "renames/songof7cities.txt")); @@ -524,7 +524,7 @@ void test_diff_patch__line_counts_with_eofnl(void) git_repository_set_config(g_repo, cfg); git_config_free(cfg); - git_repository_reset_filesystem(g_repo); + git_repository_reset_filesystem(g_repo, false); cl_git_pass(git_futils_readbuffer(&content, "renames/songof7cities.txt")); diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index 6c17b41c6..aeef7b963 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -761,16 +761,7 @@ void test_diff_workdir__submodules(void) git_diff_list *diff = NULL; diff_expects exp; - g_repo = cl_git_sandbox_init("submod2"); - - cl_fixture_sandbox("submod2_target"); - p_rename("submod2_target/.gitted", "submod2_target/.git"); - - rewrite_gitmodules(git_repository_workdir(g_repo)); - p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git"); - p_rename("submod2/not/.gitted", "submod2/not/.git"); - - cl_fixture_cleanup("submod2_target"); + g_repo = setup_fixture_submod2(); a = resolve_commit_oid_to_tree(g_repo, a_commit); diff --git a/tests-clar/index/addall.c b/tests-clar/index/addall.c index f46a1e16c..3b5f5f22d 100644 --- a/tests-clar/index/addall.c +++ b/tests-clar/index/addall.c @@ -111,8 +111,9 @@ static void check_stat_data(git_index *index, const char *path, bool match) cl_assert(st.st_gid == entry->gid); cl_assert_equal_i_fmt( GIT_MODE_TYPE(st.st_mode), GIT_MODE_TYPE(entry->mode), "%07o"); - cl_assert_equal_b( - GIT_PERMS_IS_EXEC(st.st_mode), GIT_PERMS_IS_EXEC(entry->mode)); + if (cl_is_chmod_supported()) + cl_assert_equal_b( + GIT_PERMS_IS_EXEC(st.st_mode), GIT_PERMS_IS_EXEC(entry->mode)); } else { /* most things will still match */ cl_assert(st.st_size != entry->file_size); diff --git a/tests-clar/index/filemodes.c b/tests-clar/index/filemodes.c index 8cbd6ff3a..013932696 100644 --- a/tests-clar/index/filemodes.c +++ b/tests-clar/index/filemodes.c @@ -74,7 +74,6 @@ static void add_and_check_mode_( void test_index_filemodes__untrusted(void) { git_index *index; - bool can_filemode = cl_is_chmod_supported(); cl_repo_set_bool(g_repo, "core.filemode", false); @@ -97,20 +96,15 @@ void test_index_filemodes__untrusted(void) replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755); add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); - /* these tests of newly added files won't give predictable results on - * filesystems without actual filemode support, so skip them. - */ - if (can_filemode) { - /* 5 - add new 0644 -> expect 0644 */ - cl_git_write2file("filemodes/new_off", "blah", 0, - O_WRONLY | O_CREAT | O_TRUNC, 0644); - add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); - - /* 6 - add new 0755 -> expect 0755 */ - cl_git_write2file("filemodes/new_on", "blah", 0, - O_WRONLY | O_CREAT | O_TRUNC, 0755); - add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE); - } + /* 5 - add new 0644 -> expect 0644 */ + cl_git_write2file("filemodes/new_off", "blah", 0, + O_WRONLY | O_CREAT | O_TRUNC, 0644); + add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); + + /* 6 - add new 0755 -> expect 0644 if core.filemode == false */ + cl_git_write2file("filemodes/new_on", "blah", 0, + O_WRONLY | O_CREAT | O_TRUNC, 0755); + add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB); git_index_free(index); } diff --git a/tests-clar/refs/unicode.c b/tests-clar/refs/unicode.c index 2ec103275..b29c63e2b 100644 --- a/tests-clar/refs/unicode.c +++ b/tests-clar/refs/unicode.c @@ -22,23 +22,38 @@ void test_refs_unicode__create_and_lookup(void) git_reference *ref0, *ref1, *ref2; git_repository *repo2; - const char *REFNAME = "refs/heads/" "\305" "ngstr" "\366" "m"; + const char *REFNAME = "refs/heads/" "\303\205" "ngstr" "\303\266" "m"; + const char *REFNAME_DECOMPOSED = + "refs/heads/" "A" "\314\212" "ngstro" "\314\210" "m"; const char *master = "refs/heads/master"; /* Create the reference */ cl_git_pass(git_reference_lookup(&ref0, repo, master)); cl_git_pass(git_reference_create(&ref1, repo, REFNAME, git_reference_target(ref0), 0)); cl_assert_equal_s(REFNAME, git_reference_name(ref1)); + git_reference_free(ref0); /* Lookup the reference in a different instance of the repository */ cl_git_pass(git_repository_open(&repo2, "testrepo.git")); + cl_git_pass(git_reference_lookup(&ref2, repo2, REFNAME)); + cl_assert_equal_i( + 0, git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2))); + cl_assert_equal_s(REFNAME, git_reference_name(ref2)); + git_reference_free(ref2); + +#if GIT_USE_ICONV + /* Lookup reference by decomposed unicode name */ - cl_assert(git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2)) == 0); + cl_git_pass(git_reference_lookup(&ref2, repo2, REFNAME_DECOMPOSED)); + cl_assert_equal_i( + 0, git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2))); cl_assert_equal_s(REFNAME, git_reference_name(ref2)); + git_reference_free(ref2); +#endif + + /* Cleanup */ - git_reference_free(ref0); git_reference_free(ref1); - git_reference_free(ref2); git_repository_free(repo2); } diff --git a/tests-clar/submodule/lookup.c b/tests-clar/submodule/lookup.c index b626cdf04..5f320e702 100644 --- a/tests-clar/submodule/lookup.c +++ b/tests-clar/submodule/lookup.c @@ -7,20 +7,7 @@ static git_repository *g_repo = NULL; void test_submodule_lookup__initialize(void) { - g_repo = cl_git_sandbox_init("submod2"); - - cl_fixture_sandbox("submod2_target"); - p_rename("submod2_target/.gitted", "submod2_target/.git"); - - /* must create submod2_target before rewrite so prettify will work */ - rewrite_gitmodules(git_repository_workdir(g_repo)); - p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git"); -} - -void test_submodule_lookup__cleanup(void) -{ - cl_git_sandbox_cleanup(); - cl_fixture_cleanup("submod2_target"); + g_repo = setup_fixture_submod2(); } void test_submodule_lookup__simple_lookup(void) diff --git a/tests-clar/submodule/modify.c b/tests-clar/submodule/modify.c index c0498ce6e..e326287a6 100644 --- a/tests-clar/submodule/modify.c +++ b/tests-clar/submodule/modify.c @@ -11,20 +11,7 @@ static git_repository *g_repo = NULL; void test_submodule_modify__initialize(void) { - g_repo = cl_git_sandbox_init("submod2"); - - cl_fixture_sandbox("submod2_target"); - p_rename("submod2_target/.gitted", "submod2_target/.git"); - - /* must create submod2_target before rewrite so prettify will work */ - rewrite_gitmodules(git_repository_workdir(g_repo)); - p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git"); -} - -void test_submodule_modify__cleanup(void) -{ - cl_git_sandbox_cleanup(); - cl_fixture_cleanup("submod2_target"); + g_repo = setup_fixture_submod2(); } void test_submodule_modify__add(void) diff --git a/tests-clar/submodule/submodule_helpers.c b/tests-clar/submodule/submodule_helpers.c index 3e79c77fd..cc3b7a2e3 100644 --- a/tests-clar/submodule/submodule_helpers.c +++ b/tests-clar/submodule/submodule_helpers.c @@ -102,6 +102,8 @@ git_repository *setup_fixture_submodules(void) cl_set_cleanup(cleanup_fixture_submodules, "testrepo.git"); + cl_git_pass(git_repository_reset_filesystem(repo, 1)); + return repo; } @@ -118,5 +120,7 @@ git_repository *setup_fixture_submod2(void) cl_set_cleanup(cleanup_fixture_submodules, "submod2_target"); + cl_git_pass(git_repository_reset_filesystem(repo, 1)); + return repo; } -- cgit v1.2.1 From a58eecd436ff9344cda18efcdfa1da034503512e Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 8 Oct 2013 13:40:52 -0700 Subject: WinHTTP: set Accept header for POSTs --- src/transports/winhttp.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 067d6fcc3..95c9d10bb 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -265,8 +265,8 @@ static int winhttp_stream_connect(winhttp_stream *s) goto on_error; } - /* Send Content-Type header -- only necessary on a POST */ if (post_verb == s->verb) { + /* Send Content-Type header -- only necessary on a POST */ git_buf_clear(&buf); if (git_buf_printf(&buf, "Content-Type: application/x-git-%s-request", s->service) < 0) goto on_error; @@ -277,6 +277,16 @@ static int winhttp_stream_connect(winhttp_stream *s) giterr_set(GITERR_OS, "Failed to add a header to the request"); goto on_error; } + + /* Set the Accept header */ + git_buf_clear(&buf); + if (git_buf_printf(&buf, "Accept: application/x-git-%s-result\r\n", s->service) < 0) + goto on_error; + git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)); + if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_REPLACE)) { + giterr_set(GITERR_OS, "Failed to add a header to the request"); + goto on_error; + } } /* If requested, disable certificate validation */ -- cgit v1.2.1 From 1fd21b0342f4fc5ad38a74242385c202b272da80 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 8 Oct 2013 13:59:43 -0700 Subject: Add Assembla unit test --- tests-clar/online/clone.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index 4a6ade52d..aa3d6b26a 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -11,6 +11,7 @@ #define BB_REPO_URL "https://libgit2@bitbucket.org/libgit2/testgitrepository.git" #define BB_REPO_URL_WITH_PASS "https://libgit2:libgit2@bitbucket.org/libgit2/testgitrepository.git" #define BB_REPO_URL_WITH_WRONG_PASS "https://libgit2:wrong@bitbucket.org/libgit2/testgitrepository.git" +#define ASSEMBLA_REPO_URL "https://libgit2:_Libgit2@git.assembla.com/libgit2-test-repos.git" static git_repository *g_repo; static git_clone_options g_options; @@ -227,6 +228,11 @@ void test_online_clone__bitbucket_style(void) cl_fixture_cleanup("./foo"); } +void test_online_clone__assembla_style(void) +{ + cl_git_pass(git_clone(&g_repo, ASSEMBLA_REPO_URL, "./foo", NULL)); +} + static int cancel_at_half(const git_transfer_progress *stats, void *payload) { GIT_UNUSED(payload); -- cgit v1.2.1 From d5e83627e4ed764115175dc42090afe0df332fe3 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 8 Oct 2013 14:41:32 -0700 Subject: Case sensitivity issues on Linux A couple of tests were actually dealing incorrectly with case sensitivity issues on Linux because they were relying on having core.ignorecase set to true. Now that the fixture initialization sets the case sensitivity to be accurate for the platform, it exposed bugs in these tests. --- tests-clar/status/renames.c | 14 +++++++------- tests-clar/submodule/status.c | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tests-clar/status/renames.c b/tests-clar/status/renames.c index de84a574d..16fd02676 100644 --- a/tests-clar/status/renames.c +++ b/tests-clar/status/renames.c @@ -69,14 +69,14 @@ static void test_status( actual = git_status_byindex(status_list, i); expected = &expected_list[i]; - cl_assert_equal_i_fmt(expected->status, actual->status, "%04x"); - oldname = actual->head_to_index ? actual->head_to_index->old_file.path : actual->index_to_workdir ? actual->index_to_workdir->old_file.path : NULL; newname = actual->index_to_workdir ? actual->index_to_workdir->new_file.path : actual->head_to_index ? actual->head_to_index->new_file.path : NULL; + cl_assert_equal_i_fmt(expected->status, actual->status, "%04x"); + if (oldname) cl_assert(git__strcmp(oldname, expected->oldname) == 0); else @@ -507,14 +507,14 @@ void test_status_renames__both_casechange_two(void) "untimely.txt", "untimeliest.txt" } }; struct status_entry expected_case[] = { - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED | - GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, - "ikeepsix.txt", "ikeepsix.txt" }, - { GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_RENAMED, - "sixserving.txt", "SixServing.txt" }, { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_MODIFIED | GIT_STATUS_WT_RENAMED, "songof7cities.txt", "SONGOF7.txt" }, + { GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_RENAMED, + "sixserving.txt", "SixServing.txt" }, + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED | + GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, + "ikeepsix.txt", "ikeepsix.txt" }, { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, "untimely.txt", "untimeliest.txt" } }; diff --git a/tests-clar/submodule/status.c b/tests-clar/submodule/status.c index f1227a575..f5111c84f 100644 --- a/tests-clar/submodule/status.c +++ b/tests-clar/submodule/status.c @@ -388,7 +388,8 @@ void test_submodule_status__iterator(void) opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_INCLUDE_UNMODIFIED | GIT_STATUS_OPT_INCLUDE_IGNORED | - GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; + GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS | + GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY; cl_git_pass(git_status_foreach_ext( g_repo, &opts, confirm_submodule_status, &exp)); -- cgit v1.2.1 From 3dc3c723dac9fd2550530675b61849f2215ef767 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 8 Oct 2013 15:52:37 -0700 Subject: Combine WinHTTP API calls --- src/transports/winhttp.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 95c9d10bb..702243513 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -266,24 +266,18 @@ static int winhttp_stream_connect(winhttp_stream *s) } if (post_verb == s->verb) { - /* Send Content-Type header -- only necessary on a POST */ + /* Send Content-Type and Accept headers -- only necessary on a POST */ git_buf_clear(&buf); - if (git_buf_printf(&buf, "Content-Type: application/x-git-%s-request", s->service) < 0) + if (git_buf_printf(&buf, + "Content-Type: application/x-git-%s-request\r\n" + "Accept: application/x-git-%s-result\r\n", + s->service, s->service) < 0) goto on_error; git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)); - if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) { - giterr_set(GITERR_OS, "Failed to add a header to the request"); - goto on_error; - } - - /* Set the Accept header */ - git_buf_clear(&buf); - if (git_buf_printf(&buf, "Accept: application/x-git-%s-result\r\n", s->service) < 0) - goto on_error; - git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)); - if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_REPLACE)) { + 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"); goto on_error; } -- cgit v1.2.1 From 92dac975869bf6207eca0754345dc9aa7fec8992 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 8 Oct 2013 16:35:57 -0700 Subject: Make reference lookups apply precomposeunicode Before these changes, looking up a reference would return the same precomposed or decomposed form of the reference name that was used to look it up, so on MacOS which ignores the difference between the two, a single reference could be looked up either way and git_reference_name would return the form of the name that was used to look it up! This change makes lookup always return the precomposed name if core.precomposeunicode is set regardless of which version was used to look it up. The reference iterator was already returning the precomposed form from earlier work. This also updates the CMakeLists.txt rules for enabling iconv usage because the clar tests for this code were actually not being activated properly with the old version. Finally, this moves git_repository_reset_filesystem from include/ git2/repository.h to include/git2/sys/repository.h since it is not really a function that normal library users should have to think about very often. --- CMakeLists.txt | 14 +++++++-- include/git2/refs.h | 8 +++--- include/git2/repository.h | 19 ------------ include/git2/sys/repository.h | 20 ++++++++++++- src/path.h | 5 ---- src/refs.c | 67 ++++++++++++++++++++++++++++--------------- src/refs.h | 2 ++ tests-clar/clar_libgit2.c | 1 + tests-clar/refs/unicode.c | 15 ++++------ 9 files changed, 87 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 62ebbf4e5..c7414996b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,9 +27,14 @@ OPTION( BUILD_EXAMPLES "Build library usage example apps" OFF ) OPTION( TAGS "Generate tags" OFF ) OPTION( PROFILE "Generate profiling information" OFF ) OPTION( ENABLE_TRACE "Enables tracing support" OFF ) -OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF ) +OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF ) -OPTION( ANDROID "Build for android NDK" OFF ) +OPTION( ANDROID "Build for android NDK" OFF ) + +OPTION( USE_ICONV "Link with and use iconv library" OFF ) +IF(APPLE) + SET( USE_ICONV ON ) +ENDIF() IF(MSVC) # This option is only available when building with MSVC. By default, libgit2 @@ -58,8 +63,11 @@ FUNCTION(TARGET_OS_LIBRARIES target) TARGET_LINK_LIBRARIES(${target} socket nsl) ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux") TARGET_LINK_LIBRARIES(${target} rt) - ELSEIF(APPLE) + ENDIF() + + IF(USE_ICONV) TARGET_LINK_LIBRARIES(${target} iconv) + ADD_DEFINITIONS(-DGIT_USE_ICONV) ENDIF() IF(THREADSAFE) diff --git a/include/git2/refs.h b/include/git2/refs.h index 4871e9820..4041947f6 100644 --- a/include/git2/refs.h +++ b/include/git2/refs.h @@ -453,7 +453,7 @@ GIT_EXTERN(int) git_reference_is_remote(git_reference *ref); GIT_EXTERN(int) git_reference_is_tag(git_reference *ref); typedef enum { - GIT_REF_FORMAT_NORMAL = 0, + GIT_REF_FORMAT_NORMAL = 0u, /** * Control whether one-level refnames are accepted @@ -461,7 +461,7 @@ typedef enum { * components). Those are expected to be written only using * uppercase letters and underscore (FETCH_HEAD, ...) */ - GIT_REF_FORMAT_ALLOW_ONELEVEL = (1 << 0), + GIT_REF_FORMAT_ALLOW_ONELEVEL = (1u << 0), /** * Interpret the provided name as a reference pattern for a @@ -470,14 +470,14 @@ typedef enum { * in place of a one full pathname component * (e.g., foo//bar but not foo/bar). */ - GIT_REF_FORMAT_REFSPEC_PATTERN = (1 << 1), + GIT_REF_FORMAT_REFSPEC_PATTERN = (1u << 1), /** * Interpret the name as part of a refspec in shorthand form * so the `ONELEVEL` naming rules aren't enforced and 'master' * becomes a valid name. */ - GIT_REF_FORMAT_REFSPEC_SHORTHAND = (1 << 2), + GIT_REF_FORMAT_REFSPEC_SHORTHAND = (1u << 2), } git_reference_normalize_t; /** diff --git a/include/git2/repository.h b/include/git2/repository.h index 28d8400f2..b4d561992 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -287,25 +287,6 @@ GIT_EXTERN(int) git_repository_init_ext( const char *repo_path, git_repository_init_options *opts); -/** - * Update the filesystem config settings for an open repository - * - * When a repository is initialized, config values are set based on the - * properties of the filesystem that the repository is on, such as - * "core.ignorecase", "core.filemode", "core.symlinks", etc. If the - * repository is moved to a new filesystem, these properties may no - * longer be correct and API calls may not behave as expected. This - * call reruns the phase of repository initialization that sets those - * properties to compensate for the current filesystem of the repo. - * - * @param repo A repository object - * @param recurse_submodules Should submodules be reset recursively - * @returrn 0 on success, < 0 on error - */ -GIT_EXTERN(int) git_repository_reset_filesystem( - git_repository *repo, - int recurse_submodules); - /** * Retrieve and resolve the reference pointed at by HEAD. * diff --git a/include/git2/sys/repository.h b/include/git2/sys/repository.h index ba3d65ae5..e77b1dcba 100644 --- a/include/git2/sys/repository.h +++ b/include/git2/sys/repository.h @@ -27,7 +27,6 @@ GIT_BEGIN_DECL */ GIT_EXTERN(int) git_repository_new(git_repository **out); - /** * Reset all the internal state in a repository. * @@ -41,6 +40,25 @@ GIT_EXTERN(int) git_repository_new(git_repository **out); */ GIT_EXTERN(void) git_repository__cleanup(git_repository *repo); +/** + * Update the filesystem config settings for an open repository + * + * When a repository is initialized, config values are set based on the + * properties of the filesystem that the repository is on, such as + * "core.ignorecase", "core.filemode", "core.symlinks", etc. If the + * repository is moved to a new filesystem, these properties may no + * longer be correct and API calls may not behave as expected. This + * call reruns the phase of repository initialization that sets those + * properties to compensate for the current filesystem of the repo. + * + * @param repo A repository object + * @param recurse_submodules Should submodules be reset recursively + * @returrn 0 on success, < 0 on error + */ +GIT_EXTERN(int) git_repository_reset_filesystem( + git_repository *repo, + int recurse_submodules); + /** * Set the configuration file for this repository * diff --git a/src/path.h b/src/path.h index 175756938..eaf94d486 100644 --- a/src/path.h +++ b/src/path.h @@ -365,11 +365,6 @@ extern int git_path_set_error( /* check if non-ascii characters are present in filename */ extern bool git_path_has_non_ascii(const char *path, size_t pathlen); -/* only enable iconv on Mac for now */ -#ifdef __APPLE__ -#define GIT_USE_ICONV 1 -#endif - #define GIT_PATH_REPO_ENCODING "UTF-8" #ifdef __APPLE__ diff --git a/src/refs.c b/src/refs.c index c045ab9dc..0da02a666 100644 --- a/src/refs.c +++ b/src/refs.c @@ -138,6 +138,22 @@ int git_reference_name_to_id( return 0; } +static int reference_normalize_for_repo( + char *out, + size_t out_size, + git_repository *repo, + const char *name) +{ + int precompose; + unsigned int flags = GIT_REF_FORMAT_ALLOW_ONELEVEL; + + if (!git_repository__cvar(&precompose, repo, GIT_CVAR_PRECOMPOSE) && + precompose) + flags |= GIT_REF_FORMAT__PRECOMPOSE_UNICODE; + + return git_reference_normalize_name(out, out_size, name, flags); +} + int git_reference_lookup_resolved( git_reference **ref_out, git_repository *repo, @@ -159,13 +175,13 @@ int git_reference_lookup_resolved( else if (max_nesting < 0) max_nesting = DEFAULT_NESTING_LEVEL; - strncpy(scan_name, name, GIT_REFNAME_MAX); scan_type = GIT_REF_SYMBOLIC; - if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) - return -1; + if ((error = reference_normalize_for_repo( + scan_name, sizeof(scan_name), repo, name)) < 0) + return error; - if ((error = git_reference__normalize_name_lax(scan_name, GIT_REFNAME_MAX, name)) < 0) + if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) return error; for (nesting = max_nesting; @@ -173,7 +189,7 @@ int git_reference_lookup_resolved( nesting--) { if (nesting != max_nesting) { - strncpy(scan_name, ref->target.symbolic, GIT_REFNAME_MAX); + strncpy(scan_name, ref->target.symbolic, sizeof(scan_name)); git_reference_free(ref); } @@ -711,17 +727,18 @@ static bool is_all_caps_and_underscore(const char *name, size_t len) return true; } +/* Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100 */ int git_reference__normalize_name( git_buf *buf, const char *name, unsigned int flags) { - // Inspired from https://github.com/git/git/blob/f06d47e7e0d9db709ee204ed13a8a7486149f494/refs.c#L36-100 - char *current; int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC; unsigned int process_flags; bool normalize = (buf != NULL); + git_path_iconv_t ic = GIT_PATH_ICONV_INIT; + assert(name); process_flags = flags; @@ -733,6 +750,13 @@ int git_reference__normalize_name( if (normalize) git_buf_clear(buf); + if ((flags & GIT_REF_FORMAT__PRECOMPOSE_UNICODE) != 0) { + size_t namelen = strlen(current); + if ((error = git_path_iconv_init_precompose(&ic)) < 0 || + (error = git_path_iconv(&ic, ¤t, &namelen)) < 0) + goto cleanup; + } + while (true) { segment_len = ensure_segment_validity(current); if (segment_len < 0) { @@ -809,6 +833,8 @@ cleanup: if (error && normalize) git_buf_free(buf); + git_path_iconv_clear(&ic); + return error; } @@ -983,9 +1009,9 @@ static int peel_error(int error, git_reference *ref, const char* msg) } int git_reference_peel( - git_object **peeled, - git_reference *ref, - git_otype target_type) + git_object **peeled, + git_reference *ref, + git_otype target_type) { git_reference *resolved = NULL; git_object *target = NULL; @@ -1027,24 +1053,19 @@ cleanup: return error; } -int git_reference__is_valid_name( - const char *refname, - unsigned int flags) +int git_reference__is_valid_name(const char *refname, unsigned int flags) { - int error; - - error = git_reference__normalize_name(NULL, refname, flags) == 0; - giterr_clear(); + if (git_reference__normalize_name(NULL, refname, flags) < 0) { + giterr_clear(); + return false; + } - return error; + return true; } -int git_reference_is_valid_name( - const char *refname) +int git_reference_is_valid_name(const char *refname) { - return git_reference__is_valid_name( - refname, - GIT_REF_FORMAT_ALLOW_ONELEVEL); + return git_reference__is_valid_name(refname, GIT_REF_FORMAT_ALLOW_ONELEVEL); } const char *git_reference_shorthand(git_reference *ref) diff --git a/src/refs.h b/src/refs.h index 4b91c25e8..80c7703fc 100644 --- a/src/refs.h +++ b/src/refs.h @@ -46,6 +46,8 @@ #define GIT_STASH_FILE "stash" #define GIT_REFS_STASH_FILE GIT_REFS_DIR GIT_STASH_FILE +#define GIT_REF_FORMAT__PRECOMPOSE_UNICODE (1u << 16) + #define GIT_REFNAME_MAX 1024 struct git_reference { diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 82ec5c065..9f65953f5 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "posix.h" #include "path.h" +#include "git2/sys/repository.h" void cl_git_report_failure( int error, const char *file, int line, const char *fncall) diff --git a/tests-clar/refs/unicode.c b/tests-clar/refs/unicode.c index b29c63e2b..b56012869 100644 --- a/tests-clar/refs/unicode.c +++ b/tests-clar/refs/unicode.c @@ -4,17 +4,13 @@ static git_repository *repo; void test_refs_unicode__initialize(void) { - cl_fixture_sandbox("testrepo.git"); - - cl_git_pass(git_repository_open(&repo, "testrepo.git")); + repo = cl_git_sandbox_init("testrepo.git"); } void test_refs_unicode__cleanup(void) { - git_repository_free(repo); + cl_git_sandbox_cleanup(); repo = NULL; - - cl_fixture_cleanup("testrepo.git"); } void test_refs_unicode__create_and_lookup(void) @@ -23,13 +19,12 @@ void test_refs_unicode__create_and_lookup(void) git_repository *repo2; const char *REFNAME = "refs/heads/" "\303\205" "ngstr" "\303\266" "m"; - const char *REFNAME_DECOMPOSED = - "refs/heads/" "A" "\314\212" "ngstro" "\314\210" "m"; const char *master = "refs/heads/master"; /* Create the reference */ cl_git_pass(git_reference_lookup(&ref0, repo, master)); - cl_git_pass(git_reference_create(&ref1, repo, REFNAME, git_reference_target(ref0), 0)); + cl_git_pass(git_reference_create( + &ref1, repo, REFNAME, git_reference_target(ref0), 0)); cl_assert_equal_s(REFNAME, git_reference_name(ref1)); git_reference_free(ref0); @@ -45,6 +40,8 @@ void test_refs_unicode__create_and_lookup(void) #if GIT_USE_ICONV /* Lookup reference by decomposed unicode name */ +#define REFNAME_DECOMPOSED "refs/heads/" "A" "\314\212" "ngstro" "\314\210" "m" + cl_git_pass(git_reference_lookup(&ref2, repo2, REFNAME_DECOMPOSED)); cl_assert_equal_i( 0, git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2))); -- cgit v1.2.1 From 867f7c9b3329952dc0aebf9770019a7a01ff2691 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 8 Oct 2013 16:59:59 -0700 Subject: Rename new fn to git_repository_reinit_filesystem --- include/git2/sys/repository.h | 4 ++-- src/repository.c | 8 ++++---- tests-clar/clar_libgit2.c | 2 +- tests-clar/diff/patch.c | 4 ++-- tests-clar/submodule/submodule_helpers.c | 5 +++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/git2/sys/repository.h b/include/git2/sys/repository.h index e77b1dcba..36f8b5836 100644 --- a/include/git2/sys/repository.h +++ b/include/git2/sys/repository.h @@ -52,10 +52,10 @@ GIT_EXTERN(void) git_repository__cleanup(git_repository *repo); * properties to compensate for the current filesystem of the repo. * * @param repo A repository object - * @param recurse_submodules Should submodules be reset recursively + * @param recurse_submodules Should submodules be updated recursively * @returrn 0 on success, < 0 on error */ -GIT_EXTERN(int) git_repository_reset_filesystem( +GIT_EXTERN(int) git_repository_reinit_filesystem( git_repository *repo, int recurse_submodules); diff --git a/src/repository.c b/src/repository.c index 23cafe05a..c5ce8425f 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1097,20 +1097,20 @@ cleanup: return error; } -static int repo_reset_submodule_fs(git_submodule *sm, const char *n, void *p) +static int repo_reinit_submodule_fs(git_submodule *sm, const char *n, void *p) { git_repository *smrepo = NULL; GIT_UNUSED(n); GIT_UNUSED(p); if (git_submodule_open(&smrepo, sm) < 0 || - git_repository_reset_filesystem(smrepo, true) < 0) + git_repository_reinit_filesystem(smrepo, true) < 0) giterr_clear(); git_repository_free(smrepo); return 0; } -int git_repository_reset_filesystem(git_repository *repo, int recurse) +int git_repository_reinit_filesystem(git_repository *repo, int recurse) { int error = 0; git_buf path = GIT_BUF_INIT; @@ -1127,7 +1127,7 @@ int git_repository_reset_filesystem(git_repository *repo, int recurse) git_repository__cvar_cache_clear(repo); if (!repo->is_bare && recurse) - (void)git_submodule_foreach(repo, repo_reset_submodule_fs, NULL); + (void)git_submodule_foreach(repo, repo_reinit_submodule_fs, NULL); return error; } diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index 9f65953f5..50762cdb8 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -192,7 +192,7 @@ git_repository *cl_git_sandbox_init(const char *sandbox) cl_git_pass(git_repository_open(&_cl_repo, sandbox)); /* Adjust configs after copying to new filesystem */ - cl_git_pass(git_repository_reset_filesystem(_cl_repo, 0)); + cl_git_pass(git_repository_reinit_filesystem(_cl_repo, 0)); return _cl_repo; } diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c index 1dbfc9ac5..171abc819 100644 --- a/tests-clar/diff/patch.c +++ b/tests-clar/diff/patch.c @@ -240,7 +240,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) git_repository_set_config(g_repo, cfg); git_config_free(cfg); - git_repository_reset_filesystem(g_repo, false); + git_repository_reinit_filesystem(g_repo, false); cl_git_pass( git_futils_readbuffer(&old_content, "renames/songof7cities.txt")); @@ -524,7 +524,7 @@ void test_diff_patch__line_counts_with_eofnl(void) git_repository_set_config(g_repo, cfg); git_config_free(cfg); - git_repository_reset_filesystem(g_repo, false); + git_repository_reinit_filesystem(g_repo, false); cl_git_pass(git_futils_readbuffer(&content, "renames/songof7cities.txt")); diff --git a/tests-clar/submodule/submodule_helpers.c b/tests-clar/submodule/submodule_helpers.c index cc3b7a2e3..d5750675c 100644 --- a/tests-clar/submodule/submodule_helpers.c +++ b/tests-clar/submodule/submodule_helpers.c @@ -4,6 +4,7 @@ #include "util.h" #include "posix.h" #include "submodule_helpers.h" +#include "git2/sys/repository.h" /* rewrite gitmodules -> .gitmodules * rewrite the empty or relative urls inside each module @@ -102,7 +103,7 @@ git_repository *setup_fixture_submodules(void) cl_set_cleanup(cleanup_fixture_submodules, "testrepo.git"); - cl_git_pass(git_repository_reset_filesystem(repo, 1)); + cl_git_pass(git_repository_reinit_filesystem(repo, 1)); return repo; } @@ -120,7 +121,7 @@ git_repository *setup_fixture_submod2(void) cl_set_cleanup(cleanup_fixture_submodules, "submod2_target"); - cl_git_pass(git_repository_reset_filesystem(repo, 1)); + cl_git_pass(git_repository_reinit_filesystem(repo, 1)); return repo; } -- cgit v1.2.1 From 743531372a00e41246026910e2361684e2aad59f Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 9 Oct 2013 11:57:03 -0700 Subject: After iconv init reset ref normalize error The iconv init was accidentally clearing the default error state during reference normalization. This resets so that normalization errors will be detected correctly. --- src/refs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/refs.c b/src/refs.c index 0da02a666..7530aeef9 100644 --- a/src/refs.c +++ b/src/refs.c @@ -755,6 +755,7 @@ int git_reference__normalize_name( if ((error = git_path_iconv_init_precompose(&ic)) < 0 || (error = git_path_iconv(&ic, ¤t, &namelen)) < 0) goto cleanup; + error = GIT_EINVALIDSPEC; } while (true) { -- cgit v1.2.1 From 370d1d166e3a77a5f21e3f7a73870fbb7def2249 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 9 Oct 2013 14:41:44 -0700 Subject: Un-remove init example --- examples/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Makefile b/examples/Makefile index 79c57d7d7..c9c667d16 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -3,7 +3,7 @@ CC = gcc CFLAGS = -g -I../include -I../src -Wall -Wextra -Wmissing-prototypes -Wno-missing-field-initializers LFLAGS = -L../build -lgit2 -lz -APPS = general blame showindex diff rev-list cat-file status log rev-parse +APPS = general showindex diff rev-list cat-file status log rev-parse init blame all: $(APPS) -- cgit v1.2.1 From cb45dafaf85053c6ff4f3e8ac86f8b9cbc174033 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 9 Oct 2013 16:07:17 -0700 Subject: Initialize threading, fix broken strncmp --- examples/blame.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/blame.c b/examples/blame.c index 6f6a2749d..88bdb7c76 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -41,6 +41,8 @@ int main(int argc, char *argv[]) git_tree_entry *entry; git_blob *blob; + git_threads_init(); + if (argc < 2) usage(NULL, NULL); path = argv[1]; @@ -51,7 +53,7 @@ int main(int argc, char *argv[]) opts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; else if (!strcmp(a, "-C")) opts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; - else if (!strncmp(a, "-L", 3)) { + else if (!strcmp(a, "-L")) { i++; a = argv[i]; if (i >= argc) check(-1, "Not enough arguments to -L"); check(sscanf(a, "%d,%d", &opts.min_line, &opts.max_line)-2, "-L format error"); @@ -128,4 +130,5 @@ int main(int argc, char *argv[]) git_commit_free(commit); git_blame_free(blame); git_repository_free(repo); + git_threads_shutdown(); } -- cgit v1.2.1 From 2ccc84d2efaf8adf4886cfc42d8bd16e2ba98188 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 9 Oct 2013 16:07:36 -0700 Subject: Allow null bytes in blob --- examples/blame.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/examples/blame.c b/examples/blame.c index 88bdb7c76..5efb19930 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -29,7 +29,7 @@ static void usage(const char *msg, const char *arg) int main(int argc, char *argv[]) { - int i; + int i, line; char *path = NULL, *a; const char *rawdata, *commitspec=NULL; git_repository *repo = NULL; @@ -99,11 +99,12 @@ int main(int argc, char *argv[]) rawdata = git_blob_rawcontent(blob); /* Produce the output */ - i = 1; - while (rawdata[0]) { - const char *eol = strchr(rawdata, '\n'); + line = 1; + i = 0; + while (i < git_blob_rawsize(blob)) { + const char *eol = strchr(rawdata+i, '\n'); char oid[10] = {0}; - const git_blame_hunk *hunk = git_blame_get_hunk_byline(blame, i); + const git_blame_hunk *hunk = git_blame_get_hunk_byline(blame, line); git_commit *hunkcommit; const git_signature *sig; @@ -114,13 +115,13 @@ int main(int argc, char *argv[]) printf("%s ( %-30s %3d) %.*s\n", oid, sig->name, - i, - (int)(eol-rawdata), - rawdata); + line, + (int)(eol-rawdata-i), + rawdata+i); git_commit_free(hunkcommit); - rawdata = eol+1; - i++; + i = eol - rawdata + 1; + line++; } /* Cleanup */ -- cgit v1.2.1 From 43a07b860b9c172081e3c9dee18aeead9091f2cf Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 9 Oct 2013 16:16:43 -0700 Subject: Simplify loading blob --- examples/blame.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/examples/blame.c b/examples/blame.c index 5efb19930..a7d0a12a5 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -32,13 +32,11 @@ int main(int argc, char *argv[]) int i, line; char *path = NULL, *a; const char *rawdata, *commitspec=NULL; + char spec[1024] = {0}; git_repository *repo = NULL; git_revspec revspec = {0}; git_blame_options opts = GIT_BLAME_OPTIONS_INIT; git_blame *blame = NULL; - git_commit *commit; - git_tree *tree; - git_tree_entry *entry; git_blob *blob; git_threads_init(); @@ -86,16 +84,19 @@ int main(int argc, char *argv[]) check(git_blame_file(&blame, repo, path, &opts), "Blame error"); /* Get the raw data for output */ - if (git_oid_iszero(&opts.newest_commit)) { + if (git_oid_iszero(&opts.newest_commit)) + strcpy(spec, "HEAD"); + else + git_oid_tostr(spec, sizeof(spec), &opts.newest_commit); + strcat(spec, ":"); + strcat(spec, path); + + { git_object *obj; - check(git_revparse_single(&obj, repo, "HEAD"), "Can't find HEAD"); - git_oid_cpy(&opts.newest_commit, git_object_id(obj)); + check(git_revparse_single(&obj, repo, spec), "Object lookup error"); + check(git_blob_lookup(&blob, repo, git_object_id(obj)), "Blob lookup error"); git_object_free(obj); } - check(git_commit_lookup(&commit, repo, &opts.newest_commit), "Commit lookup error"); - check(git_commit_tree(&tree, commit), "Commit tree lookup error"); - check(git_tree_entry_bypath(&entry, tree, path), "Tree entry lookup error"); - check(git_blob_lookup(&blob, repo, git_tree_entry_id(entry)), "Blob lookup error"); rawdata = git_blob_rawcontent(blob); /* Produce the output */ @@ -126,9 +127,6 @@ int main(int argc, char *argv[]) /* Cleanup */ git_blob_free(blob); - git_tree_entry_free(entry); - git_tree_free(tree); - git_commit_free(commit); git_blame_free(blame); git_repository_free(repo); git_threads_shutdown(); -- cgit v1.2.1 From 0a23d2058dc61a6d11e9da6aadf431d69e738601 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 9 Oct 2013 16:18:32 -0700 Subject: Ignore more built examples --- examples/.gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/.gitignore b/examples/.gitignore index 2b693f1ef..711493994 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -3,4 +3,9 @@ showindex diff rev-list blame +cat-file +init +log +rev-parse +status *.dSYM -- cgit v1.2.1 From d2e7532f620acd467ebeef0b3c4318420f445a13 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 10 Oct 2013 13:56:28 -0700 Subject: Be more flexible with argument order and format --- examples/blame.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/examples/blame.c b/examples/blame.c index a7d0a12a5..6423b3ca6 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -17,7 +17,7 @@ static void usage(const char *msg, const char *arg) fprintf(stderr, "%s: %s\n", msg, arg); else if (msg) fprintf(stderr, "%s\n", msg); - fprintf(stderr, "usage: blame [options] []\n"); + fprintf(stderr, "usage: blame [options] [] \n"); fprintf(stderr, "\n"); fprintf(stderr, " example: `HEAD~10..HEAD`, or `1234abcd`\n"); fprintf(stderr, " -L process only line range n-m, counting from 1\n"); @@ -30,8 +30,8 @@ static void usage(const char *msg, const char *arg) int main(int argc, char *argv[]) { int i, line; - char *path = NULL, *a; - const char *rawdata, *commitspec=NULL; + const char *path = NULL, *a; + const char *rawdata, *commitspec=NULL, *bare_args[3] = {0}; char spec[1024] = {0}; git_repository *repo = NULL; git_revspec revspec = {0}; @@ -42,16 +42,24 @@ int main(int argc, char *argv[]) git_threads_init(); if (argc < 2) usage(NULL, NULL); - path = argv[1]; - for (i=2; i= 3) + usage("Invalid argument set", NULL); + bare_args[i] = a; + } + else if (!strcmp(a, "--")) + continue; + else if (!strcasecmp(a, "-M")) opts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; - else if (!strcmp(a, "-C")) + else if (!strcasecmp(a, "-C")) opts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; - else if (!strcmp(a, "-L")) { + else if (!strcasecmp(a, "-L")) { i++; a = argv[i]; if (i >= argc) check(-1, "Not enough arguments to -L"); check(sscanf(a, "%d,%d", &opts.min_line, &opts.max_line)-2, "-L format error"); @@ -63,6 +71,21 @@ int main(int argc, char *argv[]) } } + /* Handle the bare arguments */ + if (!bare_args[0]) usage("Please specify a path", NULL); + path = bare_args[0]; + if (bare_args[1]) { + /* */ + path = bare_args[1]; + commitspec = bare_args[0]; + } + if (bare_args[2]) { + /* */ + path = bare_args[2]; + sprintf(spec, "%s..%s", bare_args[0], bare_args[1]); + commitspec = spec; + } + /* Open the repo */ check(git_repository_open_ext(&repo, ".", 0, NULL), "Couldn't open repository"); -- cgit v1.2.1 From ebd67243d5152e2c38811ba42fcdf99eecd8ef60 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 10 Oct 2013 13:56:45 -0700 Subject: Only show lines that had blame run on them --- examples/blame.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/examples/blame.c b/examples/blame.c index 6423b3ca6..df687a71a 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -128,22 +128,24 @@ int main(int argc, char *argv[]) while (i < git_blob_rawsize(blob)) { const char *eol = strchr(rawdata+i, '\n'); char oid[10] = {0}; - const git_blame_hunk *hunk = git_blame_get_hunk_byline(blame, line); git_commit *hunkcommit; const git_signature *sig; + const git_blame_hunk *hunk = git_blame_get_hunk_byline(blame, line); - git_oid_tostr(oid, 10, &hunk->final_commit_id); - check(git_commit_lookup(&hunkcommit, repo, &hunk->final_commit_id), "Commit lookup error"); - sig = git_commit_author(hunkcommit); - - printf("%s ( %-30s %3d) %.*s\n", - oid, - sig->name, - line, - (int)(eol-rawdata-i), - rawdata+i); + if (hunk) { + git_oid_tostr(oid, 10, &hunk->final_commit_id); + check(git_commit_lookup(&hunkcommit, repo, &hunk->final_commit_id), "Commit lookup error"); + sig = git_commit_author(hunkcommit); + + printf("%s ( %-30s %3d) %.*s\n", + oid, + sig->name, + line, + (int)(eol-rawdata-i), + rawdata+i); + git_commit_free(hunkcommit); + } - git_commit_free(hunkcommit); i = eol - rawdata + 1; line++; } -- cgit v1.2.1 From c1ca2b67e1747ff4d2ba5a10ee300497d1d28dbe Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 10 Oct 2013 14:30:05 -0700 Subject: Include signatures in blame hunks --- examples/blame.c | 10 ++++------ include/git2/blame.h | 2 ++ src/blame.c | 4 ++++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/blame.c b/examples/blame.c index df687a71a..8ecf2970e 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -128,22 +128,20 @@ int main(int argc, char *argv[]) while (i < git_blob_rawsize(blob)) { const char *eol = strchr(rawdata+i, '\n'); char oid[10] = {0}; - git_commit *hunkcommit; - const git_signature *sig; const git_blame_hunk *hunk = git_blame_get_hunk_byline(blame, line); if (hunk) { + char sig[128] = {0}; + git_oid_tostr(oid, 10, &hunk->final_commit_id); - check(git_commit_lookup(&hunkcommit, repo, &hunk->final_commit_id), "Commit lookup error"); - sig = git_commit_author(hunkcommit); + snprintf(sig, 30, "%s <%s>", hunk->final_signature->name, hunk->final_signature->email); printf("%s ( %-30s %3d) %.*s\n", oid, - sig->name, + sig, line, (int)(eol-rawdata-i), rawdata+i); - git_commit_free(hunkcommit); } i = eol - rawdata + 1; diff --git a/include/git2/blame.h b/include/git2/blame.h index ba3580fcf..fe51371ab 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -103,10 +103,12 @@ typedef struct git_blame_hunk { git_oid final_commit_id; uint16_t final_start_line_number; + git_signature *final_signature; git_oid orig_commit_id; const char *orig_path; uint16_t orig_start_line_number; + git_signature *orig_signature; char boundary; } git_blame_hunk; diff --git a/src/blame.c b/src/blame.c index 0722ba005..5b0ebd4fe 100644 --- a/src/blame.c +++ b/src/blame.c @@ -12,6 +12,7 @@ #include "git2/tree.h" #include "git2/diff.h" #include "git2/blob.h" +#include "git2/signature.h" #include "util.h" #include "repository.h" #include "blame_git.h" @@ -80,6 +81,8 @@ static git_blame_hunk* dup_hunk(git_blame_hunk *hunk) static void free_hunk(git_blame_hunk *hunk) { git__free((void*)hunk->orig_path); + git_signature_free(hunk->final_signature); + git_signature_free(hunk->orig_signature); git__free(hunk); } @@ -252,6 +255,7 @@ static git_blame_hunk* hunk_from_entry(git_blame__entry *e) git_blame_hunk *h = new_hunk( e->lno+1, e->num_lines, e->s_lno+1, e->suspect->path); git_oid_cpy(&h->final_commit_id, git_commit_id(e->suspect->commit)); + h->final_signature = git_signature_dup(git_commit_author(e->suspect->commit)); h->boundary = e->is_boundary ? 1 : 0; return h; } -- cgit v1.2.1 From 607fe733700109ac171661975b60735c481ed3fc Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 10 Oct 2013 14:30:31 -0700 Subject: Fix post-line-range iteration --- examples/blame.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/blame.c b/examples/blame.c index 8ecf2970e..450e98aee 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -29,7 +29,7 @@ static void usage(const char *msg, const char *arg) int main(int argc, char *argv[]) { - int i, line; + int i, line, break_on_null_hunk; const char *path = NULL, *a; const char *rawdata, *commitspec=NULL, *bare_args[3] = {0}; char spec[1024] = {0}; @@ -125,12 +125,16 @@ int main(int argc, char *argv[]) /* Produce the output */ line = 1; i = 0; + break_on_null_hunk = 0; while (i < git_blob_rawsize(blob)) { const char *eol = strchr(rawdata+i, '\n'); char oid[10] = {0}; const git_blame_hunk *hunk = git_blame_get_hunk_byline(blame, line); + if (break_on_null_hunk && !hunk) break; + if (hunk) { + break_on_null_hunk = 1; char sig[128] = {0}; git_oid_tostr(oid, 10, &hunk->final_commit_id); -- cgit v1.2.1 From 4fd847bb94b5bf8c1e4dce4e0c4798068977f916 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 10 Oct 2013 14:38:15 -0700 Subject: Fix initializer error --- tests-clar/blame/getters.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests-clar/blame/getters.c b/tests-clar/blame/getters.c index 8d67e3e45..66eaeecf9 100644 --- a/tests-clar/blame/getters.c +++ b/tests-clar/blame/getters.c @@ -10,11 +10,11 @@ void test_blame_getters__initialize(void) git_blame_options opts = GIT_BLAME_OPTIONS_INIT; git_blame_hunk hunks[] = { - { 3, {{0}}, 1, {{0}}, "a", 0}, - { 3, {{0}}, 4, {{0}}, "b", 0}, - { 3, {{0}}, 7, {{0}}, "c", 0}, - { 3, {{0}}, 10, {{0}}, "d", 0}, - { 3, {{0}}, 13, {{0}}, "e", 0}, + { 3, {{0}}, 1, NULL, {{0}}, "a", 0}, + { 3, {{0}}, 4, NULL, {{0}}, "b", 0}, + { 3, {{0}}, 7, NULL, {{0}}, "c", 0}, + { 3, {{0}}, 10, NULL, {{0}}, "d", 0}, + { 3, {{0}}, 13, NULL, {{0}}, "e", 0}, }; g_blame = git_blame__alloc(NULL, opts, ""); -- cgit v1.2.1 From 364d800b018325914ac01cb5f1b06beb1cab528f Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 10 Oct 2013 14:53:07 -0700 Subject: Move flag dependencies into docs and code. --- include/git2/blame.h | 8 ++++---- src/blame.c | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/git2/blame.h b/include/git2/blame.h index fe51371ab..b98c6f0d7 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -33,13 +33,13 @@ typedef enum { * NOT IMPLEMENTED. */ GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES = (1<<1), /** Track lines that have been copied from another file that exists in the - * same commit (like `git blame -CC`). + * same commit (like `git blame -CC`). Implies SAME_FILE. * NOT IMPLEMENTED. */ - GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES = (1<<1 | 1<<2), + GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES = (1<<2), /** Track lines that have been copied from another file that exists in *any* - * commit (like `git blame -CCC`). + * commit (like `git blame -CCC`). Implies SAME_COMMIT_COPIES. * NOT IMPLEMENTED. */ - GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<1 | 1<<2 | 1<<3), + GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<3), } git_blame_flag_t; /** diff --git a/src/blame.c b/src/blame.c index 5b0ebd4fe..e698d3941 100644 --- a/src/blame.c +++ b/src/blame.c @@ -184,6 +184,14 @@ static void normalize_options( /* min_line 0 really means 1 */ if (!out->min_line) out->min_line = 1; /* max_line 0 really means N, but we don't know N yet */ + + /* Fix up option implications */ + if (out->flags & GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES) + out->flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; + if (out->flags & GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES) + out->flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; + if (out->flags & GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES) + out->flags |= GIT_BLAME_TRACK_COPIES_SAME_FILE; } static git_blame_hunk *split_hunk_in_vector( -- cgit v1.2.1 From 84c469814e634f9e2638eaf979a644fb44baffb0 Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Fri, 11 Oct 2013 00:06:08 +0200 Subject: Fix a typo in the rpm build instructions. --- packaging/rpm/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/rpm/README b/packaging/rpm/README index 1a6410b16..cc1851fb5 100644 --- a/packaging/rpm/README +++ b/packaging/rpm/README @@ -1,4 +1,4 @@ -To build RPM pakcages for Fedora, follow these steps: +To build RPM packages for Fedora, follow these steps: cp packaging/rpm/libgit2.spec ~/rpmbuild/SPECS cd ~/rpmbuild/SOURCES wget https://github.com/downloads/libgit2/libgit2/libgit2-0.16.0.tar.gz -- cgit v1.2.1 From 7c9f5bec5182eb587fbc1094f2235d2babb70ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 17 Aug 2013 07:11:31 +0200 Subject: futils: return GIT_ENOTFOUND when trying to read a directory This lets the reference code return not-found when the user asks to look up a reference when in fact they pass a namespace. --- src/fileops.c | 8 +++++++- tests-clar/refs/lookup.c | 12 ++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/fileops.c b/src/fileops.c index 3a5a53074..210f45fa1 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -165,7 +165,13 @@ int git_futils_readbuffer_updated( return -1; } - if (S_ISDIR(st.st_mode) || !git__is_sizet(st.st_size+1)) { + + if (S_ISDIR(st.st_mode)) { + giterr_set(GITERR_INVALID, "requested file is a directory"); + return GIT_ENOTFOUND; + } + + if (!git__is_sizet(st.st_size+1)) { giterr_set(GITERR_OS, "Invalid regular file stat for '%s'", path); return -1; } diff --git a/tests-clar/refs/lookup.c b/tests-clar/refs/lookup.c index 0dbebc5c2..2e31cf0f6 100644 --- a/tests-clar/refs/lookup.c +++ b/tests-clar/refs/lookup.c @@ -46,3 +46,15 @@ void test_refs_lookup__oid(void) cl_git_pass(git_oid_fromstr(&expected, "1385f264afb75a56a5bec74243be9b367ba4ca08")); cl_assert(git_oid_cmp(&tag, &expected) == 0); } + +void test_refs_lookup__namespace(void) +{ + int error; + git_reference *ref; + + error = git_reference_lookup(&ref, g_repo, "refs/heads"); + cl_assert_equal_i(error, GIT_ENOTFOUND); + + error = git_reference_lookup(&ref, g_repo, "refs/heads/"); + cl_assert_equal_i(error, GIT_EINVALIDSPEC); +} -- cgit v1.2.1 From 893055f22e5395ec95231b4cc8a19046a3eb5b4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 11 Oct 2013 17:24:29 +0200 Subject: indexer: clearer stats for thin packs Don't increase the number of total objects, as it can produce suprising progress output. The only addition compared to pre-thin is the addition of local_objects to allow an output similar to git's "completed with %d local objects". --- include/git2/types.h | 7 +++++++ src/indexer.c | 5 ++--- tests-clar/pack/indexer.c | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/git2/types.h b/include/git2/types.h index 3939353ee..4ff2ba4c4 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -212,6 +212,13 @@ typedef struct git_remote_callbacks git_remote_callbacks; /** * This is passed as the first argument to the callback to allow the * user to see the progress. + * + * - total_objects: number of objects in the packfile being downloaded + * - indexed_objects: received objects that have been hashed + * - received_objects: objects which have been downloaded + * - local_objects: locally-available objects that have been injected + * in order to fix a thin pack. + * - received-bytes: size of the packfile received up to now */ typedef struct git_transfer_progress { unsigned int total_objects; diff --git a/src/indexer.c b/src/indexer.c index 2cda1a629..93ad116fe 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -733,7 +733,6 @@ static int fix_thin_pack(git_indexer_stream *idx, git_transfer_progress *stats) if (inject_object(idx, &base) < 0) return -1; - stats->total_objects++; stats->local_objects++; return 0; @@ -798,7 +797,7 @@ static int update_header_and_rehash(git_indexer_stream *idx, git_transfer_progre git_mwindow_free_all(mwf); /* Update the header to include the numer of local objects we injected */ - idx->hdr.hdr_entries = htonl(stats->total_objects); + idx->hdr.hdr_entries = htonl(stats->total_objects + stats->local_objects); if (p_lseek(idx->pack_file.fd, 0, SEEK_SET) < 0) { giterr_set(GITERR_OS, "failed to seek to the beginning of the pack"); return -1; @@ -870,7 +869,7 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * if (resolve_deltas(idx, stats) < 0) return -1; - if (stats->indexed_objects + stats->local_objects != stats->total_objects) { + if (stats->indexed_objects != stats->total_objects) { giterr_set(GITERR_INDEXER, "early EOF"); return -1; } diff --git a/tests-clar/pack/indexer.c b/tests-clar/pack/indexer.c index fd1616034..17ec7b3f8 100644 --- a/tests-clar/pack/indexer.c +++ b/tests-clar/pack/indexer.c @@ -79,7 +79,7 @@ void test_pack_indexer__fix_thin(void) cl_git_pass(git_indexer_stream_add(idx, thin_pack, thin_pack_len, &stats)); cl_git_pass(git_indexer_stream_finalize(idx, &stats)); - cl_assert_equal_i(stats.total_objects, 3); + cl_assert_equal_i(stats.total_objects, 2); cl_assert_equal_i(stats.received_objects, 2); cl_assert_equal_i(stats.indexed_objects, 2); cl_assert_equal_i(stats.local_objects, 1); -- cgit v1.2.1 From 3ff1d123736e5686fb9ec16e65828d5b8ffa2b30 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 11 Oct 2013 14:51:54 -0700 Subject: Rename diff objects and split patch.h This makes no functional change to diff but renames a couple of the objects and splits the new git_patch (formerly git_diff_patch) into a new header file. --- examples/diff.c | 10 +- examples/log.c | 10 +- include/git2.h | 1 + include/git2/diff.h | 380 ++++++++--------------------------------- include/git2/patch.h | 270 +++++++++++++++++++++++++++++ include/git2/pathspec.h | 2 +- src/checkout.c | 4 +- src/diff.c | 64 +++---- src/diff.h | 10 +- src/diff_file.c | 2 +- src/diff_file.h | 2 +- src/diff_patch.c | 156 ++++++++--------- src/diff_patch.h | 19 ++- src/diff_print.c | 50 +++--- src/diff_tform.c | 22 +-- src/diff_xdiff.c | 40 ++--- src/pathspec.c | 2 +- src/reset.c | 4 +- src/stash.c | 10 +- src/status.c | 6 +- src/status.h | 4 +- src/submodule.c | 6 +- tests-clar/diff/blob.c | 222 ++++++++++++------------ tests-clar/diff/diff_helpers.c | 36 ++-- tests-clar/diff/diff_helpers.h | 12 +- tests-clar/diff/diffiter.c | 110 ++++++------ tests-clar/diff/drivers.c | 58 +++---- tests-clar/diff/index.c | 12 +- tests-clar/diff/notify.c | 16 +- tests-clar/diff/patch.c | 146 ++++++++-------- tests-clar/diff/pathspec.c | 8 +- tests-clar/diff/rename.c | 108 ++++++------ tests-clar/diff/submodules.c | 84 ++++----- tests-clar/diff/tree.c | 38 ++--- tests-clar/diff/workdir.c | 150 ++++++++-------- tests-clar/stress/diff.c | 6 +- 36 files changed, 1057 insertions(+), 1023 deletions(-) create mode 100644 include/git2/patch.h diff --git a/examples/diff.c b/examples/diff.c index 11efa21ec..3200b53c8 100644 --- a/examples/diff.c +++ b/examples/diff.c @@ -45,7 +45,7 @@ char *colors[] = { static int printer( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *range, char usage, const char *line, size_t line_len, @@ -126,7 +126,7 @@ int main(int argc, char *argv[]) git_tree *t1 = NULL, *t2 = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; - git_diff_list *diff; + git_diff *diff; int i, color = -1, format = FORMAT_PATCH, cached = 0; char *a, *treeish1 = NULL, *treeish2 = NULL; const char *dir = "."; @@ -218,11 +218,11 @@ int main(int argc, char *argv[]) else if (t1 && cached) check(git_diff_tree_to_index(&diff, repo, t1, NULL, &opts), "Diff"); else if (t1) { - git_diff_list *diff2; + git_diff *diff2; check(git_diff_tree_to_index(&diff, repo, t1, NULL, &opts), "Diff"); check(git_diff_index_to_workdir(&diff2, repo, NULL, &opts), "Diff"); check(git_diff_merge(diff, diff2), "Merge diffs"); - git_diff_list_free(diff2); + git_diff_free(diff2); } else if (cached) { check(resolve_to_tree(repo, "HEAD", &t1), "looking up HEAD"); @@ -253,7 +253,7 @@ int main(int argc, char *argv[]) if (color >= 0) fputs(colors[0], stdout); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(t1); git_tree_free(t2); git_repository_free(repo); diff --git a/examples/log.c b/examples/log.c index 413c211e4..2ba5aa52a 100644 --- a/examples/log.c +++ b/examples/log.c @@ -184,7 +184,7 @@ static void print_commit(git_commit *commit) static int print_diff( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *range, char usage, const char *line, size_t line_len, @@ -218,7 +218,7 @@ static int match_with_parent( { git_commit *parent; git_tree *a, *b; - git_diff_list *diff; + git_diff *diff; int ndeltas; check(git_commit_parent(&parent, commit, (size_t)i), "Get parent", NULL); @@ -229,7 +229,7 @@ static int match_with_parent( ndeltas = (int)git_diff_num_deltas(diff); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(a); git_tree_free(b); git_commit_free(parent); @@ -373,7 +373,7 @@ int main(int argc, char *argv[]) if (opt.show_diff) { git_tree *a = NULL, *b = NULL; - git_diff_list *diff = NULL; + git_diff *diff = NULL; if (parents > 1) continue; @@ -391,7 +391,7 @@ int main(int argc, char *argv[]) check(git_diff_print_patch(diff, print_diff, NULL), "Displaying diff", NULL); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(a); git_tree_free(b); } diff --git a/include/git2.h b/include/git2.h index 93049aad9..b90673920 100644 --- a/include/git2.h +++ b/include/git2.h @@ -32,6 +32,7 @@ #include "git2/odb.h" #include "git2/oid.h" #include "git2/pack.h" +#include "git2/patch.h" #include "git2/pathspec.h" #include "git2/push.h" #include "git2/refdb.h" diff --git a/include/git2/diff.h b/include/git2/diff.h index 596098574..11c3bce20 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -20,34 +20,38 @@ * Overview * -------- * - * Calculating diffs is generally done in two phases: building a diff list - * then traversing the diff list. This makes is easier to share logic - * across the various types of diffs (tree vs tree, workdir vs index, etc.), - * and also allows you to insert optional diff list post-processing phases, - * such as rename detected, in between the steps. When you are done with a - * diff list object, it must be freed. + * Calculating diffs is generally done in two phases: building a list of + * diffs then traversing it. This makes is easier to share logic across + * the various types of diffs (tree vs tree, workdir vs index, etc.), and + * also allows you to insert optional diff list post-processing phases, + * such as rename detection, in between the steps. When you are done with + * a diff object, it must be freed. * * Terminology * ----------- * * To understand the diff APIs, you should know the following terms: * - * - A `diff` or `diff list` represents the cumulative list of differences - * between two snapshots of a repository (possibly filtered by a set of - * file name patterns). This is the `git_diff_list` object. + * - A `diff` represents the cumulative list of differences between two + * snapshots of a repository (possibly filtered by a set of file name + * patterns). This is the `git_diff` object. + * * - A `delta` is a file pair with an old and new revision. The old version * may be absent if the file was just created and the new version may be * absent if the file was deleted. A diff is mostly just a list of deltas. + * * - A `binary` file / delta is a file (or pair) for which no text diffs - * should be generated. A diff list can contain delta entries that are + * should be generated. A diff can contain delta entries that are * binary, but no diff content will be output for those files. There is * a base heuristic for binary detection and you can further tune the * behavior with git attributes or diff flags and option settings. + * * - A `hunk` is a span of modified lines in a delta along with some stable * surrounding context. You can configure the amount of context and other * properties of how hunks are generated. Each hunk also comes with a * header that described where it starts and ends in both the old and new * versions in the delta. + * * - A `line` is a range of characters inside a hunk. It could be a context * line (i.e. in both old and new versions), an added line (i.e. only in * the new version), or a removed line (i.e. only in the old version). @@ -154,14 +158,14 @@ typedef enum { } git_diff_option_t; /** - * The diff list object that contains all individual file deltas. + * The diff object that contains all individual file deltas. * * This is an opaque structure which will be allocated by one of the diff * generator functions below (such as `git_diff_tree_to_tree`). You are * responsible for releasing the object memory when done, using the - * `git_diff_list_free()` function. + * `git_diff_free()` function. */ -typedef struct git_diff_list git_diff_list; +typedef struct git_diff git_diff; /** * Flags for the delta object and the file objects on each side. @@ -200,11 +204,11 @@ typedef enum { } git_delta_t; /** - * Description of one side of a diff entry. + * Description of one side of a delta. * - * Although this is called a "file", it may actually represent a file, a - * symbolic link, a submodule commit id, or even a tree (although that only - * if you are tracking type changes or ignored/untracked directories). + * Although this is called a "file", it could represent a file, a symbolic + * link, a submodule commit id, or even a tree (although that only if you + * are tracking type changes or ignored/untracked directories). * * The `oid` is the `git_oid` of the item. If the entry represents an * absent side of a diff (e.g. the `old_file` of a `GIT_DELTA_ADDED` delta), @@ -231,9 +235,8 @@ typedef struct { /** * Description of changes to one entry. * - * When iterating over a diff list object, this will be passed to most - * callback functions and you can use the contents to understand exactly - * what has changed. + * When iterating over a diff, this will be passed to most callbacks and + * you can use the contents to understand exactly what has changed. * * The `old_file` represents the "from" side of the diff and the `new_file` * represents to "to" side of the diff. What those means depend on the @@ -266,18 +269,18 @@ typedef struct { * the score (a la `printf("M%03d", 100 - delta->similarity)`). */ typedef struct { - git_diff_file old_file; - git_diff_file new_file; git_delta_t status; uint32_t similarity; /**< for RENAMED and COPIED, value 0-100 */ uint32_t flags; + git_diff_file old_file; + git_diff_file new_file; } git_diff_delta; /** * Diff notification callback function. * * The callback will be called for each file, just before the `git_delta_t` - * gets inserted into the diff list. + * gets inserted into the diff. * * When the callback: * - returns < 0, the diff process will be aborted. @@ -287,7 +290,7 @@ typedef struct { * continues. */ typedef int (*git_diff_notify_cb)( - const git_diff_list *diff_so_far, + const git_diff *diff_so_far, const git_diff_delta *delta_to_add, const char *matched_pathspec, void *payload); @@ -349,19 +352,20 @@ typedef int (*git_diff_file_cb)( /** * Structure describing a hunk of a diff. */ -typedef struct { +typedef struct git_diff_hunk git_diff_hunk; +struct git_diff_hunk { int old_start; /** Starting line number in old_file */ int old_lines; /** Number of lines in old_file */ int new_start; /** Starting line number in new_file */ int new_lines; /** Number of lines in new_file */ -} git_diff_range; +}; /** * When iterating over a diff, callback that will be made per hunk. */ typedef int (*git_diff_hunk_cb)( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *hunk, const char *header, size_t header_len, void *payload); @@ -370,13 +374,13 @@ typedef int (*git_diff_hunk_cb)( * Line origin constants. * * These values describe where a line came from and will be passed to - * the git_diff_data_cb when iterating over a diff. There are some + * the git_diff_line_cb when iterating over a diff. There are some * special origin constants at the end that are used for the text * output callbacks to demarcate lines that are actually part of * the file or hunk headers. */ typedef enum { - /* These values will be sent to `git_diff_data_cb` along with the line */ + /* These values will be sent to `git_diff_line_cb` along with the line */ GIT_DIFF_LINE_CONTEXT = ' ', GIT_DIFF_LINE_ADDITION = '+', GIT_DIFF_LINE_DELETION = '-', @@ -385,7 +389,7 @@ typedef enum { GIT_DIFF_LINE_ADD_EOFNL = '>', /**< Old has no LF at end, new does */ GIT_DIFF_LINE_DEL_EOFNL = '<', /**< Old has LF at end, new does not */ - /* The following values will only be sent to a `git_diff_data_cb` when + /* The following values will only be sent to a `git_diff_line_cb` when * the content of a diff is being formatted (eg. through * git_diff_print_patch() or git_diff_print_compact(), for instance). */ @@ -402,22 +406,14 @@ typedef enum { * of text. This uses some extra GIT_DIFF_LINE_... constants for output * of lines of file and hunk headers. */ -typedef int (*git_diff_data_cb)( +typedef int (*git_diff_line_cb)( const git_diff_delta *delta, /** delta that contains this data */ - const git_diff_range *range, /** range of lines containing this data */ - char line_origin, /** git_diff_list_t value from above */ + const git_diff_hunk *hunk, /** range of lines containing this data */ + char line_origin, /** git_diff_t value from above */ const char *content, /** diff data - not NUL terminated */ size_t content_len, /** number of bytes of diff data */ void *payload); /** user reference data */ -/** - * The diff patch is used to store all the text diffs for a delta. - * - * You can easily loop over the content of patches and get information about - * them. - */ -typedef struct git_diff_patch git_diff_patch; - /** * Flags to control the behavior of diff rename/copy detection. */ @@ -524,7 +520,7 @@ typedef struct { /** @name Diff List Generator Functions * * These are the functions you would use to create (or destroy) a - * git_diff_list from various objects in a repository. + * git_diff from various objects in a repository. */ /**@{*/ @@ -533,7 +529,7 @@ typedef struct { * * @param diff The previously created diff list; cannot be used after free. */ -GIT_EXTERN(void) git_diff_list_free(git_diff_list *diff); +GIT_EXTERN(void) git_diff_free(git_diff *diff); /** * Create a diff list with the difference between two tree objects. @@ -545,14 +541,14 @@ GIT_EXTERN(void) git_diff_list_free(git_diff_list *diff); * pass NULL to indicate an empty tree, although it is an error to pass * NULL for both the `old_tree` and `new_tree`. * - * @param diff Output pointer to a git_diff_list pointer to be allocated. + * @param diff Output pointer to a git_diff pointer to be allocated. * @param repo The repository containing the trees. * @param old_tree A git_tree object to diff from, or NULL for empty tree. * @param new_tree A git_tree object to diff to, or NULL for empty tree. * @param opts Structure with options to influence diff or NULL for defaults. */ GIT_EXTERN(int) git_diff_tree_to_tree( - git_diff_list **diff, + git_diff **diff, git_repository *repo, git_tree *old_tree, git_tree *new_tree, @@ -567,14 +563,14 @@ GIT_EXTERN(int) git_diff_tree_to_tree( * The tree you pass will be used for the "old_file" side of the delta, and * the index will be used for the "new_file" side of the delta. * - * @param diff Output pointer to a git_diff_list pointer to be allocated. + * @param diff Output pointer to a git_diff pointer to be allocated. * @param repo The repository containing the tree and index. * @param old_tree A git_tree object to diff from, or NULL for empty tree. * @param index The index to diff with; repo index used if NULL. * @param opts Structure with options to influence diff or NULL for defaults. */ GIT_EXTERN(int) git_diff_tree_to_index( - git_diff_list **diff, + git_diff **diff, git_repository *repo, git_tree *old_tree, git_index *index, @@ -591,13 +587,13 @@ GIT_EXTERN(int) git_diff_tree_to_index( * The index will be used for the "old_file" side of the delta, and the * working directory will be used for the "new_file" side of the delta. * - * @param diff Output pointer to a git_diff_list pointer to be allocated. + * @param diff Output pointer to a git_diff pointer to be allocated. * @param repo The repository. * @param index The index to diff from; repo index used if NULL. * @param opts Structure with options to influence diff or NULL for defaults. */ GIT_EXTERN(int) git_diff_index_to_workdir( - git_diff_list **diff, + git_diff **diff, git_repository *repo, git_index *index, const git_diff_options *opts); /**< can be NULL for defaults */ @@ -619,20 +615,20 @@ GIT_EXTERN(int) git_diff_index_to_workdir( * * To emulate `git diff `, call both `git_diff_tree_to_index` and * `git_diff_index_to_workdir`, then call `git_diff_merge` on the results. - * That will yield a `git_diff_list` that matches the git output. + * That will yield a `git_diff` that matches the git output. * * If this seems confusing, take the case of a file with a staged deletion * where the file has then been put back into the working dir and modified. * The tree-to-workdir diff for that file is 'modified', but core git would * show status 'deleted' since there is a pending deletion in the index. * - * @param diff A pointer to a git_diff_list pointer that will be allocated. + * @param diff A pointer to a git_diff pointer that will be allocated. * @param repo The repository containing the tree. * @param old_tree A git_tree object to diff from, or NULL for empty tree. * @param opts Structure with options to influence diff or NULL for defaults. */ GIT_EXTERN(int) git_diff_tree_to_workdir( - git_diff_list **diff, + git_diff **diff, git_repository *repo, git_tree *old_tree, const git_diff_options *opts); /**< can be NULL for defaults */ @@ -651,8 +647,8 @@ GIT_EXTERN(int) git_diff_tree_to_workdir( * @param from Diff to merge. */ GIT_EXTERN(int) git_diff_merge( - git_diff_list *onto, - const git_diff_list *from); + git_diff *onto, + const git_diff *from); /** * Transform a diff list marking file renames, copies, etc. @@ -667,7 +663,7 @@ GIT_EXTERN(int) git_diff_merge( * @return 0 on success, -1 on failure */ GIT_EXTERN(int) git_diff_find_similar( - git_diff_list *diff, + git_diff *diff, git_diff_find_options *options); /**@}*/ @@ -694,7 +690,7 @@ GIT_EXTERN(int) git_diff_find_similar( * Returning a non-zero value from any of the callbacks will terminate * the iteration and cause this return `GIT_EUSER`. * - * @param diff A git_diff_list generated by one of the above functions. + * @param diff A git_diff generated by one of the above functions. * @param file_cb Callback function to make per file in the diff. * @param hunk_cb Optional callback to make per hunk of text diff. This * callback is called to describe a range of lines in the @@ -706,10 +702,10 @@ GIT_EXTERN(int) git_diff_find_similar( * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_diff_foreach( - git_diff_list *diff, + git_diff *diff, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb line_cb, + git_diff_line_cb line_cb, void *payload); /** @@ -718,14 +714,14 @@ GIT_EXTERN(int) git_diff_foreach( * Returning a non-zero value from the callbacks will terminate the * iteration and cause this return `GIT_EUSER`. * - * @param diff A git_diff_list generated by one of the above functions. + * @param diff A git_diff generated by one of the above functions. * @param print_cb Callback to make per line of diff text. * @param payload Reference pointer that will be passed to your callback. * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_diff_print_compact( - git_diff_list *diff, - git_diff_data_cb print_cb, + git_diff *diff, + git_diff_line_cb print_cb, void *payload); /** @@ -734,14 +730,14 @@ GIT_EXTERN(int) git_diff_print_compact( * Returning a non-zero value from the callbacks will terminate the * iteration and cause this return `GIT_EUSER`. * - * @param diff A git_diff_list generated by one of the above functions. + * @param diff A git_diff generated by one of the above functions. * @param print_cb Callback to make per line of diff text. * @param payload Reference pointer that will be passed to your callback. * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_diff_print_raw( - git_diff_list *diff, - git_diff_data_cb print_cb, + git_diff *diff, + git_diff_line_cb print_cb, void *payload); /** @@ -766,7 +762,7 @@ GIT_EXTERN(char) git_diff_status_char(git_delta_t status); * Returning a non-zero value from the callbacks will terminate the * iteration and cause this return `GIT_EUSER`. * - * @param diff A git_diff_list generated by one of the above functions. + * @param diff A git_diff generated by one of the above functions. * @param payload Reference pointer that will be passed to your callbacks. * @param print_cb Callback function to output lines of the diff. This * same function will be called for file headers, hunk @@ -776,17 +772,17 @@ GIT_EXTERN(char) git_diff_status_char(git_delta_t status); * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ GIT_EXTERN(int) git_diff_print_patch( - git_diff_list *diff, - git_diff_data_cb print_cb, + git_diff *diff, + git_diff_line_cb print_cb, void *payload); /** * Query how many diff records are there in a diff list. * - * @param diff A git_diff_list generated by one of the above functions + * @param diff A git_diff generated by one of the above functions * @return Count of number of deltas in the list */ -GIT_EXTERN(size_t) git_diff_num_deltas(git_diff_list *diff); +GIT_EXTERN(size_t) git_diff_num_deltas(git_diff *diff); /** * Query how many diff deltas are there in a diff list filtered by type. @@ -795,12 +791,12 @@ GIT_EXTERN(size_t) git_diff_num_deltas(git_diff_list *diff); * that is a `git_delta_t` and returns just the count of how many deltas * match that particular type. * - * @param diff A git_diff_list generated by one of the above functions + * @param diff A git_diff generated by one of the above functions * @param type A git_delta_t value to filter the count * @return Count of number of deltas matching delta_t type */ GIT_EXTERN(size_t) git_diff_num_deltas_of_type( - git_diff_list *diff, + git_diff *diff, git_delta_t type); /** @@ -809,191 +805,7 @@ GIT_EXTERN(size_t) git_diff_num_deltas_of_type( * @param diff Diff list to check * @return 0 if case sensitive, 1 if case is ignored */ -GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff_list *diff); - -/** - * Return the diff delta and patch for an entry in the diff list. - * - * The `git_diff_patch` is a newly created object contains the text diffs - * for the delta. You have to call `git_diff_patch_free()` when you are - * done with it. You can use the patch object to loop over all the hunks - * and lines in the diff of the one delta. - * - * For an unchanged file or a binary file, no `git_diff_patch` will be - * created, the output will be set to NULL, and the `binary` flag will be - * set true in the `git_diff_delta` structure. - * - * The `git_diff_delta` pointer points to internal data and you do not have - * to release it when you are done with it. It will go away when the - * `git_diff_list` and `git_diff_patch` go away. - * - * It is okay to pass NULL for either of the output parameters; if you pass - * NULL for the `git_diff_patch`, then the text diff will not be calculated. - * - * @param patch_out Output parameter for the delta patch object - * @param delta_out Output parameter for the delta object - * @param diff Diff list object - * @param idx Index into diff list - * @return 0 on success, other value < 0 on error - */ -GIT_EXTERN(int) git_diff_get_patch( - git_diff_patch **patch_out, - const git_diff_delta **delta_out, - git_diff_list *diff, - size_t idx); - -/** - * Free a git_diff_patch object. - */ -GIT_EXTERN(void) git_diff_patch_free( - git_diff_patch *patch); - -/** - * Get the delta associated with a patch - */ -GIT_EXTERN(const git_diff_delta *) git_diff_patch_delta( - git_diff_patch *patch); - -/** - * Get the number of hunks in a patch - */ -GIT_EXTERN(size_t) git_diff_patch_num_hunks( - git_diff_patch *patch); - -/** - * Get line counts of each type in a patch. - * - * This helps imitate a diff --numstat type of output. For that purpose, - * you only need the `total_additions` and `total_deletions` values, but we - * include the `total_context` line count in case you want the total number - * of lines of diff output that will be generated. - * - * All outputs are optional. Pass NULL if you don't need a particular count. - * - * @param total_context Count of context lines in output, can be NULL. - * @param total_additions Count of addition lines in output, can be NULL. - * @param total_deletions Count of deletion lines in output, can be NULL. - * @param patch The git_diff_patch object - * @return 0 on success, <0 on error - */ -GIT_EXTERN(int) git_diff_patch_line_stats( - size_t *total_context, - size_t *total_additions, - size_t *total_deletions, - const git_diff_patch *patch); - -/** - * Get the information about a hunk in a patch - * - * Given a patch and a hunk index into the patch, this returns detailed - * information about that hunk. Any of the output pointers can be passed - * as NULL if you don't care about that particular piece of information. - * - * @param range Output pointer to git_diff_range of hunk - * @param header Output pointer to header string for hunk. Unlike the - * content pointer for each line, this will be NUL-terminated - * @param header_len Output value of characters in header string - * @param lines_in_hunk Output count of total lines in this hunk - * @param patch Input pointer to patch object - * @param hunk_idx Input index of hunk to get information about - * @return 0 on success, GIT_ENOTFOUND if hunk_idx out of range, <0 on error - */ -GIT_EXTERN(int) git_diff_patch_get_hunk( - const git_diff_range **range, - const char **header, - size_t *header_len, - size_t *lines_in_hunk, - git_diff_patch *patch, - size_t hunk_idx); - -/** - * Get the number of lines in a hunk. - * - * @param patch The git_diff_patch object - * @param hunk_idx Index of the hunk - * @return Number of lines in hunk or -1 if invalid hunk index - */ -GIT_EXTERN(int) git_diff_patch_num_lines_in_hunk( - git_diff_patch *patch, - size_t hunk_idx); - -/** - * Get data about a line in a hunk of a patch. - * - * Given a patch, a hunk index, and a line index in the hunk, this - * will return a lot of details about that line. If you pass a hunk - * index larger than the number of hunks or a line index larger than - * the number of lines in the hunk, this will return -1. - * - * @param line_origin A GIT_DIFF_LINE constant from above - * @param content Pointer to content of diff line, not NUL-terminated - * @param content_len Number of characters in content - * @param old_lineno Line number in old file or -1 if line is added - * @param new_lineno Line number in new file or -1 if line is deleted - * @param patch The patch to look in - * @param hunk_idx The index of the hunk - * @param line_of_hunk The index of the line in the hunk - * @return 0 on success, <0 on failure - */ -GIT_EXTERN(int) git_diff_patch_get_line_in_hunk( - char *line_origin, - const char **content, - size_t *content_len, - int *old_lineno, - int *new_lineno, - git_diff_patch *patch, - size_t hunk_idx, - size_t line_of_hunk); - -/** - * Look up size of patch diff data in bytes - * - * This returns the raw size of the patch data. This only includes the - * actual data from the lines of the diff, not the file or hunk headers. - * - * If you pass `include_context` as true (non-zero), this will be the size - * of all of the diff output; if you pass it as false (zero), this will - * only include the actual changed lines (as if `context_lines` was 0). - * - * @param patch A git_diff_patch representing changes to one file - * @param include_context Include context lines in size if non-zero - * @param include_hunk_headers Include hunk header lines if non-zero - * @param include_file_headers Include file header lines if non-zero - * @return The number of bytes of data - */ -GIT_EXTERN(size_t) git_diff_patch_size( - git_diff_patch *patch, - int include_context, - int include_hunk_headers, - int include_file_headers); - -/** - * Serialize the patch to text via callback. - * - * Returning a non-zero value from the callback will terminate the iteration - * and cause this return `GIT_EUSER`. - * - * @param patch A git_diff_patch representing changes to one file - * @param print_cb Callback function to output lines of the patch. Will be - * called for file headers, hunk headers, and diff lines. - * @param payload Reference pointer that will be passed to your callbacks. - * @return 0 on success, GIT_EUSER on non-zero callback, or error code - */ -GIT_EXTERN(int) git_diff_patch_print( - git_diff_patch *patch, - git_diff_data_cb print_cb, - void *payload); - -/** - * Get the content of a patch as a single diff text. - * - * @param string Allocated string; caller must free. - * @param patch A git_diff_patch representing changes to one file - * @return 0 on success, <0 on failure. - */ -GIT_EXTERN(int) git_diff_patch_to_str( - char **string, - git_diff_patch *patch); +GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff *diff); /**@}*/ @@ -1037,33 +849,9 @@ GIT_EXTERN(int) git_diff_blobs( const git_diff_options *options, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb line_cb, + git_diff_line_cb line_cb, void *payload); -/** - * Directly generate a patch from the difference between two blobs. - * - * This is just like `git_diff_blobs()` except it generates a patch object - * for the difference instead of directly making callbacks. You can use the - * standard `git_diff_patch` accessor functions to read the patch data, and - * you must call `git_diff_patch_free()` on the patch when done. - * - * @param out The generated patch; NULL on error - * @param old_blob Blob for old side of diff, or NULL for empty blob - * @param old_as_path Treat old blob as if it had this filename; can be NULL - * @param new_blob Blob for new side of diff, or NULL for empty blob - * @param new_as_path Treat new blob as if it had this filename; can be NULL - * @param opts Options for diff, or NULL for default options - * @return 0 on success or error code < 0 - */ -GIT_EXTERN(int) git_diff_patch_from_blobs( - git_diff_patch **out, - const git_blob *old_blob, - const char *old_as_path, - const git_blob *new_blob, - const char *new_as_path, - const git_diff_options *opts); - /** * Directly run a diff between a blob and a buffer. * @@ -1084,7 +872,7 @@ GIT_EXTERN(int) git_diff_patch_from_blobs( * @param options Options for diff, or NULL for default options * @param file_cb Callback for "file"; made once if there is a diff; can be NULL * @param hunk_cb Callback for each hunk in diff; can be NULL - * @param data_cb Callback for each line in diff; can be NULL + * @param line_cb Callback for each line in diff; can be NULL * @param payload Payload passed to each callback function * @return 0 on success, GIT_EUSER on non-zero callback return, or error code */ @@ -1097,35 +885,9 @@ GIT_EXTERN(int) git_diff_blob_to_buffer( const git_diff_options *options, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb data_cb, + git_diff_line_cb line_cb, void *payload); -/** - * Directly generate a patch from the difference between a blob and a buffer. - * - * This is just like `git_diff_blob_to_buffer()` except it generates a patch - * object for the difference instead of directly making callbacks. You can - * use the standard `git_diff_patch` accessor functions to read the patch - * data, and you must call `git_diff_patch_free()` on the patch when done. - * - * @param out The generated patch; NULL on error - * @param old_blob Blob for old side of diff, or NULL for empty blob - * @param old_as_path Treat old blob as if it had this filename; can be NULL - * @param buffer Raw data for new side of diff, or NULL for empty - * @param buffer_len Length of raw data for new side of diff - * @param buffer_as_path Treat buffer as if it had this filename; can be NULL - * @param opts Options for diff, or NULL for default options - * @return 0 on success or error code < 0 - */ -GIT_EXTERN(int) git_diff_patch_from_blob_and_buffer( - git_diff_patch **out, - const git_blob *old_blob, - const char *old_as_path, - const char *buffer, - size_t buffer_len, - const char *buffer_as_path, - const git_diff_options *opts); - GIT_END_DECL diff --git a/include/git2/patch.h b/include/git2/patch.h new file mode 100644 index 000000000..ad9be7516 --- /dev/null +++ b/include/git2/patch.h @@ -0,0 +1,270 @@ +/* + * 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_patch_h__ +#define INCLUDE_git_patch_h__ + +#include "common.h" +#include "types.h" +#include "oid.h" +#include "diff.h" + +/** + * @file git2/patch.h + * @brief Patch handling routines. + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * The diff patch is used to store all the text diffs for a delta. + * + * You can easily loop over the content of patches and get information about + * them. + */ +typedef struct git_patch git_patch; + +/** + * Return the diff delta and patch for an entry in the diff list. + * + * The `git_patch` is a newly created object contains the text diffs + * for the delta. You have to call `git_patch_free()` when you are + * done with it. You can use the patch object to loop over all the hunks + * and lines in the diff of the one delta. + * + * For an unchanged file or a binary file, no `git_patch` will be + * created, the output will be set to NULL, and the `binary` flag will be + * set true in the `git_diff_delta` structure. + * + * The `git_diff_delta` pointer points to internal data and you do not have + * to release it when you are done with it. It will go away when the + * `git_diff` and `git_patch` go away. + * + * It is okay to pass NULL for either of the output parameters; if you pass + * NULL for the `git_patch`, then the text diff will not be calculated. + * + * @param patch_out Output parameter for the delta patch object + * @param delta_out Output parameter for the delta object + * @param diff Diff list object + * @param idx Index into diff list + * @return 0 on success, other value < 0 on error + */ +GIT_EXTERN(int) git_patch_from_diff( + git_patch **patch_out, + const git_diff_delta **delta_out, + git_diff *diff, + size_t idx); + +/** + * Directly generate a patch from the difference between two blobs. + * + * This is just like `git_diff_blobs()` except it generates a patch object + * for the difference instead of directly making callbacks. You can use the + * standard `git_patch` accessor functions to read the patch data, and + * you must call `git_patch_free()` on the patch when done. + * + * @param out The generated patch; NULL on error + * @param old_blob Blob for old side of diff, or NULL for empty blob + * @param old_as_path Treat old blob as if it had this filename; can be NULL + * @param new_blob Blob for new side of diff, or NULL for empty blob + * @param new_as_path Treat new blob as if it had this filename; can be NULL + * @param opts Options for diff, or NULL for default options + * @return 0 on success or error code < 0 + */ +GIT_EXTERN(int) git_patch_from_blobs( + git_patch **out, + const git_blob *old_blob, + const char *old_as_path, + const git_blob *new_blob, + const char *new_as_path, + const git_diff_options *opts); + +/** + * Directly generate a patch from the difference between a blob and a buffer. + * + * This is just like `git_diff_blob_to_buffer()` except it generates a patch + * object for the difference instead of directly making callbacks. You can + * use the standard `git_patch` accessor functions to read the patch + * data, and you must call `git_patch_free()` on the patch when done. + * + * @param out The generated patch; NULL on error + * @param old_blob Blob for old side of diff, or NULL for empty blob + * @param old_as_path Treat old blob as if it had this filename; can be NULL + * @param buffer Raw data for new side of diff, or NULL for empty + * @param buffer_len Length of raw data for new side of diff + * @param buffer_as_path Treat buffer as if it had this filename; can be NULL + * @param opts Options for diff, or NULL for default options + * @return 0 on success or error code < 0 + */ +GIT_EXTERN(int) git_patch_from_blob_and_buffer( + git_patch **out, + const git_blob *old_blob, + const char *old_as_path, + const char *buffer, + size_t buffer_len, + const char *buffer_as_path, + const git_diff_options *opts); + +/** + * Free a git_patch object. + */ +GIT_EXTERN(void) git_patch_free( + git_patch *patch); + +/** + * Get the delta associated with a patch + */ +GIT_EXTERN(const git_diff_delta *) git_patch_delta( + git_patch *patch); + +/** + * Get the number of hunks in a patch + */ +GIT_EXTERN(size_t) git_patch_num_hunks( + git_patch *patch); + +/** + * Get line counts of each type in a patch. + * + * This helps imitate a diff --numstat type of output. For that purpose, + * you only need the `total_additions` and `total_deletions` values, but we + * include the `total_context` line count in case you want the total number + * of lines of diff output that will be generated. + * + * All outputs are optional. Pass NULL if you don't need a particular count. + * + * @param total_context Count of context lines in output, can be NULL. + * @param total_additions Count of addition lines in output, can be NULL. + * @param total_deletions Count of deletion lines in output, can be NULL. + * @param patch The git_patch object + * @return 0 on success, <0 on error + */ +GIT_EXTERN(int) git_patch_line_stats( + size_t *total_context, + size_t *total_additions, + size_t *total_deletions, + const git_patch *patch); + +/** + * Get the information about a hunk in a patch + * + * Given a patch and a hunk index into the patch, this returns detailed + * information about that hunk. Any of the output pointers can be passed + * as NULL if you don't care about that particular piece of information. + * + * @param out Output pointer to git_diff_hunk of hunk + * @param header Output pointer to header string for hunk. Unlike the + * content pointer for each line, this will be NUL-terminated + * @param header_len Output value of characters in header string + * @param lines_in_hunk Output count of total lines in this hunk + * @param patch Input pointer to patch object + * @param hunk_idx Input index of hunk to get information about + * @return 0 on success, GIT_ENOTFOUND if hunk_idx out of range, <0 on error + */ +GIT_EXTERN(int) git_patch_get_hunk( + const git_diff_hunk **out, + const char **header, + size_t *header_len, + size_t *lines_in_hunk, + git_patch *patch, + size_t hunk_idx); + +/** + * Get the number of lines in a hunk. + * + * @param patch The git_patch object + * @param hunk_idx Index of the hunk + * @return Number of lines in hunk or -1 if invalid hunk index + */ +GIT_EXTERN(int) git_patch_num_lines_in_hunk( + git_patch *patch, + size_t hunk_idx); + +/** + * Get data about a line in a hunk of a patch. + * + * Given a patch, a hunk index, and a line index in the hunk, this + * will return a lot of details about that line. If you pass a hunk + * index larger than the number of hunks or a line index larger than + * the number of lines in the hunk, this will return -1. + * + * @param line_origin A GIT_DIFF_LINE constant from above + * @param content Pointer to content of diff line, not NUL-terminated + * @param content_len Number of characters in content + * @param old_lineno Line number in old file or -1 if line is added + * @param new_lineno Line number in new file or -1 if line is deleted + * @param patch The patch to look in + * @param hunk_idx The index of the hunk + * @param line_of_hunk The index of the line in the hunk + * @return 0 on success, <0 on failure + */ +GIT_EXTERN(int) git_patch_get_line_in_hunk( + char *line_origin, + const char **content, + size_t *content_len, + int *old_lineno, + int *new_lineno, + git_patch *patch, + size_t hunk_idx, + size_t line_of_hunk); + +/** + * Look up size of patch diff data in bytes + * + * This returns the raw size of the patch data. This only includes the + * actual data from the lines of the diff, not the file or hunk headers. + * + * If you pass `include_context` as true (non-zero), this will be the size + * of all of the diff output; if you pass it as false (zero), this will + * only include the actual changed lines (as if `context_lines` was 0). + * + * @param patch A git_patch representing changes to one file + * @param include_context Include context lines in size if non-zero + * @param include_hunk_headers Include hunk header lines if non-zero + * @param include_file_headers Include file header lines if non-zero + * @return The number of bytes of data + */ +GIT_EXTERN(size_t) git_patch_size( + git_patch *patch, + int include_context, + int include_hunk_headers, + int include_file_headers); + +/** + * Serialize the patch to text via callback. + * + * Returning a non-zero value from the callback will terminate the iteration + * and cause this return `GIT_EUSER`. + * + * @param patch A git_patch representing changes to one file + * @param print_cb Callback function to output lines of the patch. Will be + * called for file headers, hunk headers, and diff lines. + * @param payload Reference pointer that will be passed to your callbacks. + * @return 0 on success, GIT_EUSER on non-zero callback, or error code + */ +GIT_EXTERN(int) git_patch_print( + git_patch *patch, + git_diff_line_cb print_cb, + void *payload); + +/** + * Get the content of a patch as a single diff text. + * + * @param string Allocated string; caller must free. + * @param patch A git_patch representing changes to one file + * @return 0 on success, <0 on failure. + */ +GIT_EXTERN(int) git_patch_to_str( + char **string, + git_patch *patch); + + +GIT_END_DECL + +/**@}*/ + +#endif diff --git a/include/git2/pathspec.h b/include/git2/pathspec.h index a835f8e52..2fb0bb716 100644 --- a/include/git2/pathspec.h +++ b/include/git2/pathspec.h @@ -187,7 +187,7 @@ GIT_EXTERN(int) git_pathspec_match_tree( */ GIT_EXTERN(int) git_pathspec_match_diff( git_pathspec_match_list **out, - git_diff_list *diff, + git_diff *diff, uint32_t flags, git_pathspec *ps); diff --git a/src/checkout.c b/src/checkout.c index d3f673d40..6519ab550 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -43,7 +43,7 @@ enum { typedef struct { git_repository *repo; - git_diff_list *diff; + git_diff *diff; git_checkout_opts opts; bool opts_free_baseline; char *pfx; @@ -1320,7 +1320,7 @@ cleanup: (data.strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0) error = git_index_write(data.index); - git_diff_list_free(data.diff); + git_diff_free(data.diff); git_iterator_free(workdir); git_iterator_free(baseline); git__free(actions); diff --git a/src/diff.c b/src/diff.c index 39facce60..1efde98e4 100644 --- a/src/diff.c +++ b/src/diff.c @@ -21,7 +21,7 @@ (VAL) ? ((DIFF)->opts.flags | (FLAG)) : ((DIFF)->opts.flags & ~(VAL)) static git_diff_delta *diff_delta__alloc( - git_diff_list *diff, + git_diff *diff, git_delta_t status, const char *path) { @@ -50,7 +50,7 @@ static git_diff_delta *diff_delta__alloc( } static int diff_notify( - const git_diff_list *diff, + const git_diff *diff, const git_diff_delta *delta, const char *matched_pathspec) { @@ -62,7 +62,7 @@ static int diff_notify( } static int diff_delta__from_one( - git_diff_list *diff, + git_diff *diff, git_delta_t status, const git_index_entry *entry) { @@ -120,7 +120,7 @@ static int diff_delta__from_one( } static int diff_delta__from_two( - git_diff_list *diff, + git_diff *diff, git_delta_t status, const git_index_entry *old_entry, uint32_t old_mode, @@ -181,7 +181,7 @@ static int diff_delta__from_two( } static git_diff_delta *diff_delta__last_for_item( - git_diff_list *diff, + git_diff *diff, const git_index_entry *item) { git_diff_delta *delta = git_vector_last(&diff->deltas); @@ -340,13 +340,13 @@ static const char *diff_mnemonic_prefix( return pfx; } -static git_diff_list *diff_list_alloc( +static git_diff *diff_list_alloc( git_repository *repo, git_iterator *old_iter, git_iterator *new_iter) { git_diff_options dflt = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = git__calloc(1, sizeof(git_diff_list)); + git_diff *diff = git__calloc(1, sizeof(git_diff)); if (!diff) return NULL; @@ -360,7 +360,7 @@ static git_diff_list *diff_list_alloc( if (git_vector_init(&diff->deltas, 0, git_diff_delta__cmp) < 0 || git_pool_init(&diff->pool, 1, 0) < 0) { - git_diff_list_free(diff); + git_diff_free(diff); return NULL; } @@ -389,7 +389,7 @@ static git_diff_list *diff_list_alloc( } static int diff_list_apply_options( - git_diff_list *diff, + git_diff *diff, const git_diff_options *opts) { git_config *cfg; @@ -490,7 +490,7 @@ static int diff_list_apply_options( return 0; } -static void diff_list_free(git_diff_list *diff) +static void diff_list_free(git_diff *diff) { git_diff_delta *delta; unsigned int i; @@ -508,7 +508,7 @@ static void diff_list_free(git_diff_list *diff) git__free(diff); } -void git_diff_list_free(git_diff_list *diff) +void git_diff_free(git_diff *diff) { if (!diff) return; @@ -516,7 +516,7 @@ void git_diff_list_free(git_diff_list *diff) GIT_REFCOUNT_DEC(diff, diff_list_free); } -void git_diff_list_addref(git_diff_list *diff) +void git_diff_addref(git_diff *diff) { GIT_REFCOUNT_INC(diff); } @@ -612,7 +612,7 @@ typedef struct { static int maybe_modified_submodule( git_delta_t *status, git_oid *found_oid, - git_diff_list *diff, + git_diff *diff, diff_in_progress *info) { int error = 0; @@ -659,7 +659,7 @@ static int maybe_modified_submodule( } static int maybe_modified( - git_diff_list *diff, + git_diff *diff, diff_in_progress *info) { git_oid noid; @@ -778,7 +778,7 @@ static int maybe_modified( } static bool entry_is_prefixed( - git_diff_list *diff, + git_diff *diff, const git_index_entry *item, const git_index_entry *prefix_item) { @@ -795,7 +795,7 @@ static bool entry_is_prefixed( } static int diff_scan_inside_untracked_dir( - git_diff_list *diff, diff_in_progress *info, git_delta_t *delta_type) + git_diff *diff, diff_in_progress *info, git_delta_t *delta_type) { int error = 0; git_buf base = GIT_BUF_INIT; @@ -861,7 +861,7 @@ done: } static int handle_unmatched_new_item( - git_diff_list *diff, diff_in_progress *info) + git_diff *diff, diff_in_progress *info) { int error = 0; const git_index_entry *nitem = info->nitem; @@ -1016,7 +1016,7 @@ static int handle_unmatched_new_item( } static int handle_unmatched_old_item( - git_diff_list *diff, diff_in_progress *info) + git_diff *diff, diff_in_progress *info) { int error = diff_delta__from_one(diff, GIT_DELTA_DELETED, info->oitem); if (error < 0) @@ -1048,7 +1048,7 @@ static int handle_unmatched_old_item( } static int handle_matched_item( - git_diff_list *diff, diff_in_progress *info) + git_diff *diff, diff_in_progress *info) { int error = 0; @@ -1063,7 +1063,7 @@ static int handle_matched_item( } int git_diff__from_iterators( - git_diff_list **diff_ptr, + git_diff **diff_ptr, git_repository *repo, git_iterator *old_iter, git_iterator *new_iter, @@ -1071,7 +1071,7 @@ int git_diff__from_iterators( { int error = 0; diff_in_progress info; - git_diff_list *diff; + git_diff *diff; *diff_ptr = NULL; @@ -1132,7 +1132,7 @@ cleanup: if (!error) *diff_ptr = diff; else - git_diff_list_free(diff); + git_diff_free(diff); git_buf_free(&info.ignore_prefix); @@ -1149,7 +1149,7 @@ cleanup: } while (0) int git_diff_tree_to_tree( - git_diff_list **diff, + git_diff **diff, git_repository *repo, git_tree *old_tree, git_tree *new_tree, @@ -1176,7 +1176,7 @@ int git_diff_tree_to_tree( } int git_diff_tree_to_index( - git_diff_list **diff, + git_diff **diff, git_repository *repo, git_tree *old_tree, git_index *index, @@ -1204,7 +1204,7 @@ int git_diff_tree_to_index( git_index__set_ignore_case(index, true); if (!error) { - git_diff_list *d = *diff; + git_diff *d = *diff; d->opts.flags |= GIT_DIFF_DELTAS_ARE_ICASE; d->strcomp = git__strcasecmp; @@ -1221,7 +1221,7 @@ int git_diff_tree_to_index( } int git_diff_index_to_workdir( - git_diff_list **diff, + git_diff **diff, git_repository *repo, git_index *index, const git_diff_options *opts) @@ -1244,7 +1244,7 @@ int git_diff_index_to_workdir( int git_diff_tree_to_workdir( - git_diff_list **diff, + git_diff **diff, git_repository *repo, git_tree *old_tree, const git_diff_options *opts) @@ -1262,13 +1262,13 @@ int git_diff_tree_to_workdir( return error; } -size_t git_diff_num_deltas(git_diff_list *diff) +size_t git_diff_num_deltas(git_diff *diff) { assert(diff); return (size_t)diff->deltas.length; } -size_t git_diff_num_deltas_of_type(git_diff_list *diff, git_delta_t type) +size_t git_diff_num_deltas_of_type(git_diff *diff, git_delta_t type) { size_t i, count = 0; git_diff_delta *delta; @@ -1282,14 +1282,14 @@ size_t git_diff_num_deltas_of_type(git_diff_list *diff, git_delta_t type) return count; } -int git_diff_is_sorted_icase(const git_diff_list *diff) +int git_diff_is_sorted_icase(const git_diff *diff) { return (diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0; } int git_diff__paired_foreach( - git_diff_list *head2idx, - git_diff_list *idx2wd, + git_diff *head2idx, + git_diff *idx2wd, int (*cb)(git_diff_delta *h2i, git_diff_delta *i2w, void *payload), void *payload) { diff --git a/src/diff.h b/src/diff.h index bec7e27d7..270bea071 100644 --- a/src/diff.h +++ b/src/diff.h @@ -52,7 +52,7 @@ enum { #define GIT_DIFF__VERBOSE (1 << 30) -struct git_diff_list { +struct git_diff { git_refcount rc; git_repository *repo; git_diff_options opts; @@ -72,7 +72,7 @@ struct git_diff_list { extern void git_diff__cleanup_modes( uint32_t diffcaps, uint32_t *omode, uint32_t *nmode); -extern void git_diff_list_addref(git_diff_list *diff); +extern void git_diff_addref(git_diff *diff); extern int git_diff_delta__cmp(const void *a, const void *b); extern int git_diff_delta__casecmp(const void *a, const void *b); @@ -93,15 +93,15 @@ extern int git_diff__oid_for_file( git_repository *, const char *, uint16_t, git_off_t, git_oid *); extern int git_diff__from_iterators( - git_diff_list **diff_ptr, + git_diff **diff_ptr, git_repository *repo, git_iterator *old_iter, git_iterator *new_iter, const git_diff_options *opts); extern int git_diff__paired_foreach( - git_diff_list *idx2head, - git_diff_list *wd2idx, + git_diff *idx2head, + git_diff *wd2idx, int (*cb)(git_diff_delta *i2h, git_diff_delta *w2i, void *payload), void *payload); diff --git a/src/diff_file.c b/src/diff_file.c index 5939ee8b8..a7bca4dca 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -88,7 +88,7 @@ static int diff_file_content_init_common( int git_diff_file_content__init_from_diff( git_diff_file_content *fc, - git_diff_list *diff, + git_diff *diff, size_t delta_index, bool use_old) { diff --git a/src/diff_file.h b/src/diff_file.h index fb08cca6a..84bf255aa 100644 --- a/src/diff_file.h +++ b/src/diff_file.h @@ -27,7 +27,7 @@ typedef struct { extern int git_diff_file_content__init_from_diff( git_diff_file_content *fc, - git_diff_list *diff, + git_diff *diff, size_t delta_index, bool use_old); diff --git a/src/diff_patch.c b/src/diff_patch.c index cc45b6ddb..a106944c7 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -24,16 +24,16 @@ struct diff_patch_line { /* cached information about a hunk in a diff */ typedef struct diff_patch_hunk diff_patch_hunk; struct diff_patch_hunk { - git_diff_range range; + git_diff_hunk hunk; char header[128]; size_t header_len; size_t line_start; size_t line_count; }; -struct git_diff_patch { +struct git_patch { git_refcount rc; - git_diff_list *diff; /* for refcount purposes, maybe NULL for blob diffs */ + git_diff *diff; /* for refcount purposes, maybe NULL for blob diffs */ git_diff_delta *delta; size_t delta_index; git_diff_file_content ofile; @@ -56,11 +56,11 @@ enum { }; static void diff_output_init(git_diff_output*, const git_diff_options*, - git_diff_file_cb, git_diff_hunk_cb, git_diff_data_cb, void*); + git_diff_file_cb, git_diff_hunk_cb, git_diff_line_cb, void*); -static void diff_output_to_patch(git_diff_output *, git_diff_patch *); +static void diff_output_to_patch(git_diff_output *, git_patch *); -static void diff_patch_update_binary(git_diff_patch *patch) +static void diff_patch_update_binary(git_patch *patch) { if ((patch->delta->flags & DIFF_FLAGS_KNOWN_BINARY) != 0) return; @@ -74,7 +74,7 @@ static void diff_patch_update_binary(git_diff_patch *patch) patch->delta->flags |= GIT_DIFF_FLAG_NOT_BINARY; } -static void diff_patch_init_common(git_diff_patch *patch) +static void diff_patch_init_common(git_patch *patch) { diff_patch_update_binary(patch); @@ -84,11 +84,11 @@ static void diff_patch_init_common(git_diff_patch *patch) patch->flags |= GIT_DIFF_PATCH_INITIALIZED; if (patch->diff) - git_diff_list_addref(patch->diff); + git_diff_addref(patch->diff); } static int diff_patch_init_from_diff( - git_diff_patch *patch, git_diff_list *diff, size_t delta_index) + git_patch *patch, git_diff *diff, size_t delta_index) { int error = 0; @@ -109,12 +109,12 @@ static int diff_patch_init_from_diff( } static int diff_patch_alloc_from_diff( - git_diff_patch **out, - git_diff_list *diff, + git_patch **out, + git_diff *diff, size_t delta_index) { int error; - git_diff_patch *patch = git__calloc(1, sizeof(git_diff_patch)); + git_patch *patch = git__calloc(1, sizeof(git_patch)); GITERR_CHECK_ALLOC(patch); if (!(error = diff_patch_init_from_diff(patch, diff, delta_index))) { @@ -129,7 +129,7 @@ static int diff_patch_alloc_from_diff( return error; } -static int diff_patch_load(git_diff_patch *patch, git_diff_output *output) +static int diff_patch_load(git_patch *patch, git_diff_output *output) { int error = 0; bool incomplete_data; @@ -207,7 +207,7 @@ cleanup: } static int diff_patch_file_callback( - git_diff_patch *patch, git_diff_output *output) + git_patch *patch, git_diff_output *output) { float progress; @@ -223,7 +223,7 @@ static int diff_patch_file_callback( return output->error; } -static int diff_patch_generate(git_diff_patch *patch, git_diff_output *output) +static int diff_patch_generate(git_patch *patch, git_diff_output *output) { int error = 0; @@ -248,7 +248,7 @@ static int diff_patch_generate(git_diff_patch *patch, git_diff_output *output) return error; } -static void diff_patch_free(git_diff_patch *patch) +static void diff_patch_free(git_patch *patch) { git_diff_file_content__clear(&patch->ofile); git_diff_file_content__clear(&patch->nfile); @@ -256,7 +256,7 @@ static void diff_patch_free(git_diff_patch *patch) git_array_clear(patch->lines); git_array_clear(patch->hunks); - git_diff_list_free(patch->diff); /* decrements refcount */ + git_diff_free(patch->diff); /* decrements refcount */ patch->diff = NULL; git_pool_clear(&patch->flattened); @@ -265,7 +265,7 @@ static void diff_patch_free(git_diff_patch *patch) git__free(patch); } -static int diff_required(git_diff_list *diff, const char *action) +static int diff_required(git_diff *diff, const char *action) { if (diff) return 0; @@ -274,16 +274,16 @@ static int diff_required(git_diff_list *diff, const char *action) } int git_diff_foreach( - git_diff_list *diff, + git_diff *diff, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb data_cb, + git_diff_line_cb data_cb, void *payload) { int error = 0; git_xdiff_output xo; size_t idx; - git_diff_patch patch; + git_patch patch; if (diff_required(diff, "git_diff_foreach") < 0) return -1; @@ -305,7 +305,7 @@ int git_diff_foreach( if (!error) error = diff_patch_generate(&patch, &xo.output); - git_diff_patch_free(&patch); + git_patch_free(&patch); } if (error < 0) @@ -318,7 +318,7 @@ int git_diff_foreach( } typedef struct { - git_diff_patch patch; + git_patch patch; git_diff_delta delta; char paths[GIT_FLEX_ARRAY]; } diff_patch_with_delta; @@ -326,7 +326,7 @@ typedef struct { static int diff_single_generate(diff_patch_with_delta *pd, git_xdiff_output *xo) { int error = 0; - git_diff_patch *patch = &pd->patch; + git_patch *patch = &pd->patch; bool has_old = ((patch->ofile.flags & GIT_DIFF_FLAG__NO_DATA) == 0); bool has_new = ((patch->nfile.flags & GIT_DIFF_FLAG__NO_DATA) == 0); @@ -430,7 +430,7 @@ int git_diff_blobs( const git_diff_options *opts, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb data_cb, + git_diff_line_cb data_cb, void *payload) { int error = 0; @@ -452,13 +452,13 @@ int git_diff_blobs( error = diff_patch_from_blobs( &pd, &xo, old_blob, old_path, new_blob, new_path, opts); - git_diff_patch_free(&pd.patch); + git_patch_free(&pd.patch); return error; } -int git_diff_patch_from_blobs( - git_diff_patch **out, +int git_patch_from_blobs( + git_patch **out, const git_blob *old_blob, const char *old_path, const git_blob *new_blob, @@ -484,9 +484,9 @@ int git_diff_patch_from_blobs( pd, &xo, old_blob, old_path, new_blob, new_path, opts); if (!error) - *out = (git_diff_patch *)pd; + *out = (git_patch *)pd; else - git_diff_patch_free((git_diff_patch *)pd); + git_patch_free((git_patch *)pd); return error; } @@ -542,7 +542,7 @@ int git_diff_blob_to_buffer( const git_diff_options *opts, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb data_cb, + git_diff_line_cb data_cb, void *payload) { int error = 0; @@ -564,13 +564,13 @@ int git_diff_blob_to_buffer( error = diff_patch_from_blob_and_buffer( &pd, &xo, old_blob, old_path, buf, buflen, buf_path, opts); - git_diff_patch_free(&pd.patch); + git_patch_free(&pd.patch); return error; } -int git_diff_patch_from_blob_and_buffer( - git_diff_patch **out, +int git_patch_from_blob_and_buffer( + git_patch **out, const git_blob *old_blob, const char *old_path, const char *buf, @@ -597,28 +597,28 @@ int git_diff_patch_from_blob_and_buffer( pd, &xo, old_blob, old_path, buf, buflen, buf_path, opts); if (!error) - *out = (git_diff_patch *)pd; + *out = (git_patch *)pd; else - git_diff_patch_free((git_diff_patch *)pd); + git_patch_free((git_patch *)pd); return error; } -int git_diff_get_patch( - git_diff_patch **patch_ptr, +int git_patch_from_diff( + git_patch **patch_ptr, const git_diff_delta **delta_ptr, - git_diff_list *diff, + git_diff *diff, size_t idx) { int error = 0; git_xdiff_output xo; git_diff_delta *delta = NULL; - git_diff_patch *patch = NULL; + git_patch *patch = NULL; if (patch_ptr) *patch_ptr = NULL; if (delta_ptr) *delta_ptr = NULL; - if (diff_required(diff, "git_diff_get_patch") < 0) + if (diff_required(diff, "git_patch_from_diff") < 0) return -1; delta = git_vector_get(&diff->deltas, idx); @@ -656,7 +656,7 @@ int git_diff_get_patch( } if (error || !patch_ptr) - git_diff_patch_free(patch); + git_patch_free(patch); else *patch_ptr = patch; @@ -665,29 +665,29 @@ int git_diff_get_patch( return error; } -void git_diff_patch_free(git_diff_patch *patch) +void git_patch_free(git_patch *patch) { if (patch) GIT_REFCOUNT_DEC(patch, diff_patch_free); } -const git_diff_delta *git_diff_patch_delta(git_diff_patch *patch) +const git_diff_delta *git_patch_delta(git_patch *patch) { assert(patch); return patch->delta; } -size_t git_diff_patch_num_hunks(git_diff_patch *patch) +size_t git_patch_num_hunks(git_patch *patch) { assert(patch); return git_array_size(patch->hunks); } -int git_diff_patch_line_stats( +int git_patch_line_stats( size_t *total_ctxt, size_t *total_adds, size_t *total_dels, - const git_diff_patch *patch) + const git_patch *patch) { size_t totals[3], idx; @@ -726,12 +726,12 @@ static int diff_error_outofrange(const char *thing) return GIT_ENOTFOUND; } -int git_diff_patch_get_hunk( - const git_diff_range **range, +int git_patch_get_hunk( + const git_diff_hunk **out, const char **header, size_t *header_len, size_t *lines_in_hunk, - git_diff_patch *patch, + git_patch *patch, size_t hunk_idx) { diff_patch_hunk *hunk; @@ -740,21 +740,21 @@ int git_diff_patch_get_hunk( hunk = git_array_get(patch->hunks, hunk_idx); if (!hunk) { - if (range) *range = NULL; + if (out) *out = NULL; if (header) *header = NULL; if (header_len) *header_len = 0; if (lines_in_hunk) *lines_in_hunk = 0; return diff_error_outofrange("hunk"); } - if (range) *range = &hunk->range; + if (out) *out = &hunk->hunk; if (header) *header = hunk->header; if (header_len) *header_len = hunk->header_len; if (lines_in_hunk) *lines_in_hunk = hunk->line_count; return 0; } -int git_diff_patch_num_lines_in_hunk(git_diff_patch *patch, size_t hunk_idx) +int git_patch_num_lines_in_hunk(git_patch *patch, size_t hunk_idx) { diff_patch_hunk *hunk; assert(patch); @@ -764,13 +764,13 @@ int git_diff_patch_num_lines_in_hunk(git_diff_patch *patch, size_t hunk_idx) return (int)hunk->line_count; } -int git_diff_patch_get_line_in_hunk( +int git_patch_get_line_in_hunk( char *line_origin, const char **content, size_t *content_len, int *old_lineno, int *new_lineno, - git_diff_patch *patch, + git_patch *patch, size_t hunk_idx, size_t line_of_hunk) { @@ -810,8 +810,8 @@ notfound: return diff_error_outofrange(thing); } -size_t git_diff_patch_size( - git_diff_patch *patch, +size_t git_patch_size( + git_patch *patch, int include_context, int include_hunk_headers, int include_file_headers) @@ -843,36 +843,36 @@ size_t git_diff_patch_size( return out; } -git_diff_list *git_diff_patch__diff(git_diff_patch *patch) +git_diff *git_patch__diff(git_patch *patch) { return patch->diff; } -git_diff_driver *git_diff_patch__driver(git_diff_patch *patch) +git_diff_driver *git_patch__driver(git_patch *patch) { /* ofile driver is representative for whole patch */ return patch->ofile.driver; } -void git_diff_patch__old_data( - char **ptr, size_t *len, git_diff_patch *patch) +void git_patch__old_data( + char **ptr, size_t *len, git_patch *patch) { *ptr = patch->ofile.map.data; *len = patch->ofile.map.len; } -void git_diff_patch__new_data( - char **ptr, size_t *len, git_diff_patch *patch) +void git_patch__new_data( + char **ptr, size_t *len, git_patch *patch) { *ptr = patch->nfile.map.data; *len = patch->nfile.map.len; } -int git_diff_patch__invoke_callbacks( - git_diff_patch *patch, +int git_patch__invoke_callbacks( + git_patch *patch, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb line_cb, + git_diff_line_cb line_cb, void *payload) { int error = 0; @@ -888,7 +888,7 @@ int git_diff_patch__invoke_callbacks( diff_patch_hunk *h = git_array_get(patch->hunks, i); error = hunk_cb( - patch->delta, &h->range, h->header, h->header_len, payload); + patch->delta, &h->hunk, h->header, h->header_len, payload); if (!line_cb) continue; @@ -898,7 +898,7 @@ int git_diff_patch__invoke_callbacks( git_array_get(patch->lines, h->line_start + j); error = line_cb( - patch->delta, &h->range, l->origin, l->ptr, l->len, payload); + patch->delta, &h->hunk, l->origin, l->ptr, l->len, payload); } } @@ -917,12 +917,12 @@ static int diff_patch_file_cb( static int diff_patch_hunk_cb( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *hunk_, const char *header, size_t header_len, void *payload) { - git_diff_patch *patch = payload; + git_patch *patch = payload; diff_patch_hunk *hunk; GIT_UNUSED(delta); @@ -930,7 +930,7 @@ static int diff_patch_hunk_cb( hunk = git_array_alloc(patch->hunks); GITERR_CHECK_ALLOC(hunk); - memcpy(&hunk->range, range, sizeof(hunk->range)); + memcpy(&hunk->hunk, hunk_, sizeof(hunk->hunk)); assert(header_len + 1 < sizeof(hunk->header)); memcpy(&hunk->header, header, header_len); @@ -942,27 +942,27 @@ static int diff_patch_hunk_cb( hunk->line_start = git_array_size(patch->lines); hunk->line_count = 0; - patch->oldno = range->old_start; - patch->newno = range->new_start; + patch->oldno = hunk_->old_start; + patch->newno = hunk_->new_start; return 0; } static int diff_patch_line_cb( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *hunk_, char line_origin, const char *content, size_t content_len, void *payload) { - git_diff_patch *patch = payload; + git_patch *patch = payload; diff_patch_hunk *hunk; diff_patch_line *line; const char *content_end = content + content_len; GIT_UNUSED(delta); - GIT_UNUSED(range); + GIT_UNUSED(hunk_); hunk = git_array_last(patch->hunks); GITERR_CHECK_ALLOC(hunk); @@ -1023,7 +1023,7 @@ static void diff_output_init( const git_diff_options *opts, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb data_cb, + git_diff_line_cb data_cb, void *payload) { GIT_UNUSED(opts); @@ -1036,7 +1036,7 @@ static void diff_output_init( out->payload = payload; } -static void diff_output_to_patch(git_diff_output *out, git_diff_patch *patch) +static void diff_output_to_patch(git_diff_output *out, git_patch *patch) { diff_output_init( out, NULL, diff --git a/src/diff_patch.h b/src/diff_patch.h index 56af14600..df2ba4c31 100644 --- a/src/diff_patch.h +++ b/src/diff_patch.h @@ -11,19 +11,20 @@ #include "diff.h" #include "diff_file.h" #include "array.h" +#include "git2/patch.h" -extern git_diff_list *git_diff_patch__diff(git_diff_patch *); +extern git_diff *git_patch__diff(git_patch *); -extern git_diff_driver *git_diff_patch__driver(git_diff_patch *); +extern git_diff_driver *git_patch__driver(git_patch *); -extern void git_diff_patch__old_data(char **, size_t *, git_diff_patch *); -extern void git_diff_patch__new_data(char **, size_t *, git_diff_patch *); +extern void git_patch__old_data(char **, size_t *, git_patch *); +extern void git_patch__new_data(char **, size_t *, git_patch *); -extern int git_diff_patch__invoke_callbacks( - git_diff_patch *patch, +extern int git_patch__invoke_callbacks( + git_patch *patch, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb line_cb, + git_diff_line_cb line_cb, void *payload); typedef struct git_diff_output git_diff_output; @@ -31,7 +32,7 @@ struct git_diff_output { /* these callbacks are issued with the diff data */ git_diff_file_cb file_cb; git_diff_hunk_cb hunk_cb; - git_diff_data_cb data_cb; + git_diff_line_cb data_cb; void *payload; /* this records the actual error in cases where it may be obscured */ @@ -40,7 +41,7 @@ struct git_diff_output { /* this callback is used to do the diff and drive the other callbacks. * see diff_xdiff.h for how to use this in practice for now. */ - int (*diff_cb)(git_diff_output *output, git_diff_patch *patch); + int (*diff_cb)(git_diff_output *output, git_patch *patch); }; #endif diff --git a/src/diff_print.c b/src/diff_print.c index fd18b67e3..1cf6da2e3 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -10,8 +10,8 @@ #include "fileops.h" typedef struct { - git_diff_list *diff; - git_diff_data_cb print_cb; + git_diff *diff; + git_diff_line_cb print_cb; void *payload; git_buf *buf; int oid_strlen; @@ -19,7 +19,7 @@ typedef struct { static int diff_print_info_init( diff_print_info *pi, - git_buf *out, git_diff_list *diff, git_diff_data_cb cb, void *payload) + git_buf *out, git_diff *diff, git_diff_line_cb cb, void *payload) { pi->diff = diff; pi->print_cb = cb; @@ -119,10 +119,10 @@ static int diff_print_one_compact( return 0; } -/* print a git_diff_list to a print callback in compact format */ +/* print a git_diff to a print callback in compact format */ int git_diff_print_compact( - git_diff_list *diff, - git_diff_data_cb print_cb, + git_diff *diff, + git_diff_line_cb print_cb, void *payload) { int error; @@ -180,10 +180,10 @@ static int diff_print_one_raw( return 0; } -/* print a git_diff_list to a print callback in raw output format */ +/* print a git_diff to a print callback in raw output format */ int git_diff_print_raw( - git_diff_list *diff, - git_diff_data_cb print_cb, + git_diff *diff, + git_diff_line_cb print_cb, void *payload) { int error; @@ -325,7 +325,7 @@ static int diff_print_patch_file( static int diff_print_patch_hunk( const git_diff_delta *d, - const git_diff_range *r, + const git_diff_hunk *r, const char *header, size_t header_len, void *data) @@ -348,7 +348,7 @@ static int diff_print_patch_hunk( static int diff_print_patch_line( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *range, char line_origin, /* GIT_DIFF_LINE value from above */ const char *content, size_t content_len, @@ -379,10 +379,10 @@ static int diff_print_patch_line( return 0; } -/* print a git_diff_list to an output callback in patch format */ +/* print a git_diff to an output callback in patch format */ int git_diff_print_patch( - git_diff_list *diff, - git_diff_data_cb print_cb, + git_diff *diff, + git_diff_line_cb print_cb, void *payload) { int error; @@ -399,10 +399,10 @@ int git_diff_print_patch( return error; } -/* print a git_diff_patch to an output callback */ -int git_diff_patch_print( - git_diff_patch *patch, - git_diff_data_cb print_cb, +/* print a git_patch to an output callback */ +int git_patch_print( + git_patch *patch, + git_diff_line_cb print_cb, void *payload) { int error; @@ -412,8 +412,8 @@ int git_diff_patch_print( assert(patch && print_cb); if (!(error = diff_print_info_init( - &pi, &temp, git_diff_patch__diff(patch), print_cb, payload))) - error = git_diff_patch__invoke_callbacks( + &pi, &temp, git_patch__diff(patch), print_cb, payload))) + error = git_patch__invoke_callbacks( patch, diff_print_patch_file, diff_print_patch_hunk, diff_print_patch_line, &pi); @@ -424,7 +424,7 @@ int git_diff_patch_print( static int diff_print_to_buffer_cb( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *range, char line_origin, const char *content, size_t content_len, @@ -435,15 +435,15 @@ static int diff_print_to_buffer_cb( return git_buf_put(output, content, content_len); } -/* print a git_diff_patch to a string buffer */ -int git_diff_patch_to_str( +/* print a git_patch to a string buffer */ +int git_patch_to_str( char **string, - git_diff_patch *patch) + git_patch *patch) { int error; git_buf output = GIT_BUF_INIT; - error = git_diff_patch_print(patch, diff_print_to_buffer_cb, &output); + error = git_patch_print(patch, diff_print_to_buffer_cb, &output); /* GIT_EUSER means git_buf_put in print_to_buffer_cb returned -1, * meaning a memory allocation failure, so just map to -1... diff --git a/src/diff_tform.c b/src/diff_tform.c index cbe8bafbd..c0a60672c 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -97,8 +97,8 @@ static git_diff_delta *diff_delta__merge_like_cgit( } int git_diff_merge( - git_diff_list *onto, - const git_diff_list *from) + git_diff *onto, + const git_diff *from) { int error = 0; git_pool onto_pool; @@ -230,7 +230,7 @@ int git_diff_find_similar__calc_similarity( #define DEFAULT_RENAME_LIMIT 200 static int normalize_find_opts( - git_diff_list *diff, + git_diff *diff, git_diff_find_options *opts, git_diff_find_options *given) { @@ -328,7 +328,7 @@ static int normalize_find_opts( } static int apply_splits_and_deletes( - git_diff_list *diff, size_t expected_size, bool actually_split) + git_diff *diff, size_t expected_size, bool actually_split) { git_vector onto = GIT_VECTOR_INIT; size_t i; @@ -402,7 +402,7 @@ on_error: return -1; } -GIT_INLINE(git_diff_file *) similarity_get_file(git_diff_list *diff, size_t idx) +GIT_INLINE(git_diff_file *) similarity_get_file(git_diff *diff, size_t idx) { git_diff_delta *delta = git_vector_get(&diff->deltas, idx / 2); return (idx & 1) ? &delta->new_file : &delta->old_file; @@ -419,7 +419,7 @@ typedef struct { } similarity_info; static int similarity_init( - similarity_info *info, git_diff_list *diff, size_t file_idx) + similarity_info *info, git_diff *diff, size_t file_idx) { info->idx = file_idx; info->src = (file_idx & 1) ? diff->new_src : diff->old_src; @@ -509,7 +509,7 @@ static void similarity_unload(similarity_info *info) */ static int similarity_measure( int *score, - git_diff_list *diff, + git_diff *diff, const git_diff_find_options *opts, void **cache, size_t a_idx, @@ -595,7 +595,7 @@ cleanup: } static int calc_self_similarity( - git_diff_list *diff, + git_diff *diff, const git_diff_find_options *opts, size_t delta_idx, void **cache) @@ -620,7 +620,7 @@ static int calc_self_similarity( } static bool is_rename_target( - git_diff_list *diff, + git_diff *diff, const git_diff_find_options *opts, size_t delta_idx, void **cache) @@ -675,7 +675,7 @@ static bool is_rename_target( } static bool is_rename_source( - git_diff_list *diff, + git_diff *diff, const git_diff_find_options *opts, size_t delta_idx, void **cache) @@ -759,7 +759,7 @@ typedef struct { } diff_find_match; int git_diff_find_similar( - git_diff_list *diff, + git_diff *diff, git_diff_find_options *given_opts) { size_t s, t; diff --git a/src/diff_xdiff.c b/src/diff_xdiff.c index 7694fb996..e3aa8f3e1 100644 --- a/src/diff_xdiff.c +++ b/src/diff_xdiff.c @@ -24,26 +24,26 @@ static int git_xdiff_scan_int(const char **str, int *value) return (digits > 0) ? 0 : -1; } -static int git_xdiff_parse_hunk(git_diff_range *range, const char *header) +static int git_xdiff_parse_hunk(git_diff_hunk *hunk, const char *header) { /* expect something of the form "@@ -%d[,%d] +%d[,%d] @@" */ if (*header != '@') return -1; - if (git_xdiff_scan_int(&header, &range->old_start) < 0) + if (git_xdiff_scan_int(&header, &hunk->old_start) < 0) return -1; if (*header == ',') { - if (git_xdiff_scan_int(&header, &range->old_lines) < 0) + if (git_xdiff_scan_int(&header, &hunk->old_lines) < 0) return -1; } else - range->old_lines = 1; - if (git_xdiff_scan_int(&header, &range->new_start) < 0) + hunk->old_lines = 1; + if (git_xdiff_scan_int(&header, &hunk->new_start) < 0) return -1; if (*header == ',') { - if (git_xdiff_scan_int(&header, &range->new_lines) < 0) + if (git_xdiff_scan_int(&header, &hunk->new_lines) < 0) return -1; } else - range->new_lines = 1; - if (range->old_start < 0 || range->new_start < 0) + hunk->new_lines = 1; + if (hunk->old_start < 0 || hunk->new_start < 0) return -1; return 0; @@ -51,24 +51,24 @@ static int git_xdiff_parse_hunk(git_diff_range *range, const char *header) typedef struct { git_xdiff_output *xo; - git_diff_patch *patch; - git_diff_range range; + git_patch *patch; + git_diff_hunk hunk; } git_xdiff_info; static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) { git_xdiff_info *info = priv; - git_diff_patch *patch = info->patch; - const git_diff_delta *delta = git_diff_patch_delta(patch); + git_patch *patch = info->patch; + const git_diff_delta *delta = git_patch_delta(patch); git_diff_output *output = &info->xo->output; if (len == 1) { - output->error = git_xdiff_parse_hunk(&info->range, bufs[0].ptr); + output->error = git_xdiff_parse_hunk(&info->hunk, bufs[0].ptr); if (output->error < 0) return output->error; if (output->hunk_cb != NULL && - output->hunk_cb(delta, &info->range, + output->hunk_cb(delta, &info->hunk, bufs[0].ptr, bufs[0].size, output->payload)) output->error = GIT_EUSER; } @@ -81,7 +81,7 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) GIT_DIFF_LINE_CONTEXT; if (output->data_cb != NULL && - output->data_cb(delta, &info->range, + output->data_cb(delta, &info->hunk, origin, bufs[1].ptr, bufs[1].size, output->payload)) output->error = GIT_EUSER; } @@ -98,7 +98,7 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) GIT_DIFF_LINE_CONTEXT_EOFNL; if (output->data_cb != NULL && - output->data_cb(delta, &info->range, + output->data_cb(delta, &info->hunk, origin, bufs[2].ptr, bufs[2].size, output->payload)) output->error = GIT_EUSER; } @@ -106,7 +106,7 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) return output->error; } -static int git_xdiff(git_diff_output *output, git_diff_patch *patch) +static int git_xdiff(git_diff_output *output, git_patch *patch) { git_xdiff_output *xo = (git_xdiff_output *)output; git_xdiff_info info; @@ -120,7 +120,7 @@ static int git_xdiff(git_diff_output *output, git_diff_patch *patch) xo->callback.priv = &info; git_diff_find_context_init( - &xo->config.find_func, &findctxt, git_diff_patch__driver(patch)); + &xo->config.find_func, &findctxt, git_patch__driver(patch)); xo->config.find_func_priv = &findctxt; if (xo->config.find_func != NULL) @@ -132,8 +132,8 @@ static int git_xdiff(git_diff_output *output, git_diff_patch *patch) * updates are needed to xo->params.flags */ - git_diff_patch__old_data(&xd_old_data.ptr, &xd_old_data.size, patch); - git_diff_patch__new_data(&xd_new_data.ptr, &xd_new_data.size, patch); + git_patch__old_data(&xd_old_data.ptr, &xd_old_data.size, patch); + git_patch__new_data(&xd_new_data.ptr, &xd_new_data.size, patch); xdl_diff(&xd_old_data, &xd_new_data, &xo->params, &xo->config, &xo->callback); diff --git a/src/pathspec.c b/src/pathspec.c index d56d03918..1e7e65e90 100644 --- a/src/pathspec.c +++ b/src/pathspec.c @@ -585,7 +585,7 @@ int git_pathspec_match_tree( int git_pathspec_match_diff( git_pathspec_match_list **out, - git_diff_list *diff, + git_diff *diff, uint32_t flags, git_pathspec *ps) { diff --git a/src/reset.c b/src/reset.c index cea212a93..3fd4b9165 100644 --- a/src/reset.c +++ b/src/reset.c @@ -24,7 +24,7 @@ int git_reset_default( { git_object *commit = NULL; git_tree *tree = NULL; - git_diff_list *diff = NULL; + git_diff *diff = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; size_t i; git_diff_delta *delta; @@ -85,7 +85,7 @@ cleanup: git_object_free(commit); git_tree_free(tree); git_index_free(index); - git_diff_list_free(diff); + git_diff_free(diff); return error; } diff --git a/src/stash.c b/src/stash.c index 7742eee19..6cf26f711 100644 --- a/src/stash.c +++ b/src/stash.c @@ -221,7 +221,7 @@ static int build_untracked_tree( uint32_t flags) { git_tree *i_tree = NULL; - git_diff_list *diff = NULL; + git_diff *diff = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; struct cb_data data = {0}; int error; @@ -259,7 +259,7 @@ static int build_untracked_tree( error = build_tree_from_index(tree_out, index); cleanup: - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(i_tree); return error; } @@ -311,7 +311,7 @@ static int build_workdir_tree( { git_repository *repo = git_index_owner(index); git_tree *b_tree = NULL; - git_diff_list *diff = NULL, *diff2 = NULL; + git_diff *diff = NULL, *diff2 = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; struct cb_data data = {0}; int error; @@ -346,8 +346,8 @@ static int build_workdir_tree( goto cleanup; cleanup: - git_diff_list_free(diff); - git_diff_list_free(diff2); + git_diff_free(diff); + git_diff_free(diff2); git_tree_free(b_tree); return error; diff --git a/src/status.c b/src/status.c index be40b9f83..2b84794b5 100644 --- a/src/status.c +++ b/src/status.c @@ -52,7 +52,7 @@ static unsigned int index_delta2status(const git_diff_delta *head2idx) } static unsigned int workdir_delta2status( - git_diff_list *diff, git_diff_delta *idx2wd) + git_diff *diff, git_diff_delta *idx2wd) { git_status_t st = GIT_STATUS_CURRENT; @@ -361,8 +361,8 @@ void git_status_list_free(git_status_list *status) if (status == NULL) return; - git_diff_list_free(status->head2idx); - git_diff_list_free(status->idx2wd); + git_diff_free(status->head2idx); + git_diff_free(status->idx2wd); git_vector_foreach(&status->paired, i, status_entry) git__free(status_entry); diff --git a/src/status.h b/src/status.h index b58e0ebd6..33008b89c 100644 --- a/src/status.h +++ b/src/status.h @@ -14,8 +14,8 @@ struct git_status_list { git_status_options opts; - git_diff_list *head2idx; - git_diff_list *idx2wd; + git_diff *head2idx; + git_diff *idx2wd; git_vector paired; }; diff --git a/src/submodule.c b/src/submodule.c index 12ade83fe..18d80f0a9 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -1528,7 +1528,7 @@ static void submodule_get_wd_status( (sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) ? &sm->wd_oid : NULL; git_tree *sm_head = NULL; git_diff_options opt = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff; + git_diff *diff; *status = *status & ~GIT_SUBMODULE_STATUS__WD_FLAGS; @@ -1568,7 +1568,7 @@ static void submodule_get_wd_status( else { if (git_diff_num_deltas(diff) > 0) *status |= GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED; - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; } @@ -1588,7 +1588,7 @@ static void submodule_get_wd_status( if (git_diff_num_deltas(diff) != untracked) *status |= GIT_SUBMODULE_STATUS_WD_WD_MODIFIED; - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; } } diff --git a/tests-clar/diff/blob.c b/tests-clar/diff/blob.c index 42b9fcd5f..bed0da0bf 100644 --- a/tests-clar/diff/blob.c +++ b/tests-clar/diff/blob.c @@ -142,7 +142,7 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void) { git_blob *a, *b, *c; git_oid a_oid, b_oid, c_oid; - git_diff_patch *p; + git_patch *p; const git_diff_delta *delta; size_t tc, ta, td; @@ -161,11 +161,11 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void) /* Doing the equivalent of a `git diff -U1` on these files */ /* diff on tests/resources/attr/root_test1 */ - cl_git_pass(git_diff_patch_from_blobs(&p, a, NULL, b, NULL, &opts)); + cl_git_pass(git_patch_from_blobs(&p, a, NULL, b, NULL, &opts)); cl_assert(p != NULL); - delta = git_diff_patch_delta(p); + delta = git_patch_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.oid)); @@ -173,22 +173,22 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void) cl_assert(git_oid_equal(git_blob_id(b), &delta->new_file.oid)); cl_assert_equal_sz(git_blob_rawsize(b), delta->new_file.size); - cl_assert_equal_i(1, (int)git_diff_patch_num_hunks(p)); - cl_assert_equal_i(6, git_diff_patch_num_lines_in_hunk(p, 0)); + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(6, git_patch_num_lines_in_hunk(p, 0)); - cl_git_pass(git_diff_patch_line_stats(&tc, &ta, &td, p)); + cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); cl_assert_equal_i(1, (int)tc); cl_assert_equal_i(5, (int)ta); cl_assert_equal_i(0, (int)td); - git_diff_patch_free(p); + git_patch_free(p); /* diff on tests/resources/attr/root_test2 */ - cl_git_pass(git_diff_patch_from_blobs(&p, b, NULL, c, NULL, &opts)); + cl_git_pass(git_patch_from_blobs(&p, b, NULL, c, NULL, &opts)); cl_assert(p != NULL); - delta = git_diff_patch_delta(p); + delta = git_patch_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); cl_assert(git_oid_equal(git_blob_id(b), &delta->old_file.oid)); @@ -196,22 +196,22 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void) cl_assert(git_oid_equal(git_blob_id(c), &delta->new_file.oid)); cl_assert_equal_sz(git_blob_rawsize(c), delta->new_file.size); - cl_assert_equal_i(1, (int)git_diff_patch_num_hunks(p)); - cl_assert_equal_i(15, git_diff_patch_num_lines_in_hunk(p, 0)); + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(15, git_patch_num_lines_in_hunk(p, 0)); - cl_git_pass(git_diff_patch_line_stats(&tc, &ta, &td, p)); + cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); cl_assert_equal_i(3, (int)tc); cl_assert_equal_i(9, (int)ta); cl_assert_equal_i(3, (int)td); - git_diff_patch_free(p); + git_patch_free(p); /* diff on tests/resources/attr/root_test3 */ - cl_git_pass(git_diff_patch_from_blobs(&p, a, NULL, c, NULL, &opts)); + cl_git_pass(git_patch_from_blobs(&p, a, NULL, c, NULL, &opts)); cl_assert(p != NULL); - delta = git_diff_patch_delta(p); + delta = git_patch_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.oid)); @@ -219,19 +219,19 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void) cl_assert(git_oid_equal(git_blob_id(c), &delta->new_file.oid)); cl_assert_equal_sz(git_blob_rawsize(c), delta->new_file.size); - cl_git_pass(git_diff_patch_line_stats(&tc, &ta, &td, p)); + cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); cl_assert_equal_i(0, (int)tc); cl_assert_equal_i(12, (int)ta); cl_assert_equal_i(1, (int)td); - git_diff_patch_free(p); + git_patch_free(p); /* one more */ - cl_git_pass(git_diff_patch_from_blobs(&p, c, NULL, d, NULL, &opts)); + cl_git_pass(git_patch_from_blobs(&p, c, NULL, d, NULL, &opts)); cl_assert(p != NULL); - delta = git_diff_patch_delta(p); + delta = git_patch_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); cl_assert(git_oid_equal(git_blob_id(c), &delta->old_file.oid)); @@ -239,16 +239,16 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void) cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.oid)); cl_assert_equal_sz(git_blob_rawsize(d), delta->new_file.size); - cl_assert_equal_i(2, (int)git_diff_patch_num_hunks(p)); - cl_assert_equal_i(5, git_diff_patch_num_lines_in_hunk(p, 0)); - cl_assert_equal_i(9, git_diff_patch_num_lines_in_hunk(p, 1)); + cl_assert_equal_i(2, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(5, git_patch_num_lines_in_hunk(p, 0)); + cl_assert_equal_i(9, git_patch_num_lines_in_hunk(p, 1)); - cl_git_pass(git_diff_patch_line_stats(&tc, &ta, &td, p)); + cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); cl_assert_equal_i(4, (int)tc); cl_assert_equal_i(6, (int)ta); cl_assert_equal_i(4, (int)td); - git_diff_patch_free(p); + git_patch_free(p); git_blob_free(a); git_blob_free(b); @@ -317,16 +317,16 @@ void test_diff_blob__can_compare_against_null_blobs(void) void test_diff_blob__can_compare_against_null_blobs_with_patch(void) { git_blob *e = NULL; - git_diff_patch *p; + git_patch *p; const git_diff_delta *delta; int line; char origin; - cl_git_pass(git_diff_patch_from_blobs(&p, d, NULL, e, NULL, &opts)); + cl_git_pass(git_patch_from_blobs(&p, d, NULL, e, NULL, &opts)); cl_assert(p != NULL); - delta = git_diff_patch_delta(p); + delta = git_patch_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); cl_assert(git_oid_equal(git_blob_id(d), &delta->old_file.oid)); @@ -334,24 +334,24 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void) cl_assert(git_oid_iszero(&delta->new_file.oid)); cl_assert_equal_sz(0, delta->new_file.size); - cl_assert_equal_i(1, (int)git_diff_patch_num_hunks(p)); - cl_assert_equal_i(14, git_diff_patch_num_lines_in_hunk(p, 0)); + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p, 0)); - for (line = 0; line < git_diff_patch_num_lines_in_hunk(p, 0); ++line) { - cl_git_pass(git_diff_patch_get_line_in_hunk( + for (line = 0; line < git_patch_num_lines_in_hunk(p, 0); ++line) { + cl_git_pass(git_patch_get_line_in_hunk( &origin, NULL, NULL, NULL, NULL, p, 0, line)); cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)origin); } - git_diff_patch_free(p); + git_patch_free(p); opts.flags |= GIT_DIFF_REVERSE; - cl_git_pass(git_diff_patch_from_blobs(&p, d, NULL, e, NULL, &opts)); + cl_git_pass(git_patch_from_blobs(&p, d, NULL, e, NULL, &opts)); cl_assert(p != NULL); - delta = git_diff_patch_delta(p); + delta = git_patch_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_ADDED, delta->status); cl_assert(git_oid_iszero(&delta->old_file.oid)); @@ -359,44 +359,44 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void) cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.oid)); cl_assert_equal_sz(git_blob_rawsize(d), delta->new_file.size); - cl_assert_equal_i(1, (int)git_diff_patch_num_hunks(p)); - cl_assert_equal_i(14, git_diff_patch_num_lines_in_hunk(p, 0)); + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p, 0)); - for (line = 0; line < git_diff_patch_num_lines_in_hunk(p, 0); ++line) { - cl_git_pass(git_diff_patch_get_line_in_hunk( + for (line = 0; line < git_patch_num_lines_in_hunk(p, 0); ++line) { + cl_git_pass(git_patch_get_line_in_hunk( &origin, NULL, NULL, NULL, NULL, p, 0, line)); cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)origin); } - git_diff_patch_free(p); + git_patch_free(p); opts.flags ^= GIT_DIFF_REVERSE; - cl_git_pass(git_diff_patch_from_blobs(&p, alien, NULL, NULL, NULL, &opts)); + cl_git_pass(git_patch_from_blobs(&p, alien, NULL, NULL, NULL, &opts)); cl_assert(p != NULL); - delta = git_diff_patch_delta(p); + delta = git_patch_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); - cl_assert_equal_i(0, (int)git_diff_patch_num_hunks(p)); + cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); - git_diff_patch_free(p); + git_patch_free(p); - cl_git_pass(git_diff_patch_from_blobs(&p, NULL, NULL, alien, NULL, &opts)); + cl_git_pass(git_patch_from_blobs(&p, NULL, NULL, alien, NULL, &opts)); cl_assert(p != NULL); - delta = git_diff_patch_delta(p); + delta = git_patch_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_ADDED, delta->status); cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); - cl_assert_equal_i(0, (int)git_diff_patch_num_hunks(p)); + cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); - git_diff_patch_free(p); + git_patch_free(p); } static void assert_identical_blobs_comparison(diff_expects *expected) @@ -437,13 +437,13 @@ void test_diff_blob__can_compare_identical_blobs(void) void test_diff_blob__can_compare_identical_blobs_with_patch(void) { - git_diff_patch *p; + git_patch *p; const git_diff_delta *delta; - cl_git_pass(git_diff_patch_from_blobs(&p, d, NULL, d, NULL, &opts)); + cl_git_pass(git_patch_from_blobs(&p, d, NULL, d, NULL, &opts)); cl_assert(p != NULL); - delta = git_diff_patch_delta(p); + delta = git_patch_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status); cl_assert_equal_sz(delta->old_file.size, git_blob_rawsize(d)); @@ -451,13 +451,13 @@ void test_diff_blob__can_compare_identical_blobs_with_patch(void) cl_assert_equal_sz(delta->new_file.size, git_blob_rawsize(d)); cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.oid)); - cl_assert_equal_i(0, (int)git_diff_patch_num_hunks(p)); - git_diff_patch_free(p); + cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); + git_patch_free(p); - cl_git_pass(git_diff_patch_from_blobs(&p, NULL, NULL, NULL, NULL, &opts)); + cl_git_pass(git_patch_from_blobs(&p, NULL, NULL, NULL, NULL, &opts)); cl_assert(p != NULL); - delta = git_diff_patch_delta(p); + delta = git_patch_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status); cl_assert_equal_sz(0, delta->old_file.size); @@ -465,14 +465,14 @@ void test_diff_blob__can_compare_identical_blobs_with_patch(void) cl_assert_equal_sz(0, delta->new_file.size); cl_assert(git_oid_iszero(&delta->new_file.oid)); - cl_assert_equal_i(0, (int)git_diff_patch_num_hunks(p)); - git_diff_patch_free(p); + cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); + git_patch_free(p); - cl_git_pass(git_diff_patch_from_blobs(&p, alien, NULL, alien, NULL, &opts)); + cl_git_pass(git_patch_from_blobs(&p, alien, NULL, alien, NULL, &opts)); cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_diff_patch_delta(p)->status); - cl_assert_equal_i(0, (int)git_diff_patch_num_hunks(p)); - git_diff_patch_free(p); + cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_patch_delta(p)->status); + cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); + git_patch_free(p); } static void assert_binary_blobs_comparison(diff_expects *expected) @@ -693,7 +693,7 @@ void test_diff_blob__can_compare_blob_to_buffer(void) void test_diff_blob__can_compare_blob_to_buffer_with_patch(void) { - git_diff_patch *p; + git_patch *p; git_blob *a; git_oid a_oid; const char *a_content = "Hello from the root\n"; @@ -705,58 +705,58 @@ void test_diff_blob__can_compare_blob_to_buffer_with_patch(void) cl_git_pass(git_blob_lookup_prefix(&a, g_repo, &a_oid, 4)); /* diff from blob a to content of b */ - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, a, NULL, b_content, strlen(b_content), NULL, &opts)); cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_MODIFIED, git_diff_patch_delta(p)->status); - cl_assert_equal_i(1, (int)git_diff_patch_num_hunks(p)); - cl_assert_equal_i(6, git_diff_patch_num_lines_in_hunk(p, 0)); + cl_assert_equal_i(GIT_DELTA_MODIFIED, git_patch_delta(p)->status); + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(6, git_patch_num_lines_in_hunk(p, 0)); - cl_git_pass(git_diff_patch_line_stats(&tc, &ta, &td, p)); + cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); cl_assert_equal_i(1, (int)tc); cl_assert_equal_i(5, (int)ta); cl_assert_equal_i(0, (int)td); - git_diff_patch_free(p); + git_patch_free(p); /* diff from blob a to content of a */ opts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, a, NULL, a_content, strlen(a_content), NULL, &opts)); cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_diff_patch_delta(p)->status); - cl_assert_equal_i(0, (int)git_diff_patch_num_hunks(p)); - git_diff_patch_free(p); + cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_patch_delta(p)->status); + cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); + git_patch_free(p); /* diff from NULL blob to content of a */ - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, NULL, NULL, a_content, strlen(a_content), NULL, &opts)); cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_ADDED, git_diff_patch_delta(p)->status); - cl_assert_equal_i(1, (int)git_diff_patch_num_hunks(p)); - cl_assert_equal_i(1, git_diff_patch_num_lines_in_hunk(p, 0)); - git_diff_patch_free(p); + cl_assert_equal_i(GIT_DELTA_ADDED, git_patch_delta(p)->status); + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); + git_patch_free(p); /* diff from blob a to NULL buffer */ - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, a, NULL, NULL, 0, NULL, &opts)); cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_DELETED, git_diff_patch_delta(p)->status); - cl_assert_equal_i(1, (int)git_diff_patch_num_hunks(p)); - cl_assert_equal_i(1, git_diff_patch_num_lines_in_hunk(p, 0)); - git_diff_patch_free(p); + cl_assert_equal_i(GIT_DELTA_DELETED, git_patch_delta(p)->status); + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); + git_patch_free(p); /* diff with reverse */ opts.flags ^= GIT_DIFF_REVERSE; - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, a, NULL, NULL, 0, NULL, &opts)); cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_ADDED, git_diff_patch_delta(p)->status); - cl_assert_equal_i(1, (int)git_diff_patch_num_hunks(p)); - cl_assert_equal_i(1, git_diff_patch_num_lines_in_hunk(p, 0)); - git_diff_patch_free(p); + cl_assert_equal_i(GIT_DELTA_ADDED, git_patch_delta(p)->status); + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); + git_patch_free(p); git_blob_free(a); } @@ -853,7 +853,7 @@ void test_diff_blob__using_path_and_attributes(void) "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n"; size_t bin_len = 33; const char *changed; - git_diff_patch *p; + git_patch *p; char *pout; /* set up custom diff drivers and 'diff' attribute mappings for them */ @@ -950,9 +950,9 @@ void test_diff_blob__using_path_and_attributes(void) cl_assert_equal_i(3, expected.line_adds); cl_assert_equal_i(0, expected.line_dels); - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, nonbin, "zzz.normal", changed, strlen(changed), NULL, &opts)); - cl_git_pass(git_diff_patch_to_str(&pout, p)); + cl_git_pass(git_patch_to_str(&pout, p)); cl_assert_equal_s( "diff --git a/zzz.normal b/zzz.normal\n" "index 45141a7..75b0dbb 100644\n" @@ -963,21 +963,21 @@ void test_diff_blob__using_path_and_attributes(void) "+And more\n" "+Go here\n", pout); git__free(pout); - git_diff_patch_free(p); + git_patch_free(p); - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, nonbin, "zzz.binary", changed, strlen(changed), NULL, &opts)); - cl_git_pass(git_diff_patch_to_str(&pout, p)); + cl_git_pass(git_patch_to_str(&pout, p)); cl_assert_equal_s( "diff --git a/zzz.binary b/zzz.binary\n" "index 45141a7..75b0dbb 100644\n" "Binary files a/zzz.binary and b/zzz.binary differ\n", pout); git__free(pout); - git_diff_patch_free(p); + git_patch_free(p); - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, nonbin, "zzz.alphary", changed, strlen(changed), NULL, &opts)); - cl_git_pass(git_diff_patch_to_str(&pout, p)); + cl_git_pass(git_patch_to_str(&pout, p)); cl_assert_equal_s( "diff --git a/zzz.alphary b/zzz.alphary\n" "index 45141a7..75b0dbb 100644\n" @@ -988,11 +988,11 @@ void test_diff_blob__using_path_and_attributes(void) "+And more\n" "+Go here\n", pout); git__free(pout); - git_diff_patch_free(p); + git_patch_free(p); - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, nonbin, "zzz.numary", changed, strlen(changed), NULL, &opts)); - cl_git_pass(git_diff_patch_to_str(&pout, p)); + cl_git_pass(git_patch_to_str(&pout, p)); cl_assert_equal_s( "diff --git a/zzz.numary b/zzz.numary\n" "index 45141a7..75b0dbb 100644\n" @@ -1003,7 +1003,7 @@ void test_diff_blob__using_path_and_attributes(void) "+And more\n" "+Go here\n", pout); git__free(pout); - git_diff_patch_free(p); + git_patch_free(p); /* "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n" * 33 bytes @@ -1011,19 +1011,19 @@ void test_diff_blob__using_path_and_attributes(void) changed = "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\nreplace a line\n"; - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, bin, "zzz.normal", changed, 37, NULL, &opts)); - cl_git_pass(git_diff_patch_to_str(&pout, p)); + cl_git_pass(git_patch_to_str(&pout, p)); cl_assert_equal_s( "diff --git a/zzz.normal b/zzz.normal\n" "index b435cd5..1604519 100644\n" "Binary files a/zzz.normal and b/zzz.normal differ\n", pout); git__free(pout); - git_diff_patch_free(p); + git_patch_free(p); - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, bin, "zzz.textary", changed, 37, NULL, &opts)); - cl_git_pass(git_diff_patch_to_str(&pout, p)); + cl_git_pass(git_patch_to_str(&pout, p)); cl_assert_equal_s( "diff --git a/zzz.textary b/zzz.textary\n" "index b435cd5..1604519 100644\n" @@ -1033,11 +1033,11 @@ void test_diff_blob__using_path_and_attributes(void) "-0123456789\n" "+replace a line\n", pout); git__free(pout); - git_diff_patch_free(p); + git_patch_free(p); - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, bin, "zzz.textalphary", changed, 37, NULL, &opts)); - cl_git_pass(git_diff_patch_to_str(&pout, p)); + cl_git_pass(git_patch_to_str(&pout, p)); cl_assert_equal_s( "diff --git a/zzz.textalphary b/zzz.textalphary\n" "index b435cd5..1604519 100644\n" @@ -1047,11 +1047,11 @@ void test_diff_blob__using_path_and_attributes(void) "-0123456789\n" "+replace a line\n", pout); git__free(pout); - git_diff_patch_free(p); + git_patch_free(p); - cl_git_pass(git_diff_patch_from_blob_and_buffer( + cl_git_pass(git_patch_from_blob_and_buffer( &p, bin, "zzz.textnumary", changed, 37, NULL, &opts)); - cl_git_pass(git_diff_patch_to_str(&pout, p)); + cl_git_pass(git_patch_to_str(&pout, p)); cl_assert_equal_s( "diff --git a/zzz.textnumary b/zzz.textnumary\n" "index b435cd5..1604519 100644\n" @@ -1061,7 +1061,7 @@ void test_diff_blob__using_path_and_attributes(void) "-0123456789\n" "+replace a line\n", pout); git__free(pout); - git_diff_patch_free(p); + git_patch_free(p); git_blob_free(nonbin); git_blob_free(bin); diff --git a/tests-clar/diff/diff_helpers.c b/tests-clar/diff/diff_helpers.c index 3452f231d..34ef1df5a 100644 --- a/tests-clar/diff/diff_helpers.c +++ b/tests-clar/diff/diff_helpers.c @@ -95,7 +95,7 @@ int diff_print_file_cb( int diff_hunk_cb( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *range, const char *header, size_t header_len, void *payload) @@ -115,7 +115,7 @@ int diff_hunk_cb( int diff_line_cb( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *range, char line_origin, const char *content, size_t content_len, @@ -149,25 +149,25 @@ int diff_line_cb( } int diff_foreach_via_iterator( - git_diff_list *diff, + git_diff *diff, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb line_cb, + git_diff_line_cb line_cb, void *data) { size_t d, num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { - git_diff_patch *patch; + git_patch *patch; const git_diff_delta *delta; size_t h, num_h; - cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d)); + cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); cl_assert(delta); /* call file_cb for this file */ if (file_cb != NULL && file_cb(delta, (float)d / num_d, data) != 0) { - git_diff_patch_free(patch); + git_patch_free(patch); goto abort; } @@ -179,22 +179,22 @@ int diff_foreach_via_iterator( } if (!hunk_cb && !line_cb) { - git_diff_patch_free(patch); + git_patch_free(patch); continue; } - num_h = git_diff_patch_num_hunks(patch); + num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { - const git_diff_range *range; + const git_diff_hunk *range; const char *hdr; size_t hdr_len, l, num_l; - cl_git_pass(git_diff_patch_get_hunk( + cl_git_pass(git_patch_get_hunk( &range, &hdr, &hdr_len, &num_l, patch, h)); if (hunk_cb && hunk_cb(delta, range, hdr, hdr_len, data) != 0) { - git_diff_patch_free(patch); + git_patch_free(patch); goto abort; } @@ -204,19 +204,19 @@ int diff_foreach_via_iterator( size_t line_len; int old_lineno, new_lineno; - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &line, &line_len, &old_lineno, &new_lineno, patch, h, l)); if (line_cb && line_cb(delta, range, origin, line, line_len, data) != 0) { - git_diff_patch_free(patch); + git_patch_free(patch); goto abort; } } } - git_diff_patch_free(patch); + git_patch_free(patch); } return 0; @@ -228,7 +228,7 @@ abort: static int diff_print_cb( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *range, char line_origin, /**< GIT_DIFF_LINE_... value from above */ const char *content, size_t content_len, @@ -243,12 +243,12 @@ static int diff_print_cb( return 0; } -void diff_print(FILE *fp, git_diff_list *diff) +void diff_print(FILE *fp, git_diff *diff) { cl_git_pass(git_diff_print_patch(diff, diff_print_cb, fp ? fp : stderr)); } -void diff_print_raw(FILE *fp, git_diff_list *diff) +void diff_print_raw(FILE *fp, git_diff *diff) { cl_git_pass(git_diff_print_raw(diff, diff_print_cb, fp ? fp : stderr)); } diff --git a/tests-clar/diff/diff_helpers.h b/tests-clar/diff/diff_helpers.h index bb76d0076..e3ad61f29 100644 --- a/tests-clar/diff/diff_helpers.h +++ b/tests-clar/diff/diff_helpers.h @@ -44,25 +44,25 @@ extern int diff_print_file_cb( extern int diff_hunk_cb( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *range, const char *header, size_t header_len, void *cb_data); extern int diff_line_cb( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *range, char line_origin, const char *content, size_t content_len, void *cb_data); extern int diff_foreach_via_iterator( - git_diff_list *diff, + git_diff *diff, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, - git_diff_data_cb line_cb, + git_diff_line_cb line_cb, void *data); -extern void diff_print(FILE *fp, git_diff_list *diff); -extern void diff_print_raw(FILE *fp, git_diff_list *diff); +extern void diff_print(FILE *fp, git_diff *diff); +extern void diff_print_raw(FILE *fp, git_diff *diff); diff --git a/tests-clar/diff/diffiter.c b/tests-clar/diff/diffiter.c index ea5908475..48b56e20e 100644 --- a/tests-clar/diff/diffiter.c +++ b/tests-clar/diff/diffiter.c @@ -13,7 +13,7 @@ void test_diff_diffiter__cleanup(void) void test_diff_diffiter__create(void) { git_repository *repo = cl_git_sandbox_init("attr"); - git_diff_list *diff; + git_diff *diff; size_t d, num_d; cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); @@ -21,16 +21,16 @@ void test_diff_diffiter__create(void) num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { const git_diff_delta *delta; - cl_git_pass(git_diff_get_patch(NULL, &delta, diff, d)); + cl_git_pass(git_patch_from_diff(NULL, &delta, diff, d)); } - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_diffiter__iterate_files_1(void) { git_repository *repo = cl_git_sandbox_init("attr"); - git_diff_list *diff; + git_diff *diff; size_t d, num_d; diff_expects exp = { 0 }; @@ -40,20 +40,20 @@ void test_diff_diffiter__iterate_files_1(void) for (d = 0; d < num_d; ++d) { const git_diff_delta *delta; - cl_git_pass(git_diff_get_patch(NULL, &delta, diff, d)); + cl_git_pass(git_patch_from_diff(NULL, &delta, diff, d)); cl_assert(delta != NULL); diff_file_cb(delta, (float)d / (float)num_d, &exp); } cl_assert_equal_sz(6, exp.files); - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_diffiter__iterate_files_2(void) { git_repository *repo = cl_git_sandbox_init("status"); - git_diff_list *diff; + git_diff *diff; size_t d, num_d; int count = 0; @@ -64,20 +64,20 @@ void test_diff_diffiter__iterate_files_2(void) for (d = 0; d < num_d; ++d) { const git_diff_delta *delta; - cl_git_pass(git_diff_get_patch(NULL, &delta, diff, d)); + cl_git_pass(git_patch_from_diff(NULL, &delta, diff, d)); cl_assert(delta != NULL); count++; } cl_assert_equal_i(8, count); - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_diffiter__iterate_files_and_hunks(void) { git_repository *repo = cl_git_sandbox_init("status"); git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; size_t d, num_d; int file_count = 0, hunk_count = 0; @@ -90,25 +90,25 @@ void test_diff_diffiter__iterate_files_and_hunks(void) num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { - git_diff_patch *patch; + git_patch *patch; const git_diff_delta *delta; size_t h, num_h; - cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d)); + cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); cl_assert(delta); cl_assert(patch); file_count++; - num_h = git_diff_patch_num_hunks(patch); + num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { - const git_diff_range *range; + const git_diff_hunk *range; const char *header; size_t header_len, num_l; - cl_git_pass(git_diff_patch_get_hunk( + cl_git_pass(git_patch_get_hunk( &range, &header, &header_len, &num_l, patch, h)); cl_assert(range); @@ -117,20 +117,20 @@ void test_diff_diffiter__iterate_files_and_hunks(void) hunk_count++; } - git_diff_patch_free(patch); + git_patch_free(patch); } cl_assert_equal_i(13, file_count); cl_assert_equal_i(8, hunk_count); - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_diffiter__max_size_threshold(void) { git_repository *repo = cl_git_sandbox_init("status"); git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; int file_count = 0, binary_count = 0, hunk_count = 0; size_t d, num_d; @@ -142,27 +142,27 @@ void test_diff_diffiter__max_size_threshold(void) num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { - git_diff_patch *patch; + git_patch *patch; const git_diff_delta *delta; - cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d)); + cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); cl_assert(delta); cl_assert(patch); file_count++; - hunk_count += (int)git_diff_patch_num_hunks(patch); + hunk_count += (int)git_patch_num_hunks(patch); assert((delta->flags & (GIT_DIFF_FLAG_BINARY|GIT_DIFF_FLAG_NOT_BINARY)) != 0); binary_count += ((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); - git_diff_patch_free(patch); + git_patch_free(patch); } cl_assert_equal_i(13, file_count); cl_assert_equal_i(0, binary_count); cl_assert_equal_i(8, hunk_count); - git_diff_list_free(diff); + git_diff_free(diff); /* try again with low file size threshold */ @@ -177,18 +177,18 @@ void test_diff_diffiter__max_size_threshold(void) num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { - git_diff_patch *patch; + git_patch *patch; const git_diff_delta *delta; - cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d)); + cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); file_count++; - hunk_count += (int)git_diff_patch_num_hunks(patch); + hunk_count += (int)git_patch_num_hunks(patch); assert((delta->flags & (GIT_DIFF_FLAG_BINARY|GIT_DIFF_FLAG_NOT_BINARY)) != 0); binary_count += ((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); - git_diff_patch_free(patch); + git_patch_free(patch); } cl_assert_equal_i(13, file_count); @@ -200,7 +200,7 @@ void test_diff_diffiter__max_size_threshold(void) cl_assert_equal_i(3, binary_count); cl_assert_equal_i(5, hunk_count); - git_diff_list_free(diff); + git_diff_free(diff); } @@ -208,7 +208,7 @@ void test_diff_diffiter__iterate_all(void) { git_repository *repo = cl_git_sandbox_init("status"); git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp = {0}; size_t d, num_d; @@ -220,21 +220,21 @@ void test_diff_diffiter__iterate_all(void) num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { - git_diff_patch *patch; + git_patch *patch; const git_diff_delta *delta; size_t h, num_h; - cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d)); + cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); cl_assert(patch && delta); exp.files++; - num_h = git_diff_patch_num_hunks(patch); + num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { - const git_diff_range *range; + const git_diff_hunk *range; const char *header; size_t header_len, l, num_l; - cl_git_pass(git_diff_patch_get_hunk( + cl_git_pass(git_patch_get_hunk( &range, &header, &header_len, &num_l, patch, h)); cl_assert(range && header); exp.hunks++; @@ -244,33 +244,33 @@ void test_diff_diffiter__iterate_all(void) const char *content; size_t content_len; - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &content, &content_len, NULL, NULL, patch, h, l)); cl_assert(content); exp.lines++; } } - git_diff_patch_free(patch); + git_patch_free(patch); } cl_assert_equal_i(13, exp.files); cl_assert_equal_i(8, exp.hunks); cl_assert_equal_i(14, exp.lines); - git_diff_list_free(diff); + git_diff_free(diff); } -static void iterate_over_patch(git_diff_patch *patch, diff_expects *exp) +static void iterate_over_patch(git_patch *patch, diff_expects *exp) { - size_t h, num_h = git_diff_patch_num_hunks(patch), num_l; + size_t h, num_h = git_patch_num_hunks(patch), num_l; exp->files++; exp->hunks += (int)num_h; /* let's iterate in reverse, just because we can! */ for (h = 1, num_l = 0; h <= num_h; ++h) - num_l += git_diff_patch_num_lines_in_hunk(patch, num_h - h); + num_l += git_patch_num_lines_in_hunk(patch, num_h - h); exp->lines += (int)num_l; } @@ -281,9 +281,9 @@ void test_diff_diffiter__iterate_randomly_while_saving_state(void) { git_repository *repo = cl_git_sandbox_init("status"); git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp = {0}; - git_diff_patch *patches[PATCH_CACHE]; + git_patch *patches[PATCH_CACHE]; size_t p, d, num_d; memset(patches, 0, sizeof(patches)); @@ -308,32 +308,32 @@ void test_diff_diffiter__iterate_randomly_while_saving_state(void) for (d = 0; d < num_d; ++d) { /* take old patch */ - git_diff_patch *patch = patches[p]; + git_patch *patch = patches[p]; patches[p] = NULL; /* cache new patch */ - cl_git_pass(git_diff_get_patch(&patches[p], NULL, diff, d)); + cl_git_pass(git_patch_from_diff(&patches[p], NULL, diff, d)); cl_assert(patches[p] != NULL); /* process old patch if non-NULL */ if (patch != NULL) { iterate_over_patch(patch, &exp); - git_diff_patch_free(patch); + git_patch_free(patch); } p = rand() % PATCH_CACHE; } /* free diff list now - refcounts should keep things safe */ - git_diff_list_free(diff); + git_diff_free(diff); /* process remaining unprocessed patches */ for (p = 0; p < PATCH_CACHE; p++) { - git_diff_patch *patch = patches[p]; + git_patch *patch = patches[p]; if (patch != NULL) { iterate_over_patch(patch, &exp); - git_diff_patch_free(patch); + git_patch_free(patch); } } @@ -416,7 +416,7 @@ static const char *expected_patch_text[8] = { void test_diff_diffiter__iterate_and_generate_patch_text(void) { git_repository *repo = cl_git_sandbox_init("status"); - git_diff_list *diff; + git_diff *diff; size_t d, num_d; cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); @@ -425,28 +425,28 @@ void test_diff_diffiter__iterate_and_generate_patch_text(void) cl_assert_equal_i(8, (int)num_d); for (d = 0; d < num_d; ++d) { - git_diff_patch *patch; + git_patch *patch; char *text; - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, d)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, d)); cl_assert(patch != NULL); - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected_patch_text[d], text); git__free(text); - git_diff_patch_free(patch); + git_patch_free(patch); } - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_diffiter__checks_options_version(void) { git_repository *repo = cl_git_sandbox_init("status"); git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; const git_error *err; opts.version = 0; diff --git a/tests-clar/diff/drivers.c b/tests-clar/diff/drivers.c index 719d229fc..518f24e7b 100644 --- a/tests-clar/diff/drivers.c +++ b/tests-clar/diff/drivers.c @@ -20,8 +20,8 @@ void test_diff_drivers__patterns(void) git_config *cfg; const char *one_sha = "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13"; git_tree *one; - git_diff_list *diff; - git_diff_patch *patch; + git_diff *diff; + git_patch *patch; char *text; const char *expected0 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Comes through the blood of the vanguards who\n dreamed--too soon--it had sounded.\r\n \r\n -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n"; const char *expected1 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\nBinary files a/untimely.txt and b/untimely.txt differ\n"; @@ -35,7 +35,7 @@ void test_diff_drivers__patterns(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); cl_assert_equal_i(0, (int)git_diff_num_deltas(diff)); - git_diff_list_free(diff); + git_diff_free(diff); /* default diff */ @@ -44,13 +44,13 @@ void test_diff_drivers__patterns(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected0, text); git__free(text); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); /* attribute diff set to false */ @@ -59,13 +59,13 @@ void test_diff_drivers__patterns(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected1, text); git__free(text); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); /* attribute diff set to unconfigured value (should use default) */ @@ -74,13 +74,13 @@ void test_diff_drivers__patterns(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected0, text); git__free(text); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); /* let's define that driver */ @@ -91,13 +91,13 @@ void test_diff_drivers__patterns(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected1, text); git__free(text); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); /* let's use a real driver with some regular expressions */ @@ -112,13 +112,13 @@ void test_diff_drivers__patterns(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected2, text); git__free(text); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); git_tree_free(one); } @@ -127,8 +127,8 @@ void test_diff_drivers__long_lines(void) { const char *base = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non nisi ligula. Ut viverra enim sed lobortis suscipit.\nPhasellus eget erat odio. Praesent at est iaculis, ultricies augue vel, dignissim risus. Suspendisse at nisi quis turpis fringilla rutrum id sit amet nulla.\nNam eget dolor fermentum, aliquet nisl at, convallis tellus. Pellentesque rhoncus erat enim, id porttitor elit euismod quis.\nMauris sollicitudin magna odio, non egestas libero vehicula ut. Etiam et quam velit. Fusce eget libero rhoncus, ultricies felis sit amet, egestas purus.\nAliquam in semper tellus. Pellentesque adipiscing rutrum velit, quis malesuada lacus consequat eget.\n"; git_index *idx; - git_diff_list *diff; - git_diff_patch *patch; + git_diff *diff; + git_patch *patch; char *actual; const char *expected = "diff --git a/longlines.txt b/longlines.txt\nindex c1ce6ef..0134431 100644\n--- a/longlines.txt\n+++ b/longlines.txt\n@@ -3,3 +3,5 @@ Phasellus eget erat odio. Praesent at est iaculis, ultricies augue vel, dignissi\n Nam eget dolor fermentum, aliquet nisl at, convallis tellus. Pellentesque rhoncus erat enim, id porttitor elit euismod quis.\n Mauris sollicitudin magna odio, non egestas libero vehicula ut. Etiam et quam velit. Fusce eget libero rhoncus, ultricies felis sit amet, egestas purus.\n Aliquam in semper tellus. Pellentesque adipiscing rutrum velit, quis malesuada lacus consequat eget.\n+newline\n+newline\n"; @@ -144,8 +144,8 @@ void test_diff_drivers__long_lines(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); cl_assert_equal_sz(1, git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); - cl_git_pass(git_diff_patch_to_str(&actual, patch)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_to_str(&actual, patch)); /* if chmod not supported, overwrite mode bits since anything is possible */ if (!cl_is_chmod_supported()) { @@ -157,7 +157,7 @@ void test_diff_drivers__long_lines(void) cl_assert_equal_s(expected, actual); free(actual); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); } diff --git a/tests-clar/diff/index.c b/tests-clar/diff/index.c index e1c617dae..8f4567137 100644 --- a/tests-clar/diff/index.c +++ b/tests-clar/diff/index.c @@ -21,7 +21,7 @@ void test_diff_index__0(void) git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit); git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; cl_assert(a); @@ -56,7 +56,7 @@ void test_diff_index__0(void) cl_assert_equal_i(6, exp.line_adds); cl_assert_equal_i(2, exp.line_dels); - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; memset(&exp, 0, sizeof(exp)); @@ -84,7 +84,7 @@ void test_diff_index__0(void) cl_assert_equal_i(11, exp.line_adds); cl_assert_equal_i(2, exp.line_dels); - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; git_tree_free(a); @@ -114,7 +114,7 @@ void test_diff_index__1(void) git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit); git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; cl_assert(a); @@ -134,7 +134,7 @@ void test_diff_index__1(void) cl_assert_equal_i(2, exp.files); - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; git_tree_free(a); @@ -146,7 +146,7 @@ void test_diff_index__checks_options_version(void) const char *a_commit = "26a125ee1bf"; git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; const git_error *err; opts.version = 0; diff --git a/tests-clar/diff/notify.c b/tests-clar/diff/notify.c index 433b4a9c1..cc33cb71c 100644 --- a/tests-clar/diff/notify.c +++ b/tests-clar/diff/notify.c @@ -13,7 +13,7 @@ void test_diff_notify__cleanup(void) } static int assert_called_notifications( - const git_diff_list *diff_so_far, + const git_diff *diff_so_far, const git_diff_delta *delta_to_add, const char *matched_pathspec, void *payload) @@ -45,7 +45,7 @@ static void test_notify( int expected_diffed_files_count) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; g_repo = cl_git_sandbox_init("status"); @@ -63,7 +63,7 @@ static void test_notify( cl_assert_equal_i(expected_diffed_files_count, exp.files); - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_notify__notify_single_pathspec(void) @@ -155,7 +155,7 @@ void test_diff_notify__notify_catchall(void) } static int abort_diff( - const git_diff_list *diff_so_far, + const git_diff *diff_so_far, const git_diff_delta *delta_to_add, const char *matched_pathspec, void *payload) @@ -171,7 +171,7 @@ static int abort_diff( void test_diff_notify__notify_cb_can_abort_diff(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; char *pathspec = NULL; g_repo = cl_git_sandbox_init("status"); @@ -189,7 +189,7 @@ void test_diff_notify__notify_cb_can_abort_diff(void) } static int filter_all( - const git_diff_list *diff_so_far, + const git_diff *diff_so_far, const git_diff_delta *delta_to_add, const char *matched_pathspec, void *payload) @@ -205,7 +205,7 @@ static int filter_all( void test_diff_notify__notify_cb_can_be_used_as_filtering_function(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; char *pathspec = NULL; diff_expects exp; @@ -224,5 +224,5 @@ void test_diff_notify__notify_cb_can_be_used_as_filtering_function(void) cl_assert_equal_i(0, exp.files); - git_diff_list_free(diff); + git_diff_free(diff); } diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c index 171abc819..e5d8fca9a 100644 --- a/tests-clar/diff/patch.c +++ b/tests-clar/diff/patch.c @@ -26,7 +26,7 @@ void test_diff_patch__cleanup(void) static int check_removal_cb( const git_diff_delta *delta, - const git_diff_range *range, + const git_diff_hunk *range, char line_origin, const char *formatted_output, size_t output_len, @@ -86,7 +86,7 @@ void test_diff_patch__can_properly_display_the_removal_of_a_file(void) const char *one_sha = "26a125e"; const char *another_sha = "735b6a2"; git_tree *one, *another; - git_diff_list *diff; + git_diff *diff; g_repo = cl_git_sandbox_init("status"); @@ -97,7 +97,7 @@ void test_diff_patch__can_properly_display_the_removal_of_a_file(void) cl_git_pass(git_diff_print_patch(diff, check_removal_cb, NULL)); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(another); git_tree_free(one); @@ -108,8 +108,8 @@ void test_diff_patch__to_string(void) const char *one_sha = "26a125e"; const char *another_sha = "735b6a2"; git_tree *one, *another; - git_diff_list *diff; - git_diff_patch *patch; + git_diff *diff; + git_patch *patch; char *text; const char *expected = "diff --git a/subdir.txt b/subdir.txt\ndeleted file mode 100644\nindex e8ee89e..0000000\n--- a/subdir.txt\n+++ /dev/null\n@@ -1,2 +0,0 @@\n-Is it a bird?\n-Is it a plane?\n"; @@ -122,20 +122,20 @@ void test_diff_patch__to_string(void) cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected, text); - cl_assert_equal_sz(31, git_diff_patch_size(patch, 0, 0, 0)); - cl_assert_equal_sz(31, git_diff_patch_size(patch, 1, 0, 0)); - cl_assert_equal_sz(31 + 16, git_diff_patch_size(patch, 1, 1, 0)); - cl_assert_equal_sz(strlen(expected), git_diff_patch_size(patch, 1, 1, 1)); + cl_assert_equal_sz(31, git_patch_size(patch, 0, 0, 0)); + cl_assert_equal_sz(31, git_patch_size(patch, 1, 0, 0)); + cl_assert_equal_sz(31 + 16, git_patch_size(patch, 1, 1, 0)); + cl_assert_equal_sz(strlen(expected), git_patch_size(patch, 1, 1, 1)); git__free(text); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); git_tree_free(another); git_tree_free(one); } @@ -145,8 +145,8 @@ void test_diff_patch__config_options(void) const char *one_sha = "26a125e"; /* current HEAD */ git_tree *one; git_config *cfg; - git_diff_list *diff; - git_diff_patch *patch; + git_diff *diff; + git_patch *patch; char *text; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; char *onefile = "staged_changes_modified_file"; @@ -167,24 +167,24 @@ void test_diff_patch__config_options(void) cl_git_pass(git_diff_tree_to_index(&diff, g_repo, one, NULL, &opts)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected1, text); git__free(text); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected2, text); git__free(text); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); cl_git_pass(git_config_set_string(cfg, "diff.noprefix", "true")); @@ -192,13 +192,13 @@ void test_diff_patch__config_options(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected3, text); git__free(text); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); cl_git_pass(git_config_set_int32(cfg, "core.abbrev", 12)); @@ -206,13 +206,13 @@ void test_diff_patch__config_options(void) cl_git_pass(git_diff_tree_to_index(&diff, g_repo, one, NULL, &opts)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 0)); - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected4, text); git__free(text); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); git_tree_free(one); git_config_free(cfg); @@ -223,10 +223,10 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) git_config *cfg; git_tree *head; git_diff_options opt = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff; - git_diff_patch *patch; + git_diff *diff; + git_patch *patch; const git_diff_delta *delta; - const git_diff_range *range; + const git_diff_hunk *range; const char *hdr, *text; size_t hdrlen, hunklen, textlen; char origin; @@ -253,15 +253,15 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, &delta, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, &delta, diff, 0)); cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); - cl_assert_equal_i(2, (int)git_diff_patch_num_hunks(patch)); + cl_assert_equal_i(2, (int)git_patch_num_hunks(patch)); /* check hunk 0 */ cl_git_pass( - git_diff_patch_get_hunk(&range, &hdr, &hdrlen, &hunklen, patch, 0)); + git_patch_get_hunk(&range, &hdr, &hdrlen, &hunklen, patch, 0)); cl_assert_equal_i(18, (int)hunklen); @@ -270,9 +270,9 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(6, (int)range->new_start); cl_assert_equal_i(9, (int)range->new_lines); - cl_assert_equal_i(18, (int)git_diff_patch_num_lines_in_hunk(patch, 0)); + cl_assert_equal_i(18, (int)git_patch_num_lines_in_hunk(patch, 0)); - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &text, &textlen, &oldno, &newno, patch, 0, 0)); cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)origin); cl_git_pass(git_buf_set(&actual, text, textlen)); @@ -280,7 +280,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(6, oldno); cl_assert_equal_i(6, newno); - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &text, &textlen, &oldno, &newno, patch, 0, 3)); cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)origin); cl_git_pass(git_buf_set(&actual, text, textlen)); @@ -288,7 +288,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(9, oldno); cl_assert_equal_i(-1, newno); - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &text, &textlen, &oldno, &newno, patch, 0, 12)); cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)origin); cl_git_pass(git_buf_set(&actual, text, textlen)); @@ -299,7 +299,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) /* check hunk 1 */ cl_git_pass( - git_diff_patch_get_hunk(&range, &hdr, &hdrlen, &hunklen, patch, 1)); + git_patch_get_hunk(&range, &hdr, &hdrlen, &hunklen, patch, 1)); cl_assert_equal_i(18, (int)hunklen); @@ -308,9 +308,9 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(25, (int)range->new_start); cl_assert_equal_i(9, (int)range->new_lines); - cl_assert_equal_i(18, (int)git_diff_patch_num_lines_in_hunk(patch, 1)); + cl_assert_equal_i(18, (int)git_patch_num_lines_in_hunk(patch, 1)); - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &text, &textlen, &oldno, &newno, patch, 1, 0)); cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)origin); cl_git_pass(git_buf_set(&actual, text, textlen)); @@ -318,7 +318,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(31, oldno); cl_assert_equal_i(25, newno); - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &text, &textlen, &oldno, &newno, patch, 1, 3)); cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)origin); cl_git_pass(git_buf_set(&actual, text, textlen)); @@ -326,7 +326,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(34, oldno); cl_assert_equal_i(-1, newno); - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &text, &textlen, &oldno, &newno, patch, 1, 12)); cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)origin); cl_git_pass(git_buf_set(&actual, text, textlen)); @@ -334,8 +334,8 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(-1, oldno); cl_assert_equal_i(28, newno); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); /* Let's check line numbers when there is no newline */ @@ -346,15 +346,15 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, &delta, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, &delta, diff, 0)); cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); - cl_assert_equal_i(1, (int)git_diff_patch_num_hunks(patch)); + cl_assert_equal_i(1, (int)git_patch_num_hunks(patch)); /* check hunk 0 */ cl_git_pass( - git_diff_patch_get_hunk(&range, &hdr, &hdrlen, &hunklen, patch, 0)); + git_patch_get_hunk(&range, &hdr, &hdrlen, &hunklen, patch, 0)); cl_assert_equal_i(6, (int)hunklen); @@ -363,9 +363,9 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(46, (int)range->new_start); cl_assert_equal_i(4, (int)range->new_lines); - cl_assert_equal_i(6, (int)git_diff_patch_num_lines_in_hunk(patch, 0)); + cl_assert_equal_i(6, (int)git_patch_num_lines_in_hunk(patch, 0)); - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &text, &textlen, &oldno, &newno, patch, 0, 1)); cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)origin); cl_git_pass(git_buf_set(&actual, text, textlen)); @@ -373,7 +373,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(47, oldno); cl_assert_equal_i(47, newno); - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &text, &textlen, &oldno, &newno, patch, 0, 2)); cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)origin); cl_git_pass(git_buf_set(&actual, text, textlen)); @@ -381,7 +381,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(48, oldno); cl_assert_equal_i(48, newno); - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &text, &textlen, &oldno, &newno, patch, 0, 3)); cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)origin); cl_git_pass(git_buf_set(&actual, text, textlen)); @@ -389,7 +389,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(49, oldno); cl_assert_equal_i(-1, newno); - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &text, &textlen, &oldno, &newno, patch, 0, 4)); cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)origin); cl_git_pass(git_buf_set(&actual, text, textlen)); @@ -397,7 +397,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(-1, oldno); cl_assert_equal_i(49, newno); - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &text, &textlen, &oldno, &newno, patch, 0, 5)); cl_assert_equal_i(GIT_DIFF_LINE_DEL_EOFNL, (int)origin); cl_git_pass(git_buf_set(&actual, text, textlen)); @@ -405,8 +405,8 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(-1, oldno); cl_assert_equal_i(49, newno); - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); git_buf_free(&actual); git_buf_free(&old_content); @@ -418,8 +418,8 @@ static void check_single_patch_stats( size_t adds, size_t dels, size_t ctxt, size_t *sizes, const char *expected) { - git_diff_list *diff; - git_diff_patch *patch; + git_diff *diff; + git_patch *patch; const git_diff_delta *delta; size_t actual_ctxt, actual_adds, actual_dels; @@ -427,12 +427,12 @@ static void check_single_patch_stats( cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, &delta, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, &delta, diff, 0)); cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); - cl_assert_equal_i((int)hunks, (int)git_diff_patch_num_hunks(patch)); + cl_assert_equal_i((int)hunks, (int)git_patch_num_hunks(patch)); - cl_git_pass( git_diff_patch_line_stats( + cl_git_pass( git_patch_line_stats( &actual_ctxt, &actual_adds, &actual_dels, patch) ); cl_assert_equal_sz(ctxt, actual_ctxt); @@ -441,21 +441,21 @@ static void check_single_patch_stats( if (expected != NULL) { char *text; - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected, text); git__free(text); cl_assert_equal_sz( - strlen(expected), git_diff_patch_size(patch, 1, 1, 1)); + strlen(expected), git_patch_size(patch, 1, 1, 1)); } if (sizes) { if (sizes[0]) - cl_assert_equal_sz(sizes[0], git_diff_patch_size(patch, 0, 0, 0)); + cl_assert_equal_sz(sizes[0], git_patch_size(patch, 0, 0, 0)); if (sizes[1]) - cl_assert_equal_sz(sizes[1], git_diff_patch_size(patch, 1, 0, 0)); + cl_assert_equal_sz(sizes[1], git_patch_size(patch, 1, 0, 0)); if (sizes[2]) - cl_assert_equal_sz(sizes[2], git_diff_patch_size(patch, 1, 1, 0)); + cl_assert_equal_sz(sizes[2], git_patch_size(patch, 1, 1, 0)); } /* walk lines in hunk with basic sanity checks */ @@ -464,12 +464,12 @@ static void check_single_patch_stats( int lastoldno = -1, oldno, lastnewno = -1, newno; char origin; - max_i = git_diff_patch_num_lines_in_hunk(patch, hunks - 1); + max_i = git_patch_num_lines_in_hunk(patch, hunks - 1); for (i = 0; i < max_i; ++i) { int expected = 1; - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, NULL, NULL, &oldno, &newno, patch, hunks - 1, i)); if (origin == GIT_DIFF_LINE_ADD_EOFNL || @@ -490,8 +490,8 @@ static void check_single_patch_stats( } } - git_diff_patch_free(patch); - git_diff_list_free(diff); + git_patch_free(patch); + git_diff_free(diff); } void test_diff_patch__line_counts_with_eofnl(void) diff --git a/tests-clar/diff/pathspec.c b/tests-clar/diff/pathspec.c index 7b15ea04c..5761d2d2b 100644 --- a/tests-clar/diff/pathspec.c +++ b/tests-clar/diff/pathspec.c @@ -20,7 +20,7 @@ void test_diff_pathspec__0(void) git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit); git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; git_strarray paths = { NULL, 1 }; char *path; git_pathspec *ps; @@ -52,7 +52,7 @@ void test_diff_pathspec__0(void) (int)git_pathspec_match_list_diff_entry(matches,0)->status); git_pathspec_match_list_free(matches); - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); @@ -68,7 +68,7 @@ void test_diff_pathspec__0(void) (int)git_pathspec_match_list_diff_entry(matches,0)->status); git_pathspec_match_list_free(matches); - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); @@ -84,7 +84,7 @@ void test_diff_pathspec__0(void) (int)git_pathspec_match_list_diff_entry(matches,0)->status); git_pathspec_match_list_free(matches); - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; git_tree_free(a); diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index 9864c5896..45706fb47 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -43,7 +43,7 @@ void test_diff_rename__match_oid(void) const char *old_sha = "31e47d8c1fa36d7f8d537b96158e3f024de0a9f2"; const char *new_sha = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; git_tree *old_tree, *new_tree; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; diff_expects exp; @@ -88,7 +88,7 @@ void test_diff_rename__match_oid(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - git_diff_list_free(diff); + git_diff_free(diff); cl_git_pass(git_diff_tree_to_tree( &diff, g_repo, old_tree, new_tree, &diffopts)); @@ -109,7 +109,7 @@ void test_diff_rename__match_oid(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(old_tree); git_tree_free(new_tree); @@ -120,7 +120,7 @@ void test_diff_rename__checks_options_version(void) const char *old_sha = "31e47d8c1fa36d7f8d537b96158e3f024de0a9f2"; const char *new_sha = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; git_tree *old_tree, *new_tree; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; const git_error *err; @@ -142,7 +142,7 @@ void test_diff_rename__checks_options_version(void) err = giterr_last(); cl_assert_equal_i(GITERR_INVALID, err->klass); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(old_tree); git_tree_free(new_tree); } @@ -153,7 +153,7 @@ void test_diff_rename__not_exact_match(void) const char *sha1 = "1c068dee5790ef1580cfc4cd670915b48d790084"; const char *sha2 = "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13"; git_tree *old_tree, *new_tree; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; diff_expects exp; @@ -207,7 +207,7 @@ void test_diff_rename__not_exact_match(void) cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); - git_diff_list_free(diff); + git_diff_free(diff); /* git diff -M -C \ * 2bc7f351d20b53f1c72c16c4b036e491c478c49a \ @@ -228,7 +228,7 @@ void test_diff_rename__not_exact_match(void) cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]); - git_diff_list_free(diff); + git_diff_free(diff); /* git diff -M -C --find-copies-harder --break-rewrites \ * 2bc7f351d20b53f1c72c16c4b036e491c478c49a \ @@ -253,7 +253,7 @@ void test_diff_rename__not_exact_match(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]); - git_diff_list_free(diff); + git_diff_free(diff); /* == Changes ===================================================== * songofseven.txt -> untimely.txt (rename, convert to crlf) @@ -281,7 +281,7 @@ void test_diff_rename__not_exact_match(void) cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); - git_diff_list_free(diff); + git_diff_free(diff); /* git diff -M -C \ * 1c068dee5790ef1580cfc4cd670915b48d790084 \ @@ -301,7 +301,7 @@ void test_diff_rename__not_exact_match(void) cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); - git_diff_list_free(diff); + git_diff_free(diff); /* git diff -M -C --find-copies-harder --break-rewrites \ * 1c068dee5790ef1580cfc4cd670915b48d790084 \ @@ -330,7 +330,7 @@ void test_diff_rename__not_exact_match(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); - git_diff_list_free(diff); + git_diff_free(diff); /* git diff -M -C --find-copies-harder --break-rewrites \ * 1c068dee5790ef1580cfc4cd670915b48d790084 \ @@ -353,7 +353,7 @@ void test_diff_rename__not_exact_match(void) cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(old_tree); git_tree_free(new_tree); @@ -364,7 +364,7 @@ void test_diff_rename__handles_small_files(void) const char *tree_sha = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; git_index *index; git_tree *tree; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; @@ -388,7 +388,7 @@ void test_diff_rename__handles_small_files(void) GIT_DIFF_FIND_AND_BREAK_REWRITES; cl_git_pass(git_diff_find_similar(diff, &opts)); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(tree); git_index_free(index); } @@ -400,7 +400,7 @@ void test_diff_rename__working_directory_changes(void) git_oid id; git_tree *tree; git_blob *blob; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; diff_expects exp; @@ -451,7 +451,7 @@ void test_diff_rename__working_directory_changes(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); /* rewrite files in the working directory with / without CRLF changes */ @@ -477,7 +477,7 @@ void test_diff_rename__working_directory_changes(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); /* try a different whitespace option */ @@ -496,7 +496,7 @@ void test_diff_rename__working_directory_changes(void) cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); /* try a different matching option */ @@ -514,7 +514,7 @@ void test_diff_rename__working_directory_changes(void) cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); - git_diff_list_free(diff); + git_diff_free(diff); /* again with exact match blob */ @@ -545,7 +545,7 @@ void test_diff_rename__working_directory_changes(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(tree); git_buf_free(&content); @@ -557,10 +557,10 @@ void test_diff_rename__patch(void) const char *sha0 = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; const char *sha1 = "1c068dee5790ef1580cfc4cd670915b48d790084"; git_tree *old_tree, *new_tree; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - git_diff_patch *patch; + git_patch *patch; const git_diff_delta *delta; char *text; const char *expected = "diff --git a/sixserving.txt b/ikeepsix.txt\nindex ad0a8e5..36020db 100644\n--- a/sixserving.txt\n+++ b/ikeepsix.txt\n@@ -1,3 +1,6 @@\n+I Keep Six Honest Serving-Men\n+=============================\n+\n I KEEP six honest serving-men\n (They taught me all I knew);\n Their names are What and Why and When\n@@ -21,4 +24,4 @@ She sends'em abroad on her own affairs,\n One million Hows, two million Wheres,\n And seven million Whys!\n \n- -- Rudyard Kipling\n+ -- Rudyard Kipling\n"; @@ -584,25 +584,25 @@ void test_diff_rename__patch(void) cl_assert_equal_i(4, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, &delta, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, &delta, diff, 0)); cl_assert_equal_i(GIT_DELTA_COPIED, (int)delta->status); - cl_git_pass(git_diff_patch_to_str(&text, patch)); + cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected, text); git__free(text); - git_diff_patch_free(patch); + git_patch_free(patch); - cl_git_pass(git_diff_get_patch(NULL, &delta, diff, 1)); + cl_git_pass(git_patch_from_diff(NULL, &delta, diff, 1)); cl_assert_equal_i(GIT_DELTA_UNMODIFIED, (int)delta->status); - cl_git_pass(git_diff_get_patch(NULL, &delta, diff, 2)); + cl_git_pass(git_patch_from_diff(NULL, &delta, diff, 2)); cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); - cl_git_pass(git_diff_get_patch(NULL, &delta, diff, 3)); + cl_git_pass(git_patch_from_diff(NULL, &delta, diff, 3)); cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(old_tree); git_tree_free(new_tree); } @@ -612,7 +612,7 @@ void test_diff_rename__file_exchange(void) git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT; git_index *index; git_tree *tree; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; diff_expects exp; @@ -647,7 +647,7 @@ void test_diff_rename__file_exchange(void) cl_assert_equal_i(2, exp.files); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(tree); git_index_free(index); @@ -660,7 +660,7 @@ void test_diff_rename__file_exchange_three(void) git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT, c3 = GIT_BUF_INIT; git_index *index; git_tree *tree; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; diff_expects exp; @@ -699,7 +699,7 @@ void test_diff_rename__file_exchange_three(void) cl_assert_equal_i(3, exp.files); cl_assert_equal_i(3, exp.file_status[GIT_DELTA_RENAMED]); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(tree); git_index_free(index); @@ -713,7 +713,7 @@ void test_diff_rename__file_partial_exchange(void) git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT; git_index *index; git_tree *tree; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; diff_expects exp; @@ -752,7 +752,7 @@ void test_diff_rename__file_partial_exchange(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(tree); git_index_free(index); @@ -765,7 +765,7 @@ void test_diff_rename__rename_and_copy_from_same_source(void) git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT; git_index *index; git_tree *tree; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; diff_expects exp; @@ -809,7 +809,7 @@ void test_diff_rename__rename_and_copy_from_same_source(void) cl_assert_equal_i(2, exp.file_status[GIT_DELTA_COPIED]); cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNMODIFIED]); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(tree); git_index_free(index); @@ -822,7 +822,7 @@ void test_diff_rename__from_deleted_to_split(void) git_buf c1 = GIT_BUF_INIT; git_index *index; git_tree *tree; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; diff_expects exp; @@ -863,7 +863,7 @@ void test_diff_rename__from_deleted_to_split(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNMODIFIED]); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(tree); git_index_free(index); @@ -907,7 +907,7 @@ void test_diff_rename__rejected_match_can_match_others(void) git_index *index; git_tree *tree; git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; git_buf one = GIT_BUF_INIT, two = GIT_BUF_INIT; @@ -961,7 +961,7 @@ void test_diff_rename__rejected_match_can_match_others(void) cl_git_pass( git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(tree); git_index_free(index); git_reference_free(head); @@ -993,7 +993,7 @@ void test_diff_rename__rejected_match_can_match_others_two(void) git_index *index; git_tree *tree; git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; unsigned int status[] = { GIT_DELTA_RENAMED, GIT_DELTA_RENAMED }; @@ -1035,7 +1035,7 @@ void test_diff_rename__rejected_match_can_match_others_two(void) git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); cl_assert(expect.idx > 0); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(tree); git_index_free(index); git_reference_free(head); @@ -1048,7 +1048,7 @@ void test_diff_rename__rejected_match_can_match_others_three(void) git_index *index; git_tree *tree; git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; @@ -1091,7 +1091,7 @@ void test_diff_rename__rejected_match_can_match_others_three(void) cl_assert(expect.idx == expect.len); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(tree); git_index_free(index); git_reference_free(head); @@ -1102,7 +1102,7 @@ void test_diff_rename__can_rename_from_rewrite(void) { git_index *index; git_tree *tree; - git_diff_list *diff; + git_diff *diff; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; @@ -1140,7 +1140,7 @@ void test_diff_rename__can_rename_from_rewrite(void) cl_assert(expect.idx == expect.len); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(tree); git_index_free(index); } @@ -1149,7 +1149,7 @@ void test_diff_rename__case_changes_are_split(void) { git_index *index; git_tree *tree; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; @@ -1182,7 +1182,7 @@ void test_diff_rename__case_changes_are_split(void) cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - git_diff_list_free(diff); + git_diff_free(diff); git_index_free(index); git_tree_free(tree); } @@ -1191,7 +1191,7 @@ void test_diff_rename__unmodified_can_be_renamed(void) { git_index *index; git_tree *tree; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; @@ -1230,7 +1230,7 @@ void test_diff_rename__unmodified_can_be_renamed(void) cl_assert_equal_i(1, exp.files); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - git_diff_list_free(diff); + git_diff_free(diff); git_index_free(index); git_tree_free(tree); } @@ -1238,7 +1238,7 @@ void test_diff_rename__unmodified_can_be_renamed(void) void test_diff_rename__rewrite_on_single_file(void) { git_index *index; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; @@ -1280,6 +1280,6 @@ void test_diff_rename__rewrite_on_single_file(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); git_index_free(index); } diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index 036ff09aa..24283e2fa 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -14,15 +14,15 @@ void test_diff_submodules__cleanup(void) } static void check_diff_patches_at_line( - git_diff_list *diff, const char **expected, const char *file, int line) + git_diff *diff, const char **expected, const char *file, int line) { const git_diff_delta *delta; - git_diff_patch *patch = NULL; + git_patch *patch = NULL; size_t d, num_d = git_diff_num_deltas(diff); char *patch_text; - for (d = 0; d < num_d; ++d, git_diff_patch_free(patch)) { - cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d)); + for (d = 0; d < num_d; ++d, git_patch_free(patch)) { + cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); if (delta->status == GIT_DELTA_UNMODIFIED) { cl_assert_at_line(expected[d] == NULL, file, line); @@ -32,11 +32,11 @@ static void check_diff_patches_at_line( if (expected[d] && !strcmp(expected[d], "")) continue; if (expected[d] && !strcmp(expected[d], "")) { - cl_git_pass(git_diff_patch_to_str(&patch_text, patch)); + cl_git_pass(git_patch_to_str(&patch_text, patch)); cl_assert_at_line(!strcmp(expected[d], ""), file, line); } - cl_git_pass(git_diff_patch_to_str(&patch_text, patch)); + cl_git_pass(git_patch_to_str(&patch_text, patch)); clar__assert_equal( file, line, "expected diff did not match actual diff", 1, @@ -53,7 +53,7 @@ static void check_diff_patches_at_line( void test_diff_submodules__unmodified_submodule(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; static const char *expected[] = { "", /* .gitmodules */ NULL, /* added */ @@ -74,13 +74,13 @@ void test_diff_submodules__unmodified_submodule(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected); - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_submodules__dirty_submodule(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; static const char *expected[] = { "", /* .gitmodules */ NULL, /* added */ @@ -104,13 +104,13 @@ void test_diff_submodules__dirty_submodule(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected); - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_submodules__dirty_submodule_2(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL, *diff2 = NULL; + git_diff *diff = NULL, *diff2 = NULL; char *smpath = "testrepo"; static const char *expected_none[] = { "" }; static const char *expected_dirty[] = { @@ -132,7 +132,7 @@ void test_diff_submodules__dirty_submodule_2(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_none); - git_diff_list_free(diff); + git_diff_free(diff); cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); cl_git_mkfile("submodules/testrepo/all_new.txt", "never seen before"); @@ -146,25 +146,25 @@ void test_diff_submodules__dirty_submodule_2(void) cl_git_pass(git_repository_head_tree(&head, g_repo)); cl_git_pass(git_diff_tree_to_index(&diff2, g_repo, head, NULL, &opts)); cl_git_pass(git_diff_merge(diff, diff2)); - git_diff_list_free(diff2); + git_diff_free(diff2); git_tree_free(head); check_diff_patches(diff, expected_dirty); } - git_diff_list_free(diff); + git_diff_free(diff); cl_git_pass(git_submodule_reload_all(g_repo)); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_dirty); - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_submodules__submod2_index_to_wd(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; static const char *expected[] = { "", /* .gitmodules */ "diff --git a/sm_changed_file b/sm_changed_file\nindex 4800958..4800958 160000\n--- a/sm_changed_file\n+++ b/sm_changed_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_file */ @@ -182,14 +182,14 @@ void test_diff_submodules__submod2_index_to_wd(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected); - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_submodules__submod2_head_to_index(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_tree *head; - git_diff_list *diff = NULL; + git_diff *diff = NULL; static const char *expected[] = { "", /* .gitmodules */ "diff --git a/sm_added_and_uncommited b/sm_added_and_uncommited\nnew file mode 160000\nindex 0000000..4800958\n--- /dev/null\n+++ b/sm_added_and_uncommited\n@@ -0,0 +1 @@\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n", /* sm_added_and_uncommited */ @@ -205,7 +205,7 @@ void test_diff_submodules__submod2_head_to_index(void) cl_git_pass(git_diff_tree_to_index(&diff, g_repo, head, NULL, &opts)); check_diff_patches(diff, expected); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(head); } @@ -213,7 +213,7 @@ void test_diff_submodules__submod2_head_to_index(void) void test_diff_submodules__invalid_cache(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; git_submodule *sm; char *smpath = "sm_changed_head"; git_repository *smrepo; @@ -246,7 +246,7 @@ void test_diff_submodules__invalid_cache(void) /* baseline */ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_baseline); - git_diff_list_free(diff); + git_diff_free(diff); /* update index with new HEAD */ cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath)); @@ -254,7 +254,7 @@ void test_diff_submodules__invalid_cache(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_unchanged); - git_diff_list_free(diff); + git_diff_free(diff); /* create untracked file in submodule working directory */ cl_git_mkfile("submod2/sm_changed_head/new_around_here", "hello"); @@ -262,13 +262,13 @@ void test_diff_submodules__invalid_cache(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_dirty); - git_diff_list_free(diff); + git_diff_free(diff); git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_UNTRACKED); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_unchanged); - git_diff_list_free(diff); + git_diff_free(diff); /* modify tracked file in submodule working directory */ cl_git_append2file( @@ -276,20 +276,20 @@ void test_diff_submodules__invalid_cache(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_dirty); - git_diff_list_free(diff); + git_diff_free(diff); cl_git_pass(git_submodule_reload_all(g_repo)); cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath)); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_dirty); - git_diff_list_free(diff); + git_diff_free(diff); git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_unchanged); - git_diff_list_free(diff); + git_diff_free(diff); /* add file to index in submodule */ cl_git_pass(git_submodule_open(&smrepo, sm)); @@ -300,13 +300,13 @@ void test_diff_submodules__invalid_cache(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_dirty); - git_diff_list_free(diff); + git_diff_free(diff); git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_unchanged); - git_diff_list_free(diff); + git_diff_free(diff); /* commit changed index of submodule */ cl_repo_commit_from_index(NULL, smrepo, NULL, 1372350000, "Move it"); @@ -315,25 +315,25 @@ void test_diff_submodules__invalid_cache(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_moved); - git_diff_list_free(diff); + git_diff_free(diff); git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_ALL); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_unchanged); - git_diff_list_free(diff); + git_diff_free(diff); git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_NONE); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_moved_dirty); - git_diff_list_free(diff); + git_diff_free(diff); p_unlink("submod2/sm_changed_head/new_around_here"); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_moved); - git_diff_list_free(diff); + git_diff_free(diff); git_index_free(smindex); git_repository_free(smrepo); @@ -342,7 +342,7 @@ void test_diff_submodules__invalid_cache(void) void test_diff_submodules__diff_ignore_options(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; git_config *cfg; static const char *expected_normal[] = { "", /* .gitmodules */ @@ -371,26 +371,26 @@ void test_diff_submodules__diff_ignore_options(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_normal); - git_diff_list_free(diff); + git_diff_free(diff); opts.flags |= GIT_DIFF_IGNORE_SUBMODULES; cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_ignore_all); - git_diff_list_free(diff); + git_diff_free(diff); opts.flags &= ~GIT_DIFF_IGNORE_SUBMODULES; opts.ignore_submodules = GIT_SUBMODULE_IGNORE_ALL; cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_ignore_all); - git_diff_list_free(diff); + git_diff_free(diff); opts.ignore_submodules = GIT_SUBMODULE_IGNORE_DIRTY; cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_ignore_dirty); - git_diff_list_free(diff); + git_diff_free(diff); opts.ignore_submodules = 0; cl_git_pass(git_repository_config(&cfg, g_repo)); @@ -398,25 +398,25 @@ void test_diff_submodules__diff_ignore_options(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_normal); - git_diff_list_free(diff); + git_diff_free(diff); cl_git_pass(git_config_set_bool(cfg, "diff.ignoreSubmodules", true)); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_ignore_all); - git_diff_list_free(diff); + git_diff_free(diff); cl_git_pass(git_config_set_string(cfg, "diff.ignoreSubmodules", "none")); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_normal); - git_diff_list_free(diff); + git_diff_free(diff); cl_git_pass(git_config_set_string(cfg, "diff.ignoreSubmodules", "dirty")); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_ignore_dirty); - git_diff_list_free(diff); + git_diff_free(diff); git_config_free(cfg); } diff --git a/tests-clar/diff/tree.c b/tests-clar/diff/tree.c index f05c7869e..7286ee121 100644 --- a/tests-clar/diff/tree.c +++ b/tests-clar/diff/tree.c @@ -3,7 +3,7 @@ static git_repository *g_repo = NULL; static git_diff_options opts; -static git_diff_list *diff; +static git_diff *diff; static git_tree *a, *b; static diff_expects expect; @@ -22,7 +22,7 @@ void test_diff_tree__initialize(void) void test_diff_tree__cleanup(void) { - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(a); git_tree_free(b); @@ -65,7 +65,7 @@ void test_diff_tree__0(void) cl_assert_equal_i(24 + 1 + 5 + 5, expect.line_adds); cl_assert_equal_i(7 + 1, expect.line_dels); - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; memset(&expect, 0, sizeof(expect)); @@ -168,7 +168,7 @@ void test_diff_tree__options(void) cl_assert_equal_i(actual.line_adds, expected->line_adds); cl_assert_equal_i(actual.line_dels, expected->line_dels); - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; } @@ -214,7 +214,7 @@ void test_diff_tree__merge(void) const char *b_commit = "370fe9ec22"; const char *c_commit = "f5b0af1fb4f5c"; git_tree *c; - git_diff_list *diff1 = NULL, *diff2 = NULL; + git_diff *diff1 = NULL, *diff2 = NULL; g_repo = cl_git_sandbox_init("attr"); @@ -230,7 +230,7 @@ void test_diff_tree__merge(void) cl_git_pass(git_diff_merge(diff1, diff2)); - git_diff_list_free(diff2); + git_diff_free(diff2); cl_git_pass(git_diff_foreach( diff1, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); @@ -247,7 +247,7 @@ void test_diff_tree__merge(void) cl_assert_equal_i(36, expect.line_adds); cl_assert_equal_i(22, expect.line_dels); - git_diff_list_free(diff1); + git_diff_free(diff1); } void test_diff_tree__larger_hunks(void) @@ -256,8 +256,8 @@ void test_diff_tree__larger_hunks(void) const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10"; size_t d, num_d, h, num_h, l, num_l, header_len, line_len; const git_diff_delta *delta; - git_diff_patch *patch; - const git_diff_range *range; + git_patch *patch; + const git_diff_hunk *range; const char *header, *line; char origin; @@ -273,31 +273,31 @@ void test_diff_tree__larger_hunks(void) num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { - cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d)); + cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); cl_assert(patch && delta); - num_h = git_diff_patch_num_hunks(patch); + num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { - cl_git_pass(git_diff_patch_get_hunk( + cl_git_pass(git_patch_get_hunk( &range, &header, &header_len, &num_l, patch, h)); for (l = 0; l < num_l; ++l) { - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &line, &line_len, NULL, NULL, patch, h, l)); cl_assert(line); } - cl_git_fail(git_diff_patch_get_line_in_hunk( + cl_git_fail(git_patch_get_line_in_hunk( &origin, &line, &line_len, NULL, NULL, patch, h, num_l)); } - cl_git_fail(git_diff_patch_get_hunk( + cl_git_fail(git_patch_get_hunk( &range, &header, &header_len, &num_l, patch, num_h)); - git_diff_patch_free(patch); + git_patch_free(patch); } - cl_git_fail(git_diff_get_patch(&patch, &delta, diff, num_d)); + cl_git_fail(git_patch_from_diff(&patch, &delta, diff, num_d)); cl_assert_equal_i(2, (int)num_d); } @@ -487,7 +487,7 @@ void test_diff_tree__diff_configs(void) cl_assert_equal_i(7, expect.line_adds); cl_assert_equal_i(15, expect.line_dels); - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; set_config_int(g_repo, "diff.context", 1); @@ -507,7 +507,7 @@ void test_diff_tree__diff_configs(void) cl_assert_equal_i(7, expect.line_adds); cl_assert_equal_i(15, expect.line_dels); - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; set_config_int(g_repo, "diff.context", 0); diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index aeef7b963..4af667196 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -16,7 +16,7 @@ void test_diff_workdir__cleanup(void) void test_diff_workdir__to_index(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; int use_iterator; @@ -60,7 +60,7 @@ void test_diff_workdir__to_index(void) cl_assert_equal_i(5, exp.line_dels); } - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_workdir__to_tree(void) @@ -70,8 +70,8 @@ void test_diff_workdir__to_tree(void) const char *b_commit = "0017bd4ab1ec3"; /* the start */ git_tree *a, *b; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; - git_diff_list *diff2 = NULL; + git_diff *diff = NULL; + git_diff *diff2 = NULL; diff_expects exp; int use_iterator; @@ -119,7 +119,7 @@ void test_diff_workdir__to_tree(void) * do more apples-to-apples test comparison below. */ - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; memset(&exp, 0, sizeof(exp)); @@ -130,7 +130,7 @@ void test_diff_workdir__to_tree(void) cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); cl_git_pass(git_diff_merge(diff, diff2)); - git_diff_list_free(diff2); + git_diff_free(diff2); for (use_iterator = 0; use_iterator <= 1; use_iterator++) { memset(&exp, 0, sizeof(exp)); @@ -157,7 +157,7 @@ void test_diff_workdir__to_tree(void) cl_assert_equal_i(5, exp.line_dels); } - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; memset(&exp, 0, sizeof(exp)); @@ -167,7 +167,7 @@ void test_diff_workdir__to_tree(void) cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts)); cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); cl_git_pass(git_diff_merge(diff, diff2)); - git_diff_list_free(diff2); + git_diff_free(diff2); for (use_iterator = 0; use_iterator <= 1; use_iterator++) { memset(&exp, 0, sizeof(exp)); @@ -194,7 +194,7 @@ void test_diff_workdir__to_tree(void) cl_assert_equal_i(4, exp.line_dels); } - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(a); git_tree_free(b); @@ -203,7 +203,7 @@ void test_diff_workdir__to_tree(void) void test_diff_workdir__to_index_with_pathspec(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; char *pathspec = NULL; int use_iterator; @@ -235,7 +235,7 @@ void test_diff_workdir__to_index_with_pathspec(void) cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]); } - git_diff_list_free(diff); + git_diff_free(diff); pathspec = "modified_file"; @@ -258,7 +258,7 @@ void test_diff_workdir__to_index_with_pathspec(void) cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]); } - git_diff_list_free(diff); + git_diff_free(diff); pathspec = "subdir"; @@ -281,7 +281,7 @@ void test_diff_workdir__to_index_with_pathspec(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); } - git_diff_list_free(diff); + git_diff_free(diff); pathspec = "*_deleted"; @@ -304,12 +304,12 @@ void test_diff_workdir__to_index_with_pathspec(void) cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]); } - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_workdir__filemode_changes(void) { - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; int use_iterator; @@ -339,7 +339,7 @@ void test_diff_workdir__filemode_changes(void) cl_assert_equal_i(0, exp.hunks); } - git_diff_list_free(diff); + git_diff_free(diff); /* chmod file and test again */ @@ -362,14 +362,14 @@ void test_diff_workdir__filemode_changes(void) cl_assert_equal_i(0, exp.hunks); } - git_diff_list_free(diff); + git_diff_free(diff); cl_assert(cl_toggle_filemode("issue_592/a.txt")); } void test_diff_workdir__filemode_changes_with_filemode_false(void) { - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; if (!cl_is_chmod_supported()) @@ -391,7 +391,7 @@ void test_diff_workdir__filemode_changes_with_filemode_false(void) cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(0, exp.hunks); - git_diff_list_free(diff); + git_diff_free(diff); /* chmod file and test again */ @@ -407,7 +407,7 @@ void test_diff_workdir__filemode_changes_with_filemode_false(void) cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(0, exp.hunks); - git_diff_list_free(diff); + git_diff_free(diff); cl_assert(cl_toggle_filemode("issue_592/a.txt")); } @@ -415,7 +415,7 @@ void test_diff_workdir__filemode_changes_with_filemode_false(void) void test_diff_workdir__head_index_and_workdir_all_differ(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff_i2t = NULL, *diff_w2i = NULL; + git_diff *diff_i2t = NULL, *diff_w2i = NULL; diff_expects exp; char *pathspec = "staged_changes_modified_file"; git_tree *tree; @@ -504,8 +504,8 @@ void test_diff_workdir__head_index_and_workdir_all_differ(void) cl_assert_equal_i(0, exp.line_dels); } - git_diff_list_free(diff_i2t); - git_diff_list_free(diff_w2i); + git_diff_free(diff_i2t); + git_diff_free(diff_w2i); git_tree_free(tree); } @@ -513,7 +513,7 @@ void test_diff_workdir__head_index_and_workdir_all_differ(void) void test_diff_workdir__eof_newline_changes(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; char *pathspec = "current_file"; int use_iterator; @@ -546,7 +546,7 @@ void test_diff_workdir__eof_newline_changes(void) cl_assert_equal_i(0, exp.line_dels); } - git_diff_list_free(diff); + git_diff_free(diff); cl_git_append2file("status/current_file", "\n"); @@ -573,7 +573,7 @@ void test_diff_workdir__eof_newline_changes(void) cl_assert_equal_i(0, exp.line_dels); } - git_diff_list_free(diff); + git_diff_free(diff); cl_git_rewritefile("status/current_file", "current_file"); @@ -600,7 +600,7 @@ void test_diff_workdir__eof_newline_changes(void) cl_assert_equal_i(2, exp.line_dels); } - git_diff_list_free(diff); + git_diff_free(diff); } /* PREPARATION OF TEST DATA @@ -684,9 +684,9 @@ void test_diff_workdir__larger_hunks(void) opts.interhunk_lines = 0; for (i = 0; i <= 2; ++i) { - git_diff_list *diff = NULL; - git_diff_patch *patch; - const git_diff_range *range; + git_diff *diff = NULL; + git_patch *patch; + const git_diff_hunk *range; const char *header, *line; char origin; @@ -707,33 +707,33 @@ void test_diff_workdir__larger_hunks(void) cl_assert_equal_i(2, (int)num_d); for (d = 0; d < num_d; ++d) { - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, d)); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, d)); cl_assert(patch); - num_h = git_diff_patch_num_hunks(patch); + num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { - cl_git_pass(git_diff_patch_get_hunk( + cl_git_pass(git_patch_get_hunk( &range, &header, &header_len, &num_l, patch, h)); for (l = 0; l < num_l; ++l) { - cl_git_pass(git_diff_patch_get_line_in_hunk( + cl_git_pass(git_patch_get_line_in_hunk( &origin, &line, &line_len, NULL, NULL, patch, h, l)); cl_assert(line); } /* confirm fail after the last item */ - cl_git_fail(git_diff_patch_get_line_in_hunk( + cl_git_fail(git_patch_get_line_in_hunk( &origin, &line, &line_len, NULL, NULL, patch, h, num_l)); } /* confirm fail after the last item */ - cl_git_fail(git_diff_patch_get_hunk( + cl_git_fail(git_patch_get_hunk( &range, &header, &header_len, &num_l, patch, num_h)); - git_diff_patch_free(patch); + git_patch_free(patch); } - git_diff_list_free(diff); + git_diff_free(diff); } git_tree_free(a); @@ -758,7 +758,7 @@ void test_diff_workdir__submodules(void) const char *a_commit = "873585b94bdeabccea991ea5e3ec1a277895b698"; git_tree *a; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; g_repo = setup_fixture_submod2(); @@ -819,14 +819,14 @@ void test_diff_workdir__submodules(void) cl_assert_equal_i(30, exp.line_adds); cl_assert_equal_i(1, exp.line_dels); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(a); } void test_diff_workdir__cannot_diff_against_a_bare_repository(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; git_tree *tree; g_repo = cl_git_sandbox_init("testrepo.git"); @@ -844,7 +844,7 @@ void test_diff_workdir__cannot_diff_against_a_bare_repository(void) void test_diff_workdir__to_null_tree(void) { - git_diff_list *diff; + git_diff *diff; diff_expects exp; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; @@ -862,12 +862,12 @@ void test_diff_workdir__to_null_tree(void) cl_assert_equal_i(exp.files, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_workdir__checks_options_version(void) { - git_diff_list *diff; + git_diff *diff; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; const git_error *err; @@ -887,11 +887,11 @@ void test_diff_workdir__checks_options_version(void) void test_diff_workdir__can_diff_empty_file(void) { - git_diff_list *diff; + git_diff *diff; git_tree *tree; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; struct stat st; - git_diff_patch *patch; + git_patch *patch; g_repo = cl_git_sandbox_init("attr_index"); @@ -901,7 +901,7 @@ void test_diff_workdir__can_diff_empty_file(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); cl_assert_equal_i(2, (int)git_diff_num_deltas(diff)); - git_diff_list_free(diff); + git_diff_free(diff); /* empty contents of file */ @@ -912,9 +912,9 @@ void test_diff_workdir__can_diff_empty_file(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); cl_assert_equal_i(3, (int)git_diff_num_deltas(diff)); /* diffs are: .gitattributes, README.txt, sub/sub/.gitattributes */ - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 1)); - git_diff_patch_free(patch); - git_diff_list_free(diff); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 1)); + git_patch_free(patch); + git_diff_free(diff); /* remove a file altogether */ @@ -923,9 +923,9 @@ void test_diff_workdir__can_diff_empty_file(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); cl_assert_equal_i(3, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(&patch, NULL, diff, 1)); - git_diff_patch_free(patch); - git_diff_list_free(diff); + cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 1)); + git_patch_free(patch); + git_diff_free(diff); git_tree_free(tree); } @@ -933,7 +933,7 @@ void test_diff_workdir__can_diff_empty_file(void) void test_diff_workdir__to_index_issue_1397(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; g_repo = cl_git_sandbox_init("issue_1397"); @@ -953,7 +953,7 @@ void test_diff_workdir__to_index_issue_1397(void) cl_assert_equal_i(0, exp.hunks); cl_assert_equal_i(0, exp.lines); - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; cl_git_rewritefile("issue_1397/crlf_file.txt", @@ -975,7 +975,7 @@ void test_diff_workdir__to_index_issue_1397(void) cl_assert_equal_i(1, exp.line_adds); cl_assert_equal_i(1, exp.line_dels); - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_workdir__to_tree_issue_1397(void) @@ -983,8 +983,8 @@ void test_diff_workdir__to_tree_issue_1397(void) const char *a_commit = "7f483a738"; /* the current HEAD */ git_tree *a; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; - git_diff_list *diff2 = NULL; + git_diff *diff = NULL; + git_diff *diff2 = NULL; diff_expects exp; g_repo = cl_git_sandbox_init("issue_1397"); @@ -1006,13 +1006,13 @@ void test_diff_workdir__to_tree_issue_1397(void) cl_assert_equal_i(0, exp.hunks); cl_assert_equal_i(0, exp.lines); - git_diff_list_free(diff); + git_diff_free(diff); diff = NULL; cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); cl_git_pass(git_diff_merge(diff, diff2)); - git_diff_list_free(diff2); + git_diff_free(diff2); memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( @@ -1022,14 +1022,14 @@ void test_diff_workdir__to_tree_issue_1397(void) cl_assert_equal_i(0, exp.hunks); cl_assert_equal_i(0, exp.lines); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(a); } void test_diff_workdir__untracked_directory_scenarios(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; char *pathspec = NULL; static const char *files0[] = { @@ -1079,7 +1079,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); /* empty directory */ @@ -1099,7 +1099,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); /* empty directory in empty directory */ @@ -1119,7 +1119,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); /* directory with only ignored files */ @@ -1143,7 +1143,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); /* directory with ignored directory (contents irrelevant) */ @@ -1166,7 +1166,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); /* quick version avoids directory scan */ @@ -1186,7 +1186,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); /* directory with nested non-ignored content */ @@ -1209,7 +1209,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); /* use RECURSE_UNTRACKED_DIRS to get actual untracked files (no ignores) */ @@ -1230,14 +1230,14 @@ void test_diff_workdir__untracked_directory_scenarios(void) cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_workdir__untracked_directory_comes_last(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; g_repo = cl_git_sandbox_init("renames"); @@ -1255,13 +1255,13 @@ void test_diff_workdir__untracked_directory_comes_last(void) cl_assert(diff != NULL); - git_diff_list_free(diff); + git_diff_free(diff); } void test_diff_workdir__untracked_with_bom(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_list *diff = NULL; + git_diff *diff = NULL; const git_diff_delta *delta; g_repo = cl_git_sandbox_init("empty_standard_repo"); @@ -1276,9 +1276,9 @@ void test_diff_workdir__untracked_with_bom(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); cl_assert_equal_i(1, git_diff_num_deltas(diff)); - cl_git_pass(git_diff_get_patch(NULL, &delta, diff, 0)); + cl_git_pass(git_patch_from_diff(NULL, &delta, diff, 0)); cl_assert_equal_i(GIT_DELTA_UNTRACKED, delta->status); cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); - git_diff_list_free(diff); + git_diff_free(diff); } diff --git a/tests-clar/stress/diff.c b/tests-clar/stress/diff.c index 1d319738e..3d2092614 100644 --- a/tests-clar/stress/diff.c +++ b/tests-clar/stress/diff.c @@ -19,7 +19,7 @@ static void test_with_many(int expected_new) { git_index *index; git_tree *tree, *new_tree; - git_diff_list *diff = NULL; + git_diff *diff = NULL; diff_expects exp; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; @@ -52,7 +52,7 @@ static void test_with_many(int expected_new) cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(expected_new + 1, exp.files); - git_diff_list_free(diff); + git_diff_free(diff); cl_repo_commit_from_index(NULL, g_repo, NULL, 1372350000, "yoyoyo"); cl_git_pass(git_revparse_single( @@ -78,7 +78,7 @@ static void test_with_many(int expected_new) cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(expected_new + 1, exp.files); - git_diff_list_free(diff); + git_diff_free(diff); git_tree_free(new_tree); git_tree_free(tree); -- cgit v1.2.1 From 10672e3e455eba2d4ca983070ed427caeeb24a6f Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 15 Oct 2013 15:10:07 -0700 Subject: Diff API cleanup This lays groundwork for separating formatting options from diff creation options. This groups the formatting flags separately from the diff list creation flags and reorders the options. This also tweaks some APIs to further separate code that uses patches from code that just looks at git_diffs. --- examples/diff.c | 29 +-- examples/log.c | 2 +- include/git2/diff.h | 408 +++++++++++++++++++++++------------------ include/git2/patch.h | 17 +- src/diff.c | 70 +++++-- src/diff_file.c | 2 +- src/diff_patch.c | 19 +- src/diff_print.c | 126 ++++++++----- src/diff_tform.c | 12 +- src/diff_xdiff.c | 4 +- src/reset.c | 7 +- src/stash.c | 133 ++++++-------- tests-clar/diff/blob.c | 32 ++-- tests-clar/diff/diff_helpers.c | 10 +- tests-clar/diff/diffiter.c | 34 ++-- tests-clar/diff/drivers.c | 12 +- tests-clar/diff/patch.c | 22 ++- tests-clar/diff/rename.c | 9 +- tests-clar/diff/submodules.c | 5 +- tests-clar/diff/tree.c | 28 +-- tests-clar/diff/workdir.c | 21 ++- 21 files changed, 532 insertions(+), 470 deletions(-) diff --git a/examples/diff.c b/examples/diff.c index 3200b53c8..2542f4269 100644 --- a/examples/diff.c +++ b/examples/diff.c @@ -114,12 +114,6 @@ static void usage(const char *message, const char *arg) exit(1); } -enum { - FORMAT_PATCH = 0, - FORMAT_COMPACT = 1, - FORMAT_RAW = 2 -}; - int main(int argc, char *argv[]) { git_repository *repo = NULL; @@ -127,7 +121,8 @@ int main(int argc, char *argv[]) git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; git_diff *diff; - int i, color = -1, format = FORMAT_PATCH, cached = 0; + int i, color = -1, cached = 0; + git_diff_format_t format = GIT_DIFF_FORMAT_PATCH; char *a, *treeish1 = NULL, *treeish2 = NULL; const char *dir = "."; @@ -148,13 +143,15 @@ int main(int argc, char *argv[]) } else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) - format = FORMAT_PATCH; + format = GIT_DIFF_FORMAT_PATCH; else if (!strcmp(a, "--cached")) cached = 1; + else if (!strcmp(a, "--name-only")) + format = GIT_DIFF_FORMAT_NAME_ONLY; else if (!strcmp(a, "--name-status")) - format = FORMAT_COMPACT; + format = GIT_DIFF_FORMAT_NAME_STATUS; else if (!strcmp(a, "--raw")) - format = FORMAT_RAW; + format = GIT_DIFF_FORMAT_RAW; else if (!strcmp(a, "--color")) color = 0; else if (!strcmp(a, "--no-color")) @@ -238,17 +235,7 @@ int main(int argc, char *argv[]) if (color >= 0) fputs(colors[0], stdout); - switch (format) { - case FORMAT_PATCH: - check(git_diff_print_patch(diff, printer, &color), "Displaying diff"); - break; - case FORMAT_COMPACT: - check(git_diff_print_compact(diff, printer, &color), "Displaying diff"); - break; - case FORMAT_RAW: - check(git_diff_print_raw(diff, printer, &color), "Displaying diff"); - break; - } + check(git_diff_print(diff, format, printer, &color), "Displaying diff"); if (color >= 0) fputs(colors[0], stdout); diff --git a/examples/log.c b/examples/log.c index 2ba5aa52a..30de16ae9 100644 --- a/examples/log.c +++ b/examples/log.c @@ -388,7 +388,7 @@ int main(int argc, char *argv[]) check(git_diff_tree_to_tree( &diff, git_commit_owner(commit), a, b, &diffopts), "Diff commit with parent", NULL); - check(git_diff_print_patch(diff, print_diff, NULL), + check(git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, print_diff, NULL), "Displaying diff", NULL); git_diff_free(diff); diff --git a/include/git2/diff.h b/include/git2/diff.h index 11c3bce20..fd79ccf04 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -23,7 +23,7 @@ * Calculating diffs is generally done in two phases: building a list of * diffs then traversing it. This makes is easier to share logic across * the various types of diffs (tree vs tree, workdir vs index, etc.), and - * also allows you to insert optional diff list post-processing phases, + * also allows you to insert optional diff post-processing phases, * such as rename detection, in between the steps. When you are done with * a diff object, it must be freed. * @@ -72,89 +72,111 @@ GIT_BEGIN_DECL typedef enum { /** Normal diff, the default */ GIT_DIFF_NORMAL = 0, - /** Reverse the sides of the diff */ - GIT_DIFF_REVERSE = (1 << 0), - /** Treat all files as text, disabling binary attributes & detection */ - GIT_DIFF_FORCE_TEXT = (1 << 1), - /** Ignore all whitespace */ - GIT_DIFF_IGNORE_WHITESPACE = (1 << 2), - /** Ignore changes in amount of whitespace */ - GIT_DIFF_IGNORE_WHITESPACE_CHANGE = (1 << 3), - /** Ignore whitespace at end of line */ - GIT_DIFF_IGNORE_WHITESPACE_EOL = (1 << 4), - /** Treat all submodules as unmodified */ - GIT_DIFF_IGNORE_SUBMODULES = (1 << 5), - /** Use the "patience diff" algorithm (currently unimplemented) */ - GIT_DIFF_PATIENCE = (1 << 6), - /** Include ignored files in the diff list */ - GIT_DIFF_INCLUDE_IGNORED = (1 << 7), - /** Include untracked files in the diff list */ - GIT_DIFF_INCLUDE_UNTRACKED = (1 << 8), - /** Include unmodified files in the diff list */ - GIT_DIFF_INCLUDE_UNMODIFIED = (1 << 9), - /** Even with GIT_DIFF_INCLUDE_UNTRACKED, an entire untracked - * directory will be marked with only a single entry in the diff list - * (a la what core Git does in `git status`); this flag adds *all* - * files under untracked directories as UNTRACKED entries, too. + /* + * Options controlling which files will be in the diff */ - GIT_DIFF_RECURSE_UNTRACKED_DIRS = (1 << 10), - /** If the pathspec is set in the diff options, this flags means to - * apply it as an exact match instead of as an fnmatch pattern. - */ - GIT_DIFF_DISABLE_PATHSPEC_MATCH = (1 << 11), + /** Reverse the sides of the diff */ + GIT_DIFF_REVERSE = (1u << 0), - /** Use case insensitive filename comparisons */ - GIT_DIFF_DELTAS_ARE_ICASE = (1 << 12), + /** Include ignored files in the diff */ + GIT_DIFF_INCLUDE_IGNORED = (1u << 1), - /** When generating patch text, include the content of untracked - * files. This automatically turns on GIT_DIFF_INCLUDE_UNTRACKED but - * it does not turn on GIT_DIFF_RECURSE_UNTRACKED_DIRS. Add that - * flag if you want the content of every single UNTRACKED file. + /** Even with GIT_DIFF_INCLUDE_IGNORED, an entire ignored directory + * will be marked with only a single entry in the diff; this flag + * adds all files under the directory as IGNORED entries, too. */ - GIT_DIFF_INCLUDE_UNTRACKED_CONTENT = (1 << 13), + GIT_DIFF_RECURSE_IGNORED_DIRS = (1u << 2), - /** Disable updating of the `binary` flag in delta records. This is - * useful when iterating over a diff if you don't need hunk and data - * callbacks and want to avoid having to load file completely. + /** Include untracked files in the diff */ + GIT_DIFF_INCLUDE_UNTRACKED = (1u << 3), + + /** Even with GIT_DIFF_INCLUDE_UNTRACKED, an entire untracked + * directory will be marked with only a single entry in the diff + * (a la what core Git does in `git status`); this flag adds *all* + * files under untracked directories as UNTRACKED entries, too. */ - GIT_DIFF_SKIP_BINARY_CHECK = (1 << 14), + GIT_DIFF_RECURSE_UNTRACKED_DIRS = (1u << 4), + + /** Include unmodified files in the diff */ + GIT_DIFF_INCLUDE_UNMODIFIED = (1u << 5), /** Normally, a type change between files will be converted into a * DELETED record for the old and an ADDED record for the new; this * options enabled the generation of TYPECHANGE delta records. */ - GIT_DIFF_INCLUDE_TYPECHANGE = (1 << 15), + GIT_DIFF_INCLUDE_TYPECHANGE = (1u << 6), /** Even with GIT_DIFF_INCLUDE_TYPECHANGE, blob->tree changes still * generally show as a DELETED blob. This flag tries to correctly * label blob->tree transitions as TYPECHANGE records with new_file's * mode set to tree. Note: the tree SHA will not be available. */ - GIT_DIFF_INCLUDE_TYPECHANGE_TREES = (1 << 16), + GIT_DIFF_INCLUDE_TYPECHANGE_TREES = (1u << 7), /** Ignore file mode changes */ - GIT_DIFF_IGNORE_FILEMODE = (1 << 17), + GIT_DIFF_IGNORE_FILEMODE = (1u << 8), - /** Even with GIT_DIFF_INCLUDE_IGNORED, an entire ignored directory - * will be marked with only a single entry in the diff list; this flag - * adds all files under the directory as IGNORED entries, too. + /** Treat all submodules as unmodified */ + GIT_DIFF_IGNORE_SUBMODULES = (1u << 9), + + /** Use case insensitive filename comparisons */ + GIT_DIFF_IGNORE_CASE = (1u << 10), + + /** If the pathspec is set in the diff options, this flags means to + * apply it as an exact match instead of as an fnmatch pattern. + */ + GIT_DIFF_DISABLE_PATHSPEC_MATCH = (1u << 12), + + /** Disable updating of the `binary` flag in delta records. This is + * useful when iterating over a diff if you don't need hunk and data + * callbacks and want to avoid having to load file completely. + */ + GIT_DIFF_SKIP_BINARY_CHECK = (1u << 13), + + /** When diff finds an untracked directory, to match the behavior of + * core Git, it scans the contents for IGNORED and UNTRACKED files. + * If *all* contents are IGNORED, then the directory is IGNORED; if + * any contents are not IGNORED, then the directory is UNTRACKED. + * This is extra work that may not matter in many cases. This flag + * turns off that scan and immediately labels an untracked directory + * as UNTRACKED (changing the behavior to not match core Git). */ - GIT_DIFF_RECURSE_IGNORED_DIRS = (1 << 18), - - /** Core Git scans inside untracked directories, labeling them IGNORED - * if they are empty or only contain ignored files; a directory is - * consider UNTRACKED only if it has an actual untracked file in it. - * This scan is extra work for a case you often don't care about. This - * flag makes libgit2 immediately label an untracked directory as - * UNTRACKED without looking inside it (which differs from core Git). - * Of course, ignore rules are still checked for the directory itself. + GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS = (1u << 14), + + /* + * Options controlling how output will be generated */ - GIT_DIFF_FAST_UNTRACKED_DIRS = (1 << 19), + /** Treat all files as text, disabling binary attributes & detection */ + GIT_DIFF_FORCE_TEXT = (1u << 20), /** Treat all files as binary, disabling text diffs */ - GIT_DIFF_FORCE_BINARY = (1 << 20), + GIT_DIFF_FORCE_BINARY = (1u << 21), + + /** Ignore all whitespace */ + GIT_DIFF_IGNORE_WHITESPACE = (1u << 22), + /** Ignore changes in amount of whitespace */ + GIT_DIFF_IGNORE_WHITESPACE_CHANGE = (1u << 23), + /** Ignore whitespace at end of line */ + GIT_DIFF_IGNORE_WHITESPACE_EOL = (1u << 24), + + /** When generating patch text, include the content of untracked + * files. This automatically turns on GIT_DIFF_INCLUDE_UNTRACKED but + * it does not turn on GIT_DIFF_RECURSE_UNTRACKED_DIRS. Add that + * flag if you want the content of every single UNTRACKED file. + */ + GIT_DIFF_SHOW_UNTRACKED_CONTENT = (1u << 25), + + /** When generating output, include the names of unmodified files if + * they are included in the git_diff. Normally these are skipped in + * the formats that list files (e.g. name-only, name-status, raw). + * Even with this, these will not be included in patch format. + */ + GIT_DIFF_SHOW_UNMODIFIED = (1u << 26), + + /** Use the "patience diff" algorithm (currently unimplemented) */ + GIT_DIFF_PATIENCE = (1u << 28), } git_diff_option_t; /** @@ -176,16 +198,16 @@ typedef struct git_diff git_diff; * considered reserved for internal or future use. */ typedef enum { - GIT_DIFF_FLAG_BINARY = (1 << 0), /** file(s) treated as binary data */ - GIT_DIFF_FLAG_NOT_BINARY = (1 << 1), /** file(s) treated as text data */ - GIT_DIFF_FLAG_VALID_OID = (1 << 2), /** `oid` value is known correct */ + GIT_DIFF_FLAG_BINARY = (1u << 0), /** file(s) treated as binary data */ + GIT_DIFF_FLAG_NOT_BINARY = (1u << 1), /** file(s) treated as text data */ + GIT_DIFF_FLAG_VALID_OID = (1u << 2), /** `oid` value is known correct */ } git_diff_flag_t; /** * What type of change is described by a git_diff_delta? * * `GIT_DELTA_RENAMED` and `GIT_DELTA_COPIED` will only show up if you run - * `git_diff_find_similar()` on the diff list object. + * `git_diff_find_similar()` on the diff object. * * `GIT_DELTA_TYPECHANGE` only shows up given `GIT_DIFF_INCLUDE_TYPECHANGE` * in the option flags (otherwise type changes will be split into ADDED / @@ -284,9 +306,9 @@ typedef struct { * * When the callback: * - returns < 0, the diff process will be aborted. - * - returns > 0, the delta will not be inserted into the diff list, but the + * - returns > 0, the delta will not be inserted into the diff, but the * diff process continues. - * - returns 0, the delta is inserted into the diff list, and the diff process + * - returns 0, the delta is inserted into the diff, and the diff process * continues. */ typedef int (*git_diff_notify_cb)( @@ -323,25 +345,33 @@ typedef int (*git_diff_notify_cb)( typedef struct { unsigned int version; /**< version for the struct */ uint32_t flags; /**< defaults to GIT_DIFF_NORMAL */ - uint16_t context_lines; /**< defaults to 3 */ - uint16_t interhunk_lines; /**< defaults to 0 */ - const char *old_prefix; /**< defaults to "a" */ - const char *new_prefix; /**< defaults to "b" */ + + /* options controlling which files are in the diff */ + + git_submodule_ignore_t ignore_submodules; /** << submodule ignore rule */ git_strarray pathspec; /**< defaults to include all paths */ - git_off_t max_size; /**< defaults to 512MB */ git_diff_notify_cb notify_cb; void *notify_payload; - git_submodule_ignore_t ignore_submodules; /** << submodule ignore rule */ + + /* options controlling how to diff text is generated */ + + uint16_t context_lines; /**< defaults to 3 */ + uint16_t interhunk_lines; /**< defaults to 0 */ + uint16_t oid_abbrev; /**< default 'core.abbrev' or 7 if unset */ + git_off_t max_size; /**< defaults to 512MB */ + const char *old_prefix; /**< defaults to "a" */ + const char *new_prefix; /**< defaults to "b" */ } git_diff_options; #define GIT_DIFF_OPTIONS_VERSION 1 -#define GIT_DIFF_OPTIONS_INIT {GIT_DIFF_OPTIONS_VERSION, GIT_DIFF_NORMAL, 3} +#define GIT_DIFF_OPTIONS_INIT \ + {GIT_DIFF_OPTIONS_VERSION, 0, 0, {NULL,0}, NULL, NULL, 3} /** * When iterating over a diff, callback that will be made per file. * * @param delta A pointer to the delta data for the file - * @param progress Goes from 0 to 1 over the diff list + * @param progress Goes from 0 to 1 over the diff * @param payload User-specified pointer from foreach function */ typedef int (*git_diff_file_cb)( @@ -390,8 +420,7 @@ typedef enum { GIT_DIFF_LINE_DEL_EOFNL = '<', /**< Old has LF at end, new does not */ /* The following values will only be sent to a `git_diff_line_cb` when - * the content of a diff is being formatted (eg. through - * git_diff_print_patch() or git_diff_print_compact(), for instance). + * the content of a diff is being formatted through `git_diff_print`. */ GIT_DIFF_LINE_FILE_HDR = 'F', GIT_DIFF_LINE_HUNK_HDR = 'H', @@ -419,25 +448,25 @@ typedef int (*git_diff_line_cb)( */ typedef enum { /** look for renames? (`--find-renames`) */ - GIT_DIFF_FIND_RENAMES = (1 << 0), + GIT_DIFF_FIND_RENAMES = (1u << 0), /** consider old side of modified for renames? (`--break-rewrites=N`) */ - GIT_DIFF_FIND_RENAMES_FROM_REWRITES = (1 << 1), + GIT_DIFF_FIND_RENAMES_FROM_REWRITES = (1u << 1), /** look for copies? (a la `--find-copies`) */ - GIT_DIFF_FIND_COPIES = (1 << 2), + GIT_DIFF_FIND_COPIES = (1u << 2), /** consider unmodified as copy sources? (`--find-copies-harder`) */ - GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED = (1 << 3), + GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED = (1u << 3), /** mark large rewrites for split (`--break-rewrites=/M`) */ - GIT_DIFF_FIND_REWRITES = (1 << 4), + GIT_DIFF_FIND_REWRITES = (1u << 4), /** actually split large rewrites into delete/add pairs */ - GIT_DIFF_BREAK_REWRITES = (1 << 5), + GIT_DIFF_BREAK_REWRITES = (1u << 5), /** mark rewrites for split and break into delete/add pairs */ GIT_DIFF_FIND_AND_BREAK_REWRITES = (GIT_DIFF_FIND_REWRITES | GIT_DIFF_BREAK_REWRITES), /** find renames/copies for untracked items in working directory */ - GIT_DIFF_FIND_FOR_UNTRACKED = (1 << 6), + GIT_DIFF_FIND_FOR_UNTRACKED = (1u << 6), /** turn on all finding features */ GIT_DIFF_FIND_ALL = (0x0ff), @@ -445,14 +474,14 @@ typedef enum { /** measure similarity ignoring leading whitespace (default) */ GIT_DIFF_FIND_IGNORE_LEADING_WHITESPACE = 0, /** measure similarity ignoring all whitespace */ - GIT_DIFF_FIND_IGNORE_WHITESPACE = (1 << 12), + GIT_DIFF_FIND_IGNORE_WHITESPACE = (1u << 12), /** measure similarity including all data */ - GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE = (1 << 13), + GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE = (1u << 13), /** measure similarity only by comparing SHAs (fast and cheap) */ - GIT_DIFF_FIND_EXACT_MATCH_ONLY = (1 << 14), + GIT_DIFF_FIND_EXACT_MATCH_ONLY = (1u << 14), /** do not break rewrites unless they contribute to a rename */ - GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY = (1 << 15), + GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY = (1u << 15), } git_diff_find_t; /** @@ -517,7 +546,7 @@ typedef struct { #define GIT_DIFF_FIND_OPTIONS_VERSION 1 #define GIT_DIFF_FIND_OPTIONS_INIT {GIT_DIFF_FIND_OPTIONS_VERSION} -/** @name Diff List Generator Functions +/** @name Diff Generator Functions * * These are the functions you would use to create (or destroy) a * git_diff from various objects in a repository. @@ -525,14 +554,14 @@ typedef struct { /**@{*/ /** - * Deallocate a diff list. + * Deallocate a diff. * - * @param diff The previously created diff list; cannot be used after free. + * @param diff The previously created diff; cannot be used after free. */ GIT_EXTERN(void) git_diff_free(git_diff *diff); /** - * Create a diff list with the difference between two tree objects. + * Create a diff with the difference between two tree objects. * * This is equivalent to `git diff ` * @@ -555,7 +584,7 @@ GIT_EXTERN(int) git_diff_tree_to_tree( const git_diff_options *opts); /**< can be NULL for defaults */ /** - * Create a diff list between a tree and repository index. + * Create a diff between a tree and repository index. * * This is equivalent to `git diff --cached ` or if you pass * the HEAD tree, then like `git diff --cached`. @@ -577,7 +606,7 @@ GIT_EXTERN(int) git_diff_tree_to_index( const git_diff_options *opts); /**< can be NULL for defaults */ /** - * Create a diff list between the repository index and the workdir directory. + * Create a diff between the repository index and the workdir directory. * * This matches the `git diff` command. See the note below on * `git_diff_tree_to_workdir` for a discussion of the difference between @@ -599,7 +628,7 @@ GIT_EXTERN(int) git_diff_index_to_workdir( const git_diff_options *opts); /**< can be NULL for defaults */ /** - * Create a diff list between a tree and the working directory. + * Create a diff between a tree and the working directory. * * The tree you provide will be used for the "old_file" side of the delta, * and the working directory will be used for the "new_file" side. @@ -613,9 +642,10 @@ GIT_EXTERN(int) git_diff_index_to_workdir( * files in the index. It may come as a surprise, but there is no direct * equivalent in core git. * - * To emulate `git diff `, call both `git_diff_tree_to_index` and - * `git_diff_index_to_workdir`, then call `git_diff_merge` on the results. - * That will yield a `git_diff` that matches the git output. + * To emulate `git diff `, use `git_diff_tree_to_workdir_with_index` + * (or `git_diff_tree_to_index` and `git_diff_index_to_workdir`, then call + * `git_diff_merge` on the results). That will yield a `git_diff` that + * matches the git output. * * If this seems confusing, take the case of a file with a staged deletion * where the file has then been put back into the working dir and modified. @@ -634,10 +664,29 @@ GIT_EXTERN(int) git_diff_tree_to_workdir( const git_diff_options *opts); /**< can be NULL for defaults */ /** - * Merge one diff list into another. + * Create a diff between a tree and the working directory using index data + * to account for staged deletes, tracked files, etc. + * + * This emulates `git diff ` by diffing the tree to the index and + * the index to the working directory and blending the results into a + * single diff that includes staged deleted, etc. + * + * @param diff A pointer to a git_diff pointer that will be allocated. + * @param repo The repository containing the tree. + * @param old_tree A git_tree object to diff from, or NULL for empty tree. + * @param opts Structure with options to influence diff or NULL for defaults. + */ +GIT_EXTERN(int) git_diff_tree_to_workdir_with_index( + git_diff **diff, + git_repository *repo, + git_tree *old_tree, + const git_diff_options *opts); /**< can be NULL for defaults */ + +/** + * Merge one diff into another. * * This merges items from the "from" list into the "onto" list. The - * resulting diff list will have all items that appear in either list. + * resulting diff will have all items that appear in either list. * If an item appears in both lists, then it will be "merged" to appear * as if the old version was from the "onto" list and the new version * is from the "from" list (with the exception that if the item has a @@ -651,40 +700,90 @@ GIT_EXTERN(int) git_diff_merge( const git_diff *from); /** - * Transform a diff list marking file renames, copies, etc. + * Transform a diff marking file renames, copies, etc. * - * This modifies a diff list in place, replacing old entries that look + * This modifies a diff in place, replacing old entries that look * like renames or copies with new entries reflecting those changes. * This also will, if requested, break modified files into add/remove * pairs if the amount of change is above a threshold. * - * @param diff Diff list to run detection algorithms on + * @param diff diff to run detection algorithms on * @param options Control how detection should be run, NULL for defaults * @return 0 on success, -1 on failure */ GIT_EXTERN(int) git_diff_find_similar( git_diff *diff, - git_diff_find_options *options); + const git_diff_find_options *options); /**@}*/ -/** @name Diff List Processor Functions +/** @name Diff Processor Functions * - * These are the functions you apply to a diff list to process it + * These are the functions you apply to a diff to process it * or read it in some way. */ /**@{*/ /** - * Loop over all deltas in a diff list issuing callbacks. + * Query how many diff records are there in a diff. + * + * @param diff A git_diff generated by one of the above functions + * @return Count of number of deltas in the list + */ +GIT_EXTERN(size_t) git_diff_num_deltas(const git_diff *diff); + +/** + * Query how many diff deltas are there in a diff filtered by type. + * + * This works just like `git_diff_entrycount()` with an extra parameter + * that is a `git_delta_t` and returns just the count of how many deltas + * match that particular type. + * + * @param diff A git_diff generated by one of the above functions + * @param type A git_delta_t value to filter the count + * @return Count of number of deltas matching delta_t type + */ +GIT_EXTERN(size_t) git_diff_num_deltas_of_type( + const git_diff *diff, git_delta_t type); + +/** + * Return the diff delta for an entry in the diff list. + * + * The `git_delta` pointer points to internal data and you do not have + * to release it when you are done with it. It will go away when the + * `git_diff` (or any associated `git_patch`) goes away. + * + * Note that the flags on the delta related to whether it has binary + * content or not may not be set if there are no attributes set for the + * file and there has been no reason to load the file data at this point. + * For now, if you need those flags to be up to date, your only option is + * to either use `git_diff_foreach` or create a `git_patch`. + * + * @param diff Diff list object + * @param idx Index into diff list + * @return Pointer to git_diff_delta (or NULL if `idx` out of range) + */ +GIT_EXTERN(const git_diff_delta *) git_diff_get_delta( + const git_diff *diff, size_t idx); + +/** + * Check if deltas are sorted case sensitively or insensitively. + * + * @param diff diff to check + * @return 0 if case sensitive, 1 if case is ignored + */ +GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff *diff); + +/** + * Loop over all deltas in a diff issuing callbacks. * * This will iterate through all of the files described in a diff. You * should provide a file callback to learn about each file. * * The "hunk" and "line" callbacks are optional, and the text diff of the * files will only be calculated if they are not NULL. Of course, these - * callbacks will not be invoked for binary files on the diff list or for + * callbacks will not be invoked for binary files on the diff or for * files whose only changed is a file mode change. * * Returning a non-zero value from any of the callbacks will terminate @@ -708,46 +807,13 @@ GIT_EXTERN(int) git_diff_foreach( git_diff_line_cb line_cb, void *payload); -/** - * Iterate over a diff generating text output like "git diff --name-status". - * - * Returning a non-zero value from the callbacks will terminate the - * iteration and cause this return `GIT_EUSER`. - * - * @param diff A git_diff generated by one of the above functions. - * @param print_cb Callback to make per line of diff text. - * @param payload Reference pointer that will be passed to your callback. - * @return 0 on success, GIT_EUSER on non-zero callback, or error code - */ -GIT_EXTERN(int) git_diff_print_compact( - git_diff *diff, - git_diff_line_cb print_cb, - void *payload); - -/** - * Iterate over a diff generating text output like "git diff --raw". - * - * Returning a non-zero value from the callbacks will terminate the - * iteration and cause this return `GIT_EUSER`. - * - * @param diff A git_diff generated by one of the above functions. - * @param print_cb Callback to make per line of diff text. - * @param payload Reference pointer that will be passed to your callback. - * @return 0 on success, GIT_EUSER on non-zero callback, or error code - */ -GIT_EXTERN(int) git_diff_print_raw( - git_diff *diff, - git_diff_line_cb print_cb, - void *payload); - /** * Look up the single character abbreviation for a delta status code. * - * When you call `git_diff_print_compact` it prints single letter codes into - * the output such as 'A' for added, 'D' for deleted, 'M' for modified, etc. - * It is sometimes convenient to convert a git_delta_t value into these - * letters for your own purposes. This function does just that. By the - * way, unmodified will return a space (i.e. ' '). + * When you run `git diff --name-status` it uses single letter codes in + * the output such as 'A' for added, 'D' for deleted, 'M' for modified, + * etc. This function converts a git_delta_t value into these letters for + * your own purposes. GIT_DELTA_UNTRACKED will return a space (i.e. ' '). * * @param status The git_delta_t value to look up * @return The single character label for that code @@ -755,58 +821,34 @@ GIT_EXTERN(int) git_diff_print_raw( GIT_EXTERN(char) git_diff_status_char(git_delta_t status); /** - * Iterate over a diff generating text output like "git diff". - * - * This is a super easy way to generate a patch from a diff. + * Possible output formats for diff data + */ +typedef enum { + GIT_DIFF_FORMAT_PATCH = 1u, /**< full git diff */ + GIT_DIFF_FORMAT_PATCH_HEADER = 2u, /**< just the file headers of patch */ + GIT_DIFF_FORMAT_RAW = 3u, /**< like git diff --raw */ + GIT_DIFF_FORMAT_NAME_ONLY = 4u, /**< like git diff --name-only */ + GIT_DIFF_FORMAT_NAME_STATUS = 5u, /**< like git diff --name-status */ +} git_diff_format_t; + +/** + * Iterate over a diff generating formatted text output. * * Returning a non-zero value from the callbacks will terminate the * iteration and cause this return `GIT_EUSER`. * * @param diff A git_diff generated by one of the above functions. - * @param payload Reference pointer that will be passed to your callbacks. - * @param print_cb Callback function to output lines of the diff. This - * same function will be called for file headers, hunk - * headers, and diff lines. Fortunately, you can probably - * use various GIT_DIFF_LINE constants to determine what - * text you are given. + * @param format A git_diff_forrmat_t value to pick the text format. + * @param print_cb Callback to make per line of diff text. + * @param payload Reference pointer that will be passed to your callback. * @return 0 on success, GIT_EUSER on non-zero callback, or error code */ -GIT_EXTERN(int) git_diff_print_patch( +GIT_EXTERN(int) git_diff_print( git_diff *diff, + git_diff_format_t format, git_diff_line_cb print_cb, void *payload); -/** - * Query how many diff records are there in a diff list. - * - * @param diff A git_diff generated by one of the above functions - * @return Count of number of deltas in the list - */ -GIT_EXTERN(size_t) git_diff_num_deltas(git_diff *diff); - -/** - * Query how many diff deltas are there in a diff list filtered by type. - * - * This works just like `git_diff_entrycount()` with an extra parameter - * that is a `git_delta_t` and returns just the count of how many deltas - * match that particular type. - * - * @param diff A git_diff generated by one of the above functions - * @param type A git_delta_t value to filter the count - * @return Count of number of deltas matching delta_t type - */ -GIT_EXTERN(size_t) git_diff_num_deltas_of_type( - git_diff *diff, - git_delta_t type); - -/** - * Check if deltas are sorted case sensitively or insensitively. - * - * @param diff Diff list to check - * @return 0 if case sensitive, 1 if case is ignored - */ -GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff *diff); - /**@}*/ diff --git a/include/git2/patch.h b/include/git2/patch.h index ad9be7516..9836245de 100644 --- a/include/git2/patch.h +++ b/include/git2/patch.h @@ -47,17 +47,13 @@ typedef struct git_patch git_patch; * It is okay to pass NULL for either of the output parameters; if you pass * NULL for the `git_patch`, then the text diff will not be calculated. * - * @param patch_out Output parameter for the delta patch object - * @param delta_out Output parameter for the delta object + * @param out Output parameter for the delta patch object * @param diff Diff list object * @param idx Index into diff list * @return 0 on success, other value < 0 on error */ GIT_EXTERN(int) git_patch_from_diff( - git_patch **patch_out, - const git_diff_delta **delta_out, - git_diff *diff, - size_t idx); + git_patch **out, git_diff *diff, size_t idx); /** * Directly generate a patch from the difference between two blobs. @@ -112,20 +108,17 @@ GIT_EXTERN(int) git_patch_from_blob_and_buffer( /** * Free a git_patch object. */ -GIT_EXTERN(void) git_patch_free( - git_patch *patch); +GIT_EXTERN(void) git_patch_free(git_patch *patch); /** * Get the delta associated with a patch */ -GIT_EXTERN(const git_diff_delta *) git_patch_delta( - git_patch *patch); +GIT_EXTERN(const git_diff_delta *) git_patch_get_delta(git_patch *patch); /** * Get the number of hunks in a patch */ -GIT_EXTERN(size_t) git_patch_num_hunks( - git_patch *patch); +GIT_EXTERN(size_t) git_patch_num_hunks(git_patch *patch); /** * Get line counts of each type in a patch. diff --git a/src/diff.c b/src/diff.c index 1efde98e4..8dc704d58 100644 --- a/src/diff.c +++ b/src/diff.c @@ -81,7 +81,7 @@ static int diff_delta__from_one( if (!git_pathspec__match( &diff->pathspec, entry->path, DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH), - DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE), + DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE), &matched_pathspec, NULL)) return 0; @@ -368,14 +368,14 @@ static git_diff *diff_list_alloc( * the ignore_case bit set */ if (!git_iterator_ignore_case(old_iter) && !git_iterator_ignore_case(new_iter)) { - diff->opts.flags &= ~GIT_DIFF_DELTAS_ARE_ICASE; + diff->opts.flags &= ~GIT_DIFF_IGNORE_CASE; diff->strcomp = git__strcmp; diff->strncomp = git__strncmp; diff->pfxcomp = git__prefixcmp; diff->entrycomp = git_index_entry__cmp; } else { - diff->opts.flags |= GIT_DIFF_DELTAS_ARE_ICASE; + diff->opts.flags |= GIT_DIFF_IGNORE_CASE; diff->strcomp = git__strcasecmp; diff->strncomp = git__strncasecmp; @@ -399,9 +399,9 @@ static int diff_list_apply_options( if (opts) { /* copy user options (except case sensitivity info from iterators) */ - bool icase = DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE); + bool icase = DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE); memcpy(&diff->opts, opts, sizeof(diff->opts)); - DIFF_FLAG_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE, icase); + DIFF_FLAG_SET(diff, GIT_DIFF_IGNORE_CASE, icase); /* initialize pathspec from options */ if (git_pathspec__vinit(&diff->pathspec, &opts->pathspec, pool) < 0) @@ -413,7 +413,7 @@ static int diff_list_apply_options( diff->opts.flags |= GIT_DIFF_INCLUDE_TYPECHANGE; /* flag INCLUDE_UNTRACKED_CONTENT implies INCLUDE_UNTRACKED */ - if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_UNTRACKED_CONTENT)) + if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_SHOW_UNTRACKED_CONTENT)) diff->opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED; /* load config values that affect diff behavior */ @@ -674,7 +674,7 @@ static int maybe_modified( if (!git_pathspec__match( &diff->pathspec, oitem->path, DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH), - DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE), + DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE), &matched_pathspec, NULL)) return 0; @@ -910,7 +910,7 @@ static int handle_unmatched_new_item( */ if (!recurse_into_dir && delta_type == GIT_DELTA_UNTRACKED && - DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_FAST_UNTRACKED_DIRS)) + DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS)) { git_diff_delta *last; @@ -1084,7 +1084,7 @@ int git_diff__from_iterators( git_buf_init(&info.ignore_prefix, 0); /* make iterators have matching icase behavior */ - if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_DELTAS_ARE_ICASE)) { + if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE)) { if ((error = git_iterator_set_ignore_case(old_iter, true)) < 0 || (error = git_iterator_set_ignore_case(new_iter, true)) < 0) goto cleanup; @@ -1164,7 +1164,7 @@ int git_diff_tree_to_tree( * currently case insensitive, unless the user explicitly asked * for case insensitivity */ - if (opts && (opts->flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0) + if (opts && (opts->flags & GIT_DIFF_IGNORE_CASE) != 0) iflag = GIT_ITERATOR_IGNORE_CASE; DIFF_FROM_ITERATORS( @@ -1206,7 +1206,7 @@ int git_diff_tree_to_index( if (!error) { git_diff *d = *diff; - d->opts.flags |= GIT_DIFF_DELTAS_ARE_ICASE; + d->opts.flags |= GIT_DIFF_IGNORE_CASE; d->strcomp = git__strcasecmp; d->strncomp = git__strncasecmp; d->pfxcomp = git__prefixcmp_icase; @@ -1242,7 +1242,6 @@ int git_diff_index_to_workdir( return error; } - int git_diff_tree_to_workdir( git_diff **diff, git_repository *repo, @@ -1262,16 +1261,43 @@ int git_diff_tree_to_workdir( return error; } -size_t git_diff_num_deltas(git_diff *diff) +int git_diff_tree_to_workdir_with_index( + git_diff **diff, + git_repository *repo, + git_tree *old_tree, + const git_diff_options *opts) +{ + int error = 0; + git_diff *d1 = NULL, *d2 = NULL; + + assert(diff && repo); + + if (!(error = git_diff_tree_to_index(&d1, repo, old_tree, NULL, opts)) && + !(error = git_diff_index_to_workdir(&d2, repo, NULL, opts))) + error = git_diff_merge(d1, d2); + + git_diff_free(d2); + + if (error) { + git_diff_free(d1); + d1 = NULL; + } + + *diff = d1; + return error; +} + + +size_t git_diff_num_deltas(const git_diff *diff) { assert(diff); - return (size_t)diff->deltas.length; + return diff->deltas.length; } -size_t git_diff_num_deltas_of_type(git_diff *diff, git_delta_t type) +size_t git_diff_num_deltas_of_type(const git_diff *diff, git_delta_t type) { size_t i, count = 0; - git_diff_delta *delta; + const git_diff_delta *delta; assert(diff); @@ -1282,9 +1308,15 @@ size_t git_diff_num_deltas_of_type(git_diff *diff, git_delta_t type) return count; } +const git_diff_delta *git_diff_get_delta(const git_diff *diff, size_t idx) +{ + assert(diff); + return git_vector_get(&diff->deltas, idx); +} + int git_diff_is_sorted_icase(const git_diff *diff) { - return (diff->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0; + return (diff->opts.flags & GIT_DIFF_IGNORE_CASE) != 0; } int git_diff__paired_foreach( @@ -1318,10 +1350,10 @@ int git_diff__paired_foreach( * always sort by the old name in the i2w list. */ h2i_icase = head2idx != NULL && - (head2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0; + (head2idx->opts.flags & GIT_DIFF_IGNORE_CASE) != 0; i2w_icase = idx2wd != NULL && - (idx2wd->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0; + (idx2wd->opts.flags & GIT_DIFF_IGNORE_CASE) != 0; icase_mismatch = (head2idx != NULL && idx2wd != NULL && h2i_icase != i2w_icase); diff --git a/src/diff_file.c b/src/diff_file.c index a7bca4dca..a4c8641bc 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -110,7 +110,7 @@ int git_diff_file_content__init_from_diff( has_data = use_old; break; case GIT_DELTA_UNTRACKED: has_data = !use_old && - (diff->opts.flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) != 0; + (diff->opts.flags & GIT_DIFF_SHOW_UNTRACKED_CONTENT) != 0; break; case GIT_DELTA_MODIFIED: case GIT_DELTA_COPIED: diff --git a/src/diff_patch.c b/src/diff_patch.c index a106944c7..951368200 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -17,7 +17,9 @@ typedef struct diff_patch_line diff_patch_line; struct diff_patch_line { const char *ptr; size_t len; - size_t lines, oldno, newno; + size_t lines; + size_t oldno; + size_t newno; char origin; }; @@ -109,9 +111,7 @@ static int diff_patch_init_from_diff( } static int diff_patch_alloc_from_diff( - git_patch **out, - git_diff *diff, - size_t delta_index) + git_patch **out, git_diff *diff, size_t delta_index) { int error; git_patch *patch = git__calloc(1, sizeof(git_patch)); @@ -605,10 +605,7 @@ int git_patch_from_blob_and_buffer( } int git_patch_from_diff( - git_patch **patch_ptr, - const git_diff_delta **delta_ptr, - git_diff *diff, - size_t idx) + git_patch **patch_ptr, git_diff *diff, size_t idx) { int error = 0; git_xdiff_output xo; @@ -616,7 +613,6 @@ int git_patch_from_diff( git_patch *patch = NULL; if (patch_ptr) *patch_ptr = NULL; - if (delta_ptr) *delta_ptr = NULL; if (diff_required(diff, "git_patch_from_diff") < 0) return -1; @@ -627,9 +623,6 @@ int git_patch_from_diff( return GIT_ENOTFOUND; } - if (delta_ptr) - *delta_ptr = delta; - if (git_diff_delta__should_skip(&diff->opts, delta)) return 0; @@ -671,7 +664,7 @@ void git_patch_free(git_patch *patch) GIT_REFCOUNT_DEC(patch, diff_patch_free); } -const git_diff_delta *git_patch_delta(git_patch *patch) +const git_diff_delta *git_patch_get_delta(git_patch *patch) { assert(patch); return patch->delta; diff --git a/src/diff_print.c b/src/diff_print.c index 1cf6da2e3..a6423d92b 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -11,22 +11,34 @@ typedef struct { git_diff *diff; + git_diff_format_t format; git_diff_line_cb print_cb; void *payload; git_buf *buf; + uint32_t flags; int oid_strlen; } diff_print_info; static int diff_print_info_init( diff_print_info *pi, - git_buf *out, git_diff *diff, git_diff_line_cb cb, void *payload) + git_buf *out, + git_diff *diff, + git_diff_format_t format, + git_diff_line_cb cb, + void *payload) { pi->diff = diff; + pi->format = format; pi->print_cb = cb; pi->payload = payload; pi->buf = out; - if (!diff || !diff->repo) + if (diff) + pi->flags = diff->opts.flags; + + if (diff && diff->opts.oid_abbrev != 0) + pi->oid_strlen = diff->opts.oid_abbrev; + else if (!diff || !diff->repo) pi->oid_strlen = GIT_ABBREV_DEFAULT; else if (git_repository__cvar( &pi->oid_strlen, diff->repo, GIT_CVAR_ABBREV) < 0) @@ -77,7 +89,32 @@ static int callback_error(void) return GIT_EUSER; } -static int diff_print_one_compact( +static int diff_print_one_name_only( + const git_diff_delta *delta, float progress, void *data) +{ + diff_print_info *pi = data; + git_buf *out = pi->buf; + + GIT_UNUSED(progress); + + if ((pi->flags & GIT_DIFF_SHOW_UNMODIFIED) == 0 && + delta->status == GIT_DELTA_UNMODIFIED) + return 0; + + git_buf_clear(out); + + if (git_buf_puts(out, delta->new_file.path) < 0 || + git_buf_putc(out, '\n')) + return -1; + + if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR, + git_buf_cstr(out), git_buf_len(out), pi->payload)) + return callback_error(); + + return 0; +} + +static int diff_print_one_name_status( const git_diff_delta *delta, float progress, void *data) { diff_print_info *pi = data; @@ -88,7 +125,7 @@ static int diff_print_one_compact( GIT_UNUSED(progress); - if (code == ' ') + if ((pi->flags & GIT_DIFF_SHOW_UNMODIFIED) == 0 && code == ' ') return 0; old_suffix = diff_pick_suffix(delta->old_file.mode); @@ -119,24 +156,6 @@ static int diff_print_one_compact( return 0; } -/* print a git_diff to a print callback in compact format */ -int git_diff_print_compact( - git_diff *diff, - git_diff_line_cb print_cb, - void *payload) -{ - int error; - git_buf buf = GIT_BUF_INIT; - diff_print_info pi; - - if (!(error = diff_print_info_init(&pi, &buf, diff, print_cb, payload))) - error = git_diff_foreach(diff, diff_print_one_compact, NULL, NULL, &pi); - - git_buf_free(&buf); - - return error; -} - static int diff_print_one_raw( const git_diff_delta *delta, float progress, void *data) { @@ -147,7 +166,7 @@ static int diff_print_one_raw( GIT_UNUSED(progress); - if (code == ' ') + if ((pi->flags & GIT_DIFF_SHOW_UNMODIFIED) == 0 && code == ' ') return 0; git_buf_clear(out); @@ -180,24 +199,6 @@ static int diff_print_one_raw( return 0; } -/* print a git_diff to a print callback in raw output format */ -int git_diff_print_raw( - git_diff *diff, - git_diff_line_cb print_cb, - void *payload) -{ - int error; - git_buf buf = GIT_BUF_INIT; - diff_print_info pi; - - if (!(error = diff_print_info_init(&pi, &buf, diff, print_cb, payload))) - error = git_diff_foreach(diff, diff_print_one_raw, NULL, NULL, &pi); - - git_buf_free(&buf); - - return error; -} - static int diff_print_oid_range( git_buf *out, const git_diff_delta *delta, int oid_strlen) { @@ -287,7 +288,6 @@ static int diff_print_patch_file( pi->diff ? pi->diff->opts.old_prefix : DIFF_OLD_PREFIX_DEFAULT; const char *newpfx = pi->diff ? pi->diff->opts.new_prefix : DIFF_NEW_PREFIX_DEFAULT; - uint32_t opts_flags = pi->diff ? pi->diff->opts.flags : GIT_DIFF_NORMAL; GIT_UNUSED(progress); @@ -295,7 +295,7 @@ static int diff_print_patch_file( delta->status == GIT_DELTA_UNMODIFIED || delta->status == GIT_DELTA_IGNORED || (delta->status == GIT_DELTA_UNTRACKED && - (opts_flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) == 0)) + (pi->flags & GIT_DIFF_SHOW_UNTRACKED_CONTENT) == 0)) return 0; if (git_diff_delta__format_file_header( @@ -379,20 +379,47 @@ static int diff_print_patch_line( return 0; } -/* print a git_diff to an output callback in patch format */ -int git_diff_print_patch( +/* print a git_diff to an output callback */ +int git_diff_print( git_diff *diff, + git_diff_format_t format, git_diff_line_cb print_cb, void *payload) { int error; git_buf buf = GIT_BUF_INIT; diff_print_info pi; + git_diff_file_cb print_file = NULL; + git_diff_hunk_cb print_hunk = NULL; + git_diff_line_cb print_line = NULL; + + switch (format) { + case GIT_DIFF_FORMAT_PATCH: + print_file = diff_print_patch_file; + print_hunk = diff_print_patch_hunk; + print_line = diff_print_patch_line; + break; + case GIT_DIFF_FORMAT_PATCH_HEADER: + print_file = diff_print_patch_file; + break; + case GIT_DIFF_FORMAT_RAW: + print_file = diff_print_one_raw; + break; + case GIT_DIFF_FORMAT_NAME_ONLY: + print_file = diff_print_one_name_only; + break; + case GIT_DIFF_FORMAT_NAME_STATUS: + print_file = diff_print_one_name_status; + break; + default: + giterr_set(GITERR_INVALID, "Unknown diff output format (%d)", format); + return -1; + } - if (!(error = diff_print_info_init(&pi, &buf, diff, print_cb, payload))) + if (!(error = diff_print_info_init( + &pi, &buf, diff, format, print_cb, payload))) error = git_diff_foreach( - diff, diff_print_patch_file, diff_print_patch_hunk, - diff_print_patch_line, &pi); + diff, print_file, print_hunk, print_line, &pi); git_buf_free(&buf); @@ -412,7 +439,8 @@ int git_patch_print( assert(patch && print_cb); if (!(error = diff_print_info_init( - &pi, &temp, git_patch__diff(patch), print_cb, payload))) + &pi, &temp, git_patch__diff(patch), + GIT_DIFF_FORMAT_PATCH, print_cb, payload))) error = git_patch__invoke_callbacks( patch, diff_print_patch_file, diff_print_patch_hunk, diff_print_patch_line, &pi); diff --git a/src/diff_tform.c b/src/diff_tform.c index c0a60672c..92771847c 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -117,15 +117,15 @@ int git_diff_merge( git_pool_init(&onto_pool, 1, 0) < 0) return -1; - if ((onto->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0 || - (from->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0) + if ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0 || + (from->opts.flags & GIT_DIFF_IGNORE_CASE) != 0) { ignore_case = true; /* This function currently only supports merging diff lists that * are sorted identically. */ - assert((onto->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0 && - (from->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0); + assert((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0 && + (from->opts.flags & GIT_DIFF_IGNORE_CASE) != 0); } for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) { @@ -232,7 +232,7 @@ int git_diff_find_similar__calc_similarity( static int normalize_find_opts( git_diff *diff, git_diff_find_options *opts, - git_diff_find_options *given) + const git_diff_find_options *given) { git_config *cfg = NULL; @@ -760,7 +760,7 @@ typedef struct { int git_diff_find_similar( git_diff *diff, - git_diff_find_options *given_opts) + const git_diff_find_options *given_opts) { size_t s, t; int error = 0, similarity; diff --git a/src/diff_xdiff.c b/src/diff_xdiff.c index e3aa8f3e1..972039753 100644 --- a/src/diff_xdiff.c +++ b/src/diff_xdiff.c @@ -59,7 +59,7 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) { git_xdiff_info *info = priv; git_patch *patch = info->patch; - const git_diff_delta *delta = git_patch_delta(patch); + const git_diff_delta *delta = git_patch_get_delta(patch); git_diff_output *output = &info->xo->output; if (len == 1) { @@ -145,7 +145,7 @@ static int git_xdiff(git_diff_output *output, git_patch *patch) void git_xdiff_init(git_xdiff_output *xo, const git_diff_options *opts) { - uint32_t flags = opts ? opts->flags : GIT_DIFF_NORMAL; + uint32_t flags = opts ? opts->flags : 0; xo->output.diff_cb = git_xdiff; diff --git a/src/reset.c b/src/reset.c index 3fd4b9165..194bca6f1 100644 --- a/src/reset.c +++ b/src/reset.c @@ -26,8 +26,7 @@ int git_reset_default( git_tree *tree = NULL; git_diff *diff = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - size_t i; - git_diff_delta *delta; + size_t i, max_i; git_index_entry entry; int error; git_index *index = NULL; @@ -58,7 +57,9 @@ int git_reset_default( &diff, repo, tree, index, &opts)) < 0) goto cleanup; - git_vector_foreach(&diff->deltas, i, delta) { + for (i = 0, max_i = git_diff_num_deltas(diff); i < max_i; ++i) { + const git_diff_delta *delta = git_diff_get_delta(diff, i); + if ((error = git_index_conflict_remove(index, delta->old_file.path)) < 0) goto cleanup; diff --git a/src/stash.c b/src/stash.c index 6cf26f711..6fa74ac0a 100644 --- a/src/stash.c +++ b/src/stash.c @@ -153,65 +153,61 @@ cleanup: return error; } -struct cb_data { - git_index *index; - - int error; - +struct stash_update_rules { bool include_changed; bool include_untracked; bool include_ignored; }; -static int update_index_cb( - const git_diff_delta *delta, - float progress, - void *payload) +static int stash_update_index_from_diff( + git_index *index, + const git_diff *diff, + struct stash_update_rules *data) { - struct cb_data *data = (struct cb_data *)payload; - const char *add_path = NULL; - - GIT_UNUSED(progress); - - switch (delta->status) { - case GIT_DELTA_IGNORED: - if (data->include_ignored) - add_path = delta->new_file.path; - break; - - case GIT_DELTA_UNTRACKED: - if (data->include_untracked) - add_path = delta->new_file.path; - break; - - case GIT_DELTA_ADDED: - case GIT_DELTA_MODIFIED: - if (data->include_changed) - add_path = delta->new_file.path; - break; - - case GIT_DELTA_DELETED: - if (!data->include_changed) + int error = 0; + size_t d, max_d = git_diff_num_deltas(diff); + + for (d = 0; !error && d < max_d; ++d) { + const char *add_path = NULL; + const git_diff_delta *delta = git_diff_get_delta(diff, d); + + switch (delta->status) { + case GIT_DELTA_IGNORED: + if (data->include_ignored) + add_path = delta->new_file.path; + break; + + case GIT_DELTA_UNTRACKED: + if (data->include_untracked) + add_path = delta->new_file.path; + break; + + case GIT_DELTA_ADDED: + case GIT_DELTA_MODIFIED: + if (data->include_changed) + add_path = delta->new_file.path; + break; + + case GIT_DELTA_DELETED: + if (data->include_changed && + !git_index_find(NULL, index, delta->old_file.path)) + error = git_index_remove(index, delta->old_file.path, 0); break; - if (git_index_find(NULL, data->index, delta->old_file.path) == 0) - data->error = git_index_remove( - data->index, delta->old_file.path, 0); - break; - - default: - /* Unimplemented */ - giterr_set( - GITERR_INVALID, - "Cannot update index. Unimplemented status (%d)", - delta->status); - data->error = -1; - break; - } - if (add_path != NULL) - data->error = git_index_add_bypath(data->index, add_path); + default: + /* Unimplemented */ + giterr_set( + GITERR_INVALID, + "Cannot update index. Unimplemented status (%d)", + delta->status); + return -1; + } + + if (add_path != NULL) + error = git_index_add_bypath(index, add_path); + } - return data->error; + return error; } static int build_untracked_tree( @@ -223,13 +219,11 @@ static int build_untracked_tree( git_tree *i_tree = NULL; git_diff *diff = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - struct cb_data data = {0}; + struct stash_update_rules data = {0}; int error; git_index_clear(index); - data.index = index; - if (flags & GIT_STASH_INCLUDE_UNTRACKED) { opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_RECURSE_UNTRACKED_DIRS; @@ -248,13 +242,8 @@ static int build_untracked_tree( &diff, git_index_owner(index), i_tree, &opts)) < 0) goto cleanup; - if ((error = git_diff_foreach( - diff, update_index_cb, NULL, NULL, &data)) < 0) - { - if (error == GIT_EUSER) - error = data.error; + if ((error = stash_update_index_from_diff(index, diff, &data)) < 0) goto cleanup; - } error = build_tree_from_index(tree_out, index); @@ -311,9 +300,9 @@ static int build_workdir_tree( { git_repository *repo = git_index_owner(index); git_tree *b_tree = NULL; - git_diff *diff = NULL, *diff2 = NULL; + git_diff *diff = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - struct cb_data data = {0}; + struct stash_update_rules data = {0}; int error; opts.flags = GIT_DIFF_IGNORE_SUBMODULES; @@ -321,33 +310,19 @@ static int build_workdir_tree( if ((error = git_commit_tree(&b_tree, b_commit)) < 0) goto cleanup; - if ((error = git_diff_tree_to_index(&diff, repo, b_tree, NULL, &opts)) < 0) + if ((error = git_diff_tree_to_workdir_with_index( + &diff, repo, b_tree, &opts)) < 0) goto cleanup; - if ((error = git_diff_index_to_workdir(&diff2, repo, NULL, &opts)) < 0) - goto cleanup; - - if ((error = git_diff_merge(diff, diff2)) < 0) - goto cleanup; - - data.index = index; data.include_changed = true; - if ((error = git_diff_foreach( - diff, update_index_cb, NULL, NULL, &data)) < 0) - { - if (error == GIT_EUSER) - error = data.error; + if ((error = stash_update_index_from_diff(index, diff, &data)) < 0) goto cleanup; - } - - if ((error = build_tree_from_index(tree_out, index)) < 0) - goto cleanup; + error = build_tree_from_index(tree_out, index); cleanup: git_diff_free(diff); - git_diff_free(diff2); git_tree_free(b_tree); return error; diff --git a/tests-clar/diff/blob.c b/tests-clar/diff/blob.c index bed0da0bf..898c037b5 100644 --- a/tests-clar/diff/blob.c +++ b/tests-clar/diff/blob.c @@ -165,7 +165,7 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void) cl_assert(p != NULL); - delta = git_patch_delta(p); + delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.oid)); @@ -188,7 +188,7 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void) cl_assert(p != NULL); - delta = git_patch_delta(p); + delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); cl_assert(git_oid_equal(git_blob_id(b), &delta->old_file.oid)); @@ -211,7 +211,7 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void) cl_assert(p != NULL); - delta = git_patch_delta(p); + delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.oid)); @@ -231,7 +231,7 @@ void test_diff_blob__can_compare_text_blobs_with_patch(void) cl_assert(p != NULL); - delta = git_patch_delta(p); + delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); cl_assert(git_oid_equal(git_blob_id(c), &delta->old_file.oid)); @@ -326,7 +326,7 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void) cl_assert(p != NULL); - delta = git_patch_delta(p); + delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); cl_assert(git_oid_equal(git_blob_id(d), &delta->old_file.oid)); @@ -351,7 +351,7 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void) cl_assert(p != NULL); - delta = git_patch_delta(p); + delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_ADDED, delta->status); cl_assert(git_oid_iszero(&delta->old_file.oid)); @@ -376,7 +376,7 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void) cl_assert(p != NULL); - delta = git_patch_delta(p); + delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); @@ -389,7 +389,7 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void) cl_assert(p != NULL); - delta = git_patch_delta(p); + delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_ADDED, delta->status); cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); @@ -443,7 +443,7 @@ void test_diff_blob__can_compare_identical_blobs_with_patch(void) cl_git_pass(git_patch_from_blobs(&p, d, NULL, d, NULL, &opts)); cl_assert(p != NULL); - delta = git_patch_delta(p); + delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status); cl_assert_equal_sz(delta->old_file.size, git_blob_rawsize(d)); @@ -457,7 +457,7 @@ void test_diff_blob__can_compare_identical_blobs_with_patch(void) cl_git_pass(git_patch_from_blobs(&p, NULL, NULL, NULL, NULL, &opts)); cl_assert(p != NULL); - delta = git_patch_delta(p); + delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status); cl_assert_equal_sz(0, delta->old_file.size); @@ -470,7 +470,7 @@ void test_diff_blob__can_compare_identical_blobs_with_patch(void) cl_git_pass(git_patch_from_blobs(&p, alien, NULL, alien, NULL, &opts)); cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_patch_delta(p)->status); + cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_patch_get_delta(p)->status); cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); git_patch_free(p); } @@ -709,7 +709,7 @@ void test_diff_blob__can_compare_blob_to_buffer_with_patch(void) &p, a, NULL, b_content, strlen(b_content), NULL, &opts)); cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_MODIFIED, git_patch_delta(p)->status); + cl_assert_equal_i(GIT_DELTA_MODIFIED, git_patch_get_delta(p)->status); cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); cl_assert_equal_i(6, git_patch_num_lines_in_hunk(p, 0)); @@ -725,7 +725,7 @@ void test_diff_blob__can_compare_blob_to_buffer_with_patch(void) cl_git_pass(git_patch_from_blob_and_buffer( &p, a, NULL, a_content, strlen(a_content), NULL, &opts)); cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_patch_delta(p)->status); + cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_patch_get_delta(p)->status); cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); git_patch_free(p); @@ -733,7 +733,7 @@ void test_diff_blob__can_compare_blob_to_buffer_with_patch(void) cl_git_pass(git_patch_from_blob_and_buffer( &p, NULL, NULL, a_content, strlen(a_content), NULL, &opts)); cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_ADDED, git_patch_delta(p)->status); + cl_assert_equal_i(GIT_DELTA_ADDED, git_patch_get_delta(p)->status); cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); git_patch_free(p); @@ -742,7 +742,7 @@ void test_diff_blob__can_compare_blob_to_buffer_with_patch(void) cl_git_pass(git_patch_from_blob_and_buffer( &p, a, NULL, NULL, 0, NULL, &opts)); cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_DELETED, git_patch_delta(p)->status); + cl_assert_equal_i(GIT_DELTA_DELETED, git_patch_get_delta(p)->status); cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); git_patch_free(p); @@ -753,7 +753,7 @@ void test_diff_blob__can_compare_blob_to_buffer_with_patch(void) cl_git_pass(git_patch_from_blob_and_buffer( &p, a, NULL, NULL, 0, NULL, &opts)); cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_ADDED, git_patch_delta(p)->status); + cl_assert_equal_i(GIT_DELTA_ADDED, git_patch_get_delta(p)->status); cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); git_patch_free(p); diff --git a/tests-clar/diff/diff_helpers.c b/tests-clar/diff/diff_helpers.c index 34ef1df5a..cf768865e 100644 --- a/tests-clar/diff/diff_helpers.c +++ b/tests-clar/diff/diff_helpers.c @@ -162,8 +162,8 @@ int diff_foreach_via_iterator( const git_diff_delta *delta; size_t h, num_h; - cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); - cl_assert(delta); + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + cl_assert((delta = git_patch_get_delta(patch)) != NULL); /* call file_cb for this file */ if (file_cb != NULL && file_cb(delta, (float)d / num_d, data) != 0) { @@ -245,10 +245,12 @@ static int diff_print_cb( void diff_print(FILE *fp, git_diff *diff) { - cl_git_pass(git_diff_print_patch(diff, diff_print_cb, fp ? fp : stderr)); + cl_git_pass(git_diff_print( + diff, GIT_DIFF_FORMAT_PATCH, diff_print_cb, fp ? fp : stderr)); } void diff_print_raw(FILE *fp, git_diff *diff) { - cl_git_pass(git_diff_print_raw(diff, diff_print_cb, fp ? fp : stderr)); + cl_git_pass(git_diff_print( + diff, GIT_DIFF_FORMAT_RAW, diff_print_cb, fp ? fp : stderr)); } diff --git a/tests-clar/diff/diffiter.c b/tests-clar/diff/diffiter.c index 48b56e20e..1a1e5dfc3 100644 --- a/tests-clar/diff/diffiter.c +++ b/tests-clar/diff/diffiter.c @@ -20,10 +20,12 @@ void test_diff_diffiter__create(void) num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { - const git_diff_delta *delta; - cl_git_pass(git_patch_from_diff(NULL, &delta, diff, d)); + const git_diff_delta *delta = git_diff_get_delta(diff, d); + cl_assert(delta != NULL); } + cl_assert(!git_diff_get_delta(diff, num_d)); + git_diff_free(diff); } @@ -39,8 +41,7 @@ void test_diff_diffiter__iterate_files_1(void) num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { - const git_diff_delta *delta; - cl_git_pass(git_patch_from_diff(NULL, &delta, diff, d)); + const git_diff_delta *delta = git_diff_get_delta(diff, d); cl_assert(delta != NULL); diff_file_cb(delta, (float)d / (float)num_d, &exp); @@ -63,8 +64,7 @@ void test_diff_diffiter__iterate_files_2(void) cl_assert_equal_i(8, (int)num_d); for (d = 0; d < num_d; ++d) { - const git_diff_delta *delta; - cl_git_pass(git_patch_from_diff(NULL, &delta, diff, d)); + const git_diff_delta *delta = git_diff_get_delta(diff, d); cl_assert(delta != NULL); count++; } @@ -91,12 +91,9 @@ void test_diff_diffiter__iterate_files_and_hunks(void) for (d = 0; d < num_d; ++d) { git_patch *patch; - const git_diff_delta *delta; size_t h, num_h; - cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); - - cl_assert(delta); + cl_git_pass(git_patch_from_diff(&patch, diff, d)); cl_assert(patch); file_count++; @@ -145,9 +142,10 @@ void test_diff_diffiter__max_size_threshold(void) git_patch *patch; const git_diff_delta *delta; - cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); - cl_assert(delta); + cl_git_pass(git_patch_from_diff(&patch, diff, d)); cl_assert(patch); + delta = git_patch_get_delta(patch); + cl_assert(delta); file_count++; hunk_count += (int)git_patch_num_hunks(patch); @@ -180,7 +178,8 @@ void test_diff_diffiter__max_size_threshold(void) git_patch *patch; const git_diff_delta *delta; - cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + delta = git_patch_get_delta(patch); file_count++; hunk_count += (int)git_patch_num_hunks(patch); @@ -221,11 +220,10 @@ void test_diff_diffiter__iterate_all(void) num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { git_patch *patch; - const git_diff_delta *delta; size_t h, num_h; - cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); - cl_assert(patch && delta); + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + cl_assert(patch); exp.files++; num_h = git_patch_num_hunks(patch); @@ -312,7 +310,7 @@ void test_diff_diffiter__iterate_randomly_while_saving_state(void) patches[p] = NULL; /* cache new patch */ - cl_git_pass(git_patch_from_diff(&patches[p], NULL, diff, d)); + cl_git_pass(git_patch_from_diff(&patches[p], diff, d)); cl_assert(patches[p] != NULL); /* process old patch if non-NULL */ @@ -428,7 +426,7 @@ void test_diff_diffiter__iterate_and_generate_patch_text(void) git_patch *patch; char *text; - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, d)); + cl_git_pass(git_patch_from_diff(&patch, diff, d)); cl_assert(patch != NULL); cl_git_pass(git_patch_to_str(&text, patch)); diff --git a/tests-clar/diff/drivers.c b/tests-clar/diff/drivers.c index 518f24e7b..fbd1dff81 100644 --- a/tests-clar/diff/drivers.c +++ b/tests-clar/diff/drivers.c @@ -44,7 +44,7 @@ void test_diff_drivers__patterns(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected0, text); @@ -59,7 +59,7 @@ void test_diff_drivers__patterns(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected1, text); @@ -74,7 +74,7 @@ void test_diff_drivers__patterns(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected0, text); @@ -91,7 +91,7 @@ void test_diff_drivers__patterns(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected1, text); @@ -112,7 +112,7 @@ void test_diff_drivers__patterns(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected2, text); @@ -144,7 +144,7 @@ void test_diff_drivers__long_lines(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); cl_assert_equal_sz(1, git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); cl_git_pass(git_patch_to_str(&actual, patch)); /* if chmod not supported, overwrite mode bits since anything is possible */ diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c index e5d8fca9a..9c01c3b4e 100644 --- a/tests-clar/diff/patch.c +++ b/tests-clar/diff/patch.c @@ -95,7 +95,8 @@ void test_diff_patch__can_properly_display_the_removal_of_a_file(void) cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, one, another, NULL)); - cl_git_pass(git_diff_print_patch(diff, check_removal_cb, NULL)); + cl_git_pass(git_diff_print( + diff, GIT_DIFF_FORMAT_PATCH, check_removal_cb, NULL)); git_diff_free(diff); @@ -122,7 +123,7 @@ void test_diff_patch__to_string(void) cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); cl_git_pass(git_patch_to_str(&text, patch)); @@ -167,7 +168,7 @@ void test_diff_patch__config_options(void) cl_git_pass(git_diff_tree_to_index(&diff, g_repo, one, NULL, &opts)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected1, text); @@ -178,7 +179,7 @@ void test_diff_patch__config_options(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected2, text); @@ -192,7 +193,7 @@ void test_diff_patch__config_options(void) cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected3, text); @@ -206,7 +207,7 @@ void test_diff_patch__config_options(void) cl_git_pass(git_diff_tree_to_index(&diff, g_repo, one, NULL, &opts)); cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); cl_git_pass(git_patch_to_str(&text, patch)); cl_assert_equal_s(expected4, text); @@ -253,7 +254,8 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, &delta, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_assert((delta = git_patch_get_delta(patch)) != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); cl_assert_equal_i(2, (int)git_patch_num_hunks(patch)); @@ -346,7 +348,8 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, &delta, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_assert((delta = git_patch_get_delta(patch)) != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); cl_assert_equal_i(1, (int)git_patch_num_hunks(patch)); @@ -427,7 +430,8 @@ static void check_single_patch_stats( cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, &delta, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_assert((delta = git_patch_get_delta(patch)) != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); cl_assert_equal_i((int)hunks, (int)git_patch_num_hunks(patch)); diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c index 45706fb47..42bb65aa8 100644 --- a/tests-clar/diff/rename.c +++ b/tests-clar/diff/rename.c @@ -584,7 +584,8 @@ void test_diff_rename__patch(void) cl_assert_equal_i(4, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, &delta, diff, 0)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_assert((delta = git_patch_get_delta(patch)) != NULL); cl_assert_equal_i(GIT_DELTA_COPIED, (int)delta->status); cl_git_pass(git_patch_to_str(&text, patch)); @@ -593,13 +594,13 @@ void test_diff_rename__patch(void) git_patch_free(patch); - cl_git_pass(git_patch_from_diff(NULL, &delta, diff, 1)); + cl_assert((delta = git_diff_get_delta(diff, 1)) != NULL); cl_assert_equal_i(GIT_DELTA_UNMODIFIED, (int)delta->status); - cl_git_pass(git_patch_from_diff(NULL, &delta, diff, 2)); + cl_assert((delta = git_diff_get_delta(diff, 2)) != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); - cl_git_pass(git_patch_from_diff(NULL, &delta, diff, 3)); + cl_assert((delta = git_diff_get_delta(diff, 3)) != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); git_diff_free(diff); diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c index 24283e2fa..24545b2c7 100644 --- a/tests-clar/diff/submodules.c +++ b/tests-clar/diff/submodules.c @@ -22,7 +22,8 @@ static void check_diff_patches_at_line( char *patch_text; for (d = 0; d < num_d; ++d, git_patch_free(patch)) { - cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + cl_assert((delta = git_patch_get_delta(patch)) != NULL); if (delta->status == GIT_DELTA_UNMODIFIED) { cl_assert_at_line(expected[d] == NULL, file, line); @@ -123,7 +124,7 @@ void test_diff_submodules__dirty_submodule_2(void) cl_git_pass(git_submodule_reload_all(g_repo)); opts.flags = GIT_DIFF_INCLUDE_UNTRACKED | - GIT_DIFF_INCLUDE_UNTRACKED_CONTENT | + GIT_DIFF_SHOW_UNTRACKED_CONTENT | GIT_DIFF_RECURSE_UNTRACKED_DIRS | GIT_DIFF_DISABLE_PATHSPEC_MATCH; opts.old_prefix = "a"; opts.new_prefix = "b"; diff --git a/tests-clar/diff/tree.c b/tests-clar/diff/tree.c index 7286ee121..8231d3632 100644 --- a/tests-clar/diff/tree.c +++ b/tests-clar/diff/tree.c @@ -90,6 +90,9 @@ void test_diff_tree__0(void) git_tree_free(c); } +#define DIFF_OPTS(FLAGS, CTXT) \ + {GIT_DIFF_OPTIONS_VERSION, (FLAGS), 0, {NULL,0}, NULL, NULL, (CTXT), 1} + void test_diff_tree__options(void) { /* grabbed a couple of commit oids from the history of the attr repo */ @@ -102,16 +105,16 @@ void test_diff_tree__options(void) int test_ab_or_cd[] = { 0, 0, 0, 0, 1, 1, 1, 1, 1 }; git_diff_options test_options[] = { /* a vs b tests */ - { 1, GIT_DIFF_NORMAL, 1, 1, NULL, NULL, {0} }, - { 1, GIT_DIFF_NORMAL, 3, 1, NULL, NULL, {0} }, - { 1, GIT_DIFF_REVERSE, 2, 1, NULL, NULL, {0} }, - { 1, GIT_DIFF_FORCE_TEXT, 2, 1, NULL, NULL, {0} }, + DIFF_OPTS(GIT_DIFF_NORMAL, 1), + DIFF_OPTS(GIT_DIFF_NORMAL, 3), + DIFF_OPTS(GIT_DIFF_REVERSE, 2), + DIFF_OPTS(GIT_DIFF_FORCE_TEXT, 2), /* c vs d tests */ - { 1, GIT_DIFF_NORMAL, 3, 1, NULL, NULL, {0} }, - { 1, GIT_DIFF_IGNORE_WHITESPACE, 3, 1, NULL, NULL, {0} }, - { 1, GIT_DIFF_IGNORE_WHITESPACE_CHANGE, 3, 1, NULL, NULL, {0} }, - { 1, GIT_DIFF_IGNORE_WHITESPACE_EOL, 3, 1, NULL, NULL, {0} }, - { 1, GIT_DIFF_IGNORE_WHITESPACE | GIT_DIFF_REVERSE, 1, 1, NULL, NULL, {0} }, + DIFF_OPTS(GIT_DIFF_NORMAL, 3), + DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE, 3), + DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE_CHANGE, 3), + DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE_EOL, 3), + DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE | GIT_DIFF_REVERSE, 1), }; /* to generate these values: @@ -255,7 +258,6 @@ void test_diff_tree__larger_hunks(void) const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69"; const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10"; size_t d, num_d, h, num_h, l, num_l, header_len, line_len; - const git_diff_delta *delta; git_patch *patch; const git_diff_hunk *range; const char *header, *line; @@ -273,8 +275,8 @@ void test_diff_tree__larger_hunks(void) num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { - cl_git_pass(git_patch_from_diff(&patch, &delta, diff, d)); - cl_assert(patch && delta); + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + cl_assert(patch); num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { @@ -297,7 +299,7 @@ void test_diff_tree__larger_hunks(void) git_patch_free(patch); } - cl_git_fail(git_patch_from_diff(&patch, &delta, diff, num_d)); + cl_git_fail(git_patch_from_diff(&patch, diff, num_d)); cl_assert_equal_i(2, (int)num_d); } diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index 4af667196..ee63a700d 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -707,7 +707,7 @@ void test_diff_workdir__larger_hunks(void) cl_assert_equal_i(2, (int)num_d); for (d = 0; d < num_d; ++d) { - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, d)); + cl_git_pass(git_patch_from_diff(&patch, diff, d)); cl_assert(patch); num_h = git_patch_num_hunks(patch); @@ -769,7 +769,7 @@ void test_diff_workdir__submodules(void) GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_RECURSE_UNTRACKED_DIRS | - GIT_DIFF_INCLUDE_UNTRACKED_CONTENT; + GIT_DIFF_SHOW_UNTRACKED_CONTENT; cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); @@ -912,7 +912,7 @@ void test_diff_workdir__can_diff_empty_file(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); cl_assert_equal_i(3, (int)git_diff_num_deltas(diff)); /* diffs are: .gitattributes, README.txt, sub/sub/.gitattributes */ - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 1)); + cl_git_pass(git_patch_from_diff(&patch, diff, 1)); git_patch_free(patch); git_diff_free(diff); @@ -923,7 +923,7 @@ void test_diff_workdir__can_diff_empty_file(void) cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); cl_assert_equal_i(3, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, NULL, diff, 1)); + cl_git_pass(git_patch_from_diff(&patch, diff, 1)); git_patch_free(patch); git_diff_free(diff); @@ -1170,7 +1170,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) /* quick version avoids directory scan */ - opts.flags = opts.flags | GIT_DIFF_FAST_UNTRACKED_DIRS; + opts.flags = opts.flags | GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS; memset(&exp, 0, sizeof(exp)); exp.names = files1; @@ -1190,7 +1190,7 @@ void test_diff_workdir__untracked_directory_scenarios(void) /* directory with nested non-ignored content */ - opts.flags = opts.flags & ~GIT_DIFF_FAST_UNTRACKED_DIRS; + opts.flags = opts.flags & ~GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS; cl_git_mkfile("status/subdir/directory/more/notignored", "not ignored deep under untracked\n"); @@ -1271,14 +1271,17 @@ void test_diff_workdir__untracked_with_bom(void) "\xFF\xFE\x31\x00\x32\x00\x33\x00\x34\x00", 10, O_WRONLY|O_CREAT, 0664); opts.flags = - GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_INCLUDE_UNTRACKED_CONTENT; + GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT; cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); cl_assert_equal_i(1, git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(NULL, &delta, diff, 0)); + cl_assert((delta = git_diff_get_delta(diff, 0)) != NULL); cl_assert_equal_i(GIT_DELTA_UNTRACKED, delta->status); - cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); + + /* not known at this point + * cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); + */ git_diff_free(diff); } -- cgit v1.2.1 From 3acf44d6cb5e56fea379504c07ae7ac8dd0e586d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 17 Jul 2013 09:43:32 -0500 Subject: tests for checkout index with conflicts --- tests-clar/checkout/conflict.c | 460 +++++++++++++++++++++ .../1a/010b1c0f081b2e8901d55307a15c29ff30af0e | Bin 0 -> 19 bytes .../72/ea499e108df5ff0a4a913e7655bbeeb1fb69f2 | Bin 0 -> 26 bytes .../8b/fb012a6d809e499bd8d3e194a3929bc8995b93 | Bin 0 -> 34 bytes 4 files changed, 460 insertions(+) create mode 100644 tests-clar/checkout/conflict.c create mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/1a/010b1c0f081b2e8901d55307a15c29ff30af0e create mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/72/ea499e108df5ff0a4a913e7655bbeeb1fb69f2 create mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/8b/fb012a6d809e499bd8d3e194a3929bc8995b93 diff --git a/tests-clar/checkout/conflict.c b/tests-clar/checkout/conflict.c new file mode 100644 index 000000000..836495fef --- /dev/null +++ b/tests-clar/checkout/conflict.c @@ -0,0 +1,460 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/sys/index.h" +#include "fileops.h" + +static git_repository *g_repo; +static git_index *g_index; + +#define TEST_REPO_PATH "merge-resolve" + +#define CONFLICTING_ANCESTOR_OID "d427e0b2e138501a3d15cc376077a3631e15bd46" +#define CONFLICTING_OURS_OID "4e886e602529caa9ab11d71f86634bd1b6e0de10" +#define CONFLICTING_THEIRS_OID "2bd0a343aeef7a2cf0d158478966a6e587ff3863" + +#define AUTOMERGEABLE_ANCESTOR_OID "6212c31dab5e482247d7977e4f0dd3601decf13b" +#define AUTOMERGEABLE_OURS_OID "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf" +#define AUTOMERGEABLE_THEIRS_OID "058541fc37114bfc1dddf6bd6bffc7fae5c2e6fe" + +#define LINK_ANCESTOR_OID "1a010b1c0f081b2e8901d55307a15c29ff30af0e" +#define LINK_OURS_OID "72ea499e108df5ff0a4a913e7655bbeeb1fb69f2" +#define LINK_THEIRS_OID "8bfb012a6d809e499bd8d3e194a3929bc8995b93" + +#define LINK_ANCESTOR_TARGET "file" +#define LINK_OURS_TARGET "other-file" +#define LINK_THEIRS_TARGET "still-another-file" + +#define CONFLICTING_OURS_FILE \ + "this file is changed in master and branch\n" +#define CONFLICTING_THEIRS_FILE \ + "this file is changed in branch and master\n" +#define CONFLICTING_DIFF3_FILE \ + "<<<<<<< ours\n" \ + "this file is changed in master and branch\n" \ + "=======\n" \ + "this file is changed in branch and master\n" \ + ">>>>>>> theirs\n" + +#define AUTOMERGEABLE_MERGED_FILE \ + "this file is changed in master\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is changed in branch\n" + +struct checkout_index_entry { + uint16_t mode; + char oid_str[41]; + int stage; + char path[128]; +}; + +void test_checkout_conflict__initialize(void) +{ + g_repo = cl_git_sandbox_init(TEST_REPO_PATH); + git_repository_index(&g_index, g_repo); + + cl_git_rewritefile( + TEST_REPO_PATH "/.gitattributes", + "* text eol=lf\n"); +} + +void test_checkout_conflict__cleanup(void) +{ + git_index_free(g_index); + cl_git_sandbox_cleanup(); +} + +static void create_index(struct checkout_index_entry *entries, size_t entries_len) +{ + git_buf path = GIT_BUF_INIT; + size_t i; + + for (i = 0; i < entries_len; i++) { + git_buf_joinpath(&path, TEST_REPO_PATH, entries[i].path); + p_unlink(git_buf_cstr(&path)); + + git_index_remove_bypath(g_index, entries[i].path); + } + + for (i = 0; i < entries_len; i++) { + git_index_entry entry; + + memset(&entry, 0x0, sizeof(git_index_entry)); + + entry.mode = entries[i].mode; + entry.flags = entries[i].stage << GIT_IDXENTRY_STAGESHIFT; + git_oid_fromstr(&entry.oid, entries[i].oid_str); + entry.path = entries[i].path; + + git_index_add(g_index, &entry); + } + + git_buf_free(&path); +} + +static void create_conflicting_index(void) +{ + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting.txt" }, + { 0100644, CONFLICTING_OURS_OID, 2, "conflicting.txt" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting.txt" }, + }; + + create_index(checkout_index_entries, 3); + git_index_write(g_index); +} + +static void ensure_workdir_contents(const char *path, const char *contents) +{ + git_buf fullpath = GIT_BUF_INIT, data_buf = GIT_BUF_INIT; + + cl_git_pass( + git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); + + cl_git_pass(git_futils_readbuffer(&data_buf, git_buf_cstr(&fullpath))); + cl_assert(strcmp(git_buf_cstr(&data_buf), contents) == 0); + + git_buf_free(&fullpath); + git_buf_free(&data_buf); +} + +static void ensure_workdir_oid(const char *path, const char *oid_str) +{ + git_oid expected, actual; + + cl_git_pass(git_oid_fromstr(&expected, oid_str)); + cl_git_pass(git_repository_hashfile(&actual, g_repo, path, GIT_OBJ_BLOB, NULL)); + cl_assert(git_oid_cmp(&expected, &actual) == 0); +} + +static void ensure_workdir_mode(const char *path, int mode) +{ +#ifndef GIT_WIN32 + git_buf fullpath = GIT_BUF_INIT; + struct stat st; + + cl_git_pass( + git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); + + cl_git_pass(p_stat(git_buf_cstr(&fullpath), &st)); + cl_assert_equal_i(mode, st.st_mode); + + git_buf_free(&fullpath); +#endif +} + +static void ensure_workdir_link(const char *path, const char *target) +{ +#ifdef GIT_WIN32 + ensure_workdir_contents(path, target); +#else + git_buf fullpath = GIT_BUF_INIT; + char actual[1024]; + struct stat st; + int len; + + cl_git_pass( + git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); + + cl_git_pass(p_lstat(git_buf_cstr(&fullpath), &st)); + cl_assert(S_ISLNK(st.st_mode)); + + cl_assert((len = p_readlink(git_buf_cstr(&fullpath), actual, 1024)) > 0); + actual[len] = '\0'; + cl_assert(strcmp(actual, target) == 0); + + git_buf_free(&fullpath); +#endif +} + +void test_checkout_conflict__ignored(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy |= GIT_CHECKOUT_SKIP_UNMERGED; + + create_conflicting_index(); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + cl_assert(!git_path_exists(TEST_REPO_PATH "/conflicting.txt")); +} + +void test_checkout_conflict__ours(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy |= GIT_CHECKOUT_USE_OURS; + + create_conflicting_index(); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_contents("conflicting.txt", CONFLICTING_OURS_FILE); +} + +void test_checkout_conflict__theirs(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy |= GIT_CHECKOUT_USE_THEIRS; + + create_conflicting_index(); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_contents("conflicting.txt", CONFLICTING_THEIRS_FILE); + +} + +void test_checkout_conflict__diff3(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + create_conflicting_index(); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_contents("conflicting.txt", CONFLICTING_DIFF3_FILE); +} + +void test_checkout_conflict__automerge(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "automergeable.txt" }, + { 0100644, AUTOMERGEABLE_OURS_OID, 2, "automergeable.txt" }, + { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "automergeable.txt" }, + }; + + create_index(checkout_index_entries, 3); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_contents("automergeable.txt", AUTOMERGEABLE_MERGED_FILE); +} + +void test_checkout_conflict__directory_file(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-1" }, + { 0100644, CONFLICTING_OURS_OID, 2, "df-1" }, + { 0100644, CONFLICTING_THEIRS_OID, 0, "df-1/file" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-2" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "df-2" }, + { 0100644, CONFLICTING_OURS_OID, 0, "df-2/file" }, + + { 0100644, CONFLICTING_THEIRS_OID, 3, "df-3" }, + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-3/file" }, + { 0100644, CONFLICTING_OURS_OID, 2, "df-3/file" }, + + { 0100644, CONFLICTING_OURS_OID, 2, "df-4" }, + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-4/file" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "df-4/file" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 12); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_oid("df-1/file", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("df-1~ours", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-2/file", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-2~theirs", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("df-3/file", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-3~theirs", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("df-4~ours", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-4/file", CONFLICTING_THEIRS_OID); +} + +void test_checkout_conflict__directory_file_with_custom_labels(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-1" }, + { 0100644, CONFLICTING_OURS_OID, 2, "df-1" }, + { 0100644, CONFLICTING_THEIRS_OID, 0, "df-1/file" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-2" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "df-2" }, + { 0100644, CONFLICTING_OURS_OID, 0, "df-2/file" }, + + { 0100644, CONFLICTING_THEIRS_OID, 3, "df-3" }, + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-3/file" }, + { 0100644, CONFLICTING_OURS_OID, 2, "df-3/file" }, + + { 0100644, CONFLICTING_OURS_OID, 2, "df-4" }, + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-4/file" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "df-4/file" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + opts.our_label = "HEAD"; + opts.their_label = "branch"; + + create_index(checkout_index_entries, 12); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_oid("df-1/file", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("df-1~HEAD", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-2/file", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-2~branch", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("df-3/file", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-3~branch", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("df-4~HEAD", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-4/file", CONFLICTING_THEIRS_OID); +} + +void test_checkout_conflict__link_file(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "link-1" }, + { 0100644, CONFLICTING_OURS_OID, 2, "link-1" }, + { 0120000, LINK_THEIRS_OID, 3, "link-1" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "link-2" }, + { 0120000, LINK_OURS_OID, 2, "link-2" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "link-2" }, + + { 0120000, LINK_ANCESTOR_OID, 1, "link-3" }, + { 0100644, CONFLICTING_OURS_OID, 2, "link-3" }, + { 0120000, LINK_THEIRS_OID, 3, "link-3" }, + + { 0120000, LINK_ANCESTOR_OID, 1, "link-4" }, + { 0120000, LINK_OURS_OID, 2, "link-4" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "link-4" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 12); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + /* Typechange conflicts always keep the file in the workdir */ + ensure_workdir_oid("link-1", CONFLICTING_OURS_OID); + ensure_workdir_oid("link-2", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("link-3", CONFLICTING_OURS_OID); + ensure_workdir_oid("link-4", CONFLICTING_THEIRS_OID); +} + +void test_checkout_conflict__links(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0120000, LINK_ANCESTOR_OID, 1, "link-1" }, + { 0120000, LINK_OURS_OID, 2, "link-1" }, + { 0120000, LINK_THEIRS_OID, 3, "link-1" }, + + { 0120000, LINK_OURS_OID, 2, "link-2" }, + { 0120000, LINK_THEIRS_OID, 3, "link-2" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 5); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + /* Conflicts with links always keep the ours side (even with -Xtheirs) */ + ensure_workdir_link("link-1", LINK_OURS_TARGET); + ensure_workdir_link("link-2", LINK_OURS_TARGET); +} + +void test_checkout_conflict__add_add(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_OURS_OID, 2, "conflicting.txt" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting.txt" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 2); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + /* Add/add writes diff3 files */ + ensure_workdir_contents("conflicting.txt", CONFLICTING_DIFF3_FILE); +} + +void test_checkout_conflict__mode_change(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "executable-1" }, + { 0100755, CONFLICTING_ANCESTOR_OID, 2, "executable-1" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "executable-1" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "executable-2" }, + { 0100644, CONFLICTING_OURS_OID, 2, "executable-2" }, + { 0100755, CONFLICTING_ANCESTOR_OID, 3, "executable-2" }, + + { 0100755, CONFLICTING_ANCESTOR_OID, 1, "executable-3" }, + { 0100644, CONFLICTING_ANCESTOR_OID, 2, "executable-3" }, + { 0100755, CONFLICTING_THEIRS_OID, 3, "executable-3" }, + + { 0100755, CONFLICTING_ANCESTOR_OID, 1, "executable-4" }, + { 0100755, CONFLICTING_OURS_OID, 2, "executable-4" }, + { 0100644, CONFLICTING_ANCESTOR_OID, 3, "executable-4" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "executable-5" }, + { 0100755, CONFLICTING_OURS_OID, 2, "executable-5" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "executable-5" }, + + { 0100755, CONFLICTING_ANCESTOR_OID, 1, "executable-6" }, + { 0100644, CONFLICTING_OURS_OID, 2, "executable-6" }, + { 0100755, CONFLICTING_THEIRS_OID, 3, "executable-6" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 18); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + /* Keep the modified mode */ + ensure_workdir_oid("executable-1", CONFLICTING_THEIRS_OID); + ensure_workdir_mode("executable-1", 0100755); + + ensure_workdir_oid("executable-2", CONFLICTING_OURS_OID); + ensure_workdir_mode("executable-2", 0100755); + + ensure_workdir_oid("executable-3", CONFLICTING_THEIRS_OID); + ensure_workdir_mode("executable-3", 0100644); + + ensure_workdir_oid("executable-4", CONFLICTING_OURS_OID); + ensure_workdir_mode("executable-4", 0100644); + + ensure_workdir_contents("executable-5", CONFLICTING_DIFF3_FILE); + ensure_workdir_mode("executable-5", 0100755); + + ensure_workdir_contents("executable-6", CONFLICTING_DIFF3_FILE); + ensure_workdir_mode("executable-6", 0100644); +} diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/1a/010b1c0f081b2e8901d55307a15c29ff30af0e b/tests-clar/resources/merge-resolve/.gitted/objects/1a/010b1c0f081b2e8901d55307a15c29ff30af0e new file mode 100644 index 000000000..6039df00e Binary files /dev/null and b/tests-clar/resources/merge-resolve/.gitted/objects/1a/010b1c0f081b2e8901d55307a15c29ff30af0e differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/72/ea499e108df5ff0a4a913e7655bbeeb1fb69f2 b/tests-clar/resources/merge-resolve/.gitted/objects/72/ea499e108df5ff0a4a913e7655bbeeb1fb69f2 new file mode 100644 index 000000000..4886e492e Binary files /dev/null and b/tests-clar/resources/merge-resolve/.gitted/objects/72/ea499e108df5ff0a4a913e7655bbeeb1fb69f2 differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/8b/fb012a6d809e499bd8d3e194a3929bc8995b93 b/tests-clar/resources/merge-resolve/.gitted/objects/8b/fb012a6d809e499bd8d3e194a3929bc8995b93 new file mode 100644 index 000000000..a90ee08ce Binary files /dev/null and b/tests-clar/resources/merge-resolve/.gitted/objects/8b/fb012a6d809e499bd8d3e194a3929bc8995b93 differ -- cgit v1.2.1 From 629b661caab321a3aa5ffd7274ea4ed441d2805e Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 17 Jul 2013 09:49:56 -0500 Subject: checkout (from index) can write conflicts --- include/git2/checkout.h | 17 +- src/checkout.c | 91 +++++--- src/checkout.h | 29 +++ src/checkout_conflicts.c | 593 +++++++++++++++++++++++++++++++++++++++++++++++ src/merge_file.c | 2 +- src/reset.c | 2 +- 6 files changed, 687 insertions(+), 47 deletions(-) create mode 100644 src/checkout_conflicts.c diff --git a/include/git2/checkout.h b/include/git2/checkout.h index 844f0a9e2..3793a4f18 100644 --- a/include/git2/checkout.h +++ b/include/git2/checkout.h @@ -131,6 +131,13 @@ typedef enum { /** Don't refresh index/config/etc before doing checkout */ GIT_CHECKOUT_NO_REFRESH = (1u << 9), + /** Allow checkout to skip unmerged files */ + GIT_CHECKOUT_SKIP_UNMERGED = (1u << 10), + /** For unmerged files, checkout stage 2 from index */ + GIT_CHECKOUT_USE_OURS = (1u << 11), + /** For unmerged files, checkout stage 3 from index */ + GIT_CHECKOUT_USE_THEIRS = (1u << 12), + /** Treat pathspec as simple list of exact match file paths */ GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH = (1u << 13), @@ -141,13 +148,6 @@ typedef enum { * THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED */ - /** Allow checkout to skip unmerged files (NOT IMPLEMENTED) */ - GIT_CHECKOUT_SKIP_UNMERGED = (1u << 10), - /** For unmerged files, checkout stage 2 from index (NOT IMPLEMENTED) */ - GIT_CHECKOUT_USE_OURS = (1u << 11), - /** For unmerged files, checkout stage 3 from index (NOT IMPLEMENTED) */ - GIT_CHECKOUT_USE_THEIRS = (1u << 12), - /** Recursively checkout submodules with same options (NOT IMPLEMENTED) */ GIT_CHECKOUT_UPDATE_SUBMODULES = (1u << 16), /** Recursively checkout submodules if HEAD moved in super repo (NOT IMPLEMENTED) */ @@ -238,6 +238,9 @@ typedef struct git_checkout_opts { git_tree *baseline; /** expected content of workdir, defaults to HEAD */ const char *target_directory; /** alternative checkout path to workdir */ + + const char *our_label; /** the name of the "our" side of conflicts */ + const char *their_label; /** the name of the "their" side of conflicts */ } git_checkout_opts; #define GIT_CHECKOUT_OPTS_VERSION 1 diff --git a/src/checkout.c b/src/checkout.c index d3f673d40..fa0609fe3 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -41,24 +41,6 @@ enum { (CHECKOUT_ACTION__UPDATE_BLOB | CHECKOUT_ACTION__REMOVE), }; -typedef struct { - git_repository *repo; - git_diff_list *diff; - git_checkout_opts opts; - bool opts_free_baseline; - char *pfx; - git_index *index; - git_pool pool; - git_vector removes; - git_buf path; - size_t workdir_len; - unsigned int strategy; - int can_symlink; - bool reload_submodules; - size_t total_steps; - size_t completed_steps; -} checkout_data; - static int checkout_notify( checkout_data *data, git_checkout_notify_t why, @@ -707,6 +689,7 @@ static int blob_content_to_file( struct stat *st, git_blob *blob, const char *path, + const char * hint_path, mode_t entry_filemode, git_checkout_opts *opts) { @@ -715,9 +698,12 @@ static int blob_content_to_file( git_buf out = GIT_BUF_INIT; git_filter_list *fl = NULL; + if (hint_path == NULL) + hint_path = path; + if (!opts->disable_filters) error = git_filter_list_load( - &fl, git_blob_owner(blob), blob, path, GIT_FILTER_TO_WORKTREE); + &fl, git_blob_owner(blob), blob, hint_path, GIT_FILTER_TO_WORKTREE); if (!error) error = git_filter_list_apply_to_blob(&out, fl, blob); @@ -886,34 +872,26 @@ static int checkout_safe_for_update_only(const char *path, mode_t expected_mode) return 0; } -static int checkout_blob( +int git_checkout__write_content( checkout_data *data, - const git_diff_file *file) + const git_oid *oid, + const char *full_path, + const char *hint_path, + unsigned int mode, + struct stat *st) { int error = 0; git_blob *blob; - struct stat st; - - git_buf_truncate(&data->path, data->workdir_len); - if (git_buf_puts(&data->path, file->path) < 0) - return -1; - - if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0) { - int rval = checkout_safe_for_update_only( - git_buf_cstr(&data->path), file->mode); - if (rval <= 0) - return rval; - } - if ((error = git_blob_lookup(&blob, data->repo, &file->oid)) < 0) + if ((error = git_blob_lookup(&blob, data->repo, oid)) < 0) return error; - if (S_ISLNK(file->mode)) + if (S_ISLNK(mode)) error = blob_content_to_link( - &st, blob, git_buf_cstr(&data->path), data->opts.dir_mode, data->can_symlink); + st, blob, full_path, data->opts.dir_mode, data->can_symlink); else error = blob_content_to_file( - &st, blob, git_buf_cstr(&data->path), file->mode, &data->opts); + st, blob, full_path, hint_path, mode, &data->opts); git_blob_free(blob); @@ -928,6 +906,30 @@ static int checkout_blob( error = 0; } + return error; +} + +static int checkout_blob( + checkout_data *data, + const git_diff_file *file) +{ + int error = 0; + struct stat st; + + git_buf_truncate(&data->path, data->workdir_len); + if (git_buf_puts(&data->path, file->path) < 0) + return -1; + + if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0) { + int rval = checkout_safe_for_update_only( + git_buf_cstr(&data->path), file->mode); + if (rval <= 0) + return rval; + } + + error = git_checkout__write_content( + data, &file->oid, git_buf_cstr(&data->path), NULL, file->mode, &st); + /* update the index unless prevented */ if (!error && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0) error = checkout_update_index(data, file, &st); @@ -1172,7 +1174,17 @@ static int checkout_data_init( (error = git_index_read(data->index)) < 0) goto cleanup; - /* clear the REUC when doing a tree or commit checkout */ + /* cannot checkout if unresolved conflicts exist */ + if ((data->opts.checkout_strategy & GIT_CHECKOUT_FORCE) == 0 && + git_index_has_conflicts(data->index)) { + error = GIT_EMERGECONFLICT; + giterr_set(GITERR_CHECKOUT, + "unresolved conflicts exist in the index"); + goto cleanup; + } + + /* clean conflict data when doing a tree or commit checkout */ + git_index_name_clear(data->index); git_index_reuc_clear(data->index); } } @@ -1312,6 +1324,9 @@ int git_checkout_iterator( assert(data.completed_steps == data.total_steps); + /* Write conflict data to disk */ + error = git_checkout__conflicts(&data); + cleanup: if (error == GIT_EUSER) giterr_clear(); diff --git a/src/checkout.h b/src/checkout.h index 6d7186860..27e682fe1 100644 --- a/src/checkout.h +++ b/src/checkout.h @@ -9,9 +9,28 @@ #include "git2/checkout.h" #include "iterator.h" +#include "pool.h" #define GIT_CHECKOUT__NOTIFY_CONFLICT_TREE (1u << 12) +typedef struct { + git_repository *repo; + git_diff_list *diff; + git_checkout_opts opts; + bool opts_free_baseline; + char *pfx; + git_index *index; + git_pool pool; + git_vector removes; + git_buf path; + size_t workdir_len; + unsigned int strategy; + int can_symlink; + bool reload_submodules; + size_t total_steps; + size_t completed_steps; +} checkout_data; + /** * Update the working directory to match the target iterator. The * expected baseline value can be passed in via the checkout options @@ -21,4 +40,14 @@ extern int git_checkout_iterator( git_iterator *target, const git_checkout_opts *opts); +int git_checkout__write_content( + checkout_data *data, + const git_oid *oid, + const char *path, + const char *hint_path, + unsigned int mode, + struct stat *st); + +int git_checkout__conflicts(checkout_data *data); + #endif diff --git a/src/checkout_conflicts.c b/src/checkout_conflicts.c new file mode 100644 index 000000000..0c9c768df --- /dev/null +++ b/src/checkout_conflicts.c @@ -0,0 +1,593 @@ +/* + * 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 + +#include "checkout.h" + +#include "vector.h" +#include "index.h" +#include "merge_file.h" +#include "git2/repository.h" +#include "git2/types.h" +#include "git2/index.h" +#include "git2/sys/index.h" + +typedef struct { + const git_index_entry *ancestor; + const git_index_entry *ours; + const git_index_entry *theirs; + + int name_collision:1, + directoryfile:1; +} checkout_conflictdata; + +GIT_INLINE(int) checkout_idxentry_cmp( + const git_index_entry *a, + const git_index_entry *b) +{ + if (!a && !b) + return 0; + else if (!a && b) + return -1; + else if(a && !b) + return 1; + else + return strcmp(a->path, b->path); +} + +static int checkout_conflictdata_cmp(const void *a, const void *b) +{ + const checkout_conflictdata *ca = a; + const checkout_conflictdata *cb = b; + int diff; + + if ((diff = checkout_idxentry_cmp(ca->ancestor, cb->ancestor)) == 0 && + (diff = checkout_idxentry_cmp(ca->ours, cb->theirs)) == 0) + diff = checkout_idxentry_cmp(ca->theirs, cb->theirs); + + return diff; +} + +int checkout_conflictdata_empty(const git_vector *conflicts, size_t idx) +{ + const checkout_conflictdata *conflict; + + if ((conflict = git_vector_get(conflicts, idx)) == NULL) + return -1; + + return (conflict->ancestor == NULL && + conflict->ours == NULL && + conflict->theirs == NULL); +} + +static int checkout_conflicts_load(checkout_data *data, git_vector *conflicts) +{ + git_index_conflict_iterator *iterator = NULL; + const git_index_entry *ancestor, *ours, *theirs; + checkout_conflictdata *conflict; + int error = 0; + + if ((error = git_index_conflict_iterator_new(&iterator, data->index)) < 0) + goto done; + + conflicts->_cmp = checkout_conflictdata_cmp; + + /* Collect the conflicts */ + while ((error = git_index_conflict_next( + &ancestor, &ours, &theirs, iterator)) == 0) { + + conflict = git__calloc(1, sizeof(checkout_conflictdata)); + GITERR_CHECK_ALLOC(conflict); + + conflict->ancestor = ancestor; + conflict->ours = ours; + conflict->theirs = theirs; + + git_vector_insert(conflicts, conflict); + } + + if (error == GIT_ITEROVER) + error = 0; + +done: + git_index_conflict_iterator_free(iterator); + + return error; +} + +GIT_INLINE(int) checkout_conflicts_cmp_entry( + const char *path, + const git_index_entry *entry) +{ + /* TODO: is strcmp right here? should we use index->strcomp ? */ + return strcmp((const char *)path, entry->path); +} + +static int checkout_conflicts_cmp_ancestor(const void *p, const void *c) +{ + const char *path = p; + const checkout_conflictdata *conflict = c; + + if (!conflict->ancestor) + return 1; + + return checkout_conflicts_cmp_entry(path, conflict->ancestor); +} + +static checkout_conflictdata *checkout_conflicts_search_ancestor( + git_vector *conflicts, + const char *path) +{ + size_t pos; + + if (git_vector_bsearch2(&pos, conflicts, checkout_conflicts_cmp_ancestor, path) < 0) + return NULL; + + return git_vector_get(conflicts, pos); +} + +static checkout_conflictdata *checkout_conflicts_search_branch( + git_vector *conflicts, + const char *path) +{ + checkout_conflictdata *conflict; + size_t i; + + git_vector_foreach(conflicts, i, conflict) { + int cmp = -1; + + if (conflict->ancestor) + break; + + if (conflict->ours) + cmp = checkout_conflicts_cmp_entry(path, conflict->ours); + else if (conflict->theirs) + cmp = checkout_conflicts_cmp_entry(path, conflict->theirs); + + if (cmp == 0) + return conflict; + } + + return NULL; +} + +static int checkout_conflicts_load_byname_entry( + checkout_conflictdata **ancestor_out, + checkout_conflictdata **ours_out, + checkout_conflictdata **theirs_out, + git_vector *conflicts, + const git_index_name_entry *name_entry) +{ + checkout_conflictdata *ancestor, *ours = NULL, *theirs = NULL; + int error = 0; + + *ancestor_out = NULL; + *ours_out = NULL; + *theirs_out = NULL; + + if (!name_entry->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"); + error = -1; + goto done; + } + + if ((ancestor = checkout_conflicts_search_ancestor(conflicts, + name_entry->ancestor)) == NULL) { + giterr_set(GITERR_INDEX, + "A NAME entry referenced ancestor entry '%s' which does not exist in the main index", + name_entry->ancestor); + error = -1; + goto done; + } + + if (name_entry->ours) { + if (strcmp(name_entry->ancestor, name_entry->ours) == 0) + ours = ancestor; + else if ((ours = checkout_conflicts_search_branch(conflicts, 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", + name_entry->ours); + error = -1; + goto done; + } + } + + if (name_entry->theirs) { + if (strcmp(name_entry->ancestor, name_entry->theirs) == 0) + theirs = ancestor; + else if ((theirs = checkout_conflicts_search_branch(conflicts, 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", + name_entry->theirs); + error = -1; + goto done; + } + } + + *ancestor_out = ancestor; + *ours_out = ours; + *theirs_out = theirs; + +done: + return error; +} + +static int checkout_conflicts_coalesce_renames( + checkout_data *data, + git_vector *conflicts) +{ + const git_index_name_entry *name_entry; + checkout_conflictdata *ancestor_conflict, *our_conflict, *their_conflict; + size_t i, names; + int error = 0; + + /* Juggle entries based on renames */ + for (i = 0, names = git_index_name_entrycount(data->index); + i < names; + i++) { + + name_entry = git_index_name_get_byindex(data->index, i); + + if ((error = checkout_conflicts_load_byname_entry( + &ancestor_conflict, &our_conflict, &their_conflict, + conflicts, name_entry)) < 0) + goto done; + + if (our_conflict && our_conflict != ancestor_conflict) { + ancestor_conflict->ours = our_conflict->ours; + our_conflict->ours = NULL; + + if (our_conflict->theirs) + our_conflict->name_collision = 1; + + if (our_conflict->name_collision) + ancestor_conflict->name_collision = 1; + } + + if (their_conflict && their_conflict != ancestor_conflict) { + ancestor_conflict->theirs = their_conflict->theirs; + their_conflict->theirs = NULL; + + if (their_conflict->ours) + their_conflict->name_collision = 1; + + if (their_conflict->name_collision) + ancestor_conflict->name_collision = 1; + } + } + + git_vector_remove_matching(conflicts, checkout_conflictdata_empty); + +done: + return error; +} + +/* TODO: does this exist elsewhere? */ +GIT_INLINE(void) path_equal_or_prefixed( + bool *path_eq, + bool *path_prefixed, + const char *parent, + const char *child) +{ + size_t child_len = strlen(child); + size_t parent_len = strlen(parent); + + if (child_len == parent_len) { + *path_eq = (strcmp(parent, child) == 0); + *path_prefixed = 0; + return; + } + + *path_eq = 0; + + if (child_len < parent_len || + strncmp(parent, child, parent_len) != 0) + *path_prefixed = 0; + else + *path_prefixed = (child[parent_len] == '/'); +} + +static int checkout_conflicts_mark_directoryfile( + checkout_data *data, + git_vector *conflicts) +{ + checkout_conflictdata *conflict; + const git_index_entry *entry; + size_t i, j, len; + const char *path; + bool eq, prefixed; + int error = 0; + + len = git_index_entrycount(data->index); + + /* Find d/f conflicts */ + git_vector_foreach(conflicts, i, conflict) { + if ((conflict->ours && conflict->theirs) || + (!conflict->ours && !conflict->theirs)) + continue; + + path = conflict->ours ? + conflict->ours->path : conflict->theirs->path; + + if ((error = git_index_find(&j, data->index, path)) < 0) { + if (error == GIT_ENOTFOUND) + giterr_set(GITERR_MERGE, + "Index inconsistency, could not find entry for expected conflict '%s'", path); + + goto done; + } + + for (; j < len; j++) { + if ((entry = git_index_get_byindex(data->index, j)) == NULL) { + giterr_set(GITERR_MERGE, + "Index inconsistency, truncated index while loading expected conflict '%s'", path); + error = -1; + goto done; + } + + path_equal_or_prefixed(&eq, &prefixed, path, entry->path); + + if (eq) + continue; + + if (prefixed) + conflict->directoryfile = 1; + + break; + } + } + +done: + return error; +} + +static int conflict_entry_name( + git_buf *out, + const char *side_name, + const char *filename) +{ + if (git_buf_puts(out, side_name) < 0 || + git_buf_putc(out, ':') < 0 || + git_buf_puts(out, filename) < 0) + return -1; + + return 0; +} + +static int conflict_path_suffixed( + git_buf *out, + const char *path, + const char *side_name) +{ + if (git_buf_puts(out, path) < 0 || + git_buf_putc(out, '~') < 0 || + git_buf_puts(out, side_name) < 0) + return -1; + + return 0; +} + +static int checkout_write_entry( + checkout_data *data, + checkout_conflictdata *conflict, + const git_index_entry *side) +{ + const char *hint_path = NULL, *side_label; + struct stat st; + + assert (side == conflict->ours || + side == conflict->theirs); + + git_buf_truncate(&data->path, data->workdir_len); + if (git_buf_puts(&data->path, side->path) < 0) + return -1; + + if (conflict->name_collision || conflict->directoryfile) { + if (side == conflict->ours) + side_label = data->opts.our_label ? data->opts.our_label : + "ours"; + else if (side == conflict->theirs) + side_label = data->opts.their_label ? data->opts.their_label : + "theirs"; + + if (git_buf_putc(&data->path, '~') < 0 || + git_buf_puts(&data->path, side_label) < 0) + return -1; + + hint_path = side->path; + } + + return git_checkout__write_content(data, + &side->oid, git_buf_cstr(&data->path), hint_path, side->mode, &st); +} + +static int checkout_write_entries( + checkout_data *data, + checkout_conflictdata *conflict) +{ + int error = 0; + + if ((error = checkout_write_entry(data, conflict, conflict->ours)) >= 0) + error = checkout_write_entry(data, conflict, conflict->theirs); + + return error; +} + +static int checkout_write_merge( + checkout_data *data, + checkout_conflictdata *conflict) +{ + git_buf our_label = GIT_BUF_INIT, their_label = GIT_BUF_INIT, + path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT; + git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT, + ours = GIT_MERGE_FILE_INPUT_INIT, + theirs = GIT_MERGE_FILE_INPUT_INIT; + git_merge_file_result result = GIT_MERGE_FILE_RESULT_INIT; + git_filebuf output = GIT_FILEBUF_INIT; + const char *our_label_raw, *their_label_raw, *path; + int error = 0; + + if ((conflict->ancestor && + (error = git_merge_file_input_from_index_entry( + &ancestor, data->repo, conflict->ancestor)) < 0) || + (error = git_merge_file_input_from_index_entry( + &ours, data->repo, conflict->ours)) < 0 || + (error = git_merge_file_input_from_index_entry( + &theirs, data->repo, conflict->theirs)) < 0) + goto done; + + ancestor.label = NULL; + ours.label = our_label_raw = data->opts.our_label ? data->opts.our_label : "ours"; + theirs.label = their_label_raw = data->opts.their_label ? data->opts.their_label : "theirs"; + + /* If all the paths are identical, decorate the diff3 file with the branch + * names. Otherwise, append branch_name:path. + */ + if (conflict->ours && conflict->theirs && + strcmp(conflict->ours->path, conflict->theirs->path) != 0) { + + if ((error = conflict_entry_name( + &our_label, ours.label, conflict->ours->path)) < 0 || + (error = conflict_entry_name( + &their_label, theirs.label, conflict->theirs->path)) < 0) + goto done; + + ours.label = git_buf_cstr(&our_label); + theirs.label = git_buf_cstr(&their_label); + } + + if ((error = git_merge_files(&result, &ancestor, &ours, &theirs, 0)) < 0) + goto done; + + if (result.path == NULL || result.mode == 0) { + giterr_set(GITERR_CHECKOUT, "Could not merge contents of file"); + error = GIT_EMERGECONFLICT; + goto done; + } + + /* Rename 2->1 conflicts need the branch name appended */ + if (conflict->name_collision) { + /* TODO: strcmp? */ + if ((error = conflict_path_suffixed(&path_suffixed, result.path, + (strcmp(result.path, conflict->ours->path) == 0 ? + our_label_raw : their_label_raw))) < 0) + goto done; + + path = git_buf_cstr(&path_suffixed); + } else + path = result.path; + + if ((error = git_buf_joinpath(&path_workdir, git_repository_workdir(data->repo), path)) < 0 || + (error = git_futils_mkpath2file(path_workdir.ptr, 0755) < 0) || + (error = git_filebuf_open(&output, path_workdir.ptr, GIT_FILEBUF_DO_NOT_BUFFER)) < 0 || + (error = git_filebuf_write(&output, result.data, result.len)) < 0 || + (error = git_filebuf_commit(&output, result.mode)) < 0) + goto done; + +done: + git_buf_free(&our_label); + git_buf_free(&their_label); + + git_merge_file_input_free(&ancestor); + git_merge_file_input_free(&ours); + git_merge_file_input_free(&theirs); + git_merge_file_result_free(&result); + git_buf_free(&path_workdir); + git_buf_free(&path_suffixed); + + return error; +} + +GIT_INLINE(bool) conflict_is_1_to_2(checkout_conflictdata *conflict) +{ + /* TODO: can't we detect these when we coalesce? */ + return conflict->ancestor && conflict->ours && conflict->theirs && + (strcmp(conflict->ancestor->path, conflict->ours->path) != 0 && + strcmp(conflict->ancestor->path, conflict->theirs->path) != 0 && + strcmp(conflict->ours->path, conflict->theirs->path) != 0); +} + +int git_checkout__conflicts(checkout_data *data) +{ + git_vector conflicts = GIT_VECTOR_INIT; + checkout_conflictdata *conflict; + size_t i; + int error = 0; + + if (data->strategy & GIT_CHECKOUT_SKIP_UNMERGED) + return 0; + + if ((error = checkout_conflicts_load(data, &conflicts)) < 0 || + (error = checkout_conflicts_coalesce_renames(data, &conflicts)) < 0 || + (error = checkout_conflicts_mark_directoryfile(data, &conflicts)) < 0) + goto done; + + git_vector_foreach(&conflicts, i, conflict) { + /* Both deleted: nothing to do */ + if (conflict->ours == NULL && conflict->theirs == NULL) + error = 0; + + else if ((data->strategy & GIT_CHECKOUT_USE_OURS) && + conflict->ours) + error = checkout_write_entry(data, conflict, conflict->ours); + else if ((data->strategy & GIT_CHECKOUT_USE_THEIRS) && + conflict->theirs) + error = checkout_write_entry(data, conflict, conflict->theirs); + + /* Ignore the other side of name collisions. */ + else if ((data->strategy & GIT_CHECKOUT_USE_OURS) && + !conflict->ours && conflict->name_collision) + error = 0; + else if ((data->strategy & GIT_CHECKOUT_USE_THEIRS) && + !conflict->theirs && conflict->name_collision) + error = 0; + + /* For modify/delete, name collisions and d/f conflicts, write + * the file (potentially with the name mangled. + */ + else if (conflict->ours != NULL && conflict->theirs == NULL) + error = checkout_write_entry(data, conflict, conflict->ours); + else if (conflict->ours == NULL && conflict->theirs != NULL) + error = checkout_write_entry(data, conflict, conflict->theirs); + + /* Add/add conflicts and rename 1->2 conflicts, write the + * ours/theirs sides (potentially name mangled). + */ + else if (conflict_is_1_to_2(conflict)) + error = checkout_write_entries(data, conflict); + + /* If all sides are links, write the ours side */ + else if (S_ISLNK(conflict->ours->mode) && + S_ISLNK(conflict->theirs->mode)) + error = checkout_write_entry(data, conflict, conflict->ours); + /* Link/file conflicts, write the file side */ + else if (S_ISLNK(conflict->ours->mode)) + error = checkout_write_entry(data, conflict, conflict->theirs); + else if (S_ISLNK(conflict->theirs->mode)) + error = checkout_write_entry(data, conflict, conflict->ours); + + else + error = checkout_write_merge(data, conflict); + } + +done: + git_vector_foreach(&conflicts, i, conflict) + git__free(conflict); + + git_vector_free(&conflicts); + + return error; +} diff --git a/src/merge_file.c b/src/merge_file.c index c3477ccb9..48fc46e57 100644 --- a/src/merge_file.c +++ b/src/merge_file.c @@ -47,7 +47,7 @@ GIT_INLINE(int) merge_file_best_mode( * assume executable. Otherwise, if any mode changed from the ancestor, * use that one. */ - if (GIT_MERGE_FILE_SIDE_EXISTS(ancestor)) { + if (!GIT_MERGE_FILE_SIDE_EXISTS(ancestor)) { if (ours->mode == GIT_FILEMODE_BLOB_EXECUTABLE || theirs->mode == GIT_FILEMODE_BLOB_EXECUTABLE) return GIT_FILEMODE_BLOB_EXECUTABLE; diff --git a/src/reset.c b/src/reset.c index cea212a93..87dc45a3f 100644 --- a/src/reset.c +++ b/src/reset.c @@ -135,7 +135,7 @@ int git_reset( if (reset_type == GIT_RESET_HARD) { /* overwrite working directory with HEAD */ - opts.checkout_strategy = GIT_CHECKOUT_FORCE; + opts.checkout_strategy = GIT_CHECKOUT_FORCE | GIT_CHECKOUT_SKIP_UNMERGED; if ((error = git_checkout_tree(repo, (git_object *)tree, &opts)) < 0) goto cleanup; -- cgit v1.2.1 From 4f7897ab19daf6593b35c7f5b4f35403d00530ef Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 22 Jul 2013 08:51:29 -0700 Subject: Prevent checkout_tree when conflicts exist, clear NAME on checkout tree Prevent checkout tree when unresolved changes exist (unless FORCE flag is specified). Clear NAME table when checking out, to avoid checkout_conflicts from attempting to manipulate it. Ensure that NAME is also cleared at reset. --- tests-clar/checkout/tree.c | 44 +++++++++++++++++++++++++++++++ tests-clar/index/names.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c index fff530cdd..66b01bc7f 100644 --- a/tests-clar/checkout/tree.c +++ b/tests-clar/checkout/tree.c @@ -696,3 +696,47 @@ void test_checkout_tree__extremely_long_file_name(void) cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); cl_assert(!git_path_exists(path)); } + +static void create_conflict(void) +{ + git_index *index; + git_index_entry entry; + + cl_git_pass(git_repository_index(&index, g_repo)); + + memset(&entry, 0x0, sizeof(git_index_entry)); + entry.mode = 0100644; + entry.flags = 1 << GIT_IDXENTRY_STAGESHIFT; + git_oid_fromstr(&entry.oid, "d427e0b2e138501a3d15cc376077a3631e15bd46"); + entry.path = "conflicts.txt"; + cl_git_pass(git_index_add(index, &entry)); + + entry.flags = 2 << GIT_IDXENTRY_STAGESHIFT; + git_oid_fromstr(&entry.oid, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf"); + cl_git_pass(git_index_add(index, &entry)); + + entry.flags = 3 << GIT_IDXENTRY_STAGESHIFT; + git_oid_fromstr(&entry.oid, "2bd0a343aeef7a2cf0d158478966a6e587ff3863"); + cl_git_pass(git_index_add(index, &entry)); + + git_index_write(index); + git_index_free(index); +} + +void test_checkout_tree__fails_when_conflicts_exist_in_index(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_oid oid; + git_object *obj = NULL; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "HEAD")); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + + create_conflict(); + + cl_git_fail(git_checkout_tree(g_repo, obj, &opts)); + + git_object_free(obj); +} diff --git a/tests-clar/index/names.c b/tests-clar/index/names.c index 95a560ee4..87453ecbf 100644 --- a/tests-clar/index/names.c +++ b/tests-clar/index/names.c @@ -80,5 +80,69 @@ void test_index_names__roundtrip(void) cl_assert(strcmp(conflict_name->ancestor, "ancestor3") == 0); cl_assert(conflict_name->ours == NULL); cl_assert(strcmp(conflict_name->theirs, "theirs3") == 0); +} + +void test_index_names__cleaned_on_reset_hard(void) +{ + git_object *target; + + retrieve_target_from_oid(&target, repo, "3a34580a35add43a4cf361e8e9a30060a905c876"); + + test_index_names__add(); + cl_git_pass(git_reset(repo, target, GIT_RESET_HARD)); + cl_assert(git_index_name_entrycount(repo_index) == 0); + + git_object_free(target); +} + +void test_index_names__cleaned_on_reset_mixed(void) +{ + git_object *target; + + retrieve_target_from_oid(&target, repo, "3a34580a35add43a4cf361e8e9a30060a905c876"); + + test_index_names__add(); + cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED)); + cl_assert(git_index_name_entrycount(repo_index) == 0); + + git_object_free(target); +} + +void test_index_names__cleaned_on_checkout_tree(void) +{ + git_oid oid; + git_object *obj; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; + + test_index_names__add(); + git_reference_name_to_id(&oid, repo, "refs/heads/master"); + git_object_lookup(&obj, repo, &oid, GIT_OBJ_ANY); + git_checkout_tree(repo, obj, &opts); + cl_assert(git_index_name_entrycount(repo_index) == 0); + + git_object_free(obj); +} + +void test_index_names__cleaned_on_checkout_head(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; + + test_index_names__add(); + git_checkout_head(repo, &opts); + cl_assert(git_index_name_entrycount(repo_index) == 0); +} + +void test_index_names__retained_on_checkout_index(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; + test_index_names__add(); + git_checkout_index(repo, repo_index, &opts); + cl_assert(git_index_name_entrycount(repo_index) > 0); } -- cgit v1.2.1 From 96d799aa1830f5fcbacdfd87eca728727561d8e6 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 23 Jul 2013 15:32:42 -0700 Subject: checkout rename conflicts rename conflict tests for checkout conflicts, don't suffix filenames when checking out with USE_OURS or USE_THEIRS --- src/checkout_conflicts.c | 5 +- tests-clar/checkout/conflict.c | 378 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 381 insertions(+), 2 deletions(-) diff --git a/src/checkout_conflicts.c b/src/checkout_conflicts.c index 0c9c768df..45e43a324 100644 --- a/src/checkout_conflicts.c +++ b/src/checkout_conflicts.c @@ -395,7 +395,10 @@ static int checkout_write_entry( if (git_buf_puts(&data->path, side->path) < 0) return -1; - if (conflict->name_collision || conflict->directoryfile) { + if ((conflict->name_collision || conflict->directoryfile) && + (data->strategy & GIT_CHECKOUT_USE_OURS) == 0 && + (data->strategy & GIT_CHECKOUT_USE_THEIRS) == 0) { + if (side == conflict->ours) side_label = data->opts.our_label ? data->opts.our_label : "ours"; diff --git a/tests-clar/checkout/conflict.c b/tests-clar/checkout/conflict.c index 836495fef..da4a20fd8 100644 --- a/tests-clar/checkout/conflict.c +++ b/tests-clar/checkout/conflict.c @@ -53,6 +53,12 @@ struct checkout_index_entry { char path[128]; }; +struct checkout_name_entry { + char ancestor[64]; + char ours[64]; + char theirs[64]; +}; + void test_checkout_conflict__initialize(void) { g_repo = cl_git_sandbox_init(TEST_REPO_PATH); @@ -91,12 +97,24 @@ static void create_index(struct checkout_index_entry *entries, size_t entries_le git_oid_fromstr(&entry.oid, entries[i].oid_str); entry.path = entries[i].path; - git_index_add(g_index, &entry); + cl_git_pass(git_index_add(g_index, &entry)); } git_buf_free(&path); } +static void create_index_names(struct checkout_name_entry *entries, size_t entries_len) +{ + size_t i; + + for (i = 0; i < entries_len; i++) { + cl_git_pass(git_index_name_add(g_index, + strlen(entries[i].ancestor) == 0 ? NULL : entries[i].ancestor, + strlen(entries[i].ours) == 0 ? NULL : entries[i].ours, + strlen(entries[i].theirs) == 0 ? NULL : entries[i].theirs)); + } +} + static void create_conflicting_index(void) { struct checkout_index_entry checkout_index_entries[] = { @@ -148,6 +166,12 @@ static void ensure_workdir_mode(const char *path, int mode) #endif } +static void ensure_workdir(const char *path, int mode, const char *oid_str) +{ + ensure_workdir_mode(path, mode); + ensure_workdir_oid(path, oid_str); +} + static void ensure_workdir_link(const char *path, const char *target) { #ifdef GIT_WIN32 @@ -458,3 +482,355 @@ void test_checkout_conflict__mode_change(void) ensure_workdir_contents("executable-6", CONFLICTING_DIFF3_FILE); ensure_workdir_mode("executable-6", 0100644); } + +void test_checkout_conflict__renames(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 1, "0b-rewritten-in-ours.txt" }, + { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 2, "0b-rewritten-in-ours.txt" }, + { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 3, "0b-rewritten-in-ours.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 1, "0c-rewritten-in-theirs.txt" }, + { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 2, "0c-rewritten-in-theirs.txt" }, + { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 3, "0c-rewritten-in-theirs.txt" }, + { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, + { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, + { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, + { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, + { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 2, "3a-newname-in-ours-deleted-in-theirs.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 1, "3a-renamed-in-ours-deleted-in-theirs.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 3, "3b-newname-in-theirs-deleted-in-ours.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 1, "3b-renamed-in-theirs-deleted-in-ours.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 2, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 3, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 1, "4a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 2, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 3, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 1, "4b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 2, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 3, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 1, "5a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 3, "5a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 2, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 3, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 1, "5b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 2, "5b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 2, "6-both-renamed-1-to-2-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 3, "6-both-renamed-1-to-2-theirs.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 1, "6-both-renamed-1-to-2.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "7-both-renamed-side-1.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "7-both-renamed-side-1.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "7-both-renamed-side-2.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "7-both-renamed-side-2.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" } + }; + + struct checkout_name_entry checkout_name_entries[] = { + { + "3a-renamed-in-ours-deleted-in-theirs.txt", + "3a-newname-in-ours-deleted-in-theirs.txt", + "" + }, + + { + "3b-renamed-in-theirs-deleted-in-ours.txt", + "", + "3b-newname-in-theirs-deleted-in-ours.txt" + }, + + { + "4a-renamed-in-ours-added-in-theirs.txt", + "4a-newname-in-ours-added-in-theirs.txt", + "" + }, + + { + "4b-renamed-in-theirs-added-in-ours.txt", + "", + "4b-newname-in-theirs-added-in-ours.txt" + }, + + { + "5a-renamed-in-ours-added-in-theirs.txt", + "5a-newname-in-ours-added-in-theirs.txt", + "5a-renamed-in-ours-added-in-theirs.txt" + }, + + { + "5b-renamed-in-theirs-added-in-ours.txt", + "5b-renamed-in-theirs-added-in-ours.txt", + "5b-newname-in-theirs-added-in-ours.txt" + }, + + { + "6-both-renamed-1-to-2.txt", + "6-both-renamed-1-to-2-ours.txt", + "6-both-renamed-1-to-2-theirs.txt" + }, + + { + "7-both-renamed-side-1.txt", + "7-both-renamed.txt", + "7-both-renamed-side-1.txt" + }, + + { + "7-both-renamed-side-2.txt", + "7-both-renamed-side-2.txt", + "7-both-renamed.txt" + } + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 41); + create_index_names(checkout_name_entries, 9); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir("0a-no-change.txt", + 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"); + + ensure_workdir("0b-duplicated-in-ours.txt", + 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6"); + + ensure_workdir("0b-rewritten-in-ours.txt", + 0100644, "4c7e515d6d52d820496858f2f059ece69e99e2e3"); + + ensure_workdir("0c-duplicated-in-theirs.txt", + 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31"); + + ensure_workdir("0c-rewritten-in-theirs.txt", + 0100644, "4648d658682d1155c2a3db5b0c53305e26884ea5"); + + ensure_workdir("1a-newname-in-ours-edited-in-theirs.txt", + 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638"); + + ensure_workdir("1a-newname-in-ours.txt", + 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"); + + ensure_workdir("1b-newname-in-theirs-edited-in-ours.txt", + 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a"); + + ensure_workdir("1b-newname-in-theirs.txt", + 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"); + + ensure_workdir("2-newname-in-both.txt", + 0100644, "178940b450f238a56c0d75b7955cb57b38191982"); + + ensure_workdir("3a-newname-in-ours-deleted-in-theirs.txt", + 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"); + + ensure_workdir("3b-newname-in-theirs-deleted-in-ours.txt", + 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495"); + + ensure_workdir("4a-newname-in-ours-added-in-theirs.txt~ours", + 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c"); + + ensure_workdir("4a-newname-in-ours-added-in-theirs.txt~theirs", + 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a"); + + ensure_workdir("4b-newname-in-theirs-added-in-ours.txt~ours", + 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9"); + + ensure_workdir("4b-newname-in-theirs-added-in-ours.txt~theirs", + 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db"); + + ensure_workdir("5a-newname-in-ours-added-in-theirs.txt~ours", + 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436"); + + ensure_workdir("5a-newname-in-ours-added-in-theirs.txt~theirs", + 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714"); + + ensure_workdir("5b-newname-in-theirs-added-in-ours.txt~ours", + 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced"); + + ensure_workdir("5b-newname-in-theirs-added-in-ours.txt~theirs", + 0100644, "63247125386de9ec90a27ad36169307bf8a11a38"); + + ensure_workdir("6-both-renamed-1-to-2-ours.txt", + 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450"); + + ensure_workdir("6-both-renamed-1-to-2-theirs.txt", + 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450"); + + ensure_workdir("7-both-renamed.txt~ours", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); + + ensure_workdir("7-both-renamed.txt~theirs", + 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); +} + +void test_checkout_conflict__rename_keep_ours(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 1, "0b-rewritten-in-ours.txt" }, + { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 2, "0b-rewritten-in-ours.txt" }, + { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 3, "0b-rewritten-in-ours.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 1, "0c-rewritten-in-theirs.txt" }, + { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 2, "0c-rewritten-in-theirs.txt" }, + { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 3, "0c-rewritten-in-theirs.txt" }, + { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, + { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, + { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, + { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, + { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 2, "3a-newname-in-ours-deleted-in-theirs.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 1, "3a-renamed-in-ours-deleted-in-theirs.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 3, "3b-newname-in-theirs-deleted-in-ours.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 1, "3b-renamed-in-theirs-deleted-in-ours.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 2, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 3, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 1, "4a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 2, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 3, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 1, "4b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 2, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 3, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 1, "5a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 3, "5a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 2, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 3, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 1, "5b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 2, "5b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 2, "6-both-renamed-1-to-2-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 3, "6-both-renamed-1-to-2-theirs.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 1, "6-both-renamed-1-to-2.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "7-both-renamed-side-1.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "7-both-renamed-side-1.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "7-both-renamed-side-2.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "7-both-renamed-side-2.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" } + }; + + struct checkout_name_entry checkout_name_entries[] = { + { + "3a-renamed-in-ours-deleted-in-theirs.txt", + "3a-newname-in-ours-deleted-in-theirs.txt", + "" + }, + + { + "3b-renamed-in-theirs-deleted-in-ours.txt", + "", + "3b-newname-in-theirs-deleted-in-ours.txt" + }, + + { + "4a-renamed-in-ours-added-in-theirs.txt", + "4a-newname-in-ours-added-in-theirs.txt", + "" + }, + + { + "4b-renamed-in-theirs-added-in-ours.txt", + "", + "4b-newname-in-theirs-added-in-ours.txt" + }, + + { + "5a-renamed-in-ours-added-in-theirs.txt", + "5a-newname-in-ours-added-in-theirs.txt", + "5a-renamed-in-ours-added-in-theirs.txt" + }, + + { + "5b-renamed-in-theirs-added-in-ours.txt", + "5b-renamed-in-theirs-added-in-ours.txt", + "5b-newname-in-theirs-added-in-ours.txt" + }, + + { + "6-both-renamed-1-to-2.txt", + "6-both-renamed-1-to-2-ours.txt", + "6-both-renamed-1-to-2-theirs.txt" + }, + + { + "7-both-renamed-side-1.txt", + "7-both-renamed.txt", + "7-both-renamed-side-1.txt" + }, + + { + "7-both-renamed-side-2.txt", + "7-both-renamed-side-2.txt", + "7-both-renamed.txt" + } + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS; + + create_index(checkout_index_entries, 41); + create_index_names(checkout_name_entries, 9); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir("0a-no-change.txt", + 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"); + + ensure_workdir("0b-duplicated-in-ours.txt", + 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6"); + + ensure_workdir("0b-rewritten-in-ours.txt", + 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e"); + + ensure_workdir("0c-duplicated-in-theirs.txt", + 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31"); + + ensure_workdir("0c-rewritten-in-theirs.txt", + 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09"); + + ensure_workdir("1a-newname-in-ours-edited-in-theirs.txt", + 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638"); + + ensure_workdir("1a-newname-in-ours.txt", + 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"); + + ensure_workdir("1b-newname-in-theirs-edited-in-ours.txt", + 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a"); + + ensure_workdir("1b-newname-in-theirs.txt", + 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"); + + ensure_workdir("2-newname-in-both.txt", + 0100644, "178940b450f238a56c0d75b7955cb57b38191982"); + + ensure_workdir("3a-newname-in-ours-deleted-in-theirs.txt", + 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"); + + ensure_workdir("3b-newname-in-theirs-deleted-in-ours.txt", + 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495"); + + ensure_workdir("4a-newname-in-ours-added-in-theirs.txt", + 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c"); + + ensure_workdir("4b-newname-in-theirs-added-in-ours.txt", + 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9"); + + ensure_workdir("5a-newname-in-ours-added-in-theirs.txt", + 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436"); + + ensure_workdir("5b-newname-in-theirs-added-in-ours.txt", + 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced"); + + ensure_workdir("6-both-renamed-1-to-2-ours.txt", + 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450"); + + ensure_workdir("7-both-renamed.txt", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); +} -- cgit v1.2.1 From fc36800ecd8f8903f4cf7e40a54966855fdd4b76 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 8 Aug 2013 13:16:13 -0500 Subject: Get rid of some quick hacks --- src/checkout_conflicts.c | 48 +++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/src/checkout_conflicts.c b/src/checkout_conflicts.c index 45e43a324..54e040380 100644 --- a/src/checkout_conflicts.c +++ b/src/checkout_conflicts.c @@ -23,7 +23,8 @@ typedef struct { const git_index_entry *theirs; int name_collision:1, - directoryfile:1; + directoryfile:1, + one_to_two:1; } checkout_conflictdata; GIT_INLINE(int) checkout_idxentry_cmp( @@ -104,7 +105,6 @@ GIT_INLINE(int) checkout_conflicts_cmp_entry( const char *path, const git_index_entry *entry) { - /* TODO: is strcmp right here? should we use index->strcomp ? */ return strcmp((const char *)path, entry->path); } @@ -207,6 +207,8 @@ static int checkout_conflicts_load_byname_entry( if (name_entry->theirs) { if (strcmp(name_entry->ancestor, name_entry->theirs) == 0) theirs = ancestor; + else if (name_entry->ours && strcmp(name_entry->ours, name_entry->theirs) == 0) + theirs = ours; else if ((theirs = checkout_conflicts_search_branch(conflicts, name_entry->theirs)) == NULL || theirs->theirs == NULL) { giterr_set(GITERR_INDEX, @@ -267,6 +269,10 @@ static int checkout_conflicts_coalesce_renames( if (their_conflict->name_collision) ancestor_conflict->name_collision = 1; } + + if (our_conflict && our_conflict != ancestor_conflict && + their_conflict && their_conflict != ancestor_conflict) + ancestor_conflict->one_to_two = 1; } git_vector_remove_matching(conflicts, checkout_conflictdata_empty); @@ -275,29 +281,27 @@ done: return error; } -/* TODO: does this exist elsewhere? */ GIT_INLINE(void) path_equal_or_prefixed( bool *path_eq, bool *path_prefixed, const char *parent, const char *child) { - size_t child_len = strlen(child); - size_t parent_len = strlen(parent); + const char *p, *c; - if (child_len == parent_len) { - *path_eq = (strcmp(parent, child) == 0); - *path_prefixed = 0; - return; - } - *path_eq = 0; + *path_prefixed = 0; - if (child_len < parent_len || - strncmp(parent, child, parent_len) != 0) - *path_prefixed = 0; - else - *path_prefixed = (child[parent_len] == '/'); + for (p = parent, c = child; *p && *c; p++, c++) { + if (*p != *c) + return; + } + + if (!*p) + *path_prefixed = (*c == '/'); + + if (!*p && !*c) + *path_eq = 1; } static int checkout_conflicts_mark_directoryfile( @@ -483,7 +487,6 @@ static int checkout_write_merge( /* Rename 2->1 conflicts need the branch name appended */ if (conflict->name_collision) { - /* TODO: strcmp? */ if ((error = conflict_path_suffixed(&path_suffixed, result.path, (strcmp(result.path, conflict->ours->path) == 0 ? our_label_raw : their_label_raw))) < 0) @@ -514,15 +517,6 @@ done: return error; } -GIT_INLINE(bool) conflict_is_1_to_2(checkout_conflictdata *conflict) -{ - /* TODO: can't we detect these when we coalesce? */ - return conflict->ancestor && conflict->ours && conflict->theirs && - (strcmp(conflict->ancestor->path, conflict->ours->path) != 0 && - strcmp(conflict->ancestor->path, conflict->theirs->path) != 0 && - strcmp(conflict->ours->path, conflict->theirs->path) != 0); -} - int git_checkout__conflicts(checkout_data *data) { git_vector conflicts = GIT_VECTOR_INIT; @@ -569,7 +563,7 @@ int git_checkout__conflicts(checkout_data *data) /* Add/add conflicts and rename 1->2 conflicts, write the * ours/theirs sides (potentially name mangled). */ - else if (conflict_is_1_to_2(conflict)) + else if (conflict->one_to_two) error = checkout_write_entries(data, conflict); /* If all sides are links, write the ours side */ -- cgit v1.2.1 From e47f859db9a52f38d9ca94d725a178ac4ba93836 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 8 Aug 2013 16:46:49 -0500 Subject: Don't overwrite ~ files checking out conflicts If a D/F conflict or rename 2->1 conflict occurs, we write the file sides as filename~branchname. If a file with that name already exists in the working directory, write as filename~branchname_0 instead. (Incrementing 0 until a unique filename is found.) --- src/checkout_conflicts.c | 91 ++++++++++++++++++--------- tests-clar/checkout/conflict.c | 140 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+), 30 deletions(-) diff --git a/src/checkout_conflicts.c b/src/checkout_conflicts.c index 54e040380..dcf27145d 100644 --- a/src/checkout_conflicts.c +++ b/src/checkout_conflicts.c @@ -328,7 +328,7 @@ static int checkout_conflicts_mark_directoryfile( if ((error = git_index_find(&j, data->index, path)) < 0) { if (error == GIT_ENOTFOUND) - giterr_set(GITERR_MERGE, + giterr_set(GITERR_INDEX, "Index inconsistency, could not find entry for expected conflict '%s'", path); goto done; @@ -336,7 +336,7 @@ static int checkout_conflicts_mark_directoryfile( for (; j < len; j++) { if ((entry = git_index_get_byindex(data->index, j)) == NULL) { - giterr_set(GITERR_MERGE, + giterr_set(GITERR_INDEX, "Index inconsistency, truncated index while loading expected conflict '%s'", path); error = -1; goto done; @@ -371,16 +371,33 @@ static int conflict_entry_name( return 0; } -static int conflict_path_suffixed( - git_buf *out, - const char *path, - const char *side_name) +static int checkout_path_suffixed(git_buf *path, const char *suffix) { - if (git_buf_puts(out, path) < 0 || - git_buf_putc(out, '~') < 0 || - git_buf_puts(out, side_name) < 0) + size_t path_len; + int i = 0, error = 0; + + if ((error = git_buf_putc(path, '~')) < 0 || (error = git_buf_puts(path, suffix)) < 0) return -1; + path_len = git_buf_len(path); + + while (git_path_exists(git_buf_cstr(path)) && i < INT_MAX) { + git_buf_truncate(path, path_len); + + if ((error = git_buf_putc(path, '_')) < 0 || + (error = git_buf_printf(path, "%d", i)) < 0) + return error; + + i++; + } + + if (i == INT_MAX) { + git_buf_truncate(path, path_len); + + giterr_set(GITERR_CHECKOUT, "Could not write '%s': working directory file exists", path); + return GIT_EEXISTS; + } + return 0; } @@ -389,7 +406,7 @@ static int checkout_write_entry( checkout_conflictdata *conflict, const git_index_entry *side) { - const char *hint_path = NULL, *side_label; + const char *hint_path = NULL, *suffix; struct stat st; assert (side == conflict->ours || @@ -404,14 +421,13 @@ static int checkout_write_entry( (data->strategy & GIT_CHECKOUT_USE_THEIRS) == 0) { if (side == conflict->ours) - side_label = data->opts.our_label ? data->opts.our_label : + suffix = data->opts.our_label ? data->opts.our_label : "ours"; else if (side == conflict->theirs) - side_label = data->opts.their_label ? data->opts.their_label : + suffix = data->opts.their_label ? data->opts.their_label : "theirs"; - if (git_buf_putc(&data->path, '~') < 0 || - git_buf_puts(&data->path, side_label) < 0) + if (checkout_path_suffixed(&data->path, suffix) < 0) return -1; hint_path = side->path; @@ -433,6 +449,33 @@ static int checkout_write_entries( return error; } +static int checkout_merge_path( + git_buf *out, + checkout_data *data, + checkout_conflictdata *conflict, + git_merge_file_result *result) +{ + const char *our_label_raw, *their_label_raw, *suffix; + int i = 0, error = 0; + + if ((error = git_buf_joinpath(out, git_repository_workdir(data->repo), result->path)) < 0) + return error; + + /* Most conflicts simply use the filename in the index */ + if (!conflict->name_collision) + return 0; + + /* Rename 2->1 conflicts need the branch name appended */ + our_label_raw = data->opts.our_label ? data->opts.our_label : "ours"; + their_label_raw = data->opts.their_label ? data->opts.their_label : "theirs"; + suffix = strcmp(result->path, conflict->ours->path) == 0 ? our_label_raw : their_label_raw; + + if ((error = checkout_path_suffixed(out, suffix)) < 0) + return error; + + return 0; +} + static int checkout_write_merge( checkout_data *data, checkout_conflictdata *conflict) @@ -444,7 +487,6 @@ static int checkout_write_merge( theirs = GIT_MERGE_FILE_INPUT_INIT; git_merge_file_result result = GIT_MERGE_FILE_RESULT_INIT; git_filebuf output = GIT_FILEBUF_INIT; - const char *our_label_raw, *their_label_raw, *path; int error = 0; if ((conflict->ancestor && @@ -457,8 +499,8 @@ static int checkout_write_merge( goto done; ancestor.label = NULL; - ours.label = our_label_raw = data->opts.our_label ? data->opts.our_label : "ours"; - theirs.label = their_label_raw = data->opts.their_label ? data->opts.their_label : "theirs"; + ours.label = data->opts.our_label ? data->opts.our_label : "ours"; + theirs.label = data->opts.their_label ? data->opts.their_label : "theirs"; /* If all the paths are identical, decorate the diff3 file with the branch * names. Otherwise, append branch_name:path. @@ -485,19 +527,8 @@ static int checkout_write_merge( goto done; } - /* Rename 2->1 conflicts need the branch name appended */ - if (conflict->name_collision) { - if ((error = conflict_path_suffixed(&path_suffixed, result.path, - (strcmp(result.path, conflict->ours->path) == 0 ? - our_label_raw : their_label_raw))) < 0) - goto done; - - path = git_buf_cstr(&path_suffixed); - } else - path = result.path; - - if ((error = git_buf_joinpath(&path_workdir, git_repository_workdir(data->repo), path)) < 0 || - (error = git_futils_mkpath2file(path_workdir.ptr, 0755) < 0) || + if ((error = checkout_merge_path(&path_workdir, data, conflict, &result)) < 0 || + (error = git_futils_mkpath2file(path_workdir.ptr, 0755)) < 0 || (error = git_filebuf_open(&output, path_workdir.ptr, GIT_FILEBUF_DO_NOT_BUFFER)) < 0 || (error = git_filebuf_write(&output, result.data, result.len)) < 0 || (error = git_filebuf_commit(&output, result.mode)) < 0) diff --git a/tests-clar/checkout/conflict.c b/tests-clar/checkout/conflict.c index da4a20fd8..8b6dd4cd8 100644 --- a/tests-clar/checkout/conflict.c +++ b/tests-clar/checkout/conflict.c @@ -834,3 +834,143 @@ void test_checkout_conflict__rename_keep_ours(void) ensure_workdir("7-both-renamed.txt", 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); } + +void test_checkout_conflict__name_mangled_file_exists_in_workdir(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "test-one-side-one.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "test-one-side-one.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "test-one-side-two.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "test-one-side-two.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "test-one.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "test-one.txt" }, + + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "test-two-side-one.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "test-two-side-one.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "test-two-side-two.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "test-two-side-two.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "test-two.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "test-two.txt" }, + + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "test-three-side-one.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "test-three-side-one.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "test-three-side-two.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "test-three-side-two.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "test-three.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "test-three.txt" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-one" }, + { 0100644, CONFLICTING_OURS_OID, 2, "directory_file-one" }, + { 0100644, CONFLICTING_THEIRS_OID, 0, "directory_file-one/file" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-two" }, + { 0100644, CONFLICTING_OURS_OID, 0, "directory_file-two/file" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "directory_file-two" }, + }; + + struct checkout_name_entry checkout_name_entries[] = { + { + "test-one-side-one.txt", + "test-one.txt", + "test-one-side-one.txt" + }, + { + "test-one-side-two.txt", + "test-one-side-two.txt", + "test-one.txt" + }, + + { + "test-two-side-one.txt", + "test-two.txt", + "test-two-side-one.txt" + }, + { + "test-two-side-two.txt", + "test-two-side-two.txt", + "test-two.txt" + }, + + { + "test-three-side-one.txt", + "test-three.txt", + "test-three-side-one.txt" + }, + { + "test-three-side-two.txt", + "test-three-side-two.txt", + "test-three.txt" + } + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 24); + create_index_names(checkout_name_entries, 6); + git_index_write(g_index); + + /* Add some files on disk that conflict with the names that would be chosen + * for the files written for each side. */ + + cl_git_rewritefile("merge-resolve/test-one.txt~ours", + "Expect index contents to be written to ~ours_0"); + cl_git_rewritefile("merge-resolve/test-one.txt~theirs", + "Expect index contents to be written to ~theirs_0"); + + cl_git_rewritefile("merge-resolve/test-two.txt~ours", + "Expect index contents to be written to ~ours_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~theirs", + "Expect index contents to be written to ~theirs_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~ours_0", + "Expect index contents to be written to ~ours_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~theirs_0", + "Expect index contents to be written to ~theirs_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~ours_1", + "Expect index contents to be written to ~ours_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~theirs_1", + "Expect index contents to be written to ~theirs_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~ours_2", + "Expect index contents to be written to ~ours_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~theirs_2", + "Expect index contents to be written to ~theirs_3"); + + cl_git_rewritefile("merge-resolve/test-three.txt~Ours", + "Expect case insensitive filesystems to create ~ours_0"); + cl_git_rewritefile("merge-resolve/test-three.txt~THEIRS", + "Expect case insensitive filesystems to create ~theirs_0"); + + cl_git_rewritefile("merge-resolve/directory_file-one~ours", + "Index contents written to ~ours_0 in this D/F conflict"); + cl_git_rewritefile("merge-resolve/directory_file-two~theirs", + "Index contents written to ~theirs_0 in this D/F conflict"); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir("test-one.txt~ours_0", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); + ensure_workdir("test-one.txt~theirs_0", + 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); + + ensure_workdir("test-two.txt~ours_3", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); + ensure_workdir("test-two.txt~theirs_3", + 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); + + /* Name is mangled on case insensitive only */ +#if defined(GIT_WIN32) || defined(__APPLE__) + ensure_workdir("test-three.txt~ours_0", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); + ensure_workdir("test-three.txt~theirs_0", + 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); +#else + ensure_workdir("test-three.txt~ours", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); + ensure_workdir("test-three.txt~theirs", + 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); +#endif + + ensure_workdir("directory_file-one~ours_0", 0100644, CONFLICTING_OURS_OID); + ensure_workdir("directory_file-two~theirs_0", 0100644, CONFLICTING_THEIRS_OID); +} -- cgit v1.2.1 From 6f8cc7bb6a77e7b03751051be86a0c6b36bdd86f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 5 Aug 2013 20:06:09 -0500 Subject: Fix warning, fix memory leak --- src/checkout_conflicts.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/checkout_conflicts.c b/src/checkout_conflicts.c index dcf27145d..eb1ac6e14 100644 --- a/src/checkout_conflicts.c +++ b/src/checkout_conflicts.c @@ -56,14 +56,16 @@ static int checkout_conflictdata_cmp(const void *a, const void *b) int checkout_conflictdata_empty(const git_vector *conflicts, size_t idx) { - const checkout_conflictdata *conflict; + checkout_conflictdata *conflict; if ((conflict = git_vector_get(conflicts, idx)) == NULL) return -1; - return (conflict->ancestor == NULL && - conflict->ours == NULL && - conflict->theirs == NULL); + if (conflict->ancestor || conflict->ours || conflict->theirs) + return 0; + + git__free(conflict); + return 1; } static int checkout_conflicts_load(checkout_data *data, git_vector *conflicts) @@ -409,8 +411,7 @@ static int checkout_write_entry( const char *hint_path = NULL, *suffix; struct stat st; - assert (side == conflict->ours || - side == conflict->theirs); + assert (side == conflict->ours || side == conflict->theirs); git_buf_truncate(&data->path, data->workdir_len); if (git_buf_puts(&data->path, side->path) < 0) @@ -423,7 +424,7 @@ static int checkout_write_entry( if (side == conflict->ours) suffix = data->opts.our_label ? data->opts.our_label : "ours"; - else if (side == conflict->theirs) + else suffix = data->opts.their_label ? data->opts.their_label : "theirs"; @@ -456,7 +457,7 @@ static int checkout_merge_path( git_merge_file_result *result) { const char *our_label_raw, *their_label_raw, *suffix; - int i = 0, error = 0; + int error = 0; if ((error = git_buf_joinpath(out, git_repository_workdir(data->repo), result->path)) < 0) return error; -- cgit v1.2.1 From cfae7f85fbbc5b0e023e94f78486bf72cc1436f5 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 9 Aug 2013 20:23:36 -0500 Subject: Honor UPDATE_ONLY bit when checking out conflicts --- src/checkout.c | 4 ++-- src/checkout.h | 4 ++++ src/checkout_conflicts.c | 15 +++++++++++-- tests-clar/checkout/conflict.c | 50 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 68 insertions(+), 5 deletions(-) diff --git a/src/checkout.c b/src/checkout.c index fa0609fe3..7c90ef81d 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -851,7 +851,7 @@ static void report_progress( data->opts.progress_payload); } -static int checkout_safe_for_update_only(const char *path, mode_t expected_mode) +int git_checkout__safe_for_update_only(const char *path, mode_t expected_mode) { struct stat st; @@ -921,7 +921,7 @@ static int checkout_blob( return -1; if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0) { - int rval = checkout_safe_for_update_only( + int rval = git_checkout__safe_for_update_only( git_buf_cstr(&data->path), file->mode); if (rval <= 0) return rval; diff --git a/src/checkout.h b/src/checkout.h index 27e682fe1..9a8098998 100644 --- a/src/checkout.h +++ b/src/checkout.h @@ -40,6 +40,10 @@ extern int git_checkout_iterator( git_iterator *target, const git_checkout_opts *opts); +int git_checkout__safe_for_update_only( + const char *path, + mode_t expected_mode); + int git_checkout__write_content( checkout_data *data, const git_oid *oid, diff --git a/src/checkout_conflicts.c b/src/checkout_conflicts.c index eb1ac6e14..aa9064752 100644 --- a/src/checkout_conflicts.c +++ b/src/checkout_conflicts.c @@ -410,6 +410,7 @@ static int checkout_write_entry( { const char *hint_path = NULL, *suffix; struct stat st; + int error; assert (side == conflict->ours || side == conflict->theirs); @@ -434,6 +435,10 @@ static int checkout_write_entry( hint_path = side->path; } + if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 && + (error = git_checkout__safe_for_update_only(git_buf_cstr(&data->path), side->mode)) <= 0) + return error; + return git_checkout__write_content(data, &side->oid, git_buf_cstr(&data->path), hint_path, side->mode, &st); } @@ -528,8 +533,14 @@ static int checkout_write_merge( goto done; } - if ((error = checkout_merge_path(&path_workdir, data, conflict, &result)) < 0 || - (error = git_futils_mkpath2file(path_workdir.ptr, 0755)) < 0 || + if ((error = checkout_merge_path(&path_workdir, data, conflict, &result)) < 0) + goto done; + + if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 && + (error = git_checkout__safe_for_update_only(git_buf_cstr(&path_workdir), result.mode)) <= 0) + goto done; + + if ((error = git_futils_mkpath2file(path_workdir.ptr, 0755)) < 0 || (error = git_filebuf_open(&output, path_workdir.ptr, GIT_FILEBUF_DO_NOT_BUFFER)) < 0 || (error = git_filebuf_write(&output, result.data, result.len)) < 0 || (error = git_filebuf_commit(&output, result.mode)) < 0) diff --git a/tests-clar/checkout/conflict.c b/tests-clar/checkout/conflict.c index 8b6dd4cd8..0b37ec8f5 100644 --- a/tests-clar/checkout/conflict.c +++ b/tests-clar/checkout/conflict.c @@ -82,7 +82,9 @@ static void create_index(struct checkout_index_entry *entries, size_t entries_le for (i = 0; i < entries_len; i++) { git_buf_joinpath(&path, TEST_REPO_PATH, entries[i].path); - p_unlink(git_buf_cstr(&path)); + + if (entries[i].stage == 3 && (i == 0 || strcmp(entries[i-1].path, entries[i].path) != 0 || entries[i-1].stage != 2)) + p_unlink(git_buf_cstr(&path)); git_index_remove_bypath(g_index, entries[i].path); } @@ -203,6 +205,7 @@ void test_checkout_conflict__ignored(void) opts.checkout_strategy |= GIT_CHECKOUT_SKIP_UNMERGED; create_conflicting_index(); + cl_git_pass(p_unlink(TEST_REPO_PATH "/conflicting.txt")); cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); @@ -974,3 +977,48 @@ void test_checkout_conflict__name_mangled_file_exists_in_workdir(void) ensure_workdir("directory_file-one~ours_0", 0100644, CONFLICTING_OURS_OID); ensure_workdir("directory_file-two~theirs_0", 0100644, CONFLICTING_THEIRS_OID); } + +void test_checkout_conflict__update_only(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "automergeable.txt" }, + { 0100644, AUTOMERGEABLE_OURS_OID, 2, "automergeable.txt" }, + { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "automergeable.txt" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "modify-delete" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "modify-delete" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-one" }, + { 0100644, CONFLICTING_OURS_OID, 2, "directory_file-one" }, + { 0100644, CONFLICTING_THEIRS_OID, 0, "directory_file-one/file" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-two" }, + { 0100644, CONFLICTING_OURS_OID, 0, "directory_file-two/file" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "directory_file-two" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_UPDATE_ONLY; + + create_index(checkout_index_entries, 3); + git_index_write(g_index); + + cl_git_pass(p_mkdir("merge-resolve/directory_file-two", 0777)); + cl_git_rewritefile("merge-resolve/directory_file-two/file", CONFLICTING_OURS_FILE); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_contents("automergeable.txt", AUTOMERGEABLE_MERGED_FILE); + ensure_workdir("directory_file-two/file", 0100644, CONFLICTING_OURS_OID); + + cl_assert(!git_path_exists("merge-resolve/modify-delete")); + cl_assert(!git_path_exists("merge-resolve/test-one.txt")); + cl_assert(!git_path_exists("merge-resolve/test-one-side-one.txt")); + cl_assert(!git_path_exists("merge-resolve/test-one-side-two.txt")); + cl_assert(!git_path_exists("merge-resolve/test-one.txt~ours")); + cl_assert(!git_path_exists("merge-resolve/test-one.txt~theirs")); + cl_assert(!git_path_exists("merge-resolve/directory_file-one/file")); + cl_assert(!git_path_exists("merge-resolve/directory_file-one~ours")); + cl_assert(!git_path_exists("merge-resolve/directory_file-two~theirs")); +} -- cgit v1.2.1 From 216f97e4f68c99c21d57a9196702df1f8f4366d4 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 23 Sep 2013 09:47:47 -0400 Subject: Two-step conflict checkout (load / perform) Move conflict handling into two steps: load the conflicts and then apply the conflicts. This is more compatible with the existing checkout implementation and makes progress reporting more sane. --- src/checkout.c | 54 ++++++++++-------- src/checkout.h | 29 ++++++++++ src/checkout_conflicts.c | 122 +++++++++++++++++++++++++---------------- tests-clar/checkout/conflict.c | 100 +++++++++++++++++++++++++++++++++ 4 files changed, 234 insertions(+), 71 deletions(-) diff --git a/src/checkout.c b/src/checkout.c index 7c90ef81d..323863ce2 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -29,18 +29,6 @@ /* See docs/checkout-internals.md for more information */ -enum { - CHECKOUT_ACTION__NONE = 0, - CHECKOUT_ACTION__REMOVE = 1, - CHECKOUT_ACTION__UPDATE_BLOB = 2, - CHECKOUT_ACTION__UPDATE_SUBMODULE = 4, - CHECKOUT_ACTION__CONFLICT = 8, - CHECKOUT_ACTION__MAX = 8, - CHECKOUT_ACTION__DEFER_REMOVE = 16, - CHECKOUT_ACTION__REMOVE_AND_UPDATE = - (CHECKOUT_ACTION__UPDATE_BLOB | CHECKOUT_ACTION__REMOVE), -}; - static int checkout_notify( checkout_data *data, git_checkout_notify_t why, @@ -641,6 +629,14 @@ static int checkout_get_actions( goto fail; } + + if ((error = git_checkout__get_conflicts(data, workdir, &pathspec)) < 0) + goto fail; + + counts[CHECKOUT_ACTION__UPDATE_CONFLICT] = git_vector_length(&data->conflicts); + + /* HERE */ + git_pathspec__vfree(&pathspec); git_pool_clear(&pathpool); @@ -841,7 +837,7 @@ static int checkout_submodule( return checkout_submodule_update_index(data, file); } -static void report_progress( +void git_checkout__report_progress( checkout_data *data, const char *path) { @@ -965,7 +961,7 @@ static int checkout_remove_the_old( return error; data->completed_steps++; - report_progress(data, delta->old_file.path); + git_checkout__report_progress(data, delta->old_file.path); if ((actions[i] & CHECKOUT_ACTION__UPDATE_BLOB) == 0 && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0 && @@ -982,7 +978,7 @@ static int checkout_remove_the_old( return error; data->completed_steps++; - report_progress(data, str); + git_checkout__report_progress(data, str); if ((data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0 && data->index != NULL) @@ -1041,7 +1037,7 @@ static int checkout_create_the_new( return error; data->completed_steps++; - report_progress(data, delta->new_file.path); + git_checkout__report_progress(data, delta->new_file.path); } } @@ -1077,7 +1073,7 @@ static int checkout_create_submodules( return error; data->completed_steps++; - report_progress(data, delta->new_file.path); + git_checkout__report_progress(data, delta->new_file.path); } } @@ -1102,6 +1098,9 @@ static int checkout_lookup_head_tree(git_tree **out, git_repository *repo) static void checkout_data_clear(checkout_data *data) { + checkout_conflictdata *conflict; + size_t i; + if (data->opts_free_baseline) { git_tree_free(data->opts.baseline); data->opts.baseline = NULL; @@ -1110,6 +1109,11 @@ static void checkout_data_clear(checkout_data *data) git_vector_free(&data->removes); git_pool_clear(&data->pool); + git_vector_foreach(&data->conflicts, i, conflict) + git__free(conflict); + + git_vector_free(&data->conflicts); + git__free(data->pfx); data->pfx = NULL; @@ -1226,6 +1230,7 @@ static int checkout_data_init( } if ((error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 || + (error = git_vector_init(&data->conflicts, 0, NULL)) < 0 || (error = git_pool_init(&data->pool, 1, 0)) < 0 || (error = git_buf_puts(&data->path, data->opts.target_directory)) < 0 || (error = git_path_to_dir(&data->path)) < 0) @@ -1296,16 +1301,18 @@ int git_checkout_iterator( goto cleanup; /* Loop through diff (and working directory iterator) building a list of - * actions to be taken, plus look for conflicts and send notifications. + * actions to be taken, plus look for conflicts and send notifications, + * then loop through conflicts. */ if ((error = checkout_get_actions(&actions, &counts, &data, workdir)) < 0) goto cleanup; data.total_steps = counts[CHECKOUT_ACTION__REMOVE] + counts[CHECKOUT_ACTION__UPDATE_BLOB] + - counts[CHECKOUT_ACTION__UPDATE_SUBMODULE]; + counts[CHECKOUT_ACTION__UPDATE_SUBMODULE] + + counts[CHECKOUT_ACTION__UPDATE_CONFLICT]; - report_progress(&data, NULL); /* establish 0 baseline */ + git_checkout__report_progress(&data, NULL); /* establish 0 baseline */ /* To deal with some order dependencies, perform remaining checkout * in three passes: removes, then update blobs, then update submodules. @@ -1322,10 +1329,11 @@ int git_checkout_iterator( (error = checkout_create_submodules(actions, &data)) < 0) goto cleanup; - assert(data.completed_steps == data.total_steps); + if (counts[CHECKOUT_ACTION__UPDATE_CONFLICT] > 0 && + (error = git_checkout__conflicts(&data)) < 0) + goto cleanup; - /* Write conflict data to disk */ - error = git_checkout__conflicts(&data); + assert(data.completed_steps == data.total_steps); cleanup: if (error == GIT_EUSER) diff --git a/src/checkout.h b/src/checkout.h index 9a8098998..d48e263e4 100644 --- a/src/checkout.h +++ b/src/checkout.h @@ -22,6 +22,7 @@ typedef struct { git_index *index; git_pool pool; git_vector removes; + git_vector conflicts; git_buf path; size_t workdir_len; unsigned int strategy; @@ -31,6 +32,29 @@ typedef struct { size_t completed_steps; } checkout_data; +typedef struct { + const git_index_entry *ancestor; + const git_index_entry *ours; + const git_index_entry *theirs; + + int name_collision:1, + directoryfile:1, + one_to_two:1; +} checkout_conflictdata; + +enum { + CHECKOUT_ACTION__NONE = 0, + CHECKOUT_ACTION__REMOVE = 1, + CHECKOUT_ACTION__UPDATE_BLOB = 2, + CHECKOUT_ACTION__UPDATE_SUBMODULE = 4, + CHECKOUT_ACTION__CONFLICT = 8, + CHECKOUT_ACTION__UPDATE_CONFLICT = 16, + CHECKOUT_ACTION__MAX = 16, + CHECKOUT_ACTION__DEFER_REMOVE = 32, + CHECKOUT_ACTION__REMOVE_AND_UPDATE = + (CHECKOUT_ACTION__UPDATE_BLOB | CHECKOUT_ACTION__REMOVE), +}; + /** * Update the working directory to match the target iterator. The * expected baseline value can be passed in via the checkout options @@ -52,6 +76,11 @@ int git_checkout__write_content( unsigned int mode, struct stat *st); +void git_checkout__report_progress( + checkout_data *data, + const char *path); + +int git_checkout__get_conflicts(checkout_data *data, git_iterator *workdir, git_vector *pathspec); int git_checkout__conflicts(checkout_data *data); #endif diff --git a/src/checkout_conflicts.c b/src/checkout_conflicts.c index aa9064752..c39cb764e 100644 --- a/src/checkout_conflicts.c +++ b/src/checkout_conflicts.c @@ -11,22 +11,13 @@ #include "vector.h" #include "index.h" +#include "pathspec.h" #include "merge_file.h" #include "git2/repository.h" #include "git2/types.h" #include "git2/index.h" #include "git2/sys/index.h" -typedef struct { - const git_index_entry *ancestor; - const git_index_entry *ours; - const git_index_entry *theirs; - - int name_collision:1, - directoryfile:1, - one_to_two:1; -} checkout_conflictdata; - GIT_INLINE(int) checkout_idxentry_cmp( const git_index_entry *a, const git_index_entry *b) @@ -68,7 +59,34 @@ int checkout_conflictdata_empty(const git_vector *conflicts, size_t idx) return 1; } -static int checkout_conflicts_load(checkout_data *data, git_vector *conflicts) +GIT_INLINE(bool) conflict_pathspec_match( + checkout_data *data, + git_iterator *workdir, + git_vector *pathspec, + const git_index_entry *ancestor, + const git_index_entry *ours, + const git_index_entry *theirs) +{ + /* if the pathspec matches ours *or* theirs, proceed */ + if (ours && git_pathspec__match(pathspec, ours->path, + (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, + git_iterator_ignore_case(workdir), NULL, NULL)) + return true; + + if (theirs && git_pathspec__match(pathspec, theirs->path, + (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, + git_iterator_ignore_case(workdir), NULL, NULL)) + return true; + + if (ancestor && git_pathspec__match(pathspec, ancestor->path, + (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, + git_iterator_ignore_case(workdir), NULL, NULL)) + return true; + + return false; +} + +static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, git_vector *pathspec) { git_index_conflict_iterator *iterator = NULL; const git_index_entry *ancestor, *ours, *theirs; @@ -78,11 +96,12 @@ static int checkout_conflicts_load(checkout_data *data, git_vector *conflicts) if ((error = git_index_conflict_iterator_new(&iterator, data->index)) < 0) goto done; - conflicts->_cmp = checkout_conflictdata_cmp; + data->conflicts._cmp = checkout_conflictdata_cmp; /* Collect the conflicts */ - while ((error = git_index_conflict_next( - &ancestor, &ours, &theirs, iterator)) == 0) { + while ((error = git_index_conflict_next(&ancestor, &ours, &theirs, iterator)) == 0) { + if (!conflict_pathspec_match(data, workdir, pathspec, ancestor, ours, theirs)) + continue; conflict = git__calloc(1, sizeof(checkout_conflictdata)); GITERR_CHECK_ALLOC(conflict); @@ -91,7 +110,7 @@ static int checkout_conflicts_load(checkout_data *data, git_vector *conflicts) conflict->ours = ours; conflict->theirs = theirs; - git_vector_insert(conflicts, conflict); + git_vector_insert(&data->conflicts, conflict); } if (error == GIT_ITEROVER) @@ -122,25 +141,25 @@ static int checkout_conflicts_cmp_ancestor(const void *p, const void *c) } static checkout_conflictdata *checkout_conflicts_search_ancestor( - git_vector *conflicts, + checkout_data *data, const char *path) { size_t pos; - if (git_vector_bsearch2(&pos, conflicts, checkout_conflicts_cmp_ancestor, path) < 0) + if (git_vector_bsearch2(&pos, &data->conflicts, checkout_conflicts_cmp_ancestor, path) < 0) return NULL; - return git_vector_get(conflicts, pos); + return git_vector_get(&data->conflicts, pos); } static checkout_conflictdata *checkout_conflicts_search_branch( - git_vector *conflicts, + checkout_data *data, const char *path) { checkout_conflictdata *conflict; size_t i; - git_vector_foreach(conflicts, i, conflict) { + git_vector_foreach(&data->conflicts, i, conflict) { int cmp = -1; if (conflict->ancestor) @@ -162,7 +181,7 @@ static int checkout_conflicts_load_byname_entry( checkout_conflictdata **ancestor_out, checkout_conflictdata **ours_out, checkout_conflictdata **theirs_out, - git_vector *conflicts, + checkout_data *data, const git_index_name_entry *name_entry) { checkout_conflictdata *ancestor, *ours = NULL, *theirs = NULL; @@ -184,7 +203,7 @@ static int checkout_conflicts_load_byname_entry( goto done; } - if ((ancestor = checkout_conflicts_search_ancestor(conflicts, + 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", @@ -196,7 +215,7 @@ static int checkout_conflicts_load_byname_entry( if (name_entry->ours) { if (strcmp(name_entry->ancestor, name_entry->ours) == 0) ours = ancestor; - else if ((ours = checkout_conflicts_search_branch(conflicts, name_entry->ours)) == NULL || + 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", @@ -211,7 +230,7 @@ static int checkout_conflicts_load_byname_entry( theirs = ancestor; else if (name_entry->ours && strcmp(name_entry->ours, name_entry->theirs) == 0) theirs = ours; - else if ((theirs = checkout_conflicts_search_branch(conflicts, name_entry->theirs)) == NULL || + 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", @@ -230,8 +249,7 @@ done: } static int checkout_conflicts_coalesce_renames( - checkout_data *data, - git_vector *conflicts) + checkout_data *data) { const git_index_name_entry *name_entry; checkout_conflictdata *ancestor_conflict, *our_conflict, *their_conflict; @@ -239,15 +257,14 @@ static int checkout_conflicts_coalesce_renames( int error = 0; /* Juggle entries based on renames */ - for (i = 0, names = git_index_name_entrycount(data->index); - i < names; - i++) { - + names = git_index_name_entrycount(data->index); + + for (i = 0; i < names; i++) { name_entry = git_index_name_get_byindex(data->index, i); if ((error = checkout_conflicts_load_byname_entry( &ancestor_conflict, &our_conflict, &their_conflict, - conflicts, name_entry)) < 0) + data, name_entry)) < 0) goto done; if (our_conflict && our_conflict != ancestor_conflict) { @@ -277,7 +294,7 @@ static int checkout_conflicts_coalesce_renames( ancestor_conflict->one_to_two = 1; } - git_vector_remove_matching(conflicts, checkout_conflictdata_empty); + git_vector_remove_matching(&data->conflicts, checkout_conflictdata_empty); done: return error; @@ -307,8 +324,7 @@ GIT_INLINE(void) path_equal_or_prefixed( } static int checkout_conflicts_mark_directoryfile( - checkout_data *data, - git_vector *conflicts) + checkout_data *data) { checkout_conflictdata *conflict; const git_index_entry *entry; @@ -320,7 +336,7 @@ static int checkout_conflicts_mark_directoryfile( len = git_index_entrycount(data->index); /* Find d/f conflicts */ - git_vector_foreach(conflicts, i, conflict) { + git_vector_foreach(&data->conflicts, i, conflict) { if ((conflict->ours && conflict->theirs) || (!conflict->ours && !conflict->theirs)) continue; @@ -560,22 +576,30 @@ done: return error; } -int git_checkout__conflicts(checkout_data *data) +int git_checkout__get_conflicts(checkout_data *data, git_iterator *workdir, git_vector *pathspec) { - git_vector conflicts = GIT_VECTOR_INIT; - checkout_conflictdata *conflict; - size_t i; int error = 0; if (data->strategy & GIT_CHECKOUT_SKIP_UNMERGED) return 0; - if ((error = checkout_conflicts_load(data, &conflicts)) < 0 || - (error = checkout_conflicts_coalesce_renames(data, &conflicts)) < 0 || - (error = checkout_conflicts_mark_directoryfile(data, &conflicts)) < 0) + if ((error = checkout_conflicts_load(data, workdir, pathspec)) < 0 || + (error = checkout_conflicts_coalesce_renames(data)) < 0 || + (error = checkout_conflicts_mark_directoryfile(data)) < 0) goto done; - git_vector_foreach(&conflicts, i, conflict) { +done: + return error; +} + +int git_checkout__conflicts(checkout_data *data) +{ + git_vector conflicts = GIT_VECTOR_INIT; + checkout_conflictdata *conflict; + size_t i; + int error = 0; + + git_vector_foreach(&data->conflicts, i, conflict) { /* Both deleted: nothing to do */ if (conflict->ours == NULL && conflict->theirs == NULL) error = 0; @@ -621,13 +645,15 @@ int git_checkout__conflicts(checkout_data *data) else error = checkout_write_merge(data, conflict); - } -done: - git_vector_foreach(&conflicts, i, conflict) - git__free(conflict); + if (error) + break; - git_vector_free(&conflicts); + data->completed_steps++; + git_checkout__report_progress(data, + conflict->ours ? conflict->ours->path : + (conflict->theirs ? conflict->theirs->path : conflict->ancestor->path)); + } return error; } diff --git a/tests-clar/checkout/conflict.c b/tests-clar/checkout/conflict.c index 0b37ec8f5..d261f3860 100644 --- a/tests-clar/checkout/conflict.c +++ b/tests-clar/checkout/conflict.c @@ -1022,3 +1022,103 @@ void test_checkout_conflict__update_only(void) cl_assert(!git_path_exists("merge-resolve/directory_file-one~ours")); cl_assert(!git_path_exists("merge-resolve/directory_file-two~theirs")); } + +void test_checkout_conflict__path_filters(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + char *paths[] = { "conflicting-1.txt", "conflicting-3.txt" }; + git_strarray patharray = {0}; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-1.txt" }, + { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-1.txt" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-1.txt" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-2.txt" }, + { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-2.txt" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-2.txt" }, + + { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-3.txt" }, + { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-3.txt" }, + { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-3.txt" }, + + { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-4.txt" }, + { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-4.txt" }, + { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-4.txt" }, + }; + + patharray.count = 2; + patharray.strings = paths; + + opts.paths = patharray; + + create_index(checkout_index_entries, 12); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_contents("conflicting-1.txt", CONFLICTING_DIFF3_FILE); + cl_assert(!git_path_exists("merge-resolve/conflicting-2.txt")); + ensure_workdir_contents("conflicting-3.txt", AUTOMERGEABLE_MERGED_FILE); + cl_assert(!git_path_exists("merge-resolve/conflicting-4.txt")); +} + +static void collect_progress( + const char *path, + size_t completed_steps, + size_t total_steps, + void *payload) +{ + git_vector *paths = payload; + + if (path == NULL) + return; + + git_vector_insert(paths, strdup(path)); +} + +void test_checkout_conflict__report_progress(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_vector paths = GIT_VECTOR_INIT; + char *path; + size_t i; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-1.txt" }, + { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-1.txt" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-1.txt" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-2.txt" }, + { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-2.txt" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-2.txt" }, + + { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-3.txt" }, + { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-3.txt" }, + { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-3.txt" }, + + { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-4.txt" }, + { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-4.txt" }, + { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-4.txt" }, + }; + + opts.progress_cb = collect_progress; + opts.progress_payload = &paths; + + + create_index(checkout_index_entries, 12); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + cl_assert_equal_i(4, git_vector_length(&paths)); + cl_assert_equal_s("conflicting-1.txt", git_vector_get(&paths, 0)); + cl_assert_equal_s("conflicting-2.txt", git_vector_get(&paths, 1)); + cl_assert_equal_s("conflicting-3.txt", git_vector_get(&paths, 2)); + cl_assert_equal_s("conflicting-4.txt", git_vector_get(&paths, 3)); + + git_vector_foreach(&paths, i, path) + git__free(path); + + git_vector_free(&paths); +} -- cgit v1.2.1 From 7fa73de16378ecfa484747d1b61656282923a88a Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 23 Sep 2013 17:52:40 -0400 Subject: Move functions in checkout_conflicts to checkout.c It seemed exceptionally silly to have a split there where no split needed to be. --- src/checkout.c | 704 ++++++++++++++++++++++++++++++++++++++++++++++- src/checkout.h | 62 ----- src/checkout_conflicts.c | 659 -------------------------------------------- 3 files changed, 696 insertions(+), 729 deletions(-) delete mode 100644 src/checkout_conflicts.c diff --git a/src/checkout.c b/src/checkout.c index 323863ce2..c226f4342 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -26,9 +26,52 @@ #include "diff.h" #include "pathspec.h" #include "buf_text.h" +#include "merge_file.h" /* See docs/checkout-internals.md for more information */ +enum { + CHECKOUT_ACTION__NONE = 0, + CHECKOUT_ACTION__REMOVE = 1, + CHECKOUT_ACTION__UPDATE_BLOB = 2, + CHECKOUT_ACTION__UPDATE_SUBMODULE = 4, + CHECKOUT_ACTION__CONFLICT = 8, + CHECKOUT_ACTION__UPDATE_CONFLICT = 16, + CHECKOUT_ACTION__MAX = 16, + CHECKOUT_ACTION__DEFER_REMOVE = 32, + CHECKOUT_ACTION__REMOVE_AND_UPDATE = + (CHECKOUT_ACTION__UPDATE_BLOB | CHECKOUT_ACTION__REMOVE), +}; + +typedef struct { + git_repository *repo; + git_diff_list *diff; + git_checkout_opts opts; + bool opts_free_baseline; + char *pfx; + git_index *index; + git_pool pool; + git_vector removes; + git_vector conflicts; + git_buf path; + size_t workdir_len; + unsigned int strategy; + int can_symlink; + bool reload_submodules; + size_t total_steps; + size_t completed_steps; +} checkout_data; + +typedef struct { + const git_index_entry *ancestor; + const git_index_entry *ours; + const git_index_entry *theirs; + + int name_collision:1, + directoryfile:1, + one_to_two:1; +} checkout_conflictdata; + static int checkout_notify( checkout_data *data, git_checkout_notify_t why, @@ -562,6 +605,383 @@ static int checkout_remaining_wd_items( return error; } +GIT_INLINE(int) checkout_idxentry_cmp( + const git_index_entry *a, + const git_index_entry *b) +{ + if (!a && !b) + return 0; + else if (!a && b) + return -1; + else if(a && !b) + return 1; + else + return strcmp(a->path, b->path); +} + +static int checkout_conflictdata_cmp(const void *a, const void *b) +{ + const checkout_conflictdata *ca = a; + const checkout_conflictdata *cb = b; + int diff; + + if ((diff = checkout_idxentry_cmp(ca->ancestor, cb->ancestor)) == 0 && + (diff = checkout_idxentry_cmp(ca->ours, cb->theirs)) == 0) + diff = checkout_idxentry_cmp(ca->theirs, cb->theirs); + + return diff; +} + +int checkout_conflictdata_empty(const git_vector *conflicts, size_t idx) +{ + checkout_conflictdata *conflict; + + if ((conflict = git_vector_get(conflicts, idx)) == NULL) + return -1; + + if (conflict->ancestor || conflict->ours || conflict->theirs) + return 0; + + git__free(conflict); + return 1; +} + +GIT_INLINE(bool) conflict_pathspec_match( + checkout_data *data, + git_iterator *workdir, + git_vector *pathspec, + const git_index_entry *ancestor, + const git_index_entry *ours, + const git_index_entry *theirs) +{ + /* if the pathspec matches ours *or* theirs, proceed */ + if (ours && git_pathspec__match(pathspec, ours->path, + (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, + git_iterator_ignore_case(workdir), NULL, NULL)) + return true; + + if (theirs && git_pathspec__match(pathspec, theirs->path, + (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, + git_iterator_ignore_case(workdir), NULL, NULL)) + return true; + + if (ancestor && git_pathspec__match(pathspec, ancestor->path, + (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, + git_iterator_ignore_case(workdir), NULL, NULL)) + return true; + + return false; +} + +static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, git_vector *pathspec) +{ + git_index_conflict_iterator *iterator = NULL; + const git_index_entry *ancestor, *ours, *theirs; + checkout_conflictdata *conflict; + int error = 0; + + if ((error = git_index_conflict_iterator_new(&iterator, data->index)) < 0) + goto done; + + data->conflicts._cmp = checkout_conflictdata_cmp; + + /* Collect the conflicts */ + while ((error = git_index_conflict_next(&ancestor, &ours, &theirs, iterator)) == 0) { + if (!conflict_pathspec_match(data, workdir, pathspec, ancestor, ours, theirs)) + continue; + + conflict = git__calloc(1, sizeof(checkout_conflictdata)); + GITERR_CHECK_ALLOC(conflict); + + conflict->ancestor = ancestor; + conflict->ours = ours; + conflict->theirs = theirs; + + git_vector_insert(&data->conflicts, conflict); + } + + if (error == GIT_ITEROVER) + error = 0; + +done: + git_index_conflict_iterator_free(iterator); + + return error; +} + +GIT_INLINE(int) checkout_conflicts_cmp_entry( + const char *path, + const git_index_entry *entry) +{ + return strcmp((const char *)path, entry->path); +} + +static int checkout_conflicts_cmp_ancestor(const void *p, const void *c) +{ + const char *path = p; + const checkout_conflictdata *conflict = c; + + if (!conflict->ancestor) + return 1; + + return checkout_conflicts_cmp_entry(path, conflict->ancestor); +} + +static checkout_conflictdata *checkout_conflicts_search_ancestor( + checkout_data *data, + const char *path) +{ + size_t pos; + + if (git_vector_bsearch2(&pos, &data->conflicts, checkout_conflicts_cmp_ancestor, path) < 0) + return NULL; + + return git_vector_get(&data->conflicts, pos); +} + +static checkout_conflictdata *checkout_conflicts_search_branch( + checkout_data *data, + const char *path) +{ + checkout_conflictdata *conflict; + size_t i; + + git_vector_foreach(&data->conflicts, i, conflict) { + int cmp = -1; + + if (conflict->ancestor) + break; + + if (conflict->ours) + cmp = checkout_conflicts_cmp_entry(path, conflict->ours); + else if (conflict->theirs) + cmp = checkout_conflicts_cmp_entry(path, conflict->theirs); + + if (cmp == 0) + return conflict; + } + + return NULL; +} + +static int checkout_conflicts_load_byname_entry( + checkout_conflictdata **ancestor_out, + checkout_conflictdata **ours_out, + checkout_conflictdata **theirs_out, + checkout_data *data, + const git_index_name_entry *name_entry) +{ + checkout_conflictdata *ancestor, *ours = NULL, *theirs = NULL; + int error = 0; + + *ancestor_out = NULL; + *ours_out = NULL; + *theirs_out = NULL; + + if (!name_entry->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"); + error = -1; + goto done; + } + + 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", + name_entry->ancestor); + error = -1; + goto done; + } + + if (name_entry->ours) { + if (strcmp(name_entry->ancestor, name_entry->ours) == 0) + ours = ancestor; + 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", + name_entry->ours); + error = -1; + goto done; + } + } + + if (name_entry->theirs) { + if (strcmp(name_entry->ancestor, name_entry->theirs) == 0) + theirs = ancestor; + else if (name_entry->ours && strcmp(name_entry->ours, name_entry->theirs) == 0) + theirs = ours; + 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", + name_entry->theirs); + error = -1; + goto done; + } + } + + *ancestor_out = ancestor; + *ours_out = ours; + *theirs_out = theirs; + +done: + return error; +} + +static int checkout_conflicts_coalesce_renames( + checkout_data *data) +{ + const git_index_name_entry *name_entry; + checkout_conflictdata *ancestor_conflict, *our_conflict, *their_conflict; + size_t i, names; + int error = 0; + + /* Juggle entries based on renames */ + names = git_index_name_entrycount(data->index); + + for (i = 0; i < names; i++) { + name_entry = git_index_name_get_byindex(data->index, i); + + if ((error = checkout_conflicts_load_byname_entry( + &ancestor_conflict, &our_conflict, &their_conflict, + data, name_entry)) < 0) + goto done; + + if (our_conflict && our_conflict != ancestor_conflict) { + ancestor_conflict->ours = our_conflict->ours; + our_conflict->ours = NULL; + + if (our_conflict->theirs) + our_conflict->name_collision = 1; + + if (our_conflict->name_collision) + ancestor_conflict->name_collision = 1; + } + + if (their_conflict && their_conflict != ancestor_conflict) { + ancestor_conflict->theirs = their_conflict->theirs; + their_conflict->theirs = NULL; + + if (their_conflict->ours) + their_conflict->name_collision = 1; + + if (their_conflict->name_collision) + ancestor_conflict->name_collision = 1; + } + + if (our_conflict && our_conflict != ancestor_conflict && + their_conflict && their_conflict != ancestor_conflict) + ancestor_conflict->one_to_two = 1; + } + + git_vector_remove_matching(&data->conflicts, checkout_conflictdata_empty); + +done: + return error; +} + +GIT_INLINE(void) path_equal_or_prefixed( + bool *path_eq, + bool *path_prefixed, + const char *parent, + const char *child) +{ + const char *p, *c; + + *path_eq = 0; + *path_prefixed = 0; + + for (p = parent, c = child; *p && *c; p++, c++) { + if (*p != *c) + return; + } + + if (!*p) + *path_prefixed = (*c == '/'); + + if (!*p && !*c) + *path_eq = 1; +} + +static int checkout_conflicts_mark_directoryfile( + checkout_data *data) +{ + checkout_conflictdata *conflict; + const git_index_entry *entry; + size_t i, j, len; + const char *path; + bool eq, prefixed; + int error = 0; + + len = git_index_entrycount(data->index); + + /* Find d/f conflicts */ + git_vector_foreach(&data->conflicts, i, conflict) { + if ((conflict->ours && conflict->theirs) || + (!conflict->ours && !conflict->theirs)) + continue; + + path = conflict->ours ? + conflict->ours->path : conflict->theirs->path; + + if ((error = git_index_find(&j, data->index, path)) < 0) { + if (error == GIT_ENOTFOUND) + giterr_set(GITERR_INDEX, + "Index inconsistency, could not find entry for expected conflict '%s'", path); + + goto done; + } + + for (; j < len; j++) { + if ((entry = git_index_get_byindex(data->index, j)) == NULL) { + giterr_set(GITERR_INDEX, + "Index inconsistency, truncated index while loading expected conflict '%s'", path); + error = -1; + goto done; + } + + path_equal_or_prefixed(&eq, &prefixed, path, entry->path); + + if (eq) + continue; + + if (prefixed) + conflict->directoryfile = 1; + + break; + } + } + +done: + return error; +} + +static int checkout_get_conflicts( + checkout_data *data, + git_iterator *workdir, + git_vector *pathspec) +{ + int error = 0; + + if (data->strategy & GIT_CHECKOUT_SKIP_UNMERGED) + return 0; + + if ((error = checkout_conflicts_load(data, workdir, pathspec)) < 0 || + (error = checkout_conflicts_coalesce_renames(data)) < 0 || + (error = checkout_conflicts_mark_directoryfile(data)) < 0) + goto done; + +done: + return error; +} + static int checkout_get_actions( uint32_t **actions_ptr, size_t **counts_ptr, @@ -630,7 +1050,7 @@ static int checkout_get_actions( } - if ((error = git_checkout__get_conflicts(data, workdir, &pathspec)) < 0) + if ((error = checkout_get_conflicts(data, workdir, &pathspec)) < 0) goto fail; counts[CHECKOUT_ACTION__UPDATE_CONFLICT] = git_vector_length(&data->conflicts); @@ -837,7 +1257,7 @@ static int checkout_submodule( return checkout_submodule_update_index(data, file); } -void git_checkout__report_progress( +void report_progress( checkout_data *data, const char *path) { @@ -961,7 +1381,7 @@ static int checkout_remove_the_old( return error; data->completed_steps++; - git_checkout__report_progress(data, delta->old_file.path); + report_progress(data, delta->old_file.path); if ((actions[i] & CHECKOUT_ACTION__UPDATE_BLOB) == 0 && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0 && @@ -978,7 +1398,7 @@ static int checkout_remove_the_old( return error; data->completed_steps++; - git_checkout__report_progress(data, str); + report_progress(data, str); if ((data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0 && data->index != NULL) @@ -1037,7 +1457,7 @@ static int checkout_create_the_new( return error; data->completed_steps++; - git_checkout__report_progress(data, delta->new_file.path); + report_progress(data, delta->new_file.path); } } @@ -1073,7 +1493,7 @@ static int checkout_create_submodules( return error; data->completed_steps++; - git_checkout__report_progress(data, delta->new_file.path); + report_progress(data, delta->new_file.path); } } @@ -1096,6 +1516,274 @@ static int checkout_lookup_head_tree(git_tree **out, git_repository *repo) return error; } + +static int conflict_entry_name( + git_buf *out, + const char *side_name, + const char *filename) +{ + if (git_buf_puts(out, side_name) < 0 || + git_buf_putc(out, ':') < 0 || + git_buf_puts(out, filename) < 0) + return -1; + + return 0; +} + +static int checkout_path_suffixed(git_buf *path, const char *suffix) +{ + size_t path_len; + int i = 0, error = 0; + + if ((error = git_buf_putc(path, '~')) < 0 || (error = git_buf_puts(path, suffix)) < 0) + return -1; + + path_len = git_buf_len(path); + + while (git_path_exists(git_buf_cstr(path)) && i < INT_MAX) { + git_buf_truncate(path, path_len); + + if ((error = git_buf_putc(path, '_')) < 0 || + (error = git_buf_printf(path, "%d", i)) < 0) + return error; + + i++; + } + + if (i == INT_MAX) { + git_buf_truncate(path, path_len); + + giterr_set(GITERR_CHECKOUT, "Could not write '%s': working directory file exists", path); + return GIT_EEXISTS; + } + + return 0; +} + +static int checkout_write_entry( + checkout_data *data, + checkout_conflictdata *conflict, + const git_index_entry *side) +{ + const char *hint_path = NULL, *suffix; + struct stat st; + int error; + + assert (side == conflict->ours || side == conflict->theirs); + + git_buf_truncate(&data->path, data->workdir_len); + if (git_buf_puts(&data->path, side->path) < 0) + return -1; + + if ((conflict->name_collision || conflict->directoryfile) && + (data->strategy & GIT_CHECKOUT_USE_OURS) == 0 && + (data->strategy & GIT_CHECKOUT_USE_THEIRS) == 0) { + + if (side == conflict->ours) + suffix = data->opts.our_label ? data->opts.our_label : + "ours"; + else + suffix = data->opts.their_label ? data->opts.their_label : + "theirs"; + + if (checkout_path_suffixed(&data->path, suffix) < 0) + return -1; + + hint_path = side->path; + } + + if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 && + (error = git_checkout__safe_for_update_only(git_buf_cstr(&data->path), side->mode)) <= 0) + return error; + + return git_checkout__write_content(data, + &side->oid, git_buf_cstr(&data->path), hint_path, side->mode, &st); +} + +static int checkout_write_entries( + checkout_data *data, + checkout_conflictdata *conflict) +{ + int error = 0; + + if ((error = checkout_write_entry(data, conflict, conflict->ours)) >= 0) + error = checkout_write_entry(data, conflict, conflict->theirs); + + return error; +} + +static int checkout_merge_path( + git_buf *out, + checkout_data *data, + checkout_conflictdata *conflict, + git_merge_file_result *result) +{ + const char *our_label_raw, *their_label_raw, *suffix; + int error = 0; + + if ((error = git_buf_joinpath(out, git_repository_workdir(data->repo), result->path)) < 0) + return error; + + /* Most conflicts simply use the filename in the index */ + if (!conflict->name_collision) + return 0; + + /* Rename 2->1 conflicts need the branch name appended */ + our_label_raw = data->opts.our_label ? data->opts.our_label : "ours"; + their_label_raw = data->opts.their_label ? data->opts.their_label : "theirs"; + suffix = strcmp(result->path, conflict->ours->path) == 0 ? our_label_raw : their_label_raw; + + if ((error = checkout_path_suffixed(out, suffix)) < 0) + return error; + + return 0; +} + +static int checkout_write_merge( + checkout_data *data, + checkout_conflictdata *conflict) +{ + git_buf our_label = GIT_BUF_INIT, their_label = GIT_BUF_INIT, + path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT; + git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT, + ours = GIT_MERGE_FILE_INPUT_INIT, + theirs = GIT_MERGE_FILE_INPUT_INIT; + git_merge_file_result result = GIT_MERGE_FILE_RESULT_INIT; + git_filebuf output = GIT_FILEBUF_INIT; + int error = 0; + + if ((conflict->ancestor && + (error = git_merge_file_input_from_index_entry( + &ancestor, data->repo, conflict->ancestor)) < 0) || + (error = git_merge_file_input_from_index_entry( + &ours, data->repo, conflict->ours)) < 0 || + (error = git_merge_file_input_from_index_entry( + &theirs, data->repo, conflict->theirs)) < 0) + goto done; + + ancestor.label = NULL; + ours.label = data->opts.our_label ? data->opts.our_label : "ours"; + theirs.label = data->opts.their_label ? data->opts.their_label : "theirs"; + + /* If all the paths are identical, decorate the diff3 file with the branch + * names. Otherwise, append branch_name:path. + */ + if (conflict->ours && conflict->theirs && + strcmp(conflict->ours->path, conflict->theirs->path) != 0) { + + if ((error = conflict_entry_name( + &our_label, ours.label, conflict->ours->path)) < 0 || + (error = conflict_entry_name( + &their_label, theirs.label, conflict->theirs->path)) < 0) + goto done; + + ours.label = git_buf_cstr(&our_label); + theirs.label = git_buf_cstr(&their_label); + } + + if ((error = git_merge_files(&result, &ancestor, &ours, &theirs, 0)) < 0) + goto done; + + if (result.path == NULL || result.mode == 0) { + giterr_set(GITERR_CHECKOUT, "Could not merge contents of file"); + error = GIT_EMERGECONFLICT; + goto done; + } + + if ((error = checkout_merge_path(&path_workdir, data, conflict, &result)) < 0) + goto done; + + if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 && + (error = git_checkout__safe_for_update_only(git_buf_cstr(&path_workdir), result.mode)) <= 0) + goto done; + + if ((error = git_futils_mkpath2file(path_workdir.ptr, 0755)) < 0 || + (error = git_filebuf_open(&output, path_workdir.ptr, GIT_FILEBUF_DO_NOT_BUFFER)) < 0 || + (error = git_filebuf_write(&output, result.data, result.len)) < 0 || + (error = git_filebuf_commit(&output, result.mode)) < 0) + goto done; + +done: + git_buf_free(&our_label); + git_buf_free(&their_label); + + git_merge_file_input_free(&ancestor); + git_merge_file_input_free(&ours); + git_merge_file_input_free(&theirs); + git_merge_file_result_free(&result); + git_buf_free(&path_workdir); + git_buf_free(&path_suffixed); + + return error; +} + +static int checkout_create_conflicts(checkout_data *data) +{ + git_vector conflicts = GIT_VECTOR_INIT; + checkout_conflictdata *conflict; + size_t i; + int error = 0; + + git_vector_foreach(&data->conflicts, i, conflict) { + /* Both deleted: nothing to do */ + if (conflict->ours == NULL && conflict->theirs == NULL) + error = 0; + + else if ((data->strategy & GIT_CHECKOUT_USE_OURS) && + conflict->ours) + error = checkout_write_entry(data, conflict, conflict->ours); + else if ((data->strategy & GIT_CHECKOUT_USE_THEIRS) && + conflict->theirs) + error = checkout_write_entry(data, conflict, conflict->theirs); + + /* Ignore the other side of name collisions. */ + else if ((data->strategy & GIT_CHECKOUT_USE_OURS) && + !conflict->ours && conflict->name_collision) + error = 0; + else if ((data->strategy & GIT_CHECKOUT_USE_THEIRS) && + !conflict->theirs && conflict->name_collision) + error = 0; + + /* For modify/delete, name collisions and d/f conflicts, write + * the file (potentially with the name mangled. + */ + else if (conflict->ours != NULL && conflict->theirs == NULL) + error = checkout_write_entry(data, conflict, conflict->ours); + else if (conflict->ours == NULL && conflict->theirs != NULL) + error = checkout_write_entry(data, conflict, conflict->theirs); + + /* Add/add conflicts and rename 1->2 conflicts, write the + * ours/theirs sides (potentially name mangled). + */ + else if (conflict->one_to_two) + error = checkout_write_entries(data, conflict); + + /* If all sides are links, write the ours side */ + else if (S_ISLNK(conflict->ours->mode) && + S_ISLNK(conflict->theirs->mode)) + error = checkout_write_entry(data, conflict, conflict->ours); + /* Link/file conflicts, write the file side */ + else if (S_ISLNK(conflict->ours->mode)) + error = checkout_write_entry(data, conflict, conflict->theirs); + else if (S_ISLNK(conflict->theirs->mode)) + error = checkout_write_entry(data, conflict, conflict->ours); + + else + error = checkout_write_merge(data, conflict); + + if (error) + break; + + data->completed_steps++; + report_progress(data, + conflict->ours ? conflict->ours->path : + (conflict->theirs ? conflict->theirs->path : conflict->ancestor->path)); + } + + return error; +} + + static void checkout_data_clear(checkout_data *data) { checkout_conflictdata *conflict; @@ -1312,7 +2000,7 @@ int git_checkout_iterator( counts[CHECKOUT_ACTION__UPDATE_SUBMODULE] + counts[CHECKOUT_ACTION__UPDATE_CONFLICT]; - git_checkout__report_progress(&data, NULL); /* establish 0 baseline */ + report_progress(&data, NULL); /* establish 0 baseline */ /* To deal with some order dependencies, perform remaining checkout * in three passes: removes, then update blobs, then update submodules. @@ -1330,7 +2018,7 @@ int git_checkout_iterator( goto cleanup; if (counts[CHECKOUT_ACTION__UPDATE_CONFLICT] > 0 && - (error = git_checkout__conflicts(&data)) < 0) + (error = checkout_create_conflicts(&data)) < 0) goto cleanup; assert(data.completed_steps == data.total_steps); diff --git a/src/checkout.h b/src/checkout.h index d48e263e4..6d7186860 100644 --- a/src/checkout.h +++ b/src/checkout.h @@ -9,52 +9,9 @@ #include "git2/checkout.h" #include "iterator.h" -#include "pool.h" #define GIT_CHECKOUT__NOTIFY_CONFLICT_TREE (1u << 12) -typedef struct { - git_repository *repo; - git_diff_list *diff; - git_checkout_opts opts; - bool opts_free_baseline; - char *pfx; - git_index *index; - git_pool pool; - git_vector removes; - git_vector conflicts; - git_buf path; - size_t workdir_len; - unsigned int strategy; - int can_symlink; - bool reload_submodules; - size_t total_steps; - size_t completed_steps; -} checkout_data; - -typedef struct { - const git_index_entry *ancestor; - const git_index_entry *ours; - const git_index_entry *theirs; - - int name_collision:1, - directoryfile:1, - one_to_two:1; -} checkout_conflictdata; - -enum { - CHECKOUT_ACTION__NONE = 0, - CHECKOUT_ACTION__REMOVE = 1, - CHECKOUT_ACTION__UPDATE_BLOB = 2, - CHECKOUT_ACTION__UPDATE_SUBMODULE = 4, - CHECKOUT_ACTION__CONFLICT = 8, - CHECKOUT_ACTION__UPDATE_CONFLICT = 16, - CHECKOUT_ACTION__MAX = 16, - CHECKOUT_ACTION__DEFER_REMOVE = 32, - CHECKOUT_ACTION__REMOVE_AND_UPDATE = - (CHECKOUT_ACTION__UPDATE_BLOB | CHECKOUT_ACTION__REMOVE), -}; - /** * Update the working directory to match the target iterator. The * expected baseline value can be passed in via the checkout options @@ -64,23 +21,4 @@ extern int git_checkout_iterator( git_iterator *target, const git_checkout_opts *opts); -int git_checkout__safe_for_update_only( - const char *path, - mode_t expected_mode); - -int git_checkout__write_content( - checkout_data *data, - const git_oid *oid, - const char *path, - const char *hint_path, - unsigned int mode, - struct stat *st); - -void git_checkout__report_progress( - checkout_data *data, - const char *path); - -int git_checkout__get_conflicts(checkout_data *data, git_iterator *workdir, git_vector *pathspec); -int git_checkout__conflicts(checkout_data *data); - #endif diff --git a/src/checkout_conflicts.c b/src/checkout_conflicts.c deleted file mode 100644 index c39cb764e..000000000 --- a/src/checkout_conflicts.c +++ /dev/null @@ -1,659 +0,0 @@ -/* - * 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 - -#include "checkout.h" - -#include "vector.h" -#include "index.h" -#include "pathspec.h" -#include "merge_file.h" -#include "git2/repository.h" -#include "git2/types.h" -#include "git2/index.h" -#include "git2/sys/index.h" - -GIT_INLINE(int) checkout_idxentry_cmp( - const git_index_entry *a, - const git_index_entry *b) -{ - if (!a && !b) - return 0; - else if (!a && b) - return -1; - else if(a && !b) - return 1; - else - return strcmp(a->path, b->path); -} - -static int checkout_conflictdata_cmp(const void *a, const void *b) -{ - const checkout_conflictdata *ca = a; - const checkout_conflictdata *cb = b; - int diff; - - if ((diff = checkout_idxentry_cmp(ca->ancestor, cb->ancestor)) == 0 && - (diff = checkout_idxentry_cmp(ca->ours, cb->theirs)) == 0) - diff = checkout_idxentry_cmp(ca->theirs, cb->theirs); - - return diff; -} - -int checkout_conflictdata_empty(const git_vector *conflicts, size_t idx) -{ - checkout_conflictdata *conflict; - - if ((conflict = git_vector_get(conflicts, idx)) == NULL) - return -1; - - if (conflict->ancestor || conflict->ours || conflict->theirs) - return 0; - - git__free(conflict); - return 1; -} - -GIT_INLINE(bool) conflict_pathspec_match( - checkout_data *data, - git_iterator *workdir, - git_vector *pathspec, - const git_index_entry *ancestor, - const git_index_entry *ours, - const git_index_entry *theirs) -{ - /* if the pathspec matches ours *or* theirs, proceed */ - if (ours && git_pathspec__match(pathspec, ours->path, - (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, - git_iterator_ignore_case(workdir), NULL, NULL)) - return true; - - if (theirs && git_pathspec__match(pathspec, theirs->path, - (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, - git_iterator_ignore_case(workdir), NULL, NULL)) - return true; - - if (ancestor && git_pathspec__match(pathspec, ancestor->path, - (data->strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH) != 0, - git_iterator_ignore_case(workdir), NULL, NULL)) - return true; - - return false; -} - -static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, git_vector *pathspec) -{ - git_index_conflict_iterator *iterator = NULL; - const git_index_entry *ancestor, *ours, *theirs; - checkout_conflictdata *conflict; - int error = 0; - - if ((error = git_index_conflict_iterator_new(&iterator, data->index)) < 0) - goto done; - - data->conflicts._cmp = checkout_conflictdata_cmp; - - /* Collect the conflicts */ - while ((error = git_index_conflict_next(&ancestor, &ours, &theirs, iterator)) == 0) { - if (!conflict_pathspec_match(data, workdir, pathspec, ancestor, ours, theirs)) - continue; - - conflict = git__calloc(1, sizeof(checkout_conflictdata)); - GITERR_CHECK_ALLOC(conflict); - - conflict->ancestor = ancestor; - conflict->ours = ours; - conflict->theirs = theirs; - - git_vector_insert(&data->conflicts, conflict); - } - - if (error == GIT_ITEROVER) - error = 0; - -done: - git_index_conflict_iterator_free(iterator); - - return error; -} - -GIT_INLINE(int) checkout_conflicts_cmp_entry( - const char *path, - const git_index_entry *entry) -{ - return strcmp((const char *)path, entry->path); -} - -static int checkout_conflicts_cmp_ancestor(const void *p, const void *c) -{ - const char *path = p; - const checkout_conflictdata *conflict = c; - - if (!conflict->ancestor) - return 1; - - return checkout_conflicts_cmp_entry(path, conflict->ancestor); -} - -static checkout_conflictdata *checkout_conflicts_search_ancestor( - checkout_data *data, - const char *path) -{ - size_t pos; - - if (git_vector_bsearch2(&pos, &data->conflicts, checkout_conflicts_cmp_ancestor, path) < 0) - return NULL; - - return git_vector_get(&data->conflicts, pos); -} - -static checkout_conflictdata *checkout_conflicts_search_branch( - checkout_data *data, - const char *path) -{ - checkout_conflictdata *conflict; - size_t i; - - git_vector_foreach(&data->conflicts, i, conflict) { - int cmp = -1; - - if (conflict->ancestor) - break; - - if (conflict->ours) - cmp = checkout_conflicts_cmp_entry(path, conflict->ours); - else if (conflict->theirs) - cmp = checkout_conflicts_cmp_entry(path, conflict->theirs); - - if (cmp == 0) - return conflict; - } - - return NULL; -} - -static int checkout_conflicts_load_byname_entry( - checkout_conflictdata **ancestor_out, - checkout_conflictdata **ours_out, - checkout_conflictdata **theirs_out, - checkout_data *data, - const git_index_name_entry *name_entry) -{ - checkout_conflictdata *ancestor, *ours = NULL, *theirs = NULL; - int error = 0; - - *ancestor_out = NULL; - *ours_out = NULL; - *theirs_out = NULL; - - if (!name_entry->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"); - error = -1; - goto done; - } - - 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", - name_entry->ancestor); - error = -1; - goto done; - } - - if (name_entry->ours) { - if (strcmp(name_entry->ancestor, name_entry->ours) == 0) - ours = ancestor; - 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", - name_entry->ours); - error = -1; - goto done; - } - } - - if (name_entry->theirs) { - if (strcmp(name_entry->ancestor, name_entry->theirs) == 0) - theirs = ancestor; - else if (name_entry->ours && strcmp(name_entry->ours, name_entry->theirs) == 0) - theirs = ours; - 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", - name_entry->theirs); - error = -1; - goto done; - } - } - - *ancestor_out = ancestor; - *ours_out = ours; - *theirs_out = theirs; - -done: - return error; -} - -static int checkout_conflicts_coalesce_renames( - checkout_data *data) -{ - const git_index_name_entry *name_entry; - checkout_conflictdata *ancestor_conflict, *our_conflict, *their_conflict; - size_t i, names; - int error = 0; - - /* Juggle entries based on renames */ - names = git_index_name_entrycount(data->index); - - for (i = 0; i < names; i++) { - name_entry = git_index_name_get_byindex(data->index, i); - - if ((error = checkout_conflicts_load_byname_entry( - &ancestor_conflict, &our_conflict, &their_conflict, - data, name_entry)) < 0) - goto done; - - if (our_conflict && our_conflict != ancestor_conflict) { - ancestor_conflict->ours = our_conflict->ours; - our_conflict->ours = NULL; - - if (our_conflict->theirs) - our_conflict->name_collision = 1; - - if (our_conflict->name_collision) - ancestor_conflict->name_collision = 1; - } - - if (their_conflict && their_conflict != ancestor_conflict) { - ancestor_conflict->theirs = their_conflict->theirs; - their_conflict->theirs = NULL; - - if (their_conflict->ours) - their_conflict->name_collision = 1; - - if (their_conflict->name_collision) - ancestor_conflict->name_collision = 1; - } - - if (our_conflict && our_conflict != ancestor_conflict && - their_conflict && their_conflict != ancestor_conflict) - ancestor_conflict->one_to_two = 1; - } - - git_vector_remove_matching(&data->conflicts, checkout_conflictdata_empty); - -done: - return error; -} - -GIT_INLINE(void) path_equal_or_prefixed( - bool *path_eq, - bool *path_prefixed, - const char *parent, - const char *child) -{ - const char *p, *c; - - *path_eq = 0; - *path_prefixed = 0; - - for (p = parent, c = child; *p && *c; p++, c++) { - if (*p != *c) - return; - } - - if (!*p) - *path_prefixed = (*c == '/'); - - if (!*p && !*c) - *path_eq = 1; -} - -static int checkout_conflicts_mark_directoryfile( - checkout_data *data) -{ - checkout_conflictdata *conflict; - const git_index_entry *entry; - size_t i, j, len; - const char *path; - bool eq, prefixed; - int error = 0; - - len = git_index_entrycount(data->index); - - /* Find d/f conflicts */ - git_vector_foreach(&data->conflicts, i, conflict) { - if ((conflict->ours && conflict->theirs) || - (!conflict->ours && !conflict->theirs)) - continue; - - path = conflict->ours ? - conflict->ours->path : conflict->theirs->path; - - if ((error = git_index_find(&j, data->index, path)) < 0) { - if (error == GIT_ENOTFOUND) - giterr_set(GITERR_INDEX, - "Index inconsistency, could not find entry for expected conflict '%s'", path); - - goto done; - } - - for (; j < len; j++) { - if ((entry = git_index_get_byindex(data->index, j)) == NULL) { - giterr_set(GITERR_INDEX, - "Index inconsistency, truncated index while loading expected conflict '%s'", path); - error = -1; - goto done; - } - - path_equal_or_prefixed(&eq, &prefixed, path, entry->path); - - if (eq) - continue; - - if (prefixed) - conflict->directoryfile = 1; - - break; - } - } - -done: - return error; -} - -static int conflict_entry_name( - git_buf *out, - const char *side_name, - const char *filename) -{ - if (git_buf_puts(out, side_name) < 0 || - git_buf_putc(out, ':') < 0 || - git_buf_puts(out, filename) < 0) - return -1; - - return 0; -} - -static int checkout_path_suffixed(git_buf *path, const char *suffix) -{ - size_t path_len; - int i = 0, error = 0; - - if ((error = git_buf_putc(path, '~')) < 0 || (error = git_buf_puts(path, suffix)) < 0) - return -1; - - path_len = git_buf_len(path); - - while (git_path_exists(git_buf_cstr(path)) && i < INT_MAX) { - git_buf_truncate(path, path_len); - - if ((error = git_buf_putc(path, '_')) < 0 || - (error = git_buf_printf(path, "%d", i)) < 0) - return error; - - i++; - } - - if (i == INT_MAX) { - git_buf_truncate(path, path_len); - - giterr_set(GITERR_CHECKOUT, "Could not write '%s': working directory file exists", path); - return GIT_EEXISTS; - } - - return 0; -} - -static int checkout_write_entry( - checkout_data *data, - checkout_conflictdata *conflict, - const git_index_entry *side) -{ - const char *hint_path = NULL, *suffix; - struct stat st; - int error; - - assert (side == conflict->ours || side == conflict->theirs); - - git_buf_truncate(&data->path, data->workdir_len); - if (git_buf_puts(&data->path, side->path) < 0) - return -1; - - if ((conflict->name_collision || conflict->directoryfile) && - (data->strategy & GIT_CHECKOUT_USE_OURS) == 0 && - (data->strategy & GIT_CHECKOUT_USE_THEIRS) == 0) { - - if (side == conflict->ours) - suffix = data->opts.our_label ? data->opts.our_label : - "ours"; - else - suffix = data->opts.their_label ? data->opts.their_label : - "theirs"; - - if (checkout_path_suffixed(&data->path, suffix) < 0) - return -1; - - hint_path = side->path; - } - - if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 && - (error = git_checkout__safe_for_update_only(git_buf_cstr(&data->path), side->mode)) <= 0) - return error; - - return git_checkout__write_content(data, - &side->oid, git_buf_cstr(&data->path), hint_path, side->mode, &st); -} - -static int checkout_write_entries( - checkout_data *data, - checkout_conflictdata *conflict) -{ - int error = 0; - - if ((error = checkout_write_entry(data, conflict, conflict->ours)) >= 0) - error = checkout_write_entry(data, conflict, conflict->theirs); - - return error; -} - -static int checkout_merge_path( - git_buf *out, - checkout_data *data, - checkout_conflictdata *conflict, - git_merge_file_result *result) -{ - const char *our_label_raw, *their_label_raw, *suffix; - int error = 0; - - if ((error = git_buf_joinpath(out, git_repository_workdir(data->repo), result->path)) < 0) - return error; - - /* Most conflicts simply use the filename in the index */ - if (!conflict->name_collision) - return 0; - - /* Rename 2->1 conflicts need the branch name appended */ - our_label_raw = data->opts.our_label ? data->opts.our_label : "ours"; - their_label_raw = data->opts.their_label ? data->opts.their_label : "theirs"; - suffix = strcmp(result->path, conflict->ours->path) == 0 ? our_label_raw : their_label_raw; - - if ((error = checkout_path_suffixed(out, suffix)) < 0) - return error; - - return 0; -} - -static int checkout_write_merge( - checkout_data *data, - checkout_conflictdata *conflict) -{ - git_buf our_label = GIT_BUF_INIT, their_label = GIT_BUF_INIT, - path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT; - git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT, - ours = GIT_MERGE_FILE_INPUT_INIT, - theirs = GIT_MERGE_FILE_INPUT_INIT; - git_merge_file_result result = GIT_MERGE_FILE_RESULT_INIT; - git_filebuf output = GIT_FILEBUF_INIT; - int error = 0; - - if ((conflict->ancestor && - (error = git_merge_file_input_from_index_entry( - &ancestor, data->repo, conflict->ancestor)) < 0) || - (error = git_merge_file_input_from_index_entry( - &ours, data->repo, conflict->ours)) < 0 || - (error = git_merge_file_input_from_index_entry( - &theirs, data->repo, conflict->theirs)) < 0) - goto done; - - ancestor.label = NULL; - ours.label = data->opts.our_label ? data->opts.our_label : "ours"; - theirs.label = data->opts.their_label ? data->opts.their_label : "theirs"; - - /* If all the paths are identical, decorate the diff3 file with the branch - * names. Otherwise, append branch_name:path. - */ - if (conflict->ours && conflict->theirs && - strcmp(conflict->ours->path, conflict->theirs->path) != 0) { - - if ((error = conflict_entry_name( - &our_label, ours.label, conflict->ours->path)) < 0 || - (error = conflict_entry_name( - &their_label, theirs.label, conflict->theirs->path)) < 0) - goto done; - - ours.label = git_buf_cstr(&our_label); - theirs.label = git_buf_cstr(&their_label); - } - - if ((error = git_merge_files(&result, &ancestor, &ours, &theirs, 0)) < 0) - goto done; - - if (result.path == NULL || result.mode == 0) { - giterr_set(GITERR_CHECKOUT, "Could not merge contents of file"); - error = GIT_EMERGECONFLICT; - goto done; - } - - if ((error = checkout_merge_path(&path_workdir, data, conflict, &result)) < 0) - goto done; - - if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 && - (error = git_checkout__safe_for_update_only(git_buf_cstr(&path_workdir), result.mode)) <= 0) - goto done; - - if ((error = git_futils_mkpath2file(path_workdir.ptr, 0755)) < 0 || - (error = git_filebuf_open(&output, path_workdir.ptr, GIT_FILEBUF_DO_NOT_BUFFER)) < 0 || - (error = git_filebuf_write(&output, result.data, result.len)) < 0 || - (error = git_filebuf_commit(&output, result.mode)) < 0) - goto done; - -done: - git_buf_free(&our_label); - git_buf_free(&their_label); - - git_merge_file_input_free(&ancestor); - git_merge_file_input_free(&ours); - git_merge_file_input_free(&theirs); - git_merge_file_result_free(&result); - git_buf_free(&path_workdir); - git_buf_free(&path_suffixed); - - return error; -} - -int git_checkout__get_conflicts(checkout_data *data, git_iterator *workdir, git_vector *pathspec) -{ - int error = 0; - - if (data->strategy & GIT_CHECKOUT_SKIP_UNMERGED) - return 0; - - if ((error = checkout_conflicts_load(data, workdir, pathspec)) < 0 || - (error = checkout_conflicts_coalesce_renames(data)) < 0 || - (error = checkout_conflicts_mark_directoryfile(data)) < 0) - goto done; - -done: - return error; -} - -int git_checkout__conflicts(checkout_data *data) -{ - git_vector conflicts = GIT_VECTOR_INIT; - checkout_conflictdata *conflict; - size_t i; - int error = 0; - - git_vector_foreach(&data->conflicts, i, conflict) { - /* Both deleted: nothing to do */ - if (conflict->ours == NULL && conflict->theirs == NULL) - error = 0; - - else if ((data->strategy & GIT_CHECKOUT_USE_OURS) && - conflict->ours) - error = checkout_write_entry(data, conflict, conflict->ours); - else if ((data->strategy & GIT_CHECKOUT_USE_THEIRS) && - conflict->theirs) - error = checkout_write_entry(data, conflict, conflict->theirs); - - /* Ignore the other side of name collisions. */ - else if ((data->strategy & GIT_CHECKOUT_USE_OURS) && - !conflict->ours && conflict->name_collision) - error = 0; - else if ((data->strategy & GIT_CHECKOUT_USE_THEIRS) && - !conflict->theirs && conflict->name_collision) - error = 0; - - /* For modify/delete, name collisions and d/f conflicts, write - * the file (potentially with the name mangled. - */ - else if (conflict->ours != NULL && conflict->theirs == NULL) - error = checkout_write_entry(data, conflict, conflict->ours); - else if (conflict->ours == NULL && conflict->theirs != NULL) - error = checkout_write_entry(data, conflict, conflict->theirs); - - /* Add/add conflicts and rename 1->2 conflicts, write the - * ours/theirs sides (potentially name mangled). - */ - else if (conflict->one_to_two) - error = checkout_write_entries(data, conflict); - - /* If all sides are links, write the ours side */ - else if (S_ISLNK(conflict->ours->mode) && - S_ISLNK(conflict->theirs->mode)) - error = checkout_write_entry(data, conflict, conflict->ours); - /* Link/file conflicts, write the file side */ - else if (S_ISLNK(conflict->ours->mode)) - error = checkout_write_entry(data, conflict, conflict->theirs); - else if (S_ISLNK(conflict->theirs->mode)) - error = checkout_write_entry(data, conflict, conflict->ours); - - else - error = checkout_write_merge(data, conflict); - - if (error) - break; - - data->completed_steps++; - git_checkout__report_progress(data, - conflict->ours ? conflict->ours->path : - (conflict->theirs ? conflict->theirs->path : conflict->ancestor->path)); - } - - return error; -} -- cgit v1.2.1 From c929d6b727cb35a681152ae2c7d6dfbaf971f829 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 9 Oct 2013 18:26:42 -0400 Subject: Move path prefixed help to path.h --- src/checkout.c | 51 +++++++++++++-------------------------------------- src/path.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/checkout.c b/src/checkout.c index c226f4342..85a817608 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -27,6 +27,7 @@ #include "pathspec.h" #include "buf_text.h" #include "merge_file.h" +#include "path.h" /* See docs/checkout-internals.md for more information */ @@ -887,29 +888,6 @@ done: return error; } -GIT_INLINE(void) path_equal_or_prefixed( - bool *path_eq, - bool *path_prefixed, - const char *parent, - const char *child) -{ - const char *p, *c; - - *path_eq = 0; - *path_prefixed = 0; - - for (p = parent, c = child; *p && *c; p++, c++) { - if (*p != *c) - return; - } - - if (!*p) - *path_prefixed = (*c == '/'); - - if (!*p && !*c) - *path_eq = 1; -} - static int checkout_conflicts_mark_directoryfile( checkout_data *data) { @@ -917,8 +895,7 @@ static int checkout_conflicts_mark_directoryfile( const git_index_entry *entry; size_t i, j, len; const char *path; - bool eq, prefixed; - int error = 0; + int prefixed, error = 0; len = git_index_entrycount(data->index); @@ -947,12 +924,12 @@ static int checkout_conflicts_mark_directoryfile( goto done; } - path_equal_or_prefixed(&eq, &prefixed, path, entry->path); + prefixed = git_path_equal_or_prefixed(path, entry->path); - if (eq) + if (prefixed == GIT_PATH_EQUAL) continue; - if (prefixed) + if (prefixed == GIT_PATH_PREFIX) conflict->directoryfile = 1; break; @@ -1055,8 +1032,6 @@ static int checkout_get_actions( counts[CHECKOUT_ACTION__UPDATE_CONFLICT] = git_vector_length(&data->conflicts); - /* HERE */ - git_pathspec__vfree(&pathspec); git_pool_clear(&pathpool); @@ -1257,7 +1232,7 @@ static int checkout_submodule( return checkout_submodule_update_index(data, file); } -void report_progress( +static void report_progress( checkout_data *data, const char *path) { @@ -1267,7 +1242,7 @@ void report_progress( data->opts.progress_payload); } -int git_checkout__safe_for_update_only(const char *path, mode_t expected_mode) +static int checkout_safe_for_update_only(const char *path, mode_t expected_mode) { struct stat st; @@ -1288,7 +1263,7 @@ int git_checkout__safe_for_update_only(const char *path, mode_t expected_mode) return 0; } -int git_checkout__write_content( +static int checkout_write_content( checkout_data *data, const git_oid *oid, const char *full_path, @@ -1337,13 +1312,13 @@ static int checkout_blob( return -1; if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0) { - int rval = git_checkout__safe_for_update_only( + int rval = checkout_safe_for_update_only( git_buf_cstr(&data->path), file->mode); if (rval <= 0) return rval; } - error = git_checkout__write_content( + error = checkout_write_content( data, &file->oid, git_buf_cstr(&data->path), NULL, file->mode, &st); /* update the index unless prevented */ @@ -1593,10 +1568,10 @@ static int checkout_write_entry( } if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 && - (error = git_checkout__safe_for_update_only(git_buf_cstr(&data->path), side->mode)) <= 0) + (error = checkout_safe_for_update_only(git_buf_cstr(&data->path), side->mode)) <= 0) return error; - return git_checkout__write_content(data, + return checkout_write_content(data, &side->oid, git_buf_cstr(&data->path), hint_path, side->mode, &st); } @@ -1694,7 +1669,7 @@ static int checkout_write_merge( goto done; if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 && - (error = git_checkout__safe_for_update_only(git_buf_cstr(&path_workdir), result.mode)) <= 0) + (error = checkout_safe_for_update_only(git_buf_cstr(&path_workdir), result.mode)) <= 0) goto done; if ((error = git_futils_mkpath2file(path_workdir.ptr, 0755)) < 0 || diff --git a/src/path.h b/src/path.h index eaf94d486..17f4f7726 100644 --- a/src/path.h +++ b/src/path.h @@ -358,6 +358,34 @@ extern int git_path_dirload_with_stat( const char *end_stat, git_vector *contents); +enum { GIT_PATH_NOTEQUAL = 0, GIT_PATH_EQUAL = 1, GIT_PATH_PREFIX = 2 }; + +/* + * Determines if a path is equal to or potentially a child of another. + * @param parent The possible parent + * @param child The possible child + */ +GIT_INLINE(int) git_path_equal_or_prefixed( + const char *parent, + const char *child) +{ + const char *p = parent, *c = child; + + while (*p && *c) { + if (*p++ != *c++) + return GIT_PATH_NOTEQUAL; + } + + if (*p != '\0') + return GIT_PATH_NOTEQUAL; + if (*c == '\0') + return GIT_PATH_EQUAL; + if (*c == '/') + return GIT_PATH_PREFIX; + + return GIT_PATH_NOTEQUAL; +} + /* translate errno to libgit2 error code and set error message */ extern int git_path_set_error( int errno_value, const char *path, const char *action); -- cgit v1.2.1 From 20b5d300dce48ce34c16bf39752fae9a7d05f021 Mon Sep 17 00:00:00 2001 From: Haneef Mubarak Date: Thu, 17 Oct 2013 00:28:08 -0700 Subject: slightly clarified the "license" portion of `README.md" + formatting all over There are commercial open source applications, hence proprietary seems to be a better term. Also: - Trimmed header `=`'s to match text length - made libgit2 stand out everywhere - pretty printing links - irc link for those with the correct setup --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 9222f3dcf..f6d7ccbc8 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,21 @@ libgit2 - the Git linkable library -====================== +================================== [![Build Status](https://secure.travis-ci.org/libgit2/libgit2.png?branch=development)](http://travis-ci.org/libgit2/libgit2) -libgit2 is a portable, pure C implementation of the Git core methods provided as a +`libgit2` is a portable, pure C implementation of the Git core methods provided as a re-entrant linkable library with a solid API, allowing you to write native speed custom Git applications in any language with bindings. -libgit2 is licensed under a **very permissive license** (GPLv2 with a special Linking Exception). +`libgit2` is licensed under a **very permissive license** (GPLv2 with a special Linking Exception). This basically means that you can link it (unmodified) with any kind of software without having to release its source code. -* Website: +* Website: [libgit2.github.com](http://libgit2.github.com) * StackOverflow Tag: [libgit2](http://stackoverflow.com/questions/tagged/libgit2) -* Issues: +* Issues: [GitHub Issues](https://github.com/libgit2/libgit2/issues) (Right here!) * API documentation: -* IRC: #libgit2 on irc.freenode.net. +* IRC: [#libgit2](irc://irc.freenode.net/libgit2) on irc.freenode.net. * Mailing list: The libgit2 mailing list was traditionally hosted in Librelist but has been deprecated. We encourage you to [use StackOverflow](http://stackoverflow.com/questions/tagged/libgit2) instead for any questions regarding @@ -25,9 +25,9 @@ release its source code. What It Can Do -================================== +============== -libgit2 is already very usable and is being used in production for many applications including the GitHub.com site, in Plastic SCM +`libgit2` is already very usable and is being used in production for many applications including the GitHub.com site, in Plastic SCM and also powering Microsoft's Visual Studio tools for Git. The library provides: * SHA conversions, formatting and shortening @@ -46,12 +46,12 @@ and also powering Microsoft's Visual Studio tools for Git. The library provides Building libgit2 - Using CMake ============================== -libgit2 builds cleanly on most platforms without any external dependencies. +`libgit2` builds cleanly on most platforms without any external dependencies. Under Unix-like systems, like Linux, \*BSD and Mac OS X, libgit2 expects `pthreads` to be available; they should be installed by default on all systems. Under Windows, libgit2 uses the native Windows API for threading. -The libgit2 library is built using CMake 2.6+ () on all platforms. +The `libgit2` library is built using `CMake 2.6+` () on all platforms. On most systems you can build the library using the following commands @@ -187,9 +187,9 @@ Check the [contribution guidelines](CONTRIBUTING.md). License ================================== -libgit2 is under GPL2 **with linking exemption**. This means you -can link to the library with any program, commercial, open source or -other. However, you cannot modify libgit2 and distribute it without +`libgit2` is under GPL2 **with linking exemption**. This means you +can link to the library with any program, proprietary or open source; paid +or gratis. However, you cannot modify libgit2 and distribute it without supplying the source. See the COPYING file for the full license text. -- cgit v1.2.1 From e5e2710b781a3ebafceb2605f75182637ecfef0b Mon Sep 17 00:00:00 2001 From: Haneef Mubarak Date: Thu, 17 Oct 2013 01:52:20 -0700 Subject: slightly clarified the "license" portion of `README.md" + formatting all over added the second change suggested by @nulltoken (with two extra words :) ) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f6d7ccbc8..1f5204d13 100644 --- a/README.md +++ b/README.md @@ -188,7 +188,7 @@ Check the [contribution guidelines](CONTRIBUTING.md). License ================================== `libgit2` is under GPL2 **with linking exemption**. This means you -can link to the library with any program, proprietary or open source; paid +can can link to and use the library from any program, proprietary or open source; paid or gratis. However, you cannot modify libgit2 and distribute it without supplying the source. -- cgit v1.2.1 From caf9334115274e48b7eb9c96001037cebc57ad7a Mon Sep 17 00:00:00 2001 From: Haneef Mubarak Date: Thu, 17 Oct 2013 16:01:43 -0700 Subject: slightly clarified the "license" portion of `README.md" + formatting all over fixed typo `can can` -> `can` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f5204d13..0d735c397 100644 --- a/README.md +++ b/README.md @@ -188,7 +188,7 @@ Check the [contribution guidelines](CONTRIBUTING.md). License ================================== `libgit2` is under GPL2 **with linking exemption**. This means you -can can link to and use the library from any program, proprietary or open source; paid +can link to and use the library from any program, proprietary or open source; paid or gratis. However, you cannot modify libgit2 and distribute it without supplying the source. -- cgit v1.2.1 From 74a627f04528f7e02f69d8d7947820582ce7ca15 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 21 Oct 2013 09:07:19 -0700 Subject: Tweak to git_diff_delta structure for nfiles While the base git_diff_delta structure always contains two files, when we introduce conflict data, it will be helpful to have an indicator when an additional file is involved. --- include/git2/diff.h | 5 +++-- src/diff.c | 2 ++ src/diff_tform.c | 47 +++++++++++++++++++++++++++-------------------- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/include/git2/diff.h b/include/git2/diff.h index fd79ccf04..f1572cbd5 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -292,8 +292,9 @@ typedef struct { */ typedef struct { git_delta_t status; - uint32_t similarity; /**< for RENAMED and COPIED, value 0-100 */ - uint32_t flags; + uint32_t flags; /**< git_diff_flag_t values */ + uint16_t similarity; /**< for RENAMED and COPIED, value 0-100 */ + uint16_t nfiles; /**< number of files in this delta */ git_diff_file old_file; git_diff_file new_file; } git_diff_delta; diff --git a/src/diff.c b/src/diff.c index 8dc704d58..37bc737d6 100644 --- a/src/diff.c +++ b/src/diff.c @@ -90,6 +90,7 @@ static int diff_delta__from_one( /* This fn is just for single-sided diffs */ assert(status != GIT_DELTA_MODIFIED); + delta->nfiles = 1; if (delta->status == GIT_DELTA_DELETED) { delta->old_file.mode = entry->mode; @@ -148,6 +149,7 @@ static int diff_delta__from_two( delta = diff_delta__alloc(diff, status, canonical_path); GITERR_CHECK_ALLOC(delta); + delta->nfiles = 2; git_oid_cpy(&delta->old_file.oid, &old_entry->oid); delta->old_file.size = old_entry->file_size; diff --git a/src/diff_tform.c b/src/diff_tform.c index 92771847c..9461ca2c8 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -350,6 +350,7 @@ static int apply_splits_and_deletes( goto on_error; deleted->status = GIT_DELTA_DELETED; + deleted->nfiles = 1; memset(&deleted->new_file, 0, sizeof(deleted->new_file)); deleted->new_file.path = deleted->old_file.path; deleted->new_file.flags |= GIT_DIFF_FLAG_VALID_OID; @@ -361,6 +362,7 @@ static int apply_splits_and_deletes( delta->status = GIT_DELTA_UNTRACKED; else delta->status = GIT_DELTA_ADDED; + delta->nfiles = 1; memset(&delta->old_file, 0, sizeof(delta->old_file)); delta->old_file.path = delta->new_file.path; delta->old_file.flags |= GIT_DIFF_FLAG_VALID_OID; @@ -612,7 +614,7 @@ static int calc_self_similarity( return error; if (similarity >= 0) { - delta->similarity = (uint32_t)similarity; + delta->similarity = (uint16_t)similarity; delta->flags |= GIT_DIFF_FLAG__HAS_SELF_SIMILARITY; } @@ -745,17 +747,18 @@ GIT_INLINE(bool) delta_is_new_only(git_diff_delta *delta) } GIT_INLINE(void) delta_make_rename( - git_diff_delta *to, const git_diff_delta *from, uint32_t similarity) + git_diff_delta *to, const git_diff_delta *from, uint16_t similarity) { to->status = GIT_DELTA_RENAMED; to->similarity = similarity; + to->nfiles = 2; memcpy(&to->old_file, &from->old_file, sizeof(to->old_file)); to->flags &= ~GIT_DIFF_FLAG__TO_SPLIT; } typedef struct { - uint32_t idx; - uint32_t similarity; + size_t idx; + uint16_t similarity; } diff_find_match; int git_diff_find_similar( @@ -763,7 +766,8 @@ int git_diff_find_similar( const git_diff_find_options *given_opts) { size_t s, t; - int error = 0, similarity; + int error = 0, result; + uint16_t similarity; git_diff_delta *src, *tgt; git_diff_find_options opts; size_t num_deltas, num_srcs = 0, num_tgts = 0; @@ -839,17 +843,18 @@ find_best_matches: /* calculate similarity for this pair and find best match */ if (s == t) - similarity = -1; /* don't measure self-similarity here */ + result = -1; /* don't measure self-similarity here */ else if ((error = similarity_measure( - &similarity, diff, &opts, sigcache, 2 * s, 2 * t + 1)) < 0) + &result, diff, &opts, sigcache, 2 * s, 2 * t + 1)) < 0) goto cleanup; - if (similarity < 0) + if (result < 0) continue; + similarity = (uint16_t)result; /* is this a better rename? */ - if (tgt2src[t].similarity < (uint32_t)similarity && - src2tgt[s].similarity < (uint32_t)similarity) + if (tgt2src[t].similarity < similarity && + src2tgt[s].similarity < similarity) { /* eject old mapping */ if (src2tgt[s].similarity > 0) { @@ -862,18 +867,18 @@ find_best_matches: } /* write new mapping */ - tgt2src[t].idx = (uint32_t)s; - tgt2src[t].similarity = (uint32_t)similarity; - src2tgt[s].idx = (uint32_t)t; - src2tgt[s].similarity = (uint32_t)similarity; + tgt2src[t].idx = s; + tgt2src[t].similarity = similarity; + src2tgt[s].idx = t; + src2tgt[s].similarity = similarity; } /* keep best absolute match for copies */ if (tgt2src_copy != NULL && - tgt2src_copy[t].similarity < (uint32_t)similarity) + tgt2src_copy[t].similarity < similarity) { - tgt2src_copy[t].idx = (uint32_t)s; - tgt2src_copy[t].similarity = (uint32_t)similarity; + tgt2src_copy[t].idx = s; + tgt2src_copy[t].similarity = similarity; } if (++tried_srcs >= num_srcs) @@ -943,7 +948,7 @@ find_best_matches: delta_make_rename(tgt, src, best_match->similarity); num_rewrites--; - src->status = GIT_DELTA_DELETED; + assert(src->status == GIT_DELTA_DELETED); memcpy(&src->old_file, &swap, sizeof(src->old_file)); memset(&src->new_file, 0, sizeof(src->new_file)); src->new_file.path = src->old_file.path; @@ -953,7 +958,7 @@ find_best_matches: if (src2tgt[t].similarity > 0 && src2tgt[t].idx > t) { /* what used to be at src t is now at src s */ - tgt2src[src2tgt[t].idx].idx = (uint32_t)s; + tgt2src[src2tgt[t].idx].idx = s; } } } @@ -969,6 +974,7 @@ find_best_matches: src->status = (diff->new_src == GIT_ITERATOR_TYPE_WORKDIR) ? GIT_DELTA_UNTRACKED : GIT_DELTA_ADDED; + src->nfiles = 1; memset(&src->old_file, 0, sizeof(src->old_file)); src->old_file.path = src->new_file.path; src->old_file.flags |= GIT_DIFF_FLAG_VALID_OID; @@ -1006,7 +1012,7 @@ find_best_matches: /* otherwise, if we just overwrote a source, update mapping */ else if (src2tgt[t].similarity > 0 && src2tgt[t].idx > t) { /* what used to be at src t is now at src s */ - tgt2src[src2tgt[t].idx].idx = (uint32_t)s; + tgt2src[src2tgt[t].idx].idx = s; } num_updates++; @@ -1026,6 +1032,7 @@ find_best_matches: tgt->status = GIT_DELTA_COPIED; tgt->similarity = best_match->similarity; + tgt->nfiles = 2; memcpy(&tgt->old_file, &src->old_file, sizeof(tgt->old_file)); num_updates++; -- cgit v1.2.1 From 2648dc1a06f5431552ae272432207d456232c1e5 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 21 Oct 2013 11:03:31 -0500 Subject: Allowed credential types should be a bitfield --- include/git2/transport.h | 25 +++++++++++++++---------- src/transports/cred.c | 2 +- src/transports/ssh.c | 3 ++- tests-clar/online/push.c | 31 +++++++++++++++++++++---------- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/include/git2/transport.h b/include/git2/transport.h index 9901b15de..065b31820 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -28,11 +28,16 @@ GIT_BEGIN_DECL *** Begin interface for credentials acquisition *** */ +/** Authentication type requested */ typedef enum { /* git_cred_userpass_plaintext */ - GIT_CREDTYPE_USERPASS_PLAINTEXT = 1, - GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE = 2, - GIT_CREDTYPE_SSH_PUBLICKEY = 3, + GIT_CREDTYPE_USERPASS_PLAINTEXT = (1u << 0), + + /* git_cred_ssh_keyfile_passphrase */ + GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE = (1u << 1), + + /* git_cred_ssh_publickey */ + GIT_CREDTYPE_SSH_PUBLICKEY = (1u << 2), } git_credtype_t; /* The base structure for all credential types */ @@ -56,7 +61,7 @@ typedef LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*git_cred_sign_callback)); typedef int (*git_cred_sign_callback)(void *, ...); #endif -/* A ssh key file and passphrase */ +/* An ssh key file and passphrase */ typedef struct git_cred_ssh_keyfile_passphrase { git_cred parent; char *username; @@ -65,7 +70,7 @@ typedef struct git_cred_ssh_keyfile_passphrase { char *passphrase; } git_cred_ssh_keyfile_passphrase; -/* A ssh public key and authentication callback */ +/* An ssh public key and authentication callback */ typedef struct git_cred_ssh_publickey { git_cred parent; char *username; @@ -123,17 +128,17 @@ GIT_EXTERN(int) git_cred_ssh_keyfile_passphrase_new( * @param username username to use to authenticate * @param publickey The bytes of the public key. * @param publickey_len The length of the public key in bytes. - * @param sign_fn The callback method for authenticating. - * @param sign_data The abstract data sent to the sign_callback method. + * @param sign_fn The callback method to sign the data during the challenge. + * @param sign_data The data to pass to the sign function. * @return 0 for success or an error code for failure */ GIT_EXTERN(int) git_cred_ssh_publickey_new( git_cred **out, const char *username, const char *publickey, - size_t publickey_len, - git_cred_sign_callback sign_fn, - void *sign_data); + size_t publickey_len, + git_cred_sign_callback sign_fn, + void *sign_data); /** * Signature of a function which acquires a credential object. diff --git a/src/transports/cred.c b/src/transports/cred.c index 35aaf4f91..79b17e88d 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -58,7 +58,7 @@ int git_cred_userpass_plaintext_new( { git_cred_userpass_plaintext *c; - assert(cred); + assert(cred && username && password); c = git__malloc(sizeof(git_cred_userpass_plaintext)); GITERR_CHECK_ALLOC(c); diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 62f3f0bbf..647211f63 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -349,7 +349,8 @@ static int _git_ssh_setup_conn( if (t->owner->cred_acquire_cb( &t->cred, t->owner->url, user, GIT_CREDTYPE_USERPASS_PLAINTEXT | - GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE, + GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE | + GIT_CREDTYPE_SSH_PUBLICKEY, t->owner->cred_acquire_payload) < 0) goto on_error; diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 957cef7ca..d3d23740f 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -37,23 +37,34 @@ static git_oid _tag_lightweight; static git_oid _tag_tag; static int cred_acquire_cb( - git_cred **cred, - const char *url, - const char *user_from_url, - unsigned int allowed_types, - void *payload) + git_cred **cred, + const char *url, + const char *user_from_url, + unsigned int allowed_types, + void *payload) { GIT_UNUSED(url); GIT_UNUSED(user_from_url); + GIT_UNUSED(payload); - if (GIT_CREDTYPE_SSH_PUBLICKEY & allowed_types) + if (GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE & allowed_types) { + if (!_remote_user || !_remote_ssh_pubkey || !_remote_ssh_key || !_remote_ssh_passphrase) { + printf("GITTEST_REMOTE_USER, GITTEST_REMOTE_SSH_PUBKEY, GITTEST_REMOTE_SSH_KEY and GITTEST_REMOTE_SSH_PASSPHRASE must be set\n"); + return -1; + } return git_cred_ssh_keyfile_passphrase_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase); + } + + if (GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) { + if (!_remote_user || !_remote_pass) { + printf("GITTEST_REMOTE_USER and GITTEST_REMOTE_PASS must be set\n"); + return -1; + } - if ((GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) == 0 || - git_cred_userpass_plaintext_new(cred, _remote_user, _remote_pass) < 0) - return -1; + return git_cred_userpass_plaintext_new(cred, _remote_user, _remote_pass); + } - return 0; + return -1; } typedef struct { -- cgit v1.2.1 From 3b5f795446601868d52d09ebac70ae3b7aee157a Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 21 Oct 2013 13:42:42 -0700 Subject: Create git_diff_line and extend git_diff_hunk Instead of having functions with so very many parameters to pass hunk and line data, this takes the existing git_diff_hunk struct and extends it with more hunk data, plus adds a git_diff_line. Those structs are used to pass back hunk and line data instead of the old APIs that took tons of parameters. Some work that was previously only being done for git_diff_patch creation (scanning the diff content for exact line counts) is now done for all callbacks, but the performance difference should not be noticable. --- examples/diff.c | 28 +++--- examples/log.c | 16 +-- include/git2/diff.h | 31 ++++-- include/git2/patch.h | 17 +--- src/diff_patch.c | 133 +++++------------------- src/diff_print.c | 93 +++++++++-------- src/diff_xdiff.c | 81 +++++++++++++-- tests-clar/diff/blob.c | 20 ++-- tests-clar/diff/diff_helpers.c | 58 ++++------- tests-clar/diff/diff_helpers.h | 10 +- tests-clar/diff/diffiter.c | 28 ++---- tests-clar/diff/patch.c | 223 +++++++++++++++++++---------------------- tests-clar/diff/tree.c | 19 ++-- tests-clar/diff/workdir.c | 21 ++-- 14 files changed, 360 insertions(+), 418 deletions(-) diff --git a/examples/diff.c b/examples/diff.c index 2542f4269..694621f1e 100644 --- a/examples/diff.c +++ b/examples/diff.c @@ -45,25 +45,23 @@ char *colors[] = { static int printer( const git_diff_delta *delta, - const git_diff_hunk *range, - char usage, - const char *line, - size_t line_len, + const git_diff_hunk *hunk, + const git_diff_line *line, void *data) { int *last_color = data, color = 0; - (void)delta; (void)range; (void)line_len; + (void)delta; (void)hunk; if (*last_color >= 0) { - switch (usage) { - case GIT_DIFF_LINE_ADDITION: color = 3; break; - case GIT_DIFF_LINE_DELETION: color = 2; break; + switch (line->origin) { + case GIT_DIFF_LINE_ADDITION: color = 3; break; + case GIT_DIFF_LINE_DELETION: color = 2; break; case GIT_DIFF_LINE_ADD_EOFNL: color = 3; break; case GIT_DIFF_LINE_DEL_EOFNL: color = 2; break; - case GIT_DIFF_LINE_FILE_HDR: color = 1; break; - case GIT_DIFF_LINE_HUNK_HDR: color = 4; break; - default: color = 0; + case GIT_DIFF_LINE_FILE_HDR: color = 1; break; + case GIT_DIFF_LINE_HUNK_HDR: color = 4; break; + default: break; } if (color != *last_color) { if (*last_color == 1 || color == 1) @@ -73,7 +71,13 @@ static int printer( } } - fputs(line, stdout); + if (line->origin == GIT_DIFF_LINE_CONTEXT || + line->origin == GIT_DIFF_LINE_ADDITION || + line->origin == GIT_DIFF_LINE_DELETION) + fputc(line->origin, stdout); + + fwrite(line->content, 1, line->content_len, stdout); + return 0; } diff --git a/examples/log.c b/examples/log.c index 30de16ae9..4c2df07c9 100644 --- a/examples/log.c +++ b/examples/log.c @@ -184,14 +184,18 @@ static void print_commit(git_commit *commit) static int print_diff( const git_diff_delta *delta, - const git_diff_hunk *range, - char usage, - const char *line, - size_t line_len, + const git_diff_hunk *hunk, + const git_diff_line *line, void *data) { - (void)delta; (void)range; (void)usage; (void)line_len; (void)data; - fputs(line, stdout); + (void)delta; (void)hunk; (void)data; + + if (line->origin == GIT_DIFF_LINE_CONTEXT || + line->origin == GIT_DIFF_LINE_ADDITION || + line->origin == GIT_DIFF_LINE_DELETION) + fputc(line->origin, stdout); + + fwrite(line->content, 1, line->content_len, stdout); return 0; } diff --git a/include/git2/diff.h b/include/git2/diff.h index f1572cbd5..ed9f71355 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -385,10 +385,12 @@ typedef int (*git_diff_file_cb)( */ typedef struct git_diff_hunk git_diff_hunk; struct git_diff_hunk { - int old_start; /** Starting line number in old_file */ - int old_lines; /** Number of lines in old_file */ - int new_start; /** Starting line number in new_file */ - int new_lines; /** Number of lines in new_file */ + int old_start; /** Starting line number in old_file */ + int old_lines; /** Number of lines in old_file */ + int new_start; /** Starting line number in new_file */ + int new_lines; /** Number of lines in new_file */ + size_t header_len; /** Number of bytes in header text */ + char header[128]; /** Header text, NUL-byte terminated */ }; /** @@ -397,8 +399,6 @@ struct git_diff_hunk { typedef int (*git_diff_hunk_cb)( const git_diff_delta *delta, const git_diff_hunk *hunk, - const char *header, - size_t header_len, void *payload); /** @@ -428,6 +428,19 @@ typedef enum { GIT_DIFF_LINE_BINARY = 'B' /**< For "Binary files x and y differ" */ } git_diff_line_t; +/** + * Structure describing a line (or data span) of a diff. + */ +typedef struct git_diff_line git_diff_line; +struct git_diff_line { + char origin; /** A git_diff_line_t value */ + int old_lineno; /** Line number in old file or -1 for added line */ + int new_lineno; /** Line number in new file or -1 for deleted line */ + int num_lines; /** Number of newline characters in content */ + size_t content_len; /** Number of bytes of data */ + const char *content; /** Pointer to diff text, not NUL-byte terminated */ +}; + /** * When iterating over a diff, callback that will be made per text diff * line. In this context, the provided range will be NULL. @@ -438,10 +451,8 @@ typedef enum { */ typedef int (*git_diff_line_cb)( const git_diff_delta *delta, /** delta that contains this data */ - const git_diff_hunk *hunk, /** range of lines containing this data */ - char line_origin, /** git_diff_t value from above */ - const char *content, /** diff data - not NUL terminated */ - size_t content_len, /** number of bytes of diff data */ + const git_diff_hunk *hunk, /** hunk containing this data */ + const git_diff_line *line, /** line data */ void *payload); /** user reference data */ /** diff --git a/include/git2/patch.h b/include/git2/patch.h index 9836245de..6a6ad92d7 100644 --- a/include/git2/patch.h +++ b/include/git2/patch.h @@ -150,9 +150,6 @@ GIT_EXTERN(int) git_patch_line_stats( * as NULL if you don't care about that particular piece of information. * * @param out Output pointer to git_diff_hunk of hunk - * @param header Output pointer to header string for hunk. Unlike the - * content pointer for each line, this will be NUL-terminated - * @param header_len Output value of characters in header string * @param lines_in_hunk Output count of total lines in this hunk * @param patch Input pointer to patch object * @param hunk_idx Input index of hunk to get information about @@ -160,8 +157,6 @@ GIT_EXTERN(int) git_patch_line_stats( */ GIT_EXTERN(int) git_patch_get_hunk( const git_diff_hunk **out, - const char **header, - size_t *header_len, size_t *lines_in_hunk, git_patch *patch, size_t hunk_idx); @@ -185,22 +180,14 @@ GIT_EXTERN(int) git_patch_num_lines_in_hunk( * index larger than the number of hunks or a line index larger than * the number of lines in the hunk, this will return -1. * - * @param line_origin A GIT_DIFF_LINE constant from above - * @param content Pointer to content of diff line, not NUL-terminated - * @param content_len Number of characters in content - * @param old_lineno Line number in old file or -1 if line is added - * @param new_lineno Line number in new file or -1 if line is deleted + * @param out The git_diff_line data for this line * @param patch The patch to look in * @param hunk_idx The index of the hunk * @param line_of_hunk The index of the line in the hunk * @return 0 on success, <0 on failure */ GIT_EXTERN(int) git_patch_get_line_in_hunk( - char *line_origin, - const char **content, - size_t *content_len, - int *old_lineno, - int *new_lineno, + const git_diff_line **out, git_patch *patch, size_t hunk_idx, size_t line_of_hunk); diff --git a/src/diff_patch.c b/src/diff_patch.c index 951368200..cc49d68eb 100644 --- a/src/diff_patch.c +++ b/src/diff_patch.c @@ -12,23 +12,10 @@ #include "diff_xdiff.h" #include "fileops.h" -/* cached information about a single span in a diff */ -typedef struct diff_patch_line diff_patch_line; -struct diff_patch_line { - const char *ptr; - size_t len; - size_t lines; - size_t oldno; - size_t newno; - char origin; -}; - /* cached information about a hunk in a diff */ typedef struct diff_patch_hunk diff_patch_hunk; struct diff_patch_hunk { git_diff_hunk hunk; - char header[128]; - size_t header_len; size_t line_start; size_t line_count; }; @@ -42,8 +29,7 @@ struct git_patch { git_diff_file_content nfile; uint32_t flags; git_array_t(diff_patch_hunk) hunks; - git_array_t(diff_patch_line) lines; - size_t oldno, newno; + git_array_t(git_diff_line) lines; size_t content_size, context_size, header_size; git_pool flattened; }; @@ -57,7 +43,8 @@ enum { GIT_DIFF_PATCH_FLATTENED = (1 << 5), }; -static void diff_output_init(git_diff_output*, const git_diff_options*, +static void diff_output_init( + git_diff_output*, const git_diff_options*, git_diff_file_cb, git_diff_hunk_cb, git_diff_line_cb, void*); static void diff_output_to_patch(git_diff_output *, git_patch *); @@ -81,7 +68,7 @@ static void diff_patch_init_common(git_patch *patch) diff_patch_update_binary(patch); if ((patch->delta->flags & GIT_DIFF_FLAG_BINARY) != 0) - patch->flags |= GIT_DIFF_PATCH_LOADED; /* set LOADED but not DIFFABLE */ + patch->flags |= GIT_DIFF_PATCH_LOADED; /* LOADED but not DIFFABLE */ patch->flags |= GIT_DIFF_PATCH_INITIALIZED; @@ -687,7 +674,7 @@ int git_patch_line_stats( memset(totals, 0, sizeof(totals)); for (idx = 0; idx < git_array_size(patch->lines); ++idx) { - diff_patch_line *line = git_array_get(patch->lines, idx); + git_diff_line *line = git_array_get(patch->lines, idx); if (!line) continue; @@ -721,8 +708,6 @@ static int diff_error_outofrange(const char *thing) int git_patch_get_hunk( const git_diff_hunk **out, - const char **header, - size_t *header_len, size_t *lines_in_hunk, git_patch *patch, size_t hunk_idx) @@ -734,15 +719,11 @@ int git_patch_get_hunk( if (!hunk) { if (out) *out = NULL; - if (header) *header = NULL; - if (header_len) *header_len = 0; if (lines_in_hunk) *lines_in_hunk = 0; return diff_error_outofrange("hunk"); } if (out) *out = &hunk->hunk; - if (header) *header = hunk->header; - if (header_len) *header_len = hunk->header_len; if (lines_in_hunk) *lines_in_hunk = hunk->line_count; return 0; } @@ -758,49 +739,30 @@ int git_patch_num_lines_in_hunk(git_patch *patch, size_t hunk_idx) } int git_patch_get_line_in_hunk( - char *line_origin, - const char **content, - size_t *content_len, - int *old_lineno, - int *new_lineno, + const git_diff_line **out, git_patch *patch, size_t hunk_idx, size_t line_of_hunk) { diff_patch_hunk *hunk; - diff_patch_line *line; - const char *thing; + git_diff_line *line; assert(patch); if (!(hunk = git_array_get(patch->hunks, hunk_idx))) { - thing = "hunk"; - goto notfound; + if (out) *out = NULL; + return diff_error_outofrange("hunk"); } if (line_of_hunk >= hunk->line_count || !(line = git_array_get( patch->lines, hunk->line_start + line_of_hunk))) { - thing = "line"; - goto notfound; + if (out) *out = NULL; + return diff_error_outofrange("line"); } - if (line_origin) *line_origin = line->origin; - if (content) *content = line->ptr; - if (content_len) *content_len = line->len; - if (old_lineno) *old_lineno = (int)line->oldno; - if (new_lineno) *new_lineno = (int)line->newno; - + if (out) *out = line; return 0; - -notfound: - if (line_origin) *line_origin = GIT_DIFF_LINE_CONTEXT; - if (content) *content = NULL; - if (content_len) *content_len = 0; - if (old_lineno) *old_lineno = -1; - if (new_lineno) *new_lineno = -1; - - return diff_error_outofrange(thing); } size_t git_patch_size( @@ -880,18 +842,16 @@ int git_patch__invoke_callbacks( for (i = 0; !error && i < git_array_size(patch->hunks); ++i) { diff_patch_hunk *h = git_array_get(patch->hunks, i); - error = hunk_cb( - patch->delta, &h->hunk, h->header, h->header_len, payload); + error = hunk_cb(patch->delta, &h->hunk, payload); if (!line_cb) continue; for (j = 0; !error && j < h->line_count; ++j) { - diff_patch_line *l = + git_diff_line *l = git_array_get(patch->lines, h->line_start + j); - error = line_cb( - patch->delta, &h->hunk, l->origin, l->ptr, l->len, payload); + error = line_cb(patch->delta, &h->hunk, l, payload); } } @@ -911,8 +871,6 @@ static int diff_patch_file_cb( static int diff_patch_hunk_cb( const git_diff_delta *delta, const git_diff_hunk *hunk_, - const char *header, - size_t header_len, void *payload) { git_patch *patch = payload; @@ -925,34 +883,23 @@ static int diff_patch_hunk_cb( memcpy(&hunk->hunk, hunk_, sizeof(hunk->hunk)); - assert(header_len + 1 < sizeof(hunk->header)); - memcpy(&hunk->header, header, header_len); - hunk->header[header_len] = '\0'; - hunk->header_len = header_len; - - patch->header_size += header_len; + patch->header_size += hunk_->header_len; hunk->line_start = git_array_size(patch->lines); hunk->line_count = 0; - patch->oldno = hunk_->old_start; - patch->newno = hunk_->new_start; - return 0; } static int diff_patch_line_cb( const git_diff_delta *delta, const git_diff_hunk *hunk_, - char line_origin, - const char *content, - size_t content_len, + const git_diff_line *line_, void *payload) { git_patch *patch = payload; diff_patch_hunk *hunk; - diff_patch_line *line; - const char *content_end = content + content_len; + git_diff_line *line; GIT_UNUSED(delta); GIT_UNUSED(hunk_); @@ -963,48 +910,20 @@ static int diff_patch_line_cb( line = git_array_alloc(patch->lines); GITERR_CHECK_ALLOC(line); - line->ptr = content; - line->len = content_len; - line->origin = line_origin; + memcpy(line, line_, sizeof(*line)); /* do some bookkeeping so we can provide old/new line numbers */ - line->lines = 0; - while (content < content_end) - if (*content++ == '\n') - ++line->lines; + patch->content_size += line->content_len; - patch->content_size += content_len; - - switch (line_origin) { - case GIT_DIFF_LINE_ADDITION: - patch->content_size += 1; - case GIT_DIFF_LINE_DEL_EOFNL: - line->oldno = -1; - line->newno = patch->newno; - patch->newno += line->lines; - break; - case GIT_DIFF_LINE_DELETION: + if (line->origin == GIT_DIFF_LINE_ADDITION || + line->origin == GIT_DIFF_LINE_DELETION) patch->content_size += 1; - case GIT_DIFF_LINE_ADD_EOFNL: - line->oldno = patch->oldno; - line->newno = -1; - patch->oldno += line->lines; - break; - case GIT_DIFF_LINE_CONTEXT: + else if (line->origin == GIT_DIFF_LINE_CONTEXT) { patch->content_size += 1; - patch->context_size += 1; - case GIT_DIFF_LINE_CONTEXT_EOFNL: - patch->context_size += content_len; - line->oldno = patch->oldno; - line->newno = patch->newno; - patch->oldno += line->lines; - patch->newno += line->lines; - break; - default: - assert(false); - break; - } + patch->context_size += line->content_len + 1; + } else if (line->origin == GIT_DIFF_LINE_CONTEXT_EOFNL) + patch->context_size += line->content_len; hunk->line_count++; diff --git a/src/diff_print.c b/src/diff_print.c index a6423d92b..b04b11515 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -17,6 +17,7 @@ typedef struct { git_buf *buf; uint32_t flags; int oid_strlen; + git_diff_line line; } diff_print_info; static int diff_print_info_init( @@ -51,6 +52,11 @@ static int diff_print_info_init( else if (pi->oid_strlen > GIT_OID_HEXSZ + 1) pi->oid_strlen = GIT_OID_HEXSZ + 1; + memset(&pi->line, 0, sizeof(pi->line)); + pi->line.old_lineno = -1; + pi->line.new_lineno = -1; + pi->line.num_lines = 1; + return 0; } @@ -107,8 +113,11 @@ static int diff_print_one_name_only( git_buf_putc(out, '\n')) return -1; - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR, - git_buf_cstr(out), git_buf_len(out), pi->payload)) + pi->line.origin = GIT_DIFF_LINE_FILE_HDR; + pi->line.content = git_buf_cstr(out); + pi->line.content_len = git_buf_len(out); + + if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) return callback_error(); return 0; @@ -149,8 +158,11 @@ static int diff_print_one_name_status( if (git_buf_oom(out)) return -1; - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR, - git_buf_cstr(out), git_buf_len(out), pi->payload)) + pi->line.origin = GIT_DIFF_LINE_FILE_HDR; + pi->line.content = git_buf_cstr(out); + pi->line.content_len = git_buf_len(out); + + if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) return callback_error(); return 0; @@ -192,8 +204,11 @@ static int diff_print_one_raw( if (git_buf_oom(out)) return -1; - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR, - git_buf_cstr(out), git_buf_len(out), pi->payload)) + pi->line.origin = GIT_DIFF_LINE_FILE_HDR; + pi->line.content = git_buf_cstr(out); + pi->line.content_len = git_buf_len(out); + + if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) return callback_error(); return 0; @@ -302,8 +317,11 @@ static int diff_print_patch_file( pi->buf, delta, oldpfx, newpfx, pi->oid_strlen) < 0) return -1; - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR, - git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) + pi->line.origin = GIT_DIFF_LINE_FILE_HDR; + pi->line.content = git_buf_cstr(pi->buf); + pi->line.content_len = git_buf_len(pi->buf); + + if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) return callback_error(); if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) @@ -316,8 +334,12 @@ static int diff_print_patch_file( "Binary files %s%s and %s%s differ\n") < 0) return -1; - if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_BINARY, - git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) + pi->line.origin = GIT_DIFF_LINE_BINARY; + pi->line.content = git_buf_cstr(pi->buf); + pi->line.content_len = git_buf_len(pi->buf); + pi->line.num_lines = 1; + + if (pi->print_cb(delta, NULL, &pi->line, pi->payload)) return callback_error(); return 0; @@ -325,9 +347,7 @@ static int diff_print_patch_file( static int diff_print_patch_hunk( const git_diff_delta *d, - const git_diff_hunk *r, - const char *header, - size_t header_len, + const git_diff_hunk *h, void *data) { diff_print_info *pi = data; @@ -335,12 +355,11 @@ static int diff_print_patch_hunk( if (S_ISDIR(d->new_file.mode)) return 0; - git_buf_clear(pi->buf); - if (git_buf_put(pi->buf, header, header_len) < 0) - return -1; + pi->line.origin = GIT_DIFF_LINE_HUNK_HDR; + pi->line.content = h->header; + pi->line.content_len = h->header_len; - if (pi->print_cb(d, r, GIT_DIFF_LINE_HUNK_HDR, - git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) + if (pi->print_cb(d, h, &pi->line, pi->payload)) return callback_error(); return 0; @@ -348,10 +367,8 @@ static int diff_print_patch_hunk( static int diff_print_patch_line( const git_diff_delta *delta, - const git_diff_hunk *range, - char line_origin, /* GIT_DIFF_LINE value from above */ - const char *content, - size_t content_len, + const git_diff_hunk *hunk, + const git_diff_line *line, void *data) { diff_print_info *pi = data; @@ -359,21 +376,7 @@ static int diff_print_patch_line( if (S_ISDIR(delta->new_file.mode)) return 0; - git_buf_clear(pi->buf); - git_buf_grow(pi->buf, content_len + 2); - - if (line_origin == GIT_DIFF_LINE_ADDITION || - line_origin == GIT_DIFF_LINE_DELETION || - line_origin == GIT_DIFF_LINE_CONTEXT) - git_buf_putc(pi->buf, line_origin); - - git_buf_put(pi->buf, content, content_len); - - if (git_buf_oom(pi->buf)) - return -1; - - if (pi->print_cb(delta, range, line_origin, - git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) + if (pi->print_cb(delta, hunk, line, pi->payload)) return callback_error(); return 0; @@ -452,15 +455,19 @@ int git_patch_print( static int diff_print_to_buffer_cb( const git_diff_delta *delta, - const git_diff_hunk *range, - char line_origin, - const char *content, - size_t content_len, + const git_diff_hunk *hunk, + const git_diff_line *line, void *payload) { git_buf *output = payload; - GIT_UNUSED(delta); GIT_UNUSED(range); GIT_UNUSED(line_origin); - return git_buf_put(output, content, content_len); + GIT_UNUSED(delta); GIT_UNUSED(hunk); + + if (line->origin == GIT_DIFF_LINE_ADDITION || + line->origin == GIT_DIFF_LINE_DELETION || + line->origin == GIT_DIFF_LINE_CONTEXT) + git_buf_putc(output, line->origin); + + return git_buf_put(output, line->content, line->content_len); } /* print a git_patch to a string buffer */ diff --git a/src/diff_xdiff.c b/src/diff_xdiff.c index 972039753..a90f8d5d1 100644 --- a/src/diff_xdiff.c +++ b/src/diff_xdiff.c @@ -53,36 +53,94 @@ typedef struct { git_xdiff_output *xo; git_patch *patch; git_diff_hunk hunk; + size_t old_lineno, new_lineno; } git_xdiff_info; +static int diff_update_lines( + git_xdiff_info *info, + git_diff_line *line, + const char *content, + size_t content_len) +{ + const char *scan = content, *scan_end = content + content_len; + + for (line->num_lines = 0; scan < scan_end; ++scan) + if (*scan == '\n') + ++line->num_lines; + + line->content = content; + line->content_len = content_len; + + /* expect " "/"-"/"+", then data */ + switch (line->origin) { + case GIT_DIFF_LINE_ADDITION: + case GIT_DIFF_LINE_DEL_EOFNL: + line->old_lineno = -1; + line->new_lineno = info->new_lineno; + info->new_lineno += line->num_lines; + break; + case GIT_DIFF_LINE_DELETION: + case GIT_DIFF_LINE_ADD_EOFNL: + line->old_lineno = info->old_lineno; + line->new_lineno = -1; + info->old_lineno += line->num_lines; + break; + case GIT_DIFF_LINE_CONTEXT: + case GIT_DIFF_LINE_CONTEXT_EOFNL: + line->old_lineno = info->old_lineno; + line->new_lineno = info->new_lineno; + info->old_lineno += line->num_lines; + info->new_lineno += line->num_lines; + break; + default: + giterr_set(GITERR_INVALID, "Unknown diff line origin %02x", + (unsigned int)line->origin); + return -1; + } + + return 0; +} + static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) { git_xdiff_info *info = priv; git_patch *patch = info->patch; const git_diff_delta *delta = git_patch_get_delta(patch); git_diff_output *output = &info->xo->output; + git_diff_line line; if (len == 1) { output->error = git_xdiff_parse_hunk(&info->hunk, bufs[0].ptr); if (output->error < 0) return output->error; + info->hunk.header_len = bufs[0].size; + if (info->hunk.header_len >= sizeof(info->hunk.header)) + info->hunk.header_len = sizeof(info->hunk.header) - 1; + memcpy(info->hunk.header, bufs[0].ptr, info->hunk.header_len); + info->hunk.header[info->hunk.header_len] = '\0'; + if (output->hunk_cb != NULL && - output->hunk_cb(delta, &info->hunk, - bufs[0].ptr, bufs[0].size, output->payload)) + output->hunk_cb(delta, &info->hunk, output->payload)) output->error = GIT_EUSER; + + info->old_lineno = info->hunk.old_start; + info->new_lineno = info->hunk.new_start; } if (len == 2 || len == 3) { /* expect " "/"-"/"+", then data */ - char origin = + line.origin = (*bufs[0].ptr == '+') ? GIT_DIFF_LINE_ADDITION : (*bufs[0].ptr == '-') ? GIT_DIFF_LINE_DELETION : GIT_DIFF_LINE_CONTEXT; - if (output->data_cb != NULL && - output->data_cb(delta, &info->hunk, - origin, bufs[1].ptr, bufs[1].size, output->payload)) + output->error = diff_update_lines( + info, &line, bufs[1].ptr, bufs[1].size); + + if (!output->error && + output->data_cb != NULL && + output->data_cb(delta, &info->hunk, &line, output->payload)) output->error = GIT_EUSER; } @@ -92,14 +150,17 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) * If we have a '-' and a third buf, then we have removed a line * with out a newline but added a blank line, so ADD_EOFNL. */ - char origin = + line.origin = (*bufs[0].ptr == '+') ? GIT_DIFF_LINE_DEL_EOFNL : (*bufs[0].ptr == '-') ? GIT_DIFF_LINE_ADD_EOFNL : GIT_DIFF_LINE_CONTEXT_EOFNL; - if (output->data_cb != NULL && - output->data_cb(delta, &info->hunk, - origin, bufs[2].ptr, bufs[2].size, output->payload)) + output->error = diff_update_lines( + info, &line, bufs[2].ptr, bufs[2].size); + + if (!output->error && + output->data_cb != NULL && + output->data_cb(delta, &info->hunk, &line, output->payload)) output->error = GIT_EUSER; } diff --git a/tests-clar/diff/blob.c b/tests-clar/diff/blob.c index 898c037b5..b51bc0f38 100644 --- a/tests-clar/diff/blob.c +++ b/tests-clar/diff/blob.c @@ -319,8 +319,8 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void) git_blob *e = NULL; git_patch *p; const git_diff_delta *delta; - int line; - char origin; + const git_diff_line *line; + int l, max_l; cl_git_pass(git_patch_from_blobs(&p, d, NULL, e, NULL, &opts)); @@ -337,10 +337,10 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void) cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p, 0)); - for (line = 0; line < git_patch_num_lines_in_hunk(p, 0); ++line) { - cl_git_pass(git_patch_get_line_in_hunk( - &origin, NULL, NULL, NULL, NULL, p, 0, line)); - cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)origin); + max_l = git_patch_num_lines_in_hunk(p, 0); + for (l = 0; l < max_l; ++l) { + cl_git_pass(git_patch_get_line_in_hunk(&line, p, 0, l)); + cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); } git_patch_free(p); @@ -362,10 +362,10 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void) cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p, 0)); - for (line = 0; line < git_patch_num_lines_in_hunk(p, 0); ++line) { - cl_git_pass(git_patch_get_line_in_hunk( - &origin, NULL, NULL, NULL, NULL, p, 0, line)); - cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)origin); + max_l = git_patch_num_lines_in_hunk(p, 0); + for (l = 0; l < max_l; ++l) { + cl_git_pass(git_patch_get_line_in_hunk(&line, p, 0, l)); + cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); } git_patch_free(p); diff --git a/tests-clar/diff/diff_helpers.c b/tests-clar/diff/diff_helpers.c index cf768865e..466d0ef54 100644 --- a/tests-clar/diff/diff_helpers.c +++ b/tests-clar/diff/diff_helpers.c @@ -95,41 +95,37 @@ int diff_print_file_cb( int diff_hunk_cb( const git_diff_delta *delta, - const git_diff_hunk *range, - const char *header, - size_t header_len, + const git_diff_hunk *hunk, void *payload) { diff_expects *e = payload; + const char *scan = hunk->header, *scan_end = scan + hunk->header_len; GIT_UNUSED(delta); /* confirm no NUL bytes in header text */ - while (header_len--) cl_assert('\0' != *header++); + while (scan < scan_end) + cl_assert('\0' != *scan++); e->hunks++; - e->hunk_old_lines += range->old_lines; - e->hunk_new_lines += range->new_lines; + e->hunk_old_lines += hunk->old_lines; + e->hunk_new_lines += hunk->new_lines; return 0; } int diff_line_cb( const git_diff_delta *delta, - const git_diff_hunk *range, - char line_origin, - const char *content, - size_t content_len, + const git_diff_hunk *hunk, + const git_diff_line *line, void *payload) { diff_expects *e = payload; GIT_UNUSED(delta); - GIT_UNUSED(range); - GIT_UNUSED(content); - GIT_UNUSED(content_len); + GIT_UNUSED(hunk); e->lines++; - switch (line_origin) { + switch (line->origin) { case GIT_DIFF_LINE_CONTEXT: case GIT_DIFF_LINE_CONTEXT_EOFNL: /* techically not a line */ e->line_ctxt++; @@ -186,30 +182,23 @@ int diff_foreach_via_iterator( num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { - const git_diff_hunk *range; - const char *hdr; - size_t hdr_len, l, num_l; + const git_diff_hunk *hunk; + size_t l, num_l; - cl_git_pass(git_patch_get_hunk( - &range, &hdr, &hdr_len, &num_l, patch, h)); + cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h)); - if (hunk_cb && hunk_cb(delta, range, hdr, hdr_len, data) != 0) { + if (hunk_cb && hunk_cb(delta, hunk, data) != 0) { git_patch_free(patch); goto abort; } for (l = 0; l < num_l; ++l) { - char origin; - const char *line; - size_t line_len; - int old_lineno, new_lineno; + const git_diff_line *line; - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &line, &line_len, &old_lineno, &new_lineno, - patch, h, l)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l)); if (line_cb && - line_cb(delta, range, origin, line, line_len, data) != 0) { + line_cb(delta, hunk, line, data) != 0) { git_patch_free(patch); goto abort; } @@ -228,18 +217,15 @@ abort: static int diff_print_cb( const git_diff_delta *delta, - const git_diff_hunk *range, - char line_origin, /**< GIT_DIFF_LINE_... value from above */ - const char *content, - size_t content_len, + const git_diff_hunk *hunk, + const git_diff_line *line, void *payload) { GIT_UNUSED(payload); GIT_UNUSED(delta); - GIT_UNUSED(range); - GIT_UNUSED(line_origin); - GIT_UNUSED(content_len); - fputs(content, (FILE *)payload); + GIT_UNUSED(hunk); + fprintf((FILE *)payload, "%c%.*s", + line->origin, (int)line->content_len, line->content); return 0; } diff --git a/tests-clar/diff/diff_helpers.h b/tests-clar/diff/diff_helpers.h index e3ad61f29..bf21f4b1f 100644 --- a/tests-clar/diff/diff_helpers.h +++ b/tests-clar/diff/diff_helpers.h @@ -44,17 +44,13 @@ extern int diff_print_file_cb( extern int diff_hunk_cb( const git_diff_delta *delta, - const git_diff_hunk *range, - const char *header, - size_t header_len, + const git_diff_hunk *hunk, void *cb_data); extern int diff_line_cb( const git_diff_delta *delta, - const git_diff_hunk *range, - char line_origin, - const char *content, - size_t content_len, + const git_diff_hunk *hunk, + const git_diff_line *line, void *cb_data); extern int diff_foreach_via_iterator( diff --git a/tests-clar/diff/diffiter.c b/tests-clar/diff/diffiter.c index 1a1e5dfc3..f886e1baa 100644 --- a/tests-clar/diff/diffiter.c +++ b/tests-clar/diff/diffiter.c @@ -101,15 +101,10 @@ void test_diff_diffiter__iterate_files_and_hunks(void) num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { - const git_diff_hunk *range; - const char *header; - size_t header_len, num_l; - - cl_git_pass(git_patch_get_hunk( - &range, &header, &header_len, &num_l, patch, h)); + const git_diff_hunk *hunk; - cl_assert(range); - cl_assert(header); + cl_git_pass(git_patch_get_hunk(&hunk, NULL, patch, h)); + cl_assert(hunk); hunk_count++; } @@ -229,22 +224,17 @@ void test_diff_diffiter__iterate_all(void) num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { const git_diff_hunk *range; - const char *header; - size_t header_len, l, num_l; + size_t l, num_l; - cl_git_pass(git_patch_get_hunk( - &range, &header, &header_len, &num_l, patch, h)); - cl_assert(range && header); + cl_git_pass(git_patch_get_hunk(&range, &num_l, patch, h)); + cl_assert(range); exp.hunks++; for (l = 0; l < num_l; ++l) { - char origin; - const char *content; - size_t content_len; + const git_diff_line *line; - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &content, &content_len, NULL, NULL, patch, h, l)); - cl_assert(content); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l)); + cl_assert(line && line->content); exp.lines++; } } diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c index 9c01c3b4e..366e5da58 100644 --- a/tests-clar/diff/patch.c +++ b/tests-clar/diff/patch.c @@ -26,40 +26,37 @@ void test_diff_patch__cleanup(void) static int check_removal_cb( const git_diff_delta *delta, - const git_diff_hunk *range, - char line_origin, - const char *formatted_output, - size_t output_len, + const git_diff_hunk *hunk, + const git_diff_line *line, void *payload) { GIT_UNUSED(payload); - GIT_UNUSED(output_len); - switch (line_origin) { + switch (line->origin) { case GIT_DIFF_LINE_FILE_HDR: - cl_assert_equal_s(EXPECTED_HEADER, formatted_output); - cl_assert(range == NULL); + cl_assert_equal_s(EXPECTED_HEADER, line->content); + cl_assert(hunk == NULL); goto check_delta; case GIT_DIFF_LINE_HUNK_HDR: - cl_assert_equal_s(EXPECTED_HUNK, formatted_output); + cl_assert_equal_s(EXPECTED_HUNK, line->content); /* Fall through */ case GIT_DIFF_LINE_CONTEXT: case GIT_DIFF_LINE_DELETION: - goto check_range; + goto check_hunk; default: /* unexpected code path */ return -1; } -check_range: - cl_assert(range != NULL); - cl_assert_equal_i(1, range->old_start); - cl_assert_equal_i(2, range->old_lines); - cl_assert_equal_i(0, range->new_start); - cl_assert_equal_i(0, range->new_lines); +check_hunk: + cl_assert(hunk != NULL); + cl_assert_equal_i(1, hunk->old_start); + cl_assert_equal_i(2, hunk->old_lines); + cl_assert_equal_i(0, hunk->new_start); + cl_assert_equal_i(0, hunk->new_lines); check_delta: cl_assert_equal_s("subdir.txt", delta->old_file.path); @@ -227,11 +224,9 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) git_diff *diff; git_patch *patch; const git_diff_delta *delta; - const git_diff_hunk *range; - const char *hdr, *text; - size_t hdrlen, hunklen, textlen; - char origin; - int oldno, newno; + const git_diff_hunk *hunk; + const git_diff_line *line; + size_t hunklen; git_buf old_content = GIT_BUF_INIT, actual = GIT_BUF_INIT; const char *new_content = "The Song of Seven Cities\n------------------------\n\nI WAS Lord of Cities very sumptuously builded.\nSeven roaring Cities paid me tribute from afar.\nIvory their outposts were--the guardrooms of them gilded,\nAnd garrisoned with Amazons invincible in war.\n\nThis is some new text;\nNot as good as the old text;\nBut here it is.\n\nSo they warred and trafficked only yesterday, my Cities.\nTo-day there is no mark or mound of where my Cities stood.\nFor the River rose at midnight and it washed away my Cities.\nThey are evened with Atlantis and the towns before the Flood.\n\nRain on rain-gorged channels raised the water-levels round them,\nFreshet backed on freshet swelled and swept their world from sight,\nTill the emboldened floods linked arms and, flashing forward, drowned them--\nDrowned my Seven Cities and their peoples in one night!\n\nLow among the alders lie their derelict foundations,\nThe beams wherein they trusted and the plinths whereon they built--\nMy rulers and their treasure and their unborn populations,\nDead, destroyed, aborted, and defiled with mud and silt!\n\nAnother replacement;\nBreaking up the poem;\nGenerating some hunks.\n\nTo the sound of trumpets shall their seed restore my Cities\nWealthy and well-weaponed, that once more may I behold\nAll the world go softly when it walks before my Cities,\nAnd the horses and the chariots fleeing from them as of old!\n\n -- Rudyard Kipling\n"; @@ -263,78 +258,71 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) /* check hunk 0 */ cl_git_pass( - git_patch_get_hunk(&range, &hdr, &hdrlen, &hunklen, patch, 0)); + git_patch_get_hunk(&hunk, &hunklen, patch, 0)); cl_assert_equal_i(18, (int)hunklen); - cl_assert_equal_i(6, (int)range->old_start); - cl_assert_equal_i(15, (int)range->old_lines); - cl_assert_equal_i(6, (int)range->new_start); - cl_assert_equal_i(9, (int)range->new_lines); + cl_assert_equal_i(6, (int)hunk->old_start); + cl_assert_equal_i(15, (int)hunk->old_lines); + cl_assert_equal_i(6, (int)hunk->new_start); + cl_assert_equal_i(9, (int)hunk->new_lines); cl_assert_equal_i(18, (int)git_patch_num_lines_in_hunk(patch, 0)); - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &text, &textlen, &oldno, &newno, patch, 0, 0)); - cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)origin); - cl_git_pass(git_buf_set(&actual, text, textlen)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 0)); + cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); cl_assert_equal_s("Ivory their outposts were--the guardrooms of them gilded,\n", actual.ptr); - cl_assert_equal_i(6, oldno); - cl_assert_equal_i(6, newno); + cl_assert_equal_i(6, line->old_lineno); + cl_assert_equal_i(6, line->new_lineno); - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &text, &textlen, &oldno, &newno, patch, 0, 3)); - cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)origin); - cl_git_pass(git_buf_set(&actual, text, textlen)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 3)); + cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); cl_assert_equal_s("All the world went softly when it walked before my Cities--\n", actual.ptr); - cl_assert_equal_i(9, oldno); - cl_assert_equal_i(-1, newno); + cl_assert_equal_i(9, line->old_lineno); + cl_assert_equal_i(-1, line->new_lineno); - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &text, &textlen, &oldno, &newno, patch, 0, 12)); - cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)origin); - cl_git_pass(git_buf_set(&actual, text, textlen)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 12)); + cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); cl_assert_equal_s("This is some new text;\n", actual.ptr); - cl_assert_equal_i(-1, oldno); - cl_assert_equal_i(9, newno); + cl_assert_equal_i(-1, line->old_lineno); + cl_assert_equal_i(9, line->new_lineno); /* check hunk 1 */ - cl_git_pass( - git_patch_get_hunk(&range, &hdr, &hdrlen, &hunklen, patch, 1)); + cl_git_pass(git_patch_get_hunk(&hunk, &hunklen, patch, 1)); cl_assert_equal_i(18, (int)hunklen); - cl_assert_equal_i(31, (int)range->old_start); - cl_assert_equal_i(15, (int)range->old_lines); - cl_assert_equal_i(25, (int)range->new_start); - cl_assert_equal_i(9, (int)range->new_lines); + cl_assert_equal_i(31, (int)hunk->old_start); + cl_assert_equal_i(15, (int)hunk->old_lines); + cl_assert_equal_i(25, (int)hunk->new_start); + cl_assert_equal_i(9, (int)hunk->new_lines); cl_assert_equal_i(18, (int)git_patch_num_lines_in_hunk(patch, 1)); - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &text, &textlen, &oldno, &newno, patch, 1, 0)); - cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)origin); - cl_git_pass(git_buf_set(&actual, text, textlen)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 0)); + cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); cl_assert_equal_s("My rulers and their treasure and their unborn populations,\n", actual.ptr); - cl_assert_equal_i(31, oldno); - cl_assert_equal_i(25, newno); + cl_assert_equal_i(31, line->old_lineno); + cl_assert_equal_i(25, line->new_lineno); - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &text, &textlen, &oldno, &newno, patch, 1, 3)); - cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)origin); - cl_git_pass(git_buf_set(&actual, text, textlen)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 3)); + cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); cl_assert_equal_s("The Daughters of the Palace whom they cherished in my Cities,\n", actual.ptr); - cl_assert_equal_i(34, oldno); - cl_assert_equal_i(-1, newno); + cl_assert_equal_i(34, line->old_lineno); + cl_assert_equal_i(-1, line->new_lineno); - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &text, &textlen, &oldno, &newno, patch, 1, 12)); - cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)origin); - cl_git_pass(git_buf_set(&actual, text, textlen)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 12)); + cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); cl_assert_equal_s("Another replacement;\n", actual.ptr); - cl_assert_equal_i(-1, oldno); - cl_assert_equal_i(28, newno); + cl_assert_equal_i(-1, line->old_lineno); + cl_assert_equal_i(28, line->new_lineno); git_patch_free(patch); git_diff_free(diff); @@ -356,57 +344,51 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) /* check hunk 0 */ - cl_git_pass( - git_patch_get_hunk(&range, &hdr, &hdrlen, &hunklen, patch, 0)); + cl_git_pass(git_patch_get_hunk(&hunk, &hunklen, patch, 0)); cl_assert_equal_i(6, (int)hunklen); - cl_assert_equal_i(46, (int)range->old_start); - cl_assert_equal_i(4, (int)range->old_lines); - cl_assert_equal_i(46, (int)range->new_start); - cl_assert_equal_i(4, (int)range->new_lines); + cl_assert_equal_i(46, (int)hunk->old_start); + cl_assert_equal_i(4, (int)hunk->old_lines); + cl_assert_equal_i(46, (int)hunk->new_start); + cl_assert_equal_i(4, (int)hunk->new_lines); cl_assert_equal_i(6, (int)git_patch_num_lines_in_hunk(patch, 0)); - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &text, &textlen, &oldno, &newno, patch, 0, 1)); - cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)origin); - cl_git_pass(git_buf_set(&actual, text, textlen)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 1)); + cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); cl_assert_equal_s("And the horses and the chariots fleeing from them as of old!\n", actual.ptr); - cl_assert_equal_i(47, oldno); - cl_assert_equal_i(47, newno); + cl_assert_equal_i(47, line->old_lineno); + cl_assert_equal_i(47, line->new_lineno); - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &text, &textlen, &oldno, &newno, patch, 0, 2)); - cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)origin); - cl_git_pass(git_buf_set(&actual, text, textlen)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 2)); + cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); cl_assert_equal_s("\n", actual.ptr); - cl_assert_equal_i(48, oldno); - cl_assert_equal_i(48, newno); + cl_assert_equal_i(48, line->old_lineno); + cl_assert_equal_i(48, line->new_lineno); - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &text, &textlen, &oldno, &newno, patch, 0, 3)); - cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)origin); - cl_git_pass(git_buf_set(&actual, text, textlen)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 3)); + cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); cl_assert_equal_s(" -- Rudyard Kipling\n", actual.ptr); - cl_assert_equal_i(49, oldno); - cl_assert_equal_i(-1, newno); + cl_assert_equal_i(49, line->old_lineno); + cl_assert_equal_i(-1, line->new_lineno); - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &text, &textlen, &oldno, &newno, patch, 0, 4)); - cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)origin); - cl_git_pass(git_buf_set(&actual, text, textlen)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 4)); + cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); cl_assert_equal_s(" -- Rudyard Kipling", actual.ptr); - cl_assert_equal_i(-1, oldno); - cl_assert_equal_i(49, newno); + cl_assert_equal_i(-1, line->old_lineno); + cl_assert_equal_i(49, line->new_lineno); - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &text, &textlen, &oldno, &newno, patch, 0, 5)); - cl_assert_equal_i(GIT_DIFF_LINE_DEL_EOFNL, (int)origin); - cl_git_pass(git_buf_set(&actual, text, textlen)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 5)); + cl_assert_equal_i(GIT_DIFF_LINE_DEL_EOFNL, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); cl_assert_equal_s("\n\\ No newline at end of file\n", actual.ptr); - cl_assert_equal_i(-1, oldno); - cl_assert_equal_i(49, newno); + cl_assert_equal_i(-1, line->old_lineno); + cl_assert_equal_i(49, line->new_lineno); git_patch_free(patch); git_diff_free(diff); @@ -465,31 +447,34 @@ static void check_single_patch_stats( /* walk lines in hunk with basic sanity checks */ for (; hunks > 0; --hunks) { size_t i, max_i; - int lastoldno = -1, oldno, lastnewno = -1, newno; - char origin; + const git_diff_line *line; + int last_new_lineno = -1, last_old_lineno = -1; max_i = git_patch_num_lines_in_hunk(patch, hunks - 1); for (i = 0; i < max_i; ++i) { int expected = 1; - cl_git_pass(git_patch_get_line_in_hunk( - &origin, NULL, NULL, &oldno, &newno, patch, hunks - 1, i)); + cl_git_pass( + git_patch_get_line_in_hunk(&line, patch, hunks - 1, i)); - if (origin == GIT_DIFF_LINE_ADD_EOFNL || - origin == GIT_DIFF_LINE_DEL_EOFNL || - origin == GIT_DIFF_LINE_CONTEXT_EOFNL) + if (line->origin == GIT_DIFF_LINE_ADD_EOFNL || + line->origin == GIT_DIFF_LINE_DEL_EOFNL || + line->origin == GIT_DIFF_LINE_CONTEXT_EOFNL) expected = 0; - if (oldno >= 0) { - if (lastoldno >= 0) - cl_assert_equal_i(expected, oldno - lastoldno); - lastoldno = oldno; + if (line->old_lineno >= 0) { + if (last_old_lineno >= 0) + cl_assert_equal_i( + expected, line->old_lineno - last_old_lineno); + last_old_lineno = line->old_lineno; } - if (newno >= 0) { - if (lastnewno >= 0) - cl_assert_equal_i(expected, newno - lastnewno); - lastnewno = newno; + + if (line->new_lineno >= 0) { + if (last_new_lineno >= 0) + cl_assert_equal_i( + expected, line->new_lineno - last_new_lineno); + last_new_lineno = line->new_lineno; } } } diff --git a/tests-clar/diff/tree.c b/tests-clar/diff/tree.c index 8231d3632..ca2daf5fb 100644 --- a/tests-clar/diff/tree.c +++ b/tests-clar/diff/tree.c @@ -257,11 +257,10 @@ void test_diff_tree__larger_hunks(void) { const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69"; const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10"; - size_t d, num_d, h, num_h, l, num_l, header_len, line_len; + size_t d, num_d, h, num_h, l, num_l; git_patch *patch; - const git_diff_hunk *range; - const char *header, *line; - char origin; + const git_diff_hunk *hunk; + const git_diff_line *line; g_repo = cl_git_sandbox_init("diff"); @@ -280,21 +279,17 @@ void test_diff_tree__larger_hunks(void) num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { - cl_git_pass(git_patch_get_hunk( - &range, &header, &header_len, &num_l, patch, h)); + cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h)); for (l = 0; l < num_l; ++l) { - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &line, &line_len, NULL, NULL, patch, h, l)); + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l)); cl_assert(line); } - cl_git_fail(git_patch_get_line_in_hunk( - &origin, &line, &line_len, NULL, NULL, patch, h, num_l)); + cl_git_fail(git_patch_get_line_in_hunk(&line, patch, h, num_l)); } - cl_git_fail(git_patch_get_hunk( - &range, &header, &header_len, &num_l, patch, num_h)); + cl_git_fail(git_patch_get_hunk(&hunk, &num_l, patch, num_h)); git_patch_free(patch); } diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index ee63a700d..474891c16 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -673,7 +673,7 @@ void test_diff_workdir__larger_hunks(void) const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10"; git_tree *a, *b; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - size_t i, d, num_d, h, num_h, l, num_l, header_len, line_len; + size_t i, d, num_d, h, num_h, l, num_l; g_repo = cl_git_sandbox_init("diff"); @@ -686,9 +686,8 @@ void test_diff_workdir__larger_hunks(void) for (i = 0; i <= 2; ++i) { git_diff *diff = NULL; git_patch *patch; - const git_diff_hunk *range; - const char *header, *line; - char origin; + const git_diff_hunk *hunk; + const git_diff_line *line; /* okay, this is a bit silly, but oh well */ switch (i) { @@ -712,23 +711,21 @@ void test_diff_workdir__larger_hunks(void) num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { - cl_git_pass(git_patch_get_hunk( - &range, &header, &header_len, &num_l, patch, h)); + cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h)); for (l = 0; l < num_l; ++l) { - cl_git_pass(git_patch_get_line_in_hunk( - &origin, &line, &line_len, NULL, NULL, patch, h, l)); + cl_git_pass( + git_patch_get_line_in_hunk(&line, patch, h, l)); cl_assert(line); } /* confirm fail after the last item */ - cl_git_fail(git_patch_get_line_in_hunk( - &origin, &line, &line_len, NULL, NULL, patch, h, num_l)); + cl_git_fail( + git_patch_get_line_in_hunk(&line, patch, h, num_l)); } /* confirm fail after the last item */ - cl_git_fail(git_patch_get_hunk( - &range, &header, &header_len, &num_l, patch, num_h)); + cl_git_fail(git_patch_get_hunk(&hunk, &num_l, patch, num_h)); git_patch_free(patch); } -- cgit v1.2.1 From 623460ab139bbb0360f51b26ac27fb6932569278 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 21 Oct 2013 14:16:53 -0700 Subject: Fix warnings for win64 --- src/diff_xdiff.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/diff_xdiff.c b/src/diff_xdiff.c index a90f8d5d1..d07a33221 100644 --- a/src/diff_xdiff.c +++ b/src/diff_xdiff.c @@ -53,7 +53,7 @@ typedef struct { git_xdiff_output *xo; git_patch *patch; git_diff_hunk hunk; - size_t old_lineno, new_lineno; + int old_lineno, new_lineno; } git_xdiff_info; static int diff_update_lines( @@ -77,20 +77,20 @@ static int diff_update_lines( case GIT_DIFF_LINE_DEL_EOFNL: line->old_lineno = -1; line->new_lineno = info->new_lineno; - info->new_lineno += line->num_lines; + info->new_lineno += (int)line->num_lines; break; case GIT_DIFF_LINE_DELETION: case GIT_DIFF_LINE_ADD_EOFNL: line->old_lineno = info->old_lineno; line->new_lineno = -1; - info->old_lineno += line->num_lines; + info->old_lineno += (int)line->num_lines; break; case GIT_DIFF_LINE_CONTEXT: case GIT_DIFF_LINE_CONTEXT_EOFNL: line->old_lineno = info->old_lineno; line->new_lineno = info->new_lineno; - info->old_lineno += line->num_lines; - info->new_lineno += line->num_lines; + info->old_lineno += (int)line->num_lines; + info->new_lineno += (int)line->num_lines; break; default: giterr_set(GITERR_INVALID, "Unknown diff line origin %02x", -- cgit v1.2.1 From 5de4ec810492178095897f726bfaf879994aaf11 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 21 Oct 2013 15:36:38 -0700 Subject: Implement patience and minimal diff flags It seems that to implement these options, we just have to pass the appropriate flags through to the libxdiff code taken from core git. So let's do it (and add a test). --- include/git2/diff.h | 5 ++++- src/diff_xdiff.c | 5 +++++ tests-clar/diff/workdir.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/git2/diff.h b/include/git2/diff.h index ed9f71355..505c3e793 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -175,8 +175,11 @@ typedef enum { */ GIT_DIFF_SHOW_UNMODIFIED = (1u << 26), - /** Use the "patience diff" algorithm (currently unimplemented) */ + /** Use the "patience diff" algorithm */ GIT_DIFF_PATIENCE = (1u << 28), + /** Take extra time to find minimal diff */ + GIT_DIFF_MINIMAL = (1 << 29), + } git_diff_option_t; /** diff --git a/src/diff_xdiff.c b/src/diff_xdiff.c index d07a33221..2aca76f87 100644 --- a/src/diff_xdiff.c +++ b/src/diff_xdiff.c @@ -222,6 +222,11 @@ void git_xdiff_init(git_xdiff_output *xo, const git_diff_options *opts) if (flags & GIT_DIFF_IGNORE_WHITESPACE_EOL) xo->params.flags |= XDF_IGNORE_WHITESPACE_AT_EOL; + if (flags & GIT_DIFF_PATIENCE) + xo->params.flags |= XDF_PATIENCE_DIFF; + if (flags & GIT_DIFF_MINIMAL) + xo->params.flags |= XDF_NEED_MINIMAL; + memset(&xo->callback, 0, sizeof(xo->callback)); xo->callback.outf = git_xdiff_cb; } diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index 474891c16..e72acdb03 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -1282,3 +1282,50 @@ void test_diff_workdir__untracked_with_bom(void) git_diff_free(diff); } + +void test_diff_workdir__patience_diff(void) +{ + git_index *index; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_patch *patch = NULL; + char *as_str = NULL; + const char *expected_normal = "diff --git a/test.txt b/test.txt\nindex 34a5acc..d52725f 100644\n--- a/test.txt\n+++ b/test.txt\n@@ -1,10 +1,7 @@\n When I wrote this\n I did not know\n-how to create\n-a patience diff\n I did not know\n how to create\n+a patience diff\n another problem\n-I did not know\n-how to create\n a minimal diff\n"; + const char *expected_patience = "diff --git a/test.txt b/test.txt\nindex 34a5acc..d52725f 100644\n--- a/test.txt\n+++ b/test.txt\n@@ -1,10 +1,7 @@\n When I wrote this\n I did not know\n+I did not know\n how to create\n a patience diff\n-I did not know\n-how to create\n another problem\n-I did not know\n-how to create\n a minimal diff\n"; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_repo_set_bool(g_repo, "core.autocrlf", true); + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_mkfile( + "empty_standard_repo/test.txt", + "When I wrote this\nI did not know\nhow to create\na patience diff\nI did not know\nhow to create\nanother problem\nI did not know\nhow to create\na minimal diff\n"); + cl_git_pass(git_index_add_bypath(index, "test.txt")); + cl_repo_commit_from_index(NULL, g_repo, NULL, 1372350000, "Base"); + + cl_git_rewritefile( + "empty_standard_repo/test.txt", + "When I wrote this\nI did not know\nI did not know\nhow to create\na patience diff\nanother problem\na minimal diff\n"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + cl_assert_equal_i(1, git_diff_num_deltas(diff)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&as_str, patch)); + + cl_assert_equal_s(expected_normal, as_str); + git__free(as_str); + git_patch_free(patch); + git_diff_free(diff); + + opts.flags |= GIT_DIFF_PATIENCE; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + cl_assert_equal_i(1, git_diff_num_deltas(diff)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&as_str, patch)); + + cl_assert_equal_s(expected_patience, as_str); + git__free(as_str); + git_patch_free(patch); + git_diff_free(diff); +} -- cgit v1.2.1 From 98fec8a937b93c6a6a0ad35ccd04af4cfeae1767 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 22 Oct 2013 16:05:47 +0200 Subject: Implement `git_odb_object_dup` --- include/git2/odb.h | 14 ++++++++++++++ src/odb.c | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/include/git2/odb.h b/include/git2/odb.h index 3bd18e782..ad56384f0 100644 --- a/include/git2/odb.h +++ b/include/git2/odb.h @@ -357,6 +357,20 @@ GIT_EXTERN(int) git_odb_hash(git_oid *out, const void *data, size_t len, git_oty */ GIT_EXTERN(int) git_odb_hashfile(git_oid *out, const char *path, git_otype type); +/** + * Create a copy of an odb_object + * + * The returned copy must be manually freed with `git_odb_object_free`. + * Note that because of an implementation detail, the returned copy will be + * the same pointer as `source`: the object is internally refcounted, so the + * copy still needs to be freed twice. + * + * @param dest pointer where to store the copy + * @param source object to copy + * @return 0 or an error code + */ +GIT_EXTERN(int) git_odb_object_dup(git_odb_object **dest, git_odb_object *source); + /** * Close an ODB object * diff --git a/src/odb.c b/src/odb.c index b2c138aae..2da9937ff 100644 --- a/src/odb.c +++ b/src/odb.c @@ -124,6 +124,13 @@ git_otype git_odb_object_type(git_odb_object *object) return object->cached.type; } +int git_odb_object_dup(git_odb_object **dest, git_odb_object *source) +{ + git_cached_obj_incref(source); + *dest = source; + return 0; +} + void git_odb_object_free(git_odb_object *object) { if (object == NULL) -- cgit v1.2.1 From 7ce60099eec2442cc5428a830b88d51e8f9c1d75 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 22 Oct 2013 11:12:44 -0700 Subject: Fix typo --- include/git2/diff.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/git2/diff.h b/include/git2/diff.h index 505c3e793..5d360bedb 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -853,7 +853,7 @@ typedef enum { * iteration and cause this return `GIT_EUSER`. * * @param diff A git_diff generated by one of the above functions. - * @param format A git_diff_forrmat_t value to pick the text format. + * @param format A git_diff_format_t value to pick the text format. * @param print_cb Callback to make per line of diff text. * @param payload Reference pointer that will be passed to your callback. * @return 0 on success, GIT_EUSER on non-zero callback, or error code -- cgit v1.2.1 From 70a8c78f3618d70cf6de0961e4e3884a003a1ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 23 Oct 2013 12:08:54 +0200 Subject: Rename the ssh credentials The names from libssh2 are somewhat obtuse for us. We can simplify the usual key/passphrase credential's name, as well as make clearer what the custom signature function is. --- include/git2/transport.h | 42 ++++++++++++++++++++++++++---------------- src/transports/cred.c | 38 +++++++++++++++++++------------------- src/transports/ssh.c | 12 ++++++------ tests-clar/online/push.c | 4 ++-- 4 files changed, 53 insertions(+), 43 deletions(-) diff --git a/include/git2/transport.h b/include/git2/transport.h index 065b31820..2cbae2f70 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -33,11 +33,11 @@ typedef enum { /* git_cred_userpass_plaintext */ GIT_CREDTYPE_USERPASS_PLAINTEXT = (1u << 0), - /* git_cred_ssh_keyfile_passphrase */ - GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE = (1u << 1), + /* git_cred_ssh_key */ + GIT_CREDTYPE_SSH_KEY = (1u << 1), - /* git_cred_ssh_publickey */ - GIT_CREDTYPE_SSH_PUBLICKEY = (1u << 2), + /* git_cred_ssh_custom */ + GIT_CREDTYPE_SSH_CUSTOM = (1u << 2), } git_credtype_t; /* The base structure for all credential types */ @@ -61,24 +61,28 @@ typedef LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*git_cred_sign_callback)); typedef int (*git_cred_sign_callback)(void *, ...); #endif -/* An ssh key file and passphrase */ -typedef struct git_cred_ssh_keyfile_passphrase { +/** + * A ssh key from disk + */ +typedef struct git_cred_ssh_key { git_cred parent; char *username; char *publickey; char *privatekey; char *passphrase; -} git_cred_ssh_keyfile_passphrase; +} git_cred_ssh_key; -/* An ssh public key and authentication callback */ -typedef struct git_cred_ssh_publickey { +/** + * A key with a custom signature function + */ +typedef struct git_cred_ssh_custom { git_cred parent; char *username; char *publickey; size_t publickey_len; void *sign_callback; void *sign_data; -} git_cred_ssh_publickey; +} git_cred_ssh_custom; /** * Check whether a credential object contains username information. @@ -89,7 +93,7 @@ typedef struct git_cred_ssh_publickey { GIT_EXTERN(int) git_cred_has_username(git_cred *cred); /** - * Creates a new plain-text username and password credential object. + * Create a new plain-text username and password credential object. * The supplied credential parameter will be internally duplicated. * * @param out The newly created credential object. @@ -103,7 +107,7 @@ GIT_EXTERN(int) git_cred_userpass_plaintext_new( const char *password); /** - * Creates a new ssh key file and passphrase credential object. + * Create a new passphrase-protected ssh key credential object. * The supplied credential parameter will be internally duplicated. * * @param out The newly created credential object. @@ -113,15 +117,21 @@ GIT_EXTERN(int) git_cred_userpass_plaintext_new( * @param passphrase The passphrase of the credential. * @return 0 for success or an error code for failure */ -GIT_EXTERN(int) git_cred_ssh_keyfile_passphrase_new( +GIT_EXTERN(int) git_cred_ssh_key_new( git_cred **out, const char *username, const char *publickey, const char *privatekey, - const char *passphrase); + const char *passphrase); /** - * Creates a new ssh public key credential object. + * Create an ssh key credential with a custom signing function. + * + * This lets you use your own function to sign the challenge. + * + * This function and its credential type is provided for completeness + * and wraps `libssh2_userauth_publickey()`, which is undocumented. + * * The supplied credential parameter will be internally duplicated. * * @param out The newly created credential object. @@ -132,7 +142,7 @@ GIT_EXTERN(int) git_cred_ssh_keyfile_passphrase_new( * @param sign_data The data to pass to the sign function. * @return 0 for success or an error code for failure */ -GIT_EXTERN(int) git_cred_ssh_publickey_new( +GIT_EXTERN(int) git_cred_ssh_custom_new( git_cred **out, const char *username, const char *publickey, diff --git a/src/transports/cred.c b/src/transports/cred.c index 79b17e88d..cc7fdab4b 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -19,13 +19,13 @@ int git_cred_has_username(git_cred *cred) ret = !!c->username; break; } - case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: { - git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred; + case GIT_CREDTYPE_SSH_KEY: { + git_cred_ssh_key *c = (git_cred_ssh_key *)cred; ret = !!c->username; break; } - case GIT_CREDTYPE_SSH_PUBLICKEY: { - git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred; + case GIT_CREDTYPE_SSH_CUSTOM: { + git_cred_ssh_custom *c = (git_cred_ssh_custom *)cred; ret = !!c->username; break; } @@ -84,10 +84,10 @@ int git_cred_userpass_plaintext_new( return 0; } -static void ssh_keyfile_passphrase_free(struct git_cred *cred) +static void ssh_key_free(struct git_cred *cred) { - git_cred_ssh_keyfile_passphrase *c = - (git_cred_ssh_keyfile_passphrase *)cred; + git_cred_ssh_key *c = + (git_cred_ssh_key *)cred; git__free(c->username); git__free(c->publickey); @@ -104,9 +104,9 @@ static void ssh_keyfile_passphrase_free(struct git_cred *cred) git__free(c); } -static void ssh_publickey_free(struct git_cred *cred) +static void ssh_custom_free(struct git_cred *cred) { - git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred; + git_cred_ssh_custom *c = (git_cred_ssh_custom *)cred; git__free(c->username); git__free(c->publickey); @@ -115,22 +115,22 @@ static void ssh_publickey_free(struct git_cred *cred) git__free(c); } -int git_cred_ssh_keyfile_passphrase_new( +int git_cred_ssh_key_new( git_cred **cred, const char *username, const char *publickey, const char *privatekey, const char *passphrase) { - git_cred_ssh_keyfile_passphrase *c; + git_cred_ssh_key *c; assert(cred && privatekey); - c = git__calloc(1, sizeof(git_cred_ssh_keyfile_passphrase)); + c = git__calloc(1, sizeof(git_cred_ssh_key)); GITERR_CHECK_ALLOC(c); - c->parent.credtype = GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE; - c->parent.free = ssh_keyfile_passphrase_free; + c->parent.credtype = GIT_CREDTYPE_SSH_KEY; + c->parent.free = ssh_key_free; if (username) { c->username = git__strdup(username); @@ -154,7 +154,7 @@ int git_cred_ssh_keyfile_passphrase_new( return 0; } -int git_cred_ssh_publickey_new( +int git_cred_ssh_custom_new( git_cred **cred, const char *username, const char *publickey, @@ -162,15 +162,15 @@ int git_cred_ssh_publickey_new( git_cred_sign_callback sign_callback, void *sign_data) { - git_cred_ssh_publickey *c; + git_cred_ssh_custom *c; assert(cred); - c = git__calloc(1, sizeof(git_cred_ssh_publickey)); + c = git__calloc(1, sizeof(git_cred_ssh_custom)); GITERR_CHECK_ALLOC(c); - c->parent.credtype = GIT_CREDTYPE_SSH_PUBLICKEY; - c->parent.free = ssh_publickey_free; + c->parent.credtype = GIT_CREDTYPE_SSH_CUSTOM; + c->parent.free = ssh_custom_free; if (username) { c->username = git__strdup(username); diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 647211f63..6ce673d5e 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -249,15 +249,15 @@ static int _git_ssh_authenticate_session( rc = libssh2_userauth_password(session, user, c->password); break; } - case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: { - git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred; + case GIT_CREDTYPE_SSH_KEY: { + git_cred_ssh_key *c = (git_cred_ssh_key *)cred; user = c->username ? c->username : user; rc = libssh2_userauth_publickey_fromfile( session, c->username, c->publickey, c->privatekey, c->passphrase); break; } - case GIT_CREDTYPE_SSH_PUBLICKEY: { - git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred; + case GIT_CREDTYPE_SSH_CUSTOM: { + git_cred_ssh_custom *c = (git_cred_ssh_custom *)cred; user = c->username ? c->username : user; rc = libssh2_userauth_publickey( @@ -349,8 +349,8 @@ static int _git_ssh_setup_conn( if (t->owner->cred_acquire_cb( &t->cred, t->owner->url, user, GIT_CREDTYPE_USERPASS_PLAINTEXT | - GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE | - GIT_CREDTYPE_SSH_PUBLICKEY, + GIT_CREDTYPE_SSH_KEY | + GIT_CREDTYPE_SSH_CUSTOM, t->owner->cred_acquire_payload) < 0) goto on_error; diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index d3d23740f..fa210d7cd 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -47,12 +47,12 @@ static int cred_acquire_cb( GIT_UNUSED(user_from_url); GIT_UNUSED(payload); - if (GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE & allowed_types) { + if (GIT_CREDTYPE_SSH_KEY & allowed_types) { if (!_remote_user || !_remote_ssh_pubkey || !_remote_ssh_key || !_remote_ssh_passphrase) { printf("GITTEST_REMOTE_USER, GITTEST_REMOTE_SSH_PUBKEY, GITTEST_REMOTE_SSH_KEY and GITTEST_REMOTE_SSH_PASSPHRASE must be set\n"); return -1; } - return git_cred_ssh_keyfile_passphrase_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase); + return git_cred_ssh_key_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase); } if (GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) { -- cgit v1.2.1 From 1ecda61ec570873dd72fd129cd1bfe6a08d5a81a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 23 Oct 2013 12:58:56 +0200 Subject: Set the correct dependencies in the pkg-config file When linking statically, the including project needs to know what the current library build depends on so they can link to it. Store this information in the pkg-config file. While here, remove claims that users need to link to zlib or libcrypto. --- CMakeLists.txt | 14 ++++++++++++++ libgit2.pc.in | 5 +++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c7414996b..94418f85b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,15 @@ IF(MSVC) OPTION( STATIC_CRT "Link the static CRT libraries" ON ) ENDIF() +# This variable will contain the libraries we need to put into +# libgit2.pc's Requires.private. That is, what we're linking to or +# what someone who's statically linking us needs to link to. +SET(LIBGIT2_PC_REQUIRES "") +# This will be set later if we use the system's http-parser library or +# use iconv (OSX) and will be written to the Libs.private field in the +# pc file. +SET(LIBGIT2_PC_LIBS "") + # Installation paths # SET(BIN_INSTALL_DIR bin CACHE PATH "Where to install binaries to.") @@ -68,6 +77,7 @@ FUNCTION(TARGET_OS_LIBRARIES target) IF(USE_ICONV) TARGET_LINK_LIBRARIES(${target} iconv) ADD_DEFINITIONS(-DGIT_USE_ICONV) + SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -liconv") ENDIF() IF(THREADSAFE) @@ -119,6 +129,7 @@ ELSE () IF (HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2) INCLUDE_DIRECTORIES(${HTTP_PARSER_INCLUDE_DIRS}) LINK_LIBRARIES(${HTTP_PARSER_LIBRARIES}) + SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lhttp_parser") ELSE() MESSAGE("http-parser was not found or is too old; using bundled 3rd-party sources.") INCLUDE_DIRECTORIES(deps/http-parser) @@ -132,6 +143,7 @@ IF (WIN32 AND NOT MINGW AND NOT SHA1_TYPE STREQUAL "builtin") FILE(GLOB SRC_SHA1 src/hash/hash_win32.c) ELSEIF (OPENSSL_FOUND AND NOT SHA1_TYPE STREQUAL "builtin") ADD_DEFINITIONS(-DOPENSSL_SHA1) + SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} openssl") ELSE() FILE(GLOB SRC_SHA1 src/hash/hash_generic.c) ENDIF() @@ -154,6 +166,7 @@ FIND_PACKAGE(ZLIB QUIET) IF (ZLIB_FOUND) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS}) LINK_LIBRARIES(${ZLIB_LIBRARIES}) + SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} zlib") # Fake the message CMake would have shown MESSAGE("-- Found zlib: ${ZLIB_LIBRARY}") ELSE() @@ -169,6 +182,7 @@ ENDIF() IF (LIBSSH2_FOUND) ADD_DEFINITIONS(-DGIT_SSH) INCLUDE_DIRECTORIES(${LIBSSH2_INCLUDE_DIR}) + SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} libssh2") SET(SSH_LIBRARIES ${LIBSSH2_LIBRARIES}) ENDIF() diff --git a/libgit2.pc.in b/libgit2.pc.in index 52ad901f7..8f5279234 100644 --- a/libgit2.pc.in +++ b/libgit2.pc.in @@ -4,6 +4,7 @@ includedir=@CMAKE_INSTALL_PREFIX@/@INCLUDE_INSTALL_DIR@ Name: libgit2 Description: The git library, take 2 Version: @LIBGIT2_VERSION_STRING@ -Requires: libcrypto -Libs: -L${libdir} -lgit2 -lz -lcrypto +Requires.private: @LIBGIT2_PC_REQUIRES@ +Libs.private: @LIBGIT2_PC_LIBS@ +Libs: -L${libdir} -lgit2 Cflags: -I${includedir} -- cgit v1.2.1 From 2baee9f81e6a7d8b5e9e31269908ec0d25610b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 23 Oct 2013 13:17:51 +0200 Subject: README: add a note about the optional dependencies --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 0d735c397..f400a9fae 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,17 @@ and also powering Microsoft's Visual Studio tools for Git. The library provides * descriptive and detailed error messages * ...and more (over 175 different API calls) +Optional dependencies +===================== + +While the library provides git functionality without the need for +dependencies, it can make use of a few libraries to add to it: + +- pthreads (non-Windows) to enable threadsafe access as well as multi-threaded pack generation +- OpenSSL (non-Windows) to talk over HTTPS and provide the SHA-1 functions +- LibSSH2 to enable the ssh transport +- iconv (OSX) to handle the HFS+ path encoding peculiarities + Building libgit2 - Using CMake ============================== -- cgit v1.2.1 From ebbd48f00e87eab699862f03a457571ead3c53b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 23 Oct 2013 14:22:44 +0200 Subject: examples: show used local objects in fetch Show how many local objects were used to fix the thin pack in our fetch example. --- examples/network/fetch.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/network/fetch.c b/examples/network/fetch.c index ce016ce0b..50ec0033a 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -125,8 +125,13 @@ int fetch(git_repository *repo, int argc, char **argv) pthread_join(worker, NULL); #endif - printf("\rReceived %d/%d objects in %zu bytes\n", + if (stats->local_objects > 0) { + printf("\rReceived %d/%d objects in %zu bytes (used %d local objects)\n", + stats->indexed_objects, stats->total_objects, stats->received_bytes, stats->local_objects); + } else{ + printf("\rReceived %d/%d objects in %zu bytes\n", stats->indexed_objects, stats->total_objects, stats->received_bytes); + } // Disconnect the underlying connection to prevent from idling. git_remote_disconnect(remote); -- cgit v1.2.1 From ab46b1d8ebcdc820aefe2c1391d4be73939bce95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 23 Oct 2013 15:08:18 +0200 Subject: indexer: include the delta stats The user is unable to derive the number of deltas in the pack, as that would require them to capture the stats exactly in the moment between download and final processing, which is abstracted away in the fetch. Capture these numbers for the user and expose them in the progress struct. The clone and fetch examples now also present this information to the user. --- examples/network/clone.c | 8 +++++++- examples/network/fetch.c | 7 ++++++- include/git2/types.h | 2 ++ src/indexer.c | 6 ++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index a09a94728..54c90aff8 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -25,13 +25,19 @@ static void print_progress(const progress_data *pd) : 0.f; int kbytes = pd->fetch_progress.received_bytes / 1024; - printf("net %3d%% (%4d kb, %5d/%5d) / idx %3d%% (%5d/%5d) / chk %3d%% (%4" PRIuZ "/%4" PRIuZ ") %s\n", + if (pd->fetch_progress.received_objects == pd->fetch_progress.total_objects) { + printf("Resolving deltas %d/%d\r", + pd->fetch_progress.indexed_deltas, + pd->fetch_progress.total_deltas); + } else { + printf("net %3d%% (%4d kb, %5d/%5d) / idx %3d%% (%5d/%5d) / chk %3d%% (%4" PRIuZ "/%4" PRIuZ ") %s\n", network_percent, kbytes, pd->fetch_progress.received_objects, pd->fetch_progress.total_objects, index_percent, pd->fetch_progress.indexed_objects, pd->fetch_progress.total_objects, checkout_percent, pd->completed_steps, pd->total_steps, pd->path); + } } static int fetch_progress(const git_transfer_progress *stats, void *payload) diff --git a/examples/network/fetch.c b/examples/network/fetch.c index 50ec0033a..b4f6a6ad6 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -72,6 +72,7 @@ int fetch(git_repository *repo, int argc, char **argv) const git_transfer_progress *stats; struct dl_data data; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + int resolve_deltas_ln = 0; #ifndef _WIN32 pthread_t worker; #endif @@ -113,10 +114,14 @@ int fetch(git_repository *repo, int argc, char **argv) do { usleep(10000); - if (stats->total_objects > 0) + if (stats->received_objects == stats->total_objects) { + printf("Resolving deltas %d/%d\r", + stats->indexed_deltas, stats->total_deltas); + } else if (stats->total_objects > 0) { printf("Received %d/%d objects (%d) in %" PRIuZ " bytes\r", stats->received_objects, stats->total_objects, stats->indexed_objects, stats->received_bytes); + } } while (!data.finished); if (data.ret < 0) diff --git a/include/git2/types.h b/include/git2/types.h index 4ff2ba4c4..2d18d385a 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -225,6 +225,8 @@ typedef struct git_transfer_progress { unsigned int indexed_objects; unsigned int received_objects; unsigned int local_objects; + unsigned int total_deltas; + unsigned int indexed_deltas; size_t received_bytes; } git_transfer_progress; diff --git a/src/indexer.c b/src/indexer.c index 93ad116fe..f6e9ad902 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -483,6 +483,8 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz stats->received_objects = 0; stats->local_objects = 0; + stats->total_deltas = 0; + stats->indexed_deltas = 0; processed = stats->indexed_objects = 0; stats->total_objects = total_objects; do_progress_callback(idx, stats); @@ -758,6 +760,7 @@ static int resolve_deltas(git_indexer_stream *idx, git_transfer_progress *stats) git__free(obj.data); stats->indexed_objects++; + stats->indexed_deltas++; progressed = 1; do_progress_callback(idx, stats); @@ -866,6 +869,9 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * return -1; } + /* Freeze the number of deltas */ + stats->total_deltas = stats->total_objects - stats->indexed_objects; + if (resolve_deltas(idx, stats) < 0) return -1; -- cgit v1.2.1 From 5cb136705d7db2822357582d5b726c91ca044b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 23 Oct 2013 15:45:29 +0200 Subject: transport: let the progress output return an error There are any number of issues that can come up in the progress callback, and we should let the user cancel at that point as well. --- include/git2/remote.h | 2 +- include/git2/transport.h | 2 +- src/transports/smart_protocol.c | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 9858634cc..f4cd1cbfa 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -410,7 +410,7 @@ struct git_remote_callbacks { * progress side-band will be passed to this function (this is * the 'counting objects' output. */ - void (*progress)(const char *str, int len, void *data); + int (*progress)(const char *str, int len, void *data); /** * Completion is called when different parts of the download diff --git a/include/git2/transport.h b/include/git2/transport.h index 065b31820..b9fda80ba 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -170,7 +170,7 @@ typedef enum { GIT_TRANSPORTFLAGS_NO_CHECK_CERT = 1 } git_transport_flags_t; -typedef void (*git_transport_message_cb)(const char *str, int len, void *data); +typedef int (*git_transport_message_cb)(const char *str, int len, void *data); typedef struct git_transport git_transport; diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 24677908e..3b4d57856 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -509,7 +509,10 @@ int git_smart__download_pack( if (pkt->type == GIT_PKT_PROGRESS) { if (t->progress_cb) { git_pkt_progress *p = (git_pkt_progress *) pkt; - t->progress_cb(p->data, p->len, t->message_cb_payload); + if (t->progress_cb(p->data, p->len, t->message_cb_payload)) { + giterr_set(GITERR_NET, "The fetch was cancelled by the user"); + return GIT_EUSER; + } } git__free(pkt); } else if (pkt->type == GIT_PKT_DATA) { -- cgit v1.2.1 From 474c8cf8329c96782942763712d372534e862f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 23 Oct 2013 22:49:52 +0200 Subject: Really fix the pc file It turns out that variables have function scope by default. Let's really set -liconv and add a few libraries that were forgotten in the previous commit. We also need to special-case OSX, as they ship zlib but do not provide a pkg-config file for it. --- CMakeLists.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 94418f85b..6010b63a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,14 +70,16 @@ FUNCTION(TARGET_OS_LIBRARIES target) TARGET_LINK_LIBRARIES(${target} ws2_32) ELSEIF(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") TARGET_LINK_LIBRARIES(${target} socket nsl) + SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lsocket -lnsl" PARENT_SCOPE) ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux") TARGET_LINK_LIBRARIES(${target} rt) + SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lrt" PARENT_SCOPE) ENDIF() IF(USE_ICONV) TARGET_LINK_LIBRARIES(${target} iconv) ADD_DEFINITIONS(-DGIT_USE_ICONV) - SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -liconv") + SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -liconv" PARENT_SCOPE) ENDIF() IF(THREADSAFE) @@ -166,7 +168,11 @@ FIND_PACKAGE(ZLIB QUIET) IF (ZLIB_FOUND) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS}) LINK_LIBRARIES(${ZLIB_LIBRARIES}) - SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} zlib") + IF(APPLE) + SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} -lz") + ELSE() + SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} zlib") + ENDIF() # Fake the message CMake would have shown MESSAGE("-- Found zlib: ${ZLIB_LIBRARY}") ELSE() -- cgit v1.2.1 From 63d1fad47063a256de002f2c9d8228accac6721d Mon Sep 17 00:00:00 2001 From: Nicolas Kaiser Date: Thu, 24 Oct 2013 15:30:31 +0200 Subject: fix typos in README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f400a9fae..ce5e22915 100644 --- a/README.md +++ b/README.md @@ -123,8 +123,8 @@ Android ------- Extract toolchain from NDK using, `make-standalone-toolchain.sh` script. -Optionaly, crosscompile and install OpenSSL inside of it. Then create CMake -toolchain file that configures paths to your crosscompiler (substitude `{PATH}` +Optionally, crosscompile and install OpenSSL inside of it. Then create CMake +toolchain file that configures paths to your crosscompiler (substitute `{PATH}` with full path to the toolchain): SET(CMAKE_SYSTEM_NAME Linux) @@ -166,7 +166,7 @@ Here are the bindings to libgit2 that are currently available: * luagit2 * .NET * libgit2sharp - * libgit2net, low level bindings superceeded by libgit2sharp + * libgit2net, low level bindings superseded by libgit2sharp * Node.js * node-gitteh * nodegit -- cgit v1.2.1 From 1bfe7133e022871bd9e8f0bada14ccb8ec688a2e Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 25 Oct 2013 13:23:46 -0400 Subject: Allow -DWINHTTP=OFF to disable WinHTTP --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6010b63a6..a14abae0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,10 @@ IF(MSVC) # This option must match the settings used in your program, in particular if you # are linking statically OPTION( STATIC_CRT "Link the static CRT libraries" ON ) + + # By default, libgit2 is built with WinHTTP. To use the built-in + # HTTP transport, invoke CMake with the "-DWINHTTP=OFF" argument. + OPTION( WINHTTP "Use Win32 WinHTTP routines" ON ) ENDIF() # This variable will contain the libraries we need to put into @@ -120,7 +124,7 @@ SET(LIBGIT2_VERSION_STRING "${LIBGIT2_VERSION_MAJOR}.${LIBGIT2_VERSION_MINOR}.${ # Find required dependencies INCLUDE_DIRECTORIES(src include) -IF (WIN32 AND NOT MINGW) +IF (WIN32 AND WINHTTP AND NOT MINGW) ADD_DEFINITIONS(-DGIT_WINHTTP) ELSE () IF (NOT AMIGA) -- cgit v1.2.1 From df9fc82e97282170ec87e84f655ee468bf8afe7b Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 25 Oct 2013 13:33:42 -0400 Subject: Use two calls to set two headers --- src/transports/winhttp.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 702243513..a25fa301e 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -269,14 +269,27 @@ static int winhttp_stream_connect(winhttp_stream *s) /* Send Content-Type and Accept headers -- only necessary on a POST */ git_buf_clear(&buf); if (git_buf_printf(&buf, - "Content-Type: application/x-git-%s-request\r\n" - "Accept: application/x-git-%s-result\r\n", - s->service, s->service) < 0) + "Content-Type: application/x-git-%s-request", + s->service) < 0) goto on_error; git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)); - if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG) -1L, + 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"); + goto on_error; + } + + git_buf_clear(&buf); + if (git_buf_printf(&buf, + "Accept: application/x-git-%s-result", + s->service) < 0) + goto on_error; + + git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)); + + 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"); goto on_error; -- cgit v1.2.1 From 9d41984cd35a267b1f863faad796bb0066b26f5b Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 25 Oct 2013 14:14:22 -0400 Subject: Test for failure, but don't test the error message --- tests-clar/online/push.c | 75 +++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index d3d23740f..38ffc0854 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -67,8 +67,11 @@ static int cred_acquire_cb( return -1; } +/* the results of a push status. when used for expected values, msg may be NULL + * to indicate that it should not be matched. */ typedef struct { const char *ref; + int success; const char *msg; } push_status; @@ -83,6 +86,7 @@ static int record_push_status_cb(const char *ref, const char *msg, void *data) cl_assert(s = git__malloc(sizeof(*s))); s->ref = ref; + s->success = (msg == NULL); s->msg = msg; git_vector_insert(statuses, s); @@ -104,9 +108,8 @@ static void do_verify_push_status(git_push *push, const push_status expected[], else git_vector_foreach(&actual, i, iter) if (strcmp(expected[i].ref, iter->ref) || - (expected[i].msg && !iter->msg) || - (!expected[i].msg && iter->msg) || - (expected[i].msg && iter->msg && strcmp(expected[i].msg, iter->msg))) { + (expected[i].success != iter->success) || + (expected[i].msg && (!iter->msg || strcmp(expected[i].msg, iter->msg)))) { failed = true; break; } @@ -119,13 +122,17 @@ static void do_verify_push_status(git_push *push, const push_status expected[], for(i = 0; i < expected_len; i++) { git_buf_printf(&msg, "%s: %s\n", expected[i].ref, - expected[i].msg ? expected[i].msg : ""); + expected[i].success ? "success" : "failed"); } git_buf_puts(&msg, "\nACTUAL:\n"); - git_vector_foreach(&actual, i, iter) - git_buf_printf(&msg, "%s: %s\n", iter->ref, iter->msg); + git_vector_foreach(&actual, i, iter) { + if (iter->success) + git_buf_printf(&msg, "%s: success\n", iter->ref); + else + git_buf_printf(&msg, "%s: failed with message: %s", iter->ref, iter->msg); + } cl_fail(git_buf_cstr(&msg)); @@ -445,7 +452,7 @@ void test_online_push__noop(void) void test_online_push__b1(void) { const char *specs[] = { "refs/heads/b1:refs/heads/b1" }; - push_status exp_stats[] = { { "refs/heads/b1", NULL } }; + push_status exp_stats[] = { { "refs/heads/b1", 1 } }; expected_ref exp_refs[] = { { "refs/heads/b1", &_oid_b1 } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), @@ -455,7 +462,7 @@ void test_online_push__b1(void) void test_online_push__b2(void) { const char *specs[] = { "refs/heads/b2:refs/heads/b2" }; - push_status exp_stats[] = { { "refs/heads/b2", NULL } }; + push_status exp_stats[] = { { "refs/heads/b2", 1 } }; expected_ref exp_refs[] = { { "refs/heads/b2", &_oid_b2 } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), @@ -465,7 +472,7 @@ void test_online_push__b2(void) void test_online_push__b3(void) { const char *specs[] = { "refs/heads/b3:refs/heads/b3" }; - push_status exp_stats[] = { { "refs/heads/b3", NULL } }; + push_status exp_stats[] = { { "refs/heads/b3", 1 } }; expected_ref exp_refs[] = { { "refs/heads/b3", &_oid_b3 } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), @@ -475,7 +482,7 @@ void test_online_push__b3(void) void test_online_push__b4(void) { const char *specs[] = { "refs/heads/b4:refs/heads/b4" }; - push_status exp_stats[] = { { "refs/heads/b4", NULL } }; + push_status exp_stats[] = { { "refs/heads/b4", 1 } }; expected_ref exp_refs[] = { { "refs/heads/b4", &_oid_b4 } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), @@ -485,7 +492,7 @@ void test_online_push__b4(void) void test_online_push__b5(void) { const char *specs[] = { "refs/heads/b5:refs/heads/b5" }; - push_status exp_stats[] = { { "refs/heads/b5", NULL } }; + push_status exp_stats[] = { { "refs/heads/b5", 1 } }; expected_ref exp_refs[] = { { "refs/heads/b5", &_oid_b5 } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), @@ -502,11 +509,11 @@ void test_online_push__multi(void) "refs/heads/b5:refs/heads/b5" }; push_status exp_stats[] = { - { "refs/heads/b1", NULL }, - { "refs/heads/b2", NULL }, - { "refs/heads/b3", NULL }, - { "refs/heads/b4", NULL }, - { "refs/heads/b5", NULL } + { "refs/heads/b1", 1 }, + { "refs/heads/b2", 1 }, + { "refs/heads/b3", 1 }, + { "refs/heads/b4", 1 }, + { "refs/heads/b5", 1 } }; expected_ref exp_refs[] = { { "refs/heads/b1", &_oid_b1 }, @@ -523,11 +530,11 @@ void test_online_push__multi(void) void test_online_push__implicit_tgt(void) { const char *specs1[] = { "refs/heads/b1:" }; - push_status exp_stats1[] = { { "refs/heads/b1", NULL } }; + push_status exp_stats1[] = { { "refs/heads/b1", 1 } }; expected_ref exp_refs1[] = { { "refs/heads/b1", &_oid_b1 } }; const char *specs2[] = { "refs/heads/b2:" }; - push_status exp_stats2[] = { { "refs/heads/b2", NULL } }; + push_status exp_stats2[] = { { "refs/heads/b2", 1 } }; expected_ref exp_refs2[] = { { "refs/heads/b1", &_oid_b1 }, { "refs/heads/b2", &_oid_b2 } @@ -546,11 +553,11 @@ void test_online_push__fast_fwd(void) /* Fast forward b1 in tgt from _oid_b1 to _oid_b6. */ const char *specs_init[] = { "refs/heads/b1:refs/heads/b1" }; - push_status exp_stats_init[] = { { "refs/heads/b1", NULL } }; + push_status exp_stats_init[] = { { "refs/heads/b1", 1 } }; expected_ref exp_refs_init[] = { { "refs/heads/b1", &_oid_b1 } }; const char *specs_ff[] = { "refs/heads/b6:refs/heads/b1" }; - push_status exp_stats_ff[] = { { "refs/heads/b1", NULL } }; + push_status exp_stats_ff[] = { { "refs/heads/b1", 1 } }; expected_ref exp_refs_ff[] = { { "refs/heads/b1", &_oid_b6 } }; /* Do a force push to reset b1 in target back to _oid_b1 */ @@ -578,7 +585,7 @@ void test_online_push__fast_fwd(void) void test_online_push__tag_commit(void) { const char *specs[] = { "refs/tags/tag-commit:refs/tags/tag-commit" }; - push_status exp_stats[] = { { "refs/tags/tag-commit", NULL } }; + push_status exp_stats[] = { { "refs/tags/tag-commit", 1 } }; expected_ref exp_refs[] = { { "refs/tags/tag-commit", &_tag_commit } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), @@ -588,7 +595,7 @@ void test_online_push__tag_commit(void) void test_online_push__tag_tree(void) { const char *specs[] = { "refs/tags/tag-tree:refs/tags/tag-tree" }; - push_status exp_stats[] = { { "refs/tags/tag-tree", NULL } }; + push_status exp_stats[] = { { "refs/tags/tag-tree", 1 } }; expected_ref exp_refs[] = { { "refs/tags/tag-tree", &_tag_tree } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), @@ -598,7 +605,7 @@ void test_online_push__tag_tree(void) void test_online_push__tag_blob(void) { const char *specs[] = { "refs/tags/tag-blob:refs/tags/tag-blob" }; - push_status exp_stats[] = { { "refs/tags/tag-blob", NULL } }; + push_status exp_stats[] = { { "refs/tags/tag-blob", 1 } }; expected_ref exp_refs[] = { { "refs/tags/tag-blob", &_tag_blob } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), @@ -608,7 +615,7 @@ void test_online_push__tag_blob(void) void test_online_push__tag_lightweight(void) { const char *specs[] = { "refs/tags/tag-lightweight:refs/tags/tag-lightweight" }; - push_status exp_stats[] = { { "refs/tags/tag-lightweight", NULL } }; + push_status exp_stats[] = { { "refs/tags/tag-lightweight", 1 } }; expected_ref exp_refs[] = { { "refs/tags/tag-lightweight", &_tag_lightweight } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), @@ -618,7 +625,7 @@ void test_online_push__tag_lightweight(void) void test_online_push__tag_to_tag(void) { const char *specs[] = { "refs/tags/tag-tag:refs/tags/tag-tag" }; - push_status exp_stats[] = { { "refs/tags/tag-tag", NULL } }; + push_status exp_stats[] = { { "refs/tags/tag-tag", 1 } }; expected_ref exp_refs[] = { { "refs/tags/tag-tag", &_tag_tag } }; do_push(specs, ARRAY_SIZE(specs), exp_stats, ARRAY_SIZE(exp_stats), @@ -628,13 +635,13 @@ void test_online_push__tag_to_tag(void) void test_online_push__force(void) { const char *specs1[] = {"refs/heads/b3:refs/heads/tgt"}; - push_status exp_stats1[] = { { "refs/heads/tgt", NULL } }; + push_status exp_stats1[] = { { "refs/heads/tgt", 1 } }; expected_ref exp_refs1[] = { { "refs/heads/tgt", &_oid_b3 } }; const char *specs2[] = {"refs/heads/b4:refs/heads/tgt"}; const char *specs2_force[] = {"+refs/heads/b4:refs/heads/tgt"}; - push_status exp_stats2_force[] = { { "refs/heads/tgt", NULL } }; + push_status exp_stats2_force[] = { { "refs/heads/tgt", 1 } }; expected_ref exp_refs2_force[] = { { "refs/heads/tgt", &_oid_b4 } }; do_push(specs1, ARRAY_SIZE(specs1), @@ -658,8 +665,8 @@ void test_online_push__delete(void) "refs/heads/b1:refs/heads/tgt2" }; push_status exp_stats1[] = { - { "refs/heads/tgt1", NULL }, - { "refs/heads/tgt2", NULL } + { "refs/heads/tgt1", 1 }, + { "refs/heads/tgt2", 1 } }; expected_ref exp_refs1[] = { { "refs/heads/tgt1", &_oid_b1 }, @@ -669,10 +676,10 @@ void test_online_push__delete(void) const char *specs_del_fake[] = { ":refs/heads/fake" }; /* Force has no effect for delete. */ const char *specs_del_fake_force[] = { "+:refs/heads/fake" }; - push_status exp_stats_fake[] = { { "refs/heads/fake", NULL } }; + push_status exp_stats_fake[] = { { "refs/heads/fake", 1 } }; const char *specs_delete[] = { ":refs/heads/tgt1" }; - push_status exp_stats_delete[] = { { "refs/heads/tgt1", NULL } }; + push_status exp_stats_delete[] = { { "refs/heads/tgt1", 1 } }; expected_ref exp_refs_delete[] = { { "refs/heads/tgt2", &_oid_b1 } }; /* Force has no effect for delete. */ const char *specs_delete_force[] = { "+:refs/heads/tgt1" }; @@ -731,8 +738,10 @@ void test_online_push__expressions(void) /* TODO: Expressions in refspecs doesn't actually work yet */ const char *specs_left_expr[] = { "refs/heads/b2~1:refs/heads/b2" }; + /* expect not NULL to indicate failure (core git replies "funny refname", + * other servers may be less pithy. */ const char *specs_right_expr[] = { "refs/heads/b2:refs/heads/b2~1" }; - push_status exp_stats_right_expr[] = { { "refs/heads/b2~1", "funny refname" } }; + push_status exp_stats_right_expr[] = { { "refs/heads/b2~1", 0 } }; /* TODO: Find a more precise way of checking errors than a exit code of -1. */ do_push(specs_left_expr, ARRAY_SIZE(specs_left_expr), @@ -749,7 +758,7 @@ void test_online_push__notes(void) git_oid note_oid, *target_oid, expected_oid; git_signature *signature; const char *specs[] = { "refs/notes/commits:refs/notes/commits" }; - push_status exp_stats[] = { { "refs/notes/commits", NULL } }; + push_status exp_stats[] = { { "refs/notes/commits", 1 } }; expected_ref exp_refs[] = { { "refs/notes/commits", &expected_oid } }; git_oid_fromstr(&expected_oid, "8461a99b27b7043e58ff6e1f5d2cf07d282534fb"); -- cgit v1.2.1 From dbc45b88cced070ec221863196024cb2cf96cabb Mon Sep 17 00:00:00 2001 From: Nikolai Vladimirov Date: Sat, 26 Oct 2013 09:13:29 +0300 Subject: remove rpm spec Fedora provides a rpm package for libgit2 - https://apps.fedoraproject.org/packages/libgit2. --- packaging/rpm/README | 6 --- packaging/rpm/libgit2.spec | 106 --------------------------------------------- 2 files changed, 112 deletions(-) delete mode 100644 packaging/rpm/README delete mode 100644 packaging/rpm/libgit2.spec diff --git a/packaging/rpm/README b/packaging/rpm/README deleted file mode 100644 index cc1851fb5..000000000 --- a/packaging/rpm/README +++ /dev/null @@ -1,6 +0,0 @@ -To build RPM packages for Fedora, follow these steps: - cp packaging/rpm/libgit2.spec ~/rpmbuild/SPECS - cd ~/rpmbuild/SOURCES - wget https://github.com/downloads/libgit2/libgit2/libgit2-0.16.0.tar.gz - cd ~/rpmbuild/SPECS - rpmbuild -ba libgit2.spec diff --git a/packaging/rpm/libgit2.spec b/packaging/rpm/libgit2.spec deleted file mode 100644 index 80e70c164..000000000 --- a/packaging/rpm/libgit2.spec +++ /dev/null @@ -1,106 +0,0 @@ -# -# spec file for package libgit2 -# -# Copyright (c) 2012 Saleem Ansari -# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany. -# Copyright (c) 2011, Sascha Peilicke -# -# All modifications and additions to the file contributed by third parties -# remain the property of their copyright owners, unless otherwise agreed -# upon. The license for this file, and modifications and additions to the -# file, is the same license as for the pristine package itself (unless the -# license for the pristine package is not an Open Source License, in which -# case the license is the MIT License). An "Open Source License" is a -# license that conforms to the Open Source Definition (Version 1.9) -# published by the Open Source Initiative. - -# Please submit bugfixes or comments via http://bugs.opensuse.org/ -# -Name: libgit2 -Version: 0.16.0 -Release: 1 -Summary: C git library -License: GPL-2.0 with linking -Group: Development/Libraries/C and C++ -Url: http://libgit2.github.com/ -Source0: https://github.com/downloads/libgit2/libgit2/libgit2-0.16.0.tar.gz -BuildRequires: cmake -BuildRequires: pkgconfig -BuildRoot: %{_tmppath}/%{name}-%{version}-build -%if 0%{?fedora} || 0%{?rhel_version} || 0%{?centos_version} -BuildRequires: openssl-devel -%else -BuildRequires: libopenssl-devel -%endif - -%description -libgit2 is a portable, pure C implementation of the Git core methods -provided as a re-entrant linkable library with a solid API, allowing -you to write native speed custom Git applications in any language -with bindings. - -%package -n %{name}-0 -Summary: C git library -Group: System/Libraries - -%description -n %{name}-0 -libgit2 is a portable, pure C implementation of the Git core methods -provided as a re-entrant linkable library with a solid API, allowing -you to write native speed custom Git applications in any language -with bindings. - -%package devel -Summary: C git library -Group: Development/Libraries/C and C++ -Requires: %{name}-0 >= %{version} - -%description devel -This package contains all necessary include files and libraries needed -to compile and develop applications that use libgit2. - -%prep -%setup -q - -%build -cmake . \ - -DCMAKE_C_FLAGS:STRING="%{optflags}" \ - -DCMAKE_INSTALL_PREFIX:PATH=%{_prefix} \ - -DLIB_INSTALL_DIR:PATH=%{_libdir}S -make %{?_smp_mflags} - -%install -%make_install - -%post -n %{name}-0 -p /sbin/ldconfig -%postun -n %{name}-0 -p /sbin/ldconfig - -%files -n %{name}-0 -%defattr (-,root,root) -%doc AUTHORS COPYING README.md -%{_libdir}/%{name}.so.* - -%files devel -%defattr (-,root,root) -%doc CONVENTIONS examples -%{_libdir}/%{name}.so -%{_includedir}/git2* -%{_libdir}/pkgconfig/libgit2.pc - -%changelog -* Tue Mar 04 2012 tuxdna@gmail.com -- Update to version 0.16.0 -* Tue Jan 31 2012 jengelh@medozas.de -- Provide pkgconfig symbols -* Thu Oct 27 2011 saschpe@suse.de -- Change license to 'GPL-2.0 with linking', fixes bnc#726789 -* Wed Oct 26 2011 saschpe@suse.de -- Update to version 0.15.0: - * Upstream doesn't provide changes -- Removed outdated %%clean section -* Tue Jan 18 2011 saschpe@gmx.de -- Proper Requires for devel package -* Tue Jan 18 2011 saschpe@gmx.de -- Set BuildRequires to "openssl-devel" also for RHEL and CentOS -* Tue Jan 18 2011 saschpe@gmx.de -- Initial commit (0.0.1) -- Added patch to fix shared library soname -- cgit v1.2.1 From 157cef1048ac797dcaf9f81075a61005124d2d1c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 28 Oct 2013 12:57:15 +0800 Subject: The "common.h" should be included before "config.h". When building libgit2 for ia32 architecture on a x64 machine, including "config.h" without a "common.h" would result the following error: C:\Program Files\Microsoft SDKs\Windows\v7.1\include\winbase.h(2288): error C2373: 'InterlockedIncrement' : redefinition; different type modifiers [C:\cygwin\home\zcbenz\codes\git-utils\build\libgit2.vcxproj] C:\Program Files\Microsoft SDKs\Windows\v7.1\include\winbase.h(2295): error C2373: 'InterlockedDecrement' : redefinition; different type modifiers [C:\cygwin\home\zcbenz\codes\git-utils\build\libgit2.vcxproj] C:\Program Files\Microsoft SDKs\Windows\v7.1\include\winbase.h(2303): error C2373: 'InterlockedExchange' : redefinition; different type modifiers [C:\cygwin\home\zcbenz\codes\git-utils\build\libgit2.vcxproj] C:\Program Files\Microsoft SDKs\Windows\v7.1\include\winbase.h(2314): error C2373: 'InterlockedExchangeAdd' : redefinition; different type modifiers [C:\cygwin\home\zcbenz\codes\git-utils\build\libgit2.vcxproj] --- src/attr.c | 1 + src/ignore.c | 1 + src/remote.c | 1 + 3 files changed, 3 insertions(+) diff --git a/src/attr.c b/src/attr.c index 7946db4d6..98a328a55 100644 --- a/src/attr.c +++ b/src/attr.c @@ -1,3 +1,4 @@ +#include "common.h" #include "repository.h" #include "fileops.h" #include "config.h" diff --git a/src/ignore.c b/src/ignore.c index 0c35d0431..27d7c7ec4 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -1,4 +1,5 @@ #include "git2/ignore.h" +#include "common.h" #include "ignore.h" #include "attr.h" #include "path.h" diff --git a/src/remote.c b/src/remote.c index ccedf2386..bdfa08642 100644 --- a/src/remote.c +++ b/src/remote.c @@ -10,6 +10,7 @@ #include "git2/oid.h" #include "git2/net.h" +#include "common.h" #include "config.h" #include "repository.h" #include "remote.h" -- cgit v1.2.1 From ba02079f2d97411c3ac6f1a7c29874b0aec68b08 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 28 Oct 2013 05:01:33 -0700 Subject: Avoid temporary object in lookup routine --- src/object.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/object.c b/src/object.c index 53666ffe4..3fc984b45 100644 --- a/src/object.c +++ b/src/object.c @@ -374,27 +374,26 @@ int git_object_lookup_bypath( int error = -1; git_tree *tree = NULL; git_tree_entry *entry = NULL; - git_object *tmpobj = NULL; assert(out && treeish && path); - if (((error = git_object_peel((git_object**)&tree, treeish, GIT_OBJ_TREE)) < 0) || - ((error = git_tree_entry_bypath(&entry, tree, path)) < 0) || - ((error = git_tree_entry_to_object(&tmpobj, git_object_owner(treeish), entry)) < 0)) + if ((error = git_object_peel((git_object**)&tree, treeish, GIT_OBJ_TREE) < 0) || + (error = git_tree_entry_bypath(&entry, tree, path)) < 0) { goto cleanup; } - if (type == GIT_OBJ_ANY || git_object_type(tmpobj) == type) { - *out = tmpobj; - } else { + if (type != GIT_OBJ_ANY && git_tree_entry_type(entry) != type) + { giterr_set(GITERR_OBJECT, "object at path '%s' is not of the asked-for type %d", path, type); error = GIT_EINVALIDSPEC; - git_object_free(tmpobj); + goto cleanup; } + error = git_tree_entry_to_object(out, git_object_owner(treeish), entry); + cleanup: git_tree_entry_free(entry); git_tree_free(tree); -- cgit v1.2.1 From 7f6db0ad121a3fdfdb9249c71b6650f771f4f6b3 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 28 Oct 2013 05:19:30 -0700 Subject: Mmmm, GIT_FLEX_ARRAY --- src/blame.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blame.h b/src/blame.h index 09d349d7b..b50021a24 100644 --- a/src/blame.h +++ b/src/blame.h @@ -16,7 +16,7 @@ typedef struct git_blame__origin { struct git_blame__origin *previous; git_commit *commit; git_blob *blob; - char path[]; + char path[GIT_FLEX_ARRAY]; } git_blame__origin; /* -- cgit v1.2.1 From a7d28f40a2a01382b76c55ca0a0672c177adaf69 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 28 Oct 2013 05:22:37 -0700 Subject: :heart: bool --- src/blame.h | 4 ++-- src/blame_git.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/blame.h b/src/blame.h index b50021a24..637e43985 100644 --- a/src/blame.h +++ b/src/blame.h @@ -42,11 +42,11 @@ typedef struct git_blame__entry { /* true if the suspect is truly guilty; false while we have not * checked if the group came from one of its parents. */ - char guilty; + bool guilty; /* true if the entry has been scanned for copies in the current parent */ - char scanned; + bool scanned; /* the line number of the first line of this group in the * suspect's file; internally all line numbers are 0 based. diff --git a/src/blame_git.c b/src/blame_git.c index 4df65139a..2b02443de 100644 --- a/src/blame_git.c +++ b/src/blame_git.c @@ -602,7 +602,7 @@ void git_blame__like_git(git_blame *blame, uint32_t opt) /* Take responsibility for the remaining entries */ for (ent = blame->ent; ent; ent = ent->next) { if (same_suspect(ent->suspect, suspect)) { - ent->guilty = 1; + ent->guilty = true; ent->is_boundary = !git_oid_cmp( git_commit_id(suspect->commit), &blame->options.oldest_commit); -- cgit v1.2.1 From 7dcb1c452582d2a83ca1ad8858cb95ab20d6e13d Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 28 Oct 2013 11:21:23 -0700 Subject: Adjust for diff API changes --- src/blame.c | 23 ++++++++--------------- src/blame_git.c | 22 +++++++++++----------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/blame.c b/src/blame.c index e698d3941..192e296d8 100644 --- a/src/blame.c +++ b/src/blame.c @@ -370,19 +370,15 @@ static bool hunk_is_bufferblame(git_blame_hunk *hunk) static int buffer_hunk_cb( const git_diff_delta *delta, - const git_diff_range *range, - const char *header, - size_t header_len, + const git_diff_hunk *hunk, void *payload) { git_blame *blame = (git_blame*)payload; size_t wedge_line; GIT_UNUSED(delta); - GIT_UNUSED(header); - GIT_UNUSED(header_len); - wedge_line = (range->old_lines == 0) ? range->new_start : range->old_start; + wedge_line = (hunk->old_lines == 0) ? hunk->new_start : hunk->old_start; blame->current_diff_line = wedge_line; /* If this hunk doesn't start between existing hunks, split a hunk up so it does */ @@ -398,18 +394,15 @@ static int buffer_hunk_cb( static int ptrs_equal_cmp(const void *a, const void *b) { return ab ? 1 : 0; } static int buffer_line_cb( const git_diff_delta *delta, - const git_diff_range *range, - char line_origin, - const char *content, - size_t content_len, + const git_diff_hunk *hunk, + const git_diff_line *line, void *payload) { git_blame *blame = (git_blame*)payload; GIT_UNUSED(delta); - GIT_UNUSED(range); - GIT_UNUSED(content); - GIT_UNUSED(content_len); + GIT_UNUSED(hunk); + GIT_UNUSED(line); #ifdef DO_DEBUG { @@ -418,7 +411,7 @@ static int buffer_line_cb( } #endif - if (line_origin == GIT_DIFF_LINE_ADDITION) { + if (line->origin == GIT_DIFF_LINE_ADDITION) { if (hunk_is_bufferblame(blame->current_hunk) && hunk_ends_at_or_before_line(blame->current_hunk, blame->current_diff_line)) { /* Append to the current buffer-blame hunk */ @@ -433,7 +426,7 @@ static int buffer_line_cb( blame->current_diff_line++; } - if (line_origin == GIT_DIFF_LINE_DELETION) { + if (line->origin == GIT_DIFF_LINE_DELETION) { /* Trim the line from the current hunk; remove it if it's now empty */ size_t shift_base = blame->current_diff_line + blame->current_hunk->lines_in_hunk+1; diff --git a/src/blame_git.c b/src/blame_git.c index 2b02443de..84ffa29f0 100644 --- a/src/blame_git.c +++ b/src/blame_git.c @@ -400,7 +400,7 @@ static git_blame__origin* find_origin( git_blame__origin *origin) { git_blame__origin *porigin = NULL; - git_diff_list *difflist = NULL; + git_diff *difflist = NULL; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_tree *otree=NULL, *ptree=NULL; @@ -427,7 +427,7 @@ static git_blame__origin* find_origin( int i; /* Generate a full diff between the two trees */ - git_diff_list_free(difflist); + git_diff_free(difflist); diffopts.pathspec.count = 0; if (0 != git_diff_tree_to_tree(&difflist, blame->repository, ptree, otree, &diffopts)) goto cleanup; @@ -439,19 +439,19 @@ static git_blame__origin* find_origin( /* Find one that matches */ for (i=0; i<(int)git_diff_num_deltas(difflist); i++) { - const git_diff_delta *delta; - git_diff_get_patch(NULL, &delta, difflist, i); - if (git_vector_bsearch(NULL, &blame->paths, delta->new_file.path) != 0) - continue; - - git_vector_insert_sorted(&blame->paths, (void*)git__strdup(delta->old_file.path), - paths_on_dup); - make_origin(&porigin, parent, delta->old_file.path); + const git_diff_delta *delta = git_diff_get_delta(difflist, i); + + if (!git_vector_bsearch(NULL, &blame->paths, delta->new_file.path)) + { + git_vector_insert_sorted(&blame->paths, (void*)git__strdup(delta->old_file.path), + paths_on_dup); + make_origin(&porigin, parent, delta->old_file.path); + } } } cleanup: - git_diff_list_free(difflist); + git_diff_free(difflist); git_tree_free(otree); git_tree_free(ptree); return porigin; -- cgit v1.2.1 From 66902d47737da1100de5e24498cf8c7260b183df Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 29 Oct 2013 18:30:49 -0700 Subject: Extract common example helpers and reorg examples This reorganizes a few of the examples so that the main function comes first with the argument parsing extracted into a helper that can come at the end of the file (so the example focuses more on the use of libgit2 instead of command line support). This also creates a shared examples/common.[ch] so that useful helper funcs can be shared across examples instead of repeated. --- examples/CMakeLists.txt | 6 +- examples/Makefile | 2 +- examples/common.c | 184 +++++++++++++++++++ examples/common.h | 80 +++++++++ examples/diff.c | 374 +++++++++++++++++++------------------- examples/log.c | 468 +++++++++++++++++++++++++----------------------- examples/status.c | 234 ++++++++++++------------ 7 files changed, 808 insertions(+), 540 deletions(-) create mode 100644 examples/common.c create mode 100644 examples/common.h diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c20a6df3b..596be45ed 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -9,6 +9,8 @@ ENDIF() FILE(GLOB SRC_EXAMPLE_APPS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.c) FOREACH(src_app ${SRC_EXAMPLE_APPS}) STRING(REPLACE ".c" "" app_name ${src_app}) - ADD_EXECUTABLE(${app_name} ${src_app}) - TARGET_LINK_LIBRARIES(${app_name} git2) + IF(NOT ${app_name} STREQUAL "common") + ADD_EXECUTABLE(${app_name} ${src_app} "common.c") + TARGET_LINK_LIBRARIES(${app_name} git2) + ENDIF() ENDFOREACH() diff --git a/examples/Makefile b/examples/Makefile index d53ed8241..f4d55570a 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -8,7 +8,7 @@ APPS = general showindex diff rev-list cat-file status log rev-parse init all: $(APPS) % : %.c - $(CC) -o $@ $(CFLAGS) $< $(LFLAGS) + $(CC) -o $@ common.c $(CFLAGS) $< $(LFLAGS) clean: $(RM) $(APPS) diff --git a/examples/common.c b/examples/common.c new file mode 100644 index 000000000..5972bc5c7 --- /dev/null +++ b/examples/common.c @@ -0,0 +1,184 @@ +/* + * 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 "common.h" + +void check_lg2(int error, const char *message, const char *extra) +{ + const git_error *lg2err; + const char *lg2msg = "", *lg2spacer = ""; + + if (!error) + return; + + if ((lg2err = giterr_last()) != NULL && lg2err->message != NULL) { + lg2msg = lg2err->message; + lg2spacer = " - "; + } + + if (extra) + fprintf(stderr, "%s '%s' [%d]%s%s\n", + message, extra, error, lg2spacer, lg2msg); + else + fprintf(stderr, "%s [%d]%s%s\n", + message, error, lg2spacer, lg2msg); + + exit(1); +} + +void fatal(const char *message, const char *extra) +{ + if (extra) + fprintf(stderr, "%s %s\n", message, extra); + else + fprintf(stderr, "%s\n", message); + + exit(1); +} + +size_t is_prefixed(const char *str, const char *pfx) +{ + size_t len = strlen(pfx); + return strncmp(str, pfx, len) ? 0 : len; +} + +int match_str_arg( + const char **out, struct args_info *args, const char *opt) +{ + const char *found = args->argv[args->pos]; + size_t len = is_prefixed(found, opt); + + if (!len) + return 0; + + if (!found[len]) { + if (args->pos + 1 == args->argc) + fatal("expected value following argument", opt); + args->pos += 1; + *out = args->argv[args->pos]; + return 1; + } + + if (found[len] == '=') { + *out = found + len + 1; + return 1; + } + + return 0; +} + +static const char *match_numeric_arg(struct args_info *args, const char *opt) +{ + const char *found = args->argv[args->pos]; + size_t len = is_prefixed(found, opt); + + if (!len) + return NULL; + + if (!found[len]) { + if (args->pos + 1 == args->argc) + fatal("expected numeric value following argument", opt); + args->pos += 1; + found = args->argv[args->pos]; + } else { + found = found + len; + if (*found == '=') + found++; + } + + return found; +} + +int match_uint16_arg( + uint16_t *out, struct args_info *args, const char *opt) +{ + const char *found = match_numeric_arg(args, opt); + uint16_t val; + char *endptr = NULL; + + if (!found) + return 0; + + val = (uint16_t)strtoul(found, &endptr, 0); + if (!endptr || *endptr != '\0') + fatal("expected number after argument", opt); + + if (out) + *out = val; + return 1; +} + +static int match_int_internal( + int *out, const char *str, int allow_negative, const char *opt) +{ + char *endptr = NULL; + int val = (int)strtol(str, &endptr, 10); + + if (!endptr || *endptr != '\0') + fatal("expected number", opt); + else if (val < 0 && !allow_negative) + fatal("negative values are not allowed", opt); + + if (out) + *out = val; + + return 1; +} + +int is_integer(int *out, const char *str, int allow_negative) +{ + return match_int_internal(out, str, allow_negative, NULL); +} + +int match_int_arg( + int *out, struct args_info *args, const char *opt, int allow_negative) +{ + const char *found = match_numeric_arg(args, opt); + if (!found) + return 0; + return match_int_internal(out, found, allow_negative, opt); +} + +int diff_output( + const git_diff_delta *d, + const git_diff_hunk *h, + const git_diff_line *l, + void *p) +{ + FILE *fp = p; + + (void)d; (void)h; + + if (!fp) + fp = stdout; + + if (l->origin == GIT_DIFF_LINE_CONTEXT || + l->origin == GIT_DIFF_LINE_ADDITION || + l->origin == GIT_DIFF_LINE_DELETION) + fputc(l->origin, fp); + + fwrite(l->content, 1, l->content_len, fp); + + return 0; +} + +void treeish_to_tree( + git_tree **out, git_repository *repo, const char *treeish) +{ + git_object *obj = NULL; + + check_lg2( + git_revparse_single(&obj, repo, treeish), + "looking up object", treeish); + + check_lg2( + git_object_peel((git_object **)out, obj, GIT_OBJ_TREE), + "resolving object to tree", treeish); + + git_object_free(obj); +} + diff --git a/examples/common.h b/examples/common.h new file mode 100644 index 000000000..5ffc9c8eb --- /dev/null +++ b/examples/common.h @@ -0,0 +1,80 @@ +/* + * 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 +#include +#include +#include + +/** + * Check libgit2 error code, printing error to stderr on failure and + * exiting the program. + */ +extern void check_lg2(int error, const char *message, const char *extra); + +/** + * Exit the program, printing error to stderr + */ +extern void fatal(const char *message, const char *extra); + +/** + * Check if a string has the given prefix. Returns 0 if not prefixed + * or the length of the prefix if it is. + */ +extern size_t is_prefixed(const char *str, const char *pfx); + +/** + * Match an integer string, returning 1 if matched, 0 if not. + */ +extern int is_integer(int *out, const char *str, int allow_negative); + +struct args_info { + int argc; + char **argv; + int pos; +}; +#define ARGS_INFO_INIT { argc, argv, 0 } + +/** + * Check current `args` entry against `opt` string. If it matches + * exactly, take the next arg as a string; if it matches as a prefix with + * an equal sign, take the remainder as a string; otherwise return 0. + */ +extern int match_str_arg( + const char **out, struct args_info *args, const char *opt); + +/** + * Check current `args` entry against `opt` string parsing as uint16. If + * `opt` matches exactly, take the next arg as a uint16_t value; if `opt` + * is a prefix (equal sign optional), take the remainder of the arg as a + * uint16_t value; otherwise return 0. + */ +extern int match_uint16_arg( + uint16_t *out, struct args_info *args, const char *opt); + +/** + * Check current `args` entry against `opt` string parsing as int. If + * `opt` matches exactly, take the next arg as an int value; if it matches + * as a prefix (equal sign optional), take the remainder of the arg as a + * int value; otherwise return 0. + */ +extern int match_int_arg( + int *out, struct args_info *args, const char *opt, int allow_negative); + +/** + * Basic output function for plain text diff output + * Pass `FILE*` such as `stdout` or `stderr` as payload (or NULL == `stdout`) + */ +extern int diff_output( + const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*); + +/** + * Convert a treeish argument to an actual tree; this will call check_lg2 + * and exit the program if `treeish` cannot be resolved to a tree + */ +extern void treeish_to_tree( + git_tree **out, git_repository *repo, const char *treeish); diff --git a/examples/diff.c b/examples/diff.c index 694621f1e..d39979117 100644 --- a/examples/diff.c +++ b/examples/diff.c @@ -1,49 +1,147 @@ -#include -#include -#include -#include +/* + * 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 "common.h" + +/* + * This example demonstrates the use of the libgit2 diff APIs to + * create `git_diff` objects and display them, emulating a number of + * core Git `diff` command line options. + * + * This covers on a portion of the core Git diff options and doesn't + * have particularly good error handling, but it should show most of + * the core libgit2 diff APIs, including various types of diffs and + * how to do renaming detection and patch formatting. + */ + +static const char *colors[] = { + "\033[m", /* reset */ + "\033[1m", /* bold */ + "\033[31m", /* red */ + "\033[32m", /* green */ + "\033[36m" /* cyan */ +}; -static void check(int error, const char *message) -{ - if (error) { - fprintf(stderr, "%s (%d)\n", message, error); - exit(1); - } -} +/* this implements very rudimentary colorized output */ +static int color_printer( + const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*); + +/* the 'opts' struct captures all the various parsed command line options */ +struct opts { + git_diff_options diffopts; + git_diff_find_options findopts; + int color; + int cached; + git_diff_format_t format; + const char *treeish1; + const char *treeish2; + const char *dir; +}; + +static void parse_opts(struct opts *o, int argc, char *argv[]); -static int resolve_to_tree( - git_repository *repo, const char *identifier, git_tree **tree) +int main(int argc, char *argv[]) { - int err = 0; - git_object *obj = NULL; - - if ((err = git_revparse_single(&obj, repo, identifier)) < 0) - return err; - - switch (git_object_type(obj)) { - case GIT_OBJ_TREE: - *tree = (git_tree *)obj; - break; - case GIT_OBJ_COMMIT: - err = git_commit_tree(tree, (git_commit *)obj); - git_object_free(obj); - break; - default: - err = GIT_ENOTFOUND; + git_repository *repo = NULL; + git_tree *t1 = NULL, *t2 = NULL; + git_diff *diff; + struct opts o = { + GIT_DIFF_OPTIONS_INIT, GIT_DIFF_FIND_OPTIONS_INIT, + -1, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "." + }; + + git_threads_init(); + + parse_opts(&o, argc, argv); + + check_lg2(git_repository_open_ext(&repo, o.dir, 0, NULL), + "Could not open repository", o.dir); + + /* Possible argument patterns: + * + * --cached + * + * --cached + * nothing + * + * Currently ranged arguments like .. and ... + * are not supported in this example + */ + + if (o.treeish1) + treeish_to_tree(&t1, repo, o.treeish1); + if (o.treeish2) + treeish_to_tree(&t2, repo, o.treeish2); + + if (t1 && t2) + check_lg2( + git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts), + "diff trees", NULL); + else if (t1 && o.cached) + check_lg2( + git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts), + "diff tree to index", NULL); + else if (t1) + check_lg2( + git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts), + "diff tree to working directory", NULL); + else if (o.cached) { + treeish_to_tree(&t1, repo, "HEAD"); + check_lg2( + git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts), + "diff tree to index", NULL); } + else + check_lg2( + git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts), + "diff index to working directory", NULL); + + /* apply rename and copy detection if requested */ + + if ((o.findopts.flags & GIT_DIFF_FIND_ALL) != 0) + check_lg2( + git_diff_find_similar(diff, &o.findopts), + "finding renames and copies", NULL); + + /* generate simple output using libgit2 display helper */ - return err; + if (o.color >= 0) + fputs(colors[0], stdout); + + check_lg2( + git_diff_print(diff, o.format, color_printer, &o.color), + "displaying diff", NULL); + + if (o.color >= 0) + fputs(colors[0], stdout); + + /* cleanup before exiting */ + + git_diff_free(diff); + git_tree_free(t1); + git_tree_free(t2); + git_repository_free(repo); + + git_threads_shutdown(); + + return 0; } -char *colors[] = { - "\033[m", /* reset */ - "\033[1m", /* bold */ - "\033[31m", /* red */ - "\033[32m", /* green */ - "\033[36m" /* cyan */ -}; +static void usage(const char *message, const char *arg) +{ + if (message && arg) + fprintf(stderr, "%s: %s\n", message, arg); + else if (message) + fprintf(stderr, "%s\n", message); + fprintf(stderr, "usage: diff [ []]\n"); + exit(1); +} -static int printer( +static int color_printer( const git_diff_delta *delta, const git_diff_hunk *hunk, const git_diff_line *line, @@ -63,6 +161,7 @@ static int printer( case GIT_DIFF_LINE_HUNK_HDR: color = 4; break; default: break; } + if (color != *last_color) { if (*last_color == 1 || color == 1) fputs(colors[0], stdout); @@ -71,186 +170,79 @@ static int printer( } } - if (line->origin == GIT_DIFF_LINE_CONTEXT || - line->origin == GIT_DIFF_LINE_ADDITION || - line->origin == GIT_DIFF_LINE_DELETION) - fputc(line->origin, stdout); - - fwrite(line->content, 1, line->content_len, stdout); - - return 0; -} - -static int check_uint16_param(const char *arg, const char *pattern, uint16_t *val) -{ - size_t len = strlen(pattern); - uint16_t strval; - char *endptr = NULL; - if (strncmp(arg, pattern, len)) - return 0; - if (arg[len] == '\0' && pattern[len - 1] != '=') - return 1; - if (arg[len] == '=') - len++; - strval = strtoul(arg + len, &endptr, 0); - if (endptr == arg) - return 0; - *val = strval; - return 1; + return diff_output(delta, hunk, line, stdout); } -static int check_str_param(const char *arg, const char *pattern, const char **val) +static void parse_opts(struct opts *o, int argc, char *argv[]) { - size_t len = strlen(pattern); - if (strncmp(arg, pattern, len)) - return 0; - *val = (const char *)(arg + len); - return 1; -} - -static void usage(const char *message, const char *arg) -{ - if (message && arg) - fprintf(stderr, "%s: %s\n", message, arg); - else if (message) - fprintf(stderr, "%s\n", message); - fprintf(stderr, "usage: diff [ []]\n"); - exit(1); -} - -int main(int argc, char *argv[]) -{ - git_repository *repo = NULL; - git_tree *t1 = NULL, *t2 = NULL; - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; - git_diff *diff; - int i, color = -1, cached = 0; - git_diff_format_t format = GIT_DIFF_FORMAT_PATCH; - char *a, *treeish1 = NULL, *treeish2 = NULL; - const char *dir = "."; - - git_threads_init(); + struct args_info args = ARGS_INFO_INIT; /* parse arguments as copied from git-diff */ - for (i = 1; i < argc; ++i) { - a = argv[i]; + for (args.pos = 1; args.pos < argc; ++args.pos) { + const char *a = argv[args.pos]; if (a[0] != '-') { - if (treeish1 == NULL) - treeish1 = a; - else if (treeish2 == NULL) - treeish2 = a; + if (o->treeish1 == NULL) + o->treeish1 = a; + else if (o->treeish2 == NULL) + o->treeish2 = a; else usage("Only one or two tree identifiers can be provided", NULL); } else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) - format = GIT_DIFF_FORMAT_PATCH; + o->format = GIT_DIFF_FORMAT_PATCH; else if (!strcmp(a, "--cached")) - cached = 1; + o->cached = 1; else if (!strcmp(a, "--name-only")) - format = GIT_DIFF_FORMAT_NAME_ONLY; + o->format = GIT_DIFF_FORMAT_NAME_ONLY; else if (!strcmp(a, "--name-status")) - format = GIT_DIFF_FORMAT_NAME_STATUS; + o->format = GIT_DIFF_FORMAT_NAME_STATUS; else if (!strcmp(a, "--raw")) - format = GIT_DIFF_FORMAT_RAW; + o->format = GIT_DIFF_FORMAT_RAW; else if (!strcmp(a, "--color")) - color = 0; + o->color = 0; else if (!strcmp(a, "--no-color")) - color = -1; + o->color = -1; else if (!strcmp(a, "-R")) - opts.flags |= GIT_DIFF_REVERSE; + o->diffopts.flags |= GIT_DIFF_REVERSE; else if (!strcmp(a, "-a") || !strcmp(a, "--text")) - opts.flags |= GIT_DIFF_FORCE_TEXT; + o->diffopts.flags |= GIT_DIFF_FORCE_TEXT; else if (!strcmp(a, "--ignore-space-at-eol")) - opts.flags |= GIT_DIFF_IGNORE_WHITESPACE_EOL; + o->diffopts.flags |= GIT_DIFF_IGNORE_WHITESPACE_EOL; else if (!strcmp(a, "-b") || !strcmp(a, "--ignore-space-change")) - opts.flags |= GIT_DIFF_IGNORE_WHITESPACE_CHANGE; + o->diffopts.flags |= GIT_DIFF_IGNORE_WHITESPACE_CHANGE; else if (!strcmp(a, "-w") || !strcmp(a, "--ignore-all-space")) - opts.flags |= GIT_DIFF_IGNORE_WHITESPACE; + o->diffopts.flags |= GIT_DIFF_IGNORE_WHITESPACE; else if (!strcmp(a, "--ignored")) - opts.flags |= GIT_DIFF_INCLUDE_IGNORED; + o->diffopts.flags |= GIT_DIFF_INCLUDE_IGNORED; else if (!strcmp(a, "--untracked")) - opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED; - else if (check_uint16_param(a, "-M", &findopts.rename_threshold) || - check_uint16_param(a, "--find-renames", - &findopts.rename_threshold)) - findopts.flags |= GIT_DIFF_FIND_RENAMES; - else if (check_uint16_param(a, "-C", &findopts.copy_threshold) || - check_uint16_param(a, "--find-copies", - &findopts.copy_threshold)) - findopts.flags |= GIT_DIFF_FIND_COPIES; + o->diffopts.flags |= GIT_DIFF_INCLUDE_UNTRACKED; + else if (match_uint16_arg( + &o->findopts.rename_threshold, &args, "-M") || + match_uint16_arg( + &o->findopts.rename_threshold, &args, "--find-renames")) + o->findopts.flags |= GIT_DIFF_FIND_RENAMES; + else if (match_uint16_arg( + &o->findopts.copy_threshold, &args, "-C") || + match_uint16_arg( + &o->findopts.copy_threshold, &args, "--find-copies")) + o->findopts.flags |= GIT_DIFF_FIND_COPIES; else if (!strcmp(a, "--find-copies-harder")) - findopts.flags |= GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED; - else if (!strncmp(a, "-B", 2) || !strncmp(a, "--break-rewrites", 16)) { + o->findopts.flags |= GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED; + else if (is_prefixed(a, "-B") || is_prefixed(a, "--break-rewrites")) /* TODO: parse thresholds */ - findopts.flags |= GIT_DIFF_FIND_REWRITES; - } - else if (!check_uint16_param(a, "-U", &opts.context_lines) && - !check_uint16_param(a, "--unified=", &opts.context_lines) && - !check_uint16_param(a, "--inter-hunk-context=", - &opts.interhunk_lines) && - !check_str_param(a, "--src-prefix=", &opts.old_prefix) && - !check_str_param(a, "--dst-prefix=", &opts.new_prefix) && - !check_str_param(a, "--git-dir=", &dir)) - usage("Unknown arg", a); - } - - /* open repo */ - - check(git_repository_open_ext(&repo, dir, 0, NULL), - "Could not open repository"); - - if (treeish1) - check(resolve_to_tree(repo, treeish1, &t1), "Looking up first tree"); - if (treeish2) - check(resolve_to_tree(repo, treeish2, &t2), "Looking up second tree"); - - /* */ - /* --cached */ - /* */ - /* --cached */ - /* nothing */ - - if (t1 && t2) - check(git_diff_tree_to_tree(&diff, repo, t1, t2, &opts), "Diff"); - else if (t1 && cached) - check(git_diff_tree_to_index(&diff, repo, t1, NULL, &opts), "Diff"); - else if (t1) { - git_diff *diff2; - check(git_diff_tree_to_index(&diff, repo, t1, NULL, &opts), "Diff"); - check(git_diff_index_to_workdir(&diff2, repo, NULL, &opts), "Diff"); - check(git_diff_merge(diff, diff2), "Merge diffs"); - git_diff_free(diff2); + o->findopts.flags |= GIT_DIFF_FIND_REWRITES; + else if (!match_uint16_arg( + &o->diffopts.context_lines, &args, "-U") && + !match_uint16_arg( + &o->diffopts.context_lines, &args, "--unified") && + !match_uint16_arg( + &o->diffopts.interhunk_lines, &args, "--inter-hunk-context") && + !match_str_arg(&o->diffopts.old_prefix, &args, "--src-prefix") && + !match_str_arg(&o->diffopts.new_prefix, &args, "--dst-prefix") && + !match_str_arg(&o->dir, &args, "--git-dir")) + usage("Unknown command line argument", a); } - else if (cached) { - check(resolve_to_tree(repo, "HEAD", &t1), "looking up HEAD"); - check(git_diff_tree_to_index(&diff, repo, t1, NULL, &opts), "Diff"); - } - else - check(git_diff_index_to_workdir(&diff, repo, NULL, &opts), "Diff"); - - if ((findopts.flags & GIT_DIFF_FIND_ALL) != 0) - check(git_diff_find_similar(diff, &findopts), - "finding renames and copies "); - - if (color >= 0) - fputs(colors[0], stdout); - - check(git_diff_print(diff, format, printer, &color), "Displaying diff"); - - if (color >= 0) - fputs(colors[0], stdout); - - git_diff_free(diff); - git_tree_free(t1); - git_tree_free(t2); - git_repository_free(repo); - - git_threads_shutdown(); - - return 0; } - diff --git a/examples/log.c b/examples/log.c index 4c2df07c9..270de7c5d 100644 --- a/examples/log.c +++ b/examples/log.c @@ -1,88 +1,203 @@ -#include -#include -#include -#include - -static void check(int error, const char *message, const char *arg) -{ - if (!error) - return; - if (arg) - fprintf(stderr, "%s '%s' (%d)\n", message, arg, error); - else - fprintf(stderr, "%s (%d)\n", message, error); - exit(1); -} - -static void usage(const char *message, const char *arg) -{ - if (message && arg) - fprintf(stderr, "%s: %s\n", message, arg); - else if (message) - fprintf(stderr, "%s\n", message); - fprintf(stderr, "usage: log []\n"); - exit(1); -} - +/* + * 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 "common.h" + +/* + * This example demonstrates the libgit2 rev walker APIs to roughly + * simulate the output of `git log` and a few of command line arguments. + * `git log` has many many options and this only shows a few of them. + * + * This does not have: + * - Robust error handling + * - Colorized or paginated output formatting + * - Most of the `git log` options + * + * This does have: + * - Examples of translating command line arguments to equivalent libgit2 + * revwalker configuration calls + * - Simplified options to apply pathspec limits and to show basic diffs + */ + +/* log_state represents walker being configured while handling options */ struct log_state { git_repository *repo; const char *repodir; git_revwalk *walker; int hide; int sorting; + int revisions; }; -static void set_sorting(struct log_state *s, unsigned int sort_mode) +/* utility functions that are called to configure the walker */ +static void set_sorting(struct log_state *s, unsigned int sort_mode); +static void push_rev(struct log_state *s, git_object *obj, int hide); +static int add_revision(struct log_state *s, const char *revstr); + +/* log_options holds other command line options that affect log output */ +struct log_options { + int show_diff; + int skip, limit; + int min_parents, max_parents; + git_time_t before; + git_time_t after; + char *author; + char *committer; +}; + +/* utility functions that parse options and help with log output */ +static int parse_options( + struct log_state *s, struct log_options *opt, int argc, char **argv); +static void print_time(const git_time *intime, const char *prefix); +static void print_commit(git_commit *commit); +static int match_with_parent(git_commit *commit, int i, git_diff_options *); + + +int main(int argc, char *argv[]) { - if (!s->repo) { - if (!s->repodir) s->repodir = "."; - check(git_repository_open_ext(&s->repo, s->repodir, 0, NULL), - "Could not open repository", s->repodir); - } + int i, count = 0, printed = 0, parents, last_arg; + struct log_state s; + struct log_options opt; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_oid oid; + git_commit *commit = NULL; + git_pathspec *ps = NULL; - if (!s->walker) - check(git_revwalk_new(&s->walker, s->repo), - "Could not create revision walker", NULL); + git_threads_init(); - if (sort_mode == GIT_SORT_REVERSE) - s->sorting = s->sorting ^ GIT_SORT_REVERSE; - else - s->sorting = sort_mode | (s->sorting & GIT_SORT_REVERSE); + /* parse arguments and set up revwalker */ - git_revwalk_sorting(s->walker, s->sorting); + last_arg = parse_options(&s, &opt, argc, argv); + + diffopts.pathspec.strings = &argv[last_arg]; + diffopts.pathspec.count = argc - last_arg; + if (diffopts.pathspec.count > 0) + check_lg2(git_pathspec_new(&ps, &diffopts.pathspec), + "Building pathspec", NULL); + + if (!s.revisions) + add_revision(&s, NULL); + + /* use the revwalker to traverse the history */ + + printed = count = 0; + + for (; !git_revwalk_next(&oid, s.walker); git_commit_free(commit)) { + check_lg2(git_commit_lookup(&commit, s.repo, &oid), + "Failed to look up commit", NULL); + + parents = (int)git_commit_parentcount(commit); + if (parents < opt.min_parents) + continue; + if (opt.max_parents > 0 && parents > opt.max_parents) + continue; + + if (diffopts.pathspec.count > 0) { + int unmatched = parents; + + if (parents == 0) { + git_tree *tree; + check_lg2(git_commit_tree(&tree, commit), "Get tree", NULL); + if (git_pathspec_match_tree( + NULL, tree, GIT_PATHSPEC_NO_MATCH_ERROR, ps) != 0) + unmatched = 1; + git_tree_free(tree); + } else if (parents == 1) { + unmatched = match_with_parent(commit, 0, &diffopts) ? 0 : 1; + } else { + for (i = 0; i < parents; ++i) { + if (match_with_parent(commit, i, &diffopts)) + unmatched--; + } + } + + if (unmatched > 0) + continue; + } + + if (count++ < opt.skip) + continue; + if (opt.limit != -1 && printed++ >= opt.limit) { + git_commit_free(commit); + break; + } + + print_commit(commit); + + if (opt.show_diff) { + git_tree *a = NULL, *b = NULL; + git_diff *diff = NULL; + + if (parents > 1) + continue; + check_lg2(git_commit_tree(&b, commit), "Get tree", NULL); + if (parents == 1) { + git_commit *parent; + check_lg2(git_commit_parent(&parent, commit, 0), "Get parent", NULL); + check_lg2(git_commit_tree(&a, parent), "Tree for parent", NULL); + git_commit_free(parent); + } + + check_lg2(git_diff_tree_to_tree( + &diff, git_commit_owner(commit), a, b, &diffopts), + "Diff commit with parent", NULL); + check_lg2( + git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, diff_output, NULL), + "Displaying diff", NULL); + + git_diff_free(diff); + git_tree_free(a); + git_tree_free(b); + } + } + + git_pathspec_free(ps); + git_revwalk_free(s.walker); + git_repository_free(s.repo); + git_threads_shutdown(); + + return 0; } +/* push object (for hide or show) onto revwalker */ static void push_rev(struct log_state *s, git_object *obj, int hide) { hide = s->hide ^ hide; + /* create revwalker on demand if it doesn't already exist */ if (!s->walker) { - check(git_revwalk_new(&s->walker, s->repo), + check_lg2(git_revwalk_new(&s->walker, s->repo), "Could not create revision walker", NULL); git_revwalk_sorting(s->walker, s->sorting); } if (!obj) - check(git_revwalk_push_head(s->walker), + check_lg2(git_revwalk_push_head(s->walker), "Could not find repository HEAD", NULL); else if (hide) - check(git_revwalk_hide(s->walker, git_object_id(obj)), + check_lg2(git_revwalk_hide(s->walker, git_object_id(obj)), "Reference does not refer to a commit", NULL); else - check(git_revwalk_push(s->walker, git_object_id(obj)), + check_lg2(git_revwalk_push(s->walker, git_object_id(obj)), "Reference does not refer to a commit", NULL); git_object_free(obj); } +/* parse revision string and add revs to walker */ static int add_revision(struct log_state *s, const char *revstr) { git_revspec revs; int hide = 0; + /* open repo on demand if it isn't already open */ if (!s->repo) { if (!s->repodir) s->repodir = "."; - check(git_repository_open_ext(&s->repo, s->repodir, 0, NULL), + check_lg2(git_repository_open_ext(&s->repo, s->repodir, 0, NULL), "Could not open repository", s->repodir); } @@ -107,10 +222,11 @@ static int add_revision(struct log_state *s, const char *revstr) if ((revs.flags & GIT_REVPARSE_MERGE_BASE) != 0) { git_oid base; - check(git_merge_base(&base, s->repo, + check_lg2(git_merge_base(&base, s->repo, git_object_id(revs.from), git_object_id(revs.to)), "Could not find merge base", revstr); - check(git_object_lookup(&revs.to, s->repo, &base, GIT_OBJ_COMMIT), + check_lg2( + git_object_lookup(&revs.to, s->repo, &base, GIT_OBJ_COMMIT), "Could not find merge base commit", NULL); push_rev(s, revs.to, hide); @@ -122,6 +238,30 @@ static int add_revision(struct log_state *s, const char *revstr) return 0; } +/* update revwalker with sorting mode */ +static void set_sorting(struct log_state *s, unsigned int sort_mode) +{ + /* open repo on demand if it isn't already open */ + if (!s->repo) { + if (!s->repodir) s->repodir = "."; + check_lg2(git_repository_open_ext(&s->repo, s->repodir, 0, NULL), + "Could not open repository", s->repodir); + } + + /* create revwalker on demand if it doesn't already exist */ + if (!s->walker) + check_lg2(git_revwalk_new(&s->walker, s->repo), + "Could not create revision walker", NULL); + + if (sort_mode == GIT_SORT_REVERSE) + s->sorting = s->sorting ^ GIT_SORT_REVERSE; + else + s->sorting = sort_mode | (s->sorting & GIT_SORT_REVERSE); + + git_revwalk_sorting(s->walker, s->sorting); +} + +/* helper to format a git_time value like Git */ static void print_time(const git_time *intime, const char *prefix) { char sign, out[32]; @@ -148,6 +288,7 @@ static void print_time(const git_time *intime, const char *prefix) printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes); } +/* helper to print a commit object */ static void print_commit(git_commit *commit) { char buf[GIT_OID_HEXSZ + 1]; @@ -182,54 +323,21 @@ static void print_commit(git_commit *commit) printf("\n"); } -static int print_diff( - const git_diff_delta *delta, - const git_diff_hunk *hunk, - const git_diff_line *line, - void *data) -{ - (void)delta; (void)hunk; (void)data; - - if (line->origin == GIT_DIFF_LINE_CONTEXT || - line->origin == GIT_DIFF_LINE_ADDITION || - line->origin == GIT_DIFF_LINE_DELETION) - fputc(line->origin, stdout); - - fwrite(line->content, 1, line->content_len, stdout); - return 0; -} - -static int match_int(int *value, const char *arg, int allow_negative) -{ - char *found; - *value = (int)strtol(arg, &found, 10); - return (found && *found == '\0' && (allow_negative || *value >= 0)); -} - -static int match_int_arg( - int *value, const char *arg, const char *pfx, int allow_negative) -{ - size_t pfxlen = strlen(pfx); - if (strncmp(arg, pfx, pfxlen) != 0) - return 0; - if (!match_int(value, arg + pfxlen, allow_negative)) - usage("Invalid value after argument", arg); - return 1; -} - -static int match_with_parent( - git_commit *commit, int i, git_diff_options *opts) +/* helper to find how many files in a commit changed from its nth parent */ +static int match_with_parent(git_commit *commit, int i, git_diff_options *opts) { git_commit *parent; git_tree *a, *b; git_diff *diff; int ndeltas; - check(git_commit_parent(&parent, commit, (size_t)i), "Get parent", NULL); - check(git_commit_tree(&a, parent), "Tree for parent", NULL); - check(git_commit_tree(&b, commit), "Tree for commit", NULL); - check(git_diff_tree_to_tree(&diff, git_commit_owner(commit), a, b, opts), - "Checking diff between parent and commit", NULL); + check_lg2( + git_commit_parent(&parent, commit, (size_t)i), "Get parent", NULL); + check_lg2(git_commit_tree(&a, parent), "Tree for parent", NULL); + check_lg2(git_commit_tree(&b, commit), "Tree for commit", NULL); + check_lg2( + git_diff_tree_to_tree(&diff, git_commit_owner(commit), a, b, opts), + "Checking diff between parent and commit", NULL); ndeltas = (int)git_diff_num_deltas(diff); @@ -241,170 +349,76 @@ static int match_with_parent( return ndeltas > 0; } -struct log_options { - int show_diff; - int skip, limit; - int min_parents, max_parents; - git_time_t before; - git_time_t after; - char *author; - char *committer; -}; - -int main(int argc, char *argv[]) +/* print a usage message for the program */ +static void usage(const char *message, const char *arg) { - int i, count = 0, printed = 0, parents; - char *a; - struct log_state s; - struct log_options opt; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_oid oid; - git_commit *commit = NULL; - git_pathspec *ps = NULL; + if (message && arg) + fprintf(stderr, "%s: %s\n", message, arg); + else if (message) + fprintf(stderr, "%s\n", message); + fprintf(stderr, "usage: log []\n"); + exit(1); +} - git_threads_init(); +/* parse some log command line options */ +static int parse_options( + struct log_state *s, struct log_options *opt, int argc, char **argv) +{ + struct args_info args = ARGS_INFO_INIT; - memset(&s, 0, sizeof(s)); - s.sorting = GIT_SORT_TIME; + memset(s, 0, sizeof(*s)); + s->sorting = GIT_SORT_TIME; - memset(&opt, 0, sizeof(opt)); - opt.max_parents = -1; - opt.limit = -1; + memset(opt, 0, sizeof(*opt)); + opt->max_parents = -1; + opt->limit = -1; - for (i = 1; i < argc; ++i) { - a = argv[i]; + for (args.pos = 1; args.pos < argc; ++args.pos) { + const char *a = argv[args.pos]; if (a[0] != '-') { - if (!add_revision(&s, a)) - ++count; + if (!add_revision(s, a)) + s->revisions++; else /* try failed revision parse as filename */ break; } else if (!strcmp(a, "--")) { - ++i; + ++args.pos; break; } else if (!strcmp(a, "--date-order")) - set_sorting(&s, GIT_SORT_TIME); + set_sorting(s, GIT_SORT_TIME); else if (!strcmp(a, "--topo-order")) - set_sorting(&s, GIT_SORT_TOPOLOGICAL); + set_sorting(s, GIT_SORT_TOPOLOGICAL); else if (!strcmp(a, "--reverse")) - set_sorting(&s, GIT_SORT_REVERSE); - else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) - s.repodir = a + strlen("--git-dir="); - else if (match_int_arg(&opt.skip, a, "--skip=", 0)) + set_sorting(s, GIT_SORT_REVERSE); + else if (match_str_arg(&s->repodir, &args, "--git-dir")) + /* found git-dir */; + else if (match_int_arg(&opt->skip, &args, "--skip", 0)) /* found valid --skip */; - else if (match_int_arg(&opt.limit, a, "--max-count=", 0)) + else if (match_int_arg(&opt->limit, &args, "--max-count", 0)) /* found valid --max-count */; - else if (a[1] >= '0' && a[1] <= '9') { - if (!match_int(&opt.limit, a + 1, 0)) - usage("Invalid limit on number of commits", a); - } else if (!strcmp(a, "-n")) { - if (i + 1 == argc || !match_int(&opt.limit, argv[i + 1], 0)) - usage("Argument -n not followed by valid count", argv[i + 1]); - else - ++i; - } + else if (a[1] >= '0' && a[1] <= '9') + is_integer(&opt->limit, a + 1, 0); + else if (match_int_arg(&opt->limit, &args, "-n", 0)) + /* found valid -n */; else if (!strcmp(a, "--merges")) - opt.min_parents = 2; + opt->min_parents = 2; else if (!strcmp(a, "--no-merges")) - opt.max_parents = 1; + opt->max_parents = 1; else if (!strcmp(a, "--no-min-parents")) - opt.min_parents = 0; + opt->min_parents = 0; else if (!strcmp(a, "--no-max-parents")) - opt.max_parents = -1; - else if (match_int_arg(&opt.max_parents, a, "--max-parents=", 1)) + opt->max_parents = -1; + else if (match_int_arg(&opt->max_parents, &args, "--max-parents=", 1)) /* found valid --max-parents */; - else if (match_int_arg(&opt.min_parents, a, "--min-parents=", 0)) + else if (match_int_arg(&opt->min_parents, &args, "--min-parents=", 0)) /* found valid --min_parents */; else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) - opt.show_diff = 1; + opt->show_diff = 1; else usage("Unsupported argument", a); } - if (!count) - add_revision(&s, NULL); - - diffopts.pathspec.strings = &argv[i]; - diffopts.pathspec.count = argc - i; - if (diffopts.pathspec.count > 0) - check(git_pathspec_new(&ps, &diffopts.pathspec), - "Building pathspec", NULL); - - printed = count = 0; - - for (; !git_revwalk_next(&oid, s.walker); git_commit_free(commit)) { - check(git_commit_lookup(&commit, s.repo, &oid), - "Failed to look up commit", NULL); - - parents = (int)git_commit_parentcount(commit); - if (parents < opt.min_parents) - continue; - if (opt.max_parents > 0 && parents > opt.max_parents) - continue; - - if (diffopts.pathspec.count > 0) { - int unmatched = parents; - - if (parents == 0) { - git_tree *tree; - check(git_commit_tree(&tree, commit), "Get tree", NULL); - if (git_pathspec_match_tree( - NULL, tree, GIT_PATHSPEC_NO_MATCH_ERROR, ps) != 0) - unmatched = 1; - git_tree_free(tree); - } else if (parents == 1) { - unmatched = match_with_parent(commit, 0, &diffopts) ? 0 : 1; - } else { - for (i = 0; i < parents; ++i) { - if (match_with_parent(commit, i, &diffopts)) - unmatched--; - } - } - - if (unmatched > 0) - continue; - } - - if (count++ < opt.skip) - continue; - if (opt.limit != -1 && printed++ >= opt.limit) { - git_commit_free(commit); - break; - } - - print_commit(commit); - - if (opt.show_diff) { - git_tree *a = NULL, *b = NULL; - git_diff *diff = NULL; - - if (parents > 1) - continue; - check(git_commit_tree(&b, commit), "Get tree", NULL); - if (parents == 1) { - git_commit *parent; - check(git_commit_parent(&parent, commit, 0), "Get parent", NULL); - check(git_commit_tree(&a, parent), "Tree for parent", NULL); - git_commit_free(parent); - } - - check(git_diff_tree_to_tree( - &diff, git_commit_owner(commit), a, b, &diffopts), - "Diff commit with parent", NULL); - check(git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, print_diff, NULL), - "Displaying diff", NULL); - - git_diff_free(diff); - git_tree_free(a); - git_tree_free(b); - } - } - - git_pathspec_free(ps); - git_revwalk_free(s.walker); - git_repository_free(s.repo); - git_threads_shutdown(); - - return 0; + return args.pos; } + diff --git a/examples/status.c b/examples/status.c index 0d9f55f13..f6816bcd3 100644 --- a/examples/status.c +++ b/examples/status.c @@ -4,18 +4,8 @@ * 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 -#include -#include -#include -enum { - FORMAT_DEFAULT = 0, - FORMAT_LONG = 1, - FORMAT_SHORT = 2, - FORMAT_PORCELAIN = 3, -}; -#define MAX_PATHSPEC 8 +#include "common.h" /* * This example demonstrates the use of the libgit2 status APIs, @@ -35,32 +25,83 @@ enum { * - A sample status formatter that matches the "short" format */ -static void check(int error, const char *message, const char *extra) +enum { + FORMAT_DEFAULT = 0, + FORMAT_LONG = 1, + FORMAT_SHORT = 2, + FORMAT_PORCELAIN = 3, +}; + +#define MAX_PATHSPEC 8 + +struct opts { + git_status_options statusopt; + char *repodir; + char *pathspec[MAX_PATHSPEC]; + int npaths; + int format; + int zterm; + int showbranch; +}; + +static void parse_opts(struct opts *o, int argc, char *argv[]); +static void show_branch(git_repository *repo, int format); +static void print_long(git_repository *repo, git_status_list *status); +static void print_short(git_repository *repo, git_status_list *status); + +int main(int argc, char *argv[]) { - const git_error *lg2err; - const char *lg2msg = "", *lg2spacer = ""; + git_repository *repo = NULL; + git_status_list *status; + struct opts o = { GIT_STATUS_OPTIONS_INIT, "." }; - if (!error) - return; + git_threads_init(); - if ((lg2err = giterr_last()) != NULL && lg2err->message != NULL) { - lg2msg = lg2err->message; - lg2spacer = " - "; - } + o.statusopt.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; + o.statusopt.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | + GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX | + GIT_STATUS_OPT_SORT_CASE_SENSITIVELY; + + parse_opts(&o, argc, argv); + + /* + * Try to open the repository at the given path (or at the current + * directory if none was given). + */ + check_lg2(git_repository_open_ext(&repo, o.repodir, 0, NULL), + "Could not open repository", o.repodir); + + if (git_repository_is_bare(repo)) + fatal("Cannot report status on bare repository", + git_repository_path(repo)); + + /* + * Run status on the repository + * + * Because we want to simluate a full "git status" run and want to + * support some command line options, we use `git_status_foreach_ext()` + * instead of just the plain status call. This allows (a) iterating + * over the index and then the workdir and (b) extra flags that control + * which files are included. If you just want simple status (e.g. to + * enumerate files that are modified) then you probably don't need the + * extended API. + */ + check_lg2(git_status_list_new(&status, repo, &o.statusopt), + "Could not get status", NULL); - if (extra) - fprintf(stderr, "%s '%s' [%d]%s%s\n", - message, extra, error, lg2spacer, lg2msg); + if (o.showbranch) + show_branch(repo, o.format); + + if (o.format == FORMAT_LONG) + print_long(repo, status); else - fprintf(stderr, "%s [%d]%s%s\n", - message, error, lg2spacer, lg2msg); + print_short(repo, status); - exit(1); -} + git_status_list_free(status); + git_repository_free(repo); + git_threads_shutdown(); -static void fail(const char *message) -{ - check(-1, message, NULL); + return 0; } static void show_branch(git_repository *repo, int format) @@ -78,7 +119,7 @@ static void show_branch(git_repository *repo, int format) if (!strncmp(branch, "refs/heads/", strlen("refs/heads/"))) branch += strlen("refs/heads/"); } else - check(error, "failed to get current branch", NULL); + check_lg2(error, "failed to get current branch", NULL); if (format == FORMAT_LONG) printf("# On branch %s\n", @@ -341,103 +382,58 @@ static void print_short(git_repository *repo, git_status_list *status) } } -int main(int argc, char *argv[]) +static void parse_opts(struct opts *o, int argc, char *argv[]) { - git_repository *repo = NULL; - int i, npaths = 0, format = FORMAT_DEFAULT, zterm = 0, showbranch = 0; - git_status_options opt = GIT_STATUS_OPTIONS_INIT; - git_status_list *status; - char *repodir = ".", *pathspec[MAX_PATHSPEC]; + struct args_info args = ARGS_INFO_INIT; - opt.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; - opt.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | - GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX | - GIT_STATUS_OPT_SORT_CASE_SENSITIVELY; + for (args.pos = 1; args.pos < argc; ++args.pos) { + char *a = argv[args.pos]; - for (i = 1; i < argc; ++i) { - if (argv[i][0] != '-') { - if (npaths < MAX_PATHSPEC) - pathspec[npaths++] = argv[i]; + if (a[0] != '-') { + if (o->npaths < MAX_PATHSPEC) + o->pathspec[o->npaths++] = a; else - fail("Example only supports a limited pathspec"); + fatal("Example only supports a limited pathspec", NULL); } - else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--short")) - format = FORMAT_SHORT; - else if (!strcmp(argv[i], "--long")) - format = FORMAT_LONG; - else if (!strcmp(argv[i], "--porcelain")) - format = FORMAT_PORCELAIN; - else if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--branch")) - showbranch = 1; - else if (!strcmp(argv[i], "-z")) { - zterm = 1; - if (format == FORMAT_DEFAULT) - format = FORMAT_PORCELAIN; + else if (!strcmp(a, "-s") || !strcmp(a, "--short")) + o->format = FORMAT_SHORT; + else if (!strcmp(a, "--long")) + o->format = FORMAT_LONG; + else if (!strcmp(a, "--porcelain")) + o->format = FORMAT_PORCELAIN; + else if (!strcmp(a, "-b") || !strcmp(a, "--branch")) + o->showbranch = 1; + else if (!strcmp(a, "-z")) { + o->zterm = 1; + if (o->format == FORMAT_DEFAULT) + o->format = FORMAT_PORCELAIN; } - else if (!strcmp(argv[i], "--ignored")) - opt.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED; - else if (!strcmp(argv[i], "-uno") || - !strcmp(argv[i], "--untracked-files=no")) - opt.flags &= ~GIT_STATUS_OPT_INCLUDE_UNTRACKED; - else if (!strcmp(argv[i], "-unormal") || - !strcmp(argv[i], "--untracked-files=normal")) - opt.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; - else if (!strcmp(argv[i], "-uall") || - !strcmp(argv[i], "--untracked-files=all")) - opt.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED | + else if (!strcmp(a, "--ignored")) + o->statusopt.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED; + else if (!strcmp(a, "-uno") || + !strcmp(a, "--untracked-files=no")) + o->statusopt.flags &= ~GIT_STATUS_OPT_INCLUDE_UNTRACKED; + else if (!strcmp(a, "-unormal") || + !strcmp(a, "--untracked-files=normal")) + o->statusopt.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + else if (!strcmp(a, "-uall") || + !strcmp(a, "--untracked-files=all")) + o->statusopt.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; - else if (!strcmp(argv[i], "--ignore-submodules=all")) - opt.flags |= GIT_STATUS_OPT_EXCLUDE_SUBMODULES; - else if (!strncmp(argv[i], "--git-dir=", strlen("--git-dir="))) - repodir = argv[i] + strlen("--git-dir="); + else if (!strcmp(a, "--ignore-submodules=all")) + o->statusopt.flags |= GIT_STATUS_OPT_EXCLUDE_SUBMODULES; + else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) + o->repodir = a + strlen("--git-dir="); else - check(-1, "Unsupported option", argv[i]); + check_lg2(-1, "Unsupported option", a); } - if (format == FORMAT_DEFAULT) - format = FORMAT_LONG; - if (format == FORMAT_LONG) - showbranch = 1; - if (npaths > 0) { - opt.pathspec.strings = pathspec; - opt.pathspec.count = npaths; + if (o->format == FORMAT_DEFAULT) + o->format = FORMAT_LONG; + if (o->format == FORMAT_LONG) + o->showbranch = 1; + if (o->npaths > 0) { + o->statusopt.pathspec.strings = o->pathspec; + o->statusopt.pathspec.count = o->npaths; } - - /* - * Try to open the repository at the given path (or at the current - * directory if none was given). - */ - check(git_repository_open_ext(&repo, repodir, 0, NULL), - "Could not open repository", repodir); - - if (git_repository_is_bare(repo)) - fail("Cannot report status on bare repository"); - - /* - * Run status on the repository - * - * Because we want to simluate a full "git status" run and want to - * support some command line options, we use `git_status_foreach_ext()` - * instead of just the plain status call. This allows (a) iterating - * over the index and then the workdir and (b) extra flags that control - * which files are included. If you just want simple status (e.g. to - * enumerate files that are modified) then you probably don't need the - * extended API. - */ - check(git_status_list_new(&status, repo, &opt), - "Could not get status", NULL); - - if (showbranch) - show_branch(repo, format); - - if (format == FORMAT_LONG) - print_long(repo, status); - else - print_short(repo, status); - - git_status_list_free(status); - git_repository_free(repo); - - return 0; } - -- cgit v1.2.1 From a8422f9202e6a177750c105260dd5bbf82a0778f Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 30 Oct 2013 05:38:12 -0700 Subject: init example: deploy helpers, reorg --- examples/init.c | 249 +++++++++++++++++++++++++++----------------------------- 1 file changed, 122 insertions(+), 127 deletions(-) diff --git a/examples/init.c b/examples/init.c index 4a379c6e3..d05788e10 100644 --- a/examples/init.c +++ b/examples/init.c @@ -15,164 +15,84 @@ * a Linking Exception. For full terms see the included COPYING file. */ -#include -#include -#include -#include -#include - -/* not actually good error handling */ -static void fail(const char *msg, const char *arg) -{ - if (arg) - fprintf(stderr, "%s %s\n", msg, arg); - else - fprintf(stderr, "%s\n", msg); - exit(1); -} - -static void usage(const char *error, const char *arg) -{ - fprintf(stderr, "error: %s '%s'\n", error, arg); - fprintf(stderr, "usage: init [-q | --quiet] [--bare] " - "[--template=] [--shared[=perms]] \n"); - exit(1); -} - -/* simple string prefix test used in argument parsing */ -static size_t is_prefixed(const char *arg, const char *pfx) -{ - size_t len = strlen(pfx); - return !strncmp(arg, pfx, len) ? len : 0; -} - -/* parse the tail of the --shared= argument */ -static uint32_t parse_shared(const char *shared) -{ - if (!strcmp(shared, "false") || !strcmp(shared, "umask")) - return GIT_REPOSITORY_INIT_SHARED_UMASK; - - else if (!strcmp(shared, "true") || !strcmp(shared, "group")) - return GIT_REPOSITORY_INIT_SHARED_GROUP; - - else if (!strcmp(shared, "all") || !strcmp(shared, "world") || - !strcmp(shared, "everybody")) - return GIT_REPOSITORY_INIT_SHARED_ALL; - - else if (shared[0] == '0') { - long val; - char *end = NULL; - val = strtol(shared + 1, &end, 8); - if (end == shared + 1 || *end != 0) - usage("invalid octal value for --shared", shared); - return (uint32_t)val; - } - - else - usage("unknown value for --shared", shared); - - return 0; -} - -/* forward declaration of helper to make an empty parent-less commit */ +#include "common.h" + +/* forward declarations of helpers */ +struct opts { + int no_options; + int quiet; + int bare; + int initial_commit; + uint32_t shared; + const char *template; + const char *gitdir; + const char *dir; +}; static void create_initial_commit(git_repository *repo); +static void parse_opts(struct opts *o, int argc, char *argv[]); int main(int argc, char *argv[]) { git_repository *repo = NULL; - int no_options = 1, quiet = 0, bare = 0, initial_commit = 0, i; - uint32_t shared = GIT_REPOSITORY_INIT_SHARED_UMASK; - const char *template = NULL, *gitdir = NULL, *dir = NULL; - size_t pfxlen; + struct opts o = { 1, 0, 0, 0, GIT_REPOSITORY_INIT_SHARED_UMASK, 0, 0, 0 }; git_threads_init(); - /* Process arguments */ - - for (i = 1; i < argc; ++i) { - char *a = argv[i]; - - if (a[0] == '-') - no_options = 0; - - if (a[0] != '-') { - if (dir != NULL) - usage("extra argument", a); - dir = a; - } - else if (!strcmp(a, "-q") || !strcmp(a, "--quiet")) - quiet = 1; - else if (!strcmp(a, "--bare")) - bare = 1; - else if ((pfxlen = is_prefixed(a, "--template=")) > 0) - template = a + pfxlen; - else if (!strcmp(a, "--separate-git-dir")) - gitdir = argv[++i]; - else if ((pfxlen = is_prefixed(a, "--separate-git-dir=")) > 0) - gitdir = a + pfxlen; - else if (!strcmp(a, "--shared")) - shared = GIT_REPOSITORY_INIT_SHARED_GROUP; - else if ((pfxlen = is_prefixed(a, "--shared=")) > 0) - shared = parse_shared(a + pfxlen); - else if (!strcmp(a, "--initial-commit")) - initial_commit = 1; - else - usage("unknown option", a); - } - - if (!dir) - usage("must specify directory to init", NULL); + parse_opts(&o, argc, argv); /* Initialize repository */ - if (no_options) { + if (o.no_options) { /* No options were specified, so let's demonstrate the default * simple case of git_repository_init() API usage... */ - if (git_repository_init(&repo, dir, 0) < 0) - fail("Could not initialize repository", dir); + if (git_repository_init(&repo, o.dir, 0) < 0) + fatal("Could not initialize repository", o.dir); } else { /* Some command line options were specified, so we'll use the * extended init API to handle them */ - git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + git_repository_init_options initopts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + initopts.flags = GIT_REPOSITORY_INIT_MKPATH; - if (bare) - opts.flags |= GIT_REPOSITORY_INIT_BARE; + if (o.bare) + initopts.flags |= GIT_REPOSITORY_INIT_BARE; - if (template) { - opts.flags |= GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; - opts.template_path = template; + if (o.template) { + initopts.flags |= GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; + initopts.template_path = o.template; } - if (gitdir) { + if (o.gitdir) { /* if you specified a separate git directory, then initialize * the repository at that path and use the second path as the * working directory of the repository (with a git-link file) */ - opts.workdir_path = dir; - dir = gitdir; + initopts.workdir_path = o.dir; + o.dir = o.gitdir; } - if (shared != 0) - opts.mode = shared; + if (o.shared != 0) + initopts.mode = o.shared; - if (git_repository_init_ext(&repo, dir, &opts) < 0) - fail("Could not initialize repository", dir); + if (git_repository_init_ext(&repo, o.dir, &initopts) < 0) { + const git_error *err = giterr_last(); + fatal("Could not initialize repository:", err->message); + } } /* Print a message to stdout like "git init" does */ - if (!quiet) { - if (bare || gitdir) - dir = git_repository_path(repo); + if (!o.quiet) { + if (o.bare || o.gitdir) + o.dir = git_repository_path(repo); else - dir = git_repository_workdir(repo); + o.dir = git_repository_workdir(repo); - printf("Initialized empty Git repository in %s\n", dir); + printf("Initialized empty Git repository in %s\n", o.dir); } /* As an extension to the basic "git init" command, this example @@ -180,7 +100,7 @@ int main(int argc, char *argv[]) * mostly to demonstrate what it takes to do that, but also some * people like to have that empty base commit in their repo. */ - if (initial_commit) { + if (o.initial_commit) { create_initial_commit(repo); printf("Created empty initial commit\n"); } @@ -205,13 +125,13 @@ static void create_initial_commit(git_repository *repo) /* First use the config to initialize a commit signature for the user */ if (git_signature_default(&sig, repo) < 0) - fail("Unable to create a commit signature.", - "Perhaps 'user.name' and 'user.email' are not set"); + fatal("Unable to create a commit signature.", + "Perhaps 'user.name' and 'user.email' are not set"); /* Now let's create an empty tree for this commit */ if (git_repository_index(&index, repo) < 0) - fail("Could not open repository index", NULL); + fatal("Could not open repository index", NULL); /* Outside of this example, you could call git_index_add_bypath() * here to put actual files into the index. For our purposes, we'll @@ -219,12 +139,12 @@ static void create_initial_commit(git_repository *repo) */ if (git_index_write_tree(&tree_id, index) < 0) - fail("Unable to write initial tree from index", NULL); + fatal("Unable to write initial tree from index", NULL); git_index_free(index); if (git_tree_lookup(&tree, repo, &tree_id) < 0) - fail("Could not look up initial tree", NULL); + fatal("Could not look up initial tree", NULL); /* Ready to create the initial commit * @@ -236,10 +156,85 @@ static void create_initial_commit(git_repository *repo) if (git_commit_create_v( &commit_id, repo, "HEAD", sig, sig, NULL, "Initial commit", tree, 0) < 0) - fail("Could not create the initial commit", NULL); + fatal("Could not create the initial commit", NULL); /* Clean up so we don't leak memory */ git_tree_free(tree); git_signature_free(sig); } + +static void usage(const char *error, const char *arg) +{ + fprintf(stderr, "error: %s '%s'\n", error, arg); + fprintf(stderr, + "usage: init [-q | --quiet] [--bare] [--template=]\n" + " [--shared[=perms]] [--initial-commit]\n" + " [--separate-git-dir] \n"); + exit(1); +} + +/* parse the tail of the --shared= argument */ +static uint32_t parse_shared(const char *shared) +{ + if (!strcmp(shared, "false") || !strcmp(shared, "umask")) + return GIT_REPOSITORY_INIT_SHARED_UMASK; + + else if (!strcmp(shared, "true") || !strcmp(shared, "group")) + return GIT_REPOSITORY_INIT_SHARED_GROUP; + + else if (!strcmp(shared, "all") || !strcmp(shared, "world") || + !strcmp(shared, "everybody")) + return GIT_REPOSITORY_INIT_SHARED_ALL; + + else if (shared[0] == '0') { + long val; + char *end = NULL; + val = strtol(shared + 1, &end, 8); + if (end == shared + 1 || *end != 0) + usage("invalid octal value for --shared", shared); + return (uint32_t)val; + } + + else + usage("unknown value for --shared", shared); + + return 0; +} + +static void parse_opts(struct opts *o, int argc, char *argv[]) +{ + struct args_info args = ARGS_INFO_INIT; + const char *sharedarg; + + /* Process arguments */ + + for (args.pos = 1; args.pos < argc; ++args.pos) { + char *a = argv[args.pos]; + + if (a[0] == '-') + o->no_options = 0; + + if (a[0] != '-') { + if (o->dir != NULL) + usage("extra argument", a); + o->dir = a; + } + else if (!strcmp(a, "-q") || !strcmp(a, "--quiet")) + o->quiet = 1; + else if (!strcmp(a, "--bare")) + o->bare = 1; + else if (!strcmp(a, "--shared")) + o->shared = GIT_REPOSITORY_INIT_SHARED_GROUP; + else if (!strcmp(a, "--initial-commit")) + o->initial_commit = 1; + else if (match_str_arg(&sharedarg, &args, "--shared")) + o->shared = parse_shared(sharedarg); + else if (!match_str_arg(&o->template, &args, "--template") || + !match_str_arg(&o->gitdir, &args, "--separate-git-dir")) + usage("unknown option", a); + } + + if (!o->dir) + usage("must specify directory to init", NULL); +} -- cgit v1.2.1 From 04e0c2b24db73dd5101738605dc4fe90d479aa08 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 30 Oct 2013 14:00:44 +0100 Subject: pack-objects: Depth can be negative --- src/pack-objects.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pack-objects.c b/src/pack-objects.c index 93541e974..d2774ce6a 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -824,7 +824,7 @@ static unsigned long free_unpacked(struct unpacked *n) static int find_deltas(git_packbuilder *pb, git_pobject **list, unsigned int *list_size, unsigned int window, - unsigned int depth) + int depth) { git_pobject *po; git_buf zbuf = GIT_BUF_INIT; @@ -839,8 +839,7 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list, for (;;) { struct unpacked *n = array + idx; - unsigned int max_depth; - int j, best_base = -1; + int max_depth, j, best_base = -1; git_packbuilder__progress_lock(pb); if (!*list_size) { @@ -1033,7 +1032,7 @@ static void *threaded_find_deltas(void *arg) static int ll_find_deltas(git_packbuilder *pb, git_pobject **list, unsigned int list_size, unsigned int window, - unsigned int depth) + int depth) { struct thread_params *p; int i, ret, active_threads = 0; -- cgit v1.2.1 From e568bedf526693e2a8aab5811364ae5a3a16f4e2 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 30 Oct 2013 06:08:54 -0700 Subject: add.c example: deploy helpers, reorg --- examples/add.c | 118 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 61 insertions(+), 57 deletions(-) diff --git a/examples/add.c b/examples/add.c index a0edf4376..0411ca7bc 100644 --- a/examples/add.c +++ b/examples/add.c @@ -14,19 +14,49 @@ struct print_payload { git_repository *repo; }; -void init_array(git_strarray *array, int argc, char **argv) +/* Forward declarations for helpers */ +static void parse_opts(int *options, int *count, int argc, char *argv[]); +void init_array(git_strarray *array, int argc, char **argv); +int print_matched_cb(const char *path, const char *matched_pathspec, void *payload); + +int main (int argc, char** argv) { - unsigned int i; + git_index_matched_path_cb matched_cb = NULL; + git_repository *repo = NULL; + git_index *index; + git_strarray array = {0}; + int options = 0, count = 0; + struct print_payload payload = {0}; - array->count = argc; - array->strings = malloc(sizeof(char*) * array->count); - assert(array->strings!=NULL); + git_threads_init(); - for(i=0; icount; i++) { - array->strings[i]=argv[i]; + parse_opts(&options, &count, argc, argv); + + init_array(&array, argc-count, argv+count); + + check_lg2(git_repository_open(&repo, "."), "No git repository", NULL); + check_lg2(git_repository_index(&index, repo), "Could not open repository index", NULL); + + if (options&VERBOSE || options&SKIP) { + matched_cb = &print_matched_cb; } - return; + payload.options = options; + payload.repo = repo; + + if (options&UPDATE) { + git_index_update_all(index, &array, matched_cb, &payload); + } else { + git_index_add_all(index, &array, 0, matched_cb, &payload); + } + + git_index_write(index); + git_index_free(index); + git_repository_free(repo); + + git_threads_shutdown(); + + return 0; } int print_matched_cb(const char *path, const char *matched_pathspec, void *payload) @@ -55,36 +85,46 @@ int print_matched_cb(const char *path, const char *matched_pathspec, void *paylo return ret; } +void init_array(git_strarray *array, int argc, char **argv) +{ + unsigned int i; + + array->count = argc; + array->strings = malloc(sizeof(char*) * array->count); + assert(array->strings!=NULL); + + for(i=0; icount; i++) { + array->strings[i]=argv[i]; + } + + return; +} + void print_usage(void) { fprintf(stderr, "usage: add [options] [--] file-spec [file-spec] [...]\n\n"); fprintf(stderr, "\t-n, --dry-run dry run\n"); fprintf(stderr, "\t-v, --verbose be verbose\n"); fprintf(stderr, "\t-u, --update update tracked files\n"); + exit(1); } - -int main (int argc, char** argv) +static void parse_opts(int *options, int *count, int argc, char *argv[]) { - git_index_matched_path_cb matched_cb = NULL; - git_repository *repo = NULL; - git_index *index; - git_strarray array = {0}; - int i, options = 0; - struct print_payload payload = {0}; + int i; for (i = 1; i < argc; ++i) { if (argv[i][0] != '-') { break; } else if(!strcmp(argv[i], "--verbose") || !strcmp(argv[i], "-v")) { - options |= VERBOSE; + *options |= VERBOSE; } else if(!strcmp(argv[i], "--dry-run") || !strcmp(argv[i], "-n")) { - options |= SKIP; + *options |= SKIP; } else if(!strcmp(argv[i], "--update") || !strcmp(argv[i], "-u")) { - options |= UPDATE; + *options |= UPDATE; } else if(!strcmp(argv[i], "-h")) { print_usage(); @@ -97,47 +137,11 @@ int main (int argc, char** argv) else { fprintf(stderr, "Unsupported option %s.\n", argv[i]); print_usage(); - return 1; } } - if (argc<=i) { + if (argc<=i) print_usage(); - return 1; - } - git_threads_init(); - - init_array(&array, argc-i, argv+i); - - if (git_repository_open(&repo, ".") < 0) { - fprintf(stderr, "No git repository\n"); - return 1; - } - - if (git_repository_index(&index, repo) < 0) { - fprintf(stderr, "Could not open repository index\n"); - return 1; - } - - if (options&VERBOSE || options&SKIP) { - matched_cb = &print_matched_cb; - } - - payload.options = options; - payload.repo = repo; - - if (options&UPDATE) { - git_index_update_all(index, &array, matched_cb, &payload); - } else { - git_index_add_all(index, &array, 0, matched_cb, &payload); - } - - git_index_write(index); - git_index_free(index); - git_repository_free(repo); - - git_threads_shutdown(); - - return 0; + *count = i; } -- cgit v1.2.1 From 7cc3c9bf00788e0d91f1a495a28b12509c5bd89d Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 30 Oct 2013 06:09:08 -0700 Subject: init.c example: deploy more helpers --- examples/init.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/examples/init.c b/examples/init.c index d05788e10..5bec17b9d 100644 --- a/examples/init.c +++ b/examples/init.c @@ -47,9 +47,8 @@ int main(int argc, char *argv[]) /* No options were specified, so let's demonstrate the default * simple case of git_repository_init() API usage... */ - - if (git_repository_init(&repo, o.dir, 0) < 0) - fatal("Could not initialize repository", o.dir); + check_lg2(git_repository_init(&repo, o.dir, 0), + "Could not initialize repository", NULL); } else { /* Some command line options were specified, so we'll use the @@ -78,10 +77,8 @@ int main(int argc, char *argv[]) if (o.shared != 0) initopts.mode = o.shared; - if (git_repository_init_ext(&repo, o.dir, &initopts) < 0) { - const git_error *err = giterr_last(); - fatal("Could not initialize repository:", err->message); - } + check_lg2(git_repository_init_ext(&repo, o.dir, &initopts), + "Could not initialize repository", NULL); } /* Print a message to stdout like "git init" does */ -- cgit v1.2.1 From a6154f2183043626cdbe995b4795346610b5862e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 30 Oct 2013 15:00:05 +0100 Subject: indexer: remove the stream infix It was there to keep it apart from the one which read in from a file on disk. This other indexer does not exist anymore, so there is no need for anything other than git_indexer to refer to it. While here, rename _add() function to _append() and _finalize() to _commit(). The former change is cosmetic, while the latter avoids talking about "finalizing", which OO languages use to mean something completely different. --- examples/network/index-pack.c | 12 +++++----- include/git2/indexer.h | 16 ++++++------- include/git2/odb_backend.h | 2 +- src/indexer.c | 52 ++++++++++++++++++++--------------------- src/odb_pack.c | 14 +++++------ src/pack-objects.c | 14 +++++------ src/transports/local.c | 2 +- src/transports/smart_protocol.c | 4 ++-- tests-clar/pack/indexer.c | 30 ++++++++++++------------ tests-clar/pack/packbuilder.c | 24 +++++++++---------- 10 files changed, 85 insertions(+), 85 deletions(-) diff --git a/examples/network/index-pack.c b/examples/network/index-pack.c index 08b45c58c..59fff416a 100644 --- a/examples/network/index-pack.c +++ b/examples/network/index-pack.c @@ -31,7 +31,7 @@ static int index_cb(const git_transfer_progress *stats, void *data) int index_pack(git_repository *repo, int argc, char **argv) { - git_indexer_stream *idx; + git_indexer *idx; git_transfer_progress stats = {0, 0}; int error; char hash[GIT_OID_HEXSZ + 1] = {0}; @@ -46,7 +46,7 @@ int index_pack(git_repository *repo, int argc, char **argv) return EXIT_FAILURE; } - if (git_indexer_stream_new(&idx, ".", NULL, NULL, NULL) < 0) { + if (git_indexer_new(&idx, ".", NULL, NULL, NULL) < 0) { puts("bad idx"); return -1; } @@ -61,7 +61,7 @@ int index_pack(git_repository *repo, int argc, char **argv) if (read_bytes < 0) break; - if ((error = git_indexer_stream_add(idx, buf, read_bytes, &stats)) < 0) + if ((error = git_indexer_append(idx, buf, read_bytes, &stats)) < 0) goto cleanup; index_cb(&stats, NULL); @@ -73,16 +73,16 @@ int index_pack(git_repository *repo, int argc, char **argv) goto cleanup; } - if ((error = git_indexer_stream_finalize(idx, &stats)) < 0) + if ((error = git_indexer_commit(idx, &stats)) < 0) goto cleanup; printf("\rIndexing %d of %d\n", stats.indexed_objects, stats.total_objects); - git_oid_fmt(hash, git_indexer_stream_hash(idx)); + git_oid_fmt(hash, git_indexer_hash(idx)); puts(hash); cleanup: close(fd); - git_indexer_stream_free(idx); + git_indexer_free(idx); return error; } diff --git a/include/git2/indexer.h b/include/git2/indexer.h index 0858b6ea1..fb55672a9 100644 --- a/include/git2/indexer.h +++ b/include/git2/indexer.h @@ -13,10 +13,10 @@ GIT_BEGIN_DECL -typedef struct git_indexer_stream git_indexer_stream; +typedef struct git_indexer git_indexer; /** - * Create a new streaming indexer instance + * Create a new indexer instance * * @param out where to store the indexer instance * @param path to the directory where the packfile should be stored @@ -26,8 +26,8 @@ typedef struct git_indexer_stream git_indexer_stream; * @param progress_cb function to call with progress information * @param progress_cb_payload payload for the progress callback */ -GIT_EXTERN(int) git_indexer_stream_new( - git_indexer_stream **out, +GIT_EXTERN(int) git_indexer_new( + git_indexer **out, const char *path, git_odb *odb, git_transfer_progress_callback progress_cb, @@ -41,7 +41,7 @@ GIT_EXTERN(int) git_indexer_stream_new( * @param size the size of the data in bytes * @param stats stat storage */ -GIT_EXTERN(int) git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_transfer_progress *stats); +GIT_EXTERN(int) git_indexer_append(git_indexer *idx, const void *data, size_t size, git_transfer_progress *stats); /** * Finalize the pack and index @@ -50,7 +50,7 @@ GIT_EXTERN(int) git_indexer_stream_add(git_indexer_stream *idx, const void *data * * @param idx the indexer */ -GIT_EXTERN(int) git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress *stats); +GIT_EXTERN(int) git_indexer_commit(git_indexer *idx, git_transfer_progress *stats); /** * Get the packfile's hash @@ -60,14 +60,14 @@ GIT_EXTERN(int) git_indexer_stream_finalize(git_indexer_stream *idx, git_transfe * * @param idx the indexer instance */ -GIT_EXTERN(const git_oid *) git_indexer_stream_hash(const git_indexer_stream *idx); +GIT_EXTERN(const git_oid *) git_indexer_hash(const git_indexer *idx); /** * Free the indexer and its resources * * @param idx the indexer to free */ -GIT_EXTERN(void) git_indexer_stream_free(git_indexer_stream *idx); +GIT_EXTERN(void) git_indexer_free(git_indexer *idx); GIT_END_DECL diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index a6cb285dc..1b3e2fd12 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -116,7 +116,7 @@ struct git_odb_stream { struct git_odb_writepack { git_odb_backend *backend; - int (*add)(git_odb_writepack *writepack, const void *data, size_t size, git_transfer_progress *stats); + int (*append)(git_odb_writepack *writepack, const void *data, size_t size, git_transfer_progress *stats); int (*commit)(git_odb_writepack *writepack, git_transfer_progress *stats); void (*free)(git_odb_writepack *writepack); }; diff --git a/src/indexer.c b/src/indexer.c index 9f55c8b2c..07d0073c8 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -29,7 +29,7 @@ struct entry { uint64_t offset_long; }; -struct git_indexer_stream { +struct git_indexer { unsigned int parsed_header :1, opened_pack :1, have_stream :1, @@ -63,7 +63,7 @@ struct delta_info { git_off_t delta_off; }; -const git_oid *git_indexer_stream_hash(const git_indexer_stream *idx) +const git_oid *git_indexer_hash(const git_indexer *idx) { return &idx->hash; } @@ -116,19 +116,19 @@ static int objects_cmp(const void *a, const void *b) return git_oid__cmp(&entrya->oid, &entryb->oid); } -int git_indexer_stream_new( - git_indexer_stream **out, +int git_indexer_new( + git_indexer **out, const char *prefix, git_odb *odb, git_transfer_progress_callback progress_cb, void *progress_payload) { - git_indexer_stream *idx; + git_indexer *idx; git_buf path = GIT_BUF_INIT; static const char suff[] = "/pack"; int error; - idx = git__calloc(1, sizeof(git_indexer_stream)); + idx = git__calloc(1, sizeof(git_indexer)); GITERR_CHECK_ALLOC(idx); idx->odb = odb; idx->progress_cb = progress_cb; @@ -156,7 +156,7 @@ cleanup: } /* Try to store the delta so we can try to resolve it later */ -static int store_delta(git_indexer_stream *idx) +static int store_delta(git_indexer *idx) { struct delta_info *delta; @@ -179,7 +179,7 @@ static void hash_header(git_hash_ctx *ctx, git_off_t len, git_otype type) git_hash_update(ctx, buffer, hdrlen); } -static int hash_object_stream(git_indexer_stream *idx, git_packfile_stream *stream) +static int hash_object_stream(git_indexer*idx, git_packfile_stream *stream) { ssize_t read; @@ -199,7 +199,7 @@ static int hash_object_stream(git_indexer_stream *idx, git_packfile_stream *stre } /* In order to create the packfile stream, we need to skip over the delta base description */ -static int advance_delta_offset(git_indexer_stream *idx, git_otype type) +static int advance_delta_offset(git_indexer *idx, git_otype type) { git_mwindow *w = NULL; @@ -218,7 +218,7 @@ static int advance_delta_offset(git_indexer_stream *idx, git_otype type) } /* Read from the stream and discard any output */ -static int read_object_stream(git_indexer_stream *idx, git_packfile_stream *stream) +static int read_object_stream(git_indexer *idx, git_packfile_stream *stream) { ssize_t read; @@ -258,7 +258,7 @@ static int crc_object(uint32_t *crc_out, git_mwindow_file *mwf, git_off_t start, return 0; } -static int store_object(git_indexer_stream *idx) +static int store_object(git_indexer *idx) { int i, error; khiter_t k; @@ -316,7 +316,7 @@ on_error: return -1; } -static int save_entry(git_indexer_stream *idx, struct entry *entry, struct git_pack_entry *pentry, git_off_t entry_start) +static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_entry *pentry, git_off_t entry_start) { int i, error; khiter_t k; @@ -346,7 +346,7 @@ static int save_entry(git_indexer_stream *idx, struct entry *entry, struct git_p return 0; } -static int hash_and_save(git_indexer_stream *idx, git_rawobj *obj, git_off_t entry_start) +static int hash_and_save(git_indexer *idx, git_rawobj *obj, git_off_t entry_start) { git_oid oid; size_t entry_size; @@ -380,14 +380,14 @@ on_error: return -1; } -static int do_progress_callback(git_indexer_stream *idx, git_transfer_progress *stats) +static int do_progress_callback(git_indexer *idx, git_transfer_progress *stats) { if (!idx->progress_cb) return 0; return idx->progress_cb(stats, idx->progress_payload); } /* Hash everything but the last 20B of input */ -static void hash_partially(git_indexer_stream *idx, const uint8_t *data, size_t size) +static void hash_partially(git_indexer *idx, const uint8_t *data, size_t size) { size_t to_expell, to_keep; @@ -423,7 +423,7 @@ static void hash_partially(git_indexer_stream *idx, const uint8_t *data, size_t idx->inbuf_len += size - to_expell; } -int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_transfer_progress *stats) +int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_transfer_progress *stats) { int error = -1; size_t processed; @@ -583,7 +583,7 @@ on_error: return error; } -static int index_path_stream(git_buf *path, git_indexer_stream *idx, const char *suffix) +static int index_path(git_buf *path, git_indexer *idx, const char *suffix) { const char prefix[] = "pack-"; size_t slash = (size_t)path->size; @@ -609,7 +609,7 @@ static int index_path_stream(git_buf *path, git_indexer_stream *idx, const char * Rewind the packfile by the trailer, as we might need to fix the * packfile by injecting objects at the tail and must overwrite it. */ -static git_off_t seek_back_trailer(git_indexer_stream *idx) +static git_off_t seek_back_trailer(git_indexer *idx) { git_off_t off; @@ -622,7 +622,7 @@ static git_off_t seek_back_trailer(git_indexer_stream *idx) return off; } -static int inject_object(git_indexer_stream *idx, git_oid *id) +static int inject_object(git_indexer *idx, git_oid *id) { git_odb_object *obj; struct entry *entry; @@ -684,7 +684,7 @@ cleanup: return error; } -static int fix_thin_pack(git_indexer_stream *idx, git_transfer_progress *stats) +static int fix_thin_pack(git_indexer *idx, git_transfer_progress *stats) { int error, found_ref_delta = 0; unsigned int i; @@ -741,7 +741,7 @@ static int fix_thin_pack(git_indexer_stream *idx, git_transfer_progress *stats) return 0; } -static int resolve_deltas(git_indexer_stream *idx, git_transfer_progress *stats) +static int resolve_deltas(git_indexer *idx, git_transfer_progress *stats) { unsigned int i; struct delta_info *delta; @@ -784,7 +784,7 @@ static int resolve_deltas(git_indexer_stream *idx, git_transfer_progress *stats) return 0; } -static int update_header_and_rehash(git_indexer_stream *idx, git_transfer_progress *stats) +static int update_header_and_rehash(git_indexer *idx, git_transfer_progress *stats) { void *ptr; size_t chunk = 1024*1024; @@ -833,7 +833,7 @@ static int update_header_and_rehash(git_indexer_stream *idx, git_transfer_progre return 0; } -int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress *stats) +int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) { git_mwindow *w = NULL; unsigned int i, long_offsets = 0, left; @@ -965,7 +965,7 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * git_filebuf_write(&index_file, &trailer_hash, sizeof(git_oid)); /* Figure out what the final name should be */ - if (index_path_stream(&filename, idx, ".idx") < 0) + if (index_path(&filename, idx, ".idx") < 0) goto on_error; /* Commit file */ @@ -977,7 +977,7 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * p_close(idx->pack->mwf.fd); idx->pack->mwf.fd = -1; - if (index_path_stream(&filename, idx, ".pack") < 0) + if (index_path(&filename, idx, ".pack") < 0) goto on_error; /* And don't forget to rename the packfile to its new place. */ if (git_filebuf_commit_at(&idx->pack_file, filename.ptr, GIT_PACK_FILE_MODE) < 0) @@ -994,7 +994,7 @@ on_error: return -1; } -void git_indexer_stream_free(git_indexer_stream *idx) +void git_indexer_free(git_indexer *idx) { khiter_t k; unsigned int i; diff --git a/src/odb_pack.c b/src/odb_pack.c index 4c7c82253..12f4591ec 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -29,7 +29,7 @@ struct pack_backend { struct pack_writepack { struct git_odb_writepack parent; - git_indexer_stream *indexer_stream; + git_indexer *indexer; }; /** @@ -511,13 +511,13 @@ static int pack_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb c return 0; } -static int pack_backend__writepack_add(struct git_odb_writepack *_writepack, const void *data, size_t size, git_transfer_progress *stats) +static int pack_backend__writepack_append(struct git_odb_writepack *_writepack, const void *data, size_t size, git_transfer_progress *stats) { struct pack_writepack *writepack = (struct pack_writepack *)_writepack; assert(writepack); - return git_indexer_stream_add(writepack->indexer_stream, data, size, stats); + return git_indexer_append(writepack->indexer, data, size, stats); } static int pack_backend__writepack_commit(struct git_odb_writepack *_writepack, git_transfer_progress *stats) @@ -526,7 +526,7 @@ static int pack_backend__writepack_commit(struct git_odb_writepack *_writepack, assert(writepack); - return git_indexer_stream_finalize(writepack->indexer_stream, stats); + return git_indexer_commit(writepack->indexer, stats); } static void pack_backend__writepack_free(struct git_odb_writepack *_writepack) @@ -535,7 +535,7 @@ static void pack_backend__writepack_free(struct git_odb_writepack *_writepack) assert(writepack); - git_indexer_stream_free(writepack->indexer_stream); + git_indexer_free(writepack->indexer); git__free(writepack); } @@ -557,14 +557,14 @@ static int pack_backend__writepack(struct git_odb_writepack **out, writepack = git__calloc(1, sizeof(struct pack_writepack)); GITERR_CHECK_ALLOC(writepack); - if (git_indexer_stream_new(&writepack->indexer_stream, + if (git_indexer_new(&writepack->indexer, backend->pack_folder, odb, progress_cb, progress_payload) < 0) { git__free(writepack); return -1; } writepack->parent.backend = _backend; - writepack->parent.add = pack_backend__writepack_add; + writepack->parent.append = pack_backend__writepack_append; writepack->parent.commit = pack_backend__writepack_commit; writepack->parent.free = pack_backend__writepack_free; diff --git a/src/pack-objects.c b/src/pack-objects.c index 93541e974..938b28fde 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -35,7 +35,7 @@ struct tree_walk_context { }; struct pack_write_context { - git_indexer_stream *indexer; + git_indexer *indexer; git_transfer_progress *stats; }; @@ -1242,7 +1242,7 @@ int git_packbuilder_write_buf(git_buf *buf, git_packbuilder *pb) static int write_cb(void *buf, size_t len, void *payload) { struct pack_write_context *ctx = payload; - return git_indexer_stream_add(ctx->indexer, buf, len, ctx->stats); + return git_indexer_append(ctx->indexer, buf, len, ctx->stats); } int git_packbuilder_write( @@ -1251,13 +1251,13 @@ int git_packbuilder_write( git_transfer_progress_callback progress_cb, void *progress_cb_payload) { - git_indexer_stream *indexer; + git_indexer *indexer; git_transfer_progress stats; struct pack_write_context ctx; PREPARE_PACK; - if (git_indexer_stream_new( + if (git_indexer_new( &indexer, path, pb->odb, progress_cb, progress_cb_payload) < 0) return -1; @@ -1265,12 +1265,12 @@ int git_packbuilder_write( ctx.stats = &stats; if (git_packbuilder_foreach(pb, write_cb, &ctx) < 0 || - git_indexer_stream_finalize(indexer, &stats) < 0) { - git_indexer_stream_free(indexer); + git_indexer_commit(indexer, &stats) < 0) { + git_indexer_free(indexer); return -1; } - git_indexer_stream_free(indexer); + git_indexer_free(indexer); return 0; } diff --git a/src/transports/local.c b/src/transports/local.c index 3c1f98804..3163d2eac 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -459,7 +459,7 @@ static int foreach_cb(void *buf, size_t len, void *payload) foreach_data *data = (foreach_data*)payload; data->stats->received_bytes += len; - return data->writepack->add(data->writepack, buf, len, data->stats); + return data->writepack->append(data->writepack, buf, len, data->stats); } static int local_download_pack( diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index af6e35fa1..8833b2816 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -408,7 +408,7 @@ static int no_sideband(transport_smart *t, struct git_odb_writepack *writepack, return GIT_EUSER; } - if (writepack->add(writepack, buf->data, buf->offset, stats) < 0) + if (writepack->append(writepack, buf->data, buf->offset, stats) < 0) return -1; gitno_consume_n(buf, buf->offset); @@ -523,7 +523,7 @@ int git_smart__download_pack( git__free(pkt); } else if (pkt->type == GIT_PKT_DATA) { git_pkt_data *p = (git_pkt_data *) pkt; - error = writepack->add(writepack, p->data, p->len, stats); + error = writepack->append(writepack, p->data, p->len, stats); git__free(pkt); if (error < 0) diff --git a/tests-clar/pack/indexer.c b/tests-clar/pack/indexer.c index 17ec7b3f8..e26b3ec20 100644 --- a/tests-clar/pack/indexer.c +++ b/tests-clar/pack/indexer.c @@ -45,23 +45,23 @@ unsigned int base_obj_len = 2; void test_pack_indexer__out_of_order(void) { - git_indexer_stream *idx; + git_indexer *idx; git_transfer_progress stats; - cl_git_pass(git_indexer_stream_new(&idx, ".", NULL, NULL, NULL)); - cl_git_pass(git_indexer_stream_add(idx, out_of_order_pack, out_of_order_pack_len, &stats)); - cl_git_pass(git_indexer_stream_finalize(idx, &stats)); + cl_git_pass(git_indexer_new(&idx, ".", NULL, NULL, NULL)); + cl_git_pass(git_indexer_append(idx, out_of_order_pack, out_of_order_pack_len, &stats)); + cl_git_pass(git_indexer_commit(idx, &stats)); cl_assert_equal_i(stats.total_objects, 3); cl_assert_equal_i(stats.received_objects, 3); cl_assert_equal_i(stats.indexed_objects, 3); - git_indexer_stream_free(idx); + git_indexer_free(idx); } void test_pack_indexer__fix_thin(void) { - git_indexer_stream *idx; + git_indexer *idx; git_transfer_progress stats; git_repository *repo; git_odb *odb; @@ -75,9 +75,9 @@ void test_pack_indexer__fix_thin(void) git_oid_fromstr(&should_id, "e68fe8129b546b101aee9510c5328e7f21ca1d18"); cl_assert(!git_oid_cmp(&id, &should_id)); - cl_git_pass(git_indexer_stream_new(&idx, ".", odb, NULL, NULL)); - cl_git_pass(git_indexer_stream_add(idx, thin_pack, thin_pack_len, &stats)); - cl_git_pass(git_indexer_stream_finalize(idx, &stats)); + cl_git_pass(git_indexer_new(&idx, ".", odb, NULL, NULL)); + cl_git_pass(git_indexer_append(idx, thin_pack, thin_pack_len, &stats)); + cl_git_pass(git_indexer_commit(idx, &stats)); cl_assert_equal_i(stats.total_objects, 2); cl_assert_equal_i(stats.received_objects, 2); @@ -85,9 +85,9 @@ void test_pack_indexer__fix_thin(void) cl_assert_equal_i(stats.local_objects, 1); git_oid_fromstr(&should_id, "11f0f69b334728fdd8bc86b80499f22f29d85b15"); - cl_assert(!git_oid_cmp(git_indexer_stream_hash(idx), &should_id)); + cl_assert(!git_oid_cmp(git_indexer_hash(idx), &should_id)); - git_indexer_stream_free(idx); + git_indexer_free(idx); git_odb_free(odb); git_repository_free(repo); @@ -110,19 +110,19 @@ void test_pack_indexer__fix_thin(void) cl_git_pass(p_stat(name, &st)); left = st.st_size; - cl_git_pass(git_indexer_stream_new(&idx, ".", NULL, NULL, NULL)); + cl_git_pass(git_indexer_new(&idx, ".", NULL, NULL, NULL)); read = p_read(fd, buffer, sizeof(buffer)); cl_assert(read != -1); p_close(fd); - cl_git_pass(git_indexer_stream_add(idx, buffer, read, &stats)); - cl_git_pass(git_indexer_stream_finalize(idx, &stats)); + cl_git_pass(git_indexer_append(idx, buffer, read, &stats)); + cl_git_pass(git_indexer_commit(idx, &stats)); cl_assert_equal_i(stats.total_objects, 3); cl_assert_equal_i(stats.received_objects, 3); cl_assert_equal_i(stats.indexed_objects, 3); cl_assert_equal_i(stats.local_objects, 0); - git_indexer_stream_free(idx); + git_indexer_free(idx); } } diff --git a/tests-clar/pack/packbuilder.c b/tests-clar/pack/packbuilder.c index 69292567e..ac6f731e1 100644 --- a/tests-clar/pack/packbuilder.c +++ b/tests-clar/pack/packbuilder.c @@ -8,7 +8,7 @@ static git_repository *_repo; static git_revwalk *_revwalker; static git_packbuilder *_packbuilder; -static git_indexer_stream *_indexer; +static git_indexer *_indexer; static git_vector _commits; static int _commits_is_initialized; @@ -40,7 +40,7 @@ void test_pack_packbuilder__cleanup(void) git_revwalk_free(_revwalker); _revwalker = NULL; - git_indexer_stream_free(_indexer); + git_indexer_free(_indexer); _indexer = NULL; cl_git_sandbox_cleanup(); @@ -79,7 +79,7 @@ static int feed_indexer(void *ptr, size_t len, void *payload) { git_transfer_progress *stats = (git_transfer_progress *)payload; - return git_indexer_stream_add(_indexer, ptr, len, stats); + return git_indexer_append(_indexer, ptr, len, stats); } void test_pack_packbuilder__create_pack(void) @@ -92,11 +92,11 @@ void test_pack_packbuilder__create_pack(void) seed_packbuilder(); - cl_git_pass(git_indexer_stream_new(&_indexer, ".", NULL, NULL, NULL)); + cl_git_pass(git_indexer_new(&_indexer, ".", NULL, NULL, NULL)); cl_git_pass(git_packbuilder_foreach(_packbuilder, feed_indexer, &stats)); - cl_git_pass(git_indexer_stream_finalize(_indexer, &stats)); + cl_git_pass(git_indexer_commit(_indexer, &stats)); - git_oid_fmt(hex, git_indexer_stream_hash(_indexer)); + git_oid_fmt(hex, git_indexer_hash(_indexer)); git_buf_printf(&path, "pack-%s.pack", hex); /* @@ -131,18 +131,18 @@ void test_pack_packbuilder__create_pack(void) static git_transfer_progress stats; static int foreach_cb(void *buf, size_t len, void *payload) { - git_indexer_stream *idx = (git_indexer_stream *) payload; - cl_git_pass(git_indexer_stream_add(idx, buf, len, &stats)); + git_indexer *idx = (git_indexer *) payload; + cl_git_pass(git_indexer_append(idx, buf, len, &stats)); return 0; } void test_pack_packbuilder__foreach(void) { - git_indexer_stream *idx; + git_indexer *idx; seed_packbuilder(); - cl_git_pass(git_indexer_stream_new(&idx, ".", NULL, NULL, NULL)); + cl_git_pass(git_indexer_new(&idx, ".", NULL, NULL, NULL)); cl_git_pass(git_packbuilder_foreach(_packbuilder, foreach_cb, idx)); - cl_git_pass(git_indexer_stream_finalize(idx, &stats)); - git_indexer_stream_free(idx); + cl_git_pass(git_indexer_commit(idx, &stats)); + git_indexer_free(idx); } -- cgit v1.2.1 From 97d32abb492f7830f6e26719ce558429f6377b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 30 Oct 2013 15:09:32 +0100 Subject: Remove leftover function declaration --- include/git2/remote.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index f4cd1cbfa..b9cf86ef1 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -356,21 +356,6 @@ GIT_EXTERN(int) git_remote_list(git_strarray *out, git_repository *repo); */ GIT_EXTERN(void) git_remote_check_cert(git_remote *remote, int check); -/** - * Set a credentials acquisition callback for this remote. If the remote is - * not available for anonymous access, then you must set this callback in order - * to provide credentials to the transport at the time of authentication - * failure so that retry can be performed. - * - * @param remote the remote to configure - * @param cred_acquire_cb The credentials acquisition callback to use (defaults - * to NULL) - */ -GIT_EXTERN(void) git_remote_set_cred_acquire_cb( - git_remote *remote, - git_cred_acquire_cb cred_acquire_cb, - void *payload); - /** * Sets a custom transport for the remote. The caller can use this function * to bypass the automatic discovery of a transport by URL scheme (i.e. -- cgit v1.2.1 From dbfd2833270ecbcdf98dcb2914c148a146b70307 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 30 Oct 2013 07:21:12 -0700 Subject: add.c: proper frontmatter --- examples/add.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/examples/add.c b/examples/add.c index 0411ca7bc..999a41e64 100644 --- a/examples/add.c +++ b/examples/add.c @@ -1,6 +1,11 @@ -#include -#include -#include +/* + * 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 "common.h" #include enum print_options { -- cgit v1.2.1 From 9d83d368fcebaeb51041212dad165b991c0a8329 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 30 Oct 2013 07:21:36 -0700 Subject: cat-file.c example: deploy helpers, reorg --- examples/cat-file.c | 154 ++++++++++++++++++++++++++-------------------------- 1 file changed, 78 insertions(+), 76 deletions(-) diff --git a/examples/cat-file.c b/examples/cat-file.c index ebb6cb0ca..1e5b5ea5d 100644 --- a/examples/cat-file.c +++ b/examples/cat-file.c @@ -1,37 +1,11 @@ -#include -#include -#include -#include +/* + * 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. + */ -static git_repository *g_repo; - -static void check(int error, const char *message) -{ - if (error) { - fprintf(stderr, "%s (%d)\n", message, error); - exit(1); - } -} - -static void usage(const char *message, const char *arg) -{ - if (message && arg) - fprintf(stderr, "%s: %s\n", message, arg); - else if (message) - fprintf(stderr, "%s\n", message); - fprintf(stderr, "usage: cat-file (-t | -s | -e | -p) [] \n"); - exit(1); -} - -static int check_str_param( - const char *arg, const char *pattern, const char **val) -{ - size_t len = strlen(pattern); - if (strncmp(arg, pattern, len)) - return 0; - *val = (const char *)(arg + len); - return 1; -} +#include "common.h" static void print_signature(const char *header, const git_signature *sig) { @@ -123,53 +97,33 @@ enum { SHOW_PRETTY = 4 }; +/* Forward declarations for option-parsing helper */ +struct opts { + const char *dir; + const char *rev; + int action; + int verbose; +}; +static void parse_opts(struct opts *o, int argc, char *argv[]); + + int main(int argc, char *argv[]) { - const char *dir = ".", *rev = NULL; - int i, action = 0, verbose = 0; + git_repository *repo; + struct opts o = { ".", NULL, 0, 0 }; git_object *obj = NULL; char oidstr[GIT_OID_HEXSZ + 1]; git_threads_init(); - for (i = 1; i < argc; ++i) { - char *a = argv[i]; - - if (a[0] != '-') { - if (rev != NULL) - usage("Only one rev should be provided", NULL); - else - rev = a; - } - else if (!strcmp(a, "-t")) - action = SHOW_TYPE; - else if (!strcmp(a, "-s")) - action = SHOW_SIZE; - else if (!strcmp(a, "-e")) - action = SHOW_NONE; - else if (!strcmp(a, "-p")) - action = SHOW_PRETTY; - else if (!strcmp(a, "-q")) - verbose = 0; - else if (!strcmp(a, "-v")) - verbose = 1; - else if (!strcmp(a, "--help") || !strcmp(a, "-h")) - usage(NULL, NULL); - else if (!check_str_param(a, "--git-dir=", &dir)) - usage("Unknown option", a); - } - - if (!action || !rev) - usage(NULL, NULL); + parse_opts(&o, argc, argv); - check(git_repository_open_ext(&g_repo, dir, 0, NULL), - "Could not open repository"); + check_lg2(git_repository_open_ext(&repo, o.dir, 0, NULL), + "Could not open repository", NULL); + check_lg2(git_revparse_single(&obj, repo, o.rev), + "Could not resolve", o.rev); - if (git_revparse_single(&obj, g_repo, rev) < 0) { - fprintf(stderr, "Could not resolve '%s'\n", rev); - exit(1); - } - if (verbose) { + if (o.verbose) { char oidstr[GIT_OID_HEXSZ + 1]; git_oid_tostr(oidstr, sizeof(oidstr), git_object_id(obj)); @@ -177,7 +131,7 @@ int main(int argc, char *argv[]) git_object_type2string(git_object_type(obj)), oidstr); } - switch (action) { + switch (o.action) { case SHOW_TYPE: printf("%s\n", git_object_type2string(git_object_type(obj))); break; @@ -185,9 +139,9 @@ int main(int argc, char *argv[]) git_odb *odb; git_odb_object *odbobj; - check(git_repository_odb(&odb, g_repo), "Could not open ODB"); - check(git_odb_read(&odbobj, odb, git_object_id(obj)), - "Could not find obj"); + check_lg2(git_repository_odb(&odb, repo), "Could not open ODB", NULL); + check_lg2(git_odb_read(&odbobj, odb, git_object_id(obj)), + "Could not find obj", NULL); printf("%ld\n", (long)git_odb_object_size(odbobj)); @@ -221,9 +175,57 @@ int main(int argc, char *argv[]) } git_object_free(obj); - git_repository_free(g_repo); + git_repository_free(repo); git_threads_shutdown(); return 0; } + +static void usage(const char *message, const char *arg) +{ + if (message && arg) + fprintf(stderr, "%s: %s\n", message, arg); + else if (message) + fprintf(stderr, "%s\n", message); + fprintf(stderr, + "usage: cat-file (-t | -s | -e | -p) [-v] [-q] " + "[-h|--help] [--git-dir=] \n"); + exit(1); +} + +static void parse_opts(struct opts *o, int argc, char *argv[]) +{ + struct args_info args = ARGS_INFO_INIT; + + for (args.pos = 1; args.pos < argc; ++args.pos) { + char *a = argv[args.pos]; + + if (a[0] != '-') { + if (o->rev != NULL) + usage("Only one rev should be provided", NULL); + else + o->rev = a; + } + else if (!strcmp(a, "-t")) + o->action = SHOW_TYPE; + else if (!strcmp(a, "-s")) + o->action = SHOW_SIZE; + else if (!strcmp(a, "-e")) + o->action = SHOW_NONE; + else if (!strcmp(a, "-p")) + o->action = SHOW_PRETTY; + else if (!strcmp(a, "-q")) + o->verbose = 0; + else if (!strcmp(a, "-v")) + o->verbose = 1; + else if (!strcmp(a, "--help") || !strcmp(a, "-h")) + usage(NULL, NULL); + else if (!match_str_arg(&o->dir, &args, "--git-dir")) + usage("Unknown option", a); + } + + if (!o->action || !o->rev) + usage(NULL, NULL); + +} -- cgit v1.2.1 From 2f8c481cc08ee00fa9c298f80eae0616e99faef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 8 Oct 2013 16:22:21 +0200 Subject: protocol: basic support for multi_ack_detailed This tells the server that we speak it, but we don't make use of its extra information to determine if there's a better place to stop negotiating. In a somewhat-related change, reorder the capabilities so we ask for them in the same order as git does. Also take this opportunity to factor out a fairly-indented portion of the negotiation logic. --- src/transports/smart.h | 4 +++- src/transports/smart_pkt.c | 30 +++++++++++++---------- src/transports/smart_protocol.c | 53 ++++++++++++++++++++++++++++------------- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/src/transports/smart.h b/src/transports/smart.h index 7fda27d4e..5232e54de 100644 --- a/src/transports/smart.h +++ b/src/transports/smart.h @@ -16,6 +16,7 @@ #define GIT_CAP_OFS_DELTA "ofs-delta" #define GIT_CAP_MULTI_ACK "multi_ack" +#define GIT_CAP_MULTI_ACK_DETAILED "multi_ack_detailed" #define GIT_CAP_SIDE_BAND "side-band" #define GIT_CAP_SIDE_BAND_64K "side-band-64k" #define GIT_CAP_INCLUDE_TAG "include-tag" @@ -40,7 +41,7 @@ enum git_pkt_type { GIT_PKT_UNPACK, }; -/* Used for multi-ack */ +/* Used for multi_ack and mutli_ack_detailed */ enum git_ack_status { GIT_ACK_NONE, GIT_ACK_CONTINUE, @@ -113,6 +114,7 @@ typedef struct transport_smart_caps { int common:1, ofs_delta:1, multi_ack: 1, + multi_ack_detailed: 1, side_band:1, side_band_64k:1, include_tag:1, diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c index a1f623c78..2bb09c750 100644 --- a/src/transports/smart_pkt.c +++ b/src/transports/smart_pkt.c @@ -39,7 +39,7 @@ static int flush_pkt(git_pkt **out) return 0; } -/* the rest of the line will be useful for multi_ack */ +/* the rest of the line will be useful for multi_ack and multi_ack_detailed */ static int ack_pkt(git_pkt **out, const char *line, size_t len) { git_pkt_ack *pkt; @@ -62,6 +62,10 @@ static int ack_pkt(git_pkt **out, const char *line, size_t len) if (len >= 7) { if (!git__prefixcmp(line + 1, "continue")) pkt->status = GIT_ACK_CONTINUE; + if (!git__prefixcmp(line + 1, "common")) + pkt->status = GIT_ACK_COMMON; + if (!git__prefixcmp(line + 1, "ready")) + pkt->status = GIT_ACK_READY; } *out = (git_pkt *) pkt; @@ -456,25 +460,27 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca char oid[GIT_OID_HEXSZ +1] = {0}; unsigned int len; - /* Prefer side-band-64k if the server supports both */ - if (caps->side_band) { - if (caps->side_band_64k) - git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND_64K); - else - git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND); - } - if (caps->ofs_delta) - git_buf_puts(&str, GIT_CAP_OFS_DELTA " "); - - if (caps->multi_ack) + /* Prefer multi_ack_detailed */ + if (caps->multi_ack_detailed) + git_buf_puts(&str, GIT_CAP_MULTI_ACK_DETAILED " "); + else if (caps->multi_ack) git_buf_puts(&str, GIT_CAP_MULTI_ACK " "); + /* Prefer side-band-64k if the server supports both */ + if (caps->side_band_64k) + git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND_64K); + else if (caps->side_band) + git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND); + if (caps->include_tag) git_buf_puts(&str, GIT_CAP_INCLUDE_TAG " "); if (caps->thin_pack) git_buf_puts(&str, GIT_CAP_THIN_PACK " "); + if (caps->ofs_delta) + git_buf_puts(&str, GIT_CAP_OFS_DELTA " "); + if (git_buf_oom(&str)) return -1; diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index af6e35fa1..a12921269 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -97,6 +97,13 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps) continue; } + /* Keep multi_ack_detailed before multi_ack */ + if (!git__prefixcmp(ptr, GIT_CAP_MULTI_ACK_DETAILED)) { + caps->common = caps->multi_ack_detailed = 1; + ptr += strlen(GIT_CAP_MULTI_ACK_DETAILED); + continue; + } + if (!git__prefixcmp(ptr, GIT_CAP_MULTI_ACK)) { caps->common = caps->multi_ack = 1; ptr += strlen(GIT_CAP_MULTI_ACK); @@ -236,6 +243,32 @@ on_error: return -1; } +static int wait_while_ack(gitno_buffer *buf) +{ + int error; + git_pkt_ack *pkt = NULL; + + while (1) { + git__free(pkt); + + if ((error = recv_pkt((git_pkt **)&pkt, buf)) < 0) + return error; + + if (pkt->type == GIT_PKT_NAK) + break; + + if (pkt->type == GIT_PKT_ACK && + (pkt->status != GIT_ACK_CONTINUE || + pkt->status != GIT_ACK_COMMON)) { + git__free(pkt); + break; + } + } + + git__free(pkt); + return 0; +} + int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_remote_head * const *refs, size_t count) { transport_smart *t = (transport_smart *)transport; @@ -287,7 +320,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c goto on_error; git_buf_clear(&data); - if (t->caps.multi_ack) { + if (t->caps.multi_ack || t->caps.multi_ack_detailed) { if ((error = store_common(t)) < 0) goto on_error; } else { @@ -365,7 +398,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c git_revwalk_free(walk); /* Now let's eat up whatever the server gives us */ - if (!t->caps.multi_ack) { + if (!t->caps.multi_ack && !t->caps.multi_ack_detailed) { pkt_type = recv_pkt(NULL, buf); if (pkt_type < 0) { @@ -375,22 +408,10 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c return -1; } } else { - git_pkt_ack *pkt; - do { - if ((error = recv_pkt((git_pkt **)&pkt, buf)) < 0) - return error; - - if (pkt->type == GIT_PKT_NAK || - (pkt->type == GIT_PKT_ACK && pkt->status != GIT_ACK_CONTINUE)) { - git__free(pkt); - break; - } - - git__free(pkt); - } while (1); + error = wait_while_ack(buf); } - return 0; + return error; on_error: git_revwalk_free(walk); -- cgit v1.2.1 From 1d37da3392276c16d49a3680e9bd6c22f2c3abd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 30 Oct 2013 16:25:49 +0100 Subject: merge: any non-zero return from the user is an error This fixes #1703. --- src/merge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/merge.c b/src/merge.c index b07e8c52f..a22801e48 100644 --- a/src/merge.c +++ b/src/merge.c @@ -285,7 +285,7 @@ int git_repository_mergehead_foreach(git_repository *repo, if ((error = git_oid_fromstr(&oid, line)) < 0) goto cleanup; - if (cb(&oid, payload) < 0) { + if (cb(&oid, payload) != 0) { error = GIT_EUSER; goto cleanup; } -- cgit v1.2.1 From 784b3abbd52d786a56151ae1c8124fc8ffa432e3 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 30 Oct 2013 12:34:03 -0700 Subject: rev-list.c example: use common utils, reorganize --- examples/rev-list.c | 62 ++++++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/examples/rev-list.c b/examples/rev-list.c index 1fb7ebf9f..9330c644c 100644 --- a/examples/rev-list.c +++ b/examples/rev-list.c @@ -1,17 +1,35 @@ -#include -#include +/* + * 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 +#include "common.h" -static void check_error(int error_code, const char *action) +static int revwalk_parseopts(git_repository *repo, git_revwalk *walk, int nopts, char **opts); + +int main (int argc, char **argv) { - if (!error_code) - return; + git_repository *repo; + git_revwalk *walk; + git_oid oid; + char buf[41]; + + git_threads_init(); - const git_error *error = giterr_last(); - fprintf(stderr, "Error %d %s: %s\n", -error_code, action, - (error && error->message) ? error->message : "???"); - exit(1); + check_lg2(git_repository_open_ext(&repo, ".", 0, NULL), "opening repository", NULL); + check_lg2(git_revwalk_new(&walk, repo), "allocating revwalk", NULL); + check_lg2(revwalk_parseopts(repo, walk, argc-1, argv+1), "parsing options", NULL); + + while (!git_revwalk_next(&oid, walk)) { + git_oid_fmt(buf, &oid); + buf[40] = '\0'; + printf("%s\n", buf); + } + + git_threads_shutdown(); + return 0; } static int push_commit(git_revwalk *walk, const git_oid *oid, int hide) @@ -93,27 +111,3 @@ static int revwalk_parseopts(git_repository *repo, git_revwalk *walk, int nopts, return 0; } -int main (int argc, char **argv) -{ - int error; - git_repository *repo; - git_revwalk *walk; - git_oid oid; - char buf[41]; - - error = git_repository_open_ext(&repo, ".", 0, NULL); - check_error(error, "opening repository"); - - error = git_revwalk_new(&walk, repo); - check_error(error, "allocating revwalk"); - error = revwalk_parseopts(repo, walk, argc-1, argv+1); - check_error(error, "parsing options"); - - while (!git_revwalk_next(&oid, walk)) { - git_oid_fmt(buf, &oid); - buf[40] = '\0'; - printf("%s\n", buf); - } - - return 0; -} -- cgit v1.2.1 From b9d02460f14151909b39fc963d119b373834f6d1 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 30 Oct 2013 13:07:58 -0700 Subject: Reorganize rev-parse example --- examples/rev-parse.c | 109 ++++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/examples/rev-parse.c b/examples/rev-parse.c index cdbb61e46..21f87c881 100644 --- a/examples/rev-parse.c +++ b/examples/rev-parse.c @@ -1,17 +1,37 @@ -#include -#include -#include -#include +/* + * 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. + */ -static void check(int error, const char *message, const char *arg) +#include "common.h" + + +/* Forward declarations for helpers */ +struct parse_state { + git_repository *repo; + const char *repodir; + const char *spec; + int not; +}; +static void parse_opts(struct parse_state *ps, int argc, char *argv[]); +static int parse_revision(struct parse_state *ps); + + +int main(int argc, char *argv[]) { - if (!error) - return; - if (arg) - fprintf(stderr, "%s %s (%d)\n", message, arg, error); - else - fprintf(stderr, "%s(%d)\n", message, error); - exit(1); + struct parse_state ps = {0}; + + git_threads_init(); + parse_opts(&ps, argc, argv); + + check_lg2(parse_revision(&ps), "Parsing", NULL); + + git_repository_free(ps.repo); + git_threads_shutdown(); + + return 0; } static void usage(const char *message, const char *arg) @@ -24,13 +44,25 @@ static void usage(const char *message, const char *arg) exit(1); } -struct parse_state { - git_repository *repo; - const char *repodir; - int not; -}; +static void parse_opts(struct parse_state *ps, int argc, char *argv[]) +{ + struct args_info args = ARGS_INFO_INIT; -static int parse_revision(struct parse_state *ps, const char *revstr) + for (args.pos=1; args.pos < argc; ++args.pos) { + const char *a = argv[args.pos]; + + if (a[0] != '-') { + if (ps->spec) + usage("Too many specs", a); + ps->spec = a; + } else if (!strcmp(a, "--not")) + ps->not = !ps->not; + else if (!match_str_arg(&ps->repodir, &args, "--git-dir")) + usage("Cannot handle argument", a); + } +} + +static int parse_revision(struct parse_state *ps) { git_revspec rs; char str[GIT_OID_HEXSZ + 1]; @@ -38,11 +70,11 @@ static int parse_revision(struct parse_state *ps, const char *revstr) if (!ps->repo) { if (!ps->repodir) ps->repodir = "."; - check(git_repository_open_ext(&ps->repo, ps->repodir, 0, NULL), + check_lg2(git_repository_open_ext(&ps->repo, ps->repodir, 0, NULL), "Could not open repository from", ps->repodir); } - check(git_revparse(&rs, ps->repo, revstr), "Could not parse", revstr); + check_lg2(git_revparse(&rs, ps->repo, ps->spec), "Could not parse", ps->spec); if ((rs.flags & GIT_REVPARSE_SINGLE) != 0) { git_oid_tostr(str, sizeof(str), git_object_id(rs.from)); @@ -56,9 +88,9 @@ static int parse_revision(struct parse_state *ps, const char *revstr) if ((rs.flags & GIT_REVPARSE_MERGE_BASE) != 0) { git_oid base; - check(git_merge_base(&base, ps->repo, - git_object_id(rs.from), git_object_id(rs.to)), - "Could not find merge base", revstr); + check_lg2(git_merge_base(&base, ps->repo, + git_object_id(rs.from), git_object_id(rs.to)), + "Could not find merge base", ps->spec); git_oid_tostr(str, sizeof(str), &base); printf("%s\n", str); @@ -69,38 +101,9 @@ static int parse_revision(struct parse_state *ps, const char *revstr) git_object_free(rs.from); } else { - check(0, "Invalid results from git_revparse", revstr); + fatal("Invalid results from git_revparse", ps->spec); } return 0; } -int main(int argc, char *argv[]) -{ - int i; - char *a; - struct parse_state ps; - - git_threads_init(); - - memset(&ps, 0, sizeof(ps)); - - for (i = 1; i < argc; ++i) { - a = argv[i]; - - if (a[0] != '-') { - if (parse_revision(&ps, a) != 0) - break; - } else if (!strcmp(a, "--not")) - ps.not = !ps.not; - else if (!strncmp(a, "--git-dir=", strlen("--git-dir="))) - ps.repodir = a + strlen("--git-dir="); - else - usage("Cannot handle argument", a); - } - - git_repository_free(ps.repo); - git_threads_shutdown(); - - return 0; -} -- cgit v1.2.1 From dbdb22b330d0148e89393baee3ddee25111a7671 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 30 Oct 2013 13:20:08 -0700 Subject: Clean up showindex sample --- examples/showindex.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/examples/showindex.c b/examples/showindex.c index 93718c89b..bf852384c 100644 --- a/examples/showindex.c +++ b/examples/showindex.c @@ -1,10 +1,14 @@ -#include -#include -#include +/* + * 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 "common.h" int main (int argc, char** argv) { - git_repository *repo = NULL; git_index *index; unsigned int i, ecount; char *dir = "."; @@ -14,28 +18,19 @@ int main (int argc, char** argv) git_threads_init(); + if (argc > 2) + fatal("usage: showindex []", NULL); if (argc > 1) dir = argv[1]; - if (!dir || argc > 2) { - fprintf(stderr, "usage: showindex []\n"); - return 1; - } dirlen = strlen(dir); if (dirlen > 5 && strcmp(dir + dirlen - 5, "index") == 0) { - if (git_index_open(&index, dir) < 0) { - fprintf(stderr, "could not open index: %s\n", dir); - return 1; - } + check_lg2(git_index_open(&index, dir), "could not open index", dir); } else { - if (git_repository_open_ext(&repo, dir, 0, NULL) < 0) { - fprintf(stderr, "could not open repository: %s\n", dir); - return 1; - } - if (git_repository_index(&index, repo) < 0) { - fprintf(stderr, "could not open repository index\n"); - return 1; - } + git_repository *repo; + check_lg2(git_repository_open_ext(&repo, dir, 0, NULL), "could not open repository", dir); + check_lg2(git_repository_index(&index, repo), "could not open repository index", NULL); + git_repository_free(repo); } git_index_read(index); @@ -62,10 +57,7 @@ int main (int argc, char** argv) } git_index_free(index); - git_repository_free(repo); - git_threads_shutdown(); return 0; } - -- cgit v1.2.1 From 29b77446b7237204ddd7fee36c0ad3b4c9513715 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 30 Oct 2013 15:38:52 -0700 Subject: Initialize variables --- src/transports/git.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/transports/git.c b/src/transports/git.c index 3a0b86345..79a9e7dd4 100644 --- a/src/transports/git.c +++ b/src/transports/git.c @@ -179,7 +179,7 @@ static int _git_uploadpack_ls( const char *url, git_smart_subtransport_stream **stream) { - char *host, *port, *user=NULL, *pass=NULL; + char *host=NULL, *port=NULL, *user=NULL, *pass=NULL; git_stream *s; *stream = NULL; @@ -235,7 +235,7 @@ static int _git_receivepack_ls( const char *url, git_smart_subtransport_stream **stream) { - char *host, *port, *user=NULL, *pass=NULL; + char *host=NULL, *port=NULL, *user=NULL, *pass=NULL; git_stream *s; *stream = NULL; -- cgit v1.2.1 From ff0ef88c5bb570ea2553ba6ea99236a68d39f950 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 30 Oct 2013 18:54:39 -0700 Subject: Test more kinds of bad url --- tests-clar/clone/nonetwork.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 071e3d09f..9eb4bf9db 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -46,7 +46,7 @@ void test_clone_nonetwork__cleanup(void) cl_fixture_cleanup("./foo"); } -void test_clone_nonetwork__bad_url(void) +void test_clone_nonetwork__bad_urls(void) { /* Clone should clean up the mess if the URL isn't a git repository */ cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); @@ -54,6 +54,15 @@ void test_clone_nonetwork__bad_url(void) g_options.bare = true; cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); cl_assert(!git_path_exists("./foo")); + + cl_git_fail(git_clone(&g_repo, "git://example.com:asdf", "./foo", &g_options)); + cl_assert(!git_path_exists("./foo")); + cl_git_fail(git_clone(&g_repo, "git://example.com:asdf/foo", "./foo", &g_options)); + cl_assert(!git_path_exists("./foo")); + cl_git_fail(git_clone(&g_repo, "https://example.com:asdf", "./foo", &g_options)); + cl_assert(!git_path_exists("./foo")); + cl_git_fail(git_clone(&g_repo, "https://example.com:asdf/foo", "./foo", &g_options)); + cl_assert(!git_path_exists("./foo")); } void test_clone_nonetwork__do_not_clean_existing_directory(void) -- cgit v1.2.1 From 864e72719c9658336aa2a769e4592e8efeb8b4ef Mon Sep 17 00:00:00 2001 From: Linquize Date: Thu, 31 Oct 2013 20:58:00 +0800 Subject: Use gmtime() instead of gmtime_t() The latter is not available on Windows --- examples/log.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/log.c b/examples/log.c index 4c2df07c9..81b056cc5 100644 --- a/examples/log.c +++ b/examples/log.c @@ -125,7 +125,7 @@ static int add_revision(struct log_state *s, const char *revstr) static void print_time(const git_time *intime, const char *prefix) { char sign, out[32]; - struct tm intm; + struct tm *intm; int offset, hours, minutes; time_t t; @@ -142,8 +142,8 @@ static void print_time(const git_time *intime, const char *prefix) t = (time_t)intime->time + (intime->offset * 60); - gmtime_r(&t, &intm); - strftime(out, sizeof(out), "%a %b %e %T %Y", &intm); + intm = gmtime(&t); + strftime(out, sizeof(out), "%a %b %e %T %Y", intm); printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes); } -- cgit v1.2.1 From 7be5104d241ce84537076ad92d2ac1604ea33b8a Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 31 Oct 2013 13:15:49 -0700 Subject: Add tests for badly-formed URLs --- tests-clar/clone/nonetwork.c | 8 ++------ tests-clar/network/urlparse.c | 7 +++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 9eb4bf9db..90e1e6439 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -56,13 +56,9 @@ void test_clone_nonetwork__bad_urls(void) cl_assert(!git_path_exists("./foo")); cl_git_fail(git_clone(&g_repo, "git://example.com:asdf", "./foo", &g_options)); - cl_assert(!git_path_exists("./foo")); - cl_git_fail(git_clone(&g_repo, "git://example.com:asdf/foo", "./foo", &g_options)); - cl_assert(!git_path_exists("./foo")); - cl_git_fail(git_clone(&g_repo, "https://example.com:asdf", "./foo", &g_options)); - cl_assert(!git_path_exists("./foo")); cl_git_fail(git_clone(&g_repo, "https://example.com:asdf/foo", "./foo", &g_options)); - cl_assert(!git_path_exists("./foo")); + cl_git_fail(git_clone(&g_repo, "git://github.com/git://github.com/foo/bar.git.git", + "./bar", &g_options)); } void test_clone_nonetwork__do_not_clean_existing_directory(void) diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c index 274d7e900..15e841b35 100644 --- a/tests-clar/network/urlparse.c +++ b/tests-clar/network/urlparse.c @@ -31,6 +31,13 @@ void test_network_urlparse__trivial(void) cl_assert_equal_p(pass, NULL); } +void test_network_urlparse__bad_url(void) +{ + cl_git_fail_with(gitno_extract_url_parts(&host, &port, &user, &pass, + "github.com/git://github.com/foo/bar.git.git", "443"), + GIT_EINVALIDSPEC); +} + void test_network_urlparse__user(void) { cl_git_pass(gitno_extract_url_parts(&host, &port, &user, &pass, -- cgit v1.2.1 From 151b321898a4b24bfa25f0c4a6bacf6565e0cdb4 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 31 Oct 2013 13:16:04 -0700 Subject: Prevent segfault with a badly-formed URL --- src/netops.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/netops.c b/src/netops.c index 7a61ef820..5f0db24ef 100644 --- a/src/netops.c +++ b/src/netops.c @@ -679,9 +679,10 @@ int gitno_extract_url_parts( slash = strchr(url, '/'); at = strchr(url, '@'); - if (slash == NULL) { - giterr_set(GITERR_NET, "Malformed URL: missing /"); - return -1; + if (!slash || + (colon && slash < colon)) { + giterr_set(GITERR_NET, "Malformed URL"); + return GIT_EINVALIDSPEC; } start = url; -- cgit v1.2.1 From 887df99f17c44b0726e0034885ea922b99254933 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 31 Oct 2013 13:29:16 -0700 Subject: Test another bad URL --- tests-clar/clone/nonetwork.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 90e1e6439..a286e2a8f 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -58,7 +58,9 @@ void test_clone_nonetwork__bad_urls(void) cl_git_fail(git_clone(&g_repo, "git://example.com:asdf", "./foo", &g_options)); cl_git_fail(git_clone(&g_repo, "https://example.com:asdf/foo", "./foo", &g_options)); cl_git_fail(git_clone(&g_repo, "git://github.com/git://github.com/foo/bar.git.git", - "./bar", &g_options)); + "./foo", &g_options)); + cl_git_fail(git_clone(&g_repo, "arrbee:my/bad:password@github.com:1111/strange:words.git", + "./foo", &g_options)); } void test_clone_nonetwork__do_not_clean_existing_directory(void) -- cgit v1.2.1 From 048f837b2fd5cd12ed7e3ca497f11460ab3114a9 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 31 Oct 2013 13:30:22 -0700 Subject: Prevent another segfault from bad URL --- src/netops.c | 2 +- src/transports/ssh.c | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/netops.c b/src/netops.c index 5f0db24ef..7e13f12e7 100644 --- a/src/netops.c +++ b/src/netops.c @@ -680,7 +680,7 @@ int gitno_extract_url_parts( at = strchr(url, '@'); if (!slash || - (colon && slash < colon)) { + (colon && (slash < colon))) { giterr_set(GITERR_NET, "Malformed URL"); return GIT_EINVALIDSPEC; } diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 6ce673d5e..4e2834b49 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -213,10 +213,6 @@ static int git_ssh_extract_url_parts( colon = strchr(url, ':'); - if (colon == NULL) { - giterr_set(GITERR_NET, "Malformed URL: missing :"); - return -1; - } at = strchr(url, '@'); if (at) { @@ -228,6 +224,11 @@ static int git_ssh_extract_url_parts( *username = NULL; } + if (colon == NULL || (colon < start)) { + giterr_set(GITERR_NET, "Malformed URL"); + return -1; + } + *host = git__substrdup(start, colon - start); GITERR_CHECK_ALLOC(*host); @@ -316,7 +317,7 @@ static int _git_ssh_setup_conn( const char *cmd, git_smart_subtransport_stream **stream) { - char *host, *port=NULL, *user=NULL, *pass=NULL; + char *host=NULL, *port=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; ssh_stream *s; LIBSSH2_SESSION* session=NULL; -- cgit v1.2.1 From 85c6730ce86045da0465080b0347fde1fb0f08df Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 31 Oct 2013 14:35:32 -0700 Subject: Format comments for use with docco --- examples/diff.c | 33 ++++++++++++++++--------------- examples/init.c | 51 ++++++++++++++++++++++++++++-------------------- examples/log.c | 55 +++++++++++++++++++++++++++------------------------- examples/rev-parse.c | 3 +-- examples/status.c | 16 ++++++++------- 5 files changed, 86 insertions(+), 72 deletions(-) diff --git a/examples/diff.c b/examples/diff.c index d39979117..381325839 100644 --- a/examples/diff.c +++ b/examples/diff.c @@ -7,7 +7,7 @@ #include "common.h" -/* +/** * This example demonstrates the use of the libgit2 diff APIs to * create `git_diff` objects and display them, emulating a number of * core Git `diff` command line options. @@ -26,11 +26,7 @@ static const char *colors[] = { "\033[36m" /* cyan */ }; -/* this implements very rudimentary colorized output */ -static int color_printer( - const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*); - -/* the 'opts' struct captures all the various parsed command line options */ +/** The 'opts' struct captures all the various parsed command line options. */ struct opts { git_diff_options diffopts; git_diff_find_options findopts; @@ -43,6 +39,8 @@ struct opts { }; static void parse_opts(struct opts *o, int argc, char *argv[]); +static int color_printer( + const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*); int main(int argc, char *argv[]) { @@ -61,12 +59,14 @@ int main(int argc, char *argv[]) check_lg2(git_repository_open_ext(&repo, o.dir, 0, NULL), "Could not open repository", o.dir); - /* Possible argument patterns: - * - * --cached - * - * --cached - * nothing + /** + * Possible argument patterns: + * + * * + * * --cached + * * + * * --cached + * * nothing * * Currently ranged arguments like .. and ... * are not supported in this example @@ -100,14 +100,14 @@ int main(int argc, char *argv[]) git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts), "diff index to working directory", NULL); - /* apply rename and copy detection if requested */ + /** Apply rename and copy detection if requested. */ if ((o.findopts.flags & GIT_DIFF_FIND_ALL) != 0) check_lg2( git_diff_find_similar(diff, &o.findopts), "finding renames and copies", NULL); - /* generate simple output using libgit2 display helper */ + /** Generate simple output using libgit2 display helper. */ if (o.color >= 0) fputs(colors[0], stdout); @@ -119,7 +119,7 @@ int main(int argc, char *argv[]) if (o.color >= 0) fputs(colors[0], stdout); - /* cleanup before exiting */ + /** Cleanup before exiting. */ git_diff_free(diff); git_tree_free(t1); @@ -141,6 +141,7 @@ static void usage(const char *message, const char *arg) exit(1); } +/** This implements very rudimentary colorized output. */ static int color_printer( const git_diff_delta *delta, const git_diff_hunk *hunk, @@ -177,7 +178,7 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) { struct args_info args = ARGS_INFO_INIT; - /* parse arguments as copied from git-diff */ + /* Parse arguments as copied from git-diff. */ for (args.pos = 1; args.pos < argc; ++args.pos) { const char *a = argv[args.pos]; diff --git a/examples/init.c b/examples/init.c index 5bec17b9d..1c371252e 100644 --- a/examples/init.c +++ b/examples/init.c @@ -1,4 +1,13 @@ /* + * 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 "common.h" + +/** * This is a sample program that is similar to "git init". See the * documentation for that (try "git help init") to understand what this * program is emulating. @@ -8,16 +17,9 @@ * This also contains a special additional option that regular "git init" * does not support which is "--initial-commit" to make a first empty commit. * That is demonstrated in the "create_initial_commit" helper function. - * - * 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 "common.h" - -/* forward declarations of helpers */ +/** Forward declarations of helpers */ struct opts { int no_options; int quiet; @@ -41,17 +43,19 @@ int main(int argc, char *argv[]) parse_opts(&o, argc, argv); - /* Initialize repository */ + /* Initialize repository. */ if (o.no_options) { - /* No options were specified, so let's demonstrate the default + /** + * No options were specified, so let's demonstrate the default * simple case of git_repository_init() API usage... */ check_lg2(git_repository_init(&repo, o.dir, 0), "Could not initialize repository", NULL); } else { - /* Some command line options were specified, so we'll use the + /** + * Some command line options were specified, so we'll use the * extended init API to handle them */ git_repository_init_options initopts = GIT_REPOSITORY_INIT_OPTIONS_INIT; @@ -66,7 +70,8 @@ int main(int argc, char *argv[]) } if (o.gitdir) { - /* if you specified a separate git directory, then initialize + /** + * If you specified a separate git directory, then initialize * the repository at that path and use the second path as the * working directory of the repository (with a git-link file) */ @@ -81,7 +86,7 @@ int main(int argc, char *argv[]) "Could not initialize repository", NULL); } - /* Print a message to stdout like "git init" does */ + /** Print a message to stdout like "git init" does. */ if (!o.quiet) { if (o.bare || o.gitdir) @@ -92,7 +97,8 @@ int main(int argc, char *argv[]) printf("Initialized empty Git repository in %s\n", o.dir); } - /* As an extension to the basic "git init" command, this example + /** + * As an extension to the basic "git init" command, this example * gives the option to create an empty initial commit. This is * mostly to demonstrate what it takes to do that, but also some * people like to have that empty base commit in their repo. @@ -108,7 +114,8 @@ int main(int argc, char *argv[]) return 0; } -/* Unlike regular "git init", this example shows how to create an initial +/** + * Unlike regular "git init", this example shows how to create an initial * empty commit in the repository. This is the helper function that does * that. */ @@ -119,7 +126,7 @@ static void create_initial_commit(git_repository *repo) git_oid tree_id, commit_id; git_tree *tree; - /* First use the config to initialize a commit signature for the user */ + /** First use the config to initialize a commit signature for the user. */ if (git_signature_default(&sig, repo) < 0) fatal("Unable to create a commit signature.", @@ -130,7 +137,8 @@ static void create_initial_commit(git_repository *repo) if (git_repository_index(&index, repo) < 0) fatal("Could not open repository index", NULL); - /* Outside of this example, you could call git_index_add_bypath() + /** + * Outside of this example, you could call git_index_add_bypath() * here to put actual files into the index. For our purposes, we'll * leave it empty for now. */ @@ -143,7 +151,8 @@ static void create_initial_commit(git_repository *repo) if (git_tree_lookup(&tree, repo, &tree_id) < 0) fatal("Could not look up initial tree", NULL); - /* Ready to create the initial commit + /** + * Ready to create the initial commit. * * Normally creating a commit would involve looking up the current * HEAD commit and making that be the parent of the initial commit, @@ -155,7 +164,7 @@ static void create_initial_commit(git_repository *repo) NULL, "Initial commit", tree, 0) < 0) fatal("Could not create the initial commit", NULL); - /* Clean up so we don't leak memory */ + /** Clean up so we don't leak memory. */ git_tree_free(tree); git_signature_free(sig); @@ -171,7 +180,7 @@ static void usage(const char *error, const char *arg) exit(1); } -/* parse the tail of the --shared= argument */ +/** Parse the tail of the --shared= argument. */ static uint32_t parse_shared(const char *shared) { if (!strcmp(shared, "false") || !strcmp(shared, "umask")) @@ -204,7 +213,7 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) struct args_info args = ARGS_INFO_INIT; const char *sharedarg; - /* Process arguments */ + /** Process arguments. */ for (args.pos = 1; args.pos < argc; ++args.pos) { char *a = argv[args.pos]; diff --git a/examples/log.c b/examples/log.c index 270de7c5d..4a0487a42 100644 --- a/examples/log.c +++ b/examples/log.c @@ -7,23 +7,25 @@ #include "common.h" -/* +/** * This example demonstrates the libgit2 rev walker APIs to roughly * simulate the output of `git log` and a few of command line arguments. * `git log` has many many options and this only shows a few of them. * * This does not have: + * * - Robust error handling * - Colorized or paginated output formatting * - Most of the `git log` options * * This does have: + * * - Examples of translating command line arguments to equivalent libgit2 * revwalker configuration calls * - Simplified options to apply pathspec limits and to show basic diffs */ -/* log_state represents walker being configured while handling options */ +/** log_state represents walker being configured while handling options */ struct log_state { git_repository *repo; const char *repodir; @@ -33,12 +35,12 @@ struct log_state { int revisions; }; -/* utility functions that are called to configure the walker */ +/** utility functions that are called to configure the walker */ static void set_sorting(struct log_state *s, unsigned int sort_mode); static void push_rev(struct log_state *s, git_object *obj, int hide); static int add_revision(struct log_state *s, const char *revstr); -/* log_options holds other command line options that affect log output */ +/** log_options holds other command line options that affect log output */ struct log_options { int show_diff; int skip, limit; @@ -49,7 +51,7 @@ struct log_options { char *committer; }; -/* utility functions that parse options and help with log output */ +/** utility functions that parse options and help with log output */ static int parse_options( struct log_state *s, struct log_options *opt, int argc, char **argv); static void print_time(const git_time *intime, const char *prefix); @@ -69,7 +71,7 @@ int main(int argc, char *argv[]) git_threads_init(); - /* parse arguments and set up revwalker */ + /** Parse arguments and set up revwalker. */ last_arg = parse_options(&s, &opt, argc, argv); @@ -82,7 +84,7 @@ int main(int argc, char *argv[]) if (!s.revisions) add_revision(&s, NULL); - /* use the revwalker to traverse the history */ + /** Use the revwalker to traverse the history. */ printed = count = 0; @@ -163,12 +165,12 @@ int main(int argc, char *argv[]) return 0; } -/* push object (for hide or show) onto revwalker */ +/** Push object (for hide or show) onto revwalker. */ static void push_rev(struct log_state *s, git_object *obj, int hide) { hide = s->hide ^ hide; - /* create revwalker on demand if it doesn't already exist */ + /** Create revwalker on demand if it doesn't already exist. */ if (!s->walker) { check_lg2(git_revwalk_new(&s->walker, s->repo), "Could not create revision walker", NULL); @@ -188,13 +190,13 @@ static void push_rev(struct log_state *s, git_object *obj, int hide) git_object_free(obj); } -/* parse revision string and add revs to walker */ +/** Parse revision string and add revs to walker. */ static int add_revision(struct log_state *s, const char *revstr) { git_revspec revs; int hide = 0; - /* open repo on demand if it isn't already open */ + /** Open repo on demand if it isn't already open. */ if (!s->repo) { if (!s->repodir) s->repodir = "."; check_lg2(git_repository_open_ext(&s->repo, s->repodir, 0, NULL), @@ -238,17 +240,17 @@ static int add_revision(struct log_state *s, const char *revstr) return 0; } -/* update revwalker with sorting mode */ +/** Update revwalker with sorting mode. */ static void set_sorting(struct log_state *s, unsigned int sort_mode) { - /* open repo on demand if it isn't already open */ + /** Open repo on demand if it isn't already open. */ if (!s->repo) { if (!s->repodir) s->repodir = "."; check_lg2(git_repository_open_ext(&s->repo, s->repodir, 0, NULL), "Could not open repository", s->repodir); } - /* create revwalker on demand if it doesn't already exist */ + /** Create revwalker on demand if it doesn't already exist. */ if (!s->walker) check_lg2(git_revwalk_new(&s->walker, s->repo), "Could not create revision walker", NULL); @@ -261,7 +263,7 @@ static void set_sorting(struct log_state *s, unsigned int sort_mode) git_revwalk_sorting(s->walker, s->sorting); } -/* helper to format a git_time value like Git */ +/** Helper to format a git_time value like Git. */ static void print_time(const git_time *intime, const char *prefix) { char sign, out[32]; @@ -288,7 +290,7 @@ static void print_time(const git_time *intime, const char *prefix) printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes); } -/* helper to print a commit object */ +/** Helper to print a commit object. */ static void print_commit(git_commit *commit) { char buf[GIT_OID_HEXSZ + 1]; @@ -323,7 +325,7 @@ static void print_commit(git_commit *commit) printf("\n"); } -/* helper to find how many files in a commit changed from its nth parent */ +/** Helper to find how many files in a commit changed from its nth parent. */ static int match_with_parent(git_commit *commit, int i, git_diff_options *opts) { git_commit *parent; @@ -349,7 +351,7 @@ static int match_with_parent(git_commit *commit, int i, git_diff_options *opts) return ndeltas > 0; } -/* print a usage message for the program */ +/** Print a usage message for the program. */ static void usage(const char *message, const char *arg) { if (message && arg) @@ -360,7 +362,7 @@ static void usage(const char *message, const char *arg) exit(1); } -/* parse some log command line options */ +/** Parse some log command line options. */ static int parse_options( struct log_state *s, struct log_options *opt, int argc, char **argv) { @@ -379,7 +381,8 @@ static int parse_options( if (a[0] != '-') { if (!add_revision(s, a)) s->revisions++; - else /* try failed revision parse as filename */ + else + /** Try failed revision parse as filename. */ break; } else if (!strcmp(a, "--")) { ++args.pos; @@ -392,15 +395,15 @@ static int parse_options( else if (!strcmp(a, "--reverse")) set_sorting(s, GIT_SORT_REVERSE); else if (match_str_arg(&s->repodir, &args, "--git-dir")) - /* found git-dir */; + /** Found git-dir. */; else if (match_int_arg(&opt->skip, &args, "--skip", 0)) - /* found valid --skip */; + /** Found valid --skip. */; else if (match_int_arg(&opt->limit, &args, "--max-count", 0)) - /* found valid --max-count */; + /** Found valid --max-count. */; else if (a[1] >= '0' && a[1] <= '9') is_integer(&opt->limit, a + 1, 0); else if (match_int_arg(&opt->limit, &args, "-n", 0)) - /* found valid -n */; + /** Found valid -n. */; else if (!strcmp(a, "--merges")) opt->min_parents = 2; else if (!strcmp(a, "--no-merges")) @@ -410,9 +413,9 @@ static int parse_options( else if (!strcmp(a, "--no-max-parents")) opt->max_parents = -1; else if (match_int_arg(&opt->max_parents, &args, "--max-parents=", 1)) - /* found valid --max-parents */; + /** Found valid --max-parents. */; else if (match_int_arg(&opt->min_parents, &args, "--min-parents=", 0)) - /* found valid --min_parents */; + /** Found valid --min_parents. */; else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch")) opt->show_diff = 1; else diff --git a/examples/rev-parse.c b/examples/rev-parse.c index 21f87c881..64a02fe6e 100644 --- a/examples/rev-parse.c +++ b/examples/rev-parse.c @@ -7,8 +7,7 @@ #include "common.h" - -/* Forward declarations for helpers */ +/** Forward declarations for helpers. */ struct parse_state { git_repository *repo; const char *repodir; diff --git a/examples/status.c b/examples/status.c index f6816bcd3..459e6fafb 100644 --- a/examples/status.c +++ b/examples/status.c @@ -7,17 +7,19 @@ #include "common.h" -/* +/** * This example demonstrates the use of the libgit2 status APIs, * particularly the `git_status_list` object, to roughly simulate the * output of running `git status`. It serves as a simple example of * using those APIs to get basic status information. * * This does not have: + * * - Robust error handling * - Colorized or paginated output formatting * * This does have: + * * - Examples of translating command line arguments to the status * options settings to mimic `git status` results. * - A sample status formatter that matches the default "long" format @@ -64,7 +66,7 @@ int main(int argc, char *argv[]) parse_opts(&o, argc, argv); - /* + /** * Try to open the repository at the given path (or at the current * directory if none was given). */ @@ -75,7 +77,7 @@ int main(int argc, char *argv[]) fatal("Cannot report status on bare repository", git_repository_path(repo)); - /* + /** * Run status on the repository * * Because we want to simluate a full "git status" run and want to @@ -140,7 +142,7 @@ static void print_long(git_repository *repo, git_status_list *status) (void)repo; - /* print index changes */ + /** Print index changes. */ for (i = 0; i < maxi; ++i) { char *istatus = NULL; @@ -189,7 +191,7 @@ static void print_long(git_repository *repo, git_status_list *status) } header = 0; - /* print workdir changes to tracked files */ + /** Print workdir changes to tracked files. */ for (i = 0; i < maxi; ++i) { char *wstatus = NULL; @@ -234,7 +236,7 @@ static void print_long(git_repository *repo, git_status_list *status) } header = 0; - /* print untracked files */ + /** Print untracked files. */ header = 0; @@ -256,7 +258,7 @@ static void print_long(git_repository *repo, git_status_list *status) header = 0; - /* print ignored files */ + /** Print ignored files. */ for (i = 0; i < maxi; ++i) { s = git_status_byindex(status, i); -- cgit v1.2.1 From 76120863a74f29dbd51ad9c45dfba06728d04177 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 31 Oct 2013 14:48:41 -0700 Subject: Update examples/README.md --- examples/README.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/examples/README.md b/examples/README.md index f2b6d7d23..494d3291a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,11 +1,19 @@ libgit2 examples ================ -These examples are meant as thin, easy-to-read snippets for Docurium -(https://github.com/github/docurium) rather than full-blown -implementations of Git commands. They are not vetted as carefully -for bugs, error handling, or cross-platform compatibility as the -rest of the code in libgit2, so copy with some caution. +These examples are a mixture of basic emulation of core Git command line +functions and simple snippets demonstrating libgit2 API usage (for use +with Docurium). As a whole, they are not vetted carefully for bugs, error +handling, and cross-platform compatibility in the same manner as the rest +of the code in libgit2, so copy with caution. -For HTML versions, check "Examples" at http://libgit2.github.com/libgit2 +That being said, you are welcome to copy code from these examples as +desired when using libgit2. +For annotated HTML versions, see the "Examples" section of: + + http://libgit2.github.com/libgit2 + +such as: + + http://libgit2.github.com/libgit2/ex/HEAD/general.html -- cgit v1.2.1 From 3793fa9b181f3595c24a1cc517646f8e7a4a7175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodri=CC=81guez=20Troitin=CC=83o?= Date: Thu, 31 Oct 2013 01:08:50 +0100 Subject: Fix saving remotes with several fetch/push ref specs. At some moment git_config_delete_entry lost the ability to delete one entry of a multivar configuration. The moment you had more than one fetch or push ref spec for a remote you will not be able to save that remote anymore. The changes in network::remote::remotes::save show that problem. I needed to create a new git_config_delete_multivar because I was not able to remove one or several entries of a multivar config with the current API. Several tries modifying how git_config_set_multivar(..., NULL) behaved were not successful. git_config_delete_multivar is very similar to git_config_set_multivar, and delegates into config_delete_multivar of config_file. This function search for the cvar_t that will be deleted, storing them in a temporal array, and rebuilding the linked list. After calling config_write to delete the entries, the cvar_t stored in the temporal array are freed. There is a little fix in config_write, it avoids an infinite loop when using a regular expression (case for the multivars). This error was found by the test network::remote::remotes::tagopt. --- include/git2/config.h | 11 +++++ include/git2/sys/config.h | 1 + src/config.c | 13 ++++++ src/config_file.c | 90 ++++++++++++++++++++++++++++++++++++- src/remote.c | 6 ++- tests-clar/config/multivar.c | 65 +++++++++++++++++++++++++++ tests-clar/network/remote/remotes.c | 25 +++++++---- 7 files changed, 199 insertions(+), 12 deletions(-) diff --git a/include/git2/config.h b/include/git2/config.h index f14415148..95da4bc03 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -434,6 +434,17 @@ GIT_EXTERN(int) git_config_set_multivar(git_config *cfg, const char *name, const */ GIT_EXTERN(int) git_config_delete_entry(git_config *cfg, const char *name); +/** + * Deletes one or several entries from a multivar in the local config file. + * + * @param cfg where to look for the variables + * @param name the variable's name + * @param regexp a regular expression to indicate which values to delete + * + * @return 0 or an error code + */ +GIT_EXTERN(int) git_config_delete_multivar(git_config *cfg, const char *name, const char *regexp); + /** * Perform an operation on each config variable. * diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 7572ace51..419ad7ea7 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -61,6 +61,7 @@ struct git_config_backend { int (*set)(struct git_config_backend *, const char *key, const char *value); int (*set_multivar)(git_config_backend *cfg, const char *name, const char *regexp, const char *value); int (*del)(struct git_config_backend *, const char *key); + int (*del_multivar)(struct git_config_backend *, const char *key, const char *regexp); int (*iterator)(git_config_iterator **, struct git_config_backend *); int (*refresh)(struct git_config_backend *); void (*free)(struct git_config_backend *); diff --git a/src/config.c b/src/config.c index c98d6a52d..0d9471383 100644 --- a/src/config.c +++ b/src/config.c @@ -862,6 +862,19 @@ int git_config_set_multivar(git_config *cfg, const char *name, const char *regex return file->set_multivar(file, name, regexp, value); } +int git_config_delete_multivar(git_config *cfg, const char *name, const char *regexp) +{ + git_config_backend *file; + file_internal *internal; + + internal = git_vector_get(&cfg->files, 0); + if (!internal || !internal->file) + return config_error_nofiles(name); + file = internal->file; + + return file->del_multivar(file, name, regexp); +} + int git_config_next(git_config_entry **entry, git_config_iterator *iter) { return iter->next(entry, iter); diff --git a/src/config_file.c b/src/config_file.c index 8fb43b990..8c3d8121c 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -120,6 +120,18 @@ static void cvar_free(cvar_t *var) git__free(var); } +static int cvar_length(cvar_t *var) +{ + int length = 0; + + while (var) { + length += 1; + var = var->next; + } + + return length; +} + int git_config_file_normalize_section(char *start, char *end) { char *scan; @@ -531,6 +543,81 @@ static int config_delete(git_config_backend *cfg, const char *name) return result; } +static int config_delete_multivar(git_config_backend *cfg, const char *name, const char *regexp) +{ + cvar_t *var, *prev = NULL, *new_head = NULL; + cvar_t **to_delete; + int to_delete_idx; + diskfile_backend *b = (diskfile_backend *)cfg; + char *key; + regex_t preg; + int result; + khiter_t pos; + + if ((result = git_config__normalize_name(name, &key)) < 0) + return result; + + pos = git_strmap_lookup_index(b->values, key); + + if (!git_strmap_valid_index(b->values, pos)) { + giterr_set(GITERR_CONFIG, "Could not find key '%s' to delete", name); + git__free(key); + return GIT_ENOTFOUND; + } + + var = git_strmap_value_at(b->values, pos); + + result = regcomp(&preg, regexp, REG_EXTENDED); + if (result < 0) { + git__free(key); + giterr_set_regex(&preg, result); + regfree(&preg); + return -1; + } + + to_delete = git__calloc(cvar_length(var), sizeof(cvar_t *)); + GITERR_CHECK_ALLOC(to_delete); + to_delete_idx = 0; + + for (;;) { + cvar_t *var_next = var->next; + + if (regexec(&preg, var->entry->value, 0, NULL, 0) == 0) { + // If we are past the head, reattach previous node to next one, + // otherwise set the new head for the strmap. + if (prev != NULL) { + prev->next = var_next; + } else { + new_head = var_next; + } + + to_delete[to_delete_idx++] = var; + } else { + prev = var; + } + + if (var_next == NULL) + break; + + var = var_next; + } + + if (new_head != NULL) { + git_strmap_set_value_at(b->values, pos, new_head); + } else { + git_strmap_delete_at(b->values, pos); + } + + if (to_delete_idx > 0) + result = config_write(b, key, &preg, NULL); + + while (to_delete_idx-- > 0) + cvar_free(to_delete[to_delete_idx]); + + git__free(key); + return result; +} + int git_config_file__ondisk(git_config_backend **out, const char *path) { diskfile_backend *backend; @@ -548,6 +635,7 @@ int git_config_file__ondisk(git_config_backend **out, const char *path) backend->parent.set = config_set; backend->parent.set_multivar = config_set_multivar; backend->parent.del = config_delete; + backend->parent.del_multivar = config_delete_multivar; backend->parent.iterator = config_iterator_new; backend->parent.refresh = config_refresh; backend->parent.free = backend_free; @@ -1214,7 +1302,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p } /* multiline variable? we need to keep reading lines to match */ - if (preg != NULL) { + if (preg != NULL && section_matches) { data_start = post_start; continue; } diff --git a/src/remote.c b/src/remote.c index bdfa08642..e2b40347a 100644 --- a/src/remote.c +++ b/src/remote.c @@ -365,16 +365,18 @@ static int update_config_refspec(const git_remote *remote, git_config *config, i const char *dir; size_t i; int error = 0; + const char *cname; push = direction == GIT_DIRECTION_PUSH; dir = push ? "push" : "fetch"; if (git_buf_printf(&name, "remote.%s.%s", remote->name, dir) < 0) return -1; + cname = git_buf_cstr(&name); /* Clear out the existing config */ while (!error) - error = git_config_delete_entry(config, git_buf_cstr(&name)); + error = git_config_delete_multivar(config, cname, ".*"); if (error != GIT_ENOTFOUND) return error; @@ -386,7 +388,7 @@ static int update_config_refspec(const git_remote *remote, git_config *config, i continue; if ((error = git_config_set_multivar( - config, git_buf_cstr(&name), "", spec->string)) < 0) { + config, cname, "", spec->string)) < 0) { goto cleanup; } } diff --git a/tests-clar/config/multivar.c b/tests-clar/config/multivar.c index 0d552d65e..afdb1e5f4 100644 --- a/tests-clar/config/multivar.c +++ b/tests-clar/config/multivar.c @@ -221,3 +221,68 @@ void test_config_multivar__replace_multiple(void) git_config_free(cfg); } + +void test_config_multivar__delete(void) +{ + git_config *cfg; + int n; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 2); + + cl_git_pass(git_config_delete_multivar(cfg, _name, "github")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 1); + + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 1); + + git_config_free(cfg); +} + +void test_config_multivar__delete_multiple(void) +{ + git_config *cfg; + int n; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 2); + + cl_git_pass(git_config_delete_multivar(cfg, _name, "git")); + + n = 0; + cl_git_fail_with(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n), GIT_ENOTFOUND); + + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_fail_with(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n), GIT_ENOTFOUND); + + git_config_free(cfg); +} + +void test_config_multivar__delete_notfound(void) +{ + git_config *cfg; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + cl_git_fail_with(git_config_delete_multivar(cfg, "remote.ab.noturl", "git"), GIT_ENOTFOUND); + + git_config_free(cfg); +} diff --git a/tests-clar/network/remote/remotes.c b/tests-clar/network/remote/remotes.c index 6e0eeeb05..7c79b8318 100644 --- a/tests-clar/network/remote/remotes.c +++ b/tests-clar/network/remote/remotes.c @@ -150,8 +150,10 @@ void test_network_remote_remotes__add_pushspec(void) void test_network_remote_remotes__save(void) { git_strarray array; - const char *fetch_refspec = "refs/heads/*:refs/remotes/upstream/*"; - const char *push_refspec = "refs/heads/*:refs/heads/*"; + const char *fetch_refspec1 = "refs/heads/ns1/*:refs/remotes/upstream/ns1/*"; + const char *fetch_refspec2 = "refs/heads/ns2/*:refs/remotes/upstream/ns2/*"; + const char *push_refspec1 = "refs/heads/ns1/*:refs/heads/ns1/*"; + const char *push_refspec2 = "refs/heads/ns2/*:refs/heads/ns2/*"; git_remote_free(_remote); _remote = NULL; @@ -160,8 +162,10 @@ void test_network_remote_remotes__save(void) cl_git_pass(git_remote_create(&_remote, _repo, "upstream", "git://github.com/libgit2/libgit2")); git_remote_clear_refspecs(_remote); - cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec)); - cl_git_pass(git_remote_add_push(_remote, push_refspec)); + cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec1)); + cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec2)); + cl_git_pass(git_remote_add_push(_remote, push_refspec1)); + cl_git_pass(git_remote_add_push(_remote, push_refspec2)); cl_git_pass(git_remote_set_pushurl(_remote, "git://github.com/libgit2/libgit2_push")); cl_git_pass(git_remote_save(_remote)); git_remote_free(_remote); @@ -171,16 +175,19 @@ void test_network_remote_remotes__save(void) cl_git_pass(git_remote_load(&_remote, _repo, "upstream")); cl_git_pass(git_remote_get_fetch_refspecs(&array, _remote)); - cl_assert_equal_i(1, (int)array.count); - cl_assert_equal_s(fetch_refspec, array.strings[0]); + cl_assert_equal_i(2, (int)array.count); + cl_assert_equal_s(fetch_refspec1, array.strings[0]); + cl_assert_equal_s(fetch_refspec2, array.strings[1]); git_strarray_free(&array); cl_git_pass(git_remote_get_push_refspecs(&array, _remote)); - cl_assert_equal_i(1, (int)array.count); - cl_assert_equal_s(push_refspec, array.strings[0]); + cl_assert_equal_i(2, (int)array.count); + cl_assert_equal_s(push_refspec1, array.strings[0]); + cl_assert_equal_s(push_refspec2, array.strings[1]); + git_strarray_free(&array); + cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/libgit2_push"); - git_strarray_free(&array); /* remove the pushurl again and see if we can save that too */ cl_git_pass(git_remote_set_pushurl(_remote, NULL)); -- cgit v1.2.1 From a71331ebc40b445a58d73a1fe3fb2dc21665c09c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodri=CC=81guez=20Troitin=CC=83o?= Date: Thu, 31 Oct 2013 23:41:48 +0100 Subject: Fix memory leaks. --- src/config_file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config_file.c b/src/config_file.c index 8c3d8121c..5f36a3f8b 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -615,6 +615,8 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con cvar_free(to_delete[to_delete_idx]); git__free(key); + git__free(to_delete); + regfree(&preg); return result; } -- cgit v1.2.1 From 376454d03dbb0c78b1266a85b29ec8bf48930a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodri=CC=81guez=20Troitin=CC=83o?= Date: Thu, 31 Oct 2013 23:42:04 +0100 Subject: Set new multivar values using unmatcheable regexp. Seems that regexp in Mac OS X and Linux were behaving differently: while in OS X the empty string didn't match any value, in Linux it was matching all of them, so the the second fetch refspec was overwritting the first one, instead of creating a new one. Using an unmatcheable regular expression solves the problem (and seems to be portable). --- src/remote.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/remote.c b/src/remote.c index e2b40347a..3528b1c46 100644 --- a/src/remote.c +++ b/src/remote.c @@ -387,8 +387,11 @@ static int update_config_refspec(const git_remote *remote, git_config *config, i if (spec->push != push) continue; + // "$^" is a unmatcheable regexp: it will not match anything at all, so + // all values will be considered new and we will not replace any + // present value. if ((error = git_config_set_multivar( - config, cname, "", spec->string)) < 0) { + config, cname, "$^", spec->string)) < 0) { goto cleanup; } } -- cgit v1.2.1 From c44820c616fab29d86f7256840f7114f195c08ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 31 Oct 2013 23:42:50 +0100 Subject: A few formatting changes for rocco I'm not too happy about manually inserting < and > but those get output as html tags otherwise. --- examples/cat-file.c | 8 ++++++++ examples/diff.c | 11 ++++++----- examples/network/fetch.c | 11 +++++++++++ examples/network/ls-remote.c | 9 ++++++--- 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/examples/cat-file.c b/examples/cat-file.c index 1e5b5ea5d..2b54b53b9 100644 --- a/examples/cat-file.c +++ b/examples/cat-file.c @@ -31,12 +31,14 @@ static void print_signature(const char *header, const git_signature *sig) sign, hours, minutes); } +/** Printint out a blob is simple, get the contents and print */ static void show_blob(const git_blob *blob) { /* ? Does this need crlf filtering? */ fwrite(git_blob_rawcontent(blob), git_blob_rawsize(blob), 1, stdout); } +/** Show each entry with its type, id and attributes */ static void show_tree(const git_tree *tree) { size_t i, max_i = (int)git_tree_entrycount(tree); @@ -55,6 +57,9 @@ static void show_tree(const git_tree *tree) } } +/** + * Commits and tags have a few interesting fields in their header. + */ static void show_commit(const git_commit *commit) { unsigned int i, max_i; @@ -107,6 +112,7 @@ struct opts { static void parse_opts(struct opts *o, int argc, char *argv[]); +/** Entry point for this command */ int main(int argc, char *argv[]) { git_repository *repo; @@ -182,6 +188,7 @@ int main(int argc, char *argv[]) return 0; } +/** Print out usage information */ static void usage(const char *message, const char *arg) { if (message && arg) @@ -194,6 +201,7 @@ static void usage(const char *message, const char *arg) exit(1); } +/** Parse the command-line options taken from git */ static void parse_opts(struct opts *o, int argc, char *argv[]) { struct args_info args = ARGS_INFO_INIT; diff --git a/examples/diff.c b/examples/diff.c index 381325839..b1415648a 100644 --- a/examples/diff.c +++ b/examples/diff.c @@ -38,6 +38,7 @@ struct opts { const char *dir; }; +/** These functions are implemented at the end */ static void parse_opts(struct opts *o, int argc, char *argv[]); static int color_printer( const git_diff_delta*, const git_diff_hunk*, const git_diff_line*, void*); @@ -62,13 +63,13 @@ int main(int argc, char *argv[]) /** * Possible argument patterns: * - * * - * * --cached - * * + * * <sha1> <sha2> + * * <sha1> --cached + * * <sha1> * * --cached * * nothing * - * Currently ranged arguments like .. and ... + * Currently ranged arguments like <sha1>..<sha2> and <sha1>...<sha2> * are not supported in this example */ @@ -174,11 +175,11 @@ static int color_printer( return diff_output(delta, hunk, line, stdout); } +/** Parse arguments as copied from git-diff. */ static void parse_opts(struct opts *o, int argc, char *argv[]) { struct args_info args = ARGS_INFO_INIT; - /* Parse arguments as copied from git-diff. */ for (args.pos = 1; args.pos < argc; ++args.pos) { const char *a = argv[args.pos]; diff --git a/examples/network/fetch.c b/examples/network/fetch.c index 4167ef3ca..77327d78e 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -47,6 +47,11 @@ exit: return &data->ret; } +/** + * This function gets called for each remote-trackinb branch that gets + * updated. The message we output depends on whether it's a new one or + * an update. + */ static int update_cb(const char *refname, const git_oid *a, const git_oid *b, void *data) { char a_str[GIT_OID_HEXSZ+1], b_str[GIT_OID_HEXSZ+1]; @@ -66,6 +71,7 @@ static int update_cb(const char *refname, const git_oid *a, const git_oid *b, vo return 0; } +/** Entry point for this command */ int fetch(git_repository *repo, int argc, char **argv) { git_remote *remote = NULL; @@ -130,6 +136,11 @@ int fetch(git_repository *repo, int argc, char **argv) pthread_join(worker, NULL); #endif + /** + * If there are local objects (we got a thin pack), then tell + * the use how many objets we saved from having to cross the + * network. + */ if (stats->local_objects > 0) { printf("\rReceived %d/%d objects in %zu bytes (used %d local objects)\n", stats->indexed_objects, stats->total_objects, stats->received_bytes, stats->local_objects); diff --git a/examples/network/ls-remote.c b/examples/network/ls-remote.c index b65759ed3..18cd02367 100644 --- a/examples/network/ls-remote.c +++ b/examples/network/ls-remote.c @@ -4,6 +4,7 @@ #include #include "common.h" +/** Callback to show each item */ static int show_ref__cb(git_remote_head *head, void *payload) { char oid[GIT_OID_HEXSZ + 1] = {0}; @@ -28,6 +29,10 @@ static int use_remote(git_repository *repo, char *name) goto cleanup; } + /** + * Connect to the remote and call the printing function for + * each of the remote references. + */ callbacks.credentials = cred_acquire_cb; git_remote_set_callbacks(remote, &callbacks); @@ -42,9 +47,7 @@ cleanup: return error; } -// This gets called to do the work. The remote can be given either as -// the name of a configured remote or an URL. - +/** Entry point for this command */ int ls_remote(git_repository *repo, int argc, char **argv) { int error; -- cgit v1.2.1 From 4f62d55968d4a22a6ea03194aa34ab1b6ca8fdea Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 1 Nov 2013 05:39:21 -0700 Subject: Fix typos --- examples/cat-file.c | 2 +- examples/network/fetch.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/cat-file.c b/examples/cat-file.c index 2b54b53b9..5e547628a 100644 --- a/examples/cat-file.c +++ b/examples/cat-file.c @@ -31,7 +31,7 @@ static void print_signature(const char *header, const git_signature *sig) sign, hours, minutes); } -/** Printint out a blob is simple, get the contents and print */ +/** Printing out a blob is simple, get the contents and print */ static void show_blob(const git_blob *blob) { /* ? Does this need crlf filtering? */ diff --git a/examples/network/fetch.c b/examples/network/fetch.c index 77327d78e..ad01001d7 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -48,7 +48,7 @@ exit: } /** - * This function gets called for each remote-trackinb branch that gets + * This function gets called for each remote-tracking branch that gets * updated. The message we output depends on whether it's a new one or * an update. */ @@ -138,7 +138,7 @@ int fetch(git_repository *repo, int argc, char **argv) /** * If there are local objects (we got a thin pack), then tell - * the use how many objets we saved from having to cross the + * the user how many objects we saved from having to cross the * network. */ if (stats->local_objects > 0) { -- cgit v1.2.1 From b22593fb6444f4469445e1af2a786c8d13ee4828 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 1 Nov 2013 17:28:59 +0100 Subject: config_file: Style fixes --- src/config_file.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 5f36a3f8b..6abf60621 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -125,7 +125,7 @@ static int cvar_length(cvar_t *var) int length = 0; while (var) { - length += 1; + length++; var = var->next; } @@ -579,16 +579,16 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con GITERR_CHECK_ALLOC(to_delete); to_delete_idx = 0; - for (;;) { - cvar_t *var_next = var->next; + while (var != NULL) { + cvar_t *next = var->next; if (regexec(&preg, var->entry->value, 0, NULL, 0) == 0) { // If we are past the head, reattach previous node to next one, // otherwise set the new head for the strmap. if (prev != NULL) { - prev->next = var_next; + prev->next = next; } else { - new_head = var_next; + new_head = next; } to_delete[to_delete_idx++] = var; @@ -596,10 +596,7 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con prev = var; } - if (var_next == NULL) - break; - - var = var_next; + var = next; } if (new_head != NULL) { -- cgit v1.2.1 From 3343b5ffd37d25fa9f55c23c417cf761a7849e9f Mon Sep 17 00:00:00 2001 From: Linquize Date: Thu, 31 Oct 2013 22:59:42 +0800 Subject: Fix warning on win64 --- src/indexer.c | 5 +++-- src/pack-objects.c | 4 ++-- src/pack.c | 2 +- src/pack.h | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index 9f55c8b2c..64a9074a1 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -632,7 +632,8 @@ static int inject_object(git_indexer_stream *idx, git_oid *id) git_buf buf = GIT_BUF_INIT; git_off_t entry_start; const void *data; - size_t len, hdr_len; + size_t len; + int hdr_len; int error; entry = git__calloc(1, sizeof(*entry)); @@ -660,7 +661,7 @@ static int inject_object(git_indexer_stream *idx, git_oid *id) /* And then the compressed object */ git_filebuf_write(&idx->pack_file, buf.ptr, buf.size); idx->pack->mwf.size += buf.size; - entry->crc = htonl(crc32(entry->crc, (unsigned char *)buf.ptr, buf.size)); + entry->crc = htonl(crc32(entry->crc, (unsigned char *)buf.ptr, (uInt)buf.size)); git_buf_free(&buf); /* Write a fake trailer so the pack functions play ball */ diff --git a/src/pack-objects.c b/src/pack-objects.c index d2774ce6a..c5286f7d3 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -26,7 +26,7 @@ struct unpacked { git_pobject *object; void *data; struct git_delta_index *index; - unsigned int depth; + int depth; }; struct tree_walk_context { @@ -659,7 +659,7 @@ static int delta_cacheable(git_packbuilder *pb, unsigned long src_size, } static int try_delta(git_packbuilder *pb, struct unpacked *trg, - struct unpacked *src, unsigned int max_depth, + struct unpacked *src, int max_depth, unsigned long *mem_usage, int *ret) { git_pobject *trg_object = trg->object; diff --git a/src/pack.c b/src/pack.c index 5df0f50b9..51fbc4e9d 100644 --- a/src/pack.c +++ b/src/pack.c @@ -372,7 +372,7 @@ static unsigned char *pack_window_open( * - each byte afterwards: low seven bits are size continuation, * with the high bit being "size continues" */ -int git_packfile__object_header(unsigned char *hdr, unsigned long size, git_otype type) +int git_packfile__object_header(unsigned char *hdr, size_t size, git_otype type) { unsigned char *hdr_base; unsigned char c; diff --git a/src/pack.h b/src/pack.h index ddeefea1d..baad361f8 100644 --- a/src/pack.h +++ b/src/pack.h @@ -112,7 +112,7 @@ typedef struct git_packfile_stream { git_mwindow *mw; } git_packfile_stream; -int git_packfile__object_header(unsigned char *hdr, unsigned long size, git_otype type); +int git_packfile__object_header(unsigned char *hdr, size_t size, git_otype type); int git_packfile_unpack_header( size_t *size_p, -- cgit v1.2.1 From 51a3dfb5958e11acf3294e8f740c3ebd777c48a9 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 1 Nov 2013 16:31:02 +0100 Subject: pack: `__object_header` always returns unsigned values --- src/indexer.c | 3 +-- src/pack.c | 4 ++-- src/pack.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index 64a9074a1..3b4dffabe 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -632,8 +632,7 @@ static int inject_object(git_indexer_stream *idx, git_oid *id) git_buf buf = GIT_BUF_INIT; git_off_t entry_start; const void *data; - size_t len; - int hdr_len; + size_t len, hdr_len; int error; entry = git__calloc(1, sizeof(*entry)); diff --git a/src/pack.c b/src/pack.c index 51fbc4e9d..644b2d465 100644 --- a/src/pack.c +++ b/src/pack.c @@ -372,7 +372,7 @@ static unsigned char *pack_window_open( * - each byte afterwards: low seven bits are size continuation, * with the high bit being "size continues" */ -int git_packfile__object_header(unsigned char *hdr, size_t size, git_otype type) +size_t git_packfile__object_header(unsigned char *hdr, size_t size, git_otype type) { unsigned char *hdr_base; unsigned char c; @@ -392,7 +392,7 @@ int git_packfile__object_header(unsigned char *hdr, size_t size, git_otype type) } *hdr++ = c; - return (int)(hdr - hdr_base); + return (hdr - hdr_base); } diff --git a/src/pack.h b/src/pack.h index baad361f8..28146ab30 100644 --- a/src/pack.h +++ b/src/pack.h @@ -112,7 +112,7 @@ typedef struct git_packfile_stream { git_mwindow *mw; } git_packfile_stream; -int git_packfile__object_header(unsigned char *hdr, size_t size, git_otype type); +size_t git_packfile__object_header(unsigned char *hdr, size_t size, git_otype type); int git_packfile_unpack_header( size_t *size_p, -- cgit v1.2.1 From 73342386965db3ece91116005320c9b873af3bf2 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 1 Nov 2013 16:55:01 +0100 Subject: array: Wrap `array_alloc` as a single statement --- src/array.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/array.h b/src/array.h index d7272d78c..1d4e1c224 100644 --- a/src/array.h +++ b/src/array.h @@ -57,9 +57,9 @@ GIT_INLINE(void *) git_array_grow(void *_a, size_t item_size) } #define git_array_alloc(a) \ - ((a).size >= (a).asize) ? \ + (((a).size >= (a).asize) ? \ git_array_grow(&(a), sizeof(*(a).ptr)) : \ - ((a).ptr ? &(a).ptr[(a).size++] : NULL) + ((a).ptr ? &(a).ptr[(a).size++] : NULL)) #define git_array_last(a) ((a).size ? &(a).ptr[(a).size - 1] : NULL) -- cgit v1.2.1 From 95352b7058fe3166689e5af0b3b0a38e7c6f63a0 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 1 Nov 2013 16:55:20 +0100 Subject: checkout: Remove unused vector --- src/checkout.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/checkout.c b/src/checkout.c index 662803725..76edc6a72 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -1694,7 +1694,6 @@ done: static int checkout_create_conflicts(checkout_data *data) { - git_vector conflicts = GIT_VECTOR_INIT; checkout_conflictdata *conflict; size_t i; int error = 0; -- cgit v1.2.1 From 0bfa73234263de03e5f797c2f4c514def145433a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 1 Nov 2013 17:07:44 +0100 Subject: iconv: Do not fake an API when iconv is not available --- src/path.c | 30 ++++++++++++++++++++++++++++-- src/path.h | 10 ---------- src/refs.c | 7 +++++++ tests-clar/core/iconv.c | 14 +++++++++++--- tests-clar/repo/init.c | 2 +- 5 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/path.c b/src/path.c index d45751cd1..750dd3ef7 100644 --- a/src/path.c +++ b/src/path.c @@ -834,7 +834,12 @@ int git_path_direach( DIR *dir; path_dirent_data de_data; struct dirent *de, *de_buf = (struct dirent *)&de_data; + + (void)flags; + +#ifdef GIT_USE_ICONV git_path_iconv_t ic = GIT_PATH_ICONV_INIT; +#endif if (git_path_to_dir(path) < 0) return -1; @@ -846,8 +851,10 @@ int git_path_direach( return -1; } +#ifdef GIT_USE_ICONV if ((flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0) (void)git_path_iconv_init_precompose(&ic); +#endif while (p_readdir_r(dir, de_buf, &de) == 0 && de != NULL) { char *de_path = de->d_name; @@ -856,8 +863,12 @@ int git_path_direach( if (git_path_is_dot_or_dotdot(de_path)) continue; - if ((error = git_path_iconv(&ic, &de_path, &de_len)) < 0 || - (error = git_buf_put(path, de_path, de_len)) < 0) +#ifdef GIT_USE_ICONV + if ((error = git_path_iconv(&ic, &de_path, &de_len)) < 0) + break; +#endif + + if ((error = git_buf_put(path, de_path, de_len)) < 0) break; error = fn(arg, path); @@ -871,7 +882,10 @@ int git_path_direach( } closedir(dir); + +#ifdef GIT_USE_ICONV git_path_iconv_clear(&ic); +#endif return error; } @@ -888,7 +902,12 @@ int git_path_dirload( size_t path_len; path_dirent_data de_data; struct dirent *de, *de_buf = (struct dirent *)&de_data; + + (void)flags; + +#ifdef GIT_USE_ICONV git_path_iconv_t ic = GIT_PATH_ICONV_INIT; +#endif assert(path && contents); @@ -903,8 +922,10 @@ int git_path_dirload( return -1; } +#ifdef GIT_USE_ICONV if ((flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0) (void)git_path_iconv_init_precompose(&ic); +#endif path += prefix_len; path_len -= prefix_len; @@ -917,8 +938,10 @@ int git_path_dirload( if (git_path_is_dot_or_dotdot(de_path)) continue; +#ifdef GIT_USE_ICONV if ((error = git_path_iconv(&ic, &de_path, &de_len)) < 0) break; +#endif alloc_size = path_len + need_slash + de_len + 1 + alloc_extra; if ((entry_path = git__calloc(alloc_size, 1)) == NULL) { @@ -937,7 +960,10 @@ int git_path_dirload( } closedir(dir); + +#ifdef GIT_USE_ICONV git_path_iconv_clear(&ic); +#endif if (error != 0) giterr_set(GITERR_OS, "Failed to process directory entry in '%s'", path); diff --git a/src/path.h b/src/path.h index 17f4f7726..3daafd265 100644 --- a/src/path.h +++ b/src/path.h @@ -425,16 +425,6 @@ extern void git_path_iconv_clear(git_path_iconv_t *ic); */ extern int git_path_iconv(git_path_iconv_t *ic, char **in, size_t *inlen); -#else - -typedef struct { - int unused; -} git_path_iconv_t; -#define GIT_PATH_ICONV_INIT { 0 } -#define git_path_iconv_init_precompose(X) 0 -#define git_path_iconv_clear(X) (void)(X) -#define git_path_iconv(X,Y,Z) 0 - #endif /* GIT_USE_ICONV */ #endif diff --git a/src/refs.c b/src/refs.c index 269c5f54e..472a79890 100644 --- a/src/refs.c +++ b/src/refs.c @@ -737,7 +737,10 @@ int git_reference__normalize_name( int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC; unsigned int process_flags; bool normalize = (buf != NULL); + +#ifdef GIT_USE_ICONV git_path_iconv_t ic = GIT_PATH_ICONV_INIT; +#endif assert(name); @@ -750,6 +753,7 @@ int git_reference__normalize_name( if (normalize) git_buf_clear(buf); +#ifdef GIT_USE_ICONV if ((flags & GIT_REF_FORMAT__PRECOMPOSE_UNICODE) != 0) { size_t namelen = strlen(current); if ((error = git_path_iconv_init_precompose(&ic)) < 0 || @@ -757,6 +761,7 @@ int git_reference__normalize_name( goto cleanup; error = GIT_EINVALIDSPEC; } +#endif while (true) { segment_len = ensure_segment_validity(current); @@ -834,7 +839,9 @@ cleanup: if (error && normalize) git_buf_free(buf); +#ifdef GIT_USE_ICONV git_path_iconv_clear(&ic); +#endif return error; } diff --git a/tests-clar/core/iconv.c b/tests-clar/core/iconv.c index 73bc99a23..8aedab206 100644 --- a/tests-clar/core/iconv.c +++ b/tests-clar/core/iconv.c @@ -1,22 +1,29 @@ #include "clar_libgit2.h" #include "path.h" +#ifdef GIT_USE_ICONV static git_path_iconv_t ic; static char *nfc = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D"; static char *nfd = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D"; +#endif void test_core_iconv__initialize(void) { +#ifdef GIT_USE_ICONV cl_git_pass(git_path_iconv_init_precompose(&ic)); +#endif } void test_core_iconv__cleanup(void) { +#ifdef GIT_USE_ICONV git_path_iconv_clear(&ic); +#endif } void test_core_iconv__unchanged(void) { +#ifdef GIT_USE_ICONV char *data = "Ascii data", *original = data; size_t datalen = strlen(data); @@ -25,10 +32,12 @@ void test_core_iconv__unchanged(void) /* There are no high bits set, so this should leave data untouched */ cl_assert(data == original); +#endif } void test_core_iconv__decomposed_to_precomposed(void) { +#ifdef GIT_USE_ICONV char *data = nfd; size_t datalen = strlen(nfd); @@ -38,15 +47,13 @@ void test_core_iconv__decomposed_to_precomposed(void) /* The decomposed nfd string should be transformed to the nfc form * (on platforms where iconv is enabled, of course). */ -#ifdef GIT_USE_ICONV cl_assert_equal_s(nfc, data); -#else - cl_assert_equal_s(nfd, data); #endif } void test_core_iconv__precomposed_is_unmodified(void) { +#ifdef GIT_USE_ICONV char *data = nfc; size_t datalen = strlen(nfc); @@ -57,4 +64,5 @@ void test_core_iconv__precomposed_is_unmodified(void) * the high-bit set, the iconv transform should result in no change. */ cl_assert_equal_s(nfc, data); +#endif } diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index 617fdf879..aea383c64 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -232,6 +232,7 @@ void test_repo_init__detect_ignorecase(void) void test_repo_init__detect_precompose_unicode_required(void) { +#ifdef GIT_USE_ICONV char *composed = "ḱṷṓn", *decomposed = "ḱṷṓn"; struct stat st; bool found_with_nfd; @@ -240,7 +241,6 @@ void test_repo_init__detect_precompose_unicode_required(void) found_with_nfd = (p_stat(decomposed, &st) == 0); cl_must_pass(p_unlink(composed)); -#ifdef GIT_USE_ICONV assert_config_entry_on_init("core.precomposeunicode", found_with_nfd); #else assert_config_entry_on_init("core.precomposeunicode", GIT_ENOTFOUND); -- cgit v1.2.1 From d3ed2106c137c1117f70499544868db21d9ea715 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 1 Nov 2013 17:08:32 +0100 Subject: clar: Fix warnings in GCC/Linux --- tests-clar/checkout/conflict.c | 3 +++ tests-clar/pack/indexer.c | 2 -- tests-clar/threads/refdb.c | 6 ++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tests-clar/checkout/conflict.c b/tests-clar/checkout/conflict.c index d261f3860..66965a89b 100644 --- a/tests-clar/checkout/conflict.c +++ b/tests-clar/checkout/conflict.c @@ -1071,6 +1071,9 @@ static void collect_progress( { git_vector *paths = payload; + (void)completed_steps; + (void)total_steps; + if (path == NULL) return; diff --git a/tests-clar/pack/indexer.c b/tests-clar/pack/indexer.c index 17ec7b3f8..ccb88b945 100644 --- a/tests-clar/pack/indexer.c +++ b/tests-clar/pack/indexer.c @@ -100,7 +100,6 @@ void test_pack_indexer__fix_thin(void) unsigned char buffer[128]; int fd; ssize_t read; - git_off_t left; struct stat st; const char *name = "pack-11f0f69b334728fdd8bc86b80499f22f29d85b15.pack"; @@ -108,7 +107,6 @@ void test_pack_indexer__fix_thin(void) cl_assert(fd != -1); cl_git_pass(p_stat(name, &st)); - left = st.st_size; cl_git_pass(git_indexer_stream_new(&idx, ".", NULL, NULL, NULL)); read = p_read(fd, buffer, sizeof(buffer)); diff --git a/tests-clar/threads/refdb.c b/tests-clar/threads/refdb.c index f8d76cb9b..3c651e341 100644 --- a/tests-clar/threads/refdb.c +++ b/tests-clar/threads/refdb.c @@ -147,13 +147,16 @@ static void *delete_refs(void *arg) void test_threads_refdb__edit_while_iterate(void) { int r, t; - git_thread th[THREADS]; int id[THREADS]; git_oid head; git_reference *ref; char name[128]; git_refdb *refdb; +#ifdef GIT_THREADS + git_thread th[THREADS]; +#endif + g_repo = cl_git_sandbox_init("testrepo2"); cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); @@ -187,7 +190,6 @@ void test_threads_refdb__edit_while_iterate(void) #ifdef GIT_THREADS cl_git_pass(git_thread_create(&th[t], NULL, fn, &id[t])); #else - th[t] = t; fn(&id[t]); #endif } -- cgit v1.2.1 From 3940310e29363978ccdc1f3b557bc6f48ebae8f0 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 30 Oct 2013 13:56:42 -0700 Subject: Fix some of the glaring errors in GIT_DIFF_REVERSE These changes fix the basic problem with GIT_DIFF_REVERSE being broken for text diffs. The reversed diff entries were getting added to the git_diff correctly, but some of the metadata was kept incorrectly in a way that prevented the text diffs from being generated correctly. Once I fixed that, it became clear that it was not possible to merge reversed diffs correctly. This has a first pass at fixing that problem. We probably need more tests to make sure that is really fixed thoroughly. --- src/diff.c | 13 ++++++++++--- src/diff_tform.c | 38 ++++++++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/diff.c b/src/diff.c index 37bc737d6..b1f64e6a3 100644 --- a/src/diff.c +++ b/src/diff.c @@ -448,6 +448,13 @@ static int diff_list_apply_options( /* add other defaults here */ } + /* Reverse src info if diff is reversed */ + if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) { + git_iterator_type_t tmp_src = diff->old_src; + diff->old_src = diff->new_src; + diff->new_src = tmp_src; + } + /* if ignore_submodules not explicitly set, check diff config */ if (diff->opts.ignore_submodules <= 0) { const char *str; @@ -484,9 +491,9 @@ static int diff_list_apply_options( return -1; if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_REVERSE)) { - const char *swap = diff->opts.old_prefix; - diff->opts.old_prefix = diff->opts.new_prefix; - diff->opts.new_prefix = swap; + const char *tmp_prefix = diff->opts.old_prefix; + diff->opts.old_prefix = diff->opts.new_prefix; + diff->opts.new_prefix = tmp_prefix; } return 0; diff --git a/src/diff_tform.c b/src/diff_tform.c index 9461ca2c8..0aec754a4 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -46,7 +46,10 @@ fail: } static git_diff_delta *diff_delta__merge_like_cgit( - const git_diff_delta *a, const git_diff_delta *b, git_pool *pool) + uint16_t flags, + const git_diff_delta *a, + const git_diff_delta *b, + git_pool *pool) { git_diff_delta *dup; @@ -112,26 +115,28 @@ int git_diff_merge( if (!from->deltas.length) return 0; + if ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != + (from->opts.flags & GIT_DIFF_IGNORE_CASE) || + (onto->opts.flags & GIT_DIFF_REVERSE) != + (from->opts.flags & GIT_DIFF_REVERSE)) + { + giterr_set(GITERR_INVALID, + "Attempt to merge diffs created with conflicting options"); + return -1; + } + if (git_vector_init( &onto_new, onto->deltas.length, git_diff_delta__cmp) < 0 || git_pool_init(&onto_pool, 1, 0) < 0) return -1; - if ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0 || - (from->opts.flags & GIT_DIFF_IGNORE_CASE) != 0) - { - ignore_case = true; - - /* This function currently only supports merging diff lists that - * are sorted identically. */ - assert((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0 && - (from->opts.flags & GIT_DIFF_IGNORE_CASE) != 0); - } + ignore_case = ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0); for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) { git_diff_delta *o = GIT_VECTOR_GET(&onto->deltas, i); const git_diff_delta *f = GIT_VECTOR_GET(&from->deltas, j); - int cmp = !f ? -1 : !o ? 1 : STRCMP_CASESELECT(ignore_case, o->old_file.path, f->old_file.path); + int cmp = !f ? -1 : !o ? 1 : + STRCMP_CASESELECT(ignore_case, o->old_file.path, f->old_file.path); if (cmp < 0) { delta = diff_delta__dup(o, &onto_pool); @@ -140,7 +145,8 @@ int git_diff_merge( delta = diff_delta__dup(f, &onto_pool); j++; } else { - delta = diff_delta__merge_like_cgit(o, f, &onto_pool); + delta = diff_delta__merge_like_cgit( + onto->opts.flags, o, f, &onto_pool); i++; j++; } @@ -160,7 +166,11 @@ int git_diff_merge( if (!error) { git_vector_swap(&onto->deltas, &onto_new); git_pool_swap(&onto->pool, &onto_pool); - onto->new_src = from->new_src; + + if ((onto->opts.flags & GIT_DIFF_REVERSE) != 0) + onto->old_src = from->old_src; + else + onto->new_src = from->new_src; /* prefix strings also come from old pool, so recreate those.*/ onto->opts.old_prefix = -- cgit v1.2.1 From 4bf630b6baf342fa929a8f7e4e6643197b74216f Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Thu, 31 Oct 2013 14:36:52 -0700 Subject: Make diff and status perform soft index reload This changes `git_index_read` to have two modes - a hard index reload that always resets the index to match the on-disk data (which was the old behavior) and a soft index reload that uses the timestamp / file size information and only replaces the index data if the file on disk has been modified. This then updates the git_status code to do a soft reload unless the new GIT_STATUS_OPT_NO_REFRESH flag is passed in. This also changes the behavior of the git_diff functions that use the index so that when an index is not explicitly passed in (i.e. when the functions call git_repository_index for you), they will also do a soft reload for you. This intentionally breaks the file signature of git_index_read because there has been some confusion about the behavior previously and it seems like all existing uses of the API should probably be examined to select the desired behavior. --- examples/showindex.c | 2 +- include/git2/diff.h | 8 +++++ include/git2/index.h | 17 +++++++--- include/git2/status.h | 4 +++ src/checkout.c | 2 +- src/diff.c | 23 +++++++++++--- src/index.c | 11 ++++--- src/status.c | 17 ++++++---- src/submodule.c | 7 +++-- tests-clar/checkout/head.c | 1 - tests-clar/diff/diff_helpers.c | 14 ++++++--- tests-clar/diff/workdir.c | 70 ++++++++++++++++++++++++++++++++++++++++++ tests-clar/index/addall.c | 29 +++++++++++------ tests-clar/index/names.c | 6 ++-- tests-clar/index/reuc.c | 2 -- tests-clar/index/tests.c | 14 ++++----- tests-clar/status/worktree.c | 9 +++--- 17 files changed, 180 insertions(+), 56 deletions(-) diff --git a/examples/showindex.c b/examples/showindex.c index bf852384c..f4c92f068 100644 --- a/examples/showindex.c +++ b/examples/showindex.c @@ -33,7 +33,7 @@ int main (int argc, char** argv) git_repository_free(repo); } - git_index_read(index); + git_index_read(index, 0); ecount = git_index_entrycount(index); if (!ecount) diff --git a/include/git2/diff.h b/include/git2/diff.h index 5d360bedb..ac2d4b1e7 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -607,6 +607,10 @@ GIT_EXTERN(int) git_diff_tree_to_tree( * The tree you pass will be used for the "old_file" side of the delta, and * the index will be used for the "new_file" side of the delta. * + * If you pass NULL for the index, then the existing index of the `repo` + * will be used. In this case, the index will be refreshed from disk + * (if it has changed) before the diff is generated. + * * @param diff Output pointer to a git_diff pointer to be allocated. * @param repo The repository containing the tree and index. * @param old_tree A git_tree object to diff from, or NULL for empty tree. @@ -631,6 +635,10 @@ GIT_EXTERN(int) git_diff_tree_to_index( * The index will be used for the "old_file" side of the delta, and the * working directory will be used for the "new_file" side of the delta. * + * If you pass NULL for the index, then the existing index of the `repo` + * will be used. In this case, the index will be refreshed from disk + * (if it has changed) before the diff is generated. + * * @param diff Output pointer to a git_diff pointer to be allocated. * @param repo The repository. * @param index The index to diff from; repo index used if NULL. diff --git a/include/git2/index.h b/include/git2/index.h index 8064a62ff..7de106624 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -222,16 +222,23 @@ GIT_EXTERN(unsigned int) git_index_caps(const git_index *index); GIT_EXTERN(int) git_index_set_caps(git_index *index, unsigned int caps); /** - * Update the contents of an existing index object in memory - * by reading from the hard disk. + * Update the contents of an existing index object in memory by reading + * from the hard disk. * - * If the file doesn't exist on the filesystem, the index - * will be cleared from its current content. + * Pass 0 for `only_if_changed` to perform a "hard" read that discards + * in-memory changes and always reloads the on-disk index data. If there + * is no on-disk version, the index will be cleared. + * + * Pass non-zero for `only_if_changed` to perform a "soft" read that only + * reloads the index data if it has changed since the last time it was + * loaded. In-memory index data will be untouched. Be aware: if there + * are changes on disk, unwritten in-memory changes will be discarded. * * @param index an existing index object + * @param only_if_changed only read if on-disk file is newer than last read * @return 0 or an error code */ -GIT_EXTERN(int) git_index_read(git_index *index); +GIT_EXTERN(int) git_index_read(git_index *index, int only_if_changed); /** * Write an existing index object from memory back to disk diff --git a/include/git2/status.h b/include/git2/status.h index aa934d96b..4ec3432df 100644 --- a/include/git2/status.h +++ b/include/git2/status.h @@ -118,6 +118,9 @@ typedef enum { * case-insensitive order * - GIT_STATUS_OPT_RENAMES_FROM_REWRITES indicates that rename detection * should include rewritten files + * - GIT_STATUS_OPT_NO_REFRESH bypasses the default status behavior of + * doing a "soft" index reload (i.e. reloading the index data if the + * file on disk has been modified outside libgit2). * * Calling `git_status_foreach()` is like calling the extended version * with: GIT_STATUS_OPT_INCLUDE_IGNORED, GIT_STATUS_OPT_INCLUDE_UNTRACKED, @@ -137,6 +140,7 @@ typedef enum { GIT_STATUS_OPT_SORT_CASE_SENSITIVELY = (1u << 9), GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY = (1u << 10), GIT_STATUS_OPT_RENAMES_FROM_REWRITES = (1u << 11), + GIT_STATUS_OPT_NO_REFRESH = (1u << 12), } git_status_opt_t; #define GIT_STATUS_OPT_DEFAULTS \ diff --git a/src/checkout.c b/src/checkout.c index 76edc6a72..94968e378 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -1837,7 +1837,7 @@ static int checkout_data_init( } else { /* otherwise, grab and reload the index */ if ((error = git_repository_index(&data->index, data->repo)) < 0 || - (error = git_index_read(data->index)) < 0) + (error = git_index_read(data->index, false)) < 0) goto cleanup; /* cannot checkout if unresolved conflicts exist */ diff --git a/src/diff.c b/src/diff.c index b1f64e6a3..d1ff04b52 100644 --- a/src/diff.c +++ b/src/diff.c @@ -1184,6 +1184,17 @@ int git_diff_tree_to_tree( return error; } +static int diff_load_index(git_index **index, git_repository *repo) +{ + int error = git_repository_index__weakptr(index, repo); + + /* reload the repository index when user did not pass one in */ + if (!error && git_index_read(*index, true) < 0) + giterr_clear(); + + return error; +} + int git_diff_tree_to_index( git_diff **diff, git_repository *repo, @@ -1196,7 +1207,7 @@ int git_diff_tree_to_index( assert(diff && repo); - if (!index && (error = git_repository_index__weakptr(&index, repo)) < 0) + if (!index && (error = diff_load_index(&index, repo)) < 0) return error; if (index->ignore_case) { @@ -1239,7 +1250,7 @@ int git_diff_index_to_workdir( assert(diff && repo); - if (!index && (error = git_repository_index__weakptr(&index, repo)) < 0) + if (!index && (error = diff_load_index(&index, repo)) < 0) return error; DIFF_FROM_ITERATORS( @@ -1278,11 +1289,15 @@ int git_diff_tree_to_workdir_with_index( { int error = 0; git_diff *d1 = NULL, *d2 = NULL; + git_index *index = NULL; assert(diff && repo); - if (!(error = git_diff_tree_to_index(&d1, repo, old_tree, NULL, opts)) && - !(error = git_diff_index_to_workdir(&d2, repo, NULL, opts))) + if ((error = diff_load_index(&index, repo)) < 0) + return error; + + if (!(error = git_diff_tree_to_index(&d1, repo, old_tree, index, opts)) && + !(error = git_diff_index_to_workdir(&d2, repo, index, opts))) error = git_diff_merge(d1, d2); git_diff_free(d2); diff --git a/src/index.c b/src/index.c index 5cdd40aaa..19de43d29 100644 --- a/src/index.c +++ b/src/index.c @@ -349,7 +349,7 @@ int git_index_open(git_index **index_out, const char *index_path) *index_out = index; GIT_REFCOUNT_INC(index); - return (index_path != NULL) ? git_index_read(index) : 0; + return (index_path != NULL) ? git_index_read(index, false) : 0; } int git_index_new(git_index **out) @@ -451,11 +451,11 @@ unsigned int git_index_caps(const git_index *index) (index->no_symlinks ? GIT_INDEXCAP_NO_SYMLINKS : 0)); } -int git_index_read(git_index *index) +int git_index_read(git_index *index, int only_if_changed) { int error = 0, updated; git_buf buffer = GIT_BUF_INIT; - git_futils_filestamp stamp = {0}; + git_futils_filestamp stamp = index->stamp; if (!index->index_file_path) return create_index_error(-1, @@ -464,12 +464,13 @@ int git_index_read(git_index *index) index->on_disk = git_path_exists(index->index_file_path); if (!index->on_disk) { - git_index_clear(index); + if (!only_if_changed) + git_index_clear(index); return 0; } updated = git_futils_filestamp_check(&stamp, index->index_file_path); - if (updated <= 0) + if (updated < 0 || (only_if_changed && !updated)) return updated; error = git_futils_readbuffer(&buffer, index->index_file_path); diff --git a/src/status.c b/src/status.c index 2b84794b5..74bccf7a1 100644 --- a/src/status.c +++ b/src/status.c @@ -251,12 +251,17 @@ int git_status_list_new( return error; /* if there is no HEAD, that's okay - we'll make an empty iterator */ - if (((error = git_repository_head_tree(&head, repo)) < 0) && - error != GIT_ENOTFOUND && error != GIT_EUNBORNBRANCH) { - git_index_free(index); /* release index */ - return error; + if ((error = git_repository_head_tree(&head, repo)) < 0) { + if (error != GIT_ENOTFOUND && error != GIT_EUNBORNBRANCH) + goto done; + giterr_clear(); } + /* refresh index from disk unless prevented */ + if ((flags & GIT_STATUS_OPT_NO_REFRESH) == 0 && + git_index_read(index, true) < 0) + giterr_clear(); + status = git_status_list_alloc(index); GITERR_CHECK_ALLOC(status); @@ -291,7 +296,7 @@ int git_status_list_new( if (show != GIT_STATUS_SHOW_WORKDIR_ONLY) { if ((error = git_diff_tree_to_index( - &status->head2idx, repo, head, NULL, &diffopt)) < 0) + &status->head2idx, repo, head, index, &diffopt)) < 0) goto done; if ((flags & GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX) != 0 && @@ -301,7 +306,7 @@ int git_status_list_new( if (show != GIT_STATUS_SHOW_INDEX_ONLY) { if ((error = git_diff_index_to_workdir( - &status->idx2wd, repo, NULL, &diffopt)) < 0) + &status->idx2wd, repo, index, &diffopt)) < 0) goto done; if ((flags & GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR) != 0 && diff --git a/src/submodule.c b/src/submodule.c index 18d80f0a9..586494fed 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -1527,6 +1527,7 @@ static void submodule_get_wd_status( const git_oid *wd_oid = (sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) ? &sm->wd_oid : NULL; git_tree *sm_head = NULL; + git_index *index = NULL; git_diff_options opt = GIT_DIFF_OPTIONS_INIT; git_diff *diff; @@ -1558,12 +1559,14 @@ static void submodule_get_wd_status( if (ign == GIT_SUBMODULE_IGNORE_NONE) opt.flags |= GIT_DIFF_INCLUDE_UNTRACKED; + (void)git_repository_index__weakptr(&index, sm_repo); + /* if we don't have an unborn head, check diff with index */ if (git_repository_head_tree(&sm_head, sm_repo) < 0) giterr_clear(); else { /* perform head to index diff on submodule */ - if (git_diff_tree_to_index(&diff, sm_repo, sm_head, NULL, &opt) < 0) + if (git_diff_tree_to_index(&diff, sm_repo, sm_head, index, &opt) < 0) giterr_clear(); else { if (git_diff_num_deltas(diff) > 0) @@ -1576,7 +1579,7 @@ static void submodule_get_wd_status( } /* perform index-to-workdir diff on submodule */ - if (git_diff_index_to_workdir(&diff, sm_repo, NULL, &opt) < 0) + if (git_diff_index_to_workdir(&diff, sm_repo, index, &opt) < 0) giterr_clear(); else { size_t untracked = diff --git a/tests-clar/checkout/head.c b/tests-clar/checkout/head.c index 74c6fb87a..a7a7e9071 100644 --- a/tests-clar/checkout/head.c +++ b/tests-clar/checkout/head.c @@ -54,7 +54,6 @@ void test_checkout_head__with_index_only_tree(void) cl_git_pass(git_checkout_head(g_repo, &opts)); cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_index_read(index)); /* reload if needed */ cl_assert(!git_path_isfile("testrepo/newdir/newfile.txt")); cl_assert(git_index_get_bypath(index, "newdir/newfile.txt", 0) == NULL); diff --git a/tests-clar/diff/diff_helpers.c b/tests-clar/diff/diff_helpers.c index 466d0ef54..33bb561f6 100644 --- a/tests-clar/diff/diff_helpers.c +++ b/tests-clar/diff/diff_helpers.c @@ -221,11 +221,15 @@ static int diff_print_cb( const git_diff_line *line, void *payload) { - GIT_UNUSED(payload); - GIT_UNUSED(delta); - GIT_UNUSED(hunk); - fprintf((FILE *)payload, "%c%.*s", - line->origin, (int)line->content_len, line->content); + FILE *fp = payload; + + GIT_UNUSED(delta); GIT_UNUSED(hunk); + + if (line->origin == GIT_DIFF_LINE_CONTEXT || + line->origin == GIT_DIFF_LINE_ADDITION || + line->origin == GIT_DIFF_LINE_DELETION) + fputc(line->origin, fp); + fwrite(line->content, 1, line->content_len, fp); return 0; } diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index e72acdb03..8611be8c8 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -1329,3 +1329,73 @@ void test_diff_workdir__patience_diff(void) git_patch_free(patch); git_diff_free(diff); } + +void test_diff_workdir__with_stale_index(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_index *idx = NULL; + diff_expects exp; + + g_repo = cl_git_sandbox_init("status"); + cl_git_pass(git_repository_index(&idx, g_repo)); + + /* make the in-memory index invalid */ + { + git_repository *r2; + git_index *idx2; + cl_git_pass(git_repository_open(&r2, "status")); + cl_git_pass(git_repository_index(&idx2, r2)); + cl_git_pass(git_index_add_bypath(idx2, "new_file")); + cl_git_pass(git_index_add_bypath(idx2, "subdir/new_file")); + cl_git_pass(git_index_remove_bypath(idx2, "staged_new_file")); + cl_git_pass(git_index_remove_bypath(idx2, "staged_changes_file_deleted")); + cl_git_pass(git_index_write(idx2)); + git_index_free(idx2); + git_repository_free(r2); + } + + opts.context_lines = 3; + opts.interhunk_lines = 1; + opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_INCLUDE_UNMODIFIED; + + /* first try with index pointer which should prevent reload */ + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, idx, &opts)); + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(17, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]); + cl_assert_equal_i(5, exp.file_status[GIT_DELTA_UNMODIFIED]); + + git_diff_free(diff); + + /* now let's try without the index pointer which should trigger reload */ + + /* two files that were UNTRACKED should have become UNMODIFIED */ + /* one file that was UNMODIFIED should now have become UNTRACKED */ + /* one file that was DELETED should now be gone completely */ + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(16, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); + cl_assert_equal_i(6, exp.file_status[GIT_DELTA_UNMODIFIED]); + + git_index_free(idx); +} diff --git a/tests-clar/index/addall.c b/tests-clar/index/addall.c index 3b5f5f22d..44c51279d 100644 --- a/tests-clar/index/addall.c +++ b/tests-clar/index/addall.c @@ -68,10 +68,11 @@ static int index_status_cb( return 0; } -static void check_status( +static void check_status_at_line( git_repository *repo, size_t index_adds, size_t index_dels, size_t index_mods, - size_t wt_adds, size_t wt_dels, size_t wt_mods, size_t ignores) + size_t wt_adds, size_t wt_dels, size_t wt_mods, size_t ignores, + const char *file, int line) { index_status_counts vals; @@ -79,15 +80,25 @@ static void check_status( cl_git_pass(git_status_foreach(repo, index_status_cb, &vals)); - cl_assert_equal_sz(index_adds, vals.index_adds); - cl_assert_equal_sz(index_dels, vals.index_dels); - cl_assert_equal_sz(index_mods, vals.index_mods); - cl_assert_equal_sz(wt_adds, vals.wt_adds); - cl_assert_equal_sz(wt_dels, vals.wt_dels); - cl_assert_equal_sz(wt_mods, vals.wt_mods); - cl_assert_equal_sz(ignores, vals.ignores); + clar__assert_equal( + file,line,"wrong index adds", 1, "%"PRIuZ, index_adds, vals.index_adds); + clar__assert_equal( + file,line,"wrong index dels", 1, "%"PRIuZ, index_dels, vals.index_dels); + clar__assert_equal( + file,line,"wrong index mods", 1, "%"PRIuZ, index_mods, vals.index_mods); + clar__assert_equal( + file,line,"wrong workdir adds", 1, "%"PRIuZ, wt_adds, vals.wt_adds); + clar__assert_equal( + file,line,"wrong workdir dels", 1, "%"PRIuZ, wt_dels, vals.wt_dels); + clar__assert_equal( + file,line,"wrong workdir mods", 1, "%"PRIuZ, wt_mods, vals.wt_mods); + clar__assert_equal( + file,line,"wrong ignores", 1, "%"PRIuZ, ignores, vals.ignores); } +#define check_status(R,IA,ID,IM,WA,WD,WM,IG) \ + check_status_at_line(R,IA,ID,IM,WA,WD,WM,IG,__FILE__,__LINE__) + static void check_stat_data(git_index *index, const char *path, bool match) { const git_index_entry *entry; diff --git a/tests-clar/index/names.c b/tests-clar/index/names.c index 87453ecbf..9a86b14d2 100644 --- a/tests-clar/index/names.c +++ b/tests-clar/index/names.c @@ -63,7 +63,7 @@ void test_index_names__roundtrip(void) git_index_clear(repo_index); cl_assert(git_index_name_entrycount(repo_index) == 0); - cl_git_pass(git_index_read(repo_index)); + cl_git_pass(git_index_read(repo_index, 0)); cl_assert(git_index_name_entrycount(repo_index) == 3); conflict_name = git_index_name_get_byindex(repo_index, 0); @@ -120,7 +120,7 @@ void test_index_names__cleaned_on_checkout_tree(void) git_reference_name_to_id(&oid, repo, "refs/heads/master"); git_object_lookup(&obj, repo, &oid, GIT_OBJ_ANY); git_checkout_tree(repo, obj, &opts); - cl_assert(git_index_name_entrycount(repo_index) == 0); + cl_assert_equal_sz(0, git_index_name_entrycount(repo_index)); git_object_free(obj); } @@ -133,7 +133,7 @@ void test_index_names__cleaned_on_checkout_head(void) test_index_names__add(); git_checkout_head(repo, &opts); - cl_assert(git_index_name_entrycount(repo_index) == 0); + cl_assert_equal_sz(0, git_index_name_entrycount(repo_index)); } void test_index_names__retained_on_checkout_index(void) diff --git a/tests-clar/index/reuc.c b/tests-clar/index/reuc.c index 69ed4a933..a18d5602e 100644 --- a/tests-clar/index/reuc.c +++ b/tests-clar/index/reuc.c @@ -276,8 +276,6 @@ void test_index_reuc__write(void) 0100644, &their_oid)); cl_git_pass(git_index_write(repo_index)); - - cl_git_pass(git_index_read(repo_index)); cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); /* ensure sort order was round-tripped correct */ diff --git a/tests-clar/index/tests.c b/tests-clar/index/tests.c index 009d393d7..f538bc278 100644 --- a/tests-clar/index/tests.c +++ b/tests-clar/index/tests.c @@ -349,14 +349,14 @@ void test_index_tests__remove_entry(void) cl_git_pass(git_index_add_bypath(index, "hello")); cl_git_pass(git_index_write(index)); - cl_git_pass(git_index_read(index)); /* reload */ + cl_git_pass(git_index_read(index, false)); /* reload */ cl_assert(git_index_entrycount(index) == 1); cl_assert(git_index_get_bypath(index, "hello", 0) != NULL); cl_git_pass(git_index_remove(index, "hello", 0)); cl_git_pass(git_index_write(index)); - cl_git_pass(git_index_read(index)); /* reload */ + cl_git_pass(git_index_read(index, false)); /* reload */ cl_assert(git_index_entrycount(index) == 0); cl_assert(git_index_get_bypath(index, "hello", 0) == NULL); @@ -388,7 +388,7 @@ void test_index_tests__remove_directory(void) cl_git_pass(git_index_add_bypath(index, "b.txt")); cl_git_pass(git_index_write(index)); - cl_git_pass(git_index_read(index)); /* reload */ + cl_git_pass(git_index_read(index, false)); /* reload */ cl_assert_equal_i(4, (int)git_index_entrycount(index)); cl_assert(git_index_get_bypath(index, "a/1.txt", 0) != NULL); cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL); @@ -397,7 +397,7 @@ void test_index_tests__remove_directory(void) cl_git_pass(git_index_remove(index, "a/1.txt", 0)); cl_git_pass(git_index_write(index)); - cl_git_pass(git_index_read(index)); /* reload */ + cl_git_pass(git_index_read(index, false)); /* reload */ cl_assert_equal_i(3, (int)git_index_entrycount(index)); cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL); cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL); @@ -406,7 +406,7 @@ void test_index_tests__remove_directory(void) cl_git_pass(git_index_remove_directory(index, "a", 0)); cl_git_pass(git_index_write(index)); - cl_git_pass(git_index_read(index)); /* reload */ + cl_git_pass(git_index_read(index, false)); /* reload */ cl_assert_equal_i(1, (int)git_index_entrycount(index)); cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL); cl_assert(git_index_get_bypath(index, "a/2.txt", 0) == NULL); @@ -517,7 +517,7 @@ void test_index_tests__reload_from_disk(void) /* Sync the changes back into the read_index */ cl_assert_equal_sz(0, git_index_entrycount(read_index)); - cl_git_pass(git_index_read(read_index)); + cl_git_pass(git_index_read(read_index, false)); cl_assert_equal_i(true, read_index->on_disk); cl_assert_equal_sz(2, git_index_entrycount(read_index)); @@ -526,7 +526,7 @@ void test_index_tests__reload_from_disk(void) cl_git_pass(p_unlink(write_index->index_file_path)); /* Sync the changes back into the read_index */ - cl_git_pass(git_index_read(read_index)); + cl_git_pass(git_index_read(read_index, false)); cl_assert_equal_i(false, read_index->on_disk); cl_assert_equal_sz(0, git_index_entrycount(read_index)); diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index 3b569c7ba..34be6d34c 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -470,16 +470,15 @@ void test_status_worktree__conflict_with_diff3(void) cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_remove(index, "modified_file", 0)); - cl_git_pass(git_index_conflict_add(index, &ancestor_entry, - &our_entry, &their_entry)); + cl_git_pass(git_index_conflict_add( + index, &ancestor_entry, &our_entry, &their_entry)); + cl_git_pass(git_index_write(index)); + git_index_free(index); cl_git_pass(git_status_file(&status, repo, "modified_file")); cl_assert_equal_i(GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW, status); - - git_index_free(index); } static const char *filemode_paths[] = { -- cgit v1.2.1 From 8e5a8ef86f1d528472884f737612083abda86e17 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 1 Nov 2013 09:51:01 -0700 Subject: Convert git_index_read to have a "force" flag This is a little more intuitive than the turned-around option that I originally wrote. --- include/git2/index.h | 18 +++++++++--------- src/checkout.c | 2 +- src/diff.c | 2 +- src/index.c | 8 ++++---- src/status.c | 2 +- tests-clar/index/names.c | 2 +- tests-clar/index/tests.c | 27 ++++++++++++++------------- 7 files changed, 31 insertions(+), 30 deletions(-) diff --git a/include/git2/index.h b/include/git2/index.h index 7de106624..a60db370a 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -225,20 +225,20 @@ GIT_EXTERN(int) git_index_set_caps(git_index *index, unsigned int caps); * Update the contents of an existing index object in memory by reading * from the hard disk. * - * Pass 0 for `only_if_changed` to perform a "hard" read that discards - * in-memory changes and always reloads the on-disk index data. If there - * is no on-disk version, the index will be cleared. + * If `force` is true, this performs a "hard" read that discards in-memory + * changes and always reloads the on-disk index data. If there is no + * on-disk version, the index will be cleared. * - * Pass non-zero for `only_if_changed` to perform a "soft" read that only - * reloads the index data if it has changed since the last time it was - * loaded. In-memory index data will be untouched. Be aware: if there - * are changes on disk, unwritten in-memory changes will be discarded. + * If `force` is false, this does a "soft" read that reloads the index + * data from disk only if it has changed since the last time it was + * loaded. Purely in-memory index data will be untouched. Be aware: if + * there are changes on disk, unwritten in-memory changes are discarded. * * @param index an existing index object - * @param only_if_changed only read if on-disk file is newer than last read + * @param force if true, always reload, vs. only read if file has changed * @return 0 or an error code */ -GIT_EXTERN(int) git_index_read(git_index *index, int only_if_changed); +GIT_EXTERN(int) git_index_read(git_index *index, int force); /** * Write an existing index object from memory back to disk diff --git a/src/checkout.c b/src/checkout.c index 94968e378..dce9afdf4 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -1837,7 +1837,7 @@ static int checkout_data_init( } else { /* otherwise, grab and reload the index */ if ((error = git_repository_index(&data->index, data->repo)) < 0 || - (error = git_index_read(data->index, false)) < 0) + (error = git_index_read(data->index, true)) < 0) goto cleanup; /* cannot checkout if unresolved conflicts exist */ diff --git a/src/diff.c b/src/diff.c index d1ff04b52..5c89b6e59 100644 --- a/src/diff.c +++ b/src/diff.c @@ -1189,7 +1189,7 @@ static int diff_load_index(git_index **index, git_repository *repo) int error = git_repository_index__weakptr(index, repo); /* reload the repository index when user did not pass one in */ - if (!error && git_index_read(*index, true) < 0) + if (!error && git_index_read(*index, false) < 0) giterr_clear(); return error; diff --git a/src/index.c b/src/index.c index 19de43d29..dbf1ab529 100644 --- a/src/index.c +++ b/src/index.c @@ -349,7 +349,7 @@ int git_index_open(git_index **index_out, const char *index_path) *index_out = index; GIT_REFCOUNT_INC(index); - return (index_path != NULL) ? git_index_read(index, false) : 0; + return (index_path != NULL) ? git_index_read(index, true) : 0; } int git_index_new(git_index **out) @@ -451,7 +451,7 @@ unsigned int git_index_caps(const git_index *index) (index->no_symlinks ? GIT_INDEXCAP_NO_SYMLINKS : 0)); } -int git_index_read(git_index *index, int only_if_changed) +int git_index_read(git_index *index, int force) { int error = 0, updated; git_buf buffer = GIT_BUF_INIT; @@ -464,13 +464,13 @@ int git_index_read(git_index *index, int only_if_changed) index->on_disk = git_path_exists(index->index_file_path); if (!index->on_disk) { - if (!only_if_changed) + if (force) git_index_clear(index); return 0; } updated = git_futils_filestamp_check(&stamp, index->index_file_path); - if (updated < 0 || (only_if_changed && !updated)) + if (updated < 0 || (!updated && !force)) return updated; error = git_futils_readbuffer(&buffer, index->index_file_path); diff --git a/src/status.c b/src/status.c index 74bccf7a1..07fdcb5c3 100644 --- a/src/status.c +++ b/src/status.c @@ -259,7 +259,7 @@ int git_status_list_new( /* refresh index from disk unless prevented */ if ((flags & GIT_STATUS_OPT_NO_REFRESH) == 0 && - git_index_read(index, true) < 0) + git_index_read(index, false) < 0) giterr_clear(); status = git_status_list_alloc(index); diff --git a/tests-clar/index/names.c b/tests-clar/index/names.c index 9a86b14d2..9007b1b15 100644 --- a/tests-clar/index/names.c +++ b/tests-clar/index/names.c @@ -63,7 +63,7 @@ void test_index_names__roundtrip(void) git_index_clear(repo_index); cl_assert(git_index_name_entrycount(repo_index) == 0); - cl_git_pass(git_index_read(repo_index, 0)); + cl_git_pass(git_index_read(repo_index, true)); cl_assert(git_index_name_entrycount(repo_index) == 3); conflict_name = git_index_name_get_byindex(repo_index, 0); diff --git a/tests-clar/index/tests.c b/tests-clar/index/tests.c index f538bc278..09b05bf6e 100644 --- a/tests-clar/index/tests.c +++ b/tests-clar/index/tests.c @@ -8,7 +8,7 @@ static const size_t index_entry_count_2 = 1437; #define TEST_INDEXBIG_PATH cl_fixture("big.index") -// Suite data +/* Suite data */ struct test_entry { size_t index; char path[128]; @@ -24,7 +24,7 @@ static struct test_entry test_entries[] = { {48, "src/revobject.h", 1448, 0x4C3F7FE2} }; -// Helpers +/* Helpers */ static void copy_file(const char *src, const char *dst) { git_buf source_buf = GIT_BUF_INIT; @@ -32,7 +32,7 @@ static void copy_file(const char *src, const char *dst) cl_git_pass(git_futils_readbuffer(&source_buf, src)); - dst_fd = git_futils_creat_withpath(dst, 0777, 0666); //-V536 + dst_fd = git_futils_creat_withpath(dst, 0777, 0666); /* -V536 */ if (dst_fd < 0) goto cleanup; @@ -66,7 +66,7 @@ static void files_are_equal(const char *a, const char *b) } -// Fixture setup and teardown +/* Fixture setup and teardown */ void test_index_tests__initialize(void) { } @@ -173,7 +173,8 @@ void test_index_tests__write(void) void test_index_tests__sort0(void) { - // sort the entires in an index + /* sort the entires in an index */ + /* * TODO: This no longer applies: * index sorting in Git uses some specific changes to the way @@ -187,7 +188,7 @@ void test_index_tests__sort0(void) void test_index_tests__sort1(void) { - // sort the entires in an empty index + /* sort the entires in an empty index */ git_index *index; cl_git_pass(git_index_open(&index, "fake-index")); @@ -349,14 +350,14 @@ void test_index_tests__remove_entry(void) cl_git_pass(git_index_add_bypath(index, "hello")); cl_git_pass(git_index_write(index)); - cl_git_pass(git_index_read(index, false)); /* reload */ + cl_git_pass(git_index_read(index, true)); /* reload */ cl_assert(git_index_entrycount(index) == 1); cl_assert(git_index_get_bypath(index, "hello", 0) != NULL); cl_git_pass(git_index_remove(index, "hello", 0)); cl_git_pass(git_index_write(index)); - cl_git_pass(git_index_read(index, false)); /* reload */ + cl_git_pass(git_index_read(index, true)); /* reload */ cl_assert(git_index_entrycount(index) == 0); cl_assert(git_index_get_bypath(index, "hello", 0) == NULL); @@ -388,7 +389,7 @@ void test_index_tests__remove_directory(void) cl_git_pass(git_index_add_bypath(index, "b.txt")); cl_git_pass(git_index_write(index)); - cl_git_pass(git_index_read(index, false)); /* reload */ + cl_git_pass(git_index_read(index, true)); /* reload */ cl_assert_equal_i(4, (int)git_index_entrycount(index)); cl_assert(git_index_get_bypath(index, "a/1.txt", 0) != NULL); cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL); @@ -397,7 +398,7 @@ void test_index_tests__remove_directory(void) cl_git_pass(git_index_remove(index, "a/1.txt", 0)); cl_git_pass(git_index_write(index)); - cl_git_pass(git_index_read(index, false)); /* reload */ + cl_git_pass(git_index_read(index, true)); /* reload */ cl_assert_equal_i(3, (int)git_index_entrycount(index)); cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL); cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL); @@ -406,7 +407,7 @@ void test_index_tests__remove_directory(void) cl_git_pass(git_index_remove_directory(index, "a", 0)); cl_git_pass(git_index_write(index)); - cl_git_pass(git_index_read(index, false)); /* reload */ + cl_git_pass(git_index_read(index, true)); /* reload */ cl_assert_equal_i(1, (int)git_index_entrycount(index)); cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL); cl_assert(git_index_get_bypath(index, "a/2.txt", 0) == NULL); @@ -517,7 +518,7 @@ void test_index_tests__reload_from_disk(void) /* Sync the changes back into the read_index */ cl_assert_equal_sz(0, git_index_entrycount(read_index)); - cl_git_pass(git_index_read(read_index, false)); + cl_git_pass(git_index_read(read_index, true)); cl_assert_equal_i(true, read_index->on_disk); cl_assert_equal_sz(2, git_index_entrycount(read_index)); @@ -526,7 +527,7 @@ void test_index_tests__reload_from_disk(void) cl_git_pass(p_unlink(write_index->index_file_path)); /* Sync the changes back into the read_index */ - cl_git_pass(git_index_read(read_index, false)); + cl_git_pass(git_index_read(read_index, true)); cl_assert_equal_i(false, read_index->on_disk); cl_assert_equal_sz(0, git_index_entrycount(read_index)); -- cgit v1.2.1 From a5c16f3cfb92f1129ef13124fc70147480141d69 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 1 Nov 2013 10:18:03 -0700 Subject: Add git_diff_options_init helper Sometimes the static initializer for git_diff_options cannot be used and since setting them to all zeroes doesn't actually work quite right, this adds a new helper for that situation. This also adds an explicit new value to the submodule settings options to be used when those enums need static initialization. --- include/git2/diff.h | 30 ++++++++++++++++++++++++++---- include/git2/types.h | 28 +++++++++++++++++++--------- src/diff.c | 13 +++++++++++++ tests-clar/diff/blob.c | 3 +-- tests-clar/diff/tree.c | 7 +++---- 5 files changed, 62 insertions(+), 19 deletions(-) diff --git a/include/git2/diff.h b/include/git2/diff.h index ac2d4b1e7..a16f86a46 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -352,10 +352,10 @@ typedef struct { /* options controlling which files are in the diff */ - git_submodule_ignore_t ignore_submodules; /** << submodule ignore rule */ - git_strarray pathspec; /**< defaults to include all paths */ + git_submodule_ignore_t ignore_submodules; /**< submodule ignore rule */ + git_strarray pathspec; /**< defaults to include all paths */ git_diff_notify_cb notify_cb; - void *notify_payload; + void *notify_payload; /* options controlling how to diff text is generated */ @@ -367,9 +367,14 @@ typedef struct { const char *new_prefix; /**< defaults to "b" */ } git_diff_options; +/* The current version of the diff options structure */ #define GIT_DIFF_OPTIONS_VERSION 1 + +/* Stack initializer for diff options. Alternatively use + * `git_diff_options_init` programmatic initialization. + */ #define GIT_DIFF_OPTIONS_INIT \ - {GIT_DIFF_OPTIONS_VERSION, 0, 0, {NULL,0}, NULL, NULL, 3} + {GIT_DIFF_OPTIONS_VERSION, 0, GIT_SUBMODULE_IGNORE_DEFAULT, {NULL,0}, NULL, NULL, 3} /** * When iterating over a diff, callback that will be made per file. @@ -738,6 +743,23 @@ GIT_EXTERN(int) git_diff_find_similar( git_diff *diff, const git_diff_find_options *options); +/** + * Initialize diff options structure + * + * In most cases, you can probably just use `GIT_DIFF_OPTIONS_INIT` to + * initialize the diff options structure, but in some cases that is not + * going to work. You can call this function instead. Note that you + * must pass both a pointer to the structure to be initialized and the + * `GIT_DIFF_OPTIONS_VERSION` value from the header you compiled with. + * + * @param options Pointer to git_diff_options memory to be initialized + * @param version Should be `GIT_DIFF_OPTIONS_VERSION` + * @return 0 on success, negative on failure (such as unsupported version) + */ +GIT_EXTERN(int) git_diff_options_init( + git_diff_options *options, + unsigned int version); + /**@}*/ diff --git a/include/git2/types.h b/include/git2/types.h index 2d18d385a..71d5374d3 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -268,13 +268,18 @@ typedef struct git_submodule git_submodule; * superproject into the current checkout out branch of the submodule. * - GIT_SUBMODULE_UPDATE_NONE: do not update this submodule even when * the commit in the superproject is updated. + * - GIT_SUBMODULE_UPDATE_DEFAULT: not used except as static initializer + * when we don't want any particular update rule to be specified. */ typedef enum { - GIT_SUBMODULE_UPDATE_RESET = -1, + GIT_SUBMODULE_UPDATE_RESET = -1, + GIT_SUBMODULE_UPDATE_CHECKOUT = 1, - GIT_SUBMODULE_UPDATE_REBASE = 2, - GIT_SUBMODULE_UPDATE_MERGE = 3, - GIT_SUBMODULE_UPDATE_NONE = 4 + GIT_SUBMODULE_UPDATE_REBASE = 2, + GIT_SUBMODULE_UPDATE_MERGE = 3, + GIT_SUBMODULE_UPDATE_NONE = 4, + + GIT_SUBMODULE_UPDATE_DEFAULT = 0 } git_submodule_update_t; /** @@ -301,13 +306,18 @@ typedef enum { * only considering changes if the HEAD of submodule has moved from the * value in the superproject. * - GIT_SUBMODULE_IGNORE_ALL: never check if the submodule is dirty + * - GIT_SUBMODULE_IGNORE_DEFAULT: not used except as static initializer + * when we don't want any particular ignore rule to be specified. */ typedef enum { - GIT_SUBMODULE_IGNORE_RESET = -1, /* reset to on-disk value */ - GIT_SUBMODULE_IGNORE_NONE = 1, /* any change or untracked == dirty */ - GIT_SUBMODULE_IGNORE_UNTRACKED = 2, /* dirty if tracked files change */ - GIT_SUBMODULE_IGNORE_DIRTY = 3, /* only dirty if HEAD moved */ - GIT_SUBMODULE_IGNORE_ALL = 4 /* never dirty */ + GIT_SUBMODULE_IGNORE_RESET = -1, /* reset to on-disk value */ + + GIT_SUBMODULE_IGNORE_NONE = 1, /* any change or untracked == dirty */ + GIT_SUBMODULE_IGNORE_UNTRACKED = 2, /* dirty if tracked files change */ + GIT_SUBMODULE_IGNORE_DIRTY = 3, /* only dirty if HEAD moved */ + GIT_SUBMODULE_IGNORE_ALL = 4, /* never dirty */ + + GIT_SUBMODULE_IGNORE_DEFAULT = 0 } git_submodule_ignore_t; /** @} */ diff --git a/src/diff.c b/src/diff.c index 5c89b6e59..d94fb2c74 100644 --- a/src/diff.c +++ b/src/diff.c @@ -1311,6 +1311,19 @@ int git_diff_tree_to_workdir_with_index( return error; } +int git_diff_options_init(git_diff_options *options, unsigned int version) +{ + git_diff_options template = GIT_DIFF_OPTIONS_INIT; + + if (version != template.version) { + giterr_set(GITERR_INVALID, + "Invalid version %d for git_diff_options", (int)version); + return -1; + } + + memcpy(options, &template, sizeof(*options)); + return 0; +} size_t git_diff_num_deltas(const git_diff *diff) { diff --git a/tests-clar/diff/blob.c b/tests-clar/diff/blob.c index b51bc0f38..93f20711c 100644 --- a/tests-clar/diff/blob.c +++ b/tests-clar/diff/blob.c @@ -26,9 +26,8 @@ void test_diff_blob__initialize(void) g_repo = cl_git_sandbox_init("attr"); - GIT_INIT_STRUCTURE(&opts, GIT_DIFF_OPTIONS_VERSION); + cl_git_pass(git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION)); opts.context_lines = 1; - opts.interhunk_lines = 0; memset(&expected, 0, sizeof(expected)); diff --git a/tests-clar/diff/tree.c b/tests-clar/diff/tree.c index ca2daf5fb..582174b8b 100644 --- a/tests-clar/diff/tree.c +++ b/tests-clar/diff/tree.c @@ -9,9 +9,7 @@ static diff_expects expect; void test_diff_tree__initialize(void) { - GIT_INIT_STRUCTURE(&opts, GIT_DIFF_OPTIONS_VERSION); - /* The default context lines is set by _INIT which we can't use here */ - opts.context_lines = 3; + cl_git_pass(git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION)); memset(&expect, 0, sizeof(expect)); @@ -91,7 +89,8 @@ void test_diff_tree__0(void) } #define DIFF_OPTS(FLAGS, CTXT) \ - {GIT_DIFF_OPTIONS_VERSION, (FLAGS), 0, {NULL,0}, NULL, NULL, (CTXT), 1} + {GIT_DIFF_OPTIONS_VERSION, (FLAGS), GIT_SUBMODULE_IGNORE_DEFAULT, \ + {NULL,0}, NULL, NULL, (CTXT), 1} void test_diff_tree__options(void) { -- cgit v1.2.1 From dcfdb977d0767395055afe2dcd44fe260e39b46d Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 1 Nov 2013 10:51:12 -0700 Subject: Relicense examples under CC0 --- CONTRIBUTING.md | 8 +++- README.md | 8 ++-- examples/COPYING | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++ examples/README.md | 5 ++- 4 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 examples/COPYING diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5c2eaec5e..807cd5320 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,6 +3,12 @@ We're making it easy to do interesting things with git, and we'd love to have your help. +## Licensing + +By contributing to libgit2, you agree to release your contribution under the terms of the license. +For code under `examples`, this is governed by the [CC0 Public Domain Dedication](examples/COPYING). +All other code is released under the [GPL v2 with linking exception](COPYING). + ## Discussion & Chat We hang out in the #libgit2 channel on irc.freenode.net. @@ -70,7 +76,7 @@ you're porting code *from* to see what you need to do. As a general rule, MIT and BSD (3-clause) licenses are typically no problem. Apache 2.0 license typically doesn't work due to GPL incompatibility. -If you are pulling in code from core Git, another project or code you've pulled from +If you are pulling in code from core Git, another project or code you've pulled from a forum / Stack Overflow then please flag this in your PR and also make sure you've given proper credit to the original author in the code snippet. diff --git a/README.md b/README.md index ce5e22915..8ce60af62 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,11 @@ libgit2 - the Git linkable library re-entrant linkable library with a solid API, allowing you to write native speed custom Git applications in any language with bindings. -`libgit2` is licensed under a **very permissive license** (GPLv2 with a special Linking Exception). -This basically means that you can link it (unmodified) with any kind of software without having to -release its source code. +`libgit2` is licensed under a **very permissive license** (GPLv2 with a special +Linking Exception). This basically means that you can link it (unmodified) +with any kind of software without having to release its source code. +Additionally, the example code has been released to the public domain (see the +[separate license](examples/COPYING) for more information). * Website: [libgit2.github.com](http://libgit2.github.com) * StackOverflow Tag: [libgit2](http://stackoverflow.com/questions/tagged/libgit2) diff --git a/examples/COPYING b/examples/COPYING new file mode 100644 index 000000000..0e259d42c --- /dev/null +++ b/examples/COPYING @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/examples/README.md b/examples/README.md index 494d3291a..769c4b267 100644 --- a/examples/README.md +++ b/examples/README.md @@ -8,7 +8,10 @@ handling, and cross-platform compatibility in the same manner as the rest of the code in libgit2, so copy with caution. That being said, you are welcome to copy code from these examples as -desired when using libgit2. +desired when using libgit2. They have been [released to the public domain][cc0], +so there are no restrictions on their use. + +[cc0]: COPYING For annotated HTML versions, see the "Examples" section of: -- cgit v1.2.1 From e7c85120eab6c942d15c0f5ed3a2c8b6ec667617 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 1 Nov 2013 11:39:37 -0700 Subject: More tests and fixed for merging reversed diffs There were a lot more cases to deal with to make sure that our merged (i.e. workdir-to-tree-to-index) diffs were matching the output of core Git. --- src/diff_tform.c | 57 +++++++++++++++++++++++++++++++++++------------ tests-clar/diff/workdir.c | 32 ++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/diff_tform.c b/src/diff_tform.c index 0aec754a4..28a9cc70d 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -46,7 +46,6 @@ fail: } static git_diff_delta *diff_delta__merge_like_cgit( - uint16_t flags, const git_diff_delta *a, const git_diff_delta *b, git_pool *pool) @@ -99,15 +98,46 @@ static git_diff_delta *diff_delta__merge_like_cgit( return dup; } -int git_diff_merge( - git_diff *onto, - const git_diff *from) +static git_diff_delta *diff_delta__merge_like_cgit_reversed( + const git_diff_delta *a, + const git_diff_delta *b, + git_pool *pool) +{ + git_diff_delta *dup; + + /* reversed version of above logic */ + + if (a->status == GIT_DELTA_UNMODIFIED) + return diff_delta__dup(b, pool); + + if ((dup = diff_delta__dup(a, pool)) == NULL) + return NULL; + + if (b->status == GIT_DELTA_UNMODIFIED || b->status == GIT_DELTA_UNTRACKED) + return dup; + + if (dup->status == GIT_DELTA_DELETED) { + if (b->status == GIT_DELTA_ADDED) + dup->status = GIT_DELTA_UNMODIFIED; + } else { + dup->status = b->status; + } + + git_oid_cpy(&dup->old_file.oid, &b->old_file.oid); + dup->old_file.mode = b->old_file.mode; + dup->old_file.size = b->old_file.size; + dup->old_file.flags = b->old_file.flags; + + return dup; +} + +int git_diff_merge(git_diff *onto, const git_diff *from) { int error = 0; git_pool onto_pool; git_vector onto_new; git_diff_delta *delta; - bool ignore_case = false; + bool ignore_case, reversed; unsigned int i, j; assert(onto && from); @@ -115,11 +145,11 @@ int git_diff_merge( if (!from->deltas.length) return 0; - if ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != - (from->opts.flags & GIT_DIFF_IGNORE_CASE) || - (onto->opts.flags & GIT_DIFF_REVERSE) != - (from->opts.flags & GIT_DIFF_REVERSE)) - { + ignore_case = ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0); + reversed = ((onto->opts.flags & GIT_DIFF_REVERSE) != 0); + + 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"); return -1; @@ -130,8 +160,6 @@ int git_diff_merge( git_pool_init(&onto_pool, 1, 0) < 0) return -1; - ignore_case = ((onto->opts.flags & GIT_DIFF_IGNORE_CASE) != 0); - for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) { git_diff_delta *o = GIT_VECTOR_GET(&onto->deltas, i); const git_diff_delta *f = GIT_VECTOR_GET(&from->deltas, j); @@ -145,8 +173,9 @@ int git_diff_merge( delta = diff_delta__dup(f, &onto_pool); j++; } else { - delta = diff_delta__merge_like_cgit( - onto->opts.flags, o, f, &onto_pool); + delta = reversed ? + diff_delta__merge_like_cgit_reversed(o, f, &onto_pool) : + diff_delta__merge_like_cgit(o, f, &onto_pool); i++; j++; } diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index 8611be8c8..fba64eff3 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -196,6 +196,38 @@ void test_diff_workdir__to_tree(void) git_diff_free(diff); + /* Let's try that once more with a reversed diff */ + + opts.flags |= GIT_DIFF_REVERSE; + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts)); + cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); + cl_git_pass(git_diff_merge(diff, diff2)); + git_diff_free(diff2); + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(16, exp.files); + cl_assert_equal_i(5, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); + + cl_assert_equal_i(12, exp.hunks); + + cl_assert_equal_i(19, exp.lines); + cl_assert_equal_i(3, exp.line_ctxt); + cl_assert_equal_i(12, exp.line_dels); + cl_assert_equal_i(4, exp.line_adds); + + git_diff_free(diff); + + /* all done now */ + git_tree_free(a); git_tree_free(b); } -- cgit v1.2.1 From 3e57069e821ecf966c3de9c79923cd77657e923b Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Fri, 1 Nov 2013 13:49:43 -0700 Subject: Fix --assume-unchanged support This was never really working right because we were checking the wrong flag and not checking it in all the places that we need to be checking it. I finally got around to writing a test and adding actual support for it. --- src/diff.c | 12 ++++++----- src/diff.h | 2 +- tests-clar/diff/workdir.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/diff.c b/src/diff.c index d94fb2c74..4c33a0213 100644 --- a/src/diff.c +++ b/src/diff.c @@ -63,13 +63,16 @@ static int diff_notify( static int diff_delta__from_one( git_diff *diff, - git_delta_t status, + git_delta_t status, const git_index_entry *entry) { git_diff_delta *delta; const char *matched_pathspec; int notify_res; + if ((entry->flags & GIT_IDXENTRY_VALID) != 0) + return 0; + if (status == GIT_DELTA_IGNORED && DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_IGNORED)) return 0; @@ -426,7 +429,7 @@ static int diff_list_apply_options( diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_HAS_SYMLINKS; if (!git_repository__cvar(&val, repo, GIT_CVAR_IGNORESTAT) && val) - diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_ASSUME_UNCHANGED; + diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_IGNORE_STAT; if ((diff->opts.flags & GIT_DIFF_IGNORE_FILEMODE) == 0 && !git_repository__cvar(&val, repo, GIT_CVAR_FILEMODE) && val) @@ -701,9 +704,8 @@ static int maybe_modified( nmode = (nmode & ~MODE_BITS_MASK) | (omode & MODE_BITS_MASK); /* support "assume unchanged" (poorly, b/c we still stat everything) */ - if ((diff->diffcaps & GIT_DIFFCAPS_ASSUME_UNCHANGED) != 0) - status = (oitem->flags_extended & GIT_IDXENTRY_INTENT_TO_ADD) ? - GIT_DELTA_MODIFIED : GIT_DELTA_UNMODIFIED; + if ((oitem->flags & GIT_IDXENTRY_VALID) != 0) + status = GIT_DELTA_UNMODIFIED; /* support "skip worktree" index bit */ else if ((oitem->flags_extended & GIT_IDXENTRY_SKIP_WORKTREE) != 0) diff --git a/src/diff.h b/src/diff.h index 270bea071..2c9298a5f 100644 --- a/src/diff.h +++ b/src/diff.h @@ -23,7 +23,7 @@ enum { GIT_DIFFCAPS_HAS_SYMLINKS = (1 << 0), /* symlinks on platform? */ - GIT_DIFFCAPS_ASSUME_UNCHANGED = (1 << 1), /* use stat? */ + GIT_DIFFCAPS_IGNORE_STAT = (1 << 1), /* use stat? */ GIT_DIFFCAPS_TRUST_MODE_BITS = (1 << 2), /* use st_mode? */ GIT_DIFFCAPS_TRUST_CTIME = (1 << 3), /* use st_ctime? */ GIT_DIFFCAPS_USE_DEV = (1 << 4), /* use st_dev? */ diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index fba64eff3..77af49a37 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -63,6 +63,60 @@ void test_diff_workdir__to_index(void) git_diff_free(diff); } +void test_diff_workdir__to_index_with_assume_unchanged(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_index *idx = NULL; + diff_expects exp; + const git_index_entry *iep; + git_index_entry ie; + + g_repo = cl_git_sandbox_init("status"); + + /* do initial diff */ + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(8, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); + git_diff_free(diff); + + /* mark a couple of entries with ASSUME_UNCHANGED */ + + cl_git_pass(git_repository_index(&idx, g_repo)); + + cl_assert((iep = git_index_get_bypath(idx, "modified_file", 0)) != NULL); + memcpy(&ie, iep, sizeof(ie)); + ie.flags |= GIT_IDXENTRY_VALID; + cl_git_pass(git_index_add(idx, &ie)); + + cl_assert((iep = git_index_get_bypath(idx, "file_deleted", 0)) != NULL); + memcpy(&ie, iep, sizeof(ie)); + ie.flags |= GIT_IDXENTRY_VALID; + cl_git_pass(git_index_add(idx, &ie)); + + cl_git_pass(git_index_write(idx)); + git_index_free(idx); + + /* redo diff and see that entries are skipped */ + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(6, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); + git_diff_free(diff); + +} + void test_diff_workdir__to_tree(void) { /* grabbed a couple of commit oids from the history of the attr repo */ -- cgit v1.2.1 From c2408a698ad395c8bd84297de839080d131c6d6d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 1 Nov 2013 17:03:01 -0400 Subject: preserve windows error numbers as well --- src/common.h | 24 ++++++++++++++++++++++++ src/fileops.c | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/common.h b/src/common.h index 02d9ce9b6..159d31b2e 100644 --- a/src/common.h +++ b/src/common.h @@ -73,6 +73,30 @@ void giterr_set(int error_class, const char *string, ...); */ int giterr_set_regex(const regex_t *regex, int error_code); +/** + * Gets the system error code for this thread. + */ +GIT_INLINE(int) giterr_system_last(void) +{ +#ifdef GIT_WIN32 + return GetLastError(); +#else + return errno; +#endif +} + +/** + * Sets the system error code for this thread. + */ +GIT_INLINE(void) giterr_system_set(int code) +{ +#ifdef GIT_WIN32 + SetLastError(code); +#else + errno = code; +#endif +} + /** * Check a versioned structure for validity */ diff --git a/src/fileops.c b/src/fileops.c index 17007f823..54bf5d850 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -343,11 +343,11 @@ int git_futils_mkdir( /* make directory */ if (p_mkdir(make_path.ptr, mode) < 0) { - int tmp_errno = errno; + int tmp_errno = giterr_system_last(); /* ignore error if directory already exists */ if (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode)) { - errno = tmp_errno; + giterr_system_set(tmp_errno); giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr); goto done; } -- cgit v1.2.1 From 2f03050f4fc50746faef46be498aa0af9697fee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 26 Oct 2013 16:21:31 +0200 Subject: remote: download HEAD when no refspecs are given The correct behaviour when a remote has no refspecs (e.g. a URL from the command-line) is to download the remote's HEAD. Let's do that. This fixes #1261. --- include/git2/remote.h | 2 +- src/fetch.c | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index b9cf86ef1..15a92f3df 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -54,7 +54,7 @@ GIT_EXTERN(int) git_remote_create( * * @param out pointer to the new remote object * @param repo the associated repository - * @param fetch the fetch refspec to use for this remote. May be NULL for defaults. + * @param fetch the fetch refspec to use for this remote. * @param url the remote repository's URL * @return 0 or an error code */ diff --git a/src/fetch.c b/src/fetch.c index 5d97913e8..e83dc4add 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -23,7 +23,7 @@ struct filter_payload { git_remote *remote; const git_refspec *spec, *tagspec; git_odb *odb; - int found_head; + int want_head; }; static int filter_ref__cb(git_remote_head *head, void *payload) @@ -34,9 +34,9 @@ static int filter_ref__cb(git_remote_head *head, void *payload) if (!git_reference_is_valid_name(head->name)) return 0; - if (!p->found_head && strcmp(head->name, GIT_HEAD_FILE) == 0) - p->found_head = 1; - else if (p->remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { + if ((strcmp(head->name, GIT_HEAD_FILE) == 0) && p->want_head) { + match = 1; + } else if (p->remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { /* * If tagopt is --tags, then we only use the default * tags refspec and ignore the remote's @@ -77,8 +77,9 @@ static int filter_wants(git_remote *remote) * HEAD, which will be stored in FETCH_HEAD after the fetch. */ p.tagspec = &tagspec; - p.found_head = 0; p.remote = remote; + if (remote->refspecs.length == 0) + p.want_head = 1; if (git_repository_odb__weakptr(&p.odb, remote->repo) < 0) goto cleanup; -- cgit v1.2.1 From a7382aa28c8a24a4f718eb01574d744330f7a5a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 26 Oct 2013 16:52:54 +0200 Subject: remote: give up after 256 failures to find a common object This avoids sending our whole history bit by bit to the remote in cases where there is no common history, just to give up in the end. The number comes from the canonical implementation. --- src/transports/smart_protocol.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 651901b1b..5d7b9bcba 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -279,19 +279,20 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c unsigned int i; git_oid oid; - /* No own logic, do our thing */ if ((error = git_pkt_buffer_wants(refs, count, &t->caps, &data)) < 0) return error; if ((error = fetch_setup_walk(&walk, repo)) < 0) goto on_error; + /* - * We don't support any kind of ACK extensions, so the negotiation - * boils down to sending what we have and listening for an ACK - * every once in a while. + * Our support for ACK extensions is simply to parse them. On + * the first ACK we will accept that as enough common + * objects. We give up if we haven't found an answer in the + * first 256 we send. */ i = 0; - while (true) { + while (i < 256) { error = git_revwalk_next(&oid, walk); if (error < 0) { -- cgit v1.2.1 From 968c7d072ae61852564a831706ca5e969a2eb62c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 26 Oct 2013 17:35:12 +0200 Subject: remote: create FETCH_HEAD with a refspecless remote When downloading the default branch due to lack of refspecs, we still need to write out FETCH_HEAD with the tip we downloaded, unfortunately with a format that doesn't match what we already have. --- src/fetchhead.c | 6 ++++++ src/remote.c | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/fetchhead.c b/src/fetchhead.c index 4dcebb857..77aafc8f3 100644 --- a/src/fetchhead.c +++ b/src/fetchhead.c @@ -74,6 +74,7 @@ static int fetchhead_ref_write( { char oid[GIT_OID_HEXSZ + 1]; const char *type, *name; + int head = 0; assert(file && fetchhead_ref); @@ -87,11 +88,16 @@ static int fetchhead_ref_write( GIT_REFS_TAGS_DIR) == 0) { type = "tag "; name = fetchhead_ref->ref_name + strlen(GIT_REFS_TAGS_DIR); + } else if (!git__strcmp(fetchhead_ref->ref_name, GIT_HEAD_FILE)) { + head = 1; } else { type = ""; name = fetchhead_ref->ref_name; } + if (head) + return git_filebuf_printf(file, "%s\t\t%s\n", oid, fetchhead_ref->remote_url); + return git_filebuf_printf(file, "%s\t%s\t%s'%s' of %s\n", oid, (fetchhead_ref->is_merge) ? "" : "not-for-merge", diff --git a/src/remote.c b/src/remote.c index 3528b1c46..2b611aabc 100644 --- a/src/remote.c +++ b/src/remote.c @@ -1032,6 +1032,27 @@ int git_remote_update_tips(git_remote *remote) goto out; } + /* If we have no refspecs, update HEAD -> FETCH_HEAD manually */ + if (remote->refspecs.length == 0 && refs.length > 0 && git_remote_update_fetchhead(remote)) { + git_vector vec; + git_refspec headspec; + + if (git_refspec__parse(&headspec, "HEAD", true) < 0) + goto out; + + if (git_vector_init(&vec, 1, NULL) < 0) { + goto out; + } + + if (git_vector_insert(&vec, git_vector_get(&refs, 0)) < 0) { + git_vector_free(&vec); + goto out; + } + + error = git_remote_write_fetchhead(remote, &headspec, &vec); + git_vector_free(&vec); + } + out: git_refspec__free(&tagspec); git_vector_free(&refs); -- cgit v1.2.1 From af613ecd445bf0abfda81769e7a2d763413dfd04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 28 Oct 2013 23:30:45 +0100 Subject: remote: store dwimed refspecs separately This allows us to add e.g. "HEAD" as a refspec when none are given without overwriting the user's data. --- src/fetch.c | 22 ++++---- src/refspec.c | 68 ++++++++++++++++++++++++ src/refspec.h | 8 ++- src/remote.c | 111 +++++++++++++--------------------------- src/remote.h | 1 + src/transports/smart_protocol.c | 8 +-- 6 files changed, 128 insertions(+), 90 deletions(-) diff --git a/src/fetch.c b/src/fetch.c index e83dc4add..295b036ef 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -23,7 +23,6 @@ struct filter_payload { git_remote *remote; const git_refspec *spec, *tagspec; git_odb *odb; - int want_head; }; static int filter_ref__cb(git_remote_head *head, void *payload) @@ -34,9 +33,7 @@ static int filter_ref__cb(git_remote_head *head, void *payload) if (!git_reference_is_valid_name(head->name)) return 0; - if ((strcmp(head->name, GIT_HEAD_FILE) == 0) && p->want_head) { - match = 1; - } else if (p->remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { + if (p->remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { /* * If tagopt is --tags, then we only use the default * tags refspec and ignore the remote's @@ -63,10 +60,10 @@ static int filter_ref__cb(git_remote_head *head, void *payload) static int filter_wants(git_remote *remote) { struct filter_payload p; - git_refspec tagspec; + git_refspec tagspec, head; int error = -1; - git_vector_clear(&remote->refs); + //git_vector_clear(&remote->refs); if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0) return error; @@ -78,8 +75,15 @@ static int filter_wants(git_remote *remote) */ p.tagspec = &tagspec; p.remote = remote; - if (remote->refspecs.length == 0) - p.want_head = 1; + if (remote->active_refspecs.length == 0) { + if ((error = git_refspec__parse(&head, "HEAD", true)) < 0) + goto cleanup; + + if ((error = git_refspec__dwim_one(&remote->active_refspecs, &head, &remote->refs)) < 0) + goto cleanup; + } + + git_vector_clear(&remote->refs); if (git_repository_odb__weakptr(&p.odb, remote->repo) < 0) goto cleanup; @@ -107,7 +111,7 @@ int git_fetch_negotiate(git_remote *remote) } /* Don't try to negotiate when we don't want anything */ - if (remote->refs.length == 0 || !remote->need_pack) + if (!remote->need_pack) return 0; /* diff --git a/src/refspec.c b/src/refspec.c index 492c6ed3f..a97340071 100644 --- a/src/refspec.c +++ b/src/refspec.c @@ -12,6 +12,7 @@ #include "util.h" #include "posix.h" #include "refs.h" +#include "vector.h" int git_refspec__parse(git_refspec *refspec, const char *input, bool is_fetch) { @@ -287,3 +288,70 @@ git_direction git_refspec_direction(const git_refspec *spec) return spec->push; } + +int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs) +{ + git_buf buf = GIT_BUF_INIT; + size_t j, pos; + git_remote_head key; + + const char* formatters[] = { + GIT_REFS_DIR "%s", + GIT_REFS_TAGS_DIR "%s", + GIT_REFS_HEADS_DIR "%s", + NULL + }; + + git_refspec *cur = git__calloc(1, sizeof(git_refspec)); + GITERR_CHECK_ALLOC(cur); + + cur->force = spec->force; + cur->push = spec->push; + cur->pattern = spec->pattern; + cur->matching = spec->matching; + cur->string = git__strdup(spec->string); + + /* shorthand on the lhs */ + if (git__prefixcmp(spec->src, GIT_REFS_DIR)) { + for (j = 0; formatters[j]; j++) { + git_buf_clear(&buf); + if (git_buf_printf(&buf, formatters[j], spec->src) < 0) + return -1; + + key.name = (char *) git_buf_cstr(&buf); + if (!git_vector_search(&pos, refs, &key)) { + /* we found something to match the shorthand, set src to that */ + cur->src = git_buf_detach(&buf); + } + } + } + + /* No shorthands found, copy over the name */ + if (cur->src == NULL && spec->src != NULL) { + cur->src = git__strdup(spec->src); + GITERR_CHECK_ALLOC(cur->src); + } + + if (spec->dst && git__prefixcmp(spec->dst, GIT_REFS_DIR)) { + /* if it starts with "remotes" then we just prepend "refs/" */ + if (!git__prefixcmp(spec->dst, "remotes/")) { + git_buf_puts(&buf, GIT_REFS_DIR); + } else { + git_buf_puts(&buf, GIT_REFS_HEADS_DIR); + } + + if (git_buf_puts(&buf, spec->dst) < 0) + return -1; + + cur->dst = git_buf_detach(&buf); + } + + git_buf_free(&buf); + + if (cur->dst == NULL && spec->dst != NULL) { + cur->dst = git__strdup(spec->dst); + GITERR_CHECK_ALLOC(cur->dst); + } + + return git_vector_insert(out, cur); +} diff --git a/src/refspec.h b/src/refspec.h index 44d484c7b..51b7bfee9 100644 --- a/src/refspec.h +++ b/src/refspec.h @@ -9,6 +9,7 @@ #include "git2/refspec.h" #include "buffer.h" +#include "vector.h" struct git_refspec { char *string; @@ -17,7 +18,6 @@ struct git_refspec { unsigned int force :1, push : 1, pattern :1, - dwim :1, matching :1; }; @@ -63,4 +63,10 @@ int git_refspec__serialize(git_buf *out, const git_refspec *refspec); */ int git_refspec_is_wildcard(const git_refspec *spec); +/** + * DWIM `spec` with `refs` existing on the remote, append the dwim'ed + * result in `out`. + */ +int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs); + #endif diff --git a/src/remote.c b/src/remote.c index 2b611aabc..49de5fa25 100644 --- a/src/remote.c +++ b/src/remote.c @@ -19,6 +19,8 @@ #include "refspec.h" #include "fetchhead.h" +static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs); + static int add_refspec(git_remote *remote, const char *string, bool is_fetch) { git_refspec *spec; @@ -288,7 +290,8 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name) GITERR_CHECK_ALLOC(remote->name); if ((git_vector_init(&remote->refs, 32, NULL) < 0) || - (git_vector_init(&remote->refspecs, 2, NULL))) { + (git_vector_init(&remote->refspecs, 2, NULL) < 0) || + (git_vector_init(&remote->active_refspecs, 2, NULL) < 0)) { error = -1; goto cleanup; } @@ -347,6 +350,10 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name) if (download_tags_value(remote, config) < 0) goto cleanup; + /* Move the data over to where the matching functions can find them */ + if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs) < 0) + goto cleanup; + *out = remote; cleanup: @@ -684,60 +691,31 @@ static int store_refs(git_remote_head *head, void *payload) return git_vector_insert(refs, head); } -static int dwim_refspecs(git_vector *refspecs, git_vector *refs) +/* DWIM `refspecs` based on `refs` and append the output to `out` */ +static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs) { - git_buf buf = GIT_BUF_INIT; + size_t i; git_refspec *spec; - size_t i, j, pos; - git_remote_head key; - - const char* formatters[] = { - GIT_REFS_DIR "%s", - GIT_REFS_TAGS_DIR "%s", - GIT_REFS_HEADS_DIR "%s", - NULL - }; git_vector_foreach(refspecs, i, spec) { - if (spec->dwim) - continue; - - /* shorthand on the lhs */ - if (git__prefixcmp(spec->src, GIT_REFS_DIR)) { - for (j = 0; formatters[j]; j++) { - git_buf_clear(&buf); - if (git_buf_printf(&buf, formatters[j], spec->src) < 0) - return -1; - - key.name = (char *) git_buf_cstr(&buf); - if (!git_vector_search(&pos, refs, &key)) { - /* we found something to match the shorthand, set src to that */ - git__free(spec->src); - spec->src = git_buf_detach(&buf); - } - } - } - - if (spec->dst && git__prefixcmp(spec->dst, GIT_REFS_DIR)) { - /* if it starts with "remotes" then we just prepend "refs/" */ - if (!git__prefixcmp(spec->dst, "remotes/")) { - git_buf_puts(&buf, GIT_REFS_DIR); - } else { - git_buf_puts(&buf, GIT_REFS_HEADS_DIR); - } + if (git_refspec__dwim_one(out, spec, refs) < 0) + return -1; + } - if (git_buf_puts(&buf, spec->dst) < 0) - return -1; + return 0; +} - git__free(spec->dst); - spec->dst = git_buf_detach(&buf); - } +static void free_refspecs(git_vector *vec) +{ + size_t i; + git_refspec *spec; - spec->dwim = 1; + git_vector_foreach(vec, i, spec) { + git_refspec__free(spec); + git__free(spec); } - git_buf_free(&buf); - return 0; + git_vector_clear(vec); } static int remote_head_cmp(const void *_a, const void *_b) @@ -755,14 +733,16 @@ int git_remote_download(git_remote *remote) assert(remote); - if (git_vector_init(&refs, 16, remote_head_cmp) < 0) + if (git_vector_init(&refs, 8, remote_head_cmp) < 0) return -1; if (git_remote_ls(remote, store_refs, &refs) < 0) { return -1; } - error = dwim_refspecs(&remote->refspecs, &refs); + free_refspecs(&remote->active_refspecs); + + error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &refs); git_vector_free(&refs); if (error < 0) return -1; @@ -1024,7 +1004,7 @@ int git_remote_update_tips(git_remote *remote) goto out; } - git_vector_foreach(&remote->refspecs, i, spec) { + git_vector_foreach(&remote->active_refspecs, i, spec) { if (spec->push) continue; @@ -1032,27 +1012,6 @@ int git_remote_update_tips(git_remote *remote) goto out; } - /* If we have no refspecs, update HEAD -> FETCH_HEAD manually */ - if (remote->refspecs.length == 0 && refs.length > 0 && git_remote_update_fetchhead(remote)) { - git_vector vec; - git_refspec headspec; - - if (git_refspec__parse(&headspec, "HEAD", true) < 0) - goto out; - - if (git_vector_init(&vec, 1, NULL) < 0) { - goto out; - } - - if (git_vector_insert(&vec, git_vector_get(&refs, 0)) < 0) { - git_vector_free(&vec); - goto out; - } - - error = git_remote_write_fetchhead(remote, &headspec, &vec); - git_vector_free(&vec); - } - out: git_refspec__free(&tagspec); git_vector_free(&refs); @@ -1103,12 +1062,12 @@ void git_remote_free(git_remote *remote) git_vector_free(&remote->refs); - git_vector_foreach(&remote->refspecs, i, spec) { - git_refspec__free(spec); - git__free(spec); - } + free_refspecs(&remote->refspecs); git_vector_free(&remote->refspecs); + free_refspecs(&remote->active_refspecs); + git_vector_free(&remote->active_refspecs); + git__free(remote->url); git__free(remote->pushurl); git__free(remote->name); @@ -1517,7 +1476,7 @@ git_refspec *git_remote__matching_refspec(git_remote *remote, const char *refnam git_refspec *spec; size_t i; - git_vector_foreach(&remote->refspecs, i, spec) { + git_vector_foreach(&remote->active_refspecs, i, spec) { if (spec->push) continue; @@ -1533,7 +1492,7 @@ git_refspec *git_remote__matching_dst_refspec(git_remote *remote, const char *re git_refspec *spec; size_t i; - git_vector_foreach(&remote->refspecs, i, spec) { + git_vector_foreach(&remote->active_refspecs, i, spec) { if (spec->push) continue; diff --git a/src/remote.h b/src/remote.h index 269584d96..33e4d68f8 100644 --- a/src/remote.h +++ b/src/remote.h @@ -21,6 +21,7 @@ struct git_remote { char *pushurl; git_vector refs; git_vector refspecs; + git_vector active_refspecs; git_transport *transport; git_repository *repo; git_remote_callbacks callbacks; diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 5d7b9bcba..ce3f115ee 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -269,7 +269,7 @@ static int wait_while_ack(gitno_buffer *buf) return 0; } -int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_remote_head * const *refs, size_t count) +int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_remote_head * const *wants, size_t count) { transport_smart *t = (transport_smart *)transport; gitno_buffer *buf = &t->buffer; @@ -279,7 +279,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c unsigned int i; git_oid oid; - if ((error = git_pkt_buffer_wants(refs, count, &t->caps, &data)) < 0) + if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0) return error; if ((error = fetch_setup_walk(&walk, repo)) < 0) @@ -350,7 +350,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c git_pkt_ack *pkt; unsigned int i; - if ((error = git_pkt_buffer_wants(refs, count, &t->caps, &data)) < 0) + if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0) goto on_error; git_vector_foreach(&t->common, i, pkt) { @@ -370,7 +370,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c git_pkt_ack *pkt; unsigned int i; - if ((error = git_pkt_buffer_wants(refs, count, &t->caps, &data)) < 0) + if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0) goto on_error; git_vector_foreach(&t->common, i, pkt) { -- cgit v1.2.1 From 7e0359084ef0faba8f458f9cccad2dc8f5baf800 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 1 Nov 2013 15:29:25 -0700 Subject: Streamline url-parsing logic. --- src/netops.c | 50 +++++++++++++++++++++---------------------- tests-clar/network/urlparse.c | 10 +++++++++ 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/netops.c b/src/netops.c index 7e13f12e7..0bf3a8f13 100644 --- a/src/netops.c +++ b/src/netops.c @@ -668,47 +668,47 @@ int gitno_extract_url_parts( const char *url, const char *default_port) { - char *colon, *slash, *at, *end; - const char *start; + char *colon, *slash, *at; /* * ==> [user[:pass]@]hostname.tld[:port]/resource */ - colon = strchr(url, ':'); - slash = strchr(url, '/'); + /* Check for user and maybe password */ at = strchr(url, '@'); + if (at) { + colon = strchr(url, ':'); + if (colon && colon < at) { + /* user:pass */ + *username = git__substrdup(url, colon-url); + *password = git__substrdup(colon+1, at-colon-1); + GITERR_CHECK_ALLOC(*password); + } else { + *username = git__substrdup(url, at-url); + } + GITERR_CHECK_ALLOC(*username); + url = at + 1; + } + /* Validate URL format. Colons shouldn't be in the path part. */ + slash = strchr(url, '/'); + colon = strchr(url, ':'); if (!slash || (colon && (slash < colon))) { giterr_set(GITERR_NET, "Malformed URL"); return GIT_EINVALIDSPEC; } - start = url; - if (at && at < slash) { - start = at+1; - *username = git__substrdup(url, at - url); - } - - if (colon && colon < at) { - git__free(*username); - *username = git__substrdup(url, colon-url); - *password = git__substrdup(colon+1, at-colon-1); - colon = strchr(at, ':'); - } - - if (colon == NULL) { - *port = git__strdup(default_port); + /* Check for hostname and maybe port */ + if (colon) { + *host = git__substrdup(url, colon-url); + *port = git__substrdup(colon+1, slash-colon-1); } else { - *port = git__substrdup(colon + 1, slash - colon - 1); + *host = git__substrdup(url, slash-url); + *port = git__strdup(default_port); } - GITERR_CHECK_ALLOC(*port); - - end = colon == NULL ? slash : colon; - - *host = git__substrdup(start, end - start); GITERR_CHECK_ALLOC(*host); + GITERR_CHECK_ALLOC(*port); return 0; } diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c index 15e841b35..9fc304a07 100644 --- a/tests-clar/network/urlparse.c +++ b/tests-clar/network/urlparse.c @@ -38,6 +38,16 @@ void test_network_urlparse__bad_url(void) GIT_EINVALIDSPEC); } +void test_network_urlparse__weird_url(void) +{ + cl_git_pass(gitno_extract_url_parts(&host, &port, &user, &pass, + "arrbee:my/bad:password@github.com:1111/strange/words.git", "1")); + cl_assert_equal_s(host, "github.com"); + cl_assert_equal_s(port, "1111"); + cl_assert_equal_s(user, "arrbee"); + cl_assert_equal_s(pass, "my/bad:password"); +} + void test_network_urlparse__user(void) { cl_git_pass(gitno_extract_url_parts(&host, &port, &user, &pass, -- cgit v1.2.1 From 56c1cda28a4b33fb305d99a2c7985a37efd3839d Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 1 Nov 2013 19:22:43 -0700 Subject: Clarify parsing issues and errors --- src/netops.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/netops.c b/src/netops.c index 0bf3a8f13..d2acdb240 100644 --- a/src/netops.c +++ b/src/netops.c @@ -674,7 +674,8 @@ int gitno_extract_url_parts( * ==> [user[:pass]@]hostname.tld[:port]/resource */ - /* Check for user and maybe password */ + /* Check for user and maybe password. Note that this deviates from RFC-1738 + * in that it allows non-encoded colons in the password field. */ at = strchr(url, '@'); if (at) { colon = strchr(url, ':'); @@ -695,7 +696,7 @@ int gitno_extract_url_parts( colon = strchr(url, ':'); if (!slash || (colon && (slash < colon))) { - giterr_set(GITERR_NET, "Malformed URL"); + giterr_set(GITERR_NET, "Malformed URL: %s", url); return GIT_EINVALIDSPEC; } -- cgit v1.2.1 From 10749f6ca25179778cf60e411f7de3de1444271d Mon Sep 17 00:00:00 2001 From: Sascha Cunz Date: Sat, 2 Nov 2013 03:20:05 +0000 Subject: Checkout: Unifiy const-ness of `opts` parameter Since all 3 checkout APIs perform the same operation with the options, all of them should use the same const-ness. --- include/git2/checkout.h | 4 ++-- src/checkout.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/git2/checkout.h b/include/git2/checkout.h index 3793a4f18..4c6a4ebf7 100644 --- a/include/git2/checkout.h +++ b/include/git2/checkout.h @@ -272,7 +272,7 @@ GIT_EXTERN(int) git_checkout_head( GIT_EXTERN(int) git_checkout_index( git_repository *repo, git_index *index, - git_checkout_opts *opts); + const git_checkout_opts *opts); /** * Updates files in the index and working tree to match the content of the @@ -288,7 +288,7 @@ GIT_EXTERN(int) git_checkout_index( GIT_EXTERN(int) git_checkout_tree( git_repository *repo, const git_object *treeish, - git_checkout_opts *opts); + const git_checkout_opts *opts); /** @} */ GIT_END_DECL diff --git a/src/checkout.c b/src/checkout.c index 76edc6a72..20b964b54 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -2018,7 +2018,7 @@ cleanup: int git_checkout_index( git_repository *repo, git_index *index, - git_checkout_opts *opts) + const git_checkout_opts *opts) { int error; git_iterator *index_i; @@ -2053,7 +2053,7 @@ int git_checkout_index( int git_checkout_tree( git_repository *repo, const git_object *treeish, - git_checkout_opts *opts) + const git_checkout_opts *opts) { int error; git_tree *tree = NULL; -- cgit v1.2.1 From 352214416c0e5fd85ef02077ddf185103f3a92df Mon Sep 17 00:00:00 2001 From: Sascha Cunz Date: Sat, 2 Nov 2013 03:43:34 +0000 Subject: Checkout: Don't assert if treeish is NULL In git_checkout_tree, the first check tests if either repo or treeish is NULL and says that eithor of them has to have a valid value. But there is no code to handle the treeish == NULL case. So, do something meaningful in that case: use HEAD instead. --- include/git2/checkout.h | 2 +- src/checkout.c | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/include/git2/checkout.h b/include/git2/checkout.h index 4c6a4ebf7..efafdc3e4 100644 --- a/include/git2/checkout.h +++ b/include/git2/checkout.h @@ -280,7 +280,7 @@ GIT_EXTERN(int) git_checkout_index( * * @param repo repository to check out (must be non-bare) * @param treeish a commit, tag or tree which content will be used to update - * the working directory + * the working directory (or NULL to use HEAD) * @param opts specifies checkout options (may be NULL) * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information * about the error) diff --git a/src/checkout.c b/src/checkout.c index 20b964b54..d818a44bf 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -2073,10 +2073,21 @@ int git_checkout_tree( if (!repo) repo = git_object_owner(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"); - return -1; + 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"); + return -1; + } + } + else { + if ((error = checkout_lookup_head_tree(&tree, repo)) < 0) { + if (error != GIT_EUNBORNBRANCH) + giterr_set( + GITERR_CHECKOUT, + "HEAD could not be peeled to a tree and no treeish given"); + return error; + } } if (!(error = git_iterator_for_tree(&tree_i, tree, 0, NULL, NULL))) -- cgit v1.2.1 From 7b3959b22784d63dd6f21bc250602b886d726294 Mon Sep 17 00:00:00 2001 From: Sascha Cunz Date: Sat, 2 Nov 2013 03:45:32 +0000 Subject: Checkout: git_checkout_head is git_checkout_tree without a treeish The last commit taught git_checkout_tree to actually do something meaningfull, when treeish was NULL. This lets us rewrite git_checkout_head to simply call git_checkout_tree without giving it a treeish. --- src/checkout.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/checkout.c b/src/checkout.c index d818a44bf..376d48b86 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -2103,18 +2103,6 @@ int git_checkout_head( git_repository *repo, const git_checkout_opts *opts) { - int error; - git_tree *head = NULL; - git_iterator *head_i = NULL; - assert(repo); - - if (!(error = checkout_lookup_head_tree(&head, repo)) && - !(error = git_iterator_for_tree(&head_i, head, 0, NULL, NULL))) - error = git_checkout_iterator(head_i, opts); - - git_iterator_free(head_i); - git_tree_free(head); - - return error; + return git_checkout_tree(repo, NULL, opts); } -- cgit v1.2.1 From 6cb831bd5667d934d8947279523cb235b4f8bba4 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Sat, 2 Nov 2013 05:33:26 -0700 Subject: Replace copyright topmatter in example files --- examples/add.c | 13 ++++++++++--- examples/cat-file.c | 13 ++++++++++--- examples/common.c | 13 ++++++++++--- examples/common.h | 13 ++++++++++--- examples/diff.c | 13 ++++++++++--- examples/general.c | 14 ++++++++++++++ examples/init.c | 13 ++++++++++--- examples/log.c | 13 ++++++++++--- examples/rev-list.c | 14 +++++++++++--- examples/rev-parse.c | 13 ++++++++++--- examples/showindex.c | 13 ++++++++++--- examples/status.c | 13 ++++++++++--- 12 files changed, 125 insertions(+), 33 deletions(-) diff --git a/examples/add.c b/examples/add.c index 999a41e64..336596bde 100644 --- a/examples/add.c +++ b/examples/add.c @@ -1,8 +1,15 @@ /* - * Copyright (C) the libgit2 contributors. All rights reserved. + * libgit2 "add" example - shows how to modify the index * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . */ #include "common.h" diff --git a/examples/cat-file.c b/examples/cat-file.c index 5e547628a..fa6add07b 100644 --- a/examples/cat-file.c +++ b/examples/cat-file.c @@ -1,8 +1,15 @@ /* - * Copyright (C) the libgit2 contributors. All rights reserved. + * libgit2 "cat-file" example - shows how to print data from the ODB * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . */ #include "common.h" diff --git a/examples/common.c b/examples/common.c index 5972bc5c7..12dbccf59 100644 --- a/examples/common.c +++ b/examples/common.c @@ -1,8 +1,15 @@ /* - * Copyright (C) the libgit2 contributors. All rights reserved. + * Utilities library for libgit2 examples * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . */ #include "common.h" diff --git a/examples/common.h b/examples/common.h index 5ffc9c8eb..2fd7d579f 100644 --- a/examples/common.h +++ b/examples/common.h @@ -1,8 +1,15 @@ /* - * Copyright (C) the libgit2 contributors. All rights reserved. + * Utilities library for libgit2 examples * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . */ #include diff --git a/examples/diff.c b/examples/diff.c index b1415648a..daf5d7030 100644 --- a/examples/diff.c +++ b/examples/diff.c @@ -1,8 +1,15 @@ /* - * Copyright (C) the libgit2 contributors. All rights reserved. + * libgit2 "diff" example - shows how to use the diff API * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . */ #include "common.h" diff --git a/examples/general.c b/examples/general.c index d7a58479c..f23dccb47 100644 --- a/examples/general.c +++ b/examples/general.c @@ -1,3 +1,17 @@ +/* + * libgit2 "general" example - shows basic libgit2 concepts + * + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . + */ + // [**libgit2**][lg] is a portable, pure C implementation of the Git core // methods provided as a re-entrant linkable library with a solid API, // allowing you to write native speed custom Git applications in any diff --git a/examples/init.c b/examples/init.c index 1c371252e..0e823ab81 100644 --- a/examples/init.c +++ b/examples/init.c @@ -1,8 +1,15 @@ /* - * Copyright (C) the libgit2 contributors. All rights reserved. + * libgit2 "init" example - shows how to initialize a new repo * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . */ #include "common.h" diff --git a/examples/log.c b/examples/log.c index a36d4c95e..471c5ff96 100644 --- a/examples/log.c +++ b/examples/log.c @@ -1,8 +1,15 @@ /* - * Copyright (C) the libgit2 contributors. All rights reserved. + * libgit2 "log" example - shows how to walk history and get commit info * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . */ #include "common.h" diff --git a/examples/rev-list.c b/examples/rev-list.c index 9330c644c..5c0d751a3 100644 --- a/examples/rev-list.c +++ b/examples/rev-list.c @@ -1,8 +1,16 @@ /* - * Copyright (C) the libgit2 contributors. All rights reserved. + * libgit2 "rev-list" example - shows how to transform a rev-spec into a list + * of commit ids * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . */ #include "common.h" diff --git a/examples/rev-parse.c b/examples/rev-parse.c index 64a02fe6e..a24833767 100644 --- a/examples/rev-parse.c +++ b/examples/rev-parse.c @@ -1,8 +1,15 @@ /* - * Copyright (C) the libgit2 contributors. All rights reserved. + * libgit2 "rev-parse" example - shows how to parse revspecs * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . */ #include "common.h" diff --git a/examples/showindex.c b/examples/showindex.c index bf852384c..de463e266 100644 --- a/examples/showindex.c +++ b/examples/showindex.c @@ -1,8 +1,15 @@ /* - * Copyright (C) the libgit2 contributors. All rights reserved. + * libgit2 "showindex" example - shows how to extract data from the index * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . */ #include "common.h" diff --git a/examples/status.c b/examples/status.c index 459e6fafb..e2e2b6026 100644 --- a/examples/status.c +++ b/examples/status.c @@ -1,8 +1,15 @@ /* - * Copyright (C) the libgit2 contributors. All rights reserved. + * libgit2 "status" example - shows how to use the status APIs * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . */ #include "common.h" -- cgit v1.2.1 From 187009e253efa54f6db690a16504adf7f2c32d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 2 Nov 2013 18:34:51 +0100 Subject: Fix a leak in the diff tests --- tests-clar/diff/workdir.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index e72acdb03..60acd365d 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -1302,6 +1302,7 @@ void test_diff_workdir__patience_diff(void) "When I wrote this\nI did not know\nhow to create\na patience diff\nI did not know\nhow to create\nanother problem\nI did not know\nhow to create\na minimal diff\n"); cl_git_pass(git_index_add_bypath(index, "test.txt")); cl_repo_commit_from_index(NULL, g_repo, NULL, 1372350000, "Base"); + git_index_free(index); cl_git_rewritefile( "empty_standard_repo/test.txt", -- cgit v1.2.1 From a7a64d2cadade53175ba27c1a29023278bdc4288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 2 Nov 2013 18:36:34 +0100 Subject: remote: don't write too much when dealing with multivars We used to move `data_start` forward, which is wrong as that needs to point to the beginning of the buffer in order to perform size calculations. Introduce a `write_start` variable which indicates where we should start writing from, which is what the `data_start` was being wrongly reused to be. --- src/config_file.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 6abf60621..c7fc32060 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -1185,7 +1185,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p { int result, c; int section_matches = 0, last_section_matched = 0, preg_replaced = 0, write_trailer = 0; - const char *pre_end = NULL, *post_start = NULL, *data_start; + const char *pre_end = NULL, *post_start = NULL, *data_start, *write_start; char *current_section = NULL, *section, *name, *ldot; git_filebuf file = GIT_FILEBUF_INIT; struct reader *reader = git_array_get(cfg->readers, 0); @@ -1207,6 +1207,8 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p return -1; /* OS error when reading the file */ } + write_start = data_start; + /* Lock the file */ if (git_filebuf_open(&file, cfg->file_path, 0) < 0) return -1; @@ -1291,7 +1293,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p /* We've found the variable we wanted to change, so * write anything up to it */ - git_filebuf_write(&file, data_start, pre_end - data_start); + git_filebuf_write(&file, write_start, pre_end - write_start); preg_replaced = 1; /* Then replace the variable. If the value is NULL, it @@ -1300,9 +1302,13 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p git_filebuf_printf(&file, "\t%s = %s\n", name, value); } - /* multiline variable? we need to keep reading lines to match */ - if (preg != NULL && section_matches) { - data_start = post_start; + /* + * If we have a multivar, we should keep looking for entries, + * but only if we're in the right section. Otherwise we'll end up + * looping on the edge of a matching and a non-matching section. + */ + if (section_matches && preg != NULL) { + write_start = post_start; continue; } @@ -1332,7 +1338,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p git_filebuf_write(&file, post_start, reader->buffer.size - (post_start - data_start)); } else { if (preg_replaced) { - git_filebuf_printf(&file, "\n%s", data_start); + git_filebuf_printf(&file, "\n%s", write_start); } else { git_filebuf_write(&file, reader->buffer.ptr, reader->buffer.size); -- cgit v1.2.1 From becb13c0f04c4ba54cf27303136293dbf8abfd73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sun, 3 Nov 2013 13:46:07 +0100 Subject: examples: doc update Update the explanation to reflect our use of git_status_list_new() and make the breaks in rocco more meaningful. Clarify why GIT_STATUS_CURRENT and index_to_workdir don't always imply each other. Fixes #1740. --- examples/status.c | 58 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/examples/status.c b/examples/status.c index 459e6fafb..4a8b270c7 100644 --- a/examples/status.c +++ b/examples/status.c @@ -48,7 +48,7 @@ struct opts { static void parse_opts(struct opts *o, int argc, char *argv[]); static void show_branch(git_repository *repo, int format); -static void print_long(git_repository *repo, git_status_list *status); +static void print_long(git_status_list *status); static void print_short(git_repository *repo, git_status_list *status); int main(int argc, char *argv[]) @@ -80,13 +80,15 @@ int main(int argc, char *argv[]) /** * Run status on the repository * - * Because we want to simluate a full "git status" run and want to - * support some command line options, we use `git_status_foreach_ext()` - * instead of just the plain status call. This allows (a) iterating - * over the index and then the workdir and (b) extra flags that control - * which files are included. If you just want simple status (e.g. to - * enumerate files that are modified) then you probably don't need the - * extended API. + * We use `git_status_list_new()` to generate a list of status + * information which lets us iterate over it at our + * convenience and extract the data we want to show out of + * each entry. + * + * You can use `git_status_foreach()` or + * `git_status_foreach_ext()` if you'd prefer to execute a + * callback for each entry. The latter gives you more control + * about what results are presented. */ check_lg2(git_status_list_new(&status, repo, &o.statusopt), "Could not get status", NULL); @@ -95,7 +97,7 @@ int main(int argc, char *argv[]) show_branch(repo, o.format); if (o.format == FORMAT_LONG) - print_long(repo, status); + print_long(status); else print_short(repo, status); @@ -106,6 +108,10 @@ int main(int argc, char *argv[]) return 0; } +/** + * If the user asked for the branch, let's show the short name of the + * branch. + */ static void show_branch(git_repository *repo, int format) { int error = 0; @@ -117,9 +123,7 @@ static void show_branch(git_repository *repo, int format) if (error == GIT_EUNBORNBRANCH || error == GIT_ENOTFOUND) branch = NULL; else if (!error) { - branch = git_reference_name(head); - if (!strncmp(branch, "refs/heads/", strlen("refs/heads/"))) - branch += strlen("refs/heads/"); + branch = git_reference_shorthand(head); } else check_lg2(error, "failed to get current branch", NULL); @@ -132,7 +136,11 @@ static void show_branch(git_repository *repo, int format) git_reference_free(head); } -static void print_long(git_repository *repo, git_status_list *status) +/** + * This function print out an output similar to git's status command + * in long form, including the command-line hints. + */ +static void print_long(git_status_list *status) { size_t i, maxi = git_status_list_entrycount(status); const git_status_entry *s; @@ -140,8 +148,6 @@ static void print_long(git_repository *repo, git_status_list *status) int changed_in_workdir = 0, rm_in_workdir = 0; const char *old_path, *new_path; - (void)repo; - /** Print index changes. */ for (i = 0; i < maxi; ++i) { @@ -198,9 +204,15 @@ static void print_long(git_repository *repo, git_status_list *status) s = git_status_byindex(status, i); + /** + * With `GIT_STATUS_OPT_INCLUDE_UNMODIFIED` (not used in this example) + * `index_to_workdir` may not be `NULL` even if there are + * no differences, in which case it will be a `GIT_DELTA_UNMODIFIED`. + */ if (s->status == GIT_STATUS_CURRENT || s->index_to_workdir == NULL) continue; + /** Print out the output since we know the file has some changes */ if (s->status & GIT_STATUS_WT_MODIFIED) wstatus = "modified: "; if (s->status & GIT_STATUS_WT_DELETED) @@ -234,7 +246,6 @@ static void print_long(git_repository *repo, git_status_list *status) changed_in_workdir = 1; printf("#\n"); } - header = 0; /** Print untracked files. */ @@ -280,6 +291,10 @@ static void print_long(git_repository *repo, git_status_list *status) printf("no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"); } +/** + * This version of the output prefixes each path with two status + * columns and shows submodule status information. + */ static void print_short(git_repository *repo, git_status_list *status) { size_t i, maxi = git_status_list_entrycount(status); @@ -330,6 +345,10 @@ static void print_short(git_repository *repo, git_status_list *status) if (istatus == '?' && wstatus == '?') continue; + /** + * A commit in a tree is how submodules are stored, so + * let's go take a look at its status. + */ if (s->index_to_workdir && s->index_to_workdir->new_file.mode == GIT_FILEMODE_COMMIT) { @@ -351,6 +370,10 @@ static void print_short(git_repository *repo, git_status_list *status) } } + /** + * Now that we have all the information, it's time to format the output. + */ + if (s->head_to_index) { a = s->head_to_index->old_file.path; b = s->head_to_index->new_file.path; @@ -384,6 +407,9 @@ static void print_short(git_repository *repo, git_status_list *status) } } +/** + * Parse options that git's status command supports. + */ static void parse_opts(struct opts *o, int argc, char *argv[]) { struct args_info args = ARGS_INFO_INIT; -- cgit v1.2.1 From c227c173b84c8107a8933aeed947f16d82224377 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 4 Nov 2013 11:42:14 -0800 Subject: Use http_parser_parse_url to parse urls --- src/netops.c | 89 +++++++++++++++++++++---------------------- src/netops.h | 1 + src/transports/git.c | 72 +++++++++++++++------------------- src/transports/ssh.c | 1 - tests-clar/network/urlparse.c | 55 +++++++++++++------------- 5 files changed, 102 insertions(+), 116 deletions(-) diff --git a/src/netops.c b/src/netops.c index d2acdb240..9653344fe 100644 --- a/src/netops.c +++ b/src/netops.c @@ -32,6 +32,7 @@ #include "netops.h" #include "posix.h" #include "buffer.h" +#include "http_parser.h" #ifdef GIT_WIN32 static void net_set_error(const char *str) @@ -582,7 +583,7 @@ int gitno_connection_data_from_url( const char *service_suffix) { int error = -1; - const char *default_port = NULL; + const char *default_port = NULL, *path_search_start = NULL; char *original_host = NULL; /* service_suffix is optional */ @@ -594,22 +595,18 @@ int gitno_connection_data_from_url( gitno_connection_data_free_ptrs(data); if (!git__prefixcmp(url, prefix_http)) { - url = url + strlen(prefix_http); + path_search_start = url + strlen(prefix_http); default_port = "80"; if (data->use_ssl) { giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP is not allowed"); goto cleanup; } - } - - if (!git__prefixcmp(url, prefix_https)) { - url += strlen(prefix_https); + } else if (!git__prefixcmp(url, prefix_https)) { + path_search_start = url + strlen(prefix_https); default_port = "443"; data->use_ssl = true; - } - - if (url[0] == '/') + } else if (url[0] == '/') default_port = data->use_ssl ? "443" : "80"; if (!default_port) { @@ -618,18 +615,19 @@ int gitno_connection_data_from_url( } error = gitno_extract_url_parts( - &data->host, &data->port, &data->user, &data->pass, + &data->host, &data->port, &data->path, &data->user, &data->pass, url, default_port); if (url[0] == '/') { /* Relative redirect; reuse original host name and port */ + path_search_start = url; git__free(data->host); data->host = original_host; original_host = NULL; } if (!error) { - const char *path = strchr(url, '/'); + const char *path = strchr(path_search_start, '/'); size_t pathlen = strlen(path); size_t suffixlen = service_suffix ? strlen(service_suffix) : 0; @@ -663,53 +661,52 @@ void gitno_connection_data_free_ptrs(gitno_connection_data *d) int gitno_extract_url_parts( char **host, char **port, + char **path, char **username, char **password, const char *url, const char *default_port) { - char *colon, *slash, *at; - - /* - * ==> [user[:pass]@]hostname.tld[:port]/resource - */ + struct http_parser_url u = {0}; + const char *_host, *_port, *_path, *_userinfo; - /* Check for user and maybe password. Note that this deviates from RFC-1738 - * in that it allows non-encoded colons in the password field. */ - at = strchr(url, '@'); - if (at) { - colon = strchr(url, ':'); - if (colon && colon < at) { - /* user:pass */ - *username = git__substrdup(url, colon-url); - *password = git__substrdup(colon+1, at-colon-1); - GITERR_CHECK_ALLOC(*password); - } else { - *username = git__substrdup(url, at-url); - } - GITERR_CHECK_ALLOC(*username); - url = at + 1; + if (http_parser_parse_url(url, strlen(url), false, &u)) { + giterr_set(GITERR_NET, "Malformed URL '%s'", url); + return GIT_EINVALIDSPEC; } - /* Validate URL format. Colons shouldn't be in the path part. */ - slash = strchr(url, '/'); - colon = strchr(url, ':'); - if (!slash || - (colon && (slash < colon))) { - giterr_set(GITERR_NET, "Malformed URL: %s", url); - return GIT_EINVALIDSPEC; + _host = url+u.field_data[UF_HOST].off; + _port = url+u.field_data[UF_PORT].off; + _path = url+u.field_data[UF_PATH].off; + _userinfo = url+u.field_data[UF_USERINFO].off; + + if (u.field_data[UF_HOST].len) { + *host = git__substrdup(_host, u.field_data[UF_HOST].len); + GITERR_CHECK_ALLOC(*host); } - /* Check for hostname and maybe port */ - if (colon) { - *host = git__substrdup(url, colon-url); - *port = git__substrdup(colon+1, slash-colon-1); - } else { - *host = git__substrdup(url, slash-url); + if (u.field_data[UF_PORT].len) + *port = git__substrdup(_port, u.field_data[UF_PORT].len); + else *port = git__strdup(default_port); - } - GITERR_CHECK_ALLOC(*host); GITERR_CHECK_ALLOC(*port); + if (u.field_data[UF_PATH].len) { + *path = git__substrdup(_path, u.field_data[UF_PATH].len); + GITERR_CHECK_ALLOC(*path); + } + + if (u.field_data[UF_USERINFO].len) { + const char *colon = strchr(_userinfo, ':'); + if (colon && (colon - _userinfo) < u.field_data[UF_USERINFO].len) { + *username = git__substrdup(_userinfo, colon - _userinfo); + *password = git__substrdup(colon+1, u.field_data[UF_USERINFO].len - (colon+1-_userinfo)); + GITERR_CHECK_ALLOC(*password); + } else { + *username = git__substrdup(_userinfo, u.field_data[UF_USERINFO].len); + } + GITERR_CHECK_ALLOC(*username); + } + return 0; } diff --git a/src/netops.h b/src/netops.h index 5c105d6e3..666d66b12 100644 --- a/src/netops.h +++ b/src/netops.h @@ -92,6 +92,7 @@ void gitno_connection_data_free_ptrs(gitno_connection_data *data); int gitno_extract_url_parts( char **host, char **port, + char **path, char **username, char **password, const char *url, diff --git a/src/transports/git.c b/src/transports/git.c index 79a9e7dd4..5dcd4eff7 100644 --- a/src/transports/git.c +++ b/src/transports/git.c @@ -179,39 +179,33 @@ static int _git_uploadpack_ls( const char *url, git_smart_subtransport_stream **stream) { - char *host=NULL, *port=NULL, *user=NULL, *pass=NULL; + char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; + const char *stream_url = url; git_stream *s; + int error = -1; *stream = NULL; - if (!git__prefixcmp(url, prefix_git)) - url += strlen(prefix_git); + stream_url += strlen(prefix_git); - if (git_stream_alloc(t, url, cmd_uploadpack, stream) < 0) + if (git_stream_alloc(t, stream_url, cmd_uploadpack, stream) < 0) return -1; s = (git_stream *)*stream; - if (gitno_extract_url_parts(&host, &port, &user, &pass, url, GIT_DEFAULT_PORT) < 0) - goto on_error; - - if (gitno_connect(&s->socket, host, port, 0) < 0) - goto on_error; - - t->current_stream = s; - git__free(host); - git__free(port); - git__free(user); - git__free(pass); - return 0; + if (!(error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT))) { + if (!(error = gitno_connect(&s->socket, host, port, 0))) + t->current_stream = s; -on_error: - if (*stream) + git__free(host); + git__free(port); + git__free(path); + git__free(user); + git__free(pass); + } else if (*stream) git_stream_free(*stream); - git__free(host); - git__free(port); - return -1; + return error; } static int _git_uploadpack( @@ -235,39 +229,33 @@ static int _git_receivepack_ls( const char *url, git_smart_subtransport_stream **stream) { - char *host=NULL, *port=NULL, *user=NULL, *pass=NULL; + char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; + const char *stream_url = url; git_stream *s; + int error; *stream = NULL; - if (!git__prefixcmp(url, prefix_git)) - url += strlen(prefix_git); + stream_url += strlen(prefix_git); - if (git_stream_alloc(t, url, cmd_receivepack, stream) < 0) + if (git_stream_alloc(t, stream_url, cmd_receivepack, stream) < 0) return -1; s = (git_stream *)*stream; - if (gitno_extract_url_parts(&host, &port, &user, &pass, url, GIT_DEFAULT_PORT) < 0) - goto on_error; - - if (gitno_connect(&s->socket, host, port, 0) < 0) - goto on_error; - - t->current_stream = s; - git__free(host); - git__free(port); - git__free(user); - git__free(pass); - return 0; + if (!(error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT))) { + if (!(error = gitno_connect(&s->socket, host, port, 0))) + t->current_stream = s; -on_error: - if (*stream) + git__free(host); + git__free(port); + git__free(path); + git__free(user); + git__free(pass); + } else if (*stream) git_stream_free(*stream); - git__free(host); - git__free(port); - return -1; + return error; } static int _git_receivepack( diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 4e2834b49..db950e53d 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -330,7 +330,6 @@ static int _git_ssh_setup_conn( s = (ssh_stream *)*stream; if (!git__prefixcmp(url, prefix_ssh)) { - url = url + strlen(prefix_ssh); if (gitno_extract_url_parts(&host, &port, &user, &pass, url, default_port) < 0) goto on_error; } else { diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c index 9fc304a07..4babb0fa7 100644 --- a/tests-clar/network/urlparse.c +++ b/tests-clar/network/urlparse.c @@ -1,12 +1,12 @@ #include "clar_libgit2.h" #include "netops.h" -char *host, *port, *user, *pass; +char *host, *port, *path, *user, *pass; gitno_connection_data conndata; void test_network_urlparse__initialize(void) { - host = port = user = pass = NULL; + host = port = path = user = pass = NULL; memset(&conndata, 0, sizeof(conndata)); } @@ -15,6 +15,7 @@ void test_network_urlparse__cleanup(void) #define FREE_AND_NULL(x) if (x) { git__free(x); x = NULL; } FREE_AND_NULL(host); FREE_AND_NULL(port); + FREE_AND_NULL(path); FREE_AND_NULL(user); FREE_AND_NULL(pass); @@ -23,37 +24,33 @@ void test_network_urlparse__cleanup(void) void test_network_urlparse__trivial(void) { - cl_git_pass(gitno_extract_url_parts(&host, &port, &user, &pass, - "example.com/resource", "8080")); + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "http://example.com/resource", "8080")); cl_assert_equal_s(host, "example.com"); cl_assert_equal_s(port, "8080"); + cl_assert_equal_s(path, "/resource"); cl_assert_equal_p(user, NULL); cl_assert_equal_p(pass, NULL); } -void test_network_urlparse__bad_url(void) -{ - cl_git_fail_with(gitno_extract_url_parts(&host, &port, &user, &pass, - "github.com/git://github.com/foo/bar.git.git", "443"), - GIT_EINVALIDSPEC); -} - void test_network_urlparse__weird_url(void) { - cl_git_pass(gitno_extract_url_parts(&host, &port, &user, &pass, - "arrbee:my/bad:password@github.com:1111/strange/words.git", "1")); - cl_assert_equal_s(host, "github.com"); - cl_assert_equal_s(port, "1111"); - cl_assert_equal_s(user, "arrbee"); - cl_assert_equal_s(pass, "my/bad:password"); + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "https://user:pass%2fis%40bad@hostname.com:1234/", "1")); + cl_assert_equal_s(host, "hostname.com"); + cl_assert_equal_s(port, "1234"); + cl_assert_equal_s(path, "/"); + cl_assert_equal_s(user, "user"); + cl_assert_equal_s(pass, "pass%2fis%40bad"); } void test_network_urlparse__user(void) { - cl_git_pass(gitno_extract_url_parts(&host, &port, &user, &pass, - "user@example.com/resource", "8080")); + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "https://user@example.com/resource", "8080")); cl_assert_equal_s(host, "example.com"); cl_assert_equal_s(port, "8080"); + cl_assert_equal_s(path, "/resource"); cl_assert_equal_s(user, "user"); cl_assert_equal_p(pass, NULL); } @@ -61,10 +58,11 @@ void test_network_urlparse__user(void) void test_network_urlparse__user_pass(void) { /* user:pass@hostname.tld/resource */ - cl_git_pass(gitno_extract_url_parts(&host, &port, &user, &pass, - "user:pass@example.com/resource", "8080")); + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "https://user:pass@example.com/resource", "8080")); cl_assert_equal_s(host, "example.com"); cl_assert_equal_s(port, "8080"); + cl_assert_equal_s(path, "/resource"); cl_assert_equal_s(user, "user"); cl_assert_equal_s(pass, "pass"); } @@ -72,10 +70,11 @@ void test_network_urlparse__user_pass(void) void test_network_urlparse__port(void) { /* hostname.tld:port/resource */ - cl_git_pass(gitno_extract_url_parts(&host, &port, &user, &pass, - "example.com:9191/resource", "8080")); + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "https://example.com:9191/resource", "8080")); cl_assert_equal_s(host, "example.com"); cl_assert_equal_s(port, "9191"); + cl_assert_equal_s(path, "/resource"); cl_assert_equal_p(user, NULL); cl_assert_equal_p(pass, NULL); } @@ -83,10 +82,11 @@ void test_network_urlparse__port(void) void test_network_urlparse__user_port(void) { /* user@hostname.tld:port/resource */ - cl_git_pass(gitno_extract_url_parts(&host, &port, &user, &pass, - "user@example.com:9191/resource", "8080")); + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "https://user@example.com:9191/resource", "8080")); cl_assert_equal_s(host, "example.com"); cl_assert_equal_s(port, "9191"); + cl_assert_equal_s(path, "/resource"); cl_assert_equal_s(user, "user"); cl_assert_equal_p(pass, NULL); } @@ -94,10 +94,11 @@ void test_network_urlparse__user_port(void) void test_network_urlparse__user_pass_port(void) { /* user:pass@hostname.tld:port/resource */ - cl_git_pass(gitno_extract_url_parts(&host, &port, &user, &pass, - "user:pass@example.com:9191/resource", "8080")); + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "https://user:pass@example.com:9191/resource", "8080")); cl_assert_equal_s(host, "example.com"); cl_assert_equal_s(port, "9191"); + cl_assert_equal_s(path, "/resource"); cl_assert_equal_s(user, "user"); cl_assert_equal_s(pass, "pass"); } -- cgit v1.2.1 From dd64c71c2685d0b72b6f58149ecf2a972a6ea98b Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 4 Nov 2013 14:50:25 -0500 Subject: Allow backend consumers to specify file mode --- include/git2/odb_backend.h | 10 ++++++++- src/odb.c | 2 +- src/odb_loose.c | 20 ++++++++++++++---- tests-clar/odb/loose.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 6 deletions(-) diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index 1b3e2fd12..d3dd733a8 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -40,10 +40,18 @@ GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **out, const char *objects_ * @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 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 * * @return 0 or an error code */ -GIT_EXTERN(int) git_odb_backend_loose(git_odb_backend **out, const char *objects_dir, int compression_level, int do_fsync); +GIT_EXTERN(int) git_odb_backend_loose( + git_odb_backend **out, + const char *objects_dir, + int compression_level, + int do_fsync, + mode_t dir_mode, + mode_t file_mode); /** * Create a backend out of a single packfile diff --git a/src/odb.c b/src/odb.c index 2d6eda881..b208b279e 100644 --- a/src/odb.c +++ b/src/odb.c @@ -492,7 +492,7 @@ static int add_default_backends( #endif /* add the loose object backend */ - if (git_odb_backend_loose(&loose, objects_dir, -1, 0) < 0 || + if (git_odb_backend_loose(&loose, objects_dir, -1, 0, 0, 0) < 0 || add_backend_internal(db, loose, GIT_LOOSE_PRIORITY, as_alternates, inode) < 0) return -1; diff --git a/src/odb_loose.c b/src/odb_loose.c index 07dfae539..0dfd78aee 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -33,6 +33,8 @@ typedef struct loose_backend { int object_zlib_level; /** loose object zlib compression level. */ int fsync_object_files; /** loose object file fsync flag. */ + mode_t object_file_mode; + mode_t object_dir_mode; size_t objects_dirlen; char objects_dir[GIT_FLEX_ARRAY]; @@ -79,7 +81,7 @@ static int object_file_name( static int object_mkdir(const git_buf *name, const loose_backend *be) { return git_futils_mkdir( - name->ptr + be->objects_dirlen, be->objects_dir, GIT_OBJECT_DIR_MODE, + name->ptr + be->objects_dirlen, be->objects_dir, be->object_dir_mode, GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR); } @@ -787,7 +789,7 @@ static int loose_backend__stream_fwrite(git_odb_stream *_stream, const git_oid * error = -1; else error = git_filebuf_commit_at( - &stream->fbuf, final_path.ptr, GIT_OBJECT_FILE_MODE); + &stream->fbuf, final_path.ptr, backend->object_file_mode); git_buf_free(&final_path); @@ -876,7 +878,7 @@ static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, c if (object_file_name(&final_path, backend, oid) < 0 || object_mkdir(&final_path, backend) < 0 || - git_filebuf_commit_at(&fbuf, final_path.ptr, GIT_OBJECT_FILE_MODE) < 0) + git_filebuf_commit_at(&fbuf, final_path.ptr, backend->object_file_mode) < 0) error = -1; cleanup: @@ -899,7 +901,9 @@ int git_odb_backend_loose( git_odb_backend **backend_out, const char *objects_dir, int compression_level, - int do_fsync) + int do_fsync, + mode_t dir_mode, + mode_t file_mode) { loose_backend *backend; size_t objects_dirlen; @@ -920,8 +924,16 @@ int git_odb_backend_loose( if (compression_level < 0) compression_level = Z_BEST_SPEED; + if (dir_mode == 0) + dir_mode = GIT_OBJECT_DIR_MODE; + + if (file_mode == 0) + file_mode = GIT_OBJECT_FILE_MODE; + backend->object_zlib_level = compression_level; backend->fsync_object_files = do_fsync; + backend->object_dir_mode = dir_mode; + backend->object_file_mode = file_mode; backend->parent.read = &loose_backend__read; backend->parent.write = &loose_backend__write; diff --git a/tests-clar/odb/loose.c b/tests-clar/odb/loose.c index eb6b788b7..a85f1430d 100644 --- a/tests-clar/odb/loose.c +++ b/tests-clar/odb/loose.c @@ -1,5 +1,6 @@ #include "clar_libgit2.h" #include "odb.h" +#include "git2/odb_backend.h" #include "posix.h" #include "loose_data.h" @@ -92,3 +93,54 @@ void test_odb_loose__simple_reads(void) test_read_object(&two); test_read_object(&some); } + +void test_write_object_permission( + mode_t dir_mode, mode_t file_mode, + mode_t expected_dir_mode, mode_t expected_file_mode) +{ + git_odb *odb; + git_odb_backend *backend; + git_oid oid; + struct stat statbuf; + mode_t mask, os_mask; + + /* Windows does not return group/user bits from stat, + * files are never executable. + */ +#ifdef GIT_WIN32 + os_mask = 0600; +#else + os_mask = 0777; +#endif + + mask = p_umask(0); + p_umask(mask); + + cl_git_pass(git_odb_new(&odb)); + cl_git_pass(git_odb_backend_loose(&backend, "test-objects", -1, 0, dir_mode, file_mode)); + 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)); + + cl_git_pass(p_stat("test-objects/67", &statbuf)); + cl_assert_equal_i(statbuf.st_mode & os_mask, (expected_dir_mode & ~mask) & os_mask); + + cl_git_pass(p_stat("test-objects/67/b808feb36201507a77f85e6d898f0a2836e4a5", &statbuf)); + cl_assert_equal_i(statbuf.st_mode & os_mask, (expected_file_mode & ~mask) & os_mask); + + git_odb_free(odb); +} + +void test_odb_loose__permissions_standard(void) +{ + test_write_object_permission(0, 0, GIT_OBJECT_DIR_MODE, GIT_OBJECT_FILE_MODE); +} + +void test_odb_loose_permissions_readonly(void) +{ + test_write_object_permission(0777, 0444, 0777, 0444); +} + +void test_odb_loose__permissions_readwrite(void) +{ + test_write_object_permission(0777, 0666, 0777, 0666); +} -- cgit v1.2.1 From 16bffd1c26d8d22a61b5d99fd4063c2f71751317 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 4 Nov 2013 12:04:17 -0800 Subject: Unescape url-encoded usernames and passwords --- src/netops.c | 28 ++++++++++++++++++++++++++-- tests-clar/network/urlparse.c | 16 ++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/netops.c b/src/netops.c index 9653344fe..72172f39b 100644 --- a/src/netops.c +++ b/src/netops.c @@ -658,6 +658,29 @@ void gitno_connection_data_free_ptrs(gitno_connection_data *d) git__free(d->pass); d->pass = NULL; } +static char unescape_hex(char *x) +{ + char digit; + digit = ((x[0] >= 'A') ? ((x[0] & 0xdf) - 'A')+10 : (x[0] - '0')); + digit *= 16; + digit += ((x[1] >= 'A') ? ((x[1] & 0xdf) - 'A')+10 : (x[1] - '0')); + return digit; +} + +static char* unescape(char *str) +{ + int x, y; + + for (x=y=0; str[x]; ++x, ++y) { + if ((str[x] = str[y]) == '%') { + str[x] = unescape_hex(str+y+1); + y += 2; + } + } + str[x] = '\0'; + return str; +} + int gitno_extract_url_parts( char **host, char **port, @@ -699,13 +722,14 @@ int gitno_extract_url_parts( if (u.field_data[UF_USERINFO].len) { const char *colon = strchr(_userinfo, ':'); if (colon && (colon - _userinfo) < u.field_data[UF_USERINFO].len) { - *username = git__substrdup(_userinfo, colon - _userinfo); - *password = git__substrdup(colon+1, u.field_data[UF_USERINFO].len - (colon+1-_userinfo)); + *username = unescape(git__substrdup(_userinfo, colon - _userinfo)); + *password = unescape(git__substrdup(colon+1, u.field_data[UF_USERINFO].len - (colon+1-_userinfo))); GITERR_CHECK_ALLOC(*password); } else { *username = git__substrdup(_userinfo, u.field_data[UF_USERINFO].len); } GITERR_CHECK_ALLOC(*username); + } return 0; diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c index 4babb0fa7..3ec3a51a3 100644 --- a/tests-clar/network/urlparse.c +++ b/tests-clar/network/urlparse.c @@ -33,7 +33,7 @@ void test_network_urlparse__trivial(void) cl_assert_equal_p(pass, NULL); } -void test_network_urlparse__weird_url(void) +void test_network_urlparse__encoded_password(void) { cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, "https://user:pass%2fis%40bad@hostname.com:1234/", "1")); @@ -41,7 +41,7 @@ void test_network_urlparse__weird_url(void) cl_assert_equal_s(port, "1234"); cl_assert_equal_s(path, "/"); cl_assert_equal_s(user, "user"); - cl_assert_equal_s(pass, "pass%2fis%40bad"); + cl_assert_equal_s(pass, "pass/is@bad"); } void test_network_urlparse__user(void) @@ -127,6 +127,18 @@ void test_network_urlparse__connection_data_ssl(void) cl_assert_equal_i(conndata.use_ssl, true); } +void test_network_urlparse__encoded_username_password(void) +{ + cl_git_pass(gitno_connection_data_from_url(&conndata, + "https://user%2fname:pass%40word@example.com/foo/bar/baz", "bar/baz")); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/foo/"); + cl_assert_equal_s(conndata.user, "user/name"); + cl_assert_equal_s(conndata.pass, "pass@word"); + cl_assert_equal_i(conndata.use_ssl, true); +} + void test_network_urlparse__connection_data_cross_host_redirect(void) { conndata.host = git__strdup("bar.com"); -- cgit v1.2.1 From 2d1feaa2c7aef2e0d230e5535b214289c2c4a905 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 4 Nov 2013 15:03:44 -0800 Subject: Compile HTTP parser on win32 (for url parsing) --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a14abae0a..1d8e00cd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,6 +126,8 @@ INCLUDE_DIRECTORIES(src include) IF (WIN32 AND WINHTTP AND NOT MINGW) ADD_DEFINITIONS(-DGIT_WINHTTP) + INCLUDE_DIRECTORIES(deps/http-parser) + FILE(GLOB SRC_HTTP deps/http-parser/*.c deps/http-parser/*.h) ELSE () IF (NOT AMIGA) FIND_PACKAGE(OpenSSL) -- cgit v1.2.1 From b7bb086b1cc1348c0706ee4ec4b5524ae1f4eb97 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 4 Nov 2013 15:25:26 -0800 Subject: Standardize layout of blame sample --- examples/blame.c | 83 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/examples/blame.c b/examples/blame.c index 450e98aee..9060fa119 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -1,31 +1,25 @@ -#include -#include -#include -#include - -static void check(int error, const char *msg) -{ - if (error) { - fprintf(stderr, "%s (%d)\n", msg, error); - exit(error); - } -} - -static void usage(const char *msg, const char *arg) -{ - if (msg && arg) - fprintf(stderr, "%s: %s\n", msg, arg); - else if (msg) - fprintf(stderr, "%s\n", msg); - fprintf(stderr, "usage: blame [options] [] \n"); - fprintf(stderr, "\n"); - fprintf(stderr, " example: `HEAD~10..HEAD`, or `1234abcd`\n"); - fprintf(stderr, " -L process only line range n-m, counting from 1\n"); - fprintf(stderr, " -M find line moves within and across files\n"); - fprintf(stderr, " -C find line copies within and across files\n"); - fprintf(stderr, "\n"); - exit(1); -} +/* + * libgit2 "blame" example - shows how to use the blame API + * + * Written by the libgit2 contributors + * + * To the extent possible under law, the author(s) have dedicated all copyright + * and related and neighboring rights to this software to the public domain + * worldwide. This software is distributed without any warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication along + * with this software. If not, see + * . + */ + +#include "common.h" + +/** + * This example demonstrates how to invoke the libgit2 blame API to roughly + * simulate the output of `git blame` and a few of its command line arguments. + */ + +static void usage(const char *msg, const char *arg); int main(int argc, char *argv[]) { @@ -61,12 +55,12 @@ int main(int argc, char *argv[]) opts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; else if (!strcasecmp(a, "-L")) { i++; a = argv[i]; - if (i >= argc) check(-1, "Not enough arguments to -L"); - check(sscanf(a, "%d,%d", &opts.min_line, &opts.max_line)-2, "-L format error"); + if (i >= argc) fatal("Not enough arguments to -L", NULL); + check_lg2(sscanf(a, "%d,%d", &opts.min_line, &opts.max_line)-2, "-L format error", NULL); } else { /* commit range */ - if (commitspec) check(-1, "Only one commit spec allowed"); + if (commitspec) fatal("Only one commit spec allowed", NULL); commitspec = a; } } @@ -87,11 +81,11 @@ int main(int argc, char *argv[]) } /* Open the repo */ - check(git_repository_open_ext(&repo, ".", 0, NULL), "Couldn't open repository"); + check_lg2(git_repository_open_ext(&repo, ".", 0, NULL), "Couldn't open repository", NULL); /* Parse the end points */ if (commitspec) { - check(git_revparse(&revspec, repo, commitspec), "Couldn't parse commit spec"); + check_lg2(git_revparse(&revspec, repo, commitspec), "Couldn't parse commit spec", NULL); if (revspec.flags & GIT_REVPARSE_SINGLE) { git_oid_cpy(&opts.newest_commit, git_object_id(revspec.from)); git_object_free(revspec.from); @@ -104,7 +98,7 @@ int main(int argc, char *argv[]) } /* Run the blame */ - check(git_blame_file(&blame, repo, path, &opts), "Blame error"); + check_lg2(git_blame_file(&blame, repo, path, &opts), "Blame error", NULL); /* Get the raw data for output */ if (git_oid_iszero(&opts.newest_commit)) @@ -116,8 +110,8 @@ int main(int argc, char *argv[]) { git_object *obj; - check(git_revparse_single(&obj, repo, spec), "Object lookup error"); - check(git_blob_lookup(&blob, repo, git_object_id(obj)), "Blob lookup error"); + check_lg2(git_revparse_single(&obj, repo, spec), "Object lookup error", NULL); + check_lg2(git_blob_lookup(&blob, repo, git_object_id(obj)), "Blob lookup error", NULL); git_object_free(obj); } rawdata = git_blob_rawcontent(blob); @@ -158,3 +152,20 @@ int main(int argc, char *argv[]) git_repository_free(repo); git_threads_shutdown(); } + +static void usage(const char *msg, const char *arg) +{ + if (msg && arg) + fprintf(stderr, "%s: %s\n", msg, arg); + else if (msg) + fprintf(stderr, "%s\n", msg); + fprintf(stderr, "usage: blame [options] [] \n"); + fprintf(stderr, "\n"); + fprintf(stderr, " example: `HEAD~10..HEAD`, or `1234abcd`\n"); + fprintf(stderr, " -L process only line range n-m, counting from 1\n"); + fprintf(stderr, " -M find line moves within and across files\n"); + fprintf(stderr, " -C find line copies within and across files\n"); + fprintf(stderr, "\n"); + exit(1); +} + -- cgit v1.2.1 From d6c6016966cff46d874a8d85b38704a6ef2150e5 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 4 Nov 2013 15:45:31 -0800 Subject: Add giterr_detach API to get and clear error There are a number of cases where it is convenient to be able to fetch and "claim" the current error string, clearing the error. This is helpful when you need to call some code that may alter the error and you want to restore it later on and/or report it via some other mechanism. --- include/git2/errors.h | 17 +++++++++++++++++ src/errors.c | 23 +++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/git2/errors.h b/include/git2/errors.h index a454ac956..5f5d0ab1f 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -8,6 +8,7 @@ #define INCLUDE_git_errors_h__ #include "common.h" +#include "buffer.h" /** * @file git2/errors.h @@ -45,6 +46,7 @@ typedef struct { /** Error classes */ typedef enum { + GITERR_NONE = 0, GITERR_NOMEMORY, GITERR_OS, GITERR_INVALID, @@ -84,6 +86,21 @@ GIT_EXTERN(const git_error *) giterr_last(void); */ GIT_EXTERN(void) giterr_clear(void); +/** + * Get the last error data and clear it. + * + * This copies the last error message into the given `git_buf` and returns + * the associated `git_error_t`, leaving the error cleared as if + * `giterr_clear` had been called. You must call `git_buf_free` on the + * message to release the memory. + * + * Note: it is possible that this will return `GITERR_NONE` and set the + * buffer to NULL, so be prepared for that condition. Also, if the last + * error was an out-of-memory error, this will return `GITERR_NOMEMORY` + * but also leave the buffer set to NULL (to avoid allocation). + */ +GIT_EXTERN(git_error_t) giterr_detach(git_buf *message); + /** * Set the error message string for this thread. * diff --git a/src/errors.c b/src/errors.c index c9d9e4e37..70b5f2668 100644 --- a/src/errors.c +++ b/src/errors.c @@ -112,6 +112,29 @@ void giterr_clear(void) #endif } +git_error_t giterr_detach(git_buf *message) +{ + git_error_t rval; + git_error *error = GIT_GLOBAL->last_error; + + assert(message); + + git_buf_free(message); + + if (!error) + return GITERR_NONE; + + rval = error->klass; + + if (error != &g_git_oom_error) + git_buf_attach(message, error->message, 0); + + error->message = NULL; + giterr_clear(); + + return rval; +} + const git_error *giterr_last(void) { return GIT_GLOBAL->last_error; -- cgit v1.2.1 From 3b259cbd1afdc96a3c3eb7af5895b310c1ac2a7d Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 4 Nov 2013 15:47:35 -0800 Subject: Preserve file error in iterator When the filesystem iterator encounters an error with a file, it returns the error but because of the cleanup code, it was in some cases erasing the error message. This uses the giterr_detach API to make sure that the actual error message is restored after the cleanup code has been run. --- src/iterator.c | 12 ++++++++++++ tests-clar/repo/iterator.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/iterator.c b/src/iterator.c index c0d7862ff..369a079bc 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -991,8 +991,20 @@ static int fs_iterator__expand_dir(fs_iterator *fi) fi->base.start, fi->base.end, &ff->entries); if (error < 0) { + git_buf msg = GIT_BUF_INIT; + git_error_t errt = giterr_detach(&msg); + + /* these callbacks may clear the error message */ fs_iterator__free_frame(ff); fs_iterator__advance_over(NULL, (git_iterator *)fi); + /* next time return value we skipped to */ + fi->base.flags &= ~GIT_ITERATOR_FIRST_ACCESS; + + if (msg.ptr) { + giterr_set_str(errt, msg.ptr); + git_buf_free(&msg); + } + return error; } diff --git a/tests-clar/repo/iterator.c b/tests-clar/repo/iterator.c index 1c513e9e7..56b51852c 100644 --- a/tests-clar/repo/iterator.c +++ b/tests-clar/repo/iterator.c @@ -926,3 +926,37 @@ void test_repo_iterator__fs2(void) expect_iterator_items(i, 12, expect_base, 12, expect_base); git_iterator_free(i); } + +void test_repo_iterator__fs_preserves_error(void) +{ + git_iterator *i; + const git_index_entry *e; + + if (!cl_is_chmod_supported()) + return; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_must_pass(p_mkdir("empty_standard_repo/r", 0777)); + cl_git_mkfile("empty_standard_repo/r/a", "hello"); + cl_must_pass(p_mkdir("empty_standard_repo/r/b", 0777)); + cl_git_mkfile("empty_standard_repo/r/b/problem", "not me"); + cl_must_pass(p_chmod("empty_standard_repo/r/b", 0000)); + cl_must_pass(p_mkdir("empty_standard_repo/r/c", 0777)); + cl_git_mkfile("empty_standard_repo/r/d", "final"); + + cl_git_pass(git_iterator_for_filesystem( + &i, "empty_standard_repo/r", 0, NULL, NULL)); + + cl_git_pass(git_iterator_advance(&e, i)); /* a */ + cl_git_fail(git_iterator_advance(&e, i)); /* b */ + cl_assert(giterr_last()); + cl_assert(giterr_last()->message != NULL); + /* skip 'c/' empty directory */ + cl_git_pass(git_iterator_advance(&e, i)); /* d */ + cl_assert_equal_i(GIT_ITEROVER, git_iterator_advance(&e, i)); + + cl_must_pass(p_chmod("empty_standard_repo/r/b", 0777)); + + git_iterator_free(i); +} -- cgit v1.2.1 From e6b85be7cff913adb6d8ebe431f91f5a907d056c Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 4 Nov 2013 15:48:35 -0800 Subject: Reorganize and doc-commentify blame sample. --- examples/blame.c | 165 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 96 insertions(+), 69 deletions(-) diff --git a/examples/blame.c b/examples/blame.c index 9060fa119..182b57765 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -19,104 +19,76 @@ * simulate the output of `git blame` and a few of its command line arguments. */ -static void usage(const char *msg, const char *arg); +struct opts { + char *path; + char *commitspec; + int C; + int M; + int start_line; + int end_line; +}; +static void parse_opts(struct opts *o, int argc, char *argv[]); int main(int argc, char *argv[]) { int i, line, break_on_null_hunk; - const char *path = NULL, *a; - const char *rawdata, *commitspec=NULL, *bare_args[3] = {0}; char spec[1024] = {0}; + struct opts o = {0}; + const char *rawdata; git_repository *repo = NULL; git_revspec revspec = {0}; - git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + git_blame_options blameopts = GIT_BLAME_OPTIONS_INIT; git_blame *blame = NULL; git_blob *blob; + git_object *obj; git_threads_init(); - if (argc < 2) usage(NULL, NULL); - - for (i=1; i= 3) - usage("Invalid argument set", NULL); - bare_args[i] = a; - } - else if (!strcmp(a, "--")) - continue; - else if (!strcasecmp(a, "-M")) - opts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; - else if (!strcasecmp(a, "-C")) - opts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; - else if (!strcasecmp(a, "-L")) { - i++; a = argv[i]; - if (i >= argc) fatal("Not enough arguments to -L", NULL); - check_lg2(sscanf(a, "%d,%d", &opts.min_line, &opts.max_line)-2, "-L format error", NULL); - } - else { - /* commit range */ - if (commitspec) fatal("Only one commit spec allowed", NULL); - commitspec = a; - } - } - - /* Handle the bare arguments */ - if (!bare_args[0]) usage("Please specify a path", NULL); - path = bare_args[0]; - if (bare_args[1]) { - /* */ - path = bare_args[1]; - commitspec = bare_args[0]; - } - if (bare_args[2]) { - /* */ - path = bare_args[2]; - sprintf(spec, "%s..%s", bare_args[0], bare_args[1]); - commitspec = spec; - } - - /* Open the repo */ + /** Open the repository. */ check_lg2(git_repository_open_ext(&repo, ".", 0, NULL), "Couldn't open repository", NULL); - /* Parse the end points */ - if (commitspec) { - check_lg2(git_revparse(&revspec, repo, commitspec), "Couldn't parse commit spec", NULL); + /** + * The commit range comes in "commitish" form. Use the rev-parse API to + * nail down the end points. + */ + if (o.commitspec) { + check_lg2(git_revparse(&revspec, repo, o.commitspec), "Couldn't parse commit spec", NULL); if (revspec.flags & GIT_REVPARSE_SINGLE) { - git_oid_cpy(&opts.newest_commit, git_object_id(revspec.from)); + git_oid_cpy(&blameopts.newest_commit, git_object_id(revspec.from)); git_object_free(revspec.from); } else { - git_oid_cpy(&opts.oldest_commit, git_object_id(revspec.from)); - git_oid_cpy(&opts.newest_commit, git_object_id(revspec.to)); + git_oid_cpy(&blameopts.oldest_commit, git_object_id(revspec.from)); + git_oid_cpy(&blameopts.newest_commit, git_object_id(revspec.to)); git_object_free(revspec.from); git_object_free(revspec.to); } } - /* Run the blame */ - check_lg2(git_blame_file(&blame, repo, path, &opts), "Blame error", NULL); + /** Run the blame. */ + check_lg2(git_blame_file(&blame, repo, o.path, &blameopts), "Blame error", NULL); - /* Get the raw data for output */ - if (git_oid_iszero(&opts.newest_commit)) + /** + * Get the raw data inside the blob for output. We use the + * `commitish:path/to/file.txt` format to find it. + */ + if (git_oid_iszero(&blameopts.newest_commit)) strcpy(spec, "HEAD"); else - git_oid_tostr(spec, sizeof(spec), &opts.newest_commit); + git_oid_tostr(spec, sizeof(spec), &blameopts.newest_commit); strcat(spec, ":"); - strcat(spec, path); + strcat(spec, o.path); + + check_lg2(git_revparse_single(&obj, repo, spec), "Object lookup error", NULL); + check_lg2(git_blob_lookup(&blob, repo, git_object_id(obj)), "Blob lookup error", NULL); + git_object_free(obj); - { - git_object *obj; - check_lg2(git_revparse_single(&obj, repo, spec), "Object lookup error", NULL); - check_lg2(git_blob_lookup(&blob, repo, git_object_id(obj)), "Blob lookup error", NULL); - git_object_free(obj); - } rawdata = git_blob_rawcontent(blob); - /* Produce the output */ + /** Produce the output. */ line = 1; i = 0; break_on_null_hunk = 0; @@ -146,11 +118,14 @@ int main(int argc, char *argv[]) line++; } - /* Cleanup */ + /** Cleanup. */ git_blob_free(blob); git_blame_free(blame); git_repository_free(repo); + git_threads_shutdown(); + + return 0; } static void usage(const char *msg, const char *arg) @@ -169,3 +144,55 @@ static void usage(const char *msg, const char *arg) exit(1); } +/** Parse the arguments. */ +static void parse_opts(struct opts *o, int argc, char *argv[]) +{ + int i; + char *bare_args[3] = {0}; + + if (argc < 2) usage(NULL, NULL); + + for (i=1; i= 3) + usage("Invalid argument set", NULL); + bare_args[i] = a; + } + else if (!strcmp(a, "--")) + continue; + else if (!strcasecmp(a, "-M")) + o->M = 1; + else if (!strcasecmp(a, "-C")) + o->C = 1; + else if (!strcasecmp(a, "-L")) { + i++; a = argv[i]; + if (i >= argc) fatal("Not enough arguments to -L", NULL); + check_lg2(sscanf(a, "%d,%d", &o->start_line, &o->end_line)-2, "-L format error", NULL); + } + else { + /* commit range */ + if (o->commitspec) fatal("Only one commit spec allowed", NULL); + o->commitspec = a; + } + } + + /* Handle the bare arguments */ + if (!bare_args[0]) usage("Please specify a path", NULL); + o->path = bare_args[0]; + if (bare_args[1]) { + /* */ + o->path = bare_args[1]; + o->commitspec = bare_args[0]; + } + if (bare_args[2]) { + /* */ + char spec[128] = {0}; + o->path = bare_args[2]; + sprintf(spec, "%s..%s", bare_args[0], bare_args[1]); + o->commitspec = spec; + } +} -- cgit v1.2.1 From ea8ce3d17edbc16f8bc905fcee776629c2010eec Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 4 Nov 2013 15:50:33 -0800 Subject: Fix warnings --- examples/network/fetch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/network/fetch.c b/examples/network/fetch.c index ad01001d7..474b45bbb 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -14,11 +14,12 @@ struct dl_data { int finished; }; -static void progress_cb(const char *str, int len, void *data) +static int progress_cb(const char *str, int len, void *data) { (void)data; printf("remote: %.*s", len, str); fflush(stdout); /* We don't have the \n to force the flush */ + return 0; } static void *download(void *ptr) @@ -78,7 +79,6 @@ int fetch(git_repository *repo, int argc, char **argv) const git_transfer_progress *stats; struct dl_data data; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - int resolve_deltas_ln = 0; #ifndef _WIN32 pthread_t worker; #endif -- cgit v1.2.1 From b47949254ee5b7e5801fd3d1d80136bff5db938a Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 4 Nov 2013 15:54:11 -0800 Subject: blame sample: usage comment --- examples/blame.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/blame.c b/examples/blame.c index 182b57765..95bce6b9c 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -128,6 +128,7 @@ int main(int argc, char *argv[]) return 0; } +/** Tell the user how to make this thing work. */ static void usage(const char *msg, const char *arg) { if (msg && arg) -- cgit v1.2.1 From ac72051afa619446818adf286cf3cdbd13991b38 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 4 Nov 2013 19:09:30 -0800 Subject: Fix ssh.c compile --- src/transports/ssh.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/transports/ssh.c b/src/transports/ssh.c index db950e53d..4a905e3c9 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -317,7 +317,7 @@ static int _git_ssh_setup_conn( const char *cmd, git_smart_subtransport_stream **stream) { - char *host=NULL, *port=NULL, *user=NULL, *pass=NULL; + char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; ssh_stream *s; LIBSSH2_SESSION* session=NULL; @@ -330,7 +330,7 @@ static int _git_ssh_setup_conn( s = (ssh_stream *)*stream; if (!git__prefixcmp(url, prefix_ssh)) { - if (gitno_extract_url_parts(&host, &port, &user, &pass, url, default_port) < 0) + if (gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port) < 0) goto on_error; } else { if (git_ssh_extract_url_parts(&host, &user, url) < 0) @@ -389,6 +389,7 @@ static int _git_ssh_setup_conn( t->current_stream = s; git__free(host); git__free(port); + git__free(path); git__free(user); git__free(pass); -- cgit v1.2.1 From f966acd13366d21e0b9beeecf021c0114596c716 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 4 Nov 2013 15:46:32 -0600 Subject: Take umask into account in filebuf_commit --- include/git2/odb_backend.h | 4 ++-- src/filebuf.c | 6 +++++- src/odb_loose.c | 4 ++-- tests-clar/core/filebuf.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index d3dd733a8..4d772cab9 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -50,8 +50,8 @@ GIT_EXTERN(int) git_odb_backend_loose( const char *objects_dir, int compression_level, int do_fsync, - mode_t dir_mode, - mode_t file_mode); + unsigned int dir_mode, + unsigned int file_mode); /** * Create a backend out of a single packfile diff --git a/src/filebuf.c b/src/filebuf.c index 714a32395..de2944bbc 100644 --- a/src/filebuf.c +++ b/src/filebuf.c @@ -320,9 +320,13 @@ int git_filebuf_commit_at(git_filebuf *file, const char *path, mode_t mode) int git_filebuf_commit(git_filebuf *file, mode_t mode) { + mode_t mask; + /* temporary files cannot be committed */ assert(file && file->path_original); + p_umask(mask = p_umask(0)); + file->flush_mode = Z_FINISH; flush_buffer(file); @@ -338,7 +342,7 @@ int git_filebuf_commit(git_filebuf *file, mode_t mode) file->fd = -1; - if (p_chmod(file->path_lock, mode)) { + if (p_chmod(file->path_lock, (mode & ~mask))) { giterr_set(GITERR_OS, "Failed to set attributes for file at '%s'", file->path_lock); goto on_error; } diff --git a/src/odb_loose.c b/src/odb_loose.c index 0dfd78aee..3e52edf05 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -902,8 +902,8 @@ int git_odb_backend_loose( const char *objects_dir, int compression_level, int do_fsync, - mode_t dir_mode, - mode_t file_mode) + unsigned int dir_mode, + unsigned int file_mode) { loose_backend *backend; size_t objects_dirlen; diff --git a/tests-clar/core/filebuf.c b/tests-clar/core/filebuf.c index bf2167057..646d42c6e 100644 --- a/tests-clar/core/filebuf.c +++ b/tests-clar/core/filebuf.c @@ -90,3 +90,37 @@ void test_core_filebuf__5(void) cl_must_pass(p_unlink(test)); } + + +/* make sure git_filebuf_commit takes umask into account */ +void test_core_filebuf__umask(void) +{ + git_filebuf file = GIT_FILEBUF_INIT; + char test[] = "test"; + struct stat statbuf; + mode_t mask, os_mask; + +#ifdef GIT_WIN32 + os_mask = 0600; +#else + os_mask = 0777; +#endif + + p_umask(mask = p_umask(0)); + + cl_assert(file.buffer == NULL); + + cl_git_pass(git_filebuf_open(&file, test, 0)); + cl_assert(file.buffer != NULL); + cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks")); + cl_assert(file.buffer != NULL); + + cl_git_pass(git_filebuf_commit(&file, 0666)); + cl_assert(file.buffer == NULL); + + cl_must_pass(p_stat("test", &statbuf)); + cl_assert_equal_i(statbuf.st_mode & os_mask, (0666 & ~mask) & os_mask); + + cl_must_pass(p_unlink(test)); +} + -- cgit v1.2.1 From 1d3a8aeb4bd032d0bf34039fbcb308fba06b862a Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 4 Nov 2013 18:28:57 -0500 Subject: move mode_t to filebuf_open instead of _commit --- src/blob.c | 2 +- src/checkout.c | 4 ++-- src/config_file.c | 4 ++-- src/fetchhead.c | 4 ++-- src/filebuf.c | 29 +++++++++-------------------- src/filebuf.h | 6 +++--- src/fileops.c | 11 ++++++++++- src/fileops.h | 2 +- src/index.c | 4 ++-- src/indexer.c | 10 ++++++---- src/merge.c | 16 ++++++++-------- src/merge.h | 1 + src/odb_loose.c | 10 ++++++---- src/refdb_fs.c | 14 +++++++------- src/repository.c | 6 +++--- tests-clar/config/stress.c | 4 ++-- tests-clar/core/filebuf.c | 20 ++++++++++---------- tests-clar/index/tests.c | 6 +++--- tests-clar/odb/alternates.c | 4 ++-- 19 files changed, 80 insertions(+), 77 deletions(-) diff --git a/src/blob.c b/src/blob.c index e18db4dfc..2c6d52800 100644 --- a/src/blob.c +++ b/src/blob.c @@ -284,7 +284,7 @@ int git_blob_create_fromchunks( content = git__malloc(BUFFER_SIZE); GITERR_CHECK_ALLOC(content); - if (git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY) < 0) + if (git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY, 0666) < 0) goto cleanup; while (1) { diff --git a/src/checkout.c b/src/checkout.c index a4f326637..6d7e3cfd4 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -1673,9 +1673,9 @@ static int checkout_write_merge( goto done; if ((error = git_futils_mkpath2file(path_workdir.ptr, 0755)) < 0 || - (error = git_filebuf_open(&output, path_workdir.ptr, GIT_FILEBUF_DO_NOT_BUFFER)) < 0 || + (error = git_filebuf_open(&output, path_workdir.ptr, GIT_FILEBUF_DO_NOT_BUFFER, result.mode)) < 0 || (error = git_filebuf_write(&output, result.data, result.len)) < 0 || - (error = git_filebuf_commit(&output, result.mode)) < 0) + (error = git_filebuf_commit(&output)) < 0) goto done; done: diff --git a/src/config_file.c b/src/config_file.c index c7fc32060..40dcc5a37 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -1210,7 +1210,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p write_start = data_start; /* Lock the file */ - if (git_filebuf_open(&file, cfg->file_path, 0) < 0) + if (git_filebuf_open(&file, cfg->file_path, 0, GIT_CONFIG_FILE_MODE) < 0) return -1; skip_bom(reader); @@ -1369,7 +1369,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p /* refresh stats - if this errors, then commit will error too */ (void)git_filebuf_stats(&reader->file_mtime, &reader->file_size, &file); - result = git_filebuf_commit(&file, GIT_CONFIG_FILE_MODE); + result = git_filebuf_commit(&file); git_buf_free(&reader->buffer); return result; diff --git a/src/fetchhead.c b/src/fetchhead.c index 4dcebb857..9672623ff 100644 --- a/src/fetchhead.c +++ b/src/fetchhead.c @@ -112,7 +112,7 @@ int git_fetchhead_write(git_repository *repo, git_vector *fetchhead_refs) if (git_buf_joinpath(&path, repo->path_repository, GIT_FETCH_HEAD_FILE) < 0) return -1; - if (git_filebuf_open(&file, path.ptr, GIT_FILEBUF_FORCE) < 0) { + if (git_filebuf_open(&file, path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE) < 0) { git_buf_free(&path); return -1; } @@ -124,7 +124,7 @@ int git_fetchhead_write(git_repository *repo, git_vector *fetchhead_refs) git_vector_foreach(fetchhead_refs, i, fetchhead_ref) fetchhead_ref_write(&file, fetchhead_ref); - return git_filebuf_commit(&file, GIT_REFS_FILE_MODE); + return git_filebuf_commit(&file); } static int fetchhead_ref_parse( diff --git a/src/filebuf.c b/src/filebuf.c index de2944bbc..9c3dae811 100644 --- a/src/filebuf.c +++ b/src/filebuf.c @@ -10,8 +10,6 @@ #include "filebuf.h" #include "fileops.h" -#define GIT_LOCK_FILE_MODE 0644 - static const size_t WRITE_BUFFER_SIZE = (4096 * 2); enum buferr_t { @@ -44,7 +42,7 @@ static int verify_last_error(git_filebuf *file) } } -static int lock_file(git_filebuf *file, int flags) +static int lock_file(git_filebuf *file, int flags, mode_t mode) { if (git_path_exists(file->path_lock) == true) { if (flags & GIT_FILEBUF_FORCE) @@ -60,9 +58,9 @@ static int lock_file(git_filebuf *file, int flags) /* create path to the file buffer is required */ if (flags & GIT_FILEBUF_FORCE) { /* XXX: Should dirmode here be configurable? Or is 0777 always fine? */ - file->fd = git_futils_creat_locked_withpath(file->path_lock, 0777, GIT_LOCK_FILE_MODE); + file->fd = git_futils_creat_locked_withpath(file->path_lock, 0777, mode); } else { - file->fd = git_futils_creat_locked(file->path_lock, GIT_LOCK_FILE_MODE); + file->fd = git_futils_creat_locked(file->path_lock, mode); } if (file->fd < 0) @@ -195,7 +193,7 @@ static int write_deflate(git_filebuf *file, void *source, size_t len) return 0; } -int git_filebuf_open(git_filebuf *file, const char *path, int flags) +int git_filebuf_open(git_filebuf *file, const char *path, int flags, mode_t mode) { int compression, error = -1; size_t path_len; @@ -255,7 +253,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags) git_buf tmp_path = GIT_BUF_INIT; /* Open the file as temporary for locking */ - file->fd = git_futils_mktmp(&tmp_path, path); + file->fd = git_futils_mktmp(&tmp_path, path, mode); if (file->fd < 0) { git_buf_free(&tmp_path); @@ -282,7 +280,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags) memcpy(file->path_lock + path_len, GIT_FILELOCK_EXTENSION, GIT_FILELOCK_EXTLENGTH); /* open the file for locking */ - if ((error = lock_file(file, flags)) < 0) + if ((error = lock_file(file, flags, mode)) < 0) goto cleanup; } @@ -309,24 +307,20 @@ int git_filebuf_hash(git_oid *oid, git_filebuf *file) return 0; } -int git_filebuf_commit_at(git_filebuf *file, const char *path, mode_t mode) +int git_filebuf_commit_at(git_filebuf *file, const char *path) { git__free(file->path_original); file->path_original = git__strdup(path); GITERR_CHECK_ALLOC(file->path_original); - return git_filebuf_commit(file, mode); + return git_filebuf_commit(file); } -int git_filebuf_commit(git_filebuf *file, mode_t mode) +int git_filebuf_commit(git_filebuf *file) { - mode_t mask; - /* temporary files cannot be committed */ assert(file && file->path_original); - p_umask(mask = p_umask(0)); - file->flush_mode = Z_FINISH; flush_buffer(file); @@ -342,11 +336,6 @@ int git_filebuf_commit(git_filebuf *file, mode_t mode) file->fd = -1; - if (p_chmod(file->path_lock, (mode & ~mask))) { - giterr_set(GITERR_OS, "Failed to set attributes for file at '%s'", file->path_lock); - goto on_error; - } - p_unlink(file->path_original); if (p_rename(file->path_lock, file->path_original) < 0) { diff --git a/src/filebuf.h b/src/filebuf.h index 823af81bf..044af5405 100644 --- a/src/filebuf.h +++ b/src/filebuf.h @@ -77,9 +77,9 @@ int git_filebuf_write(git_filebuf *lock, const void *buff, size_t len); int git_filebuf_reserve(git_filebuf *file, void **buff, size_t len); int git_filebuf_printf(git_filebuf *file, const char *format, ...) GIT_FORMAT_PRINTF(2, 3); -int git_filebuf_open(git_filebuf *lock, const char *path, int flags); -int git_filebuf_commit(git_filebuf *lock, mode_t mode); -int git_filebuf_commit_at(git_filebuf *lock, const char *path, mode_t mode); +int git_filebuf_open(git_filebuf *lock, const char *path, int flags, mode_t mode); +int git_filebuf_commit(git_filebuf *lock); +int git_filebuf_commit_at(git_filebuf *lock, const char *path); void git_filebuf_cleanup(git_filebuf *lock); int git_filebuf_hash(git_oid *oid, git_filebuf *file); int git_filebuf_flush(git_filebuf *file); diff --git a/src/fileops.c b/src/fileops.c index 54bf5d850..1c27b277d 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -19,9 +19,12 @@ int git_futils_mkpath2file(const char *file_path, const mode_t mode) GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR); } -int git_futils_mktmp(git_buf *path_out, const char *filename) +int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode) { int fd; + mode_t mask; + + p_umask(mask = p_umask(0)); git_buf_sets(path_out, filename); git_buf_puts(path_out, "_git2_XXXXXX"); @@ -35,6 +38,12 @@ int git_futils_mktmp(git_buf *path_out, const char *filename) return -1; } + if (p_chmod(path_out->ptr, (mode & ~mask))) { + giterr_set(GITERR_OS, + "Failed to set permissions on file '%s'", path_out->ptr); + return -1; + } + return fd; } diff --git a/src/fileops.h b/src/fileops.h index 1b2728e58..59a6a21a7 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -141,7 +141,7 @@ extern int git_futils_rmdir_r(const char *path, const char *base, uint32_t flags * Writes the filename into path_out. * @return On success, an open file descriptor, else an error code < 0. */ -extern int git_futils_mktmp(git_buf *path_out, const char *filename); +extern int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode); /** * Move a file on the filesystem, create the diff --git a/src/index.c b/src/index.c index dbf1ab529..ecab15024 100644 --- a/src/index.c +++ b/src/index.c @@ -500,7 +500,7 @@ int git_index_write(git_index *index) git_vector_sort(&index->reuc); if ((error = git_filebuf_open( - &file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS)) < 0) { + &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 concurrrent or crashed process"); @@ -512,7 +512,7 @@ int git_index_write(git_index *index) return error; } - if ((error = git_filebuf_commit(&file, GIT_INDEX_FILE_MODE)) < 0) + if ((error = git_filebuf_commit(&file)) < 0) return error; error = git_futils_filestamp_check(&index->stamp, index->index_file_path); diff --git a/src/indexer.c b/src/indexer.c index 0873c8cf0..90fb52187 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -140,7 +140,8 @@ int git_indexer_new( goto cleanup; error = git_filebuf_open(&idx->pack_file, path.ptr, - GIT_FILEBUF_TEMPORARY | GIT_FILEBUF_DO_NOT_BUFFER); + GIT_FILEBUF_TEMPORARY | GIT_FILEBUF_DO_NOT_BUFFER, + GIT_PACK_FILE_MODE); git_buf_free(&path); if (error < 0) goto cleanup; @@ -903,7 +904,8 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) if (git_buf_oom(&filename)) return -1; - if (git_filebuf_open(&index_file, filename.ptr, GIT_FILEBUF_HASH_CONTENTS) < 0) + if (git_filebuf_open(&index_file, filename.ptr, + GIT_FILEBUF_HASH_CONTENTS, GIT_PACK_FILE_MODE) < 0) goto on_error; /* Write out the header */ @@ -969,7 +971,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) goto on_error; /* Commit file */ - if (git_filebuf_commit_at(&index_file, filename.ptr, GIT_PACK_FILE_MODE) < 0) + if (git_filebuf_commit_at(&index_file, filename.ptr) < 0) goto on_error; git_mwindow_free_all(&idx->pack->mwf); @@ -980,7 +982,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) if (index_path(&filename, idx, ".pack") < 0) goto on_error; /* And don't forget to rename the packfile to its new place. */ - if (git_filebuf_commit_at(&idx->pack_file, filename.ptr, GIT_PACK_FILE_MODE) < 0) + if (git_filebuf_commit_at(&idx->pack_file, filename.ptr) < 0) return -1; git_buf_free(&filename); diff --git a/src/merge.c b/src/merge.c index a22801e48..ea2224d86 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1623,9 +1623,9 @@ static int write_orig_head( git_oid_tostr(orig_oid_str, GIT_OID_HEXSZ+1, &our_head->oid); if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_ORIG_HEAD_FILE)) == 0 && - (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE)) == 0 && + (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) == 0 && (error = git_filebuf_printf(&file, "%s\n", orig_oid_str)) == 0) - error = git_filebuf_commit(&file, 0666); + error = git_filebuf_commit(&file); if (error < 0) git_filebuf_cleanup(&file); @@ -1649,7 +1649,7 @@ static int write_merge_head( assert(repo && heads); if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_HEAD_FILE)) < 0 || - (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE)) < 0) + (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0) goto cleanup; for (i = 0; i < heads_len; i++) { @@ -1659,7 +1659,7 @@ static int write_merge_head( goto cleanup; } - error = git_filebuf_commit(&file, 0666); + error = git_filebuf_commit(&file); cleanup: if (error < 0) @@ -1682,10 +1682,10 @@ static int write_merge_mode(git_repository *repo, unsigned int flags) assert(repo); if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MODE_FILE)) < 0 || - (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE)) < 0) + (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0) goto cleanup; - error = git_filebuf_commit(&file, 0666); + error = git_filebuf_commit(&file); cleanup: if (error < 0) @@ -1911,7 +1911,7 @@ static int write_merge_msg( entries[i].merge_head = heads[i]; if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 || - (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE)) < 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; @@ -1988,7 +1988,7 @@ static int write_merge_msg( } if ((error = git_filebuf_printf(&file, "\n")) < 0 || - (error = git_filebuf_commit(&file, 0666)) < 0) + (error = git_filebuf_commit(&file)) < 0) goto cleanup; cleanup: diff --git a/src/merge.h b/src/merge.h index ba6725de9..0ecad6e3e 100644 --- a/src/merge.h +++ b/src/merge.h @@ -16,6 +16,7 @@ #define GIT_MERGE_MSG_FILE "MERGE_MSG" #define GIT_MERGE_MODE_FILE "MERGE_MODE" +#define GIT_MERGE_FILE_MODE 0666 #define GIT_MERGE_TREE_RENAME_THRESHOLD 50 #define GIT_MERGE_TREE_TARGET_LIMIT 1000 diff --git a/src/odb_loose.c b/src/odb_loose.c index 3e52edf05..ced272b33 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -789,7 +789,7 @@ static int loose_backend__stream_fwrite(git_odb_stream *_stream, const git_oid * error = -1; else error = git_filebuf_commit_at( - &stream->fbuf, final_path.ptr, backend->object_file_mode); + &stream->fbuf, final_path.ptr); git_buf_free(&final_path); @@ -838,7 +838,8 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_ 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)) < 0 || + (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT), + backend->object_file_mode) < 0 || stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0) { git_filebuf_cleanup(&stream->fbuf); @@ -867,7 +868,8 @@ static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, c 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)) < 0) + (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT), + backend->object_file_mode) < 0) { error = -1; goto cleanup; @@ -878,7 +880,7 @@ static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, c if (object_file_name(&final_path, backend, oid) < 0 || object_mkdir(&final_path, backend) < 0 || - git_filebuf_commit_at(&fbuf, final_path.ptr, backend->object_file_mode) < 0) + git_filebuf_commit_at(&fbuf, final_path.ptr) < 0) error = -1; cleanup: diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 7ce09ba55..62d5c1047 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -702,7 +702,7 @@ static int loose_write(refdb_fs_backend *backend, const git_reference *ref) if (git_buf_joinpath(&ref_path, backend->path, ref->name) < 0) return -1; - if (git_filebuf_open(&file, ref_path.ptr, GIT_FILEBUF_FORCE) < 0) { + if (git_filebuf_open(&file, ref_path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE) < 0) { git_buf_free(&ref_path); return -1; } @@ -720,7 +720,7 @@ static int loose_write(refdb_fs_backend *backend, const git_reference *ref) assert(0); /* don't let this happen */ } - return git_filebuf_commit(&file, GIT_REFS_FILE_MODE); + return git_filebuf_commit(&file); } /* @@ -865,7 +865,7 @@ static int packed_write(refdb_fs_backend *backend) return -1; /* Open the file! */ - if (git_filebuf_open(&pack_file, git_sortedcache_path(refcache), 0) < 0) + if (git_filebuf_open(&pack_file, git_sortedcache_path(refcache), 0, GIT_PACKEDREFS_FILE_MODE) < 0) goto fail; /* Packfiles have a header... apparently @@ -886,7 +886,7 @@ static int packed_write(refdb_fs_backend *backend) /* if we've written all the references properly, we can commit * the packfile to make the changes effective */ - if (git_filebuf_commit(&pack_file, GIT_PACKEDREFS_FILE_MODE) < 0) + if (git_filebuf_commit(&pack_file) < 0) goto fail; /* when and only when the packfile has been properly written, @@ -1289,7 +1289,7 @@ static int refdb_reflog_fs__write(git_refdb_backend *_backend, git_reflog *reflo goto cleanup; } - if ((error = git_filebuf_open(&fbuf, git_buf_cstr(&log_path), 0)) < 0) + if ((error = git_filebuf_open(&fbuf, git_buf_cstr(&log_path), 0, GIT_REFLOG_FILE_MODE)) < 0) goto cleanup; git_vector_foreach(&reflog->entries, i, entry) { @@ -1300,7 +1300,7 @@ static int refdb_reflog_fs__write(git_refdb_backend *_backend, git_reflog *reflo goto cleanup; } - error = git_filebuf_commit(&fbuf, GIT_REFLOG_FILE_MODE); + error = git_filebuf_commit(&fbuf); goto success; cleanup: @@ -1350,7 +1350,7 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_ if (git_buf_joinpath(&temp_path, git_buf_cstr(&temp_path), "temp_reflog") < 0) return -1; - if ((fd = git_futils_mktmp(&temp_path, git_buf_cstr(&temp_path))) < 0) { + if ((fd = git_futils_mktmp(&temp_path, git_buf_cstr(&temp_path), GIT_REFLOG_FILE_MODE)) < 0) { error = -1; goto cleanup; } diff --git a/src/repository.c b/src/repository.c index c5ce8425f..dcc02e4fb 100644 --- a/src/repository.c +++ b/src/repository.c @@ -816,7 +816,7 @@ static int repo_init_create_head(const char *git_dir, const char *ref_name) const char *fmt; if (git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE) < 0 || - git_filebuf_open(&ref, ref_path.ptr, 0) < 0) + git_filebuf_open(&ref, ref_path.ptr, 0, GIT_REFS_FILE_MODE) < 0) goto fail; if (!ref_name) @@ -828,7 +828,7 @@ static int repo_init_create_head(const char *git_dir, const char *ref_name) fmt = "ref: " GIT_REFS_HEADS_DIR "%s\n"; if (git_filebuf_printf(&ref, fmt, ref_name) < 0 || - git_filebuf_commit(&ref, GIT_REFS_FILE_MODE) < 0) + git_filebuf_commit(&ref) < 0) goto fail; git_buf_free(&ref_path); @@ -875,7 +875,7 @@ static bool are_symlinks_supported(const char *wd_path) struct stat st; int symlinks_supported = -1; - if ((fd = git_futils_mktmp(&path, wd_path)) < 0 || + if ((fd = git_futils_mktmp(&path, wd_path, 0666)) < 0 || p_close(fd) < 0 || p_unlink(path.ptr) < 0 || p_symlink("testing", path.ptr) < 0 || diff --git a/tests-clar/config/stress.c b/tests-clar/config/stress.c index 8cc64d23c..eeca54ff4 100644 --- a/tests-clar/config/stress.c +++ b/tests-clar/config/stress.c @@ -10,12 +10,12 @@ void test_config_stress__initialize(void) { git_filebuf file = GIT_FILEBUF_INIT; - cl_git_pass(git_filebuf_open(&file, TEST_CONFIG, 0)); + cl_git_pass(git_filebuf_open(&file, TEST_CONFIG, 0, 0666)); git_filebuf_printf(&file, "[color]\n\tui = auto\n"); git_filebuf_printf(&file, "[core]\n\teditor = \n"); - cl_git_pass(git_filebuf_commit(&file, 0666)); + cl_git_pass(git_filebuf_commit(&file)); } void test_config_stress__cleanup(void) diff --git a/tests-clar/core/filebuf.c b/tests-clar/core/filebuf.c index 646d42c6e..5a3e7510f 100644 --- a/tests-clar/core/filebuf.c +++ b/tests-clar/core/filebuf.c @@ -13,7 +13,7 @@ void test_core_filebuf__0(void) cl_must_pass(fd); cl_must_pass(p_close(fd)); - cl_git_fail(git_filebuf_open(&file, test, 0)); + cl_git_fail(git_filebuf_open(&file, test, 0, 0666)); cl_assert(git_path_exists(testlock)); cl_must_pass(p_unlink(testlock)); @@ -28,9 +28,9 @@ void test_core_filebuf__1(void) cl_git_mkfile(test, "libgit2 rocks\n"); - cl_git_pass(git_filebuf_open(&file, test, GIT_FILEBUF_APPEND)); + cl_git_pass(git_filebuf_open(&file, test, GIT_FILEBUF_APPEND, 0666)); cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks")); - cl_git_pass(git_filebuf_commit(&file, 0666)); + cl_git_pass(git_filebuf_commit(&file)); cl_assert_equal_file("libgit2 rocks\nlibgit2 rocks\n", 0, test); @@ -47,9 +47,9 @@ void test_core_filebuf__2(void) memset(buf, 0xfe, sizeof(buf)); - cl_git_pass(git_filebuf_open(&file, test, 0)); + cl_git_pass(git_filebuf_open(&file, test, 0, 0666)); cl_git_pass(git_filebuf_write(&file, buf, sizeof(buf))); - cl_git_pass(git_filebuf_commit(&file, 0666)); + cl_git_pass(git_filebuf_commit(&file)); cl_assert_equal_file((char *)buf, sizeof(buf), test); @@ -64,7 +64,7 @@ void test_core_filebuf__4(void) cl_assert(file.buffer == NULL); - cl_git_pass(git_filebuf_open(&file, test, 0)); + cl_git_pass(git_filebuf_open(&file, test, 0, 0666)); cl_assert(file.buffer != NULL); git_filebuf_cleanup(&file); @@ -80,12 +80,12 @@ void test_core_filebuf__5(void) cl_assert(file.buffer == NULL); - cl_git_pass(git_filebuf_open(&file, test, 0)); + cl_git_pass(git_filebuf_open(&file, test, 0, 0666)); cl_assert(file.buffer != NULL); cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks")); cl_assert(file.buffer != NULL); - cl_git_pass(git_filebuf_commit(&file, 0666)); + cl_git_pass(git_filebuf_commit(&file)); cl_assert(file.buffer == NULL); cl_must_pass(p_unlink(test)); @@ -110,12 +110,12 @@ void test_core_filebuf__umask(void) cl_assert(file.buffer == NULL); - cl_git_pass(git_filebuf_open(&file, test, 0)); + cl_git_pass(git_filebuf_open(&file, test, 0, 0666)); cl_assert(file.buffer != NULL); cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks")); cl_assert(file.buffer != NULL); - cl_git_pass(git_filebuf_commit(&file, 0666)); + cl_git_pass(git_filebuf_commit(&file)); cl_assert(file.buffer == NULL); cl_must_pass(p_stat("test", &statbuf)); diff --git a/tests-clar/index/tests.c b/tests-clar/index/tests.c index 09b05bf6e..e5202980c 100644 --- a/tests-clar/index/tests.c +++ b/tests-clar/index/tests.c @@ -224,9 +224,9 @@ void test_index_tests__add(void) /* Create a new file in the working directory */ cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777)); - cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0)); + cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0, 0666)); cl_git_pass(git_filebuf_write(&file, "hey there\n", 10)); - cl_git_pass(git_filebuf_commit(&file, 0666)); + cl_git_pass(git_filebuf_commit(&file)); /* Store the expected hash of the file/blob * This has been generated by executing the following @@ -474,7 +474,7 @@ void test_index_tests__elocked(void) cl_git_pass(git_repository_index(&index, repo)); /* Lock the index file so we fail to lock it */ - cl_git_pass(git_filebuf_open(&file, index->index_file_path, 0)); + cl_git_pass(git_filebuf_open(&file, index->index_file_path, 0, 0666)); error = git_index_write(index); cl_assert_equal_i(GIT_ELOCKED, error); diff --git a/tests-clar/odb/alternates.c b/tests-clar/odb/alternates.c index 4e876c2b3..c75f6feaa 100644 --- a/tests-clar/odb/alternates.c +++ b/tests-clar/odb/alternates.c @@ -32,9 +32,9 @@ static void init_linked_repo(const char *path, const char *alternate) cl_git_pass(git_futils_mkdir(filepath.ptr, NULL, 0755, GIT_MKDIR_PATH)); cl_git_pass(git_buf_joinpath(&filepath, filepath.ptr , "alternates")); - cl_git_pass(git_filebuf_open(&file, git_buf_cstr(&filepath), 0)); + cl_git_pass(git_filebuf_open(&file, git_buf_cstr(&filepath), 0, 0666)); git_filebuf_printf(&file, "%s\n", git_buf_cstr(&destpath)); - cl_git_pass(git_filebuf_commit(&file, 0644)); + cl_git_pass(git_filebuf_commit(&file)); git_repository_free(repo); } -- cgit v1.2.1 From e8162fd091bbfd49fc5aaa60794a0a3558e895bb Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 5 Nov 2013 12:01:14 +0100 Subject: Propagate ELOCKED error when updating the config --- src/config_file.c | 8 ++++---- tests-clar/config/write.c | 13 +++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 40dcc5a37..9b4a7c1b6 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -385,10 +385,10 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val GITERR_CHECK_ALLOC(esc_value); } - if (config_write(b, key, NULL, esc_value) < 0) { + if ((ret = config_write(b, key, NULL, esc_value)) < 0) { git__free(esc_value); cvar_free(var); - return -1; + return ret; } git__free(esc_value); @@ -1210,8 +1210,8 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p write_start = data_start; /* Lock the file */ - if (git_filebuf_open(&file, cfg->file_path, 0, GIT_CONFIG_FILE_MODE) < 0) - return -1; + if ((result = git_filebuf_open(&file, cfg->file_path, 0, GIT_CONFIG_FILE_MODE)) < 0) + return result; skip_bom(reader); ldot = strrchr(key, '.'); diff --git a/tests-clar/config/write.c b/tests-clar/config/write.c index 57b02a7d9..309fef65a 100644 --- a/tests-clar/config/write.c +++ b/tests-clar/config/write.c @@ -259,3 +259,16 @@ void test_config_write__can_set_an_empty_value(void) git_config_free(config); cl_git_sandbox_cleanup(); } + +void test_config_write__updating_a_locked_config_file_returns_ELOCKED(void) +{ + git_config *cfg; + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + + cl_git_mkfile("config9.lock", "[core]\n"); + + cl_git_fail_with(git_config_set_string(cfg, "core.dump", "boom"), GIT_ELOCKED); + + git_config_free(cfg); +} -- cgit v1.2.1 From 1eab9f0e32178a9aac941583c69e1b9cf9849f77 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 5 Nov 2013 14:56:10 +0100 Subject: error: Simplify giterr_detach --- include/git2/errors.h | 15 ++++++--------- src/errors.c | 17 ++++++----------- src/iterator.c | 11 ++++++----- 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/include/git2/errors.h b/include/git2/errors.h index 5f5d0ab1f..be7a31d8e 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -89,17 +89,14 @@ GIT_EXTERN(void) giterr_clear(void); /** * Get the last error data and clear it. * - * This copies the last error message into the given `git_buf` and returns - * the associated `git_error_t`, leaving the error cleared as if - * `giterr_clear` had been called. You must call `git_buf_free` on the - * message to release the memory. + * This copies the last error into the given `git_error` struct + * and returns 0 if the copy was successful, leaving the error + * cleared as if `giterr_clear` had been called. * - * Note: it is possible that this will return `GITERR_NONE` and set the - * buffer to NULL, so be prepared for that condition. Also, if the last - * error was an out-of-memory error, this will return `GITERR_NOMEMORY` - * but also leave the buffer set to NULL (to avoid allocation). + * If there was no existing error in the library, -1 will be returned + * and the contents of `cpy` will be left unmodified. */ -GIT_EXTERN(git_error_t) giterr_detach(git_buf *message); +GIT_EXTERN(int) giterr_detach(git_error *cpy); /** * Set the error message string for this thread. diff --git a/src/errors.c b/src/errors.c index 70b5f2668..d04da4ca9 100644 --- a/src/errors.c +++ b/src/errors.c @@ -112,27 +112,22 @@ void giterr_clear(void) #endif } -git_error_t giterr_detach(git_buf *message) +int giterr_detach(git_error *cpy) { - git_error_t rval; git_error *error = GIT_GLOBAL->last_error; - assert(message); - - git_buf_free(message); + assert(cpy); if (!error) - return GITERR_NONE; - - rval = error->klass; + return -1; - if (error != &g_git_oom_error) - git_buf_attach(message, error->message, 0); + cpy->message = error->message; + cpy->klass = error->klass; error->message = NULL; giterr_clear(); - return rval; + return 0; } const git_error *giterr_last(void) diff --git a/src/iterator.c b/src/iterator.c index 369a079bc..8646399ab 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -991,8 +991,9 @@ static int fs_iterator__expand_dir(fs_iterator *fi) fi->base.start, fi->base.end, &ff->entries); if (error < 0) { - git_buf msg = GIT_BUF_INIT; - git_error_t errt = giterr_detach(&msg); + git_error last_error = {0}; + + giterr_detach(&last_error); /* these callbacks may clear the error message */ fs_iterator__free_frame(ff); @@ -1000,9 +1001,9 @@ static int fs_iterator__expand_dir(fs_iterator *fi) /* next time return value we skipped to */ fi->base.flags &= ~GIT_ITERATOR_FIRST_ACCESS; - if (msg.ptr) { - giterr_set_str(errt, msg.ptr); - git_buf_free(&msg); + if (last_error.message) { + giterr_set_str(last_error.klass, last_error.message); + free(last_error.message); } return error; -- cgit v1.2.1 From 8ec889a45fded32bf8508f99d77ea666d0aacdd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 2 Nov 2013 14:07:02 +0100 Subject: branch: move from foreach to an iterator Create a git_branch_iterator type which is equivalent to the foreach but lets us write loops instead of callbacks. Since the introduction of git_reference_shorthand(), the added value of passing the name is reduced. --- include/git2/branch.h | 40 +++++---- src/branch.c | 82 ++++++++++------- tests-clar/online/push.c | 37 ++++---- tests-clar/refs/branches/foreach.c | 173 ------------------------------------ tests-clar/refs/branches/iterator.c | 151 +++++++++++++++++++++++++++++++ 5 files changed, 240 insertions(+), 243 deletions(-) delete mode 100644 tests-clar/refs/branches/foreach.c create mode 100644 tests-clar/refs/branches/iterator.c diff --git a/include/git2/branch.h b/include/git2/branch.h index de414e9b0..b5e7d60ea 100644 --- a/include/git2/branch.h +++ b/include/git2/branch.h @@ -66,33 +66,41 @@ GIT_EXTERN(int) git_branch_create( */ GIT_EXTERN(int) git_branch_delete(git_reference *branch); -typedef int (*git_branch_foreach_cb)( - const char *branch_name, - git_branch_t branch_type, - void *payload); +/** Iterator type for branches */ +typedef struct git_branch_iterator git_branch_iterator; /** - * Loop over all the branches and issue a callback for each one. - * - * If the callback returns a non-zero value, this will stop looping. + * Create an iterator which loops over the requested branches. * + * @param out the iterator * @param repo Repository where to find the branches. - * * @param list_flags Filtering flags for the branch * listing. Valid values are GIT_BRANCH_LOCAL, GIT_BRANCH_REMOTE * or a combination of the two. * - * @param branch_cb Callback to invoke per found branch. + * @return 0 on success or an error code + */ +GIT_EXTERN(int) git_branch_iterator_new( + git_branch_iterator **out, + git_repository *repo, + unsigned int list_flags); + +/** + * Retrieve the next branch from the iterator * - * @param payload Extra parameter to callback function. + * @param out the reference + * @param out_type the type of branch (local or remote-tracking) + * @param iter the branch iterator + * @return 0 on success, GIT_ITEROVER if there are no more branches or an error code. + */ +GIT_EXTERN(int) git_branch_next(git_reference **out, unsigned int *out_type, git_branch_iterator *iter); + +/** + * Free a branch iterator * - * @return 0 on success, GIT_EUSER on non-zero callback, or error code + * @param iter the iterator to free */ -GIT_EXTERN(int) git_branch_foreach( - git_repository *repo, - unsigned int list_flags, - git_branch_foreach_cb branch_cb, - void *payload); +GIT_EXTERN(void) git_branch_iterator_free(git_branch_iterator *iter); /** * Move/rename an existing local branch reference. diff --git a/src/branch.c b/src/branch.c index 3a745c127..4660f00b7 100644 --- a/src/branch.c +++ b/src/branch.c @@ -124,48 +124,66 @@ on_error: return error; } -int git_branch_foreach( - git_repository *repo, - unsigned int list_flags, - git_branch_foreach_cb callback, - void *payload) -{ +typedef struct { git_reference_iterator *iter; - git_reference *ref; - int error = 0; + unsigned int flags; +} branch_iter; - if (git_reference_iterator_new(&iter, repo) < 0) - return -1; +int git_branch_next(git_reference **out, unsigned int *out_type, git_branch_iterator *_iter) +{ + branch_iter *iter = (branch_iter *) _iter; + git_reference *ref; + int error; - while ((error = git_reference_next(&ref, iter)) == 0) { - if (list_flags & GIT_BRANCH_LOCAL && - git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR) == 0) { - if (callback(ref->name + strlen(GIT_REFS_HEADS_DIR), - GIT_BRANCH_LOCAL, payload)) { - error = GIT_EUSER; - } + while ((error = git_reference_next(&ref, iter->iter)) == 0) { + if ((iter->flags & GIT_BRANCH_LOCAL) && + !git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR)) { + *out = ref; + *out_type = GIT_BRANCH_LOCAL; + + return 0; + } else if ((iter->flags & GIT_BRANCH_REMOTE) && + !git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR)) { + *out = ref; + *out_type = GIT_BRANCH_REMOTE; + + return 0; + } else { + git_reference_free(ref); } + } - if (list_flags & GIT_BRANCH_REMOTE && - git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR) == 0) { - if (callback(ref->name + strlen(GIT_REFS_REMOTES_DIR), - GIT_BRANCH_REMOTE, payload)) { - error = GIT_EUSER; - } - } + return error; +} + +int git_branch_iterator_new( + git_branch_iterator **out, + git_repository *repo, + unsigned int list_flags) +{ + branch_iter *iter; + + iter = git__calloc(1, sizeof(branch_iter)); + GITERR_CHECK_ALLOC(iter); - git_reference_free(ref); + iter->flags = list_flags; - /* check if the callback has cancelled iteration */ - if (error == GIT_EUSER) - break; + if (git_reference_iterator_new(&iter->iter, repo) < 0) { + git__free(iter); + return -1; } - if (error == GIT_ITEROVER) - error = 0; + *out = (git_branch_iterator *) iter; - git_reference_iterator_free(iter); - return error; + return 0; +} + +void git_branch_iterator_free(git_branch_iterator *_iter) +{ + branch_iter *iter = (branch_iter *) _iter; + + git_reference_iterator_free(iter->iter); + git__free(iter); } int git_branch_move( diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 5a747bba7..320ecb71e 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -163,18 +163,6 @@ static void verify_refs(git_remote *remote, expected_ref expected_refs[], size_t git_vector_free(&actual_refs); } -static int tracking_branch_list_cb(const char *branch_name, git_branch_t branch_type, void *payload) -{ - git_vector *tracking = (git_vector *)payload; - - if (branch_type == GIT_BRANCH_REMOTE) - git_vector_insert(tracking, git__strdup(branch_name)); - else - GIT_UNUSED(branch_name); - - return 0; -} - /** * Verifies that after git_push_update_tips(), remote tracking branches have the expected * names and oids. @@ -189,14 +177,24 @@ static void verify_tracking_branches(git_remote *remote, expected_ref expected_r size_t i, j; git_buf msg = GIT_BUF_INIT; git_buf ref_name = GIT_BUF_INIT; - git_buf canonical_ref_name = GIT_BUF_INIT; git_vector actual_refs = GIT_VECTOR_INIT; + git_branch_iterator *iter; char *actual_ref; git_oid oid; - int failed = 0; + int failed = 0, error; + unsigned int branch_type; + git_reference *ref; /* Get current remote branches */ - cl_git_pass(git_branch_foreach(remote->repo, GIT_BRANCH_REMOTE, tracking_branch_list_cb, &actual_refs)); + cl_git_pass(git_branch_iterator_new(&iter, remote->repo, GIT_BRANCH_REMOTE)); + + while ((error = git_branch_next(&ref, &branch_type, iter)) == 0) { + cl_assert_equal_i(branch_type, GIT_BRANCH_REMOTE); + + cl_git_pass(git_vector_insert(&actual_refs, git__strdup(git_reference_name(ref)))); + } + + cl_assert_equal_i(error, GIT_ITEROVER); /* Loop through expected refs, make sure they exist */ for (i = 0; i < expected_refs_len; i++) { @@ -212,11 +210,7 @@ static void verify_tracking_branches(git_remote *remote, expected_ref expected_r /* Find matching remote branch */ git_vector_foreach(&actual_refs, j, actual_ref) { - - /* Construct canonical ref name from the actual_ref name */ - git_buf_clear(&canonical_ref_name); - cl_git_pass(git_buf_printf(&canonical_ref_name, "refs/remotes/%s", actual_ref)); - if (!strcmp(git_buf_cstr(&ref_name), git_buf_cstr(&canonical_ref_name))) + if (!strcmp(git_buf_cstr(&ref_name), actual_ref)) break; } @@ -227,7 +221,7 @@ static void verify_tracking_branches(git_remote *remote, expected_ref expected_r } /* Make sure tracking branch is at expected commit ID */ - cl_git_pass(git_reference_name_to_id(&oid, remote->repo, git_buf_cstr(&canonical_ref_name))); + cl_git_pass(git_reference_name_to_id(&oid, remote->repo, actual_ref)); if (git_oid_cmp(expected_refs[i].oid, &oid) != 0) { git_buf_puts(&msg, "Tracking branch commit does not match expected ID."); @@ -256,7 +250,6 @@ failed: git_vector_free(&actual_refs); git_buf_free(&msg); - git_buf_free(&canonical_ref_name); git_buf_free(&ref_name); return; } diff --git a/tests-clar/refs/branches/foreach.c b/tests-clar/refs/branches/foreach.c deleted file mode 100644 index 433812cb4..000000000 --- a/tests-clar/refs/branches/foreach.c +++ /dev/null @@ -1,173 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" - -static git_repository *repo; -static git_reference *fake_remote; - -void test_refs_branches_foreach__initialize(void) -{ - git_oid id; - - cl_fixture_sandbox("testrepo.git"); - cl_git_pass(git_repository_open(&repo, "testrepo.git")); - - cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); - cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0)); -} - -void test_refs_branches_foreach__cleanup(void) -{ - git_reference_free(fake_remote); - fake_remote = NULL; - - git_repository_free(repo); - repo = NULL; - - cl_fixture_cleanup("testrepo.git"); - - cl_git_sandbox_cleanup(); -} - -static int count_branch_list_cb(const char *branch_name, git_branch_t branch_type, void *payload) -{ - int *count; - - GIT_UNUSED(branch_type); - GIT_UNUSED(branch_name); - - count = (int *)payload; - (*count)++; - - return 0; -} - -static void assert_retrieval(unsigned int flags, unsigned int expected_count) -{ - int count = 0; - - cl_git_pass(git_branch_foreach(repo, flags, count_branch_list_cb, &count)); - - cl_assert_equal_i(expected_count, count); -} - -void test_refs_branches_foreach__retrieve_all_branches(void) -{ - assert_retrieval(GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, 14); -} - -void test_refs_branches_foreach__retrieve_remote_branches(void) -{ - assert_retrieval(GIT_BRANCH_REMOTE, 2); -} - -void test_refs_branches_foreach__retrieve_local_branches(void) -{ - assert_retrieval(GIT_BRANCH_LOCAL, 12); -} - -struct expectations { - const char *branch_name; - int encounters; -}; - -static void assert_branch_has_been_found(struct expectations *findings, const char* expected_branch_name) -{ - int pos = 0; - - for (pos = 0; findings[pos].branch_name; ++pos) { - if (strcmp(expected_branch_name, findings[pos].branch_name) == 0) { - cl_assert_equal_i(1, findings[pos].encounters); - return; - } - } - - cl_fail("expected branch not found in list."); -} - -static int contains_branch_list_cb(const char *branch_name, git_branch_t branch_type, void *payload) -{ - int pos = 0; - struct expectations *exp; - - GIT_UNUSED(branch_type); - - exp = (struct expectations *)payload; - - for (pos = 0; exp[pos].branch_name; ++pos) { - if (strcmp(branch_name, exp[pos].branch_name) == 0) - exp[pos].encounters++; - } - - return 0; -} - -/* - * $ git branch -r - * nulltoken/HEAD -> nulltoken/master - * nulltoken/master - */ -void test_refs_branches_foreach__retrieve_remote_symbolic_HEAD_when_present(void) -{ - struct expectations exp[] = { - { "nulltoken/HEAD", 0 }, - { "nulltoken/master", 0 }, - { NULL, 0 } - }; - - git_reference_free(fake_remote); - cl_git_pass(git_reference_symbolic_create(&fake_remote, repo, "refs/remotes/nulltoken/HEAD", "refs/remotes/nulltoken/master", 0)); - - assert_retrieval(GIT_BRANCH_REMOTE, 3); - - cl_git_pass(git_branch_foreach(repo, GIT_BRANCH_REMOTE, contains_branch_list_cb, &exp)); - - assert_branch_has_been_found(exp, "nulltoken/HEAD"); - assert_branch_has_been_found(exp, "nulltoken/master"); -} - -static int branch_list_interrupt_cb( - const char *branch_name, git_branch_t branch_type, void *payload) -{ - int *count; - - GIT_UNUSED(branch_type); - GIT_UNUSED(branch_name); - - count = (int *)payload; - (*count)++; - - return (*count == 5); -} - -void test_refs_branches_foreach__can_cancel(void) -{ - int count = 0; - - cl_assert_equal_i(GIT_EUSER, - git_branch_foreach(repo, GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, - branch_list_interrupt_cb, &count)); - - cl_assert_equal_i(5, count); -} - -void test_refs_branches_foreach__mix_of_packed_and_loose(void) -{ - struct expectations exp[] = { - { "master", 0 }, - { "origin/HEAD", 0 }, - { "origin/master", 0 }, - { "origin/packed", 0 }, - { NULL, 0 } - }; - git_repository *r2; - - r2 = cl_git_sandbox_init("testrepo2"); - - cl_git_pass(git_branch_foreach(r2, GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, - contains_branch_list_cb, &exp)); - - assert_branch_has_been_found(exp, "master"); - assert_branch_has_been_found(exp, "origin/HEAD"); - assert_branch_has_been_found(exp, "origin/master"); - assert_branch_has_been_found(exp, "origin/packed"); -} diff --git a/tests-clar/refs/branches/iterator.c b/tests-clar/refs/branches/iterator.c new file mode 100644 index 000000000..fb2c1a19d --- /dev/null +++ b/tests-clar/refs/branches/iterator.c @@ -0,0 +1,151 @@ +#include "clar_libgit2.h" +#include "refs.h" + +static git_repository *repo; +static git_reference *fake_remote; + +void test_refs_branches_iterator__initialize(void) +{ + git_oid id; + + cl_fixture_sandbox("testrepo.git"); + cl_git_pass(git_repository_open(&repo, "testrepo.git")); + + cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); + cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0)); +} + +void test_refs_branches_iterator__cleanup(void) +{ + git_reference_free(fake_remote); + fake_remote = NULL; + + git_repository_free(repo); + repo = NULL; + + cl_fixture_cleanup("testrepo.git"); + + cl_git_sandbox_cleanup(); +} + +static void assert_retrieval(unsigned int flags, unsigned int expected_count) +{ + git_branch_iterator *iter; + git_reference *ref; + int count = 0, error; + unsigned int type; + + cl_git_pass(git_branch_iterator_new(&iter, repo, flags)); + while ((error = git_branch_next(&ref, &type, iter)) == 0) { + count++; + git_reference_free(ref); + } + + git_branch_iterator_free(iter); + cl_assert_equal_i(error, GIT_ITEROVER); + cl_assert_equal_i(expected_count, count); +} + +void test_refs_branches_iterator__retrieve_all_branches(void) +{ + assert_retrieval(GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, 14); +} + +void test_refs_branches_iterator__retrieve_remote_branches(void) +{ + assert_retrieval(GIT_BRANCH_REMOTE, 2); +} + +void test_refs_branches_iterator__retrieve_local_branches(void) +{ + assert_retrieval(GIT_BRANCH_LOCAL, 12); +} + +struct expectations { + const char *branch_name; + int encounters; +}; + +static void assert_branch_has_been_found(struct expectations *findings, const char* expected_branch_name) +{ + int pos = 0; + + for (pos = 0; findings[pos].branch_name; ++pos) { + if (strcmp(expected_branch_name, findings[pos].branch_name) == 0) { + cl_assert_equal_i(1, findings[pos].encounters); + return; + } + } + + cl_fail("expected branch not found in list."); +} + +static void contains_branches(struct expectations exp[], git_branch_iterator *iter) +{ + git_reference *ref; + unsigned int type; + int error, pos = 0; + + while ((error = git_branch_next(&ref, &type, iter)) == 0) { + for (pos = 0; exp[pos].branch_name; ++pos) { + if (strcmp(git_reference_shorthand(ref), exp[pos].branch_name) == 0) + exp[pos].encounters++; + } + + git_reference_free(ref); + } + + cl_assert_equal_i(error, GIT_ITEROVER); +} + +/* + * $ git branch -r + * nulltoken/HEAD -> nulltoken/master + * nulltoken/master + */ +void test_refs_branches_iterator__retrieve_remote_symbolic_HEAD_when_present(void) +{ + git_branch_iterator *iter; + struct expectations exp[] = { + { "nulltoken/HEAD", 0 }, + { "nulltoken/master", 0 }, + { NULL, 0 } + }; + + git_reference_free(fake_remote); + cl_git_pass(git_reference_symbolic_create(&fake_remote, repo, "refs/remotes/nulltoken/HEAD", "refs/remotes/nulltoken/master", 0)); + + assert_retrieval(GIT_BRANCH_REMOTE, 3); + + cl_git_pass(git_branch_iterator_new(&iter, repo, GIT_BRANCH_REMOTE)); + contains_branches(exp, iter); + git_branch_iterator_free(iter); + + assert_branch_has_been_found(exp, "nulltoken/HEAD"); + assert_branch_has_been_found(exp, "nulltoken/master"); +} + +void test_refs_branches_iterator__mix_of_packed_and_loose(void) +{ + git_branch_iterator *iter; + struct expectations exp[] = { + { "master", 0 }, + { "origin/HEAD", 0 }, + { "origin/master", 0 }, + { "origin/packed", 0 }, + { NULL, 0 } + }; + git_repository *r2; + + r2 = cl_git_sandbox_init("testrepo2"); + + cl_git_pass(git_branch_iterator_new(&iter, r2, GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE)); + contains_branches(exp, iter); + + git_branch_iterator_free(iter); + + assert_branch_has_been_found(exp, "master"); + assert_branch_has_been_found(exp, "origin/HEAD"); + assert_branch_has_been_found(exp, "origin/master"); + assert_branch_has_been_found(exp, "origin/packed"); +} -- cgit v1.2.1 From 61080a959d5f027d3eef066bd7b771132b50496e Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 5 Nov 2013 15:10:02 +0100 Subject: Fix leaks --- src/config_file.c | 7 +++++-- tests-clar/diff/workdir.c | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 9b4a7c1b6..0bd4e4ece 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -1210,8 +1210,11 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p write_start = data_start; /* Lock the file */ - if ((result = git_filebuf_open(&file, cfg->file_path, 0, GIT_CONFIG_FILE_MODE)) < 0) - return result; + if ((result = git_filebuf_open( + &file, cfg->file_path, 0, GIT_CONFIG_FILE_MODE)) < 0) { + git_buf_free(&reader->buffer); + return result; + } skip_bom(reader); ldot = strrchr(key, '.'); diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index df31e7322..7cc032232 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -1477,6 +1477,8 @@ void test_diff_workdir__with_stale_index(void) cl_git_pass(git_diff_foreach( diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + git_diff_free(diff); + cl_assert_equal_i(16, exp.files); cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]); -- cgit v1.2.1 From 039db728f3a0477129e664f0fd8c08316a9e8b62 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 3 Jul 2013 01:00:45 -0400 Subject: merge branch into current, updating workdir --- include/git2/merge.h | 60 ++++ include/git2/types.h | 3 + src/merge.c | 543 +++++++++++++++++++++++++++++++-- src/merge.h | 11 + tests-clar/merge/merge_helpers.c | 23 ++ tests-clar/merge/merge_helpers.h | 3 + tests-clar/merge/workdir/fastforward.c | 148 +++++++++ tests-clar/merge/workdir/renames.c | 156 ++++++++++ tests-clar/merge/workdir/setup.c | 92 +++++- tests-clar/merge/workdir/simple.c | 491 +++++++++++++++++++++++++++++ tests-clar/merge/workdir/trivial.c | 341 +++++++++++++++++++++ 11 files changed, 1851 insertions(+), 20 deletions(-) create mode 100644 tests-clar/merge/workdir/fastforward.c create mode 100644 tests-clar/merge/workdir/renames.c create mode 100644 tests-clar/merge/workdir/simple.c create mode 100644 tests-clar/merge/workdir/trivial.c diff --git a/include/git2/merge.h b/include/git2/merge.h index 62fd7d723..3354fbeab 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -65,6 +65,29 @@ typedef struct { #define GIT_MERGE_TREE_OPTS_INIT {GIT_MERGE_TREE_OPTS_VERSION} +/** + * Option flags for `git_merge`. + * + * GIT_MERGE_NO_FASTFORWARD - Do not fast-forward. + */ +typedef enum { + GIT_MERGE_NO_FASTFORWARD = 1, + GIT_MERGE_FASTFORWARD_ONLY = 2, +} git_merge_flags_t; + +typedef struct { + unsigned int version; + + git_merge_flags_t merge_flags; + git_merge_tree_opts merge_tree_opts; + + git_checkout_opts checkout_opts; +} git_merge_opts; + +#define GIT_MERGE_OPTS_VERSION 1 +#define GIT_MERGE_OPTS_INIT {GIT_MERGE_OPTS_VERSION, 0, GIT_MERGE_TREE_OPTS_INIT, GIT_CHECKOUT_OPTS_INIT} + + /** * Find a merge base between two commits * @@ -168,6 +191,43 @@ GIT_EXTERN(int) git_merge_trees( const git_tree *their_tree, const git_merge_tree_opts *opts); +/** + * Merges the given commits into HEAD, producing a new commit. + * + * @param out the results of the merge + * @param repo the repository to merge + * @param merge_heads the heads to merge into + * @param merge_heads_len the number of heads to merge + * @param flags merge flags + */ +GIT_EXTERN(int) git_merge( + git_merge_result **out, + git_repository *repo, + const git_merge_head **their_heads, + size_t their_heads_len, + const git_merge_opts *opts); + +/** + * Returns true if a merge is up-to-date (we were asked to merge the target + * into itself.) + */ +GIT_EXTERN(int) git_merge_result_is_uptodate(git_merge_result *merge_result); + +/** + * Returns true if a merge is eligible for fastforward + */ +GIT_EXTERN(int) git_merge_result_is_fastforward(git_merge_result *merge_result); + +/** + * Gets the fast-forward OID if the merge was a fastforward. + * + * @param out the OID of the fast-forward + * @param merge_result the results of the merge + */ +GIT_EXTERN(int) git_merge_result_fastforward_oid(git_oid *out, git_merge_result *merge_result); + +GIT_EXTERN(void) git_merge_result_free(git_merge_result *merge_result); + /** @} */ GIT_END_DECL #endif diff --git a/include/git2/types.h b/include/git2/types.h index 71d5374d3..55505b110 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -174,6 +174,9 @@ typedef struct git_reference_iterator git_reference_iterator; /** Merge heads, the input to merge */ typedef struct git_merge_head git_merge_head; +/** Merge result */ +typedef struct git_merge_result git_merge_result; + /** Representation of a status collection */ typedef struct git_status_list git_status_list; diff --git a/src/merge.c b/src/merge.c index ea2224d86..973d4445c 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1615,16 +1615,13 @@ static int write_orig_head( { git_filebuf file = GIT_FILEBUF_INIT; git_buf file_path = GIT_BUF_INIT; - char orig_oid_str[GIT_OID_HEXSZ + 1]; int error = 0; assert(repo && our_head); - git_oid_tostr(orig_oid_str, GIT_OID_HEXSZ+1, &our_head->oid); - if ((error = git_buf_joinpath(&file_path, repo->path_repository, 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", orig_oid_str)) == 0) + (error = git_filebuf_printf(&file, "%s\n", our_head->oid_str)) == 0) error = git_filebuf_commit(&file); if (error < 0) @@ -1642,7 +1639,6 @@ static int write_merge_head( { git_filebuf file = GIT_FILEBUF_INIT; git_buf file_path = GIT_BUF_INIT; - char merge_oid_str[GIT_OID_HEXSZ + 1]; size_t i; int error = 0; @@ -1653,9 +1649,7 @@ static int write_merge_head( goto cleanup; for (i = 0; i < heads_len; i++) { - git_oid_tostr(merge_oid_str, GIT_OID_HEXSZ+1, &heads[i]->oid); - - if ((error = git_filebuf_printf(&file, "%s\n", merge_oid_str)) < 0) + if ((error = git_filebuf_printf(&file, "%s\n", &heads[i]->oid_str)) < 0) goto cleanup; } @@ -1685,6 +1679,17 @@ static int write_merge_mode(git_repository *repo, unsigned int flags) (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0) goto cleanup; + /* + * no-ff is the only thing allowed here at present. One would + * presume they would be space-delimited when there are more, but + * this needs to be revisited. + */ + + if (flags & GIT_MERGE_NO_FASTFORWARD) { + if ((error = git_filebuf_write(&file, "no-ff", 5)) < 0) + goto cleanup; + } + error = git_filebuf_commit(&file); cleanup: @@ -1890,7 +1895,6 @@ static int write_merge_msg( { git_filebuf file = GIT_FILEBUF_INIT; git_buf file_path = GIT_BUF_INIT; - char oid_str[GIT_OID_HEXSZ + 1]; struct merge_msg_entry *entries; git_vector matching = GIT_VECTOR_INIT; size_t i; @@ -1930,10 +1934,9 @@ static int write_merge_msg( if (!msg_entry_is_oid(&entries[i])) break; - git_oid_fmt(oid_str, &entries[i].merge_head->oid); - oid_str[GIT_OID_HEXSZ] = '\0'; - - if ((error = git_filebuf_printf(&file, "%scommit '%s'", (i > 0) ? "; " : "", oid_str)) < 0) + if ((error = git_filebuf_printf(&file, + "%scommit '%s'", (i > 0) ? "; " : "", + entries[i].merge_head->oid_str)) < 0) goto cleanup; entries[i].written = 1; @@ -1980,10 +1983,8 @@ static int write_merge_msg( if (merge_msg_entry_written(&entries[i])) continue; - git_oid_fmt(oid_str, &entries[i].merge_head->oid); - oid_str[GIT_OID_HEXSZ] = '\0'; - - if ((error = git_filebuf_printf(&file, "; commit '%s'", oid_str)) < 0) + if ((error = git_filebuf_printf(&file, "; commit '%s'", + entries[i].merge_head->oid_str)) < 0) goto cleanup; } @@ -2003,6 +2004,474 @@ cleanup: return error; } +/* Merge branches */ + +static int merge_ancestor_head( + git_merge_head **ancestor_head, + git_repository *repo, + const git_merge_head *our_head, + const git_merge_head **their_heads, + size_t their_heads_len) +{ + git_oid *oids, ancestor_oid; + size_t i; + int error = 0; + + assert(repo && our_head && their_heads); + + oids = git__calloc(their_heads_len + 1, sizeof(git_oid)); + GITERR_CHECK_ALLOC(oids); + + git_oid_cpy(&oids[0], git_commit_id(our_head->commit)); + + for (i = 0; i < their_heads_len; i++) + git_oid_cpy(&oids[i + 1], &their_heads[i]->oid); + + if ((error = git_merge_base_many(&ancestor_oid, repo, their_heads_len + 1, oids)) < 0) + goto on_error; + + error = git_merge_head_from_oid(ancestor_head, repo, &ancestor_oid); + +on_error: + git__free(oids); + return error; +} + +GIT_INLINE(bool) merge_check_uptodate( + git_merge_result *result, + const git_merge_head *ancestor_head, + const git_merge_head *their_head) +{ + if (git_oid_cmp(&ancestor_head->oid, &their_head->oid) == 0) { + result->is_uptodate = 1; + return true; + } + + return false; +} + +GIT_INLINE(bool) merge_check_fastforward( + git_merge_result *result, + const git_merge_head *ancestor_head, + const git_merge_head *our_head, + const git_merge_head *their_head, + unsigned int flags) +{ + if ((flags & GIT_MERGE_NO_FASTFORWARD) == 0 && + git_oid_cmp(&ancestor_head->oid, &our_head->oid) == 0) { + result->is_fastforward = 1; + git_oid_cpy(&result->fastforward_oid, &their_head->oid); + + return true; + } + + return false; +} + +const char *merge_their_label(const char *branchname) +{ + const char *slash; + + if ((slash = strrchr(branchname, '/')) == NULL) + return branchname; + + if (*(slash+1) == '\0') + return "theirs"; + + return slash+1; +} + +static int merge_normalize_opts( + git_repository *repo, + git_merge_opts *opts, + const git_merge_opts *given, + size_t their_heads_len, + const git_merge_head **their_heads) +{ + int error = 0; + unsigned int default_checkout_strategy = GIT_CHECKOUT_SAFE_CREATE | + GIT_CHECKOUT_ALLOW_CONFLICTS; + + GIT_UNUSED(repo); + + if (given != NULL) + memcpy(opts, given, sizeof(git_merge_opts)); + else { + git_merge_opts default_opts = GIT_MERGE_OPTS_INIT; + memcpy(opts, &default_opts, sizeof(git_merge_opts)); + } + + if (!opts->checkout_opts.checkout_strategy) + opts->checkout_opts.checkout_strategy = default_checkout_strategy; + + if (!opts->checkout_opts.our_label) + opts->checkout_opts.our_label = "HEAD"; + + if (!opts->checkout_opts.their_label) { + if (their_heads_len == 1 && their_heads[0]->ref_name) + opts->checkout_opts.their_label = merge_their_label(their_heads[0]->ref_name); + else if (their_heads_len == 1) + opts->checkout_opts.their_label = their_heads[0]->oid_str; + else + opts->checkout_opts.their_label = "theirs"; + } + + return error; +} + +static int merge_affected_paths(git_vector *paths, git_repository *repo, git_index *index_new) +{ + git_tree *head_tree = NULL; + git_iterator *iter_head = NULL, *iter_new = NULL; + git_diff *merged_list = NULL; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff_delta *delta; + size_t i; + const git_index_entry *e; + char *path; + int error = 0; + + if ((error = git_repository_head_tree(&head_tree, repo)) < 0 || + (error = git_iterator_for_tree(&iter_head, head_tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 || + (error = git_iterator_for_index(&iter_new, index_new, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 || + (error = git_diff__from_iterators(&merged_list, repo, iter_head, iter_new, &opts)) < 0) + goto done; + + git_vector_foreach(&merged_list->deltas, i, delta) { + path = git__strdup(delta->new_file.path); + GITERR_CHECK_ALLOC(path); + + if ((error = git_vector_insert(paths, path)) < 0) + goto on_error; + } + + for (i = 0; i < git_index_entrycount(index_new); i++) { + e = git_index_get_byindex(index_new, i); + + if (git_index_entry_stage(e) != 0 && + (git_vector_last(paths) == NULL || + strcmp(git_vector_last(paths), e->path) != 0)) { + + path = git__strdup(e->path); + GITERR_CHECK_ALLOC(path); + + if ((error = git_vector_insert(paths, path)) < 0) + goto on_error; + } + } + + goto done; + +on_error: + git_vector_foreach(paths, i, path) + git__free(path); + + git_vector_clear(paths); + +done: + git_tree_free(head_tree); + git_iterator_free(iter_head); + git_iterator_free(iter_new); + git_diff_free(merged_list); + + return error; +} + +static int merge_check_index(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths) +{ + git_tree *head_tree = NULL; + git_index *index_repo = NULL; + git_iterator *iter_repo = NULL, *iter_new = NULL; + git_diff *staged_diff_list = NULL, *index_diff_list = NULL; + git_diff_delta *delta; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_vector staged_paths = GIT_VECTOR_INIT; + size_t i; + int error = 0; + + GIT_UNUSED(merged_paths); + + *conflicts = 0; + + /* No staged changes may exist unless the change staged is identical to + * the result of the merge. This allows one to apply to merge manually, + * then run merge. Any other staged change would be overwritten by + * a reset merge. + */ + if ((error = git_repository_head_tree(&head_tree, repo)) < 0 || + (error = git_repository_index(&index_repo, repo)) < 0 || + (error = git_diff_tree_to_index(&staged_diff_list, repo, head_tree, index_repo, &opts)) < 0) + goto done; + + if (staged_diff_list->deltas.length == 0) + goto done; + + git_vector_foreach(&staged_diff_list->deltas, i, delta) { + if ((error = git_vector_insert(&staged_paths, (char *)delta->new_file.path)) < 0) + goto done; + } + + opts.pathspec.count = staged_paths.length; + opts.pathspec.strings = (char **)staged_paths.contents; + + if ((error = git_iterator_for_index(&iter_repo, index_repo, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 || + (error = git_iterator_for_index(&iter_new, index_new, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 || + (error = git_diff__from_iterators(&index_diff_list, repo, iter_repo, iter_new, &opts)) < 0) + goto done; + + *conflicts = index_diff_list->deltas.length; + +done: + git_tree_free(head_tree); + git_index_free(index_repo); + git_iterator_free(iter_repo); + git_iterator_free(iter_new); + git_diff_free(staged_diff_list); + git_diff_free(index_diff_list); + git_vector_free(&staged_paths); + + return error; +} + +static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths) +{ + git_tree *head_tree = NULL; + git_diff *wd_diff_list = NULL; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + int error = 0; + + *conflicts = 0; + + opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED; + + if ((error = git_repository_head_tree(&head_tree, repo)) < 0) + goto done; + + /* Workdir changes may exist iff they do not conflict with changes that + * will be applied by the merge (including conflicts). Ensure that there + * are no changes in the workdir to these paths. + */ + opts.pathspec.count = merged_paths->length; + opts.pathspec.strings = (char **)merged_paths->contents; + + if ((error = git_diff_tree_to_workdir(&wd_diff_list, repo, head_tree, &opts)) < 0) + goto done; + + *conflicts = wd_diff_list->deltas.length; + +done: + git_tree_free(head_tree); + git_diff_free(wd_diff_list); + + return error; +} + +static int merge_indexes(git_repository *repo, git_index *index_new) +{ + git_index *index_repo; + unsigned int index_repo_caps; + git_vector paths = GIT_VECTOR_INIT; + size_t index_conflicts = 0, wd_conflicts = 0, conflicts, i; + char *path; + const git_index_entry *e; + const git_index_name_entry *name; + const git_index_reuc_entry *reuc; + int error = 0; + + if ((error = git_repository_index(&index_repo, repo)) < 0) + goto done; + + /* Set the index to case sensitive to handle the merge */ + index_repo_caps = git_index_caps(index_repo); + + if ((error = git_index_set_caps(index_repo, (index_repo_caps & ~GIT_INDEXCAP_IGNORE_CASE))) < 0) + goto done; + + /* Make sure the index and workdir state do not prevent merging */ + if ((error = merge_affected_paths(&paths, repo, index_new)) < 0 || + (error = merge_check_index(&index_conflicts, repo, index_new, &paths)) < 0 || + (error = merge_check_workdir(&wd_conflicts, repo, index_new, &paths)) < 0) + goto done; + + if ((conflicts = index_conflicts + wd_conflicts) > 0) { + giterr_set(GITERR_MERGE, "%d uncommitted change%s would be overwritten by merge", + conflicts, (conflicts != 1) ? "s" : ""); + error = GIT_EMERGECONFLICT; + + goto done; + } + + /* Update the new index */ + git_vector_foreach(&paths, i, path) { + if ((e = git_index_get_bypath(index_new, path, 0)) != NULL) + error = git_index_add(index_repo, e); + else + error = git_index_remove(index_repo, path, 0); + } + + /* Add conflicts */ + git_index_conflict_cleanup(index_repo); + + for (i = 0; i < git_index_entrycount(index_new); i++) { + e = git_index_get_byindex(index_new, i); + + if (git_index_entry_stage(e) != 0 && + (error = git_index_add(index_repo, e)) < 0) + goto done; + } + + /* Add name entries */ + git_index_name_clear(index_repo); + + for (i = 0; i < git_index_name_entrycount(index_new); i++) { + name = git_index_name_get_byindex(index_new, i); + + if ((error = git_index_name_add(index_repo, + name->ancestor, name->ours, name->theirs)) < 0) + goto done; + } + + /* Add the reuc */ + git_index_reuc_clear(index_repo); + + for (i = 0; i < git_index_reuc_entrycount(index_new); i++) { + reuc = (git_index_reuc_entry *)git_index_reuc_get_byindex(index_new, i); + + if ((error = git_index_reuc_add(index_repo, reuc->path, + reuc->mode[0], &reuc->oid[0], + reuc->mode[1], &reuc->oid[1], + reuc->mode[2], &reuc->oid[2])) < 0) + goto done; + } + +done: + if (index_repo != NULL) + git_index_set_caps(index_repo, index_repo_caps); + + git_index_free(index_repo); + + git_vector_foreach(&paths, i, path) + git__free(path); + + git_vector_free(&paths); + + return error; +} + +int git_merge( + git_merge_result **out, + git_repository *repo, + const git_merge_head **their_heads, + size_t their_heads_len, + const git_merge_opts *given_opts) +{ + git_merge_result *result; + git_merge_opts opts; + git_reference *our_ref = NULL; + git_merge_head *ancestor_head = NULL, *our_head = NULL; + git_tree *ancestor_tree = NULL, *our_tree = NULL, **their_trees = NULL; + git_index *index_new = NULL, *index_repo = NULL; + size_t i; + int error = 0; + + assert(out && repo && their_heads); + + *out = NULL; + + if (their_heads_len != 1) { + giterr_set(GITERR_MERGE, "Can only merge a single branch"); + return -1; + } + + result = git__calloc(1, sizeof(git_merge_result)); + GITERR_CHECK_ALLOC(result); + + their_trees = git__calloc(their_heads_len, sizeof(git_tree *)); + GITERR_CHECK_ALLOC(their_trees); + + if ((error = merge_normalize_opts(repo, &opts, given_opts, their_heads_len, their_heads)) < 0) + goto on_error; + + if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0) + goto on_error; + + if ((error = git_reference_lookup(&our_ref, repo, GIT_HEAD_FILE)) < 0 || + (error = git_merge_head_from_ref(&our_head, repo, our_ref)) < 0) + goto on_error; + + if ((error = merge_ancestor_head(&ancestor_head, repo, our_head, their_heads, their_heads_len)) < 0 && + error != GIT_ENOTFOUND) + goto on_error; + + if (their_heads_len == 1 && + ancestor_head != NULL && + (merge_check_uptodate(result, ancestor_head, their_heads[0]) || + merge_check_fastforward(result, ancestor_head, our_head, their_heads[0], opts.merge_flags))) { + *out = result; + goto done; + } + + /* If FASTFORWARD_ONLY is specified, fail. */ + if ((opts.merge_flags & GIT_MERGE_FASTFORWARD_ONLY) == + GIT_MERGE_FASTFORWARD_ONLY) { + giterr_set(GITERR_MERGE, "Not a fast-forward."); + error = GIT_ENONFASTFORWARD; + goto on_error; + } + + /* Write the merge files to the repository. */ + if ((error = git_merge__setup(repo, our_head, their_heads, their_heads_len, opts.merge_flags)) < 0) + goto on_error; + + if (ancestor_head != NULL && + (error = git_commit_tree(&ancestor_tree, ancestor_head->commit)) < 0) + goto on_error; + + if ((error = git_commit_tree(&our_tree, our_head->commit)) < 0) + goto on_error; + + for (i = 0; i < their_heads_len; i++) { + if ((error = git_commit_tree(&their_trees[i], their_heads[i]->commit)) < 0) + goto on_error; + } + + /* TODO: recursive, octopus, etc... */ + + if ((error = git_merge_trees(&index_new, repo, ancestor_tree, our_tree, their_trees[0], &opts.merge_tree_opts)) < 0 || + (error = merge_indexes(repo, index_new)) < 0 || + (error = git_repository_index(&index_repo, repo)) < 0 || + (error = git_checkout_index(repo, index_repo, &opts.checkout_opts)) < 0) + goto on_error; + + result->index = index_new; + + *out = result; + goto done; + +on_error: + git_repository_merge_cleanup(repo); + + git__free(result); + +done: + git_index_free(index_repo); + + git_tree_free(ancestor_tree); + git_tree_free(our_tree); + + for (i = 0; i < their_heads_len; i++) + git_tree_free(their_trees[i]); + + git__free(their_trees); + + git_merge_head_free(our_head); + git_merge_head_free(ancestor_head); + + git_reference_free(our_ref); + + return error; +} + int git_merge__setup( git_repository *repo, const git_merge_head *our_head, @@ -2013,7 +2482,7 @@ int git_merge__setup( int error = 0; assert (repo && our_head && heads); - + if ((error = write_orig_head(repo, our_head)) == 0 && (error = write_merge_head(repo, heads, heads_len)) == 0 && (error = write_merge_mode(repo, flags)) == 0) { @@ -2056,6 +2525,41 @@ cleanup: return error; } +/* Merge result data */ + +int git_merge_result_is_uptodate(git_merge_result *merge_result) +{ + assert(merge_result); + + return merge_result->is_uptodate; +} + +int git_merge_result_is_fastforward(git_merge_result *merge_result) +{ + assert(merge_result); + + return merge_result->is_fastforward; +} + +int git_merge_result_fastforward_oid(git_oid *out, git_merge_result *merge_result) +{ + assert(out && merge_result); + + git_oid_cpy(out, &merge_result->fastforward_oid); + return 0; +} + +void git_merge_result_free(git_merge_result *merge_result) +{ + if (merge_result == NULL) + return; + + git_index_free(merge_result->index); + merge_result->index = NULL; + + git__free(merge_result); +} + /* Merge heads are the input to merge */ static int merge_head_init( @@ -2087,6 +2591,9 @@ static int merge_head_init( git_oid_cpy(&head->oid, oid); + git_oid_fmt(head->oid_str, oid); + head->oid_str[GIT_OID_HEXSZ] = '\0'; + if ((error = git_commit_lookup(&head->commit, repo, &head->oid)) < 0) { git_merge_head_free(head); return error; diff --git a/src/merge.h b/src/merge.h index 0ecad6e3e..d7d1c67b7 100644 --- a/src/merge.h +++ b/src/merge.h @@ -114,9 +114,20 @@ struct git_merge_head { char *remote_url; git_oid oid; + char oid_str[GIT_OID_HEXSZ+1]; git_commit *commit; }; +/** Internal structure for merge results */ +struct git_merge_result { + bool is_uptodate; + + bool is_fastforward; + git_oid fastforward_oid; + + git_index *index; +}; + int git_merge__bases_many( git_commit_list **out, git_revwalk *walk, diff --git a/tests-clar/merge/merge_helpers.c b/tests-clar/merge/merge_helpers.c index ddcb93ff6..43619be0d 100644 --- a/tests-clar/merge/merge_helpers.c +++ b/tests-clar/merge/merge_helpers.c @@ -52,6 +52,29 @@ int merge_trees_from_branches( return 0; } +int merge_branches(git_merge_result **result, git_repository *repo, const char *ours_branch, const char *theirs_branch, git_merge_opts *opts) +{ + git_reference *head_ref, *theirs_ref; + git_merge_head *theirs_head; + git_checkout_opts head_checkout_opts = GIT_CHECKOUT_OPTS_INIT; + + head_checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_reference_symbolic_create(&head_ref, repo, "HEAD", ours_branch, 1)); + cl_git_pass(git_checkout_head(repo, &head_checkout_opts)); + + cl_git_pass(git_reference_lookup(&theirs_ref, repo, theirs_branch)); + cl_git_pass(git_merge_head_from_ref(&theirs_head, repo, theirs_ref)); + + cl_git_pass(git_merge(result, repo, (const git_merge_head **)&theirs_head, 1, opts)); + + git_reference_free(head_ref); + git_reference_free(theirs_ref); + git_merge_head_free(theirs_head); + + return 0; +} + void merge__dump_index_entries(git_vector *index_entries) { size_t i; diff --git a/tests-clar/merge/merge_helpers.h b/tests-clar/merge/merge_helpers.h index cb718e01a..ae3274437 100644 --- a/tests-clar/merge/merge_helpers.h +++ b/tests-clar/merge/merge_helpers.h @@ -44,6 +44,9 @@ int merge_trees_from_branches( const char *ours_name, const char *theirs_name, git_merge_tree_opts *opts); +int merge_branches(git_merge_result **result, git_repository *repo, + const char *ours_branch, const char *theirs_branch, git_merge_opts *opts); + int merge_test_diff_list(git_merge_diff_list *diff_list, const struct merge_index_entry expected[], size_t expected_len); int merge_test_merge_conflicts(git_vector *conflicts, const struct merge_index_conflict_data expected[], size_t expected_len); diff --git a/tests-clar/merge/workdir/fastforward.c b/tests-clar/merge/workdir/fastforward.c new file mode 100644 index 000000000..861f38354 --- /dev/null +++ b/tests-clar/merge/workdir/fastforward.c @@ -0,0 +1,148 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "git2/sys/index.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "refs.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "merge-resolve" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +#define THEIRS_FASTFORWARD_BRANCH "ff_branch" +#define THEIRS_FASTFORWARD_OID "fd89f8cffb663ac89095a0f9764902e93ceaca6a" + +#define THEIRS_NOFASTFORWARD_BRANCH "branch" +#define THEIRS_NOFASTFORWARD_OID "7cb63eed597130ba4abb87b3e544b85021905520" + + +// Fixture setup and teardown +void test_merge_workdir_fastforward__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); + git_repository_index(&repo_index, repo); +} + +void test_merge_workdir_fastforward__cleanup(void) +{ + git_index_free(repo_index); + cl_git_sandbox_cleanup(); +} + +static git_merge_result *merge_fastforward_branch(int flags) +{ + git_reference *their_ref; + git_merge_head *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + opts.merge_flags = flags; + + cl_git_pass(git_reference_lookup(&their_ref, repo, GIT_REFS_HEADS_DIR THEIRS_FASTFORWARD_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref)); + + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); + + git_merge_head_free(their_heads[0]); + git_reference_free(their_ref); + + return result; +} + +void test_merge_workdir_fastforward__fastforward(void) +{ + git_merge_result *result; + git_oid expected, ff_oid; + + cl_git_pass(git_oid_fromstr(&expected, THEIRS_FASTFORWARD_OID)); + + cl_assert(result = merge_fastforward_branch(0)); + cl_assert(git_merge_result_is_fastforward(result)); + cl_git_pass(git_merge_result_fastforward_oid(&ff_oid, result)); + cl_assert(git_oid_cmp(&ff_oid, &expected) == 0); + + git_merge_result_free(result); +} + +void test_merge_workdir_fastforward__fastforward_only(void) +{ + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + git_reference *their_ref; + git_merge_head *their_head; + int error; + + opts.merge_flags = GIT_MERGE_FASTFORWARD_ONLY; + + cl_git_pass(git_reference_lookup(&their_ref, repo, GIT_REFS_HEADS_DIR THEIRS_NOFASTFORWARD_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref)); + + cl_git_fail((error = git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts))); + cl_assert(error == GIT_ENONFASTFORWARD); + + git_merge_head_free(their_head); + git_reference_free(their_ref); +} + +void test_merge_workdir_fastforward__no_fastforward(void) +{ + git_merge_result *result; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, + { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" }, + { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, + { 0100644, "bd9cb4cd0a770cb9adcb5fce212142ef40ea1c35", 0, "changed-in-master.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, + { 0100644, "364bbe4ce80c7bd31e6307dce77d46e3e1759fb3", 0, "new-in-ff.txt" }, + { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, + { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, + }; + + cl_assert(result = merge_fastforward_branch(GIT_MERGE_NO_FASTFORWARD)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + git_merge_result_free(result); +} + +void test_merge_workdir_fastforward__uptodate(void) +{ + git_reference *their_ref; + git_merge_head *their_heads[1]; + git_merge_result *result; + + cl_git_pass(git_reference_lookup(&their_ref, repo, GIT_HEAD_FILE)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref)); + + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, NULL)); + + cl_assert(git_merge_result_is_uptodate(result)); + + git_merge_head_free(their_heads[0]); + git_reference_free(their_ref); + git_merge_result_free(result); +} + +void test_merge_workdir_fastforward__uptodate_merging_prev_commit(void) +{ + git_oid their_oid; + git_merge_head *their_heads[1]; + git_merge_result *result; + + cl_git_pass(git_oid_fromstr(&their_oid, "c607fc30883e335def28cd686b51f6cfa02b06ec")); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oid)); + + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, NULL)); + + cl_assert(git_merge_result_is_uptodate(result)); + + git_merge_head_free(their_heads[0]); + git_merge_result_free(result); +} + diff --git a/tests-clar/merge/workdir/renames.c b/tests-clar/merge/workdir/renames.c new file mode 100644 index 000000000..d38397983 --- /dev/null +++ b/tests-clar/merge/workdir/renames.c @@ -0,0 +1,156 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "buffer.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "fileops.h" +#include "refs.h" + +static git_repository *repo; + +#define TEST_REPO_PATH "merge-resolve" + +#define BRANCH_RENAME_OURS "rename_conflict_ours" +#define BRANCH_RENAME_THEIRS "rename_conflict_theirs" + +// Fixture setup and teardown +void test_merge_workdir_renames__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); +} + +void test_merge_workdir_renames__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_merge_workdir_renames__renames(void) +{ + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, + { 0100644, "8aac75de2a34b4d340bf62a6e58197269cb55797", 0, "0b-rewritten-in-ours.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, + { 0100644, "7edc726325da726751a4195e434e4377b0f67f9a", 0, "0c-rewritten-in-theirs.txt" }, + { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, + { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, + { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, + { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, + { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-newname-in-ours-added-in-theirs.txt~HEAD" }, + { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 0, "4a-newname-in-ours-added-in-theirs.txt~rename_conflict_theirs" }, + { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 0, "4b-newname-in-theirs-added-in-ours.txt~HEAD" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 0, "4b-newname-in-theirs-added-in-ours.txt~rename_conflict_theirs" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 0, "5a-newname-in-ours-added-in-theirs.txt~HEAD" }, + { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 0, "5a-newname-in-ours-added-in-theirs.txt~rename_conflict_theirs" }, + { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 0, "5b-newname-in-theirs-added-in-ours.txt~HEAD" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 0, "5b-newname-in-theirs-added-in-ours.txt~rename_conflict_theirs" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-theirs.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt~HEAD" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" }, + }; + + opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; + opts.merge_tree_opts.rename_threshold = 50; + + cl_git_pass(merge_branches(&result, repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &opts)); + cl_assert(merge_test_workdir(repo, merge_index_entries, 24)); + + git_merge_result_free(result); +} + +void test_merge_workdir_renames__ours(void) +{ + git_index *index; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, + { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 0, "0b-rewritten-in-ours.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, + { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 0, "0c-rewritten-in-theirs.txt" }, + { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, + { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, + { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, + { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, + { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 0, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 0, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 0, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 0, "5b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-ours.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed-side-2.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt" }, + }; + + opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; + opts.merge_tree_opts.rename_threshold = 50; + opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS; + + cl_git_pass(merge_branches(&result, repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &opts)); + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_write(index)); + cl_assert(merge_test_workdir(repo, merge_index_entries, 20)); + + git_merge_result_free(result); + git_index_free(index); +} + +void test_merge_workdir_renames__similar(void) +{ + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + /* + * Note: this differs slightly from the core git merge result - there, 4a is + * tracked as a rename/delete instead of a rename/add and the theirs side + * is not placed in workdir in any form. + */ + struct merge_index_entry merge_index_entries[] = { + { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, + { 0100644, "8aac75de2a34b4d340bf62a6e58197269cb55797", 0, "0b-rewritten-in-ours.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, + { 0100644, "7edc726325da726751a4195e434e4377b0f67f9a", 0, "0c-rewritten-in-theirs.txt" }, + { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, + { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, + { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, + { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, + { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-newname-in-ours-added-in-theirs.txt~HEAD" }, + { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 0, "4a-newname-in-ours-added-in-theirs.txt~rename_conflict_theirs" }, + { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 0, "4b-newname-in-theirs-added-in-ours.txt~HEAD" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 0, "4b-newname-in-theirs-added-in-ours.txt~rename_conflict_theirs" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 0, "5a-newname-in-ours-added-in-theirs.txt~HEAD" }, + { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 0, "5a-newname-in-ours-added-in-theirs.txt~rename_conflict_theirs" }, + { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 0, "5b-newname-in-theirs-added-in-ours.txt~HEAD" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 0, "5b-newname-in-theirs-added-in-ours.txt~rename_conflict_theirs" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-theirs.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt~HEAD" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" }, + }; + + opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; + opts.merge_tree_opts.rename_threshold = 50; + + cl_git_pass(merge_branches(&result, repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &opts)); + cl_assert(merge_test_workdir(repo, merge_index_entries, 24)); + + git_merge_result_free(result); +} + diff --git a/tests-clar/merge/workdir/setup.c b/tests-clar/merge/workdir/setup.c index 1c8403221..511106a58 100644 --- a/tests-clar/merge/workdir/setup.c +++ b/tests-clar/merge/workdir/setup.c @@ -71,7 +71,7 @@ static void write_file_contents(const char *filename, const char *output) git_buf_free(&file_path_buf); } -/* git merge --no-ff octo1 */ +/* git merge octo1 */ void test_merge_workdir_setup__one_branch(void) { git_oid our_oid; @@ -97,7 +97,33 @@ void test_merge_workdir_setup__one_branch(void) git_merge_head_free(their_heads[0]); } -/* git merge --no-ff 16f825815cfd20a07a75c71554e82d8eede0b061 */ +/* git merge --no-ff octo1 */ +void test_merge_workdir_setup__no_fastforward(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_merge_head *our_head, *their_heads[1]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, GIT_MERGE_NO_FASTFORWARD)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'\n")); + + git_reference_free(octo1_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); +} + +/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 */ void test_merge_workdir_setup__one_oid(void) { git_oid our_oid; @@ -964,3 +990,65 @@ void test_merge_workdir_setup__head_foreach_octopus(void) cl_assert(cb_data.i == cb_data.len); } + +void test_merge_workdir_setup__retained_after_success(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_merge_head *our_head, *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + opts.merge_flags |= GIT_MERGE_NO_FASTFORWARD; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_heads[0], 1, &opts)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'\n")); + + git_reference_free(octo1_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); +} + +void test_merge_workdir_setup__removed_after_failure(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_merge_head *our_head, *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + opts.merge_flags |= GIT_MERGE_NO_FASTFORWARD; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_rewritefile("merge-resolve/new-in-octo1.txt", + "Conflicting file!\n\nMerge will fail!\n"); + + cl_git_fail(git_merge(&result, repo, &their_heads[0], 1, &opts)); + + cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_HEAD_FILE)); + cl_assert(!git_path_exists("merge-resolve/" GIT_ORIG_HEAD_FILE)); + cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_MODE_FILE)); + cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_MSG_FILE)); + + git_reference_free(octo1_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); +} diff --git a/tests-clar/merge/workdir/simple.c b/tests-clar/merge/workdir/simple.c new file mode 100644 index 000000000..4a3b86ee4 --- /dev/null +++ b/tests-clar/merge/workdir/simple.c @@ -0,0 +1,491 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "buffer.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "refs.h" +#include "fileops.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "merge-resolve" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +#define THEIRS_SIMPLE_BRANCH "branch" +#define THEIRS_SIMPLE_OID "7cb63eed597130ba4abb87b3e544b85021905520" + +#define THEIRS_UNRELATED_BRANCH "unrelated" +#define THEIRS_UNRELATED_OID "55b4e4687e7a0d9ca367016ed930f385d4022e6f" +#define THEIRS_UNRELATED_PARENT "d6cf6c7741b3316826af1314042550c97ded1d50" + +#define OURS_DIRECTORY_FILE "df_side1" +#define THEIRS_DIRECTORY_FILE "fc90237dc4891fa6c69827fc465632225e391618" + + +/* Non-conflicting files, index entries are common to every merge operation */ +#define ADDED_IN_MASTER_INDEX_ENTRY \ + { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, \ + "added-in-master.txt" } +#define AUTOMERGEABLE_INDEX_ENTRY \ + { 0100644, "f2e1550a0c9e53d5811175864a29536642ae3821", 0, \ + "automergeable.txt" } +#define CHANGED_IN_BRANCH_INDEX_ENTRY \ + { 0100644, "4eb04c9e79e88f6640d01ff5b25ca2a60764f216", 0, \ + "changed-in-branch.txt" } +#define CHANGED_IN_MASTER_INDEX_ENTRY \ + { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, \ + "changed-in-master.txt" } +#define UNCHANGED_INDEX_ENTRY \ + { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, \ + "unchanged.txt" } + +/* Unrelated files */ +#define UNRELATED_NEW1 \ + { 0100644, "ef58fdd8086c243bdc81f99e379acacfd21d32d6", 0, \ + "new-in-unrelated1.txt" } +#define UNRELATED_NEW2 \ + { 0100644, "948ba6e701c1edab0c2d394fb7c5538334129793", 0, \ + "new-in-unrelated2.txt" } + +/* Expected REUC entries */ +#define AUTOMERGEABLE_REUC_ENTRY \ + { "automergeable.txt", 0100644, 0100644, 0100644, \ + "6212c31dab5e482247d7977e4f0dd3601decf13b", \ + "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", \ + "058541fc37114bfc1dddf6bd6bffc7fae5c2e6fe" } +#define CONFLICTING_REUC_ENTRY \ + { "conflicting.txt", 0100644, 0100644, 0100644, \ + "d427e0b2e138501a3d15cc376077a3631e15bd46", \ + "4e886e602529caa9ab11d71f86634bd1b6e0de10", \ + "2bd0a343aeef7a2cf0d158478966a6e587ff3863" } +#define REMOVED_IN_BRANCH_REUC_ENTRY \ + { "removed-in-branch.txt", 0100644, 0100644, 0, \ + "dfe3f22baa1f6fce5447901c3086bae368de6bdd", \ + "dfe3f22baa1f6fce5447901c3086bae368de6bdd", \ + "" } +#define REMOVED_IN_MASTER_REUC_ENTRY \ + { "removed-in-master.txt", 0100644, 0, 0100644, \ + "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", \ + "", \ + "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5" } + +#define AUTOMERGEABLE_MERGED_FILE \ + "this file is changed in master\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is changed in branch\n" + +#define AUTOMERGEABLE_MERGED_FILE_CRLF \ + "this file is changed in master\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is changed in branch\r\n" + +#define CONFLICTING_DIFF3_FILE \ + "<<<<<<< HEAD\n" \ + "this file is changed in master and branch\n" \ + "=======\n" \ + "this file is changed in branch and master\n" \ + ">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n" + +// Fixture setup and teardown +void test_merge_workdir_simple__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); + git_repository_index(&repo_index, repo); +} + +void test_merge_workdir_simple__cleanup(void) +{ + git_index_free(repo_index); + cl_git_sandbox_cleanup(); +} + +static git_merge_result *merge_simple_branch(int automerge_flags, int checkout_strategy) +{ + git_oid their_oids[1]; + git_merge_head *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_SIMPLE_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0])); + + opts.merge_tree_opts.automerge_flags = automerge_flags; + opts.checkout_opts.checkout_strategy = checkout_strategy; + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); + + git_merge_head_free(their_heads[0]); + + return result; +} + +static void set_core_autocrlf_to(git_repository *repo, bool value) +{ + git_config *cfg; + + cl_git_pass(git_repository_config(&cfg, repo)); + cl_git_pass(git_config_set_bool(cfg, "core.autocrlf", value)); + + git_config_free(cfg); +} + +void test_merge_workdir_simple__automerge(void) +{ + git_index *index; + const git_index_entry *entry; + git_merge_result *result; + git_buf automergeable_buf = GIT_BUF_INIT; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + + { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, + { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, + + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY + }; + + + set_core_autocrlf_to(repo, false); + + cl_assert(result = merge_simple_branch(0, 0)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_git_pass(git_futils_readbuffer(&automergeable_buf, + TEST_REPO_PATH "/automergeable.txt")); + cl_assert(strcmp(automergeable_buf.ptr, AUTOMERGEABLE_MERGED_FILE) == 0); + git_buf_free(&automergeable_buf); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); + cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); + + git_merge_result_free(result); + + git_repository_index(&index, repo); + + cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL); + cl_assert(entry->file_size == strlen(AUTOMERGEABLE_MERGED_FILE)); + + git_index_free(index); +} + +void test_merge_workdir_simple__automerge_crlf(void) +{ +#ifdef GIT_WIN32 + git_index *index; + const git_index_entry *entry; + + git_merge_result *result; + git_buf automergeable_buf = GIT_BUF_INIT; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + + { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, + { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, + + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY + }; + + set_core_autocrlf_to(repo, true); + + cl_assert(result = merge_simple_branch(0, 0)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_git_pass(git_futils_readbuffer(&automergeable_buf, + TEST_REPO_PATH "/automergeable.txt")); + cl_assert(strcmp(automergeable_buf.ptr, AUTOMERGEABLE_MERGED_FILE_CRLF) == 0); + git_buf_free(&automergeable_buf); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); + cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); + + git_merge_result_free(result); + + git_repository_index(&index, repo); + + cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL); + cl_assert(entry->file_size == strlen(AUTOMERGEABLE_MERGED_FILE_CRLF)); + + git_index_free(index); +#endif /* GIT_WIN32 */ +} + +void test_merge_workdir_simple__diff3(void) +{ + git_merge_result *result; + git_buf conflicting_buf = GIT_BUF_INIT; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + + { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, + { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, + + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY + }; + + cl_assert(result = merge_simple_branch(0, 0)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_git_pass(git_futils_readbuffer(&conflicting_buf, + TEST_REPO_PATH "/conflicting.txt")); + cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_DIFF3_FILE) == 0); + git_buf_free(&conflicting_buf); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); + cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); + + git_merge_result_free(result); +} + +void test_merge_workdir_simple__checkout_ours(void) +{ + git_merge_result *result; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + + { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, + { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, + + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY + }; + + cl_assert(result = merge_simple_branch(0, GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); + cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); + + cl_assert(git_path_exists(TEST_REPO_PATH "/conflicting.txt")); + + git_merge_result_free(result); +} + +void test_merge_workdir_simple__favor_ours(void) +{ + git_merge_result *result; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + CONFLICTING_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY, + }; + + cl_assert(result = merge_simple_branch(GIT_MERGE_AUTOMERGE_FAVOR_OURS, 0)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 6)); + cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4)); + + git_merge_result_free(result); +} + +void test_merge_workdir_simple__favor_theirs(void) +{ + git_merge_result *result; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 0, "conflicting.txt" }, + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + CONFLICTING_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY, + }; + + cl_assert(result = merge_simple_branch(GIT_MERGE_AUTOMERGE_FAVOR_THEIRS, 0)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 6)); + cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4)); + + git_merge_result_free(result); +} + +void test_merge_workdir_simple__directory_file(void) +{ + git_reference *head; + git_oid their_oids[1], head_commit_id; + git_merge_head *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + git_commit *head_commit; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "49130a28ef567af9a6a6104c38773fedfa5f9742", 2, "dir-10" }, + { 0100644, "6c06dcd163587c2cc18be44857e0b71116382aeb", 3, "dir-10" }, + { 0100644, "43aafd43bea779ec74317dc361f45ae3f532a505", 0, "dir-6" }, + { 0100644, "a031a28ae70e33a641ce4b8a8f6317f1ab79dee4", 3, "dir-7" }, + { 0100644, "5012fd565b1393bdfda1805d4ec38ce6619e1fd1", 1, "dir-7/file.txt" }, + { 0100644, "a5563304ddf6caba25cb50323a2ea6f7dbfcadca", 2, "dir-7/file.txt" }, + { 0100644, "e9ad6ec3e38364a3d07feda7c4197d4d845c53b5", 0, "dir-8" }, + { 0100644, "3ef4d30382ca33fdeba9fda895a99e0891ba37aa", 2, "dir-9" }, + { 0100644, "fc4c636d6515e9e261f9260dbcf3cc6eca97ea08", 1, "dir-9/file.txt" }, + { 0100644, "76ab0e2868197ec158ddd6c78d8a0d2fd73d38f9", 3, "dir-9/file.txt" }, + { 0100644, "5c2411f8075f48a6b2fdb85ebc0d371747c4df15", 0, "file-1/new" }, + { 0100644, "a39a620dae5bc8b4e771cd4d251b7d080401a21e", 1, "file-2" }, + { 0100644, "d963979c237d08b6ba39062ee7bf64c7d34a27f8", 2, "file-2" }, + { 0100644, "5c341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d", 0, "file-2/new" }, + { 0100644, "9efe7723802d4305142eee177e018fee1572c4f4", 0, "file-3/new" }, + { 0100644, "bacac9b3493509aa15e1730e1545fc0919d1dae0", 1, "file-4" }, + { 0100644, "7663fce0130db092936b137cabd693ec234eb060", 3, "file-4" }, + { 0100644, "e49f917b448d1340b31d76e54ba388268fd4c922", 0, "file-4/new" }, + { 0100644, "cab2cf23998b40f1af2d9d9a756dc9e285a8df4b", 2, "file-5/new" }, + { 0100644, "f5504f36e6f4eb797a56fc5bac6c6c7f32969bf2", 3, "file-5/new" }, + }; + + cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_DIR OURS_DIRECTORY_FILE, 1)); + cl_git_pass(git_reference_name_to_id(&head_commit_id, repo, GIT_HEAD_FILE)); + cl_git_pass(git_commit_lookup(&head_commit, repo, &head_commit_id)); + cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD)); + + cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_DIRECTORY_FILE)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0])); + + opts.merge_tree_opts.automerge_flags = 0; + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 20)); + + git_reference_free(head); + git_commit_free(head_commit); + git_merge_head_free(their_heads[0]); + git_merge_result_free(result); +} + +void test_merge_workdir_simple__unrelated(void) +{ + git_oid their_oids[1]; + git_merge_head *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, + { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" }, + { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, + { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, + { 0100644, "ef58fdd8086c243bdc81f99e379acacfd21d32d6", 0, "new-in-unrelated1.txt" }, + { 0100644, "948ba6e701c1edab0c2d394fb7c5538334129793", 0, "new-in-unrelated2.txt" }, + { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, + { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, + }; + + cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_PARENT)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0])); + + opts.merge_tree_opts.automerge_flags = 0; + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 9)); + + git_merge_head_free(their_heads[0]); + git_merge_result_free(result); +} + +void test_merge_workdir_simple__unrelated_with_conflicts(void) +{ + git_oid their_oids[1]; + git_merge_head *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, + { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 2, "automergeable.txt" }, + { 0100644, "d07ec190c306ec690bac349e87d01c4358e49bb2", 3, "automergeable.txt" }, + { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, + { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, + { 0100644, "4b253da36a0ae8bfce63aeabd8c5b58429925594", 3, "conflicting.txt" }, + { 0100644, "ef58fdd8086c243bdc81f99e379acacfd21d32d6", 0, "new-in-unrelated1.txt" }, + { 0100644, "948ba6e701c1edab0c2d394fb7c5538334129793", 0, "new-in-unrelated2.txt" }, + { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, + { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, + }; + + cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0])); + + opts.merge_tree_opts.automerge_flags = 0; + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 11)); + + git_merge_head_free(their_heads[0]); + git_merge_result_free(result); +} + diff --git a/tests-clar/merge/workdir/trivial.c b/tests-clar/merge/workdir/trivial.c new file mode 100644 index 000000000..d20d89879 --- /dev/null +++ b/tests-clar/merge/workdir/trivial.c @@ -0,0 +1,341 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "git2/sys/index.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "refs.h" +#include "fileops.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "merge-resolve" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + + +// Fixture setup and teardown +void test_merge_workdir_trivial__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); + git_repository_index(&repo_index, repo); +} + +void test_merge_workdir_trivial__cleanup(void) +{ + git_index_free(repo_index); + cl_git_sandbox_cleanup(); +} + + +static int merge_trivial(const char *ours, const char *theirs, bool automerge) +{ + git_buf branch_buf = GIT_BUF_INIT; + git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; + git_reference *our_ref, *their_ref; + git_merge_head *their_heads[1]; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + git_merge_result *result; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + opts.merge_tree_opts.automerge_flags |= automerge ? 0 : GIT_MERGE_AUTOMERGE_NONE; + + git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours); + cl_git_pass(git_reference_symbolic_create(&our_ref, repo, "HEAD", branch_buf.ptr, 1)); + + cl_git_pass(git_checkout_head(repo, &checkout_opts)); + + git_buf_clear(&branch_buf); + git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs); + cl_git_pass(git_reference_lookup(&their_ref, repo, branch_buf.ptr)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref)); + + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); + + git_buf_free(&branch_buf); + git_reference_free(our_ref); + git_reference_free(their_ref); + git_merge_head_free(their_heads[0]); + git_merge_result_free(result); + + return 0; +} + +static int merge_trivial_conflict_entrycount(void) +{ + const git_index_entry *entry; + size_t count = 0; + size_t i; + + for (i = 0; i < git_index_entrycount(repo_index); i++) { + cl_assert(entry = git_index_get_byindex(repo_index, i)); + + if (git_index_entry_stage(entry) > 0) + count++; + } + + return count; +} + +/* 2ALT: ancest:(empty)+, head:*empty*, remote:remote = result:remote */ +void test_merge_workdir_trivial__2alt(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-2alt", "trivial-2alt-branch", 0)); + + cl_assert(entry = git_index_get_bypath(repo_index, "new-in-branch.txt", 0)); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 3ALT: ancest:(empty)+, head:head, remote:*empty* = result:head */ +void test_merge_workdir_trivial__3alt(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-3alt", "trivial-3alt-branch", 0)); + + cl_assert(entry = git_index_get_bypath(repo_index, "new-in-3alt.txt", 0)); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 4: ancest:(empty)^, head:head, remote:remote = result:no merge */ +void test_merge_workdir_trivial__4(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-4", "trivial-4-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "new-and-different.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "new-and-different.txt", 2)); + cl_assert(entry = git_index_get_bypath(repo_index, "new-and-different.txt", 3)); +} + +/* 5ALT: ancest:*, head:head, remote:head = result:head */ +void test_merge_workdir_trivial__5alt_1(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-5alt-1", "trivial-5alt-1-branch", 0)); + + cl_assert(entry = git_index_get_bypath(repo_index, "new-and-same.txt", 0)); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 5ALT: ancest:*, head:head, remote:head = result:head */ +void test_merge_workdir_trivial__5alt_2(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-5alt-2", "trivial-5alt-2-branch", 0)); + + cl_assert(entry = git_index_get_bypath(repo_index, "modified-to-same.txt", 0)); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */ +void test_merge_workdir_trivial__6(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-6", "trivial-6-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 1); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 1)); +} + +/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */ +void test_merge_workdir_trivial__6_automerge(void) +{ + const git_index_entry *entry; + const git_index_reuc_entry *reuc; + + cl_git_pass(merge_trivial("trivial-6", "trivial-6-branch", 1)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 1); + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "removed-in-both.txt")); + + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */ +void test_merge_workdir_trivial__8(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-8", "trivial-8-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 3)); +} + +/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */ +void test_merge_workdir_trivial__8_automerge(void) +{ + const git_index_entry *entry; + const git_index_reuc_entry *reuc; + + cl_git_pass(merge_trivial("trivial-8", "trivial-8-branch", 1)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 0)) == NULL); + + cl_assert(git_index_reuc_entrycount(repo_index) == 1); + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "removed-in-8.txt")); + + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */ +void test_merge_workdir_trivial__7(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-7", "trivial-7-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 3)); +} + +/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */ +void test_merge_workdir_trivial__7_automerge(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-7", "trivial-7-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 3)); +} + +/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */ +void test_merge_workdir_trivial__10(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-10", "trivial-10-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 2)); +} + +/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */ +void test_merge_workdir_trivial__10_automerge(void) +{ + const git_index_entry *entry; + const git_index_reuc_entry *reuc; + + cl_git_pass(merge_trivial("trivial-10", "trivial-10-branch", 1)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 0)) == NULL); + + cl_assert(git_index_reuc_entrycount(repo_index) == 1); + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "removed-in-10-branch.txt")); + + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */ +void test_merge_workdir_trivial__9(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-9", "trivial-9-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 2)); +} + +/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */ +void test_merge_workdir_trivial__9_automerge(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-9", "trivial-9-branch", 1)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 2)); +} + +/* 13: ancest:ancest+, head:head, remote:ancest = result:head */ +void test_merge_workdir_trivial__13(void) +{ + const git_index_entry *entry; + git_oid expected_oid; + + cl_git_pass(merge_trivial("trivial-13", "trivial-13-branch", 0)); + + cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-13.txt", 0)); + cl_git_pass(git_oid_fromstr(&expected_oid, "1cff9ec6a47a537380dedfdd17c9e76d74259a2b")); + cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0); + + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 14: ancest:ancest+, head:ancest, remote:remote = result:remote */ +void test_merge_workdir_trivial__14(void) +{ + const git_index_entry *entry; + git_oid expected_oid; + + cl_git_pass(merge_trivial("trivial-14", "trivial-14-branch", 0)); + + cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-14-branch.txt", 0)); + cl_git_pass(git_oid_fromstr(&expected_oid, "26153a3ff3649b6c2bb652d3f06878c6e0a172f9")); + cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0); + + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 11: ancest:ancest+, head:head, remote:remote = result:no merge */ +void test_merge_workdir_trivial__11(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-11", "trivial-11-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 3); + cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 2)); + cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 3)); +} -- cgit v1.2.1 From 8d22773f4b2364b4cdc631a2d7db065834f80433 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 5 Nov 2013 16:44:10 +0100 Subject: Plug git_merge() related leaks --- src/merge.c | 1 + tests-clar/merge/workdir/setup.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/merge.c b/src/merge.c index 973d4445c..2cbf531f9 100644 --- a/src/merge.c +++ b/src/merge.c @@ -2451,6 +2451,7 @@ int git_merge( on_error: git_repository_merge_cleanup(repo); + git_index_free(index_new); git__free(result); done: diff --git a/tests-clar/merge/workdir/setup.c b/tests-clar/merge/workdir/setup.c index 511106a58..463dee06e 100644 --- a/tests-clar/merge/workdir/setup.c +++ b/tests-clar/merge/workdir/setup.c @@ -1019,6 +1019,7 @@ void test_merge_workdir_setup__retained_after_success(void) git_merge_head_free(our_head); git_merge_head_free(their_heads[0]); + git_merge_result_free(result); } void test_merge_workdir_setup__removed_after_failure(void) @@ -1051,4 +1052,5 @@ void test_merge_workdir_setup__removed_after_failure(void) git_merge_head_free(our_head); git_merge_head_free(their_heads[0]); + git_merge_result_free(result); } -- cgit v1.2.1 From 39b1ad7f15d19837b3a25690c796ac0a1ac2720e Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 5 Nov 2013 16:14:20 +0100 Subject: Plug configuration file search paths leaks --- src/fileops.c | 2 +- src/fileops.h | 5 +++++ tests-clar/repo/config.c | 8 ++++++++ tests-clar/repo/open.c | 2 ++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/fileops.c b/src/fileops.c index 1c27b277d..5763b370b 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -618,7 +618,7 @@ static git_futils_dirs_guess_cb git_futils__dir_guess[GIT_FUTILS_DIR__MAX] = { git_futils_guess_template_dirs, }; -static void git_futils_dirs_global_shutdown(void) +void git_futils_dirs_global_shutdown(void) { int i; for (i = 0; i < GIT_FUTILS_DIR__MAX; ++i) diff --git a/src/fileops.h b/src/fileops.h index 59a6a21a7..636c9b67d 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -399,4 +399,9 @@ extern int git_futils_filestamp_check( extern void git_futils_filestamp_set( git_futils_filestamp *tgt, const git_futils_filestamp *src); +/** + * Free the configuration file search paths. + */ +extern void git_futils_dirs_global_shutdown(void); + #endif /* INCLUDE_fileops_h__ */ diff --git a/tests-clar/repo/config.c b/tests-clar/repo/config.c index b8971bb6b..11abd42bc 100644 --- a/tests-clar/repo/config.c +++ b/tests-clar/repo/config.c @@ -46,6 +46,8 @@ void test_repo_config__open_missing_global(void) git_config_free(global); git_config_free(config); git_repository_free(repo); + + git_futils_dirs_global_shutdown(); } void test_repo_config__open_missing_global_with_separators(void) @@ -73,6 +75,8 @@ void test_repo_config__open_missing_global_with_separators(void) git_config_free(global); git_config_free(config); git_repository_free(repo); + + git_futils_dirs_global_shutdown(); } #include "repository.h" @@ -101,6 +105,8 @@ void test_repo_config__read_no_configs(void) cl_assert_equal_i(GIT_ABBREV_DEFAULT, val); git_repository_free(repo); + git_futils_dirs_global_shutdown(); + /* with just system */ cl_must_pass(p_mkdir("alternate/1", 0777)); @@ -197,4 +203,6 @@ void test_repo_config__read_no_configs(void) cl_assert(!git_path_exists("empty_standard_repo/.git/config")); cl_assert(!git_path_exists("alternate/3/.gitconfig")); + + git_futils_dirs_global_shutdown(); } diff --git a/tests-clar/repo/open.c b/tests-clar/repo/open.c index f386612a7..7cfe041c2 100644 --- a/tests-clar/repo/open.c +++ b/tests-clar/repo/open.c @@ -322,6 +322,8 @@ void test_repo_open__no_config(void) git_config_free(config); git_repository_free(repo); cl_fixture_cleanup("empty_standard_repo"); + + git_futils_dirs_global_shutdown(); } void test_repo_open__force_bare(void) -- cgit v1.2.1 From fe294b95d1f04ceb4d279b312d3f88375dbe0dc9 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 5 Nov 2013 10:37:50 -0800 Subject: Incorporate feedback --- src/netops.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/netops.c b/src/netops.c index 72172f39b..1a0d102d7 100644 --- a/src/netops.c +++ b/src/netops.c @@ -703,24 +703,24 @@ int gitno_extract_url_parts( _path = url+u.field_data[UF_PATH].off; _userinfo = url+u.field_data[UF_USERINFO].off; - if (u.field_data[UF_HOST].len) { + if (u.field_set & (1 << UF_HOST)) { *host = git__substrdup(_host, u.field_data[UF_HOST].len); GITERR_CHECK_ALLOC(*host); } - if (u.field_data[UF_PORT].len) + if (u.field_set & (1 << UF_PORT)) *port = git__substrdup(_port, u.field_data[UF_PORT].len); else *port = git__strdup(default_port); GITERR_CHECK_ALLOC(*port); - if (u.field_data[UF_PATH].len) { + if (u.field_set & (1 << UF_PATH)) { *path = git__substrdup(_path, u.field_data[UF_PATH].len); GITERR_CHECK_ALLOC(*path); } - if (u.field_data[UF_USERINFO].len) { - const char *colon = strchr(_userinfo, ':'); + if (u.field_set & (1 << UF_USERINFO)) { + const char *colon = memchr(_userinfo, ':', u.field_data[UF_USERINFO].len); if (colon && (colon - _userinfo) < u.field_data[UF_USERINFO].len) { *username = unescape(git__substrdup(_userinfo, colon - _userinfo)); *password = unescape(git__substrdup(colon+1, u.field_data[UF_USERINFO].len - (colon+1-_userinfo))); -- cgit v1.2.1 From d6eb3f9ce7f3b794d8e9ec2bb52bf995dd32cde9 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 5 Nov 2013 10:54:44 -0800 Subject: Remove unnecessary check --- src/netops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/netops.c b/src/netops.c index 1a0d102d7..ce49116e3 100644 --- a/src/netops.c +++ b/src/netops.c @@ -721,7 +721,7 @@ int gitno_extract_url_parts( if (u.field_set & (1 << UF_USERINFO)) { const char *colon = memchr(_userinfo, ':', u.field_data[UF_USERINFO].len); - if (colon && (colon - _userinfo) < u.field_data[UF_USERINFO].len) { + if (colon) { *username = unescape(git__substrdup(_userinfo, colon - _userinfo)); *password = unescape(git__substrdup(colon+1, u.field_data[UF_USERINFO].len - (colon+1-_userinfo))); GITERR_CHECK_ALLOC(*password); -- cgit v1.2.1 From aad5403fe96a88689b9d22a732d464c64a72f8ff Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 5 Nov 2013 10:55:54 -0800 Subject: Fix MSVC 64-bit warnings --- src/blame.c | 18 +++++++++--------- src/blame_git.c | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/blame.c b/src/blame.c index 192e296d8..0b4dafbf2 100644 --- a/src/blame.c +++ b/src/blame.c @@ -20,7 +20,7 @@ static int hunk_byfinalline_search_cmp(const void *key, const void *entry) { - uint32_t lineno = *(size_t*)key; + uint16_t lineno = (uint16_t)*(size_t*)key; git_blame_hunk *hunk = (git_blame_hunk*)entry; if (lineno < hunk->final_start_line_number) @@ -145,7 +145,7 @@ void git_blame_free(git_blame *blame) uint32_t git_blame_get_hunk_count(git_blame *blame) { assert(blame); - return blame->hunks.length; + return (uint32_t)blame->hunks.length; } const git_blame_hunk *git_blame_get_hunk_byindex(git_blame *blame, uint32_t index) @@ -160,7 +160,7 @@ const git_blame_hunk *git_blame_get_hunk_byline(git_blame *blame, uint32_t linen assert(blame); if (!git_vector_bsearch2( &i, &blame->hunks, hunk_byfinalline_search_cmp, &lineno)) { - return git_blame_get_hunk_byindex(blame, i); + return git_blame_get_hunk_byindex(blame, (uint32_t)i); } return NULL; @@ -211,13 +211,13 @@ static git_blame_hunk *split_hunk_in_vector( } new_line_count = hunk->lines_in_hunk - rel_line; - nh = new_hunk(hunk->final_start_line_number+rel_line, new_line_count, - hunk->orig_start_line_number+rel_line, hunk->orig_path); + nh = new_hunk((uint16_t)(hunk->final_start_line_number+rel_line), (uint16_t)new_line_count, + (uint16_t)(hunk->orig_start_line_number+rel_line), hunk->orig_path); git_oid_cpy(&nh->final_commit_id, &hunk->final_commit_id); git_oid_cpy(&nh->orig_commit_id, &hunk->orig_commit_id); /* Adjust hunk that was split */ - hunk->lines_in_hunk -= new_line_count; + hunk->lines_in_hunk -= (uint16_t)new_line_count; git_vector_insert_sorted(vec, nh, NULL); { git_blame_hunk *ret = return_new ? nh : hunk; @@ -374,7 +374,7 @@ static int buffer_hunk_cb( void *payload) { git_blame *blame = (git_blame*)payload; - size_t wedge_line; + uint32_t wedge_line; GIT_UNUSED(delta); @@ -420,7 +420,7 @@ static int buffer_line_cb( } else { /* Create a new buffer-blame hunk with this line */ shift_hunks_by(&blame->hunks, blame->current_diff_line, 1); - blame->current_hunk = new_hunk(blame->current_diff_line, 1, 0, blame->path); + blame->current_hunk = new_hunk((uint16_t)blame->current_diff_line, 1, 0, blame->path); git_vector_insert_sorted(&blame->hunks, blame->current_hunk, NULL); } blame->current_diff_line++; @@ -436,7 +436,7 @@ static int buffer_line_cb( if (!git_vector_search2(&i, &blame->hunks, ptrs_equal_cmp, blame->current_hunk)) { git_vector_remove(&blame->hunks, i); free_hunk(blame->current_hunk); - blame->current_hunk = (git_blame_hunk*)git_blame_get_hunk_byindex(blame, i); + blame->current_hunk = (git_blame_hunk*)git_blame_get_hunk_byindex(blame, (uint32_t)i); } } shift_hunks_by(&blame->hunks, shift_base, -1); diff --git a/src/blame_git.c b/src/blame_git.c index 84ffa29f0..800f1f039 100644 --- a/src/blame_git.c +++ b/src/blame_git.c @@ -324,7 +324,7 @@ static void trim_common_tail(mmfile_t *a, mmfile_t *b, long ctx) long trimmed = 0, recovered = 0; char *ap = a->ptr + a->size; char *bp = b->ptr + b->size; - long smaller = (a->size < b->size) ? a->size : b->size; + long smaller = (long)((a->size < b->size) ? a->size : b->size); if (ctx) return; -- cgit v1.2.1 From 79c443425b1b3d67e8180663c6e80793b587c888 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 5 Nov 2013 11:35:57 -0800 Subject: Make url decoding more bulletproof --- src/netops.c | 19 +++++++------------ tests-clar/network/urlparse.c | 4 ++-- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/netops.c b/src/netops.c index ce49116e3..d7f17b1fc 100644 --- a/src/netops.c +++ b/src/netops.c @@ -658,23 +658,18 @@ void gitno_connection_data_free_ptrs(gitno_connection_data *d) git__free(d->pass); d->pass = NULL; } -static char unescape_hex(char *x) -{ - char digit; - digit = ((x[0] >= 'A') ? ((x[0] & 0xdf) - 'A')+10 : (x[0] - '0')); - digit *= 16; - digit += ((x[1] >= 'A') ? ((x[1] & 0xdf) - 'A')+10 : (x[1] - '0')); - return digit; -} - +#define hex2c(c) ((c | 32) % 39 - 9) static char* unescape(char *str) { int x, y; + int len = strlen(str); - for (x=y=0; str[x]; ++x, ++y) { + for (x=y=0; str[y]; ++x, ++y) { if ((str[x] = str[y]) == '%') { - str[x] = unescape_hex(str+y+1); - y += 2; + if (y < len-2 && isxdigit(str[y+1]) && isxdigit(str[y+2])) { + str[x] = (hex2c(str[y+1]) << 4) + hex2c(str[y+2]); + y += 2; + } } } str[x] = '\0'; diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c index 3ec3a51a3..31616275a 100644 --- a/tests-clar/network/urlparse.c +++ b/tests-clar/network/urlparse.c @@ -130,12 +130,12 @@ void test_network_urlparse__connection_data_ssl(void) void test_network_urlparse__encoded_username_password(void) { cl_git_pass(gitno_connection_data_from_url(&conndata, - "https://user%2fname:pass%40word@example.com/foo/bar/baz", "bar/baz")); + "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz", "bar/baz")); cl_assert_equal_s(conndata.host, "example.com"); cl_assert_equal_s(conndata.port, "443"); cl_assert_equal_s(conndata.path, "/foo/"); cl_assert_equal_s(conndata.user, "user/name"); - cl_assert_equal_s(conndata.pass, "pass@word"); + cl_assert_equal_s(conndata.pass, "pass@word%zyx%v"); cl_assert_equal_i(conndata.use_ssl, true); } -- cgit v1.2.1 From 8adea28ae950e21d3579c0e7911567be4951c4c6 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 5 Nov 2013 11:42:42 -0800 Subject: Blame: change signature to be more binding-friendly --- include/git2/blame.h | 2 +- src/blame.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/git2/blame.h b/include/git2/blame.h index b98c6f0d7..73bcc5bc6 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -183,7 +183,7 @@ GIT_EXTERN(int) git_blame_buffer( git_blame **out, git_blame *reference, const char *buffer, - size_t buffer_len); + uint32_t buffer_len); /** * Free memory allocated by git_blame_file or git_blame_buffer. diff --git a/src/blame.c b/src/blame.c index 0b4dafbf2..01d3fc03c 100644 --- a/src/blame.c +++ b/src/blame.c @@ -448,7 +448,7 @@ int git_blame_buffer( git_blame **out, git_blame *reference, const char *buffer, - size_t buffer_len) + uint32_t buffer_len) { git_blame *blame; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; -- cgit v1.2.1 From a667ca8298193b3103c1dbdcb1f6c527e6e99eb2 Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Tue, 5 Nov 2013 20:51:07 +0100 Subject: Change the git_branch_iterator_new and git_branch_next definitions to use git_branch_t. --- include/git2/branch.h | 4 ++-- src/branch.c | 4 ++-- tests-clar/online/push.c | 2 +- tests-clar/refs/branches/iterator.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/git2/branch.h b/include/git2/branch.h index b5e7d60ea..44d6fd9c3 100644 --- a/include/git2/branch.h +++ b/include/git2/branch.h @@ -83,7 +83,7 @@ typedef struct git_branch_iterator git_branch_iterator; GIT_EXTERN(int) git_branch_iterator_new( git_branch_iterator **out, git_repository *repo, - unsigned int list_flags); + git_branch_t list_flags); /** * Retrieve the next branch from the iterator @@ -93,7 +93,7 @@ GIT_EXTERN(int) git_branch_iterator_new( * @param iter the branch iterator * @return 0 on success, GIT_ITEROVER if there are no more branches or an error code. */ -GIT_EXTERN(int) git_branch_next(git_reference **out, unsigned int *out_type, git_branch_iterator *iter); +GIT_EXTERN(int) git_branch_next(git_reference **out, git_branch_t *out_type, git_branch_iterator *iter); /** * Free a branch iterator diff --git a/src/branch.c b/src/branch.c index 4660f00b7..95b3fd980 100644 --- a/src/branch.c +++ b/src/branch.c @@ -129,7 +129,7 @@ typedef struct { unsigned int flags; } branch_iter; -int git_branch_next(git_reference **out, unsigned int *out_type, git_branch_iterator *_iter) +int git_branch_next(git_reference **out, git_branch_t *out_type, git_branch_iterator *_iter) { branch_iter *iter = (branch_iter *) _iter; git_reference *ref; @@ -159,7 +159,7 @@ int git_branch_next(git_reference **out, unsigned int *out_type, git_branch_iter int git_branch_iterator_new( git_branch_iterator **out, git_repository *repo, - unsigned int list_flags) + git_branch_t list_flags) { branch_iter *iter; diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 320ecb71e..d9ffe8aa9 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -182,7 +182,7 @@ static void verify_tracking_branches(git_remote *remote, expected_ref expected_r char *actual_ref; git_oid oid; int failed = 0, error; - unsigned int branch_type; + git_branch_t branch_type; git_reference *ref; /* Get current remote branches */ diff --git a/tests-clar/refs/branches/iterator.c b/tests-clar/refs/branches/iterator.c index fb2c1a19d..904c6a146 100644 --- a/tests-clar/refs/branches/iterator.c +++ b/tests-clar/refs/branches/iterator.c @@ -33,7 +33,7 @@ static void assert_retrieval(unsigned int flags, unsigned int expected_count) git_branch_iterator *iter; git_reference *ref; int count = 0, error; - unsigned int type; + git_branch_t type; cl_git_pass(git_branch_iterator_new(&iter, repo, flags)); while ((error = git_branch_next(&ref, &type, iter)) == 0) { @@ -83,7 +83,7 @@ static void assert_branch_has_been_found(struct expectations *findings, const ch static void contains_branches(struct expectations exp[], git_branch_iterator *iter) { git_reference *ref; - unsigned int type; + git_branch_t type; int error, pos = 0; while ((error = git_branch_next(&ref, &type, iter)) == 0) { -- cgit v1.2.1 From 73291aff6e695b13fa738c03cd344491c9ad24b3 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 5 Nov 2013 22:08:02 +0100 Subject: cmake: Add `USE_SSH` option --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a14abae0a..2440ed0b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,8 @@ OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF ) OPTION( ANDROID "Build for android NDK" OFF ) OPTION( USE_ICONV "Link with and use iconv library" OFF ) +OPTION( USE_SSH "Link with libssh to enable SSH support" ON ) + IF(APPLE) SET( USE_ICONV ON ) ENDIF() @@ -186,7 +188,7 @@ ELSE() FILE(GLOB SRC_ZLIB deps/zlib/*.c deps/zlib/*.h) ENDIF() -IF (NOT MINGW) +IF (USE_SSH AND NOT MINGW) FIND_PACKAGE(LIBSSH2 QUIET) ENDIF() IF (LIBSSH2_FOUND) -- cgit v1.2.1 From 7616b8d3ce8d75b8221aa81f048178ef13c93c05 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 5 Nov 2013 17:34:45 -0600 Subject: don't double free pkt --- src/transports/smart_protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 651901b1b..4e9e112f4 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -261,7 +261,7 @@ static int wait_while_ack(gitno_buffer *buf) (pkt->status != GIT_ACK_CONTINUE || pkt->status != GIT_ACK_COMMON)) { git__free(pkt); - break; + return 0; } } -- cgit v1.2.1 From fde93250320f97cd6cf93be1e4ab09fd330e001f Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Thu, 7 Nov 2013 13:17:36 +0100 Subject: Correctly quote config values while saving If the value contains a command (; or #) char or starts or ends with space it needs to be quoted. Signed-off-by: Sven Strickroth --- src/config_file.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index c7fc32060..1e58e3a7a 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -1178,6 +1178,22 @@ static int write_section(git_filebuf *file, const char *key) return result; } +static int needsQuote(const char *value) +{ + const char *ptr = value; + if (*value == ' ') + return 1; + while (*ptr) { + if (*ptr == ';' || *ptr == '#') + return 1; + ++ptr; + } + if (ptr != value && *(--ptr) == ' ') + return 1; + + return 0; +} + /* * This is pretty much the parsing, except we write out anything we don't have */ @@ -1299,7 +1315,10 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p /* Then replace the variable. If the value is NULL, it * means we want to delete it, so don't write anything. */ if (value != NULL) { - git_filebuf_printf(&file, "\t%s = %s\n", name, value); + if (needsQuote(value)) + git_filebuf_printf(&file, "\t%s = \"%s\"\n", name, value); + else + git_filebuf_printf(&file, "\t%s = %s\n", name, value); } /* @@ -1359,7 +1378,10 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p if (reader->buffer.size > 0 && *(reader->buffer.ptr + reader->buffer.size - 1) != '\n') git_filebuf_write(&file, "\n", 1); - git_filebuf_printf(&file, "\t%s = %s\n", name, value); + if (needsQuote(value)) + git_filebuf_printf(&file, "\t%s = \"%s\"\n", name, value); + else + git_filebuf_printf(&file, "\t%s = %s\n", name, value); } } -- cgit v1.2.1 From a9f7236affefc9918a8d3f2511fc4e5345d69942 Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Thu, 7 Nov 2013 13:38:04 +0100 Subject: Add a testcase for values which needs quotes Signed-off-by: Sven Strickroth --- tests-clar/config/write.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests-clar/config/write.c b/tests-clar/config/write.c index 57b02a7d9..c93c08a1a 100644 --- a/tests-clar/config/write.c +++ b/tests-clar/config/write.c @@ -229,6 +229,33 @@ void test_config_write__add_value_at_file_with_no_clrf_at_the_end(void) git_config_free(cfg); } +void test_config_write__add_value_which_needs_quotes(void) +{ + git_config *cfg; + const char* str1; + const char* str2; + const char* str3; + const char* str4; + + cl_git_pass(git_config_open_ondisk(&cfg, "config17")); + cl_git_pass(git_config_set_string(cfg, "core.startwithspace", " Something")); + cl_git_pass(git_config_set_string(cfg, "core.endwithspace", "Something ")); + cl_git_pass(git_config_set_string(cfg, "core.containscommentchar1", "some#thing")); + cl_git_pass(git_config_set_string(cfg, "core.containscommentchar2", "some;thing")); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config17")); + cl_git_pass(git_config_get_string(&str1, cfg, "core.startwithspace")); + cl_assert_equal_s(" Something", str1); + cl_git_pass(git_config_get_string(&str2, cfg, "core.endwithspace")); + cl_assert_equal_s("Something ", str2); + cl_git_pass(git_config_get_string(&str3, cfg, "core.containscommentchar1")); + cl_assert_equal_s("some#thing", str3); + cl_git_pass(git_config_get_string(&str4, cfg, "core.containscommentchar2")); + cl_assert_equal_s("some;thing", str4); + git_config_free(cfg); +} + void test_config_write__can_set_a_value_to_NULL(void) { git_repository *repository; -- cgit v1.2.1 From 0fe522d1057aef064084a22d116f7c225948a3bd Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 7 Nov 2013 14:16:20 +0100 Subject: allowing create remote with custom fetch spec --- include/git2/remote.h | 3 ++- src/clone.c | 2 +- src/remote.c | 11 +++++++---- src/repository.c | 2 +- tests-clar/network/fetchlocal.c | 4 ++-- tests-clar/network/remote/remotes.c | 12 ++++++------ tests-clar/online/clone.c | 2 +- tests-clar/online/fetch.c | 6 +++--- tests-clar/online/push.c | 2 +- tests-clar/refs/branches/remote.c | 2 +- 10 files changed, 25 insertions(+), 21 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index b9cf86ef1..07102594e 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -40,7 +40,8 @@ GIT_EXTERN(int) git_remote_create( git_remote **out, git_repository *repo, const char *name, - const char *url); + const char *url, + const char *fetch); /** * Create a remote in memory diff --git a/src/clone.c b/src/clone.c index 657243945..8d99e8fc8 100644 --- a/src/clone.c +++ b/src/clone.c @@ -309,7 +309,7 @@ static int create_and_configure_origin( const char *name; name = options->remote_name ? options->remote_name : "origin"; - if ((error = git_remote_create(&origin, repo, name, url)) < 0) + if ((error = git_remote_create(&origin, repo, name, url, NULL)) < 0) goto on_error; if (options->ignore_cert_errors) diff --git a/src/remote.c b/src/remote.c index 3528b1c46..b812c91dd 100644 --- a/src/remote.c +++ b/src/remote.c @@ -174,7 +174,7 @@ static int ensure_remote_doesnot_exist(git_repository *repo, const char *name) } -int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url) +int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch) { git_buf buf = GIT_BUF_INIT; git_remote *remote = NULL; @@ -186,10 +186,13 @@ int git_remote_create(git_remote **out, git_repository *repo, const char *name, if ((error = ensure_remote_doesnot_exist(repo, name)) < 0) return error; - if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0) - return -1; + if (fetch == NULL) { + if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0) + return -1; + fetch = git_buf_cstr(&buf); + } - if (create_internal(&remote, repo, name, url, git_buf_cstr(&buf)) < 0) + if (create_internal(&remote, repo, name, url, fetch) < 0) goto on_error; git_buf_free(&buf); diff --git a/src/repository.c b/src/repository.c index dcc02e4fb..f1eff165c 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1473,7 +1473,7 @@ static int repo_init_create_origin(git_repository *repo, const char *url) int error; git_remote *remote; - if (!(error = git_remote_create(&remote, repo, GIT_REMOTE_ORIGIN, url))) { + if (!(error = git_remote_create(&remote, repo, GIT_REMOTE_ORIGIN, url, NULL))) { git_remote_free(remote); } diff --git a/tests-clar/network/fetchlocal.c b/tests-clar/network/fetchlocal.c index 28c7115bf..8c133d3ad 100644 --- a/tests-clar/network/fetchlocal.c +++ b/tests-clar/network/fetchlocal.c @@ -33,7 +33,7 @@ void test_network_fetchlocal__complete(void) cl_set_cleanup(&cleanup_local_repo, "foo"); cl_git_pass(git_repository_init(&repo, "foo", true)); - cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); + cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url, NULL)); git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(origin)); @@ -71,7 +71,7 @@ void test_network_fetchlocal__partial(void) cl_assert_equal_i(1, (int)refnames.count); url = cl_git_fixture_url("testrepo.git"); - cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); + cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url, NULL)); git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(origin)); diff --git a/tests-clar/network/remote/remotes.c b/tests-clar/network/remote/remotes.c index 7c79b8318..3b7ce2924 100644 --- a/tests-clar/network/remote/remotes.c +++ b/tests-clar/network/remote/remotes.c @@ -159,7 +159,7 @@ void test_network_remote_remotes__save(void) _remote = NULL; /* Set up the remote and save it to config */ - cl_git_pass(git_remote_create(&_remote, _repo, "upstream", "git://github.com/libgit2/libgit2")); + cl_git_pass(git_remote_create(&_remote, _repo, "upstream", "git://github.com/libgit2/libgit2", NULL)); git_remote_clear_refspecs(_remote); cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec1)); @@ -298,7 +298,7 @@ void test_network_remote_remotes__add(void) git_remote_free(_remote); _remote = NULL; - cl_git_pass(git_remote_create(&_remote, _repo, "addtest", "http://github.com/libgit2/libgit2")); + cl_git_pass(git_remote_create(&_remote, _repo, "addtest", "http://github.com/libgit2/libgit2", NULL)); cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, git_remote_autotag(_remote)); git_remote_free(_remote); @@ -320,7 +320,7 @@ void test_network_remote_remotes__cannot_add_a_nameless_remote(void) cl_assert_equal_i( GIT_EINVALIDSPEC, - git_remote_create(&remote, _repo, NULL, "git://github.com/libgit2/libgit2")); + git_remote_create(&remote, _repo, NULL, "git://github.com/libgit2/libgit2", NULL)); } void test_network_remote_remotes__cannot_save_an_inmemory_remote(void) @@ -341,12 +341,12 @@ void test_network_remote_remotes__cannot_add_a_remote_with_an_invalid_name(void) cl_assert_equal_i( GIT_EINVALIDSPEC, - git_remote_create(&remote, _repo, "Inv@{id", "git://github.com/libgit2/libgit2")); + git_remote_create(&remote, _repo, "Inv@{id", "git://github.com/libgit2/libgit2", NULL)); cl_assert_equal_p(remote, NULL); cl_assert_equal_i( GIT_EINVALIDSPEC, - git_remote_create(&remote, _repo, "", "git://github.com/libgit2/libgit2")); + git_remote_create(&remote, _repo, "", "git://github.com/libgit2/libgit2", NULL)); cl_assert_equal_p(remote, NULL); } @@ -439,7 +439,7 @@ void assert_cannot_create_remote(const char *name, int expected_error) git_remote *remote = NULL; cl_git_fail_with( - git_remote_create(&remote, _repo, name, "git://github.com/libgit2/libgit2"), + git_remote_create(&remote, _repo, name, "git://github.com/libgit2/libgit2", NULL), expected_error); cl_assert_equal_p(remote, NULL); diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index aa3d6b26a..ed8a6446d 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -141,7 +141,7 @@ void test_online_clone__clone_into(void) checkout_opts.progress_payload = &checkout_progress_cb_was_called; cl_git_pass(git_repository_init(&g_repo, "./foo", false)); - cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL)); + cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL, NULL)); callbacks.transfer_progress = &fetch_progress; callbacks.payload = &fetch_progress_cb_was_called; diff --git a/tests-clar/online/fetch.c b/tests-clar/online/fetch.c index df1b2e288..3ac9ffa37 100644 --- a/tests-clar/online/fetch.c +++ b/tests-clar/online/fetch.c @@ -43,7 +43,7 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) callbacks.payload = &bytes_received; counter = 0; - cl_git_pass(git_remote_create(&remote, _repo, "test", url)); + cl_git_pass(git_remote_create(&remote, _repo, "test", url, NULL)); git_remote_set_callbacks(remote, &callbacks); git_remote_set_autotag(remote, flag); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); @@ -140,7 +140,7 @@ void test_online_fetch__can_cancel(void) git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; cl_git_pass(git_remote_create(&remote, _repo, "test", - "http://github.com/libgit2/TestGitRepository.git")); + "http://github.com/libgit2/TestGitRepository.git", NULL)); callbacks.transfer_progress = cancel_at_half; callbacks.payload = &bytes_received; @@ -168,7 +168,7 @@ void test_online_fetch__ls_disconnected(void) int nr_before = 0, nr_after = 0; cl_git_pass(git_remote_create(&remote, _repo, "test", - "http://github.com/libgit2/TestGitRepository.git")); + "http://github.com/libgit2/TestGitRepository.git", NULL)); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_ls(remote, ls_cb, &nr_before)); git_remote_disconnect(remote); diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index d9ffe8aa9..9f992db75 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -301,7 +301,7 @@ void test_online_push__initialize(void) _remote = NULL; if (_remote_url) { - cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url)); + cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url, NULL)); record_callbacks_data_clear(&_record_cbs_data); git_remote_set_callbacks(_remote, &_record_cbs); diff --git a/tests-clar/refs/branches/remote.c b/tests-clar/refs/branches/remote.c index c110adb33..aeba36347 100644 --- a/tests-clar/refs/branches/remote.c +++ b/tests-clar/refs/branches/remote.c @@ -70,7 +70,7 @@ void test_refs_branches_remote__ambiguous_remote_returns_error(void) git_remote *remote; /* Create the remote */ - cl_git_pass(git_remote_create(&remote, g_repo, "addtest", "http://github.com/libgit2/libgit2")); + cl_git_pass(git_remote_create(&remote, g_repo, "addtest", "http://github.com/libgit2/libgit2", NULL)); /* Update the remote fetch spec */ git_remote_clear_refspecs(remote); -- cgit v1.2.1 From 7dd28dde284276a09e74f66b22fe0173573d3ca7 Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Thu, 7 Nov 2013 15:39:15 +0100 Subject: Add another testcase to make sure double quotes are correctly escaped Signed-off-by: Sven Strickroth --- tests-clar/config/write.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests-clar/config/write.c b/tests-clar/config/write.c index c93c08a1a..4b217c50b 100644 --- a/tests-clar/config/write.c +++ b/tests-clar/config/write.c @@ -236,12 +236,14 @@ void test_config_write__add_value_which_needs_quotes(void) const char* str2; const char* str3; const char* str4; + const char* str5; cl_git_pass(git_config_open_ondisk(&cfg, "config17")); cl_git_pass(git_config_set_string(cfg, "core.startwithspace", " Something")); cl_git_pass(git_config_set_string(cfg, "core.endwithspace", "Something ")); cl_git_pass(git_config_set_string(cfg, "core.containscommentchar1", "some#thing")); cl_git_pass(git_config_set_string(cfg, "core.containscommentchar2", "some;thing")); + cl_git_pass(git_config_set_string(cfg, "core.startwhithsapceandcontainsdoublequote", " some\"thing")); git_config_free(cfg); cl_git_pass(git_config_open_ondisk(&cfg, "config17")); @@ -253,6 +255,8 @@ void test_config_write__add_value_which_needs_quotes(void) cl_assert_equal_s("some#thing", str3); cl_git_pass(git_config_get_string(&str4, cfg, "core.containscommentchar2")); cl_assert_equal_s("some;thing", str4); + cl_git_pass(git_config_get_string(&str5, cfg, "core.startwhithsapceandcontainsdoublequote")); + cl_assert_equal_s(" some\"thing", str5); git_config_free(cfg); } -- cgit v1.2.1 From cc2447da32a20f5d089125839555ed0fe2a05592 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 6 Nov 2013 18:41:08 -0500 Subject: Add git_packbuilder_hash to query pack filename --- include/git2/pack.h | 10 ++++++++++ src/pack-objects.c | 12 ++++++++++-- tests-clar/pack/packbuilder.c | 12 ++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/include/git2/pack.h b/include/git2/pack.h index 748817666..4632699d1 100644 --- a/include/git2/pack.h +++ b/include/git2/pack.h @@ -130,6 +130,16 @@ GIT_EXTERN(int) git_packbuilder_write( git_transfer_progress_callback progress_cb, void *progress_cb_payload); +/** +* Get the packfile's hash +* +* A packfile's name is derived from the sorted hashing of all object +* names. This is only correct after the packfile has been written. +* +* @param pb The packbuilder object +*/ +GIT_EXTERN(const git_oid *) git_packbuilder_hash(git_packbuilder *pb); + typedef int (*git_packbuilder_foreach_cb)(void *buf, size_t size, void *payload); /** * Create the new pack and pass each object to the callback diff --git a/src/pack-objects.c b/src/pack-objects.c index 9ea7c659a..91811b954 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -560,6 +560,7 @@ static int write_pack(git_packbuilder *pb, git_buf buf = GIT_BUF_INIT; enum write_one_status status; struct git_pack_header ph; + git_oid entry_oid; unsigned int i = 0; int error = 0; @@ -596,10 +597,10 @@ static int write_pack(git_packbuilder *pb, } while (pb->nr_remaining && i < pb->nr_objects); - if ((error = git_hash_final(&pb->pack_oid, &pb->ctx)) < 0) + if ((error = git_hash_final(&entry_oid, &pb->ctx)) < 0) goto done; - error = cb(pb->pack_oid.id, GIT_OID_RAWSZ, data); + error = cb(entry_oid.id, GIT_OID_RAWSZ, data); done: git__free(write_order); @@ -1269,12 +1270,19 @@ int git_packbuilder_write( return -1; } + git_oid_cpy(&pb->pack_oid, git_indexer_hash(indexer)); + git_indexer_free(indexer); return 0; } #undef PREPARE_PACK +const git_oid *git_packbuilder_hash(git_packbuilder *pb) +{ + return &pb->pack_oid; +} + static int cb_tree_walk(const char *root, const git_tree_entry *entry, void *payload) { struct tree_walk_context *ctx = payload; diff --git a/tests-clar/pack/packbuilder.c b/tests-clar/pack/packbuilder.c index ac6f731e1..dd028a143 100644 --- a/tests-clar/pack/packbuilder.c +++ b/tests-clar/pack/packbuilder.c @@ -128,6 +128,18 @@ void test_pack_packbuilder__create_pack(void) cl_assert_equal_s(hex, "5d410bdf97cf896f9007681b92868471d636954b"); } +void test_pack_packbuilder__get_hash(void) +{ + char hex[41]; hex[40] = '\0'; + + seed_packbuilder(); + + git_packbuilder_write(_packbuilder, ".", NULL, NULL); + git_oid_fmt(hex, git_packbuilder_hash(_packbuilder)); + + cl_assert_equal_s(hex, "80e61eb315239ef3c53033e37fee43b744d57122"); +} + static git_transfer_progress stats; static int foreach_cb(void *buf, size_t len, void *payload) { -- cgit v1.2.1 From 99feb98897fa1daa0ff3fd70b17ccc9d9a51f1d0 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 7 Nov 2013 16:22:49 +0100 Subject: adding doc for new param and test to check fetch spec is correctly added --- include/git2/remote.h | 4 +++- tests-clar/network/remote/remotes.c | 12 +++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 07102594e..f5e6f5aeb 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -27,13 +27,15 @@ GIT_BEGIN_DECL typedef int (*git_remote_rename_problem_cb)(const char *problematic_refspec, void *payload); /** - * Add a remote with the default fetch refspec to the repository's configuration. This + * Add a remote with the provided fetch refspec (or default if NULL) to the repository's + * configuration. This * calls git_remote_save before returning. * * @param out the resulting remote * @param repo the repository in which to create the remote * @param name the remote's name * @param url the remote's url + * @param fetch the remote fetch value * @return 0, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code */ GIT_EXTERN(int) git_remote_create( diff --git a/tests-clar/network/remote/remotes.c b/tests-clar/network/remote/remotes.c index 3b7ce2924..210790d4f 100644 --- a/tests-clar/network/remote/remotes.c +++ b/tests-clar/network/remote/remotes.c @@ -450,7 +450,6 @@ void test_network_remote_remotes__cannot_create_a_remote_which_name_conflicts_wi assert_cannot_create_remote("test", GIT_EEXISTS); } - void test_network_remote_remotes__cannot_create_a_remote_which_name_is_invalid(void) { assert_cannot_create_remote("/", GIT_EINVALIDSPEC); @@ -459,6 +458,17 @@ void test_network_remote_remotes__cannot_create_a_remote_which_name_is_invalid(v assert_cannot_create_remote("a.lock", GIT_EINVALIDSPEC); } +void test_network_remote_remotes__create_a_remote_with_custom_fetch_spec(void) +{ + git_remote *remote; + git_strarray array; + + cl_git_pass(git_remote_create(&remote, _repo, "test-new", "git://github.com/libgit2/libgit2", "+refs/*:refs/*")); + git_remote_get_fetch_refspecs(&array, remote); + cl_assert_equal_s("+refs/*:refs/*", array.strings[0]); + git_remote_free(remote); +} + static const char *fetch_refspecs[] = { "+refs/heads/*:refs/remotes/origin/*", "refs/tags/*:refs/tags/*", -- cgit v1.2.1 From 590c5efb3bab80b3e52cf68b705ef461d7388874 Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Thu, 7 Nov 2013 17:51:43 +0100 Subject: Rename method Signed-off-by: Sven Strickroth --- src/config_file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 1e58e3a7a..66a8c155b 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -1178,7 +1178,7 @@ static int write_section(git_filebuf *file, const char *key) return result; } -static int needsQuote(const char *value) +static int value_needs_surrounding_quote(const char *value) { const char *ptr = value; if (*value == ' ') @@ -1315,7 +1315,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p /* Then replace the variable. If the value is NULL, it * means we want to delete it, so don't write anything. */ if (value != NULL) { - if (needsQuote(value)) + if (value_needs_surrounding_quote(value)) git_filebuf_printf(&file, "\t%s = \"%s\"\n", name, value); else git_filebuf_printf(&file, "\t%s = %s\n", name, value); @@ -1378,7 +1378,7 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p if (reader->buffer.size > 0 && *(reader->buffer.ptr + reader->buffer.size - 1) != '\n') git_filebuf_write(&file, "\n", 1); - if (needsQuote(value)) + if (value_needs_surrounding_quote(value)) git_filebuf_printf(&file, "\t%s = \"%s\"\n", name, value); else git_filebuf_printf(&file, "\t%s = %s\n", name, value); -- cgit v1.2.1 From 1e60e5f42dbcf081ac7eece12a5eebab5871636f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 7 Nov 2013 12:03:44 -0500 Subject: Allow callers to set mode on packfile creation --- include/git2/indexer.h | 2 ++ include/git2/pack.h | 2 ++ src/indexer.c | 7 ++++-- src/odb_pack.c | 2 +- src/pack-objects.c | 3 ++- tests-clar/pack/indexer.c | 6 +++--- tests-clar/pack/packbuilder.c | 50 ++++++++++++++++++++++++++++++++++++++++--- 7 files changed, 62 insertions(+), 10 deletions(-) diff --git a/include/git2/indexer.h b/include/git2/indexer.h index fb55672a9..e4c03ad06 100644 --- a/include/git2/indexer.h +++ b/include/git2/indexer.h @@ -20,6 +20,7 @@ typedef struct git_indexer git_indexer; * * @param out where to store the indexer instance * @param path to the directory where the packfile should be stored + * @param mode permissions to use creating packfile or 0 for defaults * @param odb object database from which to read base objects when * fixing thin packs. Pass NULL if no thin pack is expected (an error * will be returned if there are bases missing) @@ -29,6 +30,7 @@ typedef struct git_indexer git_indexer; GIT_EXTERN(int) git_indexer_new( git_indexer **out, const char *path, + unsigned int mode, git_odb *odb, git_transfer_progress_callback progress_cb, void *progress_cb_payload); diff --git a/include/git2/pack.h b/include/git2/pack.h index 4632699d1..52e7adad2 100644 --- a/include/git2/pack.h +++ b/include/git2/pack.h @@ -119,6 +119,7 @@ GIT_EXTERN(int) git_packbuilder_insert_commit(git_packbuilder *pb, const git_oid * * @param pb The packbuilder * @param path to the directory where the packfile and index should be stored + * @param mode permissions to use creating a packfile or 0 for defaults * @param progress_cb function to call with progress information from the indexer (optional) * @param progress_cb_payload payload for the progress callback (optional) * @@ -127,6 +128,7 @@ GIT_EXTERN(int) git_packbuilder_insert_commit(git_packbuilder *pb, const git_oid GIT_EXTERN(int) git_packbuilder_write( git_packbuilder *pb, const char *path, + unsigned int mode, git_transfer_progress_callback progress_cb, void *progress_cb_payload); diff --git a/src/indexer.c b/src/indexer.c index 90fb52187..df1ce7cfb 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -37,6 +37,7 @@ struct git_indexer { struct git_pack_header hdr; struct git_pack_file *pack; git_filebuf pack_file; + unsigned int mode; git_off_t off; git_off_t entry_start; git_packfile_stream stream; @@ -119,6 +120,7 @@ static int objects_cmp(const void *a, const void *b) int git_indexer_new( git_indexer **out, const char *prefix, + unsigned int mode, git_odb *odb, git_transfer_progress_callback progress_cb, void *progress_payload) @@ -133,6 +135,7 @@ int git_indexer_new( idx->odb = odb; idx->progress_cb = progress_cb; idx->progress_payload = progress_payload; + idx->mode = mode ? mode : GIT_PACK_FILE_MODE; git_hash_ctx_init(&idx->trailer); error = git_buf_joinpath(&path, prefix, suff); @@ -141,7 +144,7 @@ int git_indexer_new( error = git_filebuf_open(&idx->pack_file, path.ptr, GIT_FILEBUF_TEMPORARY | GIT_FILEBUF_DO_NOT_BUFFER, - GIT_PACK_FILE_MODE); + idx->mode); git_buf_free(&path); if (error < 0) goto cleanup; @@ -905,7 +908,7 @@ 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, GIT_PACK_FILE_MODE) < 0) + GIT_FILEBUF_HASH_CONTENTS, idx->mode) < 0) goto on_error; /* Write out the header */ diff --git a/src/odb_pack.c b/src/odb_pack.c index 12f4591ec..fd2ca0fd8 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -558,7 +558,7 @@ static int pack_backend__writepack(struct git_odb_writepack **out, GITERR_CHECK_ALLOC(writepack); if (git_indexer_new(&writepack->indexer, - backend->pack_folder, odb, progress_cb, progress_payload) < 0) { + backend->pack_folder, 0, odb, progress_cb, progress_payload) < 0) { git__free(writepack); return -1; } diff --git a/src/pack-objects.c b/src/pack-objects.c index 91811b954..9967cab1f 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -1248,6 +1248,7 @@ static int write_cb(void *buf, size_t len, void *payload) int git_packbuilder_write( git_packbuilder *pb, const char *path, + unsigned int mode, git_transfer_progress_callback progress_cb, void *progress_cb_payload) { @@ -1258,7 +1259,7 @@ int git_packbuilder_write( PREPARE_PACK; if (git_indexer_new( - &indexer, path, pb->odb, progress_cb, progress_cb_payload) < 0) + &indexer, path, mode, pb->odb, progress_cb, progress_cb_payload) < 0) return -1; ctx.indexer = indexer; diff --git a/tests-clar/pack/indexer.c b/tests-clar/pack/indexer.c index d7953300f..07963a9e7 100644 --- a/tests-clar/pack/indexer.c +++ b/tests-clar/pack/indexer.c @@ -48,7 +48,7 @@ void test_pack_indexer__out_of_order(void) git_indexer *idx; git_transfer_progress stats; - cl_git_pass(git_indexer_new(&idx, ".", NULL, NULL, NULL)); + cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); cl_git_pass(git_indexer_append(idx, out_of_order_pack, out_of_order_pack_len, &stats)); cl_git_pass(git_indexer_commit(idx, &stats)); @@ -75,7 +75,7 @@ void test_pack_indexer__fix_thin(void) git_oid_fromstr(&should_id, "e68fe8129b546b101aee9510c5328e7f21ca1d18"); cl_assert(!git_oid_cmp(&id, &should_id)); - cl_git_pass(git_indexer_new(&idx, ".", odb, NULL, NULL)); + cl_git_pass(git_indexer_new(&idx, ".", 0, odb, NULL, NULL)); cl_git_pass(git_indexer_append(idx, thin_pack, thin_pack_len, &stats)); cl_git_pass(git_indexer_commit(idx, &stats)); @@ -108,7 +108,7 @@ void test_pack_indexer__fix_thin(void) cl_git_pass(p_stat(name, &st)); - cl_git_pass(git_indexer_new(&idx, ".", NULL, NULL, NULL)); + cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); read = p_read(fd, buffer, sizeof(buffer)); cl_assert(read != -1); p_close(fd); diff --git a/tests-clar/pack/packbuilder.c b/tests-clar/pack/packbuilder.c index dd028a143..54d1e8022 100644 --- a/tests-clar/pack/packbuilder.c +++ b/tests-clar/pack/packbuilder.c @@ -1,5 +1,6 @@ #include "clar_libgit2.h" #include "fileops.h" +#include "pack.h" #include "hash.h" #include "iterator.h" #include "vector.h" @@ -92,7 +93,7 @@ void test_pack_packbuilder__create_pack(void) seed_packbuilder(); - cl_git_pass(git_indexer_new(&_indexer, ".", NULL, NULL, NULL)); + cl_git_pass(git_indexer_new(&_indexer, ".", 0, NULL, NULL, NULL)); cl_git_pass(git_packbuilder_foreach(_packbuilder, feed_indexer, &stats)); cl_git_pass(git_indexer_commit(_indexer, &stats)); @@ -134,12 +135,55 @@ void test_pack_packbuilder__get_hash(void) seed_packbuilder(); - git_packbuilder_write(_packbuilder, ".", NULL, NULL); + git_packbuilder_write(_packbuilder, ".", 0, NULL, NULL); git_oid_fmt(hex, git_packbuilder_hash(_packbuilder)); cl_assert_equal_s(hex, "80e61eb315239ef3c53033e37fee43b744d57122"); } +static void test_write_pack_permission(mode_t given, mode_t expected) +{ + struct stat statbuf; + mode_t mask, os_mask; + + seed_packbuilder(); + + git_packbuilder_write(_packbuilder, ".", given, NULL, NULL); + + /* Windows does not return group/user bits from stat, + * files are never executable. + */ +#ifdef GIT_WIN32 + os_mask = 0600; +#else + os_mask = 0777; +#endif + + mask = p_umask(0); + p_umask(mask); + + cl_git_pass(p_stat("pack-80e61eb315239ef3c53033e37fee43b744d57122.idx", &statbuf)); + cl_assert_equal_i(statbuf.st_mode & os_mask, (expected & ~mask) & os_mask); + + cl_git_pass(p_stat("pack-80e61eb315239ef3c53033e37fee43b744d57122.pack", &statbuf)); + cl_assert_equal_i(statbuf.st_mode & os_mask, (expected & ~mask) & os_mask); +} + +void test_pack_packbuilder__permissions_standard(void) +{ + test_write_pack_permission(0, GIT_PACK_FILE_MODE); +} + +void test_pack_packbuilder__permissions_readonly(void) +{ + test_write_pack_permission(0444, 0444); +} + +void test_pack_packbuilder__permissions_readwrite(void) +{ + test_write_pack_permission(0666, 0666); +} + static git_transfer_progress stats; static int foreach_cb(void *buf, size_t len, void *payload) { @@ -153,7 +197,7 @@ void test_pack_packbuilder__foreach(void) git_indexer *idx; seed_packbuilder(); - cl_git_pass(git_indexer_new(&idx, ".", NULL, NULL, NULL)); + cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); cl_git_pass(git_packbuilder_foreach(_packbuilder, foreach_cb, idx)); cl_git_pass(git_indexer_commit(idx, &stats)); git_indexer_free(idx); -- cgit v1.2.1 From ad62f2eedc110bda0b66a9f1d39f06df99a2f020 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 7 Nov 2013 12:00:43 -0600 Subject: update example to new packfile creation signature --- examples/network/index-pack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/network/index-pack.c b/examples/network/index-pack.c index 59fff416a..314f21160 100644 --- a/examples/network/index-pack.c +++ b/examples/network/index-pack.c @@ -46,7 +46,7 @@ int index_pack(git_repository *repo, int argc, char **argv) return EXIT_FAILURE; } - if (git_indexer_new(&idx, ".", NULL, NULL, NULL) < 0) { + if (git_indexer_new(&idx, ".", 0, NULL, NULL, NULL) < 0) { puts("bad idx"); return -1; } -- cgit v1.2.1 From 40b99d05b4a1221768c25c889180c12d2f43be8b Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 8 Nov 2013 12:14:31 +0100 Subject: splitting funcionality in two methods to avoid ambiguity with NULL --- include/git2/remote.h | 18 ++++++++++++++++- src/clone.c | 2 +- src/remote.c | 39 +++++++++++++++++++++++++++++++------ src/repository.c | 2 +- tests-clar/network/fetchlocal.c | 4 ++-- tests-clar/network/remote/remotes.c | 16 +++++++-------- tests-clar/online/clone.c | 2 +- tests-clar/online/fetch.c | 6 +++--- tests-clar/online/push.c | 2 +- tests-clar/refs/branches/remote.c | 2 +- 10 files changed, 68 insertions(+), 25 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index f5e6f5aeb..116b31e35 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -26,6 +26,22 @@ GIT_BEGIN_DECL typedef int (*git_remote_rename_problem_cb)(const char *problematic_refspec, void *payload); +/** + * Add a remote with the default fetch refsspec to the repository's configuration. This + * calls git_remote_save before returning. + * + * @param out the resulting remote + * @param repo the repository in which to create the remote + * @param name the remote's name + * @param url the remote's url + * @return 0, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code + */ +GIT_EXTERN(int) git_remote_create( + git_remote **out, + git_repository *repo, + const char *name, + const char *url); + /** * Add a remote with the provided fetch refspec (or default if NULL) to the repository's * configuration. This @@ -38,7 +54,7 @@ typedef int (*git_remote_rename_problem_cb)(const char *problematic_refspec, voi * @param fetch the remote fetch value * @return 0, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code */ -GIT_EXTERN(int) git_remote_create( +GIT_EXTERN(int) git_remote_create_with_fetchspec( git_remote **out, git_repository *repo, const char *name, diff --git a/src/clone.c b/src/clone.c index 8d99e8fc8..657243945 100644 --- a/src/clone.c +++ b/src/clone.c @@ -309,7 +309,7 @@ static int create_and_configure_origin( const char *name; name = options->remote_name ? options->remote_name : "origin"; - if ((error = git_remote_create(&origin, repo, name, url, NULL)) < 0) + if ((error = git_remote_create(&origin, repo, name, url)) < 0) goto on_error; if (options->ignore_cert_errors) diff --git a/src/remote.c b/src/remote.c index b812c91dd..b97cc9e79 100644 --- a/src/remote.c +++ b/src/remote.c @@ -174,7 +174,7 @@ static int ensure_remote_doesnot_exist(git_repository *repo, const char *name) } -int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch) +int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url) { git_buf buf = GIT_BUF_INIT; git_remote *remote = NULL; @@ -186,11 +186,38 @@ int git_remote_create(git_remote **out, git_repository *repo, const char *name, if ((error = ensure_remote_doesnot_exist(repo, name)) < 0) return error; - if (fetch == NULL) { - if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0) - return -1; - fetch = git_buf_cstr(&buf); - } + if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0) + return -1; + + if (create_internal(&remote, repo, name, url, git_buf_cstr(&buf)) < 0) + goto on_error; + + git_buf_free(&buf); + + if (git_remote_save(remote) < 0) + goto on_error; + + *out = remote; + + return 0; + +on_error: + git_buf_free(&buf); + git_remote_free(remote); + return -1; +} + +int git_remote_create_with_fetchspec(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch) +{ + git_buf buf = GIT_BUF_INIT; + git_remote *remote = NULL; + int error; + + if ((error = ensure_remote_name_is_valid(name)) < 0) + return error; + + if ((error = ensure_remote_doesnot_exist(repo, name)) < 0) + return error; if (create_internal(&remote, repo, name, url, fetch) < 0) goto on_error; diff --git a/src/repository.c b/src/repository.c index f1eff165c..dcc02e4fb 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1473,7 +1473,7 @@ static int repo_init_create_origin(git_repository *repo, const char *url) int error; git_remote *remote; - if (!(error = git_remote_create(&remote, repo, GIT_REMOTE_ORIGIN, url, NULL))) { + if (!(error = git_remote_create(&remote, repo, GIT_REMOTE_ORIGIN, url))) { git_remote_free(remote); } diff --git a/tests-clar/network/fetchlocal.c b/tests-clar/network/fetchlocal.c index 8c133d3ad..28c7115bf 100644 --- a/tests-clar/network/fetchlocal.c +++ b/tests-clar/network/fetchlocal.c @@ -33,7 +33,7 @@ void test_network_fetchlocal__complete(void) cl_set_cleanup(&cleanup_local_repo, "foo"); cl_git_pass(git_repository_init(&repo, "foo", true)); - cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url, NULL)); + cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(origin)); @@ -71,7 +71,7 @@ void test_network_fetchlocal__partial(void) cl_assert_equal_i(1, (int)refnames.count); url = cl_git_fixture_url("testrepo.git"); - cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url, NULL)); + cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); git_remote_set_callbacks(origin, &callbacks); cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_download(origin)); diff --git a/tests-clar/network/remote/remotes.c b/tests-clar/network/remote/remotes.c index 210790d4f..954ded82c 100644 --- a/tests-clar/network/remote/remotes.c +++ b/tests-clar/network/remote/remotes.c @@ -159,7 +159,7 @@ void test_network_remote_remotes__save(void) _remote = NULL; /* Set up the remote and save it to config */ - cl_git_pass(git_remote_create(&_remote, _repo, "upstream", "git://github.com/libgit2/libgit2", NULL)); + cl_git_pass(git_remote_create(&_remote, _repo, "upstream", "git://github.com/libgit2/libgit2")); git_remote_clear_refspecs(_remote); cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec1)); @@ -298,7 +298,7 @@ void test_network_remote_remotes__add(void) git_remote_free(_remote); _remote = NULL; - cl_git_pass(git_remote_create(&_remote, _repo, "addtest", "http://github.com/libgit2/libgit2", NULL)); + cl_git_pass(git_remote_create(&_remote, _repo, "addtest", "http://github.com/libgit2/libgit2")); cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, git_remote_autotag(_remote)); git_remote_free(_remote); @@ -320,7 +320,7 @@ void test_network_remote_remotes__cannot_add_a_nameless_remote(void) cl_assert_equal_i( GIT_EINVALIDSPEC, - git_remote_create(&remote, _repo, NULL, "git://github.com/libgit2/libgit2", NULL)); + git_remote_create(&remote, _repo, NULL, "git://github.com/libgit2/libgit2")); } void test_network_remote_remotes__cannot_save_an_inmemory_remote(void) @@ -341,12 +341,12 @@ void test_network_remote_remotes__cannot_add_a_remote_with_an_invalid_name(void) cl_assert_equal_i( GIT_EINVALIDSPEC, - git_remote_create(&remote, _repo, "Inv@{id", "git://github.com/libgit2/libgit2", NULL)); + git_remote_create(&remote, _repo, "Inv@{id", "git://github.com/libgit2/libgit2")); cl_assert_equal_p(remote, NULL); cl_assert_equal_i( GIT_EINVALIDSPEC, - git_remote_create(&remote, _repo, "", "git://github.com/libgit2/libgit2", NULL)); + git_remote_create(&remote, _repo, "", "git://github.com/libgit2/libgit2")); cl_assert_equal_p(remote, NULL); } @@ -439,7 +439,7 @@ void assert_cannot_create_remote(const char *name, int expected_error) git_remote *remote = NULL; cl_git_fail_with( - git_remote_create(&remote, _repo, name, "git://github.com/libgit2/libgit2", NULL), + git_remote_create(&remote, _repo, name, "git://github.com/libgit2/libgit2"), expected_error); cl_assert_equal_p(remote, NULL); @@ -458,12 +458,12 @@ void test_network_remote_remotes__cannot_create_a_remote_which_name_is_invalid(v assert_cannot_create_remote("a.lock", GIT_EINVALIDSPEC); } -void test_network_remote_remotes__create_a_remote_with_custom_fetch_spec(void) +void test_network_remote_remote__git_remote_create_with_fetchspec(void) { git_remote *remote; git_strarray array; - cl_git_pass(git_remote_create(&remote, _repo, "test-new", "git://github.com/libgit2/libgit2", "+refs/*:refs/*")); + cl_git_pass(git_remote_create_with_fetchspec(&remote, _repo, "test-new", "git://github.com/libgit2/libgit2", "+refs/*:refs/*")); git_remote_get_fetch_refspecs(&array, remote); cl_assert_equal_s("+refs/*:refs/*", array.strings[0]); git_remote_free(remote); diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index ed8a6446d..aa3d6b26a 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -141,7 +141,7 @@ void test_online_clone__clone_into(void) checkout_opts.progress_payload = &checkout_progress_cb_was_called; cl_git_pass(git_repository_init(&g_repo, "./foo", false)); - cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL, NULL)); + cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL)); callbacks.transfer_progress = &fetch_progress; callbacks.payload = &fetch_progress_cb_was_called; diff --git a/tests-clar/online/fetch.c b/tests-clar/online/fetch.c index 3ac9ffa37..df1b2e288 100644 --- a/tests-clar/online/fetch.c +++ b/tests-clar/online/fetch.c @@ -43,7 +43,7 @@ static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) callbacks.payload = &bytes_received; counter = 0; - cl_git_pass(git_remote_create(&remote, _repo, "test", url, NULL)); + cl_git_pass(git_remote_create(&remote, _repo, "test", url)); git_remote_set_callbacks(remote, &callbacks); git_remote_set_autotag(remote, flag); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); @@ -140,7 +140,7 @@ void test_online_fetch__can_cancel(void) git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; cl_git_pass(git_remote_create(&remote, _repo, "test", - "http://github.com/libgit2/TestGitRepository.git", NULL)); + "http://github.com/libgit2/TestGitRepository.git")); callbacks.transfer_progress = cancel_at_half; callbacks.payload = &bytes_received; @@ -168,7 +168,7 @@ void test_online_fetch__ls_disconnected(void) int nr_before = 0, nr_after = 0; cl_git_pass(git_remote_create(&remote, _repo, "test", - "http://github.com/libgit2/TestGitRepository.git", NULL)); + "http://github.com/libgit2/TestGitRepository.git")); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); cl_git_pass(git_remote_ls(remote, ls_cb, &nr_before)); git_remote_disconnect(remote); diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 9f992db75..d9ffe8aa9 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -301,7 +301,7 @@ void test_online_push__initialize(void) _remote = NULL; if (_remote_url) { - cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url, NULL)); + cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url)); record_callbacks_data_clear(&_record_cbs_data); git_remote_set_callbacks(_remote, &_record_cbs); diff --git a/tests-clar/refs/branches/remote.c b/tests-clar/refs/branches/remote.c index aeba36347..c110adb33 100644 --- a/tests-clar/refs/branches/remote.c +++ b/tests-clar/refs/branches/remote.c @@ -70,7 +70,7 @@ void test_refs_branches_remote__ambiguous_remote_returns_error(void) git_remote *remote; /* Create the remote */ - cl_git_pass(git_remote_create(&remote, g_repo, "addtest", "http://github.com/libgit2/libgit2", NULL)); + cl_git_pass(git_remote_create(&remote, g_repo, "addtest", "http://github.com/libgit2/libgit2")); /* Update the remote fetch spec */ git_remote_clear_refspecs(remote); -- cgit v1.2.1 From 886cc447389da78885a909a96b43ddbe67c9807f Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 8 Nov 2013 15:42:52 +0100 Subject: fixing typo --- include/git2/remote.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 116b31e35..559b8dcc1 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -27,7 +27,7 @@ GIT_BEGIN_DECL typedef int (*git_remote_rename_problem_cb)(const char *problematic_refspec, void *payload); /** - * Add a remote with the default fetch refsspec to the repository's configuration. This + * Add a remote with the default fetch refspec to the repository's configuration. This * calls git_remote_save before returning. * * @param out the resulting remote -- cgit v1.2.1 From a1d35ede189f6f3286102c53a499b5e486d86b79 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 10 Nov 2013 16:41:41 +0100 Subject: config_file: style --- src/config_file.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 25ebd1c97..15c8de49c 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -1178,20 +1178,22 @@ static int write_section(git_filebuf *file, const char *key) return result; } -static int value_needs_surrounding_quote(const char *value) +static const char *quotes_for_value(const char *value) { - const char *ptr = value; - if (*value == ' ') - return 1; - while (*ptr) { + const char *ptr; + + if (value[0] == ' ' || value[0] == '\0') + return "\""; + + for (ptr = value; *ptr; ++ptr) { if (*ptr == ';' || *ptr == '#') - return 1; - ++ptr; + return "\""; } - if (ptr != value && *(--ptr) == ' ') - return 1; - return 0; + if (ptr[-1] == ' ') + return "\""; + + return ""; } /* @@ -1318,10 +1320,8 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p /* Then replace the variable. If the value is NULL, it * means we want to delete it, so don't write anything. */ if (value != NULL) { - if (value_needs_surrounding_quote(value)) - git_filebuf_printf(&file, "\t%s = \"%s\"\n", name, value); - else - git_filebuf_printf(&file, "\t%s = %s\n", name, value); + const char *q = quotes_for_value(value); + git_filebuf_printf(&file, "\t%s = %s%s%s\n", name, q, value, q); } /* @@ -1362,6 +1362,8 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p if (preg_replaced) { git_filebuf_printf(&file, "\n%s", write_start); } else { + const char *q; + git_filebuf_write(&file, reader->buffer.ptr, reader->buffer.size); /* And now if we just need to add a variable */ @@ -1381,10 +1383,8 @@ static int config_write(diskfile_backend *cfg, const char *key, const regex_t *p if (reader->buffer.size > 0 && *(reader->buffer.ptr + reader->buffer.size - 1) != '\n') git_filebuf_write(&file, "\n", 1); - if (value_needs_surrounding_quote(value)) - git_filebuf_printf(&file, "\t%s = \"%s\"\n", name, value); - else - git_filebuf_printf(&file, "\t%s = %s\n", name, value); + q = quotes_for_value(value); + git_filebuf_printf(&file, "\t%s = %s%s%s\n", name, q, value, q); } } -- cgit v1.2.1 From 18bd73e50d21087e09a7193e55504b981c163e46 Mon Sep 17 00:00:00 2001 From: Linquize Date: Mon, 11 Nov 2013 00:08:54 +0800 Subject: Fix warning in tests-clar/merge/workdir/trivial.c --- tests-clar/merge/workdir/trivial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests-clar/merge/workdir/trivial.c b/tests-clar/merge/workdir/trivial.c index d20d89879..9f9566243 100644 --- a/tests-clar/merge/workdir/trivial.c +++ b/tests-clar/merge/workdir/trivial.c @@ -62,7 +62,7 @@ static int merge_trivial(const char *ours, const char *theirs, bool automerge) return 0; } -static int merge_trivial_conflict_entrycount(void) +static size_t merge_trivial_conflict_entrycount(void) { const git_index_entry *entry; size_t count = 0; -- cgit v1.2.1 From 266af6d81960144334c16e061f1d30f94f8a1b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 30 Oct 2013 13:44:22 +0100 Subject: remote: don't allow such direct access to the refspecs Removing arbitrary refspecs makes things more complex to reason about. Instead, let the user set the fetch and push refspec list to whatever they want it to be. --- include/git2/remote.h | 37 ++++++++++++++++++------- src/clone.c | 16 ++++++++--- src/remote.c | 76 +++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 95 insertions(+), 34 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 15a92f3df..1f33c92e8 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -145,8 +145,11 @@ GIT_EXTERN(int) git_remote_set_pushurl(git_remote *remote, const char* url); /** * Add a fetch refspec to the remote * + * Convenience function for adding a single fetch refspec to the + * current list in the remote. + * * @param remote the remote - * @apram refspec the new fetch refspec + * @param refspec the new fetch refspec * @return 0 or an error value */ GIT_EXTERN(int) git_remote_add_fetch(git_remote *remote, const char *refspec); @@ -162,9 +165,22 @@ GIT_EXTERN(int) git_remote_add_fetch(git_remote *remote, const char *refspec); */ GIT_EXTERN(int) git_remote_get_fetch_refspecs(git_strarray *array, git_remote *remote); +/** + * Set the remote's list of fetch refspecs + * + * The contents of the string array are copied. + * + * @param remote the remote to modify + * @param array the new list of fetch resfpecs + */ +GIT_EXTERN(int) git_remote_set_fetch_refspecs(git_remote *remote, git_strarray *array); + /** * Add a push refspec to the remote * + * Convenience function for adding a single push refspec to the + * current list in the remote. + * * @param remote the remote * @param refspec the new push refspec * @return 0 or an error value @@ -182,6 +198,16 @@ GIT_EXTERN(int) git_remote_add_push(git_remote *remote, const char *refspec); */ GIT_EXTERN(int) git_remote_get_push_refspecs(git_strarray *array, git_remote *remote); +/** + * Set the remote's list of push refspecs + * + * The contents of the string array are copied. + * + * @param remote the remote to modify + * @param array the new list of push resfpecs + */ +GIT_EXTERN(int) git_remote_set_push_refspecs(git_remote *remote, git_strarray *array); + /** * Clear the refspecs * @@ -208,15 +234,6 @@ GIT_EXTERN(size_t) git_remote_refspec_count(git_remote *remote); */ GIT_EXTERN(const git_refspec *)git_remote_get_refspec(git_remote *remote, size_t n); -/** - * Remove a refspec from the remote - * - * @param remote the remote to query - * @param n the refspec to remove - * @return 0 or GIT_ENOTFOUND - */ -GIT_EXTERN(int) git_remote_remove_refspec(git_remote *remote, size_t n); - /** * Open a connection to a remote * diff --git a/src/clone.c b/src/clone.c index 657243945..f9338b746 100644 --- a/src/clone.c +++ b/src/clone.c @@ -349,7 +349,7 @@ static bool should_checkout( int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch) { int error = 0, old_fetchhead; - size_t nspecs; + git_strarray refspecs; assert(repo && remote); @@ -358,6 +358,10 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_ return -1; } + + if ((error = git_remote_get_fetch_refspecs(&refspecs, remote)) < 0) + return error; + if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0) return error; @@ -378,9 +382,13 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_ cleanup: git_remote_set_update_fetchhead(remote, old_fetchhead); - /* Remove the tags refspec */ - nspecs = git_remote_refspec_count(remote); - git_remote_remove_refspec(remote, nspecs); + /* Go back to the original refspecs */ + if (git_remote_set_fetch_refspecs(remote, &refspecs) < 0) { + git_strarray_free(&refspecs); + return -1; + } + + git_strarray_free(&refspecs); return error; } diff --git a/src/remote.c b/src/remote.c index 49de5fa25..a2fd21007 100644 --- a/src/remote.c +++ b/src/remote.c @@ -1047,9 +1047,6 @@ void git_remote_disconnect(git_remote *remote) void git_remote_free(git_remote *remote) { - git_refspec *spec; - size_t i; - if (remote == NULL) return; @@ -1515,14 +1512,68 @@ void git_remote_clear_refspecs(git_remote *remote) git_vector_clear(&remote->refspecs); } +static int add_and_dwim(git_remote *remote, const char *str, int push) +{ + git_refspec *spec; + git_vector *vec; + + if (add_refspec(remote, str, !push) < 0) + return -1; + + vec = &remote->refspecs; + spec = git_vector_get(vec, vec->length - 1); + return git_refspec__dwim_one(&remote->active_refspecs, spec, &remote->refs); +} + int git_remote_add_fetch(git_remote *remote, const char *refspec) { - return add_refspec(remote, refspec, true); + return add_and_dwim(remote, refspec, false); } int git_remote_add_push(git_remote *remote, const char *refspec) { - return add_refspec(remote, refspec, false); + return add_and_dwim(remote, refspec, true); +} + +static int set_refspecs(git_remote *remote, git_strarray *array, int push) +{ + git_vector *vec = &remote->refspecs; + git_refspec *spec; + size_t i; + + /* Start by removing any refspecs of the same type */ + for (i = 0; i < vec->length; i++) { + spec = git_vector_get(vec, i); + if (spec->push != push) + continue; + + git_refspec__free(spec); + git__free(spec); + git_vector_remove(vec, i); + i--; + } + + /* And now we add the new ones */ + + for (i = 0; i < array->count; i++) { + if (add_refspec(remote, array->strings[i], !push) < 0) + return -1; + } + + free_refspecs(&remote->active_refspecs); + git_vector_clear(&remote->active_refspecs); + + return dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs); +} + +int git_remote_set_fetch_refspecs(git_remote *remote, git_strarray *array) +{ + return set_refspecs(remote, array, false); +} + +int git_remote_set_push_refspecs(git_remote *remote, git_strarray *array) +{ + return set_refspecs(remote, array, true); } static int copy_refspecs(git_strarray *array, git_remote *remote, unsigned int push) @@ -1580,18 +1631,3 @@ const git_refspec *git_remote_get_refspec(git_remote *remote, size_t n) { return git_vector_get(&remote->refspecs, n); } - -int git_remote_remove_refspec(git_remote *remote, size_t n) -{ - git_refspec *spec; - - assert(remote); - - spec = git_vector_get(&remote->refspecs, n); - if (spec) { - git_refspec__free(spec); - git__free(spec); - } - - return git_vector_remove(&remote->refspecs, n); -} -- cgit v1.2.1 From 359dce726d215be65aee719c7316b43e3851c031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 2 Nov 2013 00:05:32 +0100 Subject: remote: make _ls return the list directly The callback-based method of listing remote references dates back to the beginning of the network code's lifetime, when we didn't know any better. We need to keep the list around for update_tips() after disconnect() so let's make use of this to simply give the user a pointer to the array so they can write straightforward code instead of having to go through a callback. --- examples/network/ls-remote.c | 26 +++++++++++--------- include/git2/remote.h | 13 +++++----- include/git2/transport.h | 12 ++++----- src/clone.c | 25 ++++++------------- src/fetch.c | 43 +++++++++++++++------------------ src/push.c | 20 +++++++++------ src/remote.c | 21 ++++------------ src/transports/local.c | 10 +++----- src/transports/smart.c | 34 +++++++++++++++----------- src/transports/smart.h | 1 + src/transports/smart_protocol.c | 1 + tests-clar/network/remote/local.c | 51 ++++++++++++++++----------------------- tests-clar/online/fetch.c | 19 ++++----------- tests-clar/online/push.c | 7 +++--- tests-clar/online/push_util.c | 15 +++++++----- tests-clar/online/push_util.h | 5 ++-- 16 files changed, 140 insertions(+), 163 deletions(-) diff --git a/examples/network/ls-remote.c b/examples/network/ls-remote.c index 18cd02367..1e08b293e 100644 --- a/examples/network/ls-remote.c +++ b/examples/network/ls-remote.c @@ -4,21 +4,12 @@ #include #include "common.h" -/** Callback to show each item */ -static int show_ref__cb(git_remote_head *head, void *payload) -{ - char oid[GIT_OID_HEXSZ + 1] = {0}; - - (void)payload; - git_oid_fmt(oid, &head->oid); - printf("%s\t%s\n", oid, head->name); - return 0; -} - static int use_remote(git_repository *repo, char *name) { git_remote *remote = NULL; int error; + const git_remote_head **refs; + size_t refs_len, i; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; // Find the remote by name @@ -40,7 +31,18 @@ static int use_remote(git_repository *repo, char *name) if (error < 0) goto cleanup; - error = git_remote_ls(remote, &show_ref__cb, NULL); + /** + * Get the list of references on the remote and print out + * their name next to what they point to. + */ + if (git_remote_ls(&refs, &refs_len, remote) < 0) + goto cleanup; + + for (i = 0; i < refs_len; i++) { + char oid[GIT_OID_HEXSZ + 1] = {0}; + git_oid_fmt(oid, &refs[i]->oid); + printf("%s\t%s\n", oid, refs[i]->name); + } cleanup: git_remote_free(remote); diff --git a/include/git2/remote.h b/include/git2/remote.h index 1f33c92e8..9e7d218a8 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -254,15 +254,16 @@ GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction); * The remote (or more exactly its transport) must be connected. The * memory belongs to the remote. * - * If you a return a non-zero value from the callback, this will stop - * looping over the refs. + * The array will stay valid as long as the remote object exists and + * its transport isn't changed, but a copy is recommended for usage of + * the data. * + * @param out pointer to the array + * @param size the number of remote heads * @param remote the remote - * @param list_cb function to call with each ref discovered at the remote - * @param payload additional data to pass to the callback - * @return 0 on success, GIT_EUSER on non-zero callback, or error code + * @return 0 on success, or an error code */ -GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload); +GIT_EXTERN(int) git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote); /** * Download and index the packfile diff --git a/include/git2/transport.h b/include/git2/transport.h index 147b3fdcb..81ebf4dc9 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -203,13 +203,13 @@ struct git_transport { int direction, int flags); - /* This function may be called after a successful call to connect(). The - * provided callback is invoked for each ref discovered on the remote - * end. */ + /* This function may be called after a successful call to + * connect(). The array returned is owned by the transport and + * is guranteed until the next call of a transport function. */ int (*ls)( - git_transport *transport, - git_headlist_cb list_cb, - void *payload); + const git_remote_head ***out, + size_t *size, + git_transport *transport); /* Executes the push whose context is in the git_push object. */ int (*push)(git_transport *transport, git_push *push); diff --git a/src/clone.c b/src/clone.c index f9338b746..23aacd478 100644 --- a/src/clone.c +++ b/src/clone.c @@ -176,25 +176,20 @@ static int update_head_to_new_branch( return error; } -static int get_head_callback(git_remote_head *head, void *payload) -{ - git_remote_head **destination = (git_remote_head **)payload; - - /* Save the first entry, and terminate the enumeration */ - *destination = head; - return 1; -} - static int update_head_to_remote(git_repository *repo, git_remote *remote) { int retcode = -1; + size_t refs_len; git_refspec dummy_spec; - git_remote_head *remote_head; + const git_remote_head *remote_head, **refs; struct head_info head_info; git_buf remote_master_name = GIT_BUF_INIT; + if (git_remote_ls(&refs, &refs_len, remote) < 0) + return -1; + /* Did we just clone an empty repository? */ - if (remote->refs.length == 0) { + if (refs_len == 0) { return setup_tracking_config( repo, "master", @@ -202,12 +197,8 @@ static int update_head_to_remote(git_repository *repo, git_remote *remote) GIT_REFS_HEADS_MASTER_FILE); } - /* Get the remote's HEAD. This is always the first ref in remote->refs. */ - remote_head = NULL; - - if (!remote->transport->ls(remote->transport, get_head_callback, &remote_head)) - return -1; - + /* Get the remote's HEAD. This is always the first ref in the list. */ + remote_head = refs[0]; assert(remote_head); git_oid_cpy(&head_info.remote_head_oid, &remote_head->oid); diff --git a/src/fetch.c b/src/fetch.c index 295b036ef..19afddcd8 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -19,52 +19,47 @@ #include "repository.h" #include "refs.h" -struct filter_payload { - git_remote *remote; - const git_refspec *spec, *tagspec; - git_odb *odb; -}; - -static int filter_ref__cb(git_remote_head *head, void *payload) +static int maybe_want(git_remote *remote, git_remote_head *head, git_odb *odb, git_refspec *tagspec) { - struct filter_payload *p = payload; int match = 0; if (!git_reference_is_valid_name(head->name)) return 0; - if (p->remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { + if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { /* * If tagopt is --tags, then we only use the default * tags refspec and ignore the remote's */ - if (git_refspec_src_matches(p->tagspec, head->name)) + if (git_refspec_src_matches(tagspec, head->name)) match = 1; else return 0; - } else if (git_remote__matching_refspec(p->remote, head->name)) + } else if (git_remote__matching_refspec(remote, head->name)) match = 1; if (!match) return 0; /* If we have the object, mark it so we don't ask for it */ - if (git_odb_exists(p->odb, &head->oid)) + if (git_odb_exists(odb, &head->oid)) head->local = 1; else - p->remote->need_pack = 1; + remote->need_pack = 1; - return git_vector_insert(&p->remote->refs, head); + return git_vector_insert(&remote->refs, head); } static int filter_wants(git_remote *remote) { - struct filter_payload p; + git_remote_head **heads; git_refspec tagspec, head; - int error = -1; + int error = 0; + git_odb *odb; + size_t i, heads_len; - //git_vector_clear(&remote->refs); - if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0) + git_vector_clear(&remote->refs); + if ((error = git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true)) < 0) return error; /* @@ -73,8 +68,6 @@ static int filter_wants(git_remote *remote) * not interested in any particular branch but just the remote's * HEAD, which will be stored in FETCH_HEAD after the fetch. */ - p.tagspec = &tagspec; - p.remote = remote; if (remote->active_refspecs.length == 0) { if ((error = git_refspec__parse(&head, "HEAD", true)) < 0) goto cleanup; @@ -83,12 +76,16 @@ static int filter_wants(git_remote *remote) goto cleanup; } - git_vector_clear(&remote->refs); + if (git_repository_odb__weakptr(&odb, remote->repo) < 0) + goto cleanup; - if (git_repository_odb__weakptr(&p.odb, remote->repo) < 0) + if (git_remote_ls((const git_remote_head ***)&heads, &heads_len, remote) < 0) goto cleanup; - error = git_remote_ls(remote, filter_ref__cb, &p); + for (i = 0; i < heads_len; i++) { + if ((error = maybe_want(remote, heads[i], odb, &tagspec)) < 0) + break; + } cleanup: git_refspec__free(&tagspec); diff --git a/src/push.c b/src/push.c index a799db8d0..4f442c6a2 100644 --- a/src/push.c +++ b/src/push.c @@ -616,16 +616,22 @@ on_error: return error; } -static int cb_filter_refs(git_remote_head *ref, void *data) -{ - git_remote *remote = (git_remote *) data; - return git_vector_insert(&remote->refs, ref); -} - static int filter_refs(git_remote *remote) { + const git_remote_head **heads; + size_t heads_len, i; + git_vector_clear(&remote->refs); - return git_remote_ls(remote, cb_filter_refs, remote); + + if (git_remote_ls(&heads, &heads_len, remote) < 0) + return -1; + + for (i = 0; i < heads_len; i++) { + if (git_vector_insert(&remote->refs, heads[i]) < 0) + return -1; + } + + return 0; } int git_push_finish(git_push *push) diff --git a/src/remote.c b/src/remote.c index a2fd21007..289ead802 100644 --- a/src/remote.c +++ b/src/remote.c @@ -620,11 +620,11 @@ on_error: return -1; } -int git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload) +int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote) { assert(remote); - return remote->transport->ls(remote->transport, list_cb, payload); + return remote->transport->ls(out, size, remote->transport); } int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url) @@ -684,13 +684,6 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur return 0; } -static int store_refs(git_remote_head *head, void *payload) -{ - git_vector *refs = (git_vector *)payload; - - return git_vector_insert(refs, head); -} - /* DWIM `refspecs` based on `refs` and append the output to `out` */ static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs) { @@ -736,15 +729,12 @@ int git_remote_download(git_remote *remote) if (git_vector_init(&refs, 8, remote_head_cmp) < 0) return -1; - if (git_remote_ls(remote, store_refs, &refs) < 0) { + if (git_remote_ls((const git_remote_head ***)&refs.contents, &refs.length, remote) < 0) return -1; - } free_refspecs(&remote->active_refspecs); - error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &refs); - git_vector_free(&refs); - if (error < 0) + if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &refs) < 0) return -1; if ((error = git_fetch_negotiate(remote)) < 0) @@ -996,7 +986,7 @@ int git_remote_update_tips(git_remote *remote) if (git_vector_init(&refs, 16, NULL) < 0) return -1; - if ((error = git_remote_ls(remote, store_refs, &refs)) < 0) + if ((error = git_remote_ls((const git_remote_head ***)&refs.contents, &refs.length, remote)) < 0) goto out; if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { @@ -1014,7 +1004,6 @@ int git_remote_update_tips(git_remote *remote) out: git_refspec__free(&tagspec); - git_vector_free(&refs); return error; } diff --git a/src/transports/local.c b/src/transports/local.c index 3163d2eac..4502f0202 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -213,21 +213,17 @@ static int local_connect( return 0; } -static int local_ls(git_transport *transport, git_headlist_cb list_cb, void *payload) +static int local_ls(const git_remote_head ***out, size_t *size, git_transport *transport) { transport_local *t = (transport_local *)transport; - unsigned int i; - git_remote_head *head = NULL; if (!t->have_refs) { giterr_set(GITERR_NET, "The transport has not yet loaded the refs"); return -1; } - git_vector_foreach(&t->refs, i, head) { - if (list_cb(head, payload)) - return GIT_EUSER; - } + *out = (const git_remote_head **) t->refs.contents; + *size = t->refs.length; return 0; } diff --git a/src/transports/smart.c b/src/transports/smart.c index a681d5f40..53f880583 100644 --- a/src/transports/smart.c +++ b/src/transports/smart.c @@ -74,6 +74,7 @@ static int git_smart__connect( transport_smart *t = (transport_smart *)transport; git_smart_subtransport_stream *stream; int error; + size_t i; git_pkt *pkt; git_pkt_ref *first; git_smart_service_t service; @@ -140,6 +141,16 @@ static int git_smart__connect( git_pkt_free((git_pkt *)first); } + /* Keep a list of heads for _ls */ + git_vector_foreach(&t->refs, i, pkt) { + git_pkt_ref *ref = (git_pkt_ref *) pkt; + if (pkt->type != GIT_PKT_REF) + continue; + + if (git_vector_insert(&t->heads, &ref->head) < 0) + return -1; + } + if (t->rpc && git_smart__reset_stream(t, false) < 0) return -1; @@ -149,28 +160,17 @@ static int git_smart__connect( return 0; } -static int git_smart__ls(git_transport *transport, git_headlist_cb list_cb, void *payload) +static int git_smart__ls(const git_remote_head ***out, size_t *size, git_transport *transport) { transport_smart *t = (transport_smart *)transport; - unsigned int i; - git_pkt *p = NULL; if (!t->have_refs) { giterr_set(GITERR_NET, "The transport has not yet loaded the refs"); return -1; } - git_vector_foreach(&t->refs, i, p) { - git_pkt_ref *pkt = NULL; - - if (p->type != GIT_PKT_REF) - continue; - - pkt = (git_pkt_ref *)p; - - if (list_cb(&pkt->head, payload)) - return GIT_EUSER; - } + *out = (const git_remote_head **) t->heads.contents; + *size = t->heads.length; return 0; } @@ -293,6 +293,7 @@ static void git_smart__free(git_transport *transport) /* Free the subtransport */ t->wrapped->free(t->wrapped); + git_vector_free(&t->heads); git_vector_foreach(refs, i, p) git_pkt_free(p); @@ -340,6 +341,11 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param) return -1; } + if (git_vector_init(&t->heads, 16, ref_name_cmp) < 0) { + git__free(t); + return -1; + } + if (definition->callback(&t->wrapped, &t->parent) < 0) { git__free(t); return -1; diff --git a/src/transports/smart.h b/src/transports/smart.h index 5232e54de..b46a798a4 100644 --- a/src/transports/smart.h +++ b/src/transports/smart.h @@ -140,6 +140,7 @@ typedef struct { git_smart_subtransport_stream *current_stream; transport_smart_caps caps; git_vector refs; + git_vector heads; git_vector common; git_atomic cancelled; packetsize_cb packetsize_cb; diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index ce3f115ee..4fe7c0d09 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -32,6 +32,7 @@ int git_smart__store_refs(transport_smart *t, int flushes) /* Clear existing refs in case git_remote_connect() is called again * after git_remote_disconnect(). */ + git_vector_clear(&t->heads); git_vector_foreach(refs, i, ref) { git__free(ref->head.name); git__free(ref); diff --git a/tests-clar/network/remote/local.c b/tests-clar/network/remote/local.c index 6d658a2e4..309142925 100644 --- a/tests-clar/network/remote/local.c +++ b/tests-clar/network/remote/local.c @@ -26,26 +26,6 @@ void test_network_remote_local__cleanup(void) cl_fixture_cleanup("remotelocal"); } -static int count_ref__cb(git_remote_head *head, void *payload) -{ - int *count = (int *)payload; - - (void)head; - (*count)++; - - return 0; -} - -static int ensure_peeled__cb(git_remote_head *head, void *payload) -{ - GIT_UNUSED(payload); - - if(strcmp(head->name, "refs/tags/test^{}") != 0) - return 0; - - return git_oid_streq(&head->oid, "e90810b8df3e80c413d903f631643c716887138d"); -} - static void connect_to_local_repository(const char *local_repository) { git_buf_sets(&file_path_buf, cl_git_path_url(local_repository)); @@ -65,39 +45,42 @@ void test_network_remote_local__connected(void) void test_network_remote_local__retrieve_advertised_references(void) { - int how_many_refs = 0; + const git_remote_head **refs; + size_t refs_len; connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs)); + cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); - cl_assert_equal_i(how_many_refs, 28); + cl_assert_equal_i(refs_len, 28); } void test_network_remote_local__retrieve_advertised_references_after_disconnect(void) { - int how_many_refs = 0; + const git_remote_head **refs; + size_t refs_len; connect_to_local_repository(cl_fixture("testrepo.git")); git_remote_disconnect(remote); - cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs)); + cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); - cl_assert_equal_i(how_many_refs, 28); + cl_assert_equal_i(refs_len, 28); } void test_network_remote_local__retrieve_advertised_references_from_spaced_repository(void) { - int how_many_refs = 0; + const git_remote_head **refs; + size_t refs_len; cl_fixture_sandbox("testrepo.git"); cl_git_pass(p_rename("testrepo.git", "spaced testrepo.git")); connect_to_local_repository("spaced testrepo.git"); - cl_git_pass(git_remote_ls(remote, &count_ref__cb, &how_many_refs)); + cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); - cl_assert_equal_i(how_many_refs, 28); + cl_assert_equal_i(refs_len, 28); git_remote_free(remote); /* Disconnect from the "spaced repo" before the cleanup */ remote = NULL; @@ -107,9 +90,17 @@ void test_network_remote_local__retrieve_advertised_references_from_spaced_repos void test_network_remote_local__nested_tags_are_completely_peeled(void) { + const git_remote_head **refs; + size_t refs_len, i; + connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_ls(remote, &ensure_peeled__cb, NULL)); + cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); + + for (i = 0; i < refs_len; i++) { + if (!strcmp(refs[i]->name, "refs/tags/test^{}")) + cl_git_pass(git_oid_streq(&refs[i]->oid, "e90810b8df3e80c413d903f631643c716887138d")); + } } void test_network_remote_local__shorthand_fetch_refspec0(void) diff --git a/tests-clar/online/fetch.c b/tests-clar/online/fetch.c index df1b2e288..5153a7ae0 100644 --- a/tests-clar/online/fetch.c +++ b/tests-clar/online/fetch.c @@ -152,29 +152,20 @@ void test_online_fetch__can_cancel(void) git_remote_free(remote); } -int ls_cb(git_remote_head *rhead, void *payload) -{ - int *nr = payload; - GIT_UNUSED(rhead); - - (*nr)++; - - return 0; -} - void test_online_fetch__ls_disconnected(void) { + const git_remote_head **refs; + size_t refs_len_before, refs_len_after; git_remote *remote; - int nr_before = 0, nr_after = 0; cl_git_pass(git_remote_create(&remote, _repo, "test", "http://github.com/libgit2/TestGitRepository.git")); cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_ls(remote, ls_cb, &nr_before)); + cl_git_pass(git_remote_ls(&refs, &refs_len_before, remote)); git_remote_disconnect(remote); - cl_git_pass(git_remote_ls(remote, ls_cb, &nr_after)); + cl_git_pass(git_remote_ls(&refs, &refs_len_after, remote)); - cl_assert_equal_i(nr_before, nr_after); + cl_assert_equal_i(refs_len_before, refs_len_after); git_remote_free(remote); } diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 5a747bba7..9ed97174b 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -155,10 +155,11 @@ static void do_verify_push_status(git_push *push, const push_status expected[], */ static void verify_refs(git_remote *remote, expected_ref expected_refs[], size_t expected_refs_len) { - git_vector actual_refs = GIT_VECTOR_INIT; + const git_remote_head **actual_refs; + size_t actual_refs_len; - git_remote_ls(remote, record_ref_cb, &actual_refs); - verify_remote_refs(&actual_refs, expected_refs, expected_refs_len); + git_remote_ls(&actual_refs, &actual_refs_len, remote); + verify_remote_refs(actual_refs, actual_refs_len, expected_refs, expected_refs_len); git_vector_free(&actual_refs); } diff --git a/tests-clar/online/push_util.c b/tests-clar/online/push_util.c index 2e457844d..e3f326932 100644 --- a/tests-clar/online/push_util.c +++ b/tests-clar/online/push_util.c @@ -69,26 +69,28 @@ int record_ref_cb(git_remote_head *head, void *payload) return git_vector_insert(refs, head); } -void verify_remote_refs(git_vector *actual_refs, const expected_ref expected_refs[], size_t expected_refs_len) +void verify_remote_refs(const git_remote_head *actual_refs[], size_t actual_refs_len, const expected_ref expected_refs[], size_t expected_refs_len) { size_t i, j = 0; git_buf msg = GIT_BUF_INIT; - git_remote_head *actual; + const git_remote_head *actual; char *oid_str; bool master_present = false; /* We don't care whether "master" is present on the other end or not */ - git_vector_foreach(actual_refs, i, actual) { + for (i = 0; i < actual_refs_len; i++) { + actual = actual_refs[i]; if (!strcmp(actual->name, "refs/heads/master")) { master_present = true; break; } } - if (expected_refs_len + (master_present ? 1 : 0) != actual_refs->length) + if (expected_refs_len + (master_present ? 1 : 0) != actual_refs_len) goto failed; - git_vector_foreach(actual_refs, i, actual) { + for (i = 0; i < actual_refs_len; i++) { + actual = actual_refs[i]; if (master_present && !strcmp(actual->name, "refs/heads/master")) continue; @@ -111,7 +113,8 @@ failed: } git_buf_puts(&msg, "\nACTUAL:\n"); - git_vector_foreach(actual_refs, i, actual) { + for (i = 0; i < actual_refs_len; i++) { + actual = actual_refs[i]; if (master_present && !strcmp(actual->name, "refs/heads/master")) continue; diff --git a/tests-clar/online/push_util.h b/tests-clar/online/push_util.h index 64f02cf2f..e6ddb7133 100644 --- a/tests-clar/online/push_util.h +++ b/tests-clar/online/push_util.h @@ -60,10 +60,11 @@ int record_ref_cb(git_remote_head *head, void *payload); * Verifies that refs on remote stored by record_ref_cb match the expected * names, oids, and order. * - * @param actual_refs actual refs stored by record_ref_cb() + * @param actual_refs actual refs in the remote + * @param actual_refs_len length of actual_refs * @param expected_refs expected remote refs * @param expected_refs_len length of expected_refs */ -void verify_remote_refs(git_vector *actual_refs, const expected_ref expected_refs[], size_t expected_refs_len); +void verify_remote_refs(const git_remote_head *actual_refs[], size_t actual_refs_len, const expected_ref expected_refs[], size_t expected_refs_len); #endif /* INCLUDE_cl_push_util_h__ */ -- cgit v1.2.1 From 1c967df31c9285af6eaea3c462314b4b88c2706a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 2 Nov 2013 00:51:57 +0100 Subject: remote: fix a couple of leaks --- src/fetch.c | 5 ++++- src/remote.c | 6 ------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/fetch.c b/src/fetch.c index 19afddcd8..276591821 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -72,7 +72,10 @@ static int filter_wants(git_remote *remote) if ((error = git_refspec__parse(&head, "HEAD", true)) < 0) goto cleanup; - if ((error = git_refspec__dwim_one(&remote->active_refspecs, &head, &remote->refs)) < 0) + error = git_refspec__dwim_one(&remote->active_refspecs, &head, &remote->refs); + git_refspec__free(&head); + + if (error < 0) goto cleanup; } diff --git a/src/remote.c b/src/remote.c index 289ead802..dcadb92ae 100644 --- a/src/remote.c +++ b/src/remote.c @@ -726,9 +726,6 @@ int git_remote_download(git_remote *remote) assert(remote); - if (git_vector_init(&refs, 8, remote_head_cmp) < 0) - return -1; - if (git_remote_ls((const git_remote_head ***)&refs.contents, &refs.length, remote) < 0) return -1; @@ -983,9 +980,6 @@ int git_remote_update_tips(git_remote *remote) if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0) return -1; - if (git_vector_init(&refs, 16, NULL) < 0) - return -1; - if ((error = git_remote_ls((const git_remote_head ***)&refs.contents, &refs.length, remote)) < 0) goto out; -- cgit v1.2.1 From 877cde765a9957f893d7b22026a8c82bf82226d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 2 Nov 2013 01:10:21 +0100 Subject: remote: let's at least pretend to have some memory safety Copy the pointers into temporary vectors instead of assigning them tot he same array so we don't mess up with someone else's memory by accident (e.g. by sorting). --- src/remote.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/remote.c b/src/remote.c index dcadb92ae..62f297a7e 100644 --- a/src/remote.c +++ b/src/remote.c @@ -719,6 +719,25 @@ static int remote_head_cmp(const void *_a, const void *_b) return git__strcmp_cb(a->name, b->name); } +static int ls_to_vector(git_vector *out, git_remote *remote) +{ + git_remote_head **heads; + size_t heads_len, i; + + if (git_remote_ls((const git_remote_head ***)&heads, &heads_len, remote) < 0) + return -1; + + if (git_vector_init(out, heads_len, remote_head_cmp) < 0) + return -1; + + for (i = 0; i < heads_len; i++) { + if (git_vector_insert(out, heads[i]) < 0) + return -1; + } + + return 0; +} + int git_remote_download(git_remote *remote) { int error; @@ -726,12 +745,15 @@ int git_remote_download(git_remote *remote) assert(remote); - if (git_remote_ls((const git_remote_head ***)&refs.contents, &refs.length, remote) < 0) + if (ls_to_vector(&refs, remote) < 0) return -1; free_refspecs(&remote->active_refspecs); - if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &refs) < 0) + error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &refs); + git_vector_free(&refs); + + if (error < 0) return -1; if ((error = git_fetch_negotiate(remote)) < 0) @@ -980,7 +1002,8 @@ int git_remote_update_tips(git_remote *remote) if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0) return -1; - if ((error = git_remote_ls((const git_remote_head ***)&refs.contents, &refs.length, remote)) < 0) + + if ((error = ls_to_vector(&refs, remote)) < 0) goto out; if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { @@ -997,6 +1020,7 @@ int git_remote_update_tips(git_remote *remote) } out: + git_vector_free(&refs); git_refspec__free(&tagspec); return error; } -- cgit v1.2.1 From ae2972122e9487c38a2e72109a35b7d337658d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sun, 10 Nov 2013 17:29:06 +0100 Subject: tests: update push tests These tests were forgotten when modifying git_remote_ls(). --- tests-clar/online/push.c | 8 ++++---- tests-clar/online/push_util.c | 25 ++++++++++++++----------- tests-clar/online/push_util.h | 9 +++++---- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 9ed97174b..b5ec77a37 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -160,8 +160,6 @@ static void verify_refs(git_remote *remote, expected_ref expected_refs[], size_t git_remote_ls(&actual_refs, &actual_refs_len, remote); verify_remote_refs(actual_refs, actual_refs_len, expected_refs, expected_refs_len); - - git_vector_free(&actual_refs); } static int tracking_branch_list_cb(const char *branch_name, git_branch_t branch_type, void *payload) @@ -265,7 +263,8 @@ failed: void test_online_push__initialize(void) { git_vector delete_specs = GIT_VECTOR_INIT; - size_t i; + const git_remote_head **heads; + size_t i, heads_len; char *curr_del_spec; _repo = cl_git_sandbox_init("push_src"); @@ -322,7 +321,8 @@ void test_online_push__initialize(void) * order to delete the remote branch pointed to by HEAD (usually master). * See: https://raw.github.com/git/git/master/Documentation/RelNotes/1.7.0.txt */ - cl_git_pass(git_remote_ls(_remote, delete_ref_cb, &delete_specs)); + cl_git_pass(git_remote_ls(&heads, &heads_len, _remote)); + cl_git_pass(create_deletion_refspecs(&delete_specs, heads, heads_len)); if (delete_specs.length) { git_push *push; diff --git a/tests-clar/online/push_util.c b/tests-clar/online/push_util.c index e3f326932..038c144db 100644 --- a/tests-clar/online/push_util.c +++ b/tests-clar/online/push_util.c @@ -44,20 +44,23 @@ int record_update_tips_cb(const char *refname, const git_oid *a, const git_oid * return 0; } -int delete_ref_cb(git_remote_head *head, void *payload) +int create_deletion_refspecs(git_vector *out, const git_remote_head **heads, size_t heads_len) { - git_vector *delete_specs = (git_vector *)payload; git_buf del_spec = GIT_BUF_INIT; + size_t i; - /* Ignore malformed ref names (which also saves us from tag^{} */ - if (!git_reference_is_valid_name(head->name)) - return 0; - - /* Create a refspec that deletes a branch in the remote */ - if (strcmp(head->name, "refs/heads/master")) { - cl_git_pass(git_buf_putc(&del_spec, ':')); - cl_git_pass(git_buf_puts(&del_spec, head->name)); - cl_git_pass(git_vector_insert(delete_specs, git_buf_detach(&del_spec))); + for (i = 0; i < heads_len; i++) { + const git_remote_head *head = heads[i]; + /* Ignore malformed ref names (which also saves us from tag^{} */ + if (!git_reference_is_valid_name(head->name)) + return 0; + + /* Create a refspec that deletes a branch in the remote */ + if (strcmp(head->name, "refs/heads/master")) { + cl_git_pass(git_buf_putc(&del_spec, ':')); + cl_git_pass(git_buf_puts(&del_spec, head->name)); + cl_git_pass(git_vector_insert(out, git_buf_detach(&del_spec))); + } } return 0; diff --git a/tests-clar/online/push_util.h b/tests-clar/online/push_util.h index e6ddb7133..a7207c49e 100644 --- a/tests-clar/online/push_util.h +++ b/tests-clar/online/push_util.h @@ -41,12 +41,13 @@ void record_callbacks_data_clear(record_callbacks_data *data); int record_update_tips_cb(const char *refname, const git_oid *a, const git_oid *b, void *data); /** - * Callback for git_remote_list that adds refspecs to delete each ref + * Create a set of refspecs that deletes each of the inputs * - * @param head a ref on the remote - * @param payload a git_push instance + * @param out the vector in which to store the refspecs + * @param heads the remote heads + * @param heads_len the size of the array */ -int delete_ref_cb(git_remote_head *head, void *payload); +int create_deletion_refspecs(git_vector *out, const git_remote_head **heads, size_t heads_len); /** * Callback for git_remote_list that adds refspecs to vector -- cgit v1.2.1 From a6192d7c98976edb0ce4fd10438ac7a19c283598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 11 Nov 2013 15:32:13 +0100 Subject: remote: update head list on push A previous commit forgot to update the head list after push as well, leading to wrong output of git_remote_ls(). --- src/transports/smart.c | 28 +++++++++++++++++++--------- src/transports/smart.h | 2 ++ src/transports/smart_protocol.c | 8 ++++++-- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/transports/smart.c b/src/transports/smart.c index 53f880583..5242beb65 100644 --- a/src/transports/smart.c +++ b/src/transports/smart.c @@ -63,6 +63,24 @@ static int git_smart__set_callbacks( return 0; } +int git_smart__update_heads(transport_smart *t) +{ + size_t i; + git_pkt *pkt; + + git_vector_clear(&t->heads); + git_vector_foreach(&t->refs, i, pkt) { + git_pkt_ref *ref = (git_pkt_ref *) pkt; + if (pkt->type != GIT_PKT_REF) + continue; + + if (git_vector_insert(&t->heads, &ref->head) < 0) + return -1; + } + + return 0; +} + static int git_smart__connect( git_transport *transport, const char *url, @@ -74,7 +92,6 @@ static int git_smart__connect( transport_smart *t = (transport_smart *)transport; git_smart_subtransport_stream *stream; int error; - size_t i; git_pkt *pkt; git_pkt_ref *first; git_smart_service_t service; @@ -142,14 +159,7 @@ static int git_smart__connect( } /* Keep a list of heads for _ls */ - git_vector_foreach(&t->refs, i, pkt) { - git_pkt_ref *ref = (git_pkt_ref *) pkt; - if (pkt->type != GIT_PKT_REF) - continue; - - if (git_vector_insert(&t->heads, &ref->head) < 0) - return -1; - } + git_smart__update_heads(t); if (t->rpc && git_smart__reset_stream(t, false) < 0) return -1; diff --git a/src/transports/smart.h b/src/transports/smart.h index b46a798a4..32f0be7f2 100644 --- a/src/transports/smart.h +++ b/src/transports/smart.h @@ -174,6 +174,8 @@ int git_smart__download_pack( int git_smart__negotiation_step(git_transport *transport, void *data, size_t len); int git_smart__get_push_stream(transport_smart *t, git_smart_subtransport_stream **out); +int git_smart__update_heads(transport_smart *t); + /* smart_pkt.c */ int git_pkt_parse_line(git_pkt **head, const char *line, const char **out, size_t len); int git_pkt_buffer_flush(git_buf *buf); diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 4fe7c0d09..ee1d34377 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -32,7 +32,6 @@ int git_smart__store_refs(transport_smart *t, int flushes) /* Clear existing refs in case git_remote_connect() is called again * after git_remote_disconnect(). */ - git_vector_clear(&t->heads); git_vector_foreach(refs, i, ref) { git__free(ref->head.name); git__free(ref); @@ -945,8 +944,13 @@ int git_smart__push(git_transport *transport, git_push *push) push->transfer_progress_cb(push->pb->nr_written, push->pb->nr_objects, packbuilder_payload.last_bytes, push->transfer_progress_cb_payload); } - if (push->status.length) + if (push->status.length) { error = update_refs_from_report(&t->refs, &push->specs, &push->status); + if (error < 0) + goto done; + + error = git_smart__update_heads(t); + } done: git_buf_free(&pktline); -- cgit v1.2.1 From fb190bbbd06952b369b4fb6c06fa827802671332 Mon Sep 17 00:00:00 2001 From: Linquize Date: Tue, 12 Nov 2013 19:44:13 +0800 Subject: Fix warnings --- examples/blame.c | 2 +- src/netops.c | 2 +- src/pack-objects.c | 2 +- src/push.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/blame.c b/examples/blame.c index 95bce6b9c..06310d540 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -114,7 +114,7 @@ int main(int argc, char *argv[]) rawdata+i); } - i = eol - rawdata + 1; + i = (int)(eol - rawdata + 1); line++; } diff --git a/src/netops.c b/src/netops.c index d7f17b1fc..592e46449 100644 --- a/src/netops.c +++ b/src/netops.c @@ -662,7 +662,7 @@ void gitno_connection_data_free_ptrs(gitno_connection_data *d) static char* unescape(char *str) { int x, y; - int len = strlen(str); + size_t len = strlen(str); for (x=y=0; str[y]; ++x, ++y) { if ((str[x] = str[y]) == '%') { diff --git a/src/pack-objects.c b/src/pack-objects.c index 9967cab1f..2d62507f2 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -272,7 +272,7 @@ static int write_object(git_buf *buf, git_packbuilder *pb, git_pobject *po) git_buf zbuf = GIT_BUF_INIT; git_otype type; unsigned char hdr[10]; - unsigned int hdr_len; + size_t hdr_len; unsigned long size; void *data; diff --git a/src/push.c b/src/push.c index 4f442c6a2..5ad15e3fd 100644 --- a/src/push.c +++ b/src/push.c @@ -618,7 +618,7 @@ on_error: static int filter_refs(git_remote *remote) { - const git_remote_head **heads; + git_remote_head **heads; size_t heads_len, i; git_vector_clear(&remote->refs); -- cgit v1.2.1 From f6f7537cfd8041d407a4f3b6c350b012975be116 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 12 Nov 2013 15:24:05 -0800 Subject: Add some failing blame test cases --- tests-clar/blame/buffer.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests-clar/blame/buffer.c b/tests-clar/blame/buffer.c index 69b2d5440..5da004652 100644 --- a/tests-clar/blame/buffer.c +++ b/tests-clar/blame/buffer.c @@ -19,6 +19,8 @@ void test_blame_buffer__cleanup(void) void test_blame_buffer__added_line(void) { + git_blame_hunk *hunk; + const char *buffer = "\ EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ @@ -39,6 +41,10 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); cl_assert_equal_i(5, git_blame_get_hunk_count(g_bufferblame)); check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "000000", "b.txt"); + + hunk = git_blame_get_hunk_byline(g_bufferblame, 16); + cl_assert(hunk); + cl_assert_equal_s("Ben Straub", hunk->final_signature->name); } void test_blame_buffer__deleted_line(void) @@ -128,3 +134,33 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 1, 0, "00000000", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 4, 8, 3, 0, "63d671eb", "b.txt"); } + +void test_blame_buffer__add_line_at_end(void) +{ + const char *buffer = "\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +abc\n\ +\n"; + cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); + + cl_assert_equal_i(5, git_blame_get_hunk_count(g_bufferblame)); + check_blame_hunk_index(g_repo, g_bufferblame, 0, 1, 4, 0, "da237394", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 5, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 11, 5, 0, "aa06ecca", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 4, 16, 1, 0, "00000000", "b.txt"); + +} -- cgit v1.2.1 From 089297b2cd4f50a2218130f9f3a0ddceb86b8697 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 12 Nov 2013 15:24:59 -0800 Subject: Duplicate all fields of a blame hunk --- src/blame.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/blame.c b/src/blame.c index 01d3fc03c..b562b5b98 100644 --- a/src/blame.c +++ b/src/blame.c @@ -75,6 +75,11 @@ static git_blame_hunk* dup_hunk(git_blame_hunk *hunk) hunk->orig_path); git_oid_cpy(&newhunk->orig_commit_id, &hunk->orig_commit_id); git_oid_cpy(&newhunk->final_commit_id, &hunk->final_commit_id); + newhunk->boundary = hunk->boundary; + if (hunk->final_signature) + newhunk->final_signature = git_signature_dup(hunk->final_signature); + if (hunk->orig_signature) + newhunk->orig_signature = git_signature_dup(hunk->orig_signature); return newhunk; } -- cgit v1.2.1 From 9db56cc4a78ee7799450cd3838af12124ccc4e8e Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 12 Nov 2013 18:57:16 -0800 Subject: Fix buffer blame with new lines at end of file --- src/blame.c | 15 ++++++--------- tests-clar/blame/buffer.c | 5 +++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/blame.c b/src/blame.c index b562b5b98..c5b7083ad 100644 --- a/src/blame.c +++ b/src/blame.c @@ -386,9 +386,13 @@ static int buffer_hunk_cb( wedge_line = (hunk->old_lines == 0) ? hunk->new_start : hunk->old_start; blame->current_diff_line = wedge_line; - /* If this hunk doesn't start between existing hunks, split a hunk up so it does */ blame->current_hunk = (git_blame_hunk*)git_blame_get_hunk_byline(blame, wedge_line); - if (!hunk_starts_at_or_after_line(blame->current_hunk, wedge_line)){ + if (!blame->current_hunk) { + /* Line added at the end of the file */ + blame->current_hunk = new_hunk(wedge_line, 0, wedge_line, blame->path); + git_vector_insert(&blame->hunks, blame->current_hunk); + } else if (!hunk_starts_at_or_after_line(blame->current_hunk, wedge_line)){ + /* If this hunk doesn't start between existing hunks, split a hunk up so it does */ blame->current_hunk = split_hunk_in_vector(&blame->hunks, blame->current_hunk, wedge_line - blame->current_hunk->orig_start_line_number, true); } @@ -409,13 +413,6 @@ static int buffer_line_cb( GIT_UNUSED(hunk); GIT_UNUSED(line); -#ifdef DO_DEBUG - { - char *str = git__substrdup(content, content_len); - git__free(str); - } -#endif - if (line->origin == GIT_DIFF_LINE_ADDITION) { if (hunk_is_bufferblame(blame->current_hunk) && hunk_ends_at_or_before_line(blame->current_hunk, blame->current_diff_line)) { diff --git a/tests-clar/blame/buffer.c b/tests-clar/blame/buffer.c index 5da004652..82085c3d5 100644 --- a/tests-clar/blame/buffer.c +++ b/tests-clar/blame/buffer.c @@ -152,8 +152,9 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +\n\ abc\n\ -\n"; +def\n"; cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); cl_assert_equal_i(5, git_blame_get_hunk_count(g_bufferblame)); @@ -161,6 +162,6 @@ abc\n\ check_blame_hunk_index(g_repo, g_bufferblame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 5, 0, "63d671eb", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 3, 11, 5, 0, "aa06ecca", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 4, 16, 1, 0, "00000000", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 4, 16, 2, 0, "00000000", "b.txt"); } -- cgit v1.2.1 From b20c40a8d6127a3ee9b807b2243e41bc8e85124c Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 12 Nov 2013 19:02:28 -0800 Subject: Don't leak memory when duplicating a NULL signature --- src/blame.c | 6 ++---- src/signature.c | 6 +++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/blame.c b/src/blame.c index c5b7083ad..219a6bfe4 100644 --- a/src/blame.c +++ b/src/blame.c @@ -76,10 +76,8 @@ static git_blame_hunk* dup_hunk(git_blame_hunk *hunk) git_oid_cpy(&newhunk->orig_commit_id, &hunk->orig_commit_id); git_oid_cpy(&newhunk->final_commit_id, &hunk->final_commit_id); newhunk->boundary = hunk->boundary; - if (hunk->final_signature) - newhunk->final_signature = git_signature_dup(hunk->final_signature); - if (hunk->orig_signature) - newhunk->orig_signature = git_signature_dup(hunk->orig_signature); + newhunk->final_signature = git_signature_dup(hunk->final_signature); + newhunk->orig_signature = git_signature_dup(hunk->orig_signature); return newhunk; } diff --git a/src/signature.c b/src/signature.c index 52ca2b375..ec51a42e9 100644 --- a/src/signature.c +++ b/src/signature.c @@ -84,8 +84,12 @@ int git_signature_new(git_signature **sig_out, const char *name, const char *ema git_signature *git_signature_dup(const git_signature *sig) { - git_signature *new = git__calloc(1, sizeof(git_signature)); + git_signature *new; + if (sig == NULL) + return NULL; + + new = git__calloc(1, sizeof(git_signature)); if (new == NULL) return NULL; -- cgit v1.2.1 From 4320bec09bff4596ed0647eb2fcbedf19995f631 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 12 Nov 2013 19:02:34 -0800 Subject: Minor cleanup --- tests-clar/blame/buffer.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests-clar/blame/buffer.c b/tests-clar/blame/buffer.c index 82085c3d5..912ee9846 100644 --- a/tests-clar/blame/buffer.c +++ b/tests-clar/blame/buffer.c @@ -19,7 +19,7 @@ void test_blame_buffer__cleanup(void) void test_blame_buffer__added_line(void) { - git_blame_hunk *hunk; + const git_blame_hunk *hunk; const char *buffer = "\ EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ @@ -135,7 +135,7 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC check_blame_hunk_index(g_repo, g_bufferblame, 4, 8, 3, 0, "63d671eb", "b.txt"); } -void test_blame_buffer__add_line_at_end(void) +void test_blame_buffer__add_lines_at_end(void) { const char *buffer = "\ EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ @@ -163,5 +163,4 @@ def\n"; check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 5, 0, "63d671eb", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 3, 11, 5, 0, "aa06ecca", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 4, 16, 2, 0, "00000000", "b.txt"); - } -- cgit v1.2.1 From cfd16ca28e593d084350b497b06eac7cb7a6c240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 13 Nov 2013 13:08:56 +0100 Subject: tests: make a few globals statics ld was warning that the size of path changed, rightly so. --- tests-clar/network/urlparse.c | 4 ++-- tests-clar/repo/config.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c index 31616275a..2a9c2f69f 100644 --- a/tests-clar/network/urlparse.c +++ b/tests-clar/network/urlparse.c @@ -1,8 +1,8 @@ #include "clar_libgit2.h" #include "netops.h" -char *host, *port, *path, *user, *pass; -gitno_connection_data conndata; +static char *host, *port, *path, *user, *pass; +static gitno_connection_data conndata; void test_network_urlparse__initialize(void) { diff --git a/tests-clar/repo/config.c b/tests-clar/repo/config.c index 11abd42bc..e77acc8c5 100644 --- a/tests-clar/repo/config.c +++ b/tests-clar/repo/config.c @@ -2,7 +2,7 @@ #include "fileops.h" #include -git_buf path = GIT_BUF_INIT; +static git_buf path = GIT_BUF_INIT; void test_repo_config__initialize(void) { -- cgit v1.2.1 From 98eaf39a87164eeb284df5c0239c3a31dfb538e7 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 13 Nov 2013 11:12:31 -0800 Subject: Fix warnings --- src/merge.c | 4 +++- src/netops.c | 2 +- src/push.c | 4 ++-- tests-clar/merge/workdir/setup.c | 3 ++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/merge.c b/src/merge.c index 2cbf531f9..115867971 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1649,7 +1649,7 @@ static int write_merge_head( goto cleanup; for (i = 0; i < heads_len; i++) { - if ((error = git_filebuf_printf(&file, "%s\n", &heads[i]->oid_str)) < 0) + if ((error = git_filebuf_printf(&file, "%s\n", heads[i]->oid_str)) < 0) goto cleanup; } @@ -2240,6 +2240,8 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde git_diff_options opts = GIT_DIFF_OPTIONS_INIT; int error = 0; + GIT_UNUSED(index_new); + *conflicts = 0; opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED; diff --git a/src/netops.c b/src/netops.c index 592e46449..15ed0fc26 100644 --- a/src/netops.c +++ b/src/netops.c @@ -662,7 +662,7 @@ void gitno_connection_data_free_ptrs(gitno_connection_data *d) static char* unescape(char *str) { int x, y; - size_t len = strlen(str); + int len = (int)strlen(str); for (x=y=0; str[y]; ++x, ++y) { if ((str[x] = str[y]) == '%') { diff --git a/src/push.c b/src/push.c index 5ad15e3fd..3c9d5bb35 100644 --- a/src/push.c +++ b/src/push.c @@ -618,7 +618,7 @@ on_error: static int filter_refs(git_remote *remote) { - git_remote_head **heads; + const git_remote_head **heads; size_t heads_len, i; git_vector_clear(&remote->refs); @@ -627,7 +627,7 @@ static int filter_refs(git_remote *remote) return -1; for (i = 0; i < heads_len; i++) { - if (git_vector_insert(&remote->refs, heads[i]) < 0) + if (git_vector_insert(&remote->refs, (void *)heads[i]) < 0) return -1; } diff --git a/tests-clar/merge/workdir/setup.c b/tests-clar/merge/workdir/setup.c index 463dee06e..870d55ef2 100644 --- a/tests-clar/merge/workdir/setup.c +++ b/tests-clar/merge/workdir/setup.c @@ -1041,7 +1041,8 @@ void test_merge_workdir_setup__removed_after_failure(void) cl_git_rewritefile("merge-resolve/new-in-octo1.txt", "Conflicting file!\n\nMerge will fail!\n"); - cl_git_fail(git_merge(&result, repo, &their_heads[0], 1, &opts)); + cl_git_fail(git_merge( + &result, repo, (const git_merge_head **)&their_heads[0], 1, &opts)); cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_HEAD_FILE)); cl_assert(!git_path_exists("merge-resolve/" GIT_ORIG_HEAD_FILE)); -- cgit v1.2.1 From 1782038144ef3413831801bb9c2f3038a84ac6f4 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 14 Nov 2013 14:05:52 -0800 Subject: Rename tests-clar to tests --- tests-clar/README.md | 22 - tests-clar/attr/attr_expect.h | 43 - tests-clar/attr/file.c | 224 --- tests-clar/attr/flags.c | 108 -- tests-clar/attr/ignore.c | 102 -- tests-clar/attr/lookup.c | 262 ---- tests-clar/attr/repo.c | 310 ---- tests-clar/blame/blame_helpers.c | 64 - tests-clar/blame/blame_helpers.h | 16 - tests-clar/blame/buffer.c | 166 --- tests-clar/blame/getters.c | 56 - tests-clar/blame/harder.c | 71 - tests-clar/blame/simple.c | 305 ---- tests-clar/buf/basic.c | 29 - tests-clar/buf/splice.c | 93 -- tests-clar/checkout/binaryunicode.c | 58 - tests-clar/checkout/checkout_helpers.c | 130 -- tests-clar/checkout/checkout_helpers.h | 29 - tests-clar/checkout/conflict.c | 1127 --------------- tests-clar/checkout/crlf.c | 231 --- tests-clar/checkout/head.c | 62 - tests-clar/checkout/index.c | 620 -------- tests-clar/checkout/tree.c | 742 ---------- tests-clar/checkout/typechange.c | 240 ---- tests-clar/clar.c | 511 ------- tests-clar/clar.h | 95 -- tests-clar/clar/fixtures.h | 38 - tests-clar/clar/fs.h | 325 ----- tests-clar/clar/print.h | 60 - tests-clar/clar/sandbox.h | 129 -- tests-clar/clar_libgit2.c | 483 ------- tests-clar/clar_libgit2.h | 119 -- tests-clar/clone/empty.c | 85 -- tests-clar/clone/nonetwork.c | 179 --- tests-clar/commit/commit.c | 46 - tests-clar/commit/parent.c | 60 - tests-clar/commit/parse.c | 413 ------ tests-clar/commit/signature.c | 81 -- tests-clar/commit/write.c | 147 -- tests-clar/config/add.c | 37 - tests-clar/config/backend.c | 24 - tests-clar/config/config_helpers.c | 37 - tests-clar/config/config_helpers.h | 9 - tests-clar/config/configlevel.c | 71 - tests-clar/config/global.c | 72 - tests-clar/config/include.c | 109 -- tests-clar/config/multivar.c | 288 ---- tests-clar/config/new.c | 32 - tests-clar/config/read.c | 569 -------- tests-clar/config/refresh.c | 67 - tests-clar/config/stress.c | 92 -- tests-clar/config/validkeyname.c | 68 - tests-clar/config/write.c | 305 ---- tests-clar/core/bitvec.c | 64 - tests-clar/core/buffer.c | 1039 -------------- tests-clar/core/caps.c | 31 - tests-clar/core/copy.c | 126 -- tests-clar/core/dirent.c | 236 ---- tests-clar/core/env.c | 303 ---- tests-clar/core/errors.c | 87 -- tests-clar/core/filebuf.c | 126 -- tests-clar/core/hex.c | 22 - tests-clar/core/iconv.c | 68 - tests-clar/core/mkdir.c | 188 --- tests-clar/core/oid.c | 70 - tests-clar/core/oidmap.c | 110 -- tests-clar/core/opts.c | 19 - tests-clar/core/path.c | 583 -------- tests-clar/core/pool.c | 145 -- tests-clar/core/posix.c | 99 -- tests-clar/core/rmdir.c | 98 -- tests-clar/core/sortedcache.c | 363 ----- tests-clar/core/stat.c | 97 -- tests-clar/core/string.c | 41 - tests-clar/core/strmap.c | 102 -- tests-clar/core/strtol.c | 37 - tests-clar/core/vector.c | 275 ---- tests-clar/date/date.c | 15 - tests-clar/diff/blob.c | 1067 -------------- tests-clar/diff/diff_helpers.c | 246 ---- tests-clar/diff/diff_helpers.h | 64 - tests-clar/diff/diffiter.c | 453 ------ tests-clar/diff/drivers.c | 163 --- tests-clar/diff/index.c | 167 --- tests-clar/diff/iterator.c | 937 ------------ tests-clar/diff/notify.c | 228 --- tests-clar/diff/patch.c | 571 -------- tests-clar/diff/pathspec.c | 93 -- tests-clar/diff/rename.c | 1286 ----------------- tests-clar/diff/submodules.c | 423 ------ tests-clar/diff/tree.c | 526 ------- tests-clar/diff/workdir.c | 1490 -------------------- tests-clar/fetchhead/fetchhead_data.h | 31 - tests-clar/fetchhead/nonetwork.c | 309 ---- tests-clar/filter/blob.c | 84 -- tests-clar/filter/crlf.c | 71 - tests-clar/filter/crlf.h | 25 - tests-clar/filter/custom.c | 337 ----- tests-clar/filter/ident.c | 131 -- tests-clar/generate.py | 244 ---- tests-clar/index/addall.c | 258 ---- tests-clar/index/conflicts.c | 287 ---- tests-clar/index/filemodes.c | 154 -- tests-clar/index/inmemory.c | 22 - tests-clar/index/names.c | 148 -- tests-clar/index/read_tree.c | 46 - tests-clar/index/rename.c | 50 - tests-clar/index/reuc.c | 372 ----- tests-clar/index/stage.c | 62 - tests-clar/index/tests.c | 537 ------- tests-clar/main.c | 20 - tests-clar/merge/merge_helpers.c | 333 ----- tests-clar/merge/merge_helpers.h | 62 - tests-clar/merge/trees/automerge.c | 217 --- tests-clar/merge/trees/modeconflict.c | 59 - tests-clar/merge/trees/renames.c | 252 ---- tests-clar/merge/trees/treediff.c | 542 ------- tests-clar/merge/trees/trivial.c | 397 ------ tests-clar/merge/workdir/fastforward.c | 148 -- tests-clar/merge/workdir/renames.c | 156 -- tests-clar/merge/workdir/setup.c | 1057 -------------- tests-clar/merge/workdir/simple.c | 491 ------- tests-clar/merge/workdir/trivial.c | 341 ----- tests-clar/network/cred.c | 50 - tests-clar/network/fetchlocal.c | 88 -- tests-clar/network/refspecs.c | 87 -- tests-clar/network/remote/createthenload.c | 37 - tests-clar/network/remote/isvalidname.c | 17 - tests-clar/network/remote/local.c | 234 --- tests-clar/network/remote/remotes.c | 510 ------- tests-clar/network/remote/rename.c | 174 --- tests-clar/network/urlparse.c | 193 --- tests-clar/notes/notes.c | 387 ----- tests-clar/notes/notesref.c | 64 - tests-clar/object/blob/filter.c | 143 -- tests-clar/object/blob/fromchunks.c | 119 -- tests-clar/object/blob/write.c | 69 - tests-clar/object/cache.c | 287 ---- tests-clar/object/commit/commitstagedfile.c | 132 -- tests-clar/object/lookup.c | 65 - tests-clar/object/lookupbypath.c | 83 -- tests-clar/object/message.c | 236 ---- tests-clar/object/peel.c | 105 -- tests-clar/object/raw/chars.c | 41 - tests-clar/object/raw/compare.c | 124 -- tests-clar/object/raw/convert.c | 112 -- tests-clar/object/raw/data.h | 323 ----- tests-clar/object/raw/fromstr.c | 30 - tests-clar/object/raw/hash.c | 166 --- tests-clar/object/raw/short.c | 137 -- tests-clar/object/raw/size.c | 13 - tests-clar/object/raw/type2string.c | 54 - tests-clar/object/raw/write.c | 462 ------ tests-clar/object/tag/list.c | 115 -- tests-clar/object/tag/peel.c | 61 - tests-clar/object/tag/read.c | 142 -- tests-clar/object/tag/write.c | 260 ---- tests-clar/object/tree/attributes.c | 115 -- tests-clar/object/tree/duplicateentries.c | 157 --- tests-clar/object/tree/frompath.c | 68 - tests-clar/object/tree/read.c | 75 - tests-clar/object/tree/walk.c | 177 --- tests-clar/object/tree/write.c | 262 ---- tests-clar/odb/alternates.c | 80 -- tests-clar/odb/backend/nonrefreshing.c | 274 ---- tests-clar/odb/foreach.c | 80 -- tests-clar/odb/loose.c | 146 -- tests-clar/odb/loose_data.h | 522 ------- tests-clar/odb/mixed.c | 93 -- tests-clar/odb/pack_data.h | 151 -- tests-clar/odb/pack_data_one.h | 19 - tests-clar/odb/packed.c | 79 -- tests-clar/odb/packed_one.c | 60 - tests-clar/odb/sorting.c | 69 - tests-clar/odb/streamwrite.c | 56 - tests-clar/online/clone.c | 256 ---- tests-clar/online/fetch.c | 171 --- tests-clar/online/fetchhead.c | 91 -- tests-clar/online/push.c | 770 ---------- tests-clar/online/push_util.c | 132 -- tests-clar/online/push_util.h | 71 - tests-clar/pack/indexer.c | 126 -- tests-clar/pack/packbuilder.c | 204 --- tests-clar/refs/branches/create.c | 76 - tests-clar/refs/branches/delete.c | 117 -- tests-clar/refs/branches/ishead.c | 116 -- tests-clar/refs/branches/iterator.c | 151 -- tests-clar/refs/branches/lookup.c | 45 - tests-clar/refs/branches/move.c | 146 -- tests-clar/refs/branches/name.c | 45 - tests-clar/refs/branches/remote.c | 86 -- tests-clar/refs/branches/upstream.c | 143 -- tests-clar/refs/branches/upstreamname.c | 42 - tests-clar/refs/crashes.c | 20 - tests-clar/refs/create.c | 168 --- tests-clar/refs/delete.c | 93 -- tests-clar/refs/foreachglob.c | 95 -- tests-clar/refs/isvalidname.c | 31 - tests-clar/refs/iterator.c | 97 -- tests-clar/refs/list.c | 57 - tests-clar/refs/listall.c | 47 - tests-clar/refs/lookup.c | 60 - tests-clar/refs/normalize.c | 403 ------ tests-clar/refs/overwrite.c | 136 -- tests-clar/refs/pack.c | 105 -- tests-clar/refs/peel.c | 119 -- tests-clar/refs/read.c | 284 ---- tests-clar/refs/ref_helpers.c | 25 - tests-clar/refs/ref_helpers.h | 1 - tests-clar/refs/reflog/drop.c | 115 -- tests-clar/refs/reflog/reflog.c | 209 --- tests-clar/refs/rename.c | 367 ----- tests-clar/refs/revparse.c | 813 ----------- tests-clar/refs/setter.c | 99 -- tests-clar/refs/shorthand.c | 27 - tests-clar/refs/unicode.c | 56 - tests-clar/refs/update.c | 26 - tests-clar/repo/config.c | 208 --- tests-clar/repo/discover.c | 142 -- tests-clar/repo/getters.c | 40 - tests-clar/repo/hashfile.c | 85 -- tests-clar/repo/head.c | 196 --- tests-clar/repo/headtree.c | 53 - tests-clar/repo/init.c | 606 -------- tests-clar/repo/iterator.c | 962 ------------- tests-clar/repo/message.c | 52 - tests-clar/repo/open.c | 376 ----- tests-clar/repo/pathspec.c | 385 ----- tests-clar/repo/repo_helpers.c | 22 - tests-clar/repo/repo_helpers.h | 6 - tests-clar/repo/setters.c | 107 -- tests-clar/repo/shallow.c | 33 - tests-clar/repo/state.c | 96 -- tests-clar/reset/default.c | 180 --- tests-clar/reset/hard.c | 200 --- tests-clar/reset/mixed.c | 49 - tests-clar/reset/reset_helpers.c | 10 - tests-clar/reset/reset_helpers.h | 6 - tests-clar/reset/soft.c | 157 --- tests-clar/resources/.gitattributes | 1 - tests-clar/resources/.gitignore | 1 - tests-clar/resources/attr/.gitted/HEAD | 1 - tests-clar/resources/attr/.gitted/config | 6 - tests-clar/resources/attr/.gitted/description | 1 - tests-clar/resources/attr/.gitted/index | Bin 1856 -> 0 bytes tests-clar/resources/attr/.gitted/info/attributes | 4 - tests-clar/resources/attr/.gitted/info/exclude | 6 - tests-clar/resources/attr/.gitted/logs/HEAD | 9 - .../resources/attr/.gitted/logs/refs/heads/master | 9 - .../10/8bb4e7fd7b16490dc33ff7d972151e73d7166e | Bin 130 -> 0 bytes .../16/983da6643656bb44c43965ecb6855c6d574512 | Bin 446 -> 0 bytes .../21/7878ab49e1314388ea2e32dc6fdb58a1b969e0 | 4 - .../24/fa9a9fc4e202313e24b648087495441dab432b | Bin 180 -> 0 bytes .../29/29de282ce999e95183aedac6451d3384559c4b | Bin 58 -> 0 bytes .../2b/40c5aca159b04ea8d20ffe36cdf8b09369b14a | 1 - .../2c/66e14f77196ea763fb1e41612c1aa2bc2d8ed2 | Bin 316 -> 0 bytes .../2d/e7dfe3588f3c7e9ad59e7d50ba90e3329df9d9 | Bin 124 -> 0 bytes .../37/0fe9ec224ce33e71f9e5ec2bd1142ce9937a6a | Bin 177 -> 0 bytes .../3a/6df026462ebafe455af9867d27eda20a9e0974 | Bin 84 -> 0 bytes .../3b/74db7ab381105dc0d28f8295a77f6a82989292 | Bin 276 -> 0 bytes .../3e/42ffc54a663f9401cc25843d6c0e71a33e4249 | Bin 596 -> 0 bytes .../45/141a79a77842c59a63229403220a4e4be74e3d | Bin 36 -> 0 bytes .../45/5a314fa848d52ae1f11d254da4f60858fc97f4 | Bin 446 -> 0 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 18 -> 0 bytes .../4d/713dc48e6b1bd75b0d61ad078ba9ca3a56745d | 2 - .../4e/49ba8c5b6c32ff28cd9dcb60be34df50fcc485 | Bin 81 -> 0 bytes .../55/6f8c827b8e4a02ad5cab77dca2bcb3e226b0b3 | Bin 24 -> 0 bytes .../58/19a185d77b03325aaf87cafc771db36f6ddca7 | Bin 19 -> 0 bytes .../60/5812ab7fe421fdd325a935d35cb06a9234a7d7 | 2 - .../6b/ab5c79cd5140d0f800917f550eb2a3dc32b0da | 3 - .../6d/968d62c89c7d9ea23a4c9a7b665d017c3d8ffd | Bin 422 -> 0 bytes .../71/7fc31f6b84f9d6fc3a4edbca259d7fc92beee2 | Bin 422 -> 0 bytes .../8d/0b9df9bd30be7910ddda60548d485bc302b911 | 1 - .../93/61f40bb97239cf55811892e14de2e344168ba1 | Bin 45 -> 0 bytes .../94/da4faa0a6bfb8ee6ccf7153801a69202b31857 | Bin 124 -> 0 bytes .../96/089fd31ce1d3ee2afb0ba09ba063066932f027 | Bin 422 -> 0 bytes .../99/eae476896f4907224978b88e5ecaa6c5bb67a9 | Bin 95 -> 0 bytes .../9e/5bdc47d6a80f2be0ea3049ad74231b94609242 | Bin 20 -> 0 bytes .../9f/b40b6675dde60b5697afceae91b66d908c02d9 | Bin 151 -> 0 bytes .../a0/f7217ae99f5ac3e88534f5cea267febc5fa85b | 1 - .../a5/6bbcecaeac760cc26239384d2d4c614e7e4320 | Bin 351 -> 0 bytes .../a5/d76cad53f66f1312bd995909a5bab3c0820770 | 4 - .../a9/7cc019851d401a4f1d091cb91a15890a0dd1ba | 2 - .../b4/35cd5689a0fb54afbeda4ac20368aa480e8f04 | Bin 40 -> 0 bytes .../c0/091889c0c77142b87a1fa5123a6398a61d33e7 | Bin 290 -> 0 bytes .../c4/85abe35abd4aa6fd83b076a78bbea9e2e7e06c | Bin 129 -> 0 bytes .../c7/aadd770d5907a8475c29e9ee21a27b88bf675d | Bin 60 -> 0 bytes .../c9/6bbb2c2557a8325ae1559e3ba79cdcecb23076 | 2 - .../ce/39a97a7fb1fa90bcf5e711249c1e507476ae0e | Bin 446 -> 0 bytes .../d5/7da33c16b14326ecb05d19bbea908f5e4c47d9 | Bin 379 -> 0 bytes .../d8/00886d9c86731ae5c4a62b0b77c437015e00d2 | Bin 18 -> 0 bytes .../dc/cada462d3df8ac6de596fb8c896aba9344f941 | Bin 35 -> 0 bytes .../de/863bff4976c9ed7e17a4da0fd524908dc84049 | Bin 4115 -> 0 bytes .../e5/63cf4758f0d646f1b14b76016aa17fa9e549a4 | Bin 39 -> 0 bytes .../ec/b97df2a174987475ac816e3847fc8e9f6c596b | Bin 171 -> 0 bytes .../ed/f3dcee4003d71f139777898882ccd097e34c53 | Bin 6289 -> 0 bytes .../f2/c6d717cf4a5a3e6b02684155ab07b766982165 | Bin 44 -> 0 bytes .../f5/b0af1fb4f5c0cd7aad880711d368a07333c307 | 2 - .../fb/5067b1aef3ac1ada4b379dbcb7d17255df7d78 | Bin 28 -> 0 bytes .../fe/773770c5a6cc7185580c9204b1ff18a33ff3fc | 1 - .../ff/69f8639ce2e6010b3f33a74160aad98b48da2b | Bin 18 -> 0 bytes .../resources/attr/.gitted/refs/heads/master | 1 - tests-clar/resources/attr/attr0 | 1 - tests-clar/resources/attr/attr1 | 29 - tests-clar/resources/attr/attr2 | 21 - tests-clar/resources/attr/attr3 | 4 - tests-clar/resources/attr/binfile | 1 - tests-clar/resources/attr/dir/file | 0 tests-clar/resources/attr/file | 1 - tests-clar/resources/attr/gitattributes | 29 - tests-clar/resources/attr/gitignore | 2 - tests-clar/resources/attr/ign | 1 - tests-clar/resources/attr/macro_bad | 1 - tests-clar/resources/attr/macro_test | 1 - tests-clar/resources/attr/root_test1 | 1 - tests-clar/resources/attr/root_test2 | 6 - tests-clar/resources/attr/root_test3 | 19 - tests-clar/resources/attr/root_test4.txt | 14 - tests-clar/resources/attr/sub/.gitattributes | 7 - tests-clar/resources/attr/sub/abc | 37 - tests-clar/resources/attr/sub/dir/file | 0 tests-clar/resources/attr/sub/file | 1 - tests-clar/resources/attr/sub/ign/file | 1 - tests-clar/resources/attr/sub/ign/sub/file | 1 - tests-clar/resources/attr/sub/sub/.gitattributes | 3 - tests-clar/resources/attr/sub/sub/dir | 0 tests-clar/resources/attr/sub/sub/file | 1 - tests-clar/resources/attr/sub/sub/subsub.txt | 1 - tests-clar/resources/attr/sub/subdir_test1 | 2 - tests-clar/resources/attr/sub/subdir_test2.txt | 1 - tests-clar/resources/attr_index/.gitted/HEAD | 1 - tests-clar/resources/attr_index/.gitted/config | 6 - .../resources/attr_index/.gitted/description | 1 - tests-clar/resources/attr_index/.gitted/index | Bin 520 -> 0 bytes .../resources/attr_index/.gitted/info/exclude | 6 - tests-clar/resources/attr_index/.gitted/info/refs | 1 - tests-clar/resources/attr_index/.gitted/logs/HEAD | 4 - .../attr_index/.gitted/logs/refs/heads/master | 4 - .../38/12cfef36615db1788d4e63f90028007e17a348 | 3 - .../59/d942b8be2784bc96db9b22202c10815c9a077b | 1 - .../cd/f17ea3fe625ef812f4dce7f423f4f299287505 | Bin 61 -> 0 bytes .../f7/2502ddd01412bb20796ff812af56fd53b82b52 | Bin 149 -> 0 bytes .../attr_index/.gitted/objects/info/packs | 2 - ...ck-4e6438607204ce78827e3885594b2c0bb4f13895.idx | Bin 1492 -> 0 bytes ...k-4e6438607204ce78827e3885594b2c0bb4f13895.pack | Bin 1106 -> 0 bytes .../resources/attr_index/.gitted/packed-refs | 2 - .../resources/attr_index/.gitted/refs/heads/master | 1 - tests-clar/resources/attr_index/README.md | 1 - tests-clar/resources/attr_index/README.txt | 1 - tests-clar/resources/attr_index/gitattributes | 4 - .../resources/attr_index/sub/sub/.gitattributes | 3 - tests-clar/resources/attr_index/sub/sub/README.md | 1 - tests-clar/resources/attr_index/sub/sub/README.txt | 1 - tests-clar/resources/bad_tag.git/HEAD | 1 - tests-clar/resources/bad_tag.git/config | 5 - ...ck-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.idx | Bin 1268 -> 0 bytes ...k-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.pack | Bin 596 -> 0 bytes tests-clar/resources/bad_tag.git/packed-refs | 5 - .../resources/bad_tag.git/refs/dummy-marker.txt | 0 tests-clar/resources/big.index | Bin 335272 -> 0 bytes tests-clar/resources/binaryunicode/.gitted/HEAD | 1 - tests-clar/resources/binaryunicode/.gitted/config | 6 - .../resources/binaryunicode/.gitted/description | 1 - tests-clar/resources/binaryunicode/.gitted/index | Bin 104 -> 0 bytes .../resources/binaryunicode/.gitted/info/exclude | 6 - .../resources/binaryunicode/.gitted/info/refs | 3 - .../binaryunicode/.gitted/objects/info/packs | 2 - ...ck-c5bfca875b4995d7aba6e5abf36241f3c397327d.idx | Bin 1380 -> 0 bytes ...k-c5bfca875b4995d7aba6e5abf36241f3c397327d.pack | Bin 20879 -> 0 bytes .../binaryunicode/.gitted/refs/heads/branch1 | 1 - .../binaryunicode/.gitted/refs/heads/branch2 | 1 - .../binaryunicode/.gitted/refs/heads/master | 1 - tests-clar/resources/binaryunicode/file.txt | 1 - tests-clar/resources/blametest.git/HEAD | 1 - tests-clar/resources/blametest.git/config | 5 - tests-clar/resources/blametest.git/description | 1 - .../0c/bab4d45fd61e55a1c9697f9f9cb07a12e15448 | Bin 46 -> 0 bytes .../1a/ac69ae5d96461afc4d81d0066cb12f5b05a35b | Bin 28 -> 0 bytes .../1b/5f0775af166331c854bd8d1bca3450eaf2532a | Bin 35 -> 0 bytes .../48/2f2c370e35c2c314fc1f96db2beb33f955a26a | Bin 35 -> 0 bytes .../63/d671eb32d250e4a83766ebbc60e818c1e1e93a | 3 - .../63/eb57322e363e18d460da5ea8284f3cd2340b36 | Bin 76 -> 0 bytes .../8b/137891791fe96927ad78e64b0aad7bded08bdc | Bin 16 -> 0 bytes .../96/679d59cf9f74d69b3c920f258559b5e8c9a18a | Bin 47 -> 0 bytes .../98/89d6e5557761aa8e3607e80c874a6dc51ada7c | Bin 43 -> 0 bytes .../aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 | 1 - .../b1/76dfc3a4dc8734e4c579f77236a9c8d0a965d2 | Bin 76 -> 0 bytes .../b9/0bb887b7c03750ae6b352ffe76ab9d2e86ee7d | Bin 56 -> 0 bytes .../b9/9f7ac0b88909253d829554c14af488c3b0f3a5 | 2 - .../bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 | 3 - .../cf/e0e1e1e3ba18f149fd47f5e1aef6016b2260c3 | Bin 76 -> 0 bytes .../d0/67729932057cdb7527a833d6799c4ddc520640 | 1 - .../da/237394e6132d20d30f175b9b73c8638fddddda | 4 - .../e5/b41c1ea533f87388ab69b13baf0b5a562d6243 | Bin 76 -> 0 bytes .../ef/32df4d259143933715c74951f932d9892364d1 | Bin 42 -> 0 bytes .../resources/blametest.git/refs/heads/master | 1 - tests-clar/resources/config/.gitconfig | 3 - tests-clar/resources/config/config-include | 2 - tests-clar/resources/config/config-included | 2 - tests-clar/resources/config/config0 | 7 - tests-clar/resources/config/config1 | 5 - tests-clar/resources/config/config10 | 1 - tests-clar/resources/config/config11 | 5 - tests-clar/resources/config/config12 | 7 - tests-clar/resources/config/config13 | 2 - tests-clar/resources/config/config14 | 4 - tests-clar/resources/config/config15 | 3 - tests-clar/resources/config/config16 | 3 - tests-clar/resources/config/config17 | 3 - tests-clar/resources/config/config18 | 5 - tests-clar/resources/config/config19 | 5 - tests-clar/resources/config/config2 | 5 - tests-clar/resources/config/config20 | 11 - tests-clar/resources/config/config3 | 3 - tests-clar/resources/config/config4 | 5 - tests-clar/resources/config/config5 | 9 - tests-clar/resources/config/config6 | 5 - tests-clar/resources/config/config7 | 5 - tests-clar/resources/config/config8 | 0 tests-clar/resources/config/config9 | 9 - tests-clar/resources/crlf/.gitted/HEAD | 1 - tests-clar/resources/crlf/.gitted/config | 0 .../04/de00b358f13389948756732158eaaaefa1448c | Bin 28 -> 0 bytes .../0a/a76e474d259bd7c13eb726a1396c381db55c88 | Bin 27 -> 0 bytes .../0d/06894e14df22e066763ae906e0ed3eb79c205f | Bin 134 -> 0 bytes .../0f/f5a53f19bfd2b5eea1ba550295c47515678987 | Bin 29 -> 0 bytes .../12/faf3c1ea55f572473cec9052fca468c3584ccb | 1 - .../38/1cfe630df902bc29271a202d3277981180e4a6 | Bin 25 -> 0 bytes .../79/9770d1cff46753a57db7a066159b5610da6e3a | Bin 20 -> 0 bytes .../7c/ce67e58173e2b01f7db124ceaabe3183d19c49 | Bin 24 -> 0 bytes .../a9/a2e8913c1dbe2812fac5e6b4e0a4bd5d0d5966 | 1 - .../ba/aa042ab2976f8264e467988e6112ee518ec62e | Bin 159 -> 0 bytes .../dc/88e3b917de821e25962bea7ec1f55c4ce2112c | Bin 32 -> 0 bytes .../ea/030d3c6cec212069eca698cabaa5b4550f1511 | Bin 32 -> 0 bytes .../fe/085d9ace90cc675b87df15e1aeed0c3a31407f | Bin 139 -> 0 bytes .../resources/crlf/.gitted/refs/heads/master | 1 - tests-clar/resources/crlf/.gitted/refs/heads/utf8 | 1 - tests-clar/resources/deprecated-mode.git/HEAD | 1 - tests-clar/resources/deprecated-mode.git/config | 6 - .../resources/deprecated-mode.git/description | 1 - tests-clar/resources/deprecated-mode.git/index | Bin 112 -> 0 bytes .../resources/deprecated-mode.git/info/exclude | 2 - .../06/262edc257418e9987caf999f9a7a3e1547adff | Bin 124 -> 0 bytes .../08/10fb7818088ff5ac41ee49199b51473b1bd6c7 | Bin 350 -> 0 bytes .../1b/05fdaa881ee45b48cbaa5e9b037d667a47745e | Bin 57 -> 0 bytes .../3d/0970ec547fc41ef8a5882dde99c6adce65b021 | Bin 29 -> 0 bytes .../deprecated-mode.git/refs/heads/master | 1 - tests-clar/resources/diff/.gitted/HEAD | 1 - tests-clar/resources/diff/.gitted/config | 6 - tests-clar/resources/diff/.gitted/description | 1 - tests-clar/resources/diff/.gitted/index | Bin 225 -> 0 bytes tests-clar/resources/diff/.gitted/info/exclude | 6 - tests-clar/resources/diff/.gitted/logs/HEAD | 2 - .../resources/diff/.gitted/logs/refs/heads/master | 2 - .../29/ab7053bb4dde0298e03e2c179e890b7dd465a7 | Bin 730 -> 0 bytes .../3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847 | Bin 1108 -> 0 bytes .../54/6c735f16a3b44d9784075c2c0dab2ac9bf1989 | Bin 1110 -> 0 bytes .../7a/9e0b02e63179929fed24f0a3e0f19168114d10 | Bin 160 -> 0 bytes .../7b/808f723a8ca90df319682c221187235af76693 | Bin 922 -> 0 bytes .../88/789109439c1e1c3cd45224001edee5304ed53c | 1 - .../cb/8294e696339863df760b2ff5d1e275bee72455 | Bin 86 -> 0 bytes .../d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69 | 1 - .../resources/diff/.gitted/refs/heads/master | 1 - tests-clar/resources/diff/another.txt | 38 - tests-clar/resources/diff/readme.txt | 36 - tests-clar/resources/duplicate.git/COMMIT_EDITMSG | 1 - tests-clar/resources/duplicate.git/HEAD | 1 - tests-clar/resources/duplicate.git/config | 5 - tests-clar/resources/duplicate.git/description | 1 - tests-clar/resources/duplicate.git/index | Bin 104 -> 0 bytes tests-clar/resources/duplicate.git/info/exclude | 6 - tests-clar/resources/duplicate.git/info/refs | 1 - tests-clar/resources/duplicate.git/logs/HEAD | 1 - .../resources/duplicate.git/logs/refs/heads/master | 1 - .../0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea | Bin 22 -> 0 bytes .../ce/013625030ba8dba906f756967f9e9ca394464a | Bin 21 -> 0 bytes .../resources/duplicate.git/objects/info/packs | 3 - ...ck-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx | Bin 1184 -> 0 bytes ...k-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack | Bin 249 -> 0 bytes ...ck-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx | Bin 1268 -> 0 bytes ...k-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack | Bin 369 -> 0 bytes ...ck-e87994ad581c9af946de0eb890175c08cd005f38.idx | Bin 1156 -> 0 bytes ...k-e87994ad581c9af946de0eb890175c08cd005f38.pack | Bin 213 -> 0 bytes ...ck-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx | Bin 1100 -> 0 bytes ...k-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack | Bin 47 -> 0 bytes tests-clar/resources/duplicate.git/packed-refs | 2 - .../duplicate.git/refs/heads/dummy-marker.txt | 1 - tests-clar/resources/empty_bare.git/HEAD | 1 - tests-clar/resources/empty_bare.git/config | 7 - tests-clar/resources/empty_bare.git/description | 1 - tests-clar/resources/empty_bare.git/info/exclude | 6 - .../empty_bare.git/objects/info/dummy-marker.txt | 0 .../empty_bare.git/objects/pack/dummy-marker.txt | 0 .../empty_bare.git/refs/heads/dummy-marker.txt | 0 .../empty_bare.git/refs/tags/dummy-marker.txt | 0 .../resources/empty_standard_repo/.gitted/HEAD | 1 - .../resources/empty_standard_repo/.gitted/config | 8 - .../empty_standard_repo/.gitted/description | 1 - .../empty_standard_repo/.gitted/info/exclude | 6 - .../.gitted/objects/info/dummy-marker.txt | 0 .../.gitted/objects/pack/dummy-marker.txt | 0 .../.gitted/refs/heads/dummy-marker.txt | 0 .../.gitted/refs/tags/dummy-marker.txt | 0 tests-clar/resources/filemodes/.gitted/HEAD | 1 - tests-clar/resources/filemodes/.gitted/config | 6 - tests-clar/resources/filemodes/.gitted/description | 1 - tests-clar/resources/filemodes/.gitted/index | Bin 528 -> 0 bytes .../resources/filemodes/.gitted/info/exclude | 6 - tests-clar/resources/filemodes/.gitted/logs/HEAD | 1 - .../filemodes/.gitted/logs/refs/heads/master | 1 - .../99/62c8453ba6f0cf8dac7c5dcc2fa2897fa9964a | Bin 139 -> 0 bytes .../a5/c5dd0fc6c313159a69b1d19d7f61a9f978e8f1 | Bin 21 -> 0 bytes .../e7/48d196331bcb20267eaaee4ff3326cb73b8182 | Bin 99 -> 0 bytes .../resources/filemodes/.gitted/refs/heads/master | 1 - tests-clar/resources/filemodes/exec_off | 1 - tests-clar/resources/filemodes/exec_off2on_staged | 1 - tests-clar/resources/filemodes/exec_off2on_workdir | 1 - tests-clar/resources/filemodes/exec_off_untracked | 1 - tests-clar/resources/filemodes/exec_on | 1 - tests-clar/resources/filemodes/exec_on2off_staged | 1 - tests-clar/resources/filemodes/exec_on2off_workdir | 1 - tests-clar/resources/filemodes/exec_on_untracked | 1 - tests-clar/resources/gitgit.index | Bin 134799 -> 0 bytes tests-clar/resources/icase/.gitted/HEAD | 1 - tests-clar/resources/icase/.gitted/config | 7 - tests-clar/resources/icase/.gitted/description | 1 - tests-clar/resources/icase/.gitted/index | Bin 1392 -> 0 bytes tests-clar/resources/icase/.gitted/info/exclude | 6 - tests-clar/resources/icase/.gitted/logs/HEAD | 1 - .../resources/icase/.gitted/logs/refs/heads/master | 1 - .../3e/257c57f136a1cb8f2b8e9a2e5bc8ec0258bdce | Bin 114 -> 0 bytes .../4d/d6027d083575c7431396dc2a3174afeb393c93 | Bin 61 -> 0 bytes .../62/e0af52c199ec731fe4ad230041cd3286192d49 | Bin 19 -> 0 bytes .../76/d6e1d231b1085fcce151427e9899335de74be6 | 3 - .../d4/4e18fb93b7107b5cd1b95d601591d77869a1b6 | Bin 21 -> 0 bytes .../resources/icase/.gitted/refs/heads/master | 1 - tests-clar/resources/icase/B | 1 - tests-clar/resources/icase/D | 1 - tests-clar/resources/icase/F | 1 - tests-clar/resources/icase/H | 1 - tests-clar/resources/icase/J | 1 - tests-clar/resources/icase/L/1 | 1 - tests-clar/resources/icase/L/B | 1 - tests-clar/resources/icase/L/D | 1 - tests-clar/resources/icase/L/a | 1 - tests-clar/resources/icase/L/c | 1 - tests-clar/resources/icase/a | 1 - tests-clar/resources/icase/c | 1 - tests-clar/resources/icase/e | 1 - tests-clar/resources/icase/g | 1 - tests-clar/resources/icase/i | 1 - tests-clar/resources/icase/k/1 | 1 - tests-clar/resources/icase/k/B | 1 - tests-clar/resources/icase/k/D | 1 - tests-clar/resources/icase/k/a | 1 - tests-clar/resources/icase/k/c | 1 - tests-clar/resources/issue_1397/.gitted/HEAD | 1 - tests-clar/resources/issue_1397/.gitted/config | 6 - tests-clar/resources/issue_1397/.gitted/index | Bin 233 -> 0 bytes .../7f/483a738f867e5b21c8f377d70311f011eb48b5 | 3 - .../83/12e0889a9cbab77c732b6bc39b51a683e3a318 | Bin 48 -> 0 bytes .../8a/7ef047fc933edb62e84e7977b0612ec3f6f283 | Bin 141 -> 0 bytes .../8e/8f80088a9274fd23584992f587083ca1bcbbac | Bin 63 -> 0 bytes .../f2/c62dea0372a0578e053697d5c1ba1ac05e774a | Bin 94 -> 0 bytes .../ff/3578d64d199d5b48d92bbb569e0a273e411741 | Bin 73 -> 0 bytes .../resources/issue_1397/.gitted/refs/heads/master | 1 - tests-clar/resources/issue_1397/crlf_file.txt | 3 - .../resources/issue_1397/some_other_crlf_file.txt | 3 - .../resources/issue_592/.gitted/COMMIT_EDITMSG | 1 - tests-clar/resources/issue_592/.gitted/HEAD | 1 - tests-clar/resources/issue_592/.gitted/config | 8 - tests-clar/resources/issue_592/.gitted/index | Bin 392 -> 0 bytes .../resources/issue_592/.gitted/info/exclude | 6 - tests-clar/resources/issue_592/.gitted/logs/HEAD | 2 - .../issue_592/.gitted/logs/refs/heads/master | 2 - .../06/07ee9d4ccce8e4c4fa13c2c7d727e7faba4e0e | Bin 87 -> 0 bytes .../49/363a72a90d9424240258cd3759f23788ecf1d8 | Bin 55 -> 0 bytes .../4d/383e87f0371ba8fa353f3912db6862b2625e85 | 2 - .../71/44be264b61825fbff68046fe999bdfe96a1792 | Bin 50 -> 0 bytes .../be/de83ee10b5b3f00239660b00acec2d55fd0b84 | Bin 107 -> 0 bytes .../e3/8fcc7a6060f5eb5b876e836b52ae4769363f21 | Bin 137 -> 0 bytes .../f1/adef63cb08891a0942b76fc4b9c50c6c494bc7 | Bin 29 -> 0 bytes .../resources/issue_592/.gitted/refs/heads/master | 1 - tests-clar/resources/issue_592/a.txt | 1 - tests-clar/resources/issue_592/c/a.txt | 1 - tests-clar/resources/issue_592/l.txt | 1 - tests-clar/resources/issue_592/t/a.txt | 1 - tests-clar/resources/issue_592/t/b.txt | 1 - tests-clar/resources/issue_592b/.gitted/HEAD | 1 - tests-clar/resources/issue_592b/.gitted/config | 6 - .../resources/issue_592b/.gitted/description | 1 - tests-clar/resources/issue_592b/.gitted/index | Bin 376 -> 0 bytes .../resources/issue_592b/.gitted/info/exclude | 6 - tests-clar/resources/issue_592b/.gitted/logs/HEAD | 1 - .../issue_592b/.gitted/logs/refs/heads/master | 1 - .../3f/bf1852f72fd268e36457b13a18cdd9a4c9ea35 | 2 - .../6f/a891d3e578c83e1c03bdb9e0fdd8e6e934157f | Bin 28 -> 0 bytes .../80/07d41d5794e6ce4d4d2c97e370d5a9aa6d5213 | Bin 24 -> 0 bytes .../a6/5fb6583a7c425284142f285bc359a2d6565513 | Bin 93 -> 0 bytes .../ae/be7a55922c7097ef91ca3a7bc327a901d87c2c | Bin 122 -> 0 bytes .../b3/44b055867fcdc1f01eaa75056a43e868eb4fbc | Bin 36 -> 0 bytes .../f7/d75fbfad8b1d2e307ced287ea78aad403cdce3 | Bin 57 -> 0 bytes .../resources/issue_592b/.gitted/refs/heads/master | 1 - tests-clar/resources/issue_592b/gitignore | 1 - .../issue_592b/ignored/contained/ignored3.txt | 1 - .../issue_592b/ignored/contained/tracked3.txt | 1 - .../resources/issue_592b/ignored/ignored2.txt | 1 - .../resources/issue_592b/ignored/tracked2.txt | 1 - tests-clar/resources/issue_592b/ignored1.txt | 1 - tests-clar/resources/issue_592b/tracked1.txt | 1 - .../resources/merge-resolve/.gitted/COMMIT_EDITMSG | 1 - tests-clar/resources/merge-resolve/.gitted/HEAD | 1 - .../resources/merge-resolve/.gitted/ORIG_HEAD | 1 - tests-clar/resources/merge-resolve/.gitted/config | 6 - .../resources/merge-resolve/.gitted/description | 1 - tests-clar/resources/merge-resolve/.gitted/index | Bin 624 -> 0 bytes .../resources/merge-resolve/.gitted/logs/HEAD | 236 ---- .../merge-resolve/.gitted/logs/refs/heads/branch | 2 - .../.gitted/logs/refs/heads/df_ancestor | 5 - .../merge-resolve/.gitted/logs/refs/heads/df_side1 | 14 - .../merge-resolve/.gitted/logs/refs/heads/df_side2 | 9 - .../.gitted/logs/refs/heads/ff_branch | 5 - .../merge-resolve/.gitted/logs/refs/heads/master | 5 - .../merge-resolve/.gitted/logs/refs/heads/octo1 | 2 - .../merge-resolve/.gitted/logs/refs/heads/octo2 | 2 - .../merge-resolve/.gitted/logs/refs/heads/octo3 | 2 - .../merge-resolve/.gitted/logs/refs/heads/octo4 | 2 - .../merge-resolve/.gitted/logs/refs/heads/octo5 | 2 - .../merge-resolve/.gitted/logs/refs/heads/octo6 | 3 - .../merge-resolve/.gitted/logs/refs/heads/renames1 | 2 - .../merge-resolve/.gitted/logs/refs/heads/renames2 | 3 - .../.gitted/logs/refs/heads/trivial-10 | 3 - .../.gitted/logs/refs/heads/trivial-10-branch | 2 - .../.gitted/logs/refs/heads/trivial-11 | 3 - .../.gitted/logs/refs/heads/trivial-11-branch | 2 - .../.gitted/logs/refs/heads/trivial-13 | 3 - .../.gitted/logs/refs/heads/trivial-13-branch | 2 - .../.gitted/logs/refs/heads/trivial-14 | 3 - .../.gitted/logs/refs/heads/trivial-14-branch | 2 - .../.gitted/logs/refs/heads/trivial-2alt | 2 - .../.gitted/logs/refs/heads/trivial-2alt-branch | 2 - .../.gitted/logs/refs/heads/trivial-3alt | 3 - .../.gitted/logs/refs/heads/trivial-3alt-branch | 1 - .../.gitted/logs/refs/heads/trivial-4 | 2 - .../.gitted/logs/refs/heads/trivial-4-branch | 2 - .../.gitted/logs/refs/heads/trivial-5alt-1 | 2 - .../.gitted/logs/refs/heads/trivial-5alt-1-branch | 2 - .../.gitted/logs/refs/heads/trivial-5alt-2 | 3 - .../.gitted/logs/refs/heads/trivial-5alt-2-branch | 2 - .../.gitted/logs/refs/heads/trivial-6 | 3 - .../.gitted/logs/refs/heads/trivial-6-branch | 2 - .../.gitted/logs/refs/heads/trivial-7 | 3 - .../.gitted/logs/refs/heads/trivial-7-branch | 5 - .../.gitted/logs/refs/heads/trivial-8 | 3 - .../.gitted/logs/refs/heads/trivial-8-branch | 2 - .../.gitted/logs/refs/heads/trivial-9 | 3 - .../.gitted/logs/refs/heads/trivial-9-branch | 2 - .../.gitted/logs/refs/heads/unrelated | 1 - .../00/5b6fcc8fec71d2550bef8462d169b3c26aa14b | Bin 168 -> 0 bytes .../00/9b9cab6fdac02915a88ecd078b7a792ed802d8 | Bin 164 -> 0 bytes .../00/c7d33f1ffa79d19c2272b370fcaeaadba49c08 | Bin 147 -> 0 bytes .../01/f149e1b8f84bd8896aaff6d6b22af88459ded0 | Bin 166 -> 0 bytes .../02/04a84f822acbf6386b36d33f1f6bc68bbbf858 | Bin 168 -> 0 bytes .../02/251f990ca8e92e7ae61d3426163fa821c64001 | Bin 264 -> 0 bytes .../03/21415405cb906c46869919af56d51dbbe5e85c | Bin 271 -> 0 bytes .../03/2ebc5ab85d9553bb187d3cd40875ff23a63ed0 | Bin 29 -> 0 bytes .../03/b87706555accbf874ccd410dbda01e8e70a67f | Bin 353 -> 0 bytes .../03/dad1005e5d06d418f50b12e0bcd48ff2306a03 | Bin 264 -> 0 bytes .../05/1ffd7901a442faf56b226161649074f15c7c47 | 1 - .../05/8541fc37114bfc1dddf6bd6bffc7fae5c2e6fe | Bin 63 -> 0 bytes .../05/f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c | Bin 170 -> 0 bytes .../07/a759da919f737221791d542f176ab49c88837f | Bin 165 -> 0 bytes .../07/c514b04698e068892b31c8d352b85813b99c6e | Bin 32 -> 0 bytes .../09/055301463b7f2f8ee5d368f8ed5c0a40ad8515 | Bin 41 -> 0 bytes .../09/17bb159596aea4d295f4857da77e8f96b3c7dc | Bin 36 -> 0 bytes .../09/2ce8682d7f3a2a3a769a6daca58950168ba5c4 | Bin 163 -> 0 bytes .../09/3bebf072dd4bbba88833667d6ffe454df199e1 | Bin 266 -> 0 bytes .../09/768bed22680cdb0859683fa9677ccc8d5a25c1 | Bin 275 -> 0 bytes .../0a/75d9aac1dc84fb5aa51f7325c0ab53242ddef7 | Bin 275 -> 0 bytes .../0c/fd6c54ef6532d862408f562309dc9c74a401e8 | Bin 28 -> 0 bytes .../0d/52e3a556e189ba0948ae56780918011c1b167d | Bin 235 -> 0 bytes .../0d/872f8e871a30208305978ecbf9e66d864f1638 | Bin 89 -> 0 bytes .../0e/c5f433959cd46177f745903353efb5be08d151 | Bin 165 -> 0 bytes .../11/deab00b2d3a6f5a3073988ac050c2d7b6655e2 | Bin 34 -> 0 bytes .../11/f4f3c08b737f5fd896cbefa1425ee63b21b2fa | 1 - .../13/d1be4ea52a6ced1d7a1d832f0ee3c399348e5e | Bin 168 -> 0 bytes .../14/39088f509b79b1535b64193137d3ce4b240734 | Bin 58 -> 0 bytes .../15/8dc7bedb202f5b26502bf3574faa7f4238d56c | 2 - .../16/f825815cfd20a07a75c71554e82d8eede0b061 | 1 - .../17/8940b450f238a56c0d75b7955cb57b38191982 | Bin 65 -> 0 bytes .../18/3310e30fb1499af8c619108ffea4d300b5e778 | Bin 170 -> 0 bytes .../18/cb316b1cefa0f8a6946f0e201a8e1a6f845ab9 | Bin 68 -> 0 bytes .../19/b7ac485269b672a101060894de3ba9c2a24dd1 | Bin 53 -> 0 bytes .../1a/010b1c0f081b2e8901d55307a15c29ff30af0e | Bin 19 -> 0 bytes .../1c/ff9ec6a47a537380dedfdd17c9e76d74259a2b | Bin 33 -> 0 bytes .../1e/4ff029aee68d0d69ef9eb6efa6cbf1ec732f99 | Bin 29 -> 0 bytes .../1f/81433e3161efbf250576c58fede7f6b836f3d3 | Bin 262 -> 0 bytes .../20/91d94c8bd3eb0835dc5220de5e8bb310fa1513 | Bin 271 -> 0 bytes .../21/671e290278286fb2ce4c63d01699b67adce331 | Bin 79 -> 0 bytes .../22/7792b52aaa0b238bea00ec7e509b02623f168c | Bin 102 -> 0 bytes .../23/3c0919c998ed110a4b6ff36f353aec8b713487 | Bin 43 -> 0 bytes .../23/92a2dacc9efb562b8635d6579fb458751c7c5b | Bin 142 -> 0 bytes .../24/1a1005cd9b980732741b74385b891142bcba28 | Bin 67 -> 0 bytes .../24/2591eb280ee9eeb2ce63524b9a8b9bc4cb515d | Bin 30 -> 0 bytes .../24/90b9f1a079420870027deefb49f51d6656cf74 | Bin 268 -> 0 bytes .../25/9d08ca43af9200e9ea9a098e44a5a350ebd9b3 | Bin 381 -> 0 bytes .../25/c40b7660c08c8fb581f770312f41b9b03119d1 | Bin 31 -> 0 bytes .../26/153a3ff3649b6c2bb652d3f06878c6e0a172f9 | Bin 48 -> 0 bytes .../27/133da702ba3c60af2a01e96c2555ff4045d692 | Bin 32 -> 0 bytes .../2b/0de5dc27505dcdd83a75c8bf1fcd9462cd7add | Bin 147 -> 0 bytes .../2b/5f1f181ee3b58ea751f5dd5d8f9b445520a136 | Bin 53 -> 0 bytes .../2b/d0a343aeef7a2cf0d158478966a6e587ff3863 | Bin 56 -> 0 bytes .../2d/a538570bc1e5b2c3e855bf702f35248ad0735f | 2 - .../2f/2e37b7ebbae467978610896ca3aafcdad2ee67 | Bin 52 -> 0 bytes .../2f/4024ce528d36d8670c289cce5a7963e625bb0c | Bin 179 -> 0 bytes .../2f/56120107d680129a5d9791b521cb1e73a2ed31 | 3 - .../2f/598248eeccfc27e5ca44d9d96383f6dfea7b16 | 1 - .../31/68dca1a561889b045a6441909f4c56145e666d | 2 - .../31/d5472536041a83d986829240bbbdc897c6f8a6 | Bin 41 -> 0 bytes .../32/21dd512b7e2dc4b5bd03046df6c81b2ab2070b | Bin 47 -> 0 bytes .../33/46d64325b39e5323733492cd55f808994a2475 | Bin 33 -> 0 bytes .../33/d500f588fbbe65901d82b4e6b008e549064be0 | 2 - .../34/bfafff88eaf118402b44e6f3e2dbbf1a582b05 | 1 - .../35/0c6eb3010efc403a6bed682332635314e9ed58 | Bin 92 -> 0 bytes .../35/411bfb77cd2cc431f3a03a2b4976ed94b5d241 | Bin 31 -> 0 bytes .../35/4704d3613ad4228e4786fc76656b11e98236c4 | Bin 41 -> 0 bytes .../35/632e43612c06a3ea924bfbacd48333da874c29 | 1 - .../35/75826c96a975031d2c14368529cc5c4353a8fd | Bin 163 -> 0 bytes .../36/219b49367146cb2e6a1555b5a9ebd4d0328495 | Bin 68 -> 0 bytes .../36/4bbe4ce80c7bd31e6307dce77d46e3e1759fb3 | Bin 35 -> 0 bytes .../37/48859b001c6e627e712a07951aee40afd19b41 | Bin 41 -> 0 bytes .../38/5c8a0f26ddf79e9041e15e17dc352ed2c4cced | 2 - .../3b/47b031b3e55ae11e14a05260b1c3ffd6838d55 | Bin 161 -> 0 bytes .../3b/bf0bf59b20df5d5fc58b9fc1dc07be637c301f | Bin 269 -> 0 bytes .../3e/f4d30382ca33fdeba9fda895a99e0891ba37aa | Bin 36 -> 0 bytes .../3e/f9bfe82f9635518ae89152322f3b46fd4ba25b | Bin 172 -> 0 bytes .../40/2784a46a4a3982294231594cbeb431f506d22c | Bin 83 -> 0 bytes .../41/2b32fb66137366147f1801ecc962452757d48a | 2 - .../43/aafd43bea779ec74317dc361f45ae3f532a505 | Bin 37 -> 0 bytes .../43/c338656342227a3a3cd3aa85cbf784061f5425 | Bin 266 -> 0 bytes .../45/299c1ca5e07bba1fd90843056fb559f96b1f5a | Bin 58 -> 0 bytes .../46/6daf8552b891e5c22bc58c9d7fc1a2eb8f0289 | Bin 382 -> 0 bytes .../47/6dbb3e207313d1d8aaa120c6ad204bf1295e53 | Bin 522 -> 0 bytes .../47/8172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 | Bin 165 -> 0 bytes .../49/130a28ef567af9a6a6104c38773fedfa5f9742 | Bin 37 -> 0 bytes .../49/9df817155e4bdd3c6ee192a72c52f481818230 | Bin 35 -> 0 bytes .../4a/9550ebcc97ce22b22f45af7b829bb030d003f5 | Bin 53 -> 0 bytes .../4b/253da36a0ae8bfce63aeabd8c5b58429925594 | 2 - .../4b/48deed3a433909bfd6b6ab3d4b91348b6af464 | Bin 24 -> 0 bytes .../4b/825dc642cb6eb9a060e54bf8d69288fbee4904 | Bin 15 -> 0 bytes .../4c/9fac0707f8d4195037ae5a681aa48626491541 | Bin 167 -> 0 bytes .../4c/a408a8c88655f7586a1b580be6fad138121e98 | Bin 159 -> 0 bytes .../4e/0d9401aee78eb345a8685a859d37c8c3c0bbed | Bin 262 -> 0 bytes .../4e/886e602529caa9ab11d71f86634bd1b6e0de10 | Bin 56 -> 0 bytes .../4e/b04c9e79e88f6640d01ff5b25ca2a60764f216 | Bin 34 -> 0 bytes .../4f/e93c0ec83eb6305cbace3dace88ecee1b63cb6 | Bin 161 -> 0 bytes .../50/12fd565b1393bdfda1805d4ec38ce6619e1fd1 | Bin 29 -> 0 bytes .../50/4f75ac95a71ef98051817618576a68505b92f9 | Bin 93 -> 0 bytes .../50/84fc2a88b6bdba8db93bd3953a8f4fdb470238 | Bin 53 -> 0 bytes .../50/ce7d7d01217679e26c55939eef119e0c93e272 | Bin 159 -> 0 bytes .../51/95a1b480f66691b667f10a9e41e70115a78351 | Bin 170 -> 0 bytes .../52/d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 | 3 - .../53/825f41ac8d640612f9423a2f03a69f3d96809a | Bin 164 -> 0 bytes .../54/269b3f6ec3d7d4ede24dd350dd5d605495c3ae | 2 - .../54/59c89aa0026d543ce8343bd89871bce543f9c2 | 3 - .../54/7607c690372fe81fab8e3bb44c530e129118fd | Bin 58 -> 0 bytes .../55/b4e4687e7a0d9ca367016ed930f385d4022e6f | 1 - .../56/6ab53c220a2eafc1212af1a024513230280ab9 | 3 - .../56/a638b76b75e068590ac999c2f8621e7f3e264c | 1 - .../57/079a46233ae2b6df62e9ade71c4948512abefb | Bin 168 -> 0 bytes .../58/43febcb23480df0b5edb22a21c59c772bb8e29 | Bin 71 -> 0 bytes .../58/e853f66699fd02629fd50bde08082bc005933a | Bin 160 -> 0 bytes .../59/6803b523203a4851c824c07366906f8353f4ad | Bin 163 -> 0 bytes .../5c/2411f8075f48a6b2fdb85ebc0d371747c4df15 | Bin 37 -> 0 bytes .../5c/341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d | Bin 37 -> 0 bytes .../5c/3b68a71fc4fa5d362fd3875e53137c6a5ab7a5 | Bin 40 -> 0 bytes .../5d/c1018e90b19654bee986b7a0c268804d39659d | Bin 168 -> 0 bytes .../5d/dd0fe66f990dc0e5cf9fec6d9b465240e9537f | Bin 43 -> 0 bytes .../5e/b7bb6a146eb3c7fd3990b240a2308eceb1cf8d | Bin 268 -> 0 bytes .../5f/bfbdc04b4eca46f54f4853a3c5a1dce28f5165 | Bin 283 -> 0 bytes .../60/91fc2c036a382a69489e3f518ee5aae9a4e567 | Bin 258 -> 0 bytes .../61/340eeed7340fa6a8792def9a5938bb5d4434bb | Bin 92 -> 0 bytes .../61/78885b38fe96e825ac0f492c0a941f288b37f6 | Bin 289 -> 0 bytes .../62/12c31dab5e482247d7977e4f0dd3601decf13b | Bin 45 -> 0 bytes .../62/269111c3b02a9355badcb9da8678b1bf41787b | Bin 269 -> 0 bytes .../62/c4f6533c9a3894191fdcb96a3be935ade63f1a | Bin 53 -> 0 bytes .../63/247125386de9ec90a27ad36169307bf8a11a38 | 1 - .../67/18a45909532d1fcf5600d0877f7fe7e78f0b86 | 1 - .../68/c6c84b091926c7d90aa6a79b2bc3bb6adccd8e | Bin 55 -> 0 bytes .../69/f570c57b24ea7c086e94c5e574964798321435 | Bin 266 -> 0 bytes .../6a/e1a3967031a42cf955d9d5c2395211ac82f6cf | Bin 272 -> 0 bytes .../6b/7e37be8ce0b897093f2878a9dcd8f396beda2c | Bin 53 -> 0 bytes .../6c/06dcd163587c2cc18be44857e0b71116382aeb | Bin 30 -> 0 bytes .../6f/32739c3724d1d5f855299309f388606f407468 | Bin 630 -> 0 bytes .../6f/a33014764bf1120a454eb8437ae098238e409b | Bin 168 -> 0 bytes .../6f/be9fb85c86d7d1435f728da418bdff52c640a9 | Bin 83 -> 0 bytes .../71/17467b18605a660ebe5586df69e2311ed5609f | Bin 265 -> 0 bytes .../71/2ebba6669ea847d9829e4f1059d6c830c8b531 | Bin 152 -> 0 bytes .../71/add2d7b93d55bf3600f8a1582beceebbd050c8 | Bin 264 -> 0 bytes .../72/ea499e108df5ff0a4a913e7655bbeeb1fb69f2 | Bin 26 -> 0 bytes .../74/df13f0793afdaa972150bba976f7de8284914e | Bin 26 -> 0 bytes .../75/a811bf6bc57694adb3fe604786f3a4efd1cd1b | 2 - .../76/63fce0130db092936b137cabd693ec234eb060 | Bin 49 -> 0 bytes .../76/ab0e2868197ec158ddd6c78d8a0d2fd73d38f9 | Bin 37 -> 0 bytes .../7a/a3edf2bcfee22398e6b55295aa56366b7aaf76 | Bin 271 -> 0 bytes .../7c/2c5228c9e90170d4a35e6558e47163daf092e5 | Bin 172 -> 0 bytes .../7c/b63eed597130ba4abb87b3e544b85021905520 | 3 - .../7e/2d058d5fedf8329db44db4fac610d6b1a89159 | Bin 165 -> 0 bytes .../7f/7a2da58126226986d71c6ddfab4afba693280d | Bin 199 -> 0 bytes .../80/a8fbb3abb1ba423d554e9630b8fc2e5698f86b | Bin 168 -> 0 bytes .../81/87117062b750eed4f93fd7e899f17b52ce554d | Bin 170 -> 0 bytes .../83/07d93a155903a5c49576583f0ce1f6ff897c0e | Bin 30 -> 0 bytes .../83/824a8c6658768e2013905219cc8c64cc3d9a2e | Bin 382 -> 0 bytes .../84/9619b03ae540acee4d1edec96b86993da6b497 | 3 - .../84/de84f8f3a6d63e636ee9ad81f4b80512fa9bbe | Bin 41 -> 0 bytes .../86/088dae8bade454995b21a1c88107b0e1accdab | Bin 47 -> 0 bytes .../87/b4926260d77a3b851e71ecce06839bd650b231 | Bin 43 -> 0 bytes .../88/e185910a15cd13bdf44854ad037f4842b03b29 | Bin 177 -> 0 bytes .../8a/ad9d0ea334951da47b621a475b39cc6ed759bf | Bin 51 -> 0 bytes .../8a/ae714f7d939309d7f132b30646d96743134a9f | 1 - .../8b/095d8fd01594f4d14454d073e3ac57b9ce485f | Bin 201 -> 0 bytes .../8b/5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a | 1 - .../8b/fb012a6d809e499bd8d3e194a3929bc8995b93 | Bin 34 -> 0 bytes .../8c/749d9968d4b10dcfb06c9f97d0e5d92d337071 | 2 - .../8f/4433f8593ddd65b7dd43dd4564d841f4d9c8aa | Bin 164 -> 0 bytes .../90/a336c7dacbe295159413559b0043b8bdc60d57 | Bin 271 -> 0 bytes .../91/2b2d7819cf9c1029e414883857ed61d597a1a5 | Bin 295 -> 0 bytes .../91/8bb3e09090a9995d48af9a2a6296d7e6088d1c | Bin 38 -> 0 bytes .../92/7d4943cdbdc9a667db8e62cfd0a41870235c51 | Bin 535 -> 0 bytes .../93/77fccdb210540b8c0520cc6e80eb632c20bd25 | Bin 53 -> 0 bytes .../94/4f5dd1a867cab4c2bbcb896493435cae1dcc1a | 2 - .../94/8ba6e701c1edab0c2d394fb7c5538334129793 | Bin 71 -> 0 bytes .../95/646149ab6b6ba6edc83cff678582538b457b2b | 3 - .../95/9de65e568274120fdf9e3af9f77b1550122149 | Bin 40 -> 0 bytes .../96/8ca794a4597f7f6abbb2b8d940b4078a0f3fd4 | Bin 53 -> 0 bytes .../97/7c696519c5a3004c5f1d15d60c89dbeb8f235f | Bin 160 -> 0 bytes .../98/ba4205fcf31f5dd93c916d35fe3f3b3d0e6714 | 1 - .../98/d52d07c0b0bbf2b46548f6aa521295c2cb55db | 3 - .../99/b4f7e4f24470fa06b980bc21f1095c2a9425c0 | Bin 164 -> 0 bytes .../9a/301fbe6fada7dcb74fcd7c20269b5c743459a7 | Bin 163 -> 0 bytes .../9a/f731fa116d1eb9a6c0109562472cfee6f5a979 | Bin 48 -> 0 bytes .../9c/0b6c34ef379a42d858f03fef38630f476b9102 | Bin 38 -> 0 bytes .../9e/7f4359c469f309b6057febf4c6e80742cbed5b | Bin 539 -> 0 bytes .../9e/fe7723802d4305142eee177e018fee1572c4f4 | Bin 36 -> 0 bytes .../9f/74397a3397b3585faf09e9926b110d7f654254 | Bin 621 -> 0 bytes .../a0/31a28ae70e33a641ce4b8a8f6317f1ab79dee4 | Bin 37 -> 0 bytes .../a3/9a620dae5bc8b4e771cd4d251b7d080401a21e | Bin 29 -> 0 bytes .../a3/fabece9eb8748da810e1e08266fef9b7136ad4 | Bin 164 -> 0 bytes .../a4/1b1bb6d0be3c22fb654234c33b428e15c8cc27 | Bin 92 -> 0 bytes .../a4/3150a738849c59376cf30bb2a68348a83c8f48 | Bin 162 -> 0 bytes .../a5/563304ddf6caba25cb50323a2ea6f7dbfcadca | Bin 48 -> 0 bytes .../a7/08b253bd507417ec42d1467a7fd2d7519c4956 | Bin 40 -> 0 bytes .../a7/65fb87eb2f7a1920b73b2d5a057f8f8476a42b | Bin 170 -> 0 bytes .../a7/7a56a49f8f3ae242e02717f18ebbc60c5cc543 | Bin 65 -> 0 bytes .../a7/dbfcbfc1a60709cb80b5ca24539008456531d0 | 1 - .../a8/02e06f1782a9645b9851bc7202cee74a8a4972 | Bin 172 -> 0 bytes .../a8/87dd39ad3edd610fc9083dcb61e40ab50673d1 | 1 - .../a9/0bc3fb6f15181972a2959a921429efbd81a473 | 2 - .../ab/40af3cb8a3ed2e2843e96d9aa7871336b94573 | Bin 161 -> 0 bytes .../ab/6c44a2e84492ad4b41bb6bac87353e9d02ac8b | Bin 33 -> 0 bytes .../ab/929391ac42572f92110f3deeb4f0844a951e22 | Bin 40 -> 0 bytes .../ac/4045f965119e6998f4340ed0f411decfb3ec05 | Bin 29 -> 0 bytes .../ad/a14492498136771f69dd451866cabcb0e9ef9a | Bin 39 -> 0 bytes .../ad/a55a45d14527dc3dfc714ea1c65d2e1e6fbe87 | 1 - .../b2/d399ae15224e1d58066e3c8df70ce37de7a656 | 2 - .../b4/2712cfe99a1a500b2a51fe984e0b8a7702ba11 | 5 - .../b6/9fe837e4cecfd4c9a40cdca7c138468687df07 | 2 - .../b6/f610aef53bd343e6c96227de874c66f00ee8e8 | Bin 162 -> 0 bytes .../b7/a2576f9fc20024ac9ef17cb134acbd1ac73127 | Bin 320 -> 0 bytes .../b8/a3a806d3950e8c0a03a34f234a92eff0e2c68d | Bin 286 -> 0 bytes .../ba/cac9b3493509aa15e1730e1545fc0919d1dae0 | Bin 29 -> 0 bytes .../bc/744705e1d8a019993cf88f62bc4020f1b80919 | 2 - .../bc/95c75d59386147d1e79a87c33068d8dbfd71f2 | Bin 348 -> 0 bytes .../bd/593285fc7fe4ca18ccdbabf027f5d689101452 | Bin 159 -> 0 bytes .../bd/867fbae2faa80b920b002b80b1c91bcade7784 | Bin 48 -> 0 bytes .../bd/9cb4cd0a770cb9adcb5fce212142ef40ea1c35 | Bin 51 -> 0 bytes .../be/f6e37b3ee632ba74159168836f382fed21d77d | 2 - .../c0/6a9be584ac49aa02c5551312d9e2982c91df10 | Bin 348 -> 0 bytes .../c1/b17981db0840109a820dae8674ee29684134ff | Bin 348 -> 0 bytes .../c1/b6a51bbb87c2f82b161412c3d20b59fc69b090 | Bin 47 -> 0 bytes .../c3/5dee9bcc0e989f3b0c40f68372a9a51b6c4e6a | Bin 162 -> 0 bytes .../c3/d02eeef75183df7584d8d13ac03053910c1301 | Bin 67 -> 0 bytes .../c4/efe31e9decccc8b2b4d3df9aac2cdfe2995618 | Bin 538 -> 0 bytes .../c5/0d0f1cb60b8b0fe1615ad20ace557e9d68d7bd | 1 - .../c5/bbe550b9f09444bdddd3ecf3d97c0b42aa786c | Bin 269 -> 0 bytes .../c6/07fc30883e335def28cd686b51f6cfa02b06ec | 2 - .../c6/92ecf62007c0ac9fb26e2aa884de2933de15ed | Bin 40 -> 0 bytes .../c8/f06f2e3bb2964174677e91f0abead0e43c9e5d | Bin 45 -> 0 bytes .../c9/174cef549ec94ecbc43ef03cdc775b4950becb | 2 - .../c9/4b27e41064c521120627e07e2035cca1d24ffa | Bin 162 -> 0 bytes .../ca/b2cf23998b40f1af2d9d9a756dc9e285a8df4b | Bin 40 -> 0 bytes .../cb/491780d82e46dc88a065b965ab307a038f2bc2 | Bin 163 -> 0 bytes .../cb/6693a788715b82440a54e0eacd19ba9f6ec559 | Bin 41 -> 0 bytes .../cc/3e3009134cb88014129fc8858d1101359e5e2f | 2 - .../ce/8860d49e3bea6fd745874a01b7c3e46da8cbc3 | Bin 48 -> 0 bytes .../ce/e656c392ad0557b3aae0fb411475c206e2926f | Bin 32 -> 0 bytes .../cf/8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d | Bin 29 -> 0 bytes .../d0/7ec190c306ec690bac349e87d01c4358e49bb2 | 2 - .../d0/d4594e16f2e19107e3fa7ea63e7aaaff305ffb | Bin 51 -> 0 bytes .../d2/f8637f2eab2507a1e13cbc9df4729ec386627e | Bin 268 -> 0 bytes .../d3/719a5ae8e4d92276b5313ce976f6ee5af2b436 | 2 - .../d3/7aa3bbfe1c0c49b909781251b956dbabe85f96 | Bin 80 -> 0 bytes .../d3/7ad72a2052685fc6201c2af90103ad42d2079b | Bin 233 -> 0 bytes .../d4/207f77243500bec335ab477f9227fcdb1e271a | 2 - .../d4/27e0b2e138501a3d15cc376077a3631e15bd46 | Bin 38 -> 0 bytes .../d5/093787ef302b941b6aab081b99fb4880038bd8 | Bin 30 -> 0 bytes .../d5/a61b0b4992a4f0caa887fa08b52431e727bb6f | Bin 81 -> 0 bytes .../d5/b6fc965c926a1bfc9ee456042b94088b5c5d21 | Bin 319 -> 0 bytes .../d5/ec1152fe25e9fec00189eb00b3db71db24c218 | Bin 24 -> 0 bytes .../d6/42b9770c66bba94a08df09b5efb095001f76d7 | Bin 539 -> 0 bytes .../d6/462fa3f5292857db599c54aea2bf91616230c5 | Bin 48 -> 0 bytes .../d6/cf6c7741b3316826af1314042550c97ded1d50 | 2 - .../d8/74671ef5b20184836cb983bb273e5280384d0b | Bin 162 -> 0 bytes .../d8/fa77b6833082c1ea36b7828a582d4c43882450 | 1 - .../d9/63979c237d08b6ba39062ee7bf64c7d34a27f8 | Bin 48 -> 0 bytes .../da/178208145ef585a1bd5ca5f4c9785d738df2cf | Bin 41 -> 0 bytes .../db/6261a7c65c7fd678520c9bb6f2c47582ab9ed5 | Bin 624 -> 0 bytes .../dd/9a570c3400e6e07bc4d7651d6e20b08926b3d9 | Bin 36 -> 0 bytes .../de/872ee3618b894992e9d1e18ba2ebe256a112f9 | 1 - .../df/e3f22baa1f6fce5447901c3086bae368de6bdd | Bin 40 -> 0 bytes .../e0/67f9361140f19391472df8a82d6610813c73b7 | Bin 53 -> 0 bytes .../e1/129b3cfb5898e0fbd606e0cb80b2755e50d161 | Bin 92 -> 0 bytes .../e1/7ace1492648c9dc5701bad5c47af9d1b60c4e9 | Bin 264 -> 0 bytes .../e2/c6abbd55fed5ac71a5f2751e29b4a34726a595 | 1 - .../e3/1e7ad3ed298f24e383c4950f4671993ec078e4 | Bin 210 -> 0 bytes .../e3/76fbdd06ebf021c92724da9f26f44212734e3e | 3 - .../e4/9f917b448d1340b31d76e54ba388268fd4c922 | Bin 36 -> 0 bytes .../e4/f618a2c3ed0669308735727df5ebf2447f022f | 2 - .../e6/5a9bb2af9f4c2d1c375dd0f8f8a46cf9c68812 | Bin 160 -> 0 bytes .../e8/107f24196736b870a318a0e28f048e29f6feff | 3 - .../e9/2cdb7017dc6c5aed25cb4202c5b0104b872246 | Bin 48 -> 0 bytes .../e9/ad6ec3e38364a3d07feda7c4197d4d845c53b5 | Bin 36 -> 0 bytes .../e9/f48beccc62d535739bfbdebe0a55ed716d8366 | Bin 382 -> 0 bytes .../eb/c09d0137cfb0c26697aed0109fb943ad906f3f | Bin 166 -> 0 bytes .../ec/67e5a86adff465359f1c8f995e12dbdfa08d8a | Bin 166 -> 0 bytes .../ed/9523e62e453e50dd9be1606af19399b96e397a | Bin 87 -> 0 bytes .../ee/1d6f164893c1866a323f072eeed36b855656be | Bin 291 -> 0 bytes .../ee/3fa1b8c00aff7fe02065fdb50864bb0d932ccf | Bin 64 -> 0 bytes .../ee/a9286df54245fea72c5b557291470eb825f38f | Bin 235 -> 0 bytes .../ef/58fdd8086c243bdc81f99e379acacfd21d32d6 | 2 - .../ef/c499524cf105d5264ac7fc54e07e95764e8075 | Bin 32 -> 0 bytes .../ef/c9121fdedaf08ba180b53ebfbcf71bd488ed09 | Bin 160 -> 0 bytes .../f0/053b8060bb3f0be5cbcc3147a07ece26bf097e | Bin 163 -> 0 bytes .../f0/ce2b8e4986084d9b308fb72709e414c23eb5e6 | Bin 125 -> 0 bytes .../f2/0c9063fa0bda9a397c96947a7b687305c49753 | Bin 29 -> 0 bytes .../f2/9e7fb590551095230c6149cbe72f2e9104a796 | Bin 41 -> 0 bytes .../f3/293571dcd708b6a3faf03818cd2844d000e198 | 1 - .../f3/f1164b68b57b1995b658a828320e6df3081fae | Bin 310 -> 0 bytes .../f4/15caf3fcad16304cb424b67f0ee6b12dc03aae | Bin 320 -> 0 bytes .../f4/8097eb340dc5a7cae55aabcf1faf4548aa821f | Bin 165 -> 0 bytes .../f5/504f36e6f4eb797a56fc5bac6c6c7f32969bf2 | Bin 42 -> 0 bytes .../f5/b50c85a87cac64d7eb3254cdd1aec9564c0293 | Bin 35 -> 0 bytes .../f5/f9dd5886a6ee20272be0aafc790cba43b31931 | Bin 244 -> 0 bytes .../f6/be049e284c0f9dcbbc745543885be3502ea521 | Bin 265 -> 0 bytes .../f7/c332bd4d4d4b777366cae4d24d1687477576bf | Bin 156 -> 0 bytes .../f8/958bdf4d365a84a9a178b1f5f35ff1dacbd884 | 2 - .../fa/c03f2c5139618d87d53614c153823bf1f31396 | Bin 76 -> 0 bytes .../fa/da9356aa3f74622327a3038ae9c6f92e1c5c1d | Bin 168 -> 0 bytes .../fb/738a106cfd097a4acb96ce132ecb1ad6c46b03 | Bin 264 -> 0 bytes .../fc/4c636d6515e9e261f9260dbcf3cc6eca97ea08 | Bin 29 -> 0 bytes .../fc/7d7b805f7a9428574f4f802b2e34cd20ab9d99 | Bin 575 -> 0 bytes .../fc/90237dc4891fa6c69827fc465632225e391618 | Bin 163 -> 0 bytes .../fd/57d2d6770fad8e9959124793a17f441b571e66 | Bin 279 -> 0 bytes .../fd/89f8cffb663ac89095a0f9764902e93ceaca6a | 2 - .../fe/5407fc50a53aecb41d1a6e9ea7b612e581af87 | Bin 48 -> 0 bytes .../ff/49d07869831ad761bbdaea026086f8789bcb00 | Bin 24 -> 0 bytes .../ff/b312248d607284c290023f9502eea010d34efd | Bin 68 -> 0 bytes .../merge-resolve/.gitted/refs/heads/branch | 1 - .../merge-resolve/.gitted/refs/heads/df_ancestor | 1 - .../merge-resolve/.gitted/refs/heads/df_side1 | 1 - .../merge-resolve/.gitted/refs/heads/df_side2 | 1 - .../merge-resolve/.gitted/refs/heads/ff_branch | 1 - .../merge-resolve/.gitted/refs/heads/master | 1 - .../merge-resolve/.gitted/refs/heads/octo1 | 1 - .../merge-resolve/.gitted/refs/heads/octo2 | 1 - .../merge-resolve/.gitted/refs/heads/octo3 | 1 - .../merge-resolve/.gitted/refs/heads/octo4 | 1 - .../merge-resolve/.gitted/refs/heads/octo5 | 1 - .../merge-resolve/.gitted/refs/heads/octo6 | 1 - .../.gitted/refs/heads/rename_conflict_ancestor | 1 - .../.gitted/refs/heads/rename_conflict_ours | 1 - .../.gitted/refs/heads/rename_conflict_theirs | 1 - .../merge-resolve/.gitted/refs/heads/renames1 | 1 - .../merge-resolve/.gitted/refs/heads/renames2 | 1 - .../merge-resolve/.gitted/refs/heads/trivial-10 | 1 - .../.gitted/refs/heads/trivial-10-branch | 1 - .../merge-resolve/.gitted/refs/heads/trivial-11 | 1 - .../.gitted/refs/heads/trivial-11-branch | 1 - .../merge-resolve/.gitted/refs/heads/trivial-13 | 1 - .../.gitted/refs/heads/trivial-13-branch | 1 - .../merge-resolve/.gitted/refs/heads/trivial-14 | 1 - .../.gitted/refs/heads/trivial-14-branch | 1 - .../merge-resolve/.gitted/refs/heads/trivial-2alt | 1 - .../.gitted/refs/heads/trivial-2alt-branch | 1 - .../merge-resolve/.gitted/refs/heads/trivial-3alt | 1 - .../.gitted/refs/heads/trivial-3alt-branch | 1 - .../merge-resolve/.gitted/refs/heads/trivial-4 | 1 - .../.gitted/refs/heads/trivial-4-branch | 1 - .../.gitted/refs/heads/trivial-5alt-1 | 1 - .../.gitted/refs/heads/trivial-5alt-1-branch | 1 - .../.gitted/refs/heads/trivial-5alt-2 | 1 - .../.gitted/refs/heads/trivial-5alt-2-branch | 1 - .../merge-resolve/.gitted/refs/heads/trivial-6 | 1 - .../.gitted/refs/heads/trivial-6-branch | 1 - .../merge-resolve/.gitted/refs/heads/trivial-7 | 1 - .../.gitted/refs/heads/trivial-7-branch | 1 - .../merge-resolve/.gitted/refs/heads/trivial-8 | 1 - .../.gitted/refs/heads/trivial-8-branch | 1 - .../merge-resolve/.gitted/refs/heads/trivial-9 | 1 - .../.gitted/refs/heads/trivial-9-branch | 1 - .../merge-resolve/.gitted/refs/heads/unrelated | 1 - .../resources/merge-resolve/added-in-master.txt | 1 - .../resources/merge-resolve/automergeable.txt | 9 - .../resources/merge-resolve/changed-in-branch.txt | 1 - .../resources/merge-resolve/changed-in-master.txt | 1 - tests-clar/resources/merge-resolve/conflicting.txt | 1 - .../resources/merge-resolve/removed-in-branch.txt | 1 - tests-clar/resources/merge-resolve/unchanged.txt | 1 - .../resources/mergedrepo/.gitted/COMMIT_EDITMSG | 1 - tests-clar/resources/mergedrepo/.gitted/HEAD | 1 - tests-clar/resources/mergedrepo/.gitted/MERGE_HEAD | 1 - tests-clar/resources/mergedrepo/.gitted/MERGE_MODE | 0 tests-clar/resources/mergedrepo/.gitted/MERGE_MSG | 5 - tests-clar/resources/mergedrepo/.gitted/ORIG_HEAD | 1 - tests-clar/resources/mergedrepo/.gitted/config | 6 - .../resources/mergedrepo/.gitted/description | 1 - tests-clar/resources/mergedrepo/.gitted/index | Bin 842 -> 0 bytes .../resources/mergedrepo/.gitted/info/exclude | 6 - tests-clar/resources/mergedrepo/.gitted/logs/HEAD | 5 - .../mergedrepo/.gitted/logs/refs/heads/branch | 2 - .../mergedrepo/.gitted/logs/refs/heads/master | 2 - .../03/db1d37504ca0c4f7c26d7776b0e28bdea08712 | Bin 141 -> 0 bytes .../17/0efc1023e0ed2390150bb4469c8456b63e8f91 | Bin 141 -> 0 bytes .../1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 | Bin 34 -> 0 bytes .../22/0bd62631c8cf7a83ef39c6b94595f00517211e | Bin 42 -> 0 bytes .../32/d55d59265db86dd690f0a7fc563db43e2bc6a6 | Bin 159 -> 0 bytes .../38/e2d82b9065a237904af4b780b4d68da6950534 | Bin 74 -> 0 bytes .../3a/34580a35add43a4cf361e8e9a30060a905c876 | 2 - .../44/58b8bc9e72b6c8755ae456f60e9844d0538d8c | Bin 39 -> 0 bytes .../47/8871385b9cd03908c5383acfd568bef023c6b3 | Bin 36 -> 0 bytes .../51/6bd85f78061e09ccc714561d7b504672cb52da | Bin 36 -> 0 bytes .../53/c1d95a01f4514b162066fc98564500c96c46ad | Bin 45 -> 0 bytes .../6a/ea5f295304c36144ad6e9247a291b7f8112399 | Bin 49 -> 0 bytes .../70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 | Bin 85 -> 0 bytes .../75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 | Bin 41 -> 0 bytes .../7b/26923aaf452b1977eb08617c59475fb3f74b71 | Bin 41 -> 0 bytes .../84/af62840be1b1c47b778a8a249f3ff45155038c | Bin 40 -> 0 bytes .../88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda | Bin 66 -> 0 bytes .../88/7b153b165d32409c70163e0f734c090f12f673 | Bin 38 -> 0 bytes .../8a/ad34cc83733590e74b93d0f7cf00375e2a735a | Bin 78 -> 0 bytes .../8b/3f43d2402825c200f835ca1762413e386fd0b2 | Bin 57 -> 0 bytes .../8b/72416545c7e761b64cecad4f1686eae4078aa8 | Bin 38 -> 0 bytes .../8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 | Bin 39 -> 0 bytes .../8f/fcc405925511824a2240a6d3686aa7f8c7ac50 | Bin 140 -> 0 bytes .../9a/05ccb4e0f948de03128e095f39dae6976751c5 | 1 - .../9d/81f82fccc7dcd7de7a1ffead1815294c2e092c | Bin 36 -> 0 bytes .../b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d | Bin 66 -> 0 bytes .../d0/1885ea594926eae9ba5b54ad76692af5969f51 | Bin 55 -> 0 bytes .../e2/809157a7766f272e4cfe26e61ef2678a5357ff | 3 - .../e6/2cac5c88b9928f2695b934c70efa4285324478 | Bin 87 -> 0 bytes .../f7/2784290c151092abf04ce6b875068547f70406 | Bin 141 -> 0 bytes .../resources/mergedrepo/.gitted/refs/heads/branch | 1 - .../resources/mergedrepo/.gitted/refs/heads/master | 1 - tests-clar/resources/mergedrepo/conflicts-one.txt | 5 - tests-clar/resources/mergedrepo/conflicts-two.txt | 5 - tests-clar/resources/mergedrepo/one.txt | 10 - tests-clar/resources/mergedrepo/two.txt | 12 - tests-clar/resources/partial-testrepo/.gitted/HEAD | 1 - .../resources/partial-testrepo/.gitted/config | 7 - .../resources/partial-testrepo/.gitted/index | Bin 328 -> 0 bytes .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 19 -> 0 bytes .../14/4344043ba4d4a405da03de3844aa829ae8be0e | Bin 163 -> 0 bytes .../16/8e4ebd1c667499548ae12403b19b22a5c5e925 | Bin 147 -> 0 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 51 -> 0 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 119 -> 0 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 18 -> 0 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 - .../4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 | Bin 50 -> 0 bytes .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 - .../62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc | Bin 50 -> 0 bytes .../66/3adb09143767984f7be83a91effa47e128c735 | Bin 19 -> 0 bytes .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 119 -> 0 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 82 -> 0 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 126 -> 0 bytes .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 - .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 - .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 28 -> 0 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 26 -> 0 bytes .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 - .../cf/80f8de9f1185bf3a05f993f6121880dd0cfbc9 | Bin 162 -> 0 bytes .../d5/2a8fe84ceedf260afe4f0287bbfca04a117e83 | Bin 147 -> 0 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 82 -> 0 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 24 -> 0 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 82 -> 0 bytes .../partial-testrepo/.gitted/objects/pack/.gitkeep | 0 .../partial-testrepo/.gitted/refs/heads/dir | 1 - tests-clar/resources/peeled.git/HEAD | 1 - tests-clar/resources/peeled.git/config | 8 - tests-clar/resources/peeled.git/objects/info/packs | 2 - ...ck-e84773eaf3fce1774755580e3dbb8d9f3a1adc45.idx | Bin 1156 -> 0 bytes ...k-e84773eaf3fce1774755580e3dbb8d9f3a1adc45.pack | Bin 274 -> 0 bytes tests-clar/resources/peeled.git/packed-refs | 6 - tests-clar/resources/peeled.git/refs/heads/master | 1 - tests-clar/resources/push.sh | 55 - .../resources/push_src/.gitted/COMMIT_EDITMSG | 1 - tests-clar/resources/push_src/.gitted/HEAD | 1 - tests-clar/resources/push_src/.gitted/ORIG_HEAD | 1 - tests-clar/resources/push_src/.gitted/config | 10 - tests-clar/resources/push_src/.gitted/description | 1 - tests-clar/resources/push_src/.gitted/index | Bin 470 -> 0 bytes tests-clar/resources/push_src/.gitted/info/exclude | 6 - tests-clar/resources/push_src/.gitted/logs/HEAD | 10 - .../resources/push_src/.gitted/logs/refs/heads/b1 | 1 - .../resources/push_src/.gitted/logs/refs/heads/b2 | 1 - .../resources/push_src/.gitted/logs/refs/heads/b3 | 2 - .../resources/push_src/.gitted/logs/refs/heads/b4 | 2 - .../resources/push_src/.gitted/logs/refs/heads/b5 | 2 - .../push_src/.gitted/logs/refs/heads/master | 3 - .../push_src/.gitted/modules/submodule/HEAD | 1 - .../push_src/.gitted/modules/submodule/config | 15 - .../push_src/.gitted/modules/submodule/description | 1 - .../push_src/.gitted/modules/submodule/index | Bin 256 -> 0 bytes .../.gitted/modules/submodule/info/exclude | 6 - .../push_src/.gitted/modules/submodule/logs/HEAD | 1 - .../modules/submodule/logs/refs/heads/master | 1 - .../submodule/logs/refs/remotes/origin/HEAD | 1 - .../08/b041783f40edfe12bb406c9c9a8a040177c125 | Bin 54 -> 0 bytes .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 19 -> 0 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 51 -> 0 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 119 -> 0 bytes .../1a/443023183e3f2bfbef8ac923cd81c1018a18fd | Bin 122 -> 0 bytes .../1b/8cbad43e867676df601306689fe7c3def5e689 | Bin 51 -> 0 bytes .../1f/67fc4386b2d171e0d21be1c447e12660561f9b | Bin 21 -> 0 bytes .../25/8f0e2a959a364e40ed6603d5d44fbb24765b10 | Bin 168 -> 0 bytes .../27/0b8ea76056d5cad83af921837702d3e3c2924d | Bin 21 -> 0 bytes .../2d/59075e0681f540482d4f6223a68e0fef790bc7 | Bin 44 -> 0 bytes .../32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 | Bin 50 -> 0 bytes .../36/97d64be941a53d4ae8f6a271e4e3fa56b022cc | Bin 23 -> 0 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 18 -> 0 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 - .../4b/22b35d44b5a4f589edf3dc89196399771796ea | Bin 44 -> 0 bytes .../52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 | Bin 152 -> 0 bytes .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 - .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 119 -> 0 bytes .../76/3d71aadf09a7951596c9746c024e7eece7c7af | 1 - .../7b/4384978d2493e851f9cca7858815fac9b10980 | Bin 145 -> 0 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 82 -> 0 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 126 -> 0 bytes .../84/9a5e34a26815e821f865b8479f5815a47af0fe | 2 - .../94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 | 1 - .../9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 | Bin 50 -> 0 bytes .../9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 | 2 - .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 - .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 - .../a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 | 3 - .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 28 -> 0 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 26 -> 0 bytes .../ae/90f12eea699729ed24555e40b9fd669da12a12 | Bin 148 -> 0 bytes .../b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 | 2 - .../b6/361fc6a97178d8fc8639fdeed71c775ab52593 | Bin 80 -> 0 bytes .../be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 | 3 - .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 - .../d0/7b0f9a8c89f1d9e74dc4fce6421dec5ef8a659 | Bin 149 -> 0 bytes .../d6/c93164c249c8000205dd4ec5cbca1b516d487f | Bin 21 -> 0 bytes .../d7/1aab4f9b04b45ce09bcaa636a9be6231474759 | Bin 79 -> 0 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 15 -> 0 bytes .../e7/b4ad382349ff96dd8199000580b9b1e2042eb0 | Bin 21 -> 0 bytes .../f1/425cef211cc08caa31e7b545ffb232acb098c3 | Bin 103 -> 0 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 82 -> 0 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 24 -> 0 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 82 -> 0 bytes .../fd/4959ce7510db09d4d8217fa2d1780413e05a09 | Bin 152 -> 0 bytes ...ck-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx | Bin 46656 -> 0 bytes ...k-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack | Bin 386089 -> 0 bytes ...ck-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx | Bin 1240 -> 0 bytes ...k-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack | Bin 491 -> 0 bytes ...ck-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx | Bin 1240 -> 0 bytes ...k-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack | Bin 498 -> 0 bytes .../push_src/.gitted/modules/submodule/packed-refs | 24 - .../.gitted/modules/submodule/refs/heads/master | 1 - .../modules/submodule/refs/remotes/origin/HEAD | 1 - .../08/585692ce06452da6f82ae66b90d98b55536fca | 1 - .../27/b7ce66243eb1403862d05f958c002312df173d | 4 - .../28/905c54ea45a4bed8d7b90f51bd8bd81eec8840 | Bin 109 -> 0 bytes .../36/6226fb970ac0caa9d3f55967ab01334a548f60 | Bin 20 -> 0 bytes .../36/f79b2846017d3761e0a02d0bccd573e0f90c57 | 2 - .../5c/0bb3d1b9449d1cc69d7519fd05166f01840915 | Bin 128 -> 0 bytes .../61/780798228d17af2d34fce4cfbdf35556832472 | Bin 17 -> 0 bytes .../64/fd55f9b6390202db5e5666fd1fb339089fba4d | Bin 176 -> 0 bytes .../78/981922613b2afb6025042ff6bd878ac1994e85 | Bin 17 -> 0 bytes .../80/5c54522e614f29f70d2413a0470247d8b424ac | Bin 131 -> 0 bytes .../95/1bbbb90e2259a4c8950db78946784fb53fcbce | 2 - .../a7/8705c3b2725f931d3ee05348d83cc26700f247 | Bin 166 -> 0 bytes .../b4/83ae7ba66decee9aee971f501221dea84b1498 | 3 - .../b4/e1f2b375a64c1ccd40c5ff6aa8bc96839ba4fd | Bin 148 -> 0 bytes .../c1/0409136a7a75e025fa502a1b2fd7b62b77d279 | Bin 22 -> 0 bytes .../cd/881f90f2933db2e4cc26b8c71fe6037ac7fe4c | Bin 80 -> 0 bytes .../d9/b63a88223d8367516f50bd131a5f7349b7f3e4 | 2 - .../dc/ab83249f6f9d1ed735d651352a80519339b591 | Bin 80 -> 0 bytes .../ee/a4f2705eeec2db3813f2430829afce99cd00b5 | Bin 141 -> 0 bytes .../f7/8a3106c85fb549c65198b2a2086276c6174928 | Bin 65 -> 0 bytes .../f8/f7aefc2900a3d737cea9eee45729fd55761e1a | Bin 50 -> 0 bytes .../fa/38b91f199934685819bea316186d8b008c52a2 | 2 - .../ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e | 4 - .../ff/fe95c7fd0a37fa2ed702f8f93b56b2196b3925 | Bin 109 -> 0 bytes .../resources/push_src/.gitted/objects/pack/dummy | 0 .../resources/push_src/.gitted/refs/heads/b1 | 1 - .../resources/push_src/.gitted/refs/heads/b2 | 1 - .../resources/push_src/.gitted/refs/heads/b3 | 1 - .../resources/push_src/.gitted/refs/heads/b4 | 1 - .../resources/push_src/.gitted/refs/heads/b5 | 1 - .../resources/push_src/.gitted/refs/heads/b6 | 1 - .../resources/push_src/.gitted/refs/tags/tag-blob | 1 - .../push_src/.gitted/refs/tags/tag-commit | 1 - .../push_src/.gitted/refs/tags/tag-commit-two | 1 - .../push_src/.gitted/refs/tags/tag-lightweight | 1 - .../resources/push_src/.gitted/refs/tags/tag-tag | 1 - .../resources/push_src/.gitted/refs/tags/tag-tree | 1 - tests-clar/resources/push_src/a.txt | 2 - tests-clar/resources/push_src/fold/b.txt | 1 - tests-clar/resources/push_src/foldb.txt | 1 - tests-clar/resources/push_src/gitmodules | 3 - tests-clar/resources/push_src/submodule/.gitted | 1 - tests-clar/resources/push_src/submodule/README | 1 - .../resources/push_src/submodule/branch_file.txt | 2 - tests-clar/resources/push_src/submodule/new.txt | 1 - tests-clar/resources/renames/.gitted/HEAD | 1 - tests-clar/resources/renames/.gitted/config | 7 - tests-clar/resources/renames/.gitted/description | 1 - tests-clar/resources/renames/.gitted/index | Bin 352 -> 0 bytes tests-clar/resources/renames/.gitted/info/exclude | 6 - tests-clar/resources/renames/.gitted/logs/HEAD | 4 - .../renames/.gitted/logs/refs/heads/master | 4 - .../03/da7ad872536bd448da8d88eb7165338bf923a7 | Bin 90 -> 0 bytes .../17/58bdd7c16a72ff7c17d8de0c957ced3ccad645 | 5 - .../19/dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 | 1 - .../1c/068dee5790ef1580cfc4cd670915b48d790084 | Bin 176 -> 0 bytes .../2b/c7f351d20b53f1c72c16c4b036e491c478c49a | Bin 173 -> 0 bytes .../31/e47d8c1fa36d7f8d537b96158e3f024de0a9f2 | Bin 131 -> 0 bytes .../35/92953ff3ea5e8ba700c429f3aefe33c8806754 | Bin 80 -> 0 bytes .../36/020db6cdacaa93497f31edcd8f242ff9bc366d | Bin 431 -> 0 bytes .../3c/04741dd4b96c4ae4b00ec0f6e10c816a30aad2 | Bin 159 -> 0 bytes .../42/10ffd5c390b21dd5483375e75288dea9ede512 | Bin 1145 -> 0 bytes .../44/4a76ed3e45b183753f49376af30da8c3fe276a | Bin 135 -> 0 bytes .../47/184c1e7eb22abcbed2bf4ee87d4e38096f7951 | Bin 229 -> 0 bytes .../4e/4cae3e7dd56ed74bff39526d0469e554432953 | Bin 452 -> 0 bytes .../50/e90273af7d826ff0a95865bcd3ba8412c447d9 | 3 - .../5e/26abc56a5a84d89790f45416648899cbe13109 | Bin 163 -> 0 bytes .../61/8c6f2f8740bd6049b2fb9eb93fc15726462745 | Bin 106 -> 0 bytes .../66/311f5cfbe7836c27510a3ba2f43e282e2c8bba | Bin 1155 -> 0 bytes .../93/f538c45a57a87eb4c1e86f91c6ee41d66c7ba7 | Bin 229 -> 0 bytes .../9a/69d960ae94b060f56c2a8702545e2bb1abb935 | Bin 464 -> 0 bytes .../ad/0a8e55a104ac54a8a29ed4b84b49e76837a113 | Bin 415 -> 0 bytes .../b9/25b224cc91f897001a9993fbce169fdaa8858f | Bin 76 -> 0 bytes .../d7/9b202de198fa61b02424b9e25e840dc75e1323 | Bin 421 -> 0 bytes .../ea/c43f5195a2cee53b7458d8dad16aedde10711b | Bin 118 -> 0 bytes .../ea/f4a3e3bfe68585e90cada20736ace491cd100b | 5 - .../f9/0d4fc20ecddf21eebe6a37e9225d244339d2b5 | Bin 441 -> 0 bytes .../resources/renames/.gitted/refs/heads/master | 1 - .../renames/.gitted/refs/heads/renames_similar | 1 - .../renames/.gitted/refs/heads/renames_similar_two | 1 - tests-clar/resources/renames/ikeepsix.txt | 27 - tests-clar/resources/renames/sixserving.txt | 25 - tests-clar/resources/renames/songof7cities.txt | 49 - tests-clar/resources/renames/untimely.txt | 24 - tests-clar/resources/shallow.git/HEAD | 1 - tests-clar/resources/shallow.git/config | 8 - ...ck-706e49b161700946489570d96153e5be4dc31ad4.idx | Bin 1324 -> 0 bytes ...k-706e49b161700946489570d96153e5be4dc31ad4.pack | Bin 791 -> 0 bytes tests-clar/resources/shallow.git/packed-refs | 2 - tests-clar/resources/shallow.git/refs/.gitkeep | 0 tests-clar/resources/shallow.git/shallow | 1 - tests-clar/resources/short_tag.git/HEAD | 1 - tests-clar/resources/short_tag.git/config | 5 - tests-clar/resources/short_tag.git/index | Bin 104 -> 0 bytes .../4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c | Bin 169 -> 0 bytes .../4d/5fcadc293a348e88f777dc0920f11e7d71441c | Bin 48 -> 0 bytes .../5d/a7760512a953e3c7c4e47e4392c7a4338fb729 | 1 - .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 15 -> 0 bytes tests-clar/resources/short_tag.git/packed-refs | 1 - .../resources/short_tag.git/refs/heads/master | 1 - tests-clar/resources/status/.gitted/COMMIT_EDITMSG | 1 - tests-clar/resources/status/.gitted/HEAD | 1 - tests-clar/resources/status/.gitted/ORIG_HEAD | 1 - tests-clar/resources/status/.gitted/config | 6 - tests-clar/resources/status/.gitted/description | 1 - tests-clar/resources/status/.gitted/index | Bin 1160 -> 0 bytes tests-clar/resources/status/.gitted/info/exclude | 8 - tests-clar/resources/status/.gitted/logs/HEAD | 3 - .../status/.gitted/logs/refs/heads/master | 3 - .../00/17bd4ab1ec30440b17bae1680cff124ab5f1f6 | 2 - .../06/1d42a44cacde5726057b67558821d95db96f19 | Bin 44 -> 0 bytes .../18/88c805345ba265b0ee9449b8877b6064592058 | Bin 36 -> 0 bytes .../19/d9cc8584ac2c7dcf57d2680375e80f099dc481 | Bin 22 -> 0 bytes .../26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f | 2 - .../32/504b727382542f9f089e24fddac5e78533e96c | Bin 31 -> 0 bytes .../37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0 | Bin 331 -> 0 bytes .../45/2e4244b5d083ddf0460acf1ecc74db9dcfa11a | Bin 30 -> 0 bytes .../52/9a16e8e762d4acb7b9636ff540a00831f9155a | Bin 32 -> 0 bytes .../53/ace0d1cc1145a5f4fe4f78a186a60263190733 | Bin 36 -> 0 bytes .../54/52d32f1dd538eb0405e8a83cc185f79e25e80f | Bin 29 -> 0 bytes .../55/d316c9ba708999f1918e9677d01dfcae69c6b9 | Bin 33 -> 0 bytes .../70/bd9443ada07063e7fbf0b3ff5c13f7494d89c2 | Bin 44 -> 0 bytes .../73/5b6a258cd196a8f7c9428419b02c1dca93fd75 | Bin 160 -> 0 bytes .../75/6e27627e67bfbc048d01ece5819c6de733d7ea | Bin 301 -> 0 bytes .../90/6ee7711f4f4928ddcb2a5f8fbc500deba0d2a8 | Bin 46 -> 0 bytes .../90/b8c29d8ba39434d1c63e1b093daaa26e5bd972 | Bin 41 -> 0 bytes .../9c/2e02cdffa8d73e6c189074594477a6baf87960 | Bin 268 -> 0 bytes .../a0/de7e0ac200c489c41c59dfa910154a70264e6e | Bin 29 -> 0 bytes .../a6/191982709b746d5650e93c2acf34ef74e11504 | Bin 37 -> 0 bytes .../a6/be623522ce87a1d862128ac42672604f7b468b | Bin 46 -> 0 bytes .../aa/27a641456848200fdb7f7c99ba36f8a0952877 | Bin 120 -> 0 bytes .../da/bc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 | Bin 42 -> 0 bytes .../e8/ee89e15bbe9b20137715232387b3de5b28972e | Bin 38 -> 0 bytes .../e9/b9107f290627c04d097733a10055af941f6bca | Bin 37 -> 0 bytes .../ed/062903b8f6f3dccb2fa81117ba6590944ef9bd | Bin 42 -> 0 bytes .../resources/status/.gitted/refs/heads/master | 1 - tests-clar/resources/status/current_file | 1 - tests-clar/resources/status/ignored_file | 1 - tests-clar/resources/status/modified_file | 2 - tests-clar/resources/status/new_file | 1 - tests-clar/resources/status/staged_changes | 2 - .../resources/status/staged_changes_modified_file | 3 - .../resources/status/staged_delete_modified_file | 1 - tests-clar/resources/status/staged_new_file | 1 - .../resources/status/staged_new_file_modified_file | 2 - tests-clar/resources/status/subdir.txt | 2 - tests-clar/resources/status/subdir/current_file | 1 - tests-clar/resources/status/subdir/modified_file | 2 - tests-clar/resources/status/subdir/new_file | 1 - "tests-clar/resources/status/\350\277\231" | 1 - tests-clar/resources/submod2/.gitted/HEAD | 1 - tests-clar/resources/submod2/.gitted/config | 20 - tests-clar/resources/submod2/.gitted/description | 1 - tests-clar/resources/submod2/.gitted/index | Bin 944 -> 0 bytes tests-clar/resources/submod2/.gitted/info/exclude | 6 - tests-clar/resources/submod2/.gitted/logs/HEAD | 4 - .../submod2/.gitted/logs/refs/heads/master | 4 - .../.gitted/modules/sm_added_and_uncommited/HEAD | 1 - .../.gitted/modules/sm_added_and_uncommited/config | 13 - .../modules/sm_added_and_uncommited/description | 1 - .../.gitted/modules/sm_added_and_uncommited/index | Bin 192 -> 0 bytes .../modules/sm_added_and_uncommited/info/exclude | 6 - .../modules/sm_added_and_uncommited/logs/HEAD | 1 - .../sm_added_and_uncommited/logs/refs/heads/master | 1 - .../logs/refs/remotes/origin/HEAD | 1 - .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 55 -> 0 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 53 -> 0 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 93 -> 0 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 163 -> 0 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 163 -> 0 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 167 -> 0 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 - .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 93 -> 0 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 - .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 - .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 81 -> 0 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 93 -> 0 bytes .../modules/sm_added_and_uncommited/packed-refs | 2 - .../sm_added_and_uncommited/refs/heads/master | 1 - .../refs/remotes/origin/HEAD | 1 - .../submod2/.gitted/modules/sm_changed_file/HEAD | 1 - .../submod2/.gitted/modules/sm_changed_file/config | 13 - .../.gitted/modules/sm_changed_file/description | 1 - .../submod2/.gitted/modules/sm_changed_file/index | Bin 192 -> 0 bytes .../.gitted/modules/sm_changed_file/info/exclude | 6 - .../.gitted/modules/sm_changed_file/logs/HEAD | 1 - .../modules/sm_changed_file/logs/refs/heads/master | 1 - .../sm_changed_file/logs/refs/remotes/origin/HEAD | 1 - .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 55 -> 0 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 53 -> 0 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 93 -> 0 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 163 -> 0 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 163 -> 0 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 167 -> 0 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 - .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 93 -> 0 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 - .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 - .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 81 -> 0 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 93 -> 0 bytes .../.gitted/modules/sm_changed_file/packed-refs | 2 - .../modules/sm_changed_file/refs/heads/master | 1 - .../sm_changed_file/refs/remotes/origin/HEAD | 1 - .../.gitted/modules/sm_changed_head/COMMIT_EDITMSG | 1 - .../submod2/.gitted/modules/sm_changed_head/HEAD | 1 - .../submod2/.gitted/modules/sm_changed_head/config | 13 - .../.gitted/modules/sm_changed_head/description | 1 - .../submod2/.gitted/modules/sm_changed_head/index | Bin 192 -> 0 bytes .../.gitted/modules/sm_changed_head/info/exclude | 6 - .../.gitted/modules/sm_changed_head/logs/HEAD | 2 - .../modules/sm_changed_head/logs/refs/heads/master | 2 - .../sm_changed_head/logs/refs/remotes/origin/HEAD | 1 - .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 55 -> 0 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 53 -> 0 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 93 -> 0 bytes .../3d/9386c507f6b093471a3e324085657a3c2b4247 | 3 - .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 163 -> 0 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 163 -> 0 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 167 -> 0 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 - .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 93 -> 0 bytes .../77/fb0ed3e58568d6ad362c78de08ab8649d76e29 | Bin 93 -> 0 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 - .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 - .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 81 -> 0 bytes .../8e/b1e637ed9fc8e5454fa20d38f809091f9395f4 | 2 - .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 93 -> 0 bytes .../.gitted/modules/sm_changed_head/packed-refs | 2 - .../modules/sm_changed_head/refs/heads/master | 1 - .../sm_changed_head/refs/remotes/origin/HEAD | 1 - .../submod2/.gitted/modules/sm_changed_index/HEAD | 1 - .../.gitted/modules/sm_changed_index/config | 13 - .../.gitted/modules/sm_changed_index/description | 1 - .../submod2/.gitted/modules/sm_changed_index/index | Bin 192 -> 0 bytes .../.gitted/modules/sm_changed_index/info/exclude | 6 - .../.gitted/modules/sm_changed_index/logs/HEAD | 1 - .../sm_changed_index/logs/refs/heads/master | 1 - .../sm_changed_index/logs/refs/remotes/origin/HEAD | 1 - .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 55 -> 0 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 53 -> 0 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 93 -> 0 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 163 -> 0 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 163 -> 0 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 167 -> 0 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 - .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 93 -> 0 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 - .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 - .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 81 -> 0 bytes .../a0/2d31770687965547ab7a04cee199b29ee458d6 | Bin 134 -> 0 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 93 -> 0 bytes .../.gitted/modules/sm_changed_index/packed-refs | 2 - .../modules/sm_changed_index/refs/heads/master | 1 - .../sm_changed_index/refs/remotes/origin/HEAD | 1 - .../.gitted/modules/sm_changed_untracked_file/HEAD | 1 - .../modules/sm_changed_untracked_file/config | 13 - .../modules/sm_changed_untracked_file/description | 1 - .../modules/sm_changed_untracked_file/index | Bin 192 -> 0 bytes .../modules/sm_changed_untracked_file/info/exclude | 6 - .../modules/sm_changed_untracked_file/logs/HEAD | 1 - .../logs/refs/heads/master | 1 - .../logs/refs/remotes/origin/HEAD | 1 - .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 55 -> 0 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 53 -> 0 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 93 -> 0 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 163 -> 0 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 163 -> 0 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 167 -> 0 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 - .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 93 -> 0 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 - .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 - .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 81 -> 0 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 93 -> 0 bytes .../modules/sm_changed_untracked_file/packed-refs | 2 - .../sm_changed_untracked_file/refs/heads/master | 1 - .../refs/remotes/origin/HEAD | 1 - .../.gitted/modules/sm_missing_commits/HEAD | 1 - .../.gitted/modules/sm_missing_commits/config | 13 - .../.gitted/modules/sm_missing_commits/description | 1 - .../.gitted/modules/sm_missing_commits/index | Bin 192 -> 0 bytes .../modules/sm_missing_commits/info/exclude | 6 - .../.gitted/modules/sm_missing_commits/logs/HEAD | 1 - .../sm_missing_commits/logs/refs/heads/master | 1 - .../logs/refs/remotes/origin/HEAD | 1 - .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 55 -> 0 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 53 -> 0 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 93 -> 0 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 163 -> 0 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 167 -> 0 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 - .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 - .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 81 -> 0 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 93 -> 0 bytes .../.gitted/modules/sm_missing_commits/packed-refs | 2 - .../modules/sm_missing_commits/refs/heads/master | 1 - .../sm_missing_commits/refs/remotes/origin/HEAD | 1 - .../submod2/.gitted/modules/sm_unchanged/HEAD | 1 - .../submod2/.gitted/modules/sm_unchanged/config | 13 - .../.gitted/modules/sm_unchanged/description | 1 - .../submod2/.gitted/modules/sm_unchanged/index | Bin 192 -> 0 bytes .../.gitted/modules/sm_unchanged/info/exclude | 6 - .../submod2/.gitted/modules/sm_unchanged/logs/HEAD | 1 - .../modules/sm_unchanged/logs/refs/heads/master | 1 - .../sm_unchanged/logs/refs/remotes/origin/HEAD | 1 - .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 55 -> 0 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 53 -> 0 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 93 -> 0 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 163 -> 0 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 163 -> 0 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 167 -> 0 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 - .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 93 -> 0 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 - .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 - .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 81 -> 0 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 93 -> 0 bytes .../.gitted/modules/sm_unchanged/packed-refs | 2 - .../.gitted/modules/sm_unchanged/refs/heads/master | 1 - .../modules/sm_unchanged/refs/remotes/origin/HEAD | 1 - .../09/460e5b6cbcb05a3e404593c32a3aa7221eca0e | Bin 197 -> 0 bytes .../14/fe9ccf104058df25e0a08361c4494e167ef243 | 1 - .../22/ce3e0311dda73a5992d54a4a595518d3876ea7 | 4 - .../25/5546424b0efb847b1bfc91dbf7348b277f8970 | Bin 157 -> 0 bytes .../2a/30f1e6f94b20917005a21273f65b406d0f8bad | Bin 144 -> 0 bytes .../42/cfb95cd01bf9225b659b5ee3edcc78e8eeb478 | Bin 40 -> 0 bytes .../57/958699c2dc394f81cfc76950e9c3ac3025c398 | Bin 136 -> 0 bytes .../59/01da4f1c67756eeadc5121d206bec2431f253b | 2 - .../60/7d96653d4d0a4f733107f7890c2e67b55b620d | Bin 53 -> 0 bytes .../74/84482eb8db738cafa696993664607500a3f2b9 | Bin 173 -> 0 bytes .../7b/a4c5c3561daa5ab1a86215cfb0587e96d404d6 | Bin 48 -> 0 bytes .../87/3585b94bdeabccea991ea5e3ec1a277895b698 | Bin 137 -> 0 bytes .../97/4cf7c73de336b0c4e019f918f3cee367d72e84 | 2 - .../9d/bc299bc013ea253583b40bf327b5a6e4037b89 | Bin 80 -> 0 bytes .../a9/104bf89e911387244ef499413960ba472066d9 | Bin 165 -> 0 bytes .../b6/14088620bbdc1d29549d223ceba0f4419fd4cb | Bin 110 -> 0 bytes .../d4/07f19e50c1da1ff584beafe0d6dac7237c5d06 | Bin 55 -> 0 bytes .../d9/3e95571d92cceb5de28c205f1d5f3cc8b88bc8 | 2 - .../e3/b83bf274ee065eee48734cf8c6dfaf5e81471c | Bin 246 -> 0 bytes .../f5/4414c25e6d24fe39f5c3f128d7c8a17bc23833 | 2 - .../f9/90a25a74d1a8281ce2ab018ea8df66795cd60b | 1 - .../resources/submod2/.gitted/refs/heads/master | 1 - tests-clar/resources/submod2/README.txt | 3 - tests-clar/resources/submod2/gitmodules | 24 - tests-clar/resources/submod2/just_a_dir/contents | 1 - tests-clar/resources/submod2/just_a_file | 1 - .../resources/submod2/not-submodule/.gitted/HEAD | 1 - .../resources/submod2/not-submodule/.gitted/config | 6 - .../submod2/not-submodule/.gitted/description | 1 - .../resources/submod2/not-submodule/.gitted/index | Bin 112 -> 0 bytes .../submod2/not-submodule/.gitted/info/exclude | 6 - .../submod2/not-submodule/.gitted/logs/HEAD | 1 - .../not-submodule/.gitted/logs/refs/heads/master | 1 - .../68/e92c611b80ee1ed8f38314ff9577f0d15b2444 | Bin 132 -> 0 bytes .../71/ff9927d7c8a5639e062c38a7d35c433c424627 | Bin 52 -> 0 bytes .../f0/1d56b18efd353ef2bb93a4585d590a0847195e | Bin 55 -> 0 bytes .../not-submodule/.gitted/refs/heads/master | 1 - .../resources/submod2/not-submodule/README.txt | 1 - tests-clar/resources/submod2/not/.gitted/notempty | 1 - tests-clar/resources/submod2/not/README.txt | 1 - .../submod2/sm_added_and_uncommited/.gitted | 1 - .../submod2/sm_added_and_uncommited/README.txt | 3 - .../submod2/sm_added_and_uncommited/file_to_modify | 3 - .../resources/submod2/sm_changed_file/.gitted | 1 - .../resources/submod2/sm_changed_file/README.txt | 3 - .../submod2/sm_changed_file/file_to_modify | 4 - .../resources/submod2/sm_changed_head/.gitted | 1 - .../resources/submod2/sm_changed_head/README.txt | 3 - .../submod2/sm_changed_head/file_to_modify | 4 - .../resources/submod2/sm_changed_index/.gitted | 1 - .../resources/submod2/sm_changed_index/README.txt | 3 - .../submod2/sm_changed_index/file_to_modify | 4 - .../submod2/sm_changed_untracked_file/.gitted | 1 - .../submod2/sm_changed_untracked_file/README.txt | 3 - .../sm_changed_untracked_file/file_to_modify | 3 - .../sm_changed_untracked_file/i_am_untracked | 1 - .../resources/submod2/sm_missing_commits/.gitted | 1 - .../submod2/sm_missing_commits/README.txt | 3 - .../submod2/sm_missing_commits/file_to_modify | 3 - tests-clar/resources/submod2/sm_unchanged/.gitted | 1 - .../resources/submod2/sm_unchanged/README.txt | 3 - .../resources/submod2/sm_unchanged/file_to_modify | 3 - tests-clar/resources/submod2_target/.gitted/HEAD | 1 - tests-clar/resources/submod2_target/.gitted/config | 6 - .../resources/submod2_target/.gitted/description | 1 - tests-clar/resources/submod2_target/.gitted/index | Bin 192 -> 0 bytes .../resources/submod2_target/.gitted/info/exclude | 6 - .../resources/submod2_target/.gitted/logs/HEAD | 4 - .../submod2_target/.gitted/logs/refs/heads/master | 4 - .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 55 -> 0 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 53 -> 0 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 93 -> 0 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 163 -> 0 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 163 -> 0 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 167 -> 0 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 - .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 93 -> 0 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 - .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 - .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 81 -> 0 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 93 -> 0 bytes .../submod2_target/.gitted/refs/heads/master | 1 - tests-clar/resources/submod2_target/README.txt | 3 - tests-clar/resources/submod2_target/file_to_modify | 3 - tests-clar/resources/submodules/.gitted/HEAD | 1 - tests-clar/resources/submodules/.gitted/config | 6 - .../resources/submodules/.gitted/description | 1 - tests-clar/resources/submodules/.gitted/index | Bin 408 -> 0 bytes .../resources/submodules/.gitted/info/exclude | 8 - tests-clar/resources/submodules/.gitted/info/refs | 1 - tests-clar/resources/submodules/.gitted/logs/HEAD | 2 - .../submodules/.gitted/logs/refs/heads/master | 2 - .../26/a3b32a9b7d97486c5557f5902e8ac94638145e | 2 - .../78/308c9251cf4eee8b25a76c7d2790c73d797357 | Bin 97 -> 0 bytes .../97/896810b3210244a62a82458b8e0819ecfc6850 | 3 - .../b6/0fd986699ba4e9e68bea07cf8e793f323ef888 | Bin 138 -> 0 bytes .../d5/f7fc3f74f7dec08280f370a975b112e8f60818 | Bin 21 -> 0 bytes .../e3/50052cc767cd1fcb37e84e9a89e701925be4ae | Bin 120 -> 0 bytes .../submodules/.gitted/objects/info/packs | 2 - ...ck-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx | Bin 1156 -> 0 bytes ...k-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack | Bin 228 -> 0 bytes .../resources/submodules/.gitted/packed-refs | 2 - .../resources/submodules/.gitted/refs/heads/master | 1 - tests-clar/resources/submodules/added | 1 - tests-clar/resources/submodules/gitmodules | 6 - tests-clar/resources/submodules/ignored | 1 - tests-clar/resources/submodules/modified | 2 - .../resources/submodules/testrepo/.gitted/HEAD | 1 - .../resources/submodules/testrepo/.gitted/config | 12 - .../submodules/testrepo/.gitted/description | 1 - .../resources/submodules/testrepo/.gitted/index | Bin 256 -> 0 bytes .../submodules/testrepo/.gitted/info/exclude | 6 - .../submodules/testrepo/.gitted/logs/HEAD | 1 - .../testrepo/.gitted/logs/refs/heads/master | 1 - .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 19 -> 0 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 51 -> 0 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 119 -> 0 bytes .../1f/67fc4386b2d171e0d21be1c447e12660561f9b | Bin 21 -> 0 bytes .../27/0b8ea76056d5cad83af921837702d3e3c2924d | Bin 21 -> 0 bytes .../32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 | Bin 50 -> 0 bytes .../36/97d64be941a53d4ae8f6a271e4e3fa56b022cc | Bin 23 -> 0 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 18 -> 0 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 - .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 - .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 119 -> 0 bytes .../76/3d71aadf09a7951596c9746c024e7eece7c7af | 1 - .../7b/4384978d2493e851f9cca7858815fac9b10980 | Bin 145 -> 0 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 82 -> 0 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 126 -> 0 bytes .../94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 | 1 - .../9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 | Bin 50 -> 0 bytes .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 - .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 - .../a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 | 3 - .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 28 -> 0 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 26 -> 0 bytes .../ae/90f12eea699729ed24555e40b9fd669da12a12 | Bin 148 -> 0 bytes .../b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 | 2 - .../b6/361fc6a97178d8fc8639fdeed71c775ab52593 | Bin 80 -> 0 bytes .../be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 | 3 - .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 - .../d6/c93164c249c8000205dd4ec5cbca1b516d487f | Bin 21 -> 0 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 15 -> 0 bytes .../e7/b4ad382349ff96dd8199000580b9b1e2042eb0 | Bin 21 -> 0 bytes .../f1/425cef211cc08caa31e7b545ffb232acb098c3 | Bin 103 -> 0 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 82 -> 0 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 24 -> 0 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 82 -> 0 bytes ...ck-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx | Bin 46656 -> 0 bytes ...k-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack | Bin 386089 -> 0 bytes ...ck-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx | Bin 1240 -> 0 bytes ...k-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack | Bin 491 -> 0 bytes ...ck-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx | Bin 1240 -> 0 bytes ...k-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack | Bin 498 -> 0 bytes .../submodules/testrepo/.gitted/packed-refs | 12 - .../submodules/testrepo/.gitted/refs/heads/master | 1 - .../testrepo/.gitted/refs/remotes/origin/HEAD | 1 - tests-clar/resources/submodules/testrepo/README | 1 - .../resources/submodules/testrepo/branch_file.txt | 2 - tests-clar/resources/submodules/testrepo/new.txt | 1 - tests-clar/resources/submodules/unmodified | 1 - tests-clar/resources/submodules/untracked | 1 - tests-clar/resources/template/branches/.gitignore | 2 - tests-clar/resources/template/description | 1 - tests-clar/resources/template/hooks/link.sample | 1 - tests-clar/resources/template/hooks/update.sample | 9 - tests-clar/resources/template/info/exclude | 6 - tests-clar/resources/testrepo.git/FETCH_HEAD | 2 - tests-clar/resources/testrepo.git/HEAD | 1 - tests-clar/resources/testrepo.git/HEAD_TRACKER | 1 - tests-clar/resources/testrepo.git/config | 40 - tests-clar/resources/testrepo.git/index | Bin 10041 -> 0 bytes tests-clar/resources/testrepo.git/logs/HEAD | 7 - .../resources/testrepo.git/logs/refs/heads/br2 | 2 - .../resources/testrepo.git/logs/refs/heads/master | 2 - .../testrepo.git/logs/refs/heads/not-good | 1 - .../testrepo.git/logs/refs/remotes/origin/HEAD | 1 - .../testrepo.git/logs/refs/remotes/test/master | 2 - .../08/b041783f40edfe12bb406c9c9a8a040177c125 | Bin 54 -> 0 bytes .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 19 -> 0 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 51 -> 0 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 119 -> 0 bytes .../1a/443023183e3f2bfbef8ac923cd81c1018a18fd | Bin 122 -> 0 bytes .../1b/8cbad43e867676df601306689fe7c3def5e689 | Bin 51 -> 0 bytes .../1f/67fc4386b2d171e0d21be1c447e12660561f9b | Bin 21 -> 0 bytes .../25/8f0e2a959a364e40ed6603d5d44fbb24765b10 | Bin 168 -> 0 bytes .../27/0b8ea76056d5cad83af921837702d3e3c2924d | Bin 21 -> 0 bytes .../2d/59075e0681f540482d4f6223a68e0fef790bc7 | Bin 44 -> 0 bytes .../32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 | Bin 50 -> 0 bytes .../36/97d64be941a53d4ae8f6a271e4e3fa56b022cc | Bin 23 -> 0 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 18 -> 0 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 - .../4a/23e2e65ad4e31c4c9db7dc746650bfad082679 | Bin 83 -> 0 bytes .../4b/22b35d44b5a4f589edf3dc89196399771796ea | Bin 44 -> 0 bytes .../52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 | Bin 152 -> 0 bytes .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 - .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 119 -> 0 bytes .../76/3d71aadf09a7951596c9746c024e7eece7c7af | 1 - .../7b/4384978d2493e851f9cca7858815fac9b10980 | Bin 145 -> 0 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 82 -> 0 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 126 -> 0 bytes .../84/9a5e34a26815e821f865b8479f5815a47af0fe | 2 - .../94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 | 1 - .../9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 | Bin 50 -> 0 bytes .../9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 | 2 - .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 - .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 - .../a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 | 3 - .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 28 -> 0 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 26 -> 0 bytes .../ae/90f12eea699729ed24555e40b9fd669da12a12 | Bin 148 -> 0 bytes .../b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 | 2 - .../b6/361fc6a97178d8fc8639fdeed71c775ab52593 | Bin 80 -> 0 bytes .../be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 | 3 - .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 - .../d0/7b0f9a8c89f1d9e74dc4fce6421dec5ef8a659 | Bin 149 -> 0 bytes .../d6/c93164c249c8000205dd4ec5cbca1b516d487f | Bin 21 -> 0 bytes .../d7/1aab4f9b04b45ce09bcaa636a9be6231474759 | Bin 79 -> 0 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 15 -> 0 bytes .../e7/b4ad382349ff96dd8199000580b9b1e2042eb0 | Bin 21 -> 0 bytes .../f1/425cef211cc08caa31e7b545ffb232acb098c3 | Bin 103 -> 0 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 82 -> 0 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 24 -> 0 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 82 -> 0 bytes .../fd/4959ce7510db09d4d8217fa2d1780413e05a09 | Bin 152 -> 0 bytes ...ck-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx | Bin 46656 -> 0 bytes ...k-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack | Bin 386089 -> 0 bytes ...ck-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx | Bin 1240 -> 0 bytes ...k-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack | Bin 491 -> 0 bytes ...ck-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx | Bin 1240 -> 0 bytes ...k-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack | Bin 498 -> 0 bytes tests-clar/resources/testrepo.git/packed-refs | 3 - tests-clar/resources/testrepo.git/refs/heads/br2 | 1 - .../resources/testrepo.git/refs/heads/cannot-fetch | 1 - .../resources/testrepo.git/refs/heads/chomped | 1 - .../resources/testrepo.git/refs/heads/haacked | 1 - .../resources/testrepo.git/refs/heads/master | 1 - .../resources/testrepo.git/refs/heads/not-good | 1 - .../resources/testrepo.git/refs/heads/packed-test | 1 - .../resources/testrepo.git/refs/heads/subtrees | 1 - tests-clar/resources/testrepo.git/refs/heads/test | 1 - .../resources/testrepo.git/refs/heads/track-local | 1 - .../resources/testrepo.git/refs/heads/trailing | 1 - .../resources/testrepo.git/refs/notes/fanout | 1 - .../testrepo.git/refs/remotes/test/master | 1 - .../testrepo.git/refs/tags/annotated_tag_to_blob | 1 - .../resources/testrepo.git/refs/tags/e90810b | 1 - .../resources/testrepo.git/refs/tags/hard_tag | 1 - .../resources/testrepo.git/refs/tags/point_to_blob | 1 - .../resources/testrepo.git/refs/tags/taggerless | 1 - tests-clar/resources/testrepo.git/refs/tags/test | 1 - .../resources/testrepo.git/refs/tags/wrapped_tag | 1 - tests-clar/resources/testrepo/.gitted/HEAD | 1 - tests-clar/resources/testrepo/.gitted/HEAD_TRACKER | 1 - tests-clar/resources/testrepo/.gitted/config | 8 - tests-clar/resources/testrepo/.gitted/index | Bin 10041 -> 0 bytes .../09/9fabac3a9ea935598528c27f866e34089c2eff | 1 - .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 19 -> 0 bytes .../14/4344043ba4d4a405da03de3844aa829ae8be0e | Bin 163 -> 0 bytes .../16/8e4ebd1c667499548ae12403b19b22a5c5e925 | Bin 147 -> 0 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 51 -> 0 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 119 -> 0 bytes .../1f/67fc4386b2d171e0d21be1c447e12660561f9b | Bin 21 -> 0 bytes .../27/0b8ea76056d5cad83af921837702d3e3c2924d | Bin 21 -> 0 bytes .../32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 | Bin 50 -> 0 bytes .../36/97d64be941a53d4ae8f6a271e4e3fa56b022cc | Bin 23 -> 0 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 18 -> 0 bytes .../45/dd856fdd4d89b884c340ba0e047752d9b085d6 | Bin 156 -> 0 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 - .../4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 | Bin 50 -> 0 bytes .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 - .../62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc | Bin 50 -> 0 bytes .../66/3adb09143767984f7be83a91effa47e128c735 | Bin 19 -> 0 bytes .../6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 | Bin 167 -> 0 bytes .../6b/9b767af9992b4abad5e24ffb1ba2d688ca602e | Bin 41 -> 0 bytes .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 119 -> 0 bytes .../76/3d71aadf09a7951596c9746c024e7eece7c7af | 1 - .../7b/2417a23b63e1fdde88c80e14b33247c6e5785a | Bin 187 -> 0 bytes .../7b/4384978d2493e851f9cca7858815fac9b10980 | Bin 145 -> 0 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 82 -> 0 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 126 -> 0 bytes .../87/380ae84009e9c503506c2f6143a4fc6c60bf80 | Bin 161 -> 0 bytes .../94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 | 1 - .../9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 | Bin 50 -> 0 bytes .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 - .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 - .../a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 | 3 - .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 28 -> 0 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 26 -> 0 bytes .../ae/90f12eea699729ed24555e40b9fd669da12a12 | Bin 148 -> 0 bytes .../b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 | 2 - .../b6/361fc6a97178d8fc8639fdeed71c775ab52593 | Bin 80 -> 0 bytes .../be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 | 3 - .../c0/528fd6cc988c0a40ce0be11bc192fc8dc5346e | Bin 22 -> 0 bytes .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 - .../cf/80f8de9f1185bf3a05f993f6121880dd0cfbc9 | Bin 162 -> 0 bytes .../d5/2a8fe84ceedf260afe4f0287bbfca04a117e83 | Bin 147 -> 0 bytes .../d6/c93164c249c8000205dd4ec5cbca1b516d487f | Bin 21 -> 0 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 15 -> 0 bytes .../e7/b4ad382349ff96dd8199000580b9b1e2042eb0 | Bin 21 -> 0 bytes .../f1/425cef211cc08caa31e7b545ffb232acb098c3 | Bin 103 -> 0 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 82 -> 0 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 24 -> 0 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 82 -> 0 bytes ...ck-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx | Bin 46656 -> 0 bytes ...k-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack | Bin 386089 -> 0 bytes ...ck-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx | Bin 1240 -> 0 bytes ...k-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack | Bin 491 -> 0 bytes ...ck-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx | Bin 1240 -> 0 bytes ...k-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack | Bin 498 -> 0 bytes tests-clar/resources/testrepo/.gitted/packed-refs | 4 - .../resources/testrepo/.gitted/refs/heads/br2 | 1 - .../resources/testrepo/.gitted/refs/heads/dir | 1 - .../testrepo/.gitted/refs/heads/long-file-name | 1 - .../resources/testrepo/.gitted/refs/heads/master | 1 - .../testrepo/.gitted/refs/heads/packed-test | 1 - .../resources/testrepo/.gitted/refs/heads/subtrees | 1 - .../resources/testrepo/.gitted/refs/heads/test | 1 - .../resources/testrepo/.gitted/refs/tags/e90810b | 1 - .../resources/testrepo/.gitted/refs/tags/foo/bar | 1 - .../testrepo/.gitted/refs/tags/foo/foo/bar | 1 - .../testrepo/.gitted/refs/tags/point_to_blob | 1 - .../resources/testrepo/.gitted/refs/tags/test | 1 - tests-clar/resources/testrepo2/.gitted/HEAD | 1 - tests-clar/resources/testrepo2/.gitted/config | 14 - tests-clar/resources/testrepo2/.gitted/description | 1 - tests-clar/resources/testrepo2/.gitted/index | Bin 512 -> 0 bytes .../resources/testrepo2/.gitted/info/exclude | 6 - tests-clar/resources/testrepo2/.gitted/logs/HEAD | 1 - .../testrepo2/.gitted/logs/refs/heads/master | 1 - .../.gitted/logs/refs/remotes/origin/HEAD | 1 - .../0c/37a5391bbff43c37f0d0371823a5509eed5b1d | Bin 134 -> 0 bytes .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 19 -> 0 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 51 -> 0 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 119 -> 0 bytes .../2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 | Bin 125 -> 0 bytes .../36/060c58702ed4c2a40832c51758d5344201d89a | 2 - .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 18 -> 0 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 - .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 - .../61/9f9935957e010c419cb9d15621916ddfcc0b96 | Bin 116 -> 0 bytes .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 119 -> 0 bytes .../7f/043268ea43ce18e3540acaabf9e090c91965b0 | Bin 55 -> 0 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 82 -> 0 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 126 -> 0 bytes .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 - .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 - .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 28 -> 0 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 26 -> 0 bytes .../be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 | 3 - .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 - .../c4/dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b | Bin 116 -> 0 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 15 -> 0 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 82 -> 0 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 24 -> 0 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 82 -> 0 bytes ...ck-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx | Bin 1240 -> 0 bytes ...k-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack | Bin 491 -> 0 bytes tests-clar/resources/testrepo2/.gitted/packed-refs | 6 - .../resources/testrepo2/.gitted/refs/heads/master | 1 - .../testrepo2/.gitted/refs/remotes/origin/HEAD | 1 - tests-clar/resources/testrepo2/README | 1 - tests-clar/resources/testrepo2/new.txt | 1 - tests-clar/resources/testrepo2/subdir/README | 1 - tests-clar/resources/testrepo2/subdir/new.txt | 1 - .../resources/testrepo2/subdir/subdir2/README | 1 - .../resources/testrepo2/subdir/subdir2/new.txt | 1 - tests-clar/resources/twowaymerge.git/HEAD | 1 - tests-clar/resources/twowaymerge.git/config | 5 - tests-clar/resources/twowaymerge.git/description | 1 - tests-clar/resources/twowaymerge.git/info/exclude | 6 - .../0c/8a3f1f3d5f421cf83048c7c73ee3b55a5e0f29 | Bin 157 -> 0 bytes .../10/2dce8e3081f398e4bdd9fd894dc85ac3ca6a67 | Bin 54 -> 0 bytes .../17/7d8634a28e26ec7819284752757ebe01a479d5 | Bin 80 -> 0 bytes .../1c/30b88f5f3ee66d78df6520a7de9e89b890818b | 3 - .../1f/4c0311a24b63f6fc209a59a1e404942d4a5006 | 2 - .../22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 | 3 - .../29/6e56023cdc034d2735fee8c0d85a659d1b07f4 | Bin 51 -> 0 bytes .../31/51880ae2b363f1c262cf98b750c1f169a0d432 | Bin 68 -> 0 bytes .../3b/287f8730c81d0b763c2d294618a5e32b67b4f8 | Bin 54 -> 0 bytes .../42/b7311aa626e712891940c1ec5d5cba201946a4 | 3 - .../49/6d6428b9cf92981dc9495211e6e1120fb6f2ba | Bin 46 -> 0 bytes .../59/b0cf7d74659e1cdb13305319d6d4ce2733c118 | Bin 65 -> 0 bytes .../6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f | 1 - .../6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 | Bin 68 -> 0 bytes .../76/5b32c65d38f04c4f287abda055818ec0f26912 | Bin 54 -> 0 bytes .../7b/8c336c45fc6895c1c60827260fe5d798e5d247 | 3 - .../82/bf9a1a10a4b25c1f14c9607b60970705e92545 | 1 - .../8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 | 3 - .../9a/40a2f11c191f180c47e54b11567cb3c1e89b30 | Bin 62 -> 0 bytes .../9b/219343610c88a1187c996d0dc58330b55cee28 | 2 - .../9f/e06a50f4d1634d6c6879854d01d80857388706 | Bin 65 -> 0 bytes .../a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 | 3 - .../a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 | 1 - .../a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c | 1 - .../bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 | Bin 158 -> 0 bytes .../c3/7a783c20d92ac92362a78a32860f7eebf938ef | Bin 158 -> 0 bytes .../cb/dd40facab1682754eb67f7a43f29e672903cf6 | Bin 51 -> 0 bytes .../cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 | Bin 158 -> 0 bytes .../d6/f10d549cb335b9e6d38afc1f0088be69b50494 | Bin 62 -> 0 bytes .../d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e | 1 - .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 15 -> 0 bytes .../ef/0488f0b722f0be8bcb90a7730ac7efafd1d694 | 1 - .../fc/f7e3f51c11d199ab7a78403ee4f9ccd028da25 | Bin 62 -> 0 bytes .../twowaymerge.git/refs/heads/first-branch | 1 - .../resources/twowaymerge.git/refs/heads/master | 1 - .../twowaymerge.git/refs/heads/second-branch | 1 - tests-clar/resources/typechanges/.gitted/HEAD | 1 - tests-clar/resources/typechanges/.gitted/config | 12 - .../resources/typechanges/.gitted/description | 1 - tests-clar/resources/typechanges/.gitted/index | Bin 184 -> 0 bytes .../resources/typechanges/.gitted/info/exclude | 6 - .../resources/typechanges/.gitted/modules/b/HEAD | 1 - .../resources/typechanges/.gitted/modules/b/config | 13 - .../typechanges/.gitted/modules/b/description | 1 - .../resources/typechanges/.gitted/modules/b/index | Bin 192 -> 0 bytes .../typechanges/.gitted/modules/b/info/exclude | 6 - .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 55 -> 0 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 53 -> 0 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 93 -> 0 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 163 -> 0 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 163 -> 0 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 167 -> 0 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 - .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 93 -> 0 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 - .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 - .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 81 -> 0 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 93 -> 0 bytes .../typechanges/.gitted/modules/b/packed-refs | 2 - .../.gitted/modules/b/refs/heads/master | 1 - .../.gitted/modules/b/refs/remotes/origin/HEAD | 1 - .../resources/typechanges/.gitted/modules/d/HEAD | 1 - .../resources/typechanges/.gitted/modules/d/config | 13 - .../typechanges/.gitted/modules/d/description | 1 - .../resources/typechanges/.gitted/modules/d/index | Bin 192 -> 0 bytes .../typechanges/.gitted/modules/d/info/exclude | 6 - .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 55 -> 0 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 53 -> 0 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 93 -> 0 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 163 -> 0 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 163 -> 0 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 167 -> 0 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 - .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 93 -> 0 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 - .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 - .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 81 -> 0 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 93 -> 0 bytes .../typechanges/.gitted/modules/d/packed-refs | 2 - .../.gitted/modules/d/refs/heads/master | 1 - .../.gitted/modules/d/refs/remotes/origin/HEAD | 1 - .../resources/typechanges/.gitted/modules/e/HEAD | 1 - .../resources/typechanges/.gitted/modules/e/config | 13 - .../typechanges/.gitted/modules/e/description | 1 - .../resources/typechanges/.gitted/modules/e/index | Bin 192 -> 0 bytes .../typechanges/.gitted/modules/e/info/exclude | 6 - .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 55 -> 0 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 53 -> 0 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 93 -> 0 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 163 -> 0 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 163 -> 0 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 167 -> 0 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 - .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 93 -> 0 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 - .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 - .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 81 -> 0 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 93 -> 0 bytes .../typechanges/.gitted/modules/e/packed-refs | 2 - .../.gitted/modules/e/refs/heads/master | 1 - .../.gitted/modules/e/refs/remotes/origin/HEAD | 1 - .../0d/78578795b7ca49fd8df6c4b6d27c5c02d991d8 | Bin 76 -> 0 bytes .../0e/7ed140b514b8cae23254cb8656fe1674403aff | Bin 162 -> 0 bytes .../0f/f461da9689266f482d8f6654a4400b4e33c586 | Bin 486 -> 0 bytes .../18/aa7e45bbe4c3cc24a0b079696c59d36675af97 | Bin 89 -> 0 bytes .../1b/63caae4a5ca96f78e8dfefc376c6a39a142475 | Bin 161 -> 0 bytes .../1e/abe82aa3b2365a394f6108f24435df6e193d02 | Bin 549 -> 0 bytes .../42/061c01a1c70097d1e4579f29a5adf40abdec95 | Bin 24 -> 0 bytes .../46/2838cee476a87e7cff32196b66fa18ed756592 | Bin 76 -> 0 bytes .../63/499e4ea8e096b831515ceb1d5a7593e4d87ae5 | Bin 18 -> 0 bytes .../68/1af94e10eaf262f3ab7cb9b8fd5f4158ba4d3e | Bin 24 -> 0 bytes .../6a/9008602b811e69a9b7a2d83496f39a794fdeeb | Bin 602 -> 0 bytes .../6e/ae26c90e8ccc4d16208972119c40635489c6f0 | Bin 160 -> 0 bytes .../6f/39eabbb8a7541515e0d35971078bccb502e7e0 | Bin 66 -> 0 bytes .../71/54d3083461536dfc71ad5542f3e65e723a06c4 | Bin 657 -> 0 bytes .../75/56c1d893a4c0ca85ac8ac51de47ff399758729 | Bin 226 -> 0 bytes .../76/fef844064c26d5e06c2508240dae661e7231b2 | Bin 66 -> 0 bytes .../79/b9f23e85f55ea36a472a902e875bc1121a94cb | 2 - .../85/28da0ea65eacf1f74f9ed6696adbac547963ad | Bin 451 -> 0 bytes .../8b/3726b365824ad5a07c537247f4bc73ed7d37ea | Bin 76 -> 0 bytes .../93/3e28c1c8a68838a763d250bdf0b2c6068289c3 | Bin 226 -> 0 bytes .../96/2710fe5b4e453e9e827945b3487c525968ec4a | Bin 76 -> 0 bytes .../96/6cf1b3598e195b31b2cde3784f9a19f0728a6f | Bin 226 -> 0 bytes .../99/e8bab9ece009f0fba7eb41f850f4c12bedb9b7 | Bin 701 -> 0 bytes .../9b/19edf33a03a0c59cdfc113bfa5c06179bf9b1a | 5 - .../9b/db75b73836a99e3dbeea640a81de81031fdc29 | Bin 162 -> 0 bytes .../9d/0235c7a7edc0889a18f97a42ee6db9fe688447 | Bin 160 -> 0 bytes .../9e/ffc457877f109b2a4319e14bee613a15f2a00d | Bin 226 -> 0 bytes .../a0/a9bad6f6f40325198f938a0e3ae981622d7707 | Bin 54 -> 0 bytes .../b1/977dc4e573b812d4619754c98138c56999dc0d | Bin 518 -> 0 bytes .../d7/5992dd02391e128dac332dcc78d649dd9ab095 | Bin 577 -> 0 bytes .../da/e2709d638df52212b1f43ff61797ebfedfcc7c | Bin 78 -> 0 bytes .../e1/152adcb9adf37ec551ada9ba377ab53aec3bad | Bin 19 -> 0 bytes .../e4/ed436a9eb0f198cda722886a5f8d6d6c836b7b | Bin 225 -> 0 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 15 -> 0 bytes .../f2/0b79342712e0b2315647cd8227a573fd3bc46e | Bin 66 -> 0 bytes .../fd/e0147e3b59f381635a3b016e3fe6dacb70779d | Bin 53 -> 0 bytes .../typechanges/.gitted/refs/heads/master | 1 - tests-clar/resources/typechanges/README.md | 43 - tests-clar/resources/typechanges/gitmodules | 0 tests-clar/resources/unsymlinked.git/HEAD | 1 - tests-clar/resources/unsymlinked.git/config | 6 - tests-clar/resources/unsymlinked.git/description | 1 - tests-clar/resources/unsymlinked.git/info/exclude | 2 - .../08/8b64704e0d6b8bd061dea879418cb5442a3fbf | Bin 49 -> 0 bytes .../13/a5e939bca25940c069fd2169d993dba328e30b | Bin 44 -> 0 bytes .../19/bf568e59e3a0b363cafb4106226e62d4a4c41c | Bin 29 -> 0 bytes .../58/1fadd35b4cf320d102a152f918729011604773 | Bin 47 -> 0 bytes .../5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c | Bin 78 -> 0 bytes .../6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 | Bin 49 -> 0 bytes .../7f/ccd75616ec188b8f1b23d67506a334cc34a49d | Bin 132 -> 0 bytes .../80/6999882bf91d24241e4077906b9017605eb1f3 | Bin 170 -> 0 bytes .../83/7d176303c5005505ec1e4a30231c40930c0230 | Bin 44 -> 0 bytes .../a8/595ccca04f40818ae0155c8f9c77a230e597b6 | 2 - .../cf/8f1cf5cce859c438d6cc067284cb5e161206e7 | Bin 49 -> 0 bytes .../d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a | Bin 49 -> 0 bytes .../f4/e16fb76536591a41454194058d048d8e4dd2e9 | Bin 44 -> 0 bytes .../f9/e65619d93fdf2673882e0a261c5e93b1a84006 | Bin 32 -> 0 bytes .../resources/unsymlinked.git/refs/heads/exe-file | 1 - .../resources/unsymlinked.git/refs/heads/master | 1 - .../resources/unsymlinked.git/refs/heads/reg-file | 1 - tests-clar/revwalk/basic.c | 254 ---- tests-clar/revwalk/mergebase.c | 392 ----- tests-clar/revwalk/signatureparsing.c | 47 - tests-clar/revwalk/simplify.c | 55 - tests-clar/stash/drop.c | 174 --- tests-clar/stash/foreach.c | 124 -- tests-clar/stash/save.c | 354 ----- tests-clar/stash/stash_helpers.c | 56 - tests-clar/stash/stash_helpers.h | 8 - tests-clar/stash/submodules.c | 80 -- tests-clar/status/ignore.c | 582 -------- tests-clar/status/renames.c | 557 -------- tests-clar/status/single.c | 45 - tests-clar/status/status_data.h | 326 ----- tests-clar/status/status_helpers.c | 101 -- tests-clar/status/status_helpers.h | 39 - tests-clar/status/submodules.c | 223 --- tests-clar/status/worktree.c | 875 ------------ tests-clar/status/worktree_init.c | 341 ----- tests-clar/stress/diff.c | 146 -- tests-clar/submodule/lookup.c | 172 --- tests-clar/submodule/modify.c | 253 ---- tests-clar/submodule/status.c | 425 ------ tests-clar/submodule/submodule_helpers.c | 127 -- tests-clar/submodule/submodule_helpers.h | 5 - tests-clar/threads/basic.c | 36 - tests-clar/threads/refdb.c | 213 --- tests-clar/trace/trace.c | 87 -- tests-clar/valgrind-supp-mac.txt | 184 --- tests/README.md | 22 + tests/attr/attr_expect.h | 43 + tests/attr/file.c | 224 +++ tests/attr/flags.c | 108 ++ tests/attr/ignore.c | 102 ++ tests/attr/lookup.c | 262 ++++ tests/attr/repo.c | 310 ++++ tests/blame/blame_helpers.c | 64 + tests/blame/blame_helpers.h | 16 + tests/blame/buffer.c | 166 +++ tests/blame/getters.c | 56 + tests/blame/harder.c | 71 + tests/blame/simple.c | 305 ++++ tests/buf/basic.c | 29 + tests/buf/splice.c | 93 ++ tests/checkout/binaryunicode.c | 58 + tests/checkout/checkout_helpers.c | 130 ++ tests/checkout/checkout_helpers.h | 29 + tests/checkout/conflict.c | 1127 +++++++++++++++ tests/checkout/crlf.c | 231 +++ tests/checkout/head.c | 62 + tests/checkout/index.c | 620 ++++++++ tests/checkout/tree.c | 742 ++++++++++ tests/checkout/typechange.c | 240 ++++ tests/clar.c | 511 +++++++ tests/clar.h | 95 ++ tests/clar/fixtures.h | 38 + tests/clar/fs.h | 325 +++++ tests/clar/print.h | 60 + tests/clar/sandbox.h | 129 ++ tests/clar_libgit2.c | 483 +++++++ tests/clar_libgit2.h | 119 ++ tests/clone/empty.c | 85 ++ tests/clone/nonetwork.c | 179 +++ tests/commit/commit.c | 46 + tests/commit/parent.c | 60 + tests/commit/parse.c | 413 ++++++ tests/commit/signature.c | 81 ++ tests/commit/write.c | 147 ++ tests/config/add.c | 37 + tests/config/backend.c | 24 + tests/config/config_helpers.c | 37 + tests/config/config_helpers.h | 9 + tests/config/configlevel.c | 71 + tests/config/global.c | 72 + tests/config/include.c | 109 ++ tests/config/multivar.c | 288 ++++ tests/config/new.c | 32 + tests/config/read.c | 569 ++++++++ tests/config/refresh.c | 67 + tests/config/stress.c | 92 ++ tests/config/validkeyname.c | 68 + tests/config/write.c | 305 ++++ tests/core/bitvec.c | 64 + tests/core/buffer.c | 1039 ++++++++++++++ tests/core/caps.c | 31 + tests/core/copy.c | 126 ++ tests/core/dirent.c | 236 ++++ tests/core/env.c | 303 ++++ tests/core/errors.c | 87 ++ tests/core/filebuf.c | 126 ++ tests/core/hex.c | 22 + tests/core/iconv.c | 68 + tests/core/mkdir.c | 188 +++ tests/core/oid.c | 70 + tests/core/oidmap.c | 110 ++ tests/core/opts.c | 19 + tests/core/path.c | 583 ++++++++ tests/core/pool.c | 145 ++ tests/core/posix.c | 99 ++ tests/core/rmdir.c | 98 ++ tests/core/sortedcache.c | 363 +++++ tests/core/stat.c | 97 ++ tests/core/string.c | 41 + tests/core/strmap.c | 102 ++ tests/core/strtol.c | 37 + tests/core/vector.c | 275 ++++ tests/date/date.c | 15 + tests/diff/blob.c | 1067 ++++++++++++++ tests/diff/diff_helpers.c | 246 ++++ tests/diff/diff_helpers.h | 64 + tests/diff/diffiter.c | 453 ++++++ tests/diff/drivers.c | 163 +++ tests/diff/index.c | 167 +++ tests/diff/iterator.c | 937 ++++++++++++ tests/diff/notify.c | 228 +++ tests/diff/patch.c | 571 ++++++++ tests/diff/pathspec.c | 93 ++ tests/diff/rename.c | 1286 +++++++++++++++++ tests/diff/submodules.c | 423 ++++++ tests/diff/tree.c | 526 +++++++ tests/diff/workdir.c | 1490 ++++++++++++++++++++ tests/fetchhead/fetchhead_data.h | 31 + tests/fetchhead/nonetwork.c | 309 ++++ tests/filter/blob.c | 84 ++ tests/filter/crlf.c | 71 + tests/filter/crlf.h | 25 + tests/filter/custom.c | 337 +++++ tests/filter/ident.c | 131 ++ tests/generate.py | 244 ++++ tests/index/addall.c | 258 ++++ tests/index/conflicts.c | 287 ++++ tests/index/filemodes.c | 154 ++ tests/index/inmemory.c | 22 + tests/index/names.c | 148 ++ tests/index/read_tree.c | 46 + tests/index/rename.c | 50 + tests/index/reuc.c | 372 +++++ tests/index/stage.c | 62 + tests/index/tests.c | 537 +++++++ tests/main.c | 20 + tests/merge/merge_helpers.c | 333 +++++ tests/merge/merge_helpers.h | 62 + tests/merge/trees/automerge.c | 217 +++ tests/merge/trees/modeconflict.c | 59 + tests/merge/trees/renames.c | 252 ++++ tests/merge/trees/treediff.c | 542 +++++++ tests/merge/trees/trivial.c | 397 ++++++ tests/merge/workdir/fastforward.c | 148 ++ tests/merge/workdir/renames.c | 156 ++ tests/merge/workdir/setup.c | 1057 ++++++++++++++ tests/merge/workdir/simple.c | 491 +++++++ tests/merge/workdir/trivial.c | 341 +++++ tests/network/cred.c | 50 + tests/network/fetchlocal.c | 88 ++ tests/network/refspecs.c | 87 ++ tests/network/remote/createthenload.c | 37 + tests/network/remote/isvalidname.c | 17 + tests/network/remote/local.c | 234 +++ tests/network/remote/remotes.c | 510 +++++++ tests/network/remote/rename.c | 174 +++ tests/network/urlparse.c | 193 +++ tests/notes/notes.c | 387 +++++ tests/notes/notesref.c | 64 + tests/object/blob/filter.c | 143 ++ tests/object/blob/fromchunks.c | 119 ++ tests/object/blob/write.c | 69 + tests/object/cache.c | 287 ++++ tests/object/commit/commitstagedfile.c | 132 ++ tests/object/lookup.c | 65 + tests/object/lookupbypath.c | 83 ++ tests/object/message.c | 236 ++++ tests/object/peel.c | 105 ++ tests/object/raw/chars.c | 41 + tests/object/raw/compare.c | 124 ++ tests/object/raw/convert.c | 112 ++ tests/object/raw/data.h | 323 +++++ tests/object/raw/fromstr.c | 30 + tests/object/raw/hash.c | 166 +++ tests/object/raw/short.c | 137 ++ tests/object/raw/size.c | 13 + tests/object/raw/type2string.c | 54 + tests/object/raw/write.c | 462 ++++++ tests/object/tag/list.c | 115 ++ tests/object/tag/peel.c | 61 + tests/object/tag/read.c | 142 ++ tests/object/tag/write.c | 260 ++++ tests/object/tree/attributes.c | 115 ++ tests/object/tree/duplicateentries.c | 157 +++ tests/object/tree/frompath.c | 68 + tests/object/tree/read.c | 75 + tests/object/tree/walk.c | 177 +++ tests/object/tree/write.c | 262 ++++ tests/odb/alternates.c | 80 ++ tests/odb/backend/nonrefreshing.c | 274 ++++ tests/odb/foreach.c | 80 ++ tests/odb/loose.c | 146 ++ tests/odb/loose_data.h | 522 +++++++ tests/odb/mixed.c | 93 ++ tests/odb/pack_data.h | 151 ++ tests/odb/pack_data_one.h | 19 + tests/odb/packed.c | 79 ++ tests/odb/packed_one.c | 60 + tests/odb/sorting.c | 69 + tests/odb/streamwrite.c | 56 + tests/online/clone.c | 256 ++++ tests/online/fetch.c | 171 +++ tests/online/fetchhead.c | 91 ++ tests/online/push.c | 770 ++++++++++ tests/online/push_util.c | 132 ++ tests/online/push_util.h | 71 + tests/pack/indexer.c | 126 ++ tests/pack/packbuilder.c | 204 +++ tests/refs/branches/create.c | 76 + tests/refs/branches/delete.c | 117 ++ tests/refs/branches/ishead.c | 116 ++ tests/refs/branches/iterator.c | 151 ++ tests/refs/branches/lookup.c | 45 + tests/refs/branches/move.c | 146 ++ tests/refs/branches/name.c | 45 + tests/refs/branches/remote.c | 86 ++ tests/refs/branches/upstream.c | 143 ++ tests/refs/branches/upstreamname.c | 42 + tests/refs/crashes.c | 20 + tests/refs/create.c | 168 +++ tests/refs/delete.c | 93 ++ tests/refs/foreachglob.c | 95 ++ tests/refs/isvalidname.c | 31 + tests/refs/iterator.c | 97 ++ tests/refs/list.c | 57 + tests/refs/listall.c | 47 + tests/refs/lookup.c | 60 + tests/refs/normalize.c | 403 ++++++ tests/refs/overwrite.c | 136 ++ tests/refs/pack.c | 105 ++ tests/refs/peel.c | 119 ++ tests/refs/read.c | 284 ++++ tests/refs/ref_helpers.c | 25 + tests/refs/ref_helpers.h | 1 + tests/refs/reflog/drop.c | 115 ++ tests/refs/reflog/reflog.c | 209 +++ tests/refs/rename.c | 367 +++++ tests/refs/revparse.c | 813 +++++++++++ tests/refs/setter.c | 99 ++ tests/refs/shorthand.c | 27 + tests/refs/unicode.c | 56 + tests/refs/update.c | 26 + tests/repo/config.c | 208 +++ tests/repo/discover.c | 142 ++ tests/repo/getters.c | 40 + tests/repo/hashfile.c | 85 ++ tests/repo/head.c | 196 +++ tests/repo/headtree.c | 53 + tests/repo/init.c | 606 ++++++++ tests/repo/iterator.c | 962 +++++++++++++ tests/repo/message.c | 52 + tests/repo/open.c | 376 +++++ tests/repo/pathspec.c | 385 +++++ tests/repo/repo_helpers.c | 22 + tests/repo/repo_helpers.h | 6 + tests/repo/setters.c | 107 ++ tests/repo/shallow.c | 33 + tests/repo/state.c | 96 ++ tests/reset/default.c | 180 +++ tests/reset/hard.c | 200 +++ tests/reset/mixed.c | 49 + tests/reset/reset_helpers.c | 10 + tests/reset/reset_helpers.h | 6 + tests/reset/soft.c | 157 +++ tests/resources/.gitattributes | 1 + tests/resources/.gitignore | 1 + tests/resources/attr/.gitted/HEAD | 1 + tests/resources/attr/.gitted/config | 6 + tests/resources/attr/.gitted/description | 1 + tests/resources/attr/.gitted/index | Bin 0 -> 1856 bytes tests/resources/attr/.gitted/info/attributes | 4 + tests/resources/attr/.gitted/info/exclude | 6 + tests/resources/attr/.gitted/logs/HEAD | 9 + .../resources/attr/.gitted/logs/refs/heads/master | 9 + .../10/8bb4e7fd7b16490dc33ff7d972151e73d7166e | Bin 0 -> 130 bytes .../16/983da6643656bb44c43965ecb6855c6d574512 | Bin 0 -> 446 bytes .../21/7878ab49e1314388ea2e32dc6fdb58a1b969e0 | 4 + .../24/fa9a9fc4e202313e24b648087495441dab432b | Bin 0 -> 180 bytes .../29/29de282ce999e95183aedac6451d3384559c4b | Bin 0 -> 58 bytes .../2b/40c5aca159b04ea8d20ffe36cdf8b09369b14a | 1 + .../2c/66e14f77196ea763fb1e41612c1aa2bc2d8ed2 | Bin 0 -> 316 bytes .../2d/e7dfe3588f3c7e9ad59e7d50ba90e3329df9d9 | Bin 0 -> 124 bytes .../37/0fe9ec224ce33e71f9e5ec2bd1142ce9937a6a | Bin 0 -> 177 bytes .../3a/6df026462ebafe455af9867d27eda20a9e0974 | Bin 0 -> 84 bytes .../3b/74db7ab381105dc0d28f8295a77f6a82989292 | Bin 0 -> 276 bytes .../3e/42ffc54a663f9401cc25843d6c0e71a33e4249 | Bin 0 -> 596 bytes .../45/141a79a77842c59a63229403220a4e4be74e3d | Bin 0 -> 36 bytes .../45/5a314fa848d52ae1f11d254da4f60858fc97f4 | Bin 0 -> 446 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 0 -> 18 bytes .../4d/713dc48e6b1bd75b0d61ad078ba9ca3a56745d | 2 + .../4e/49ba8c5b6c32ff28cd9dcb60be34df50fcc485 | Bin 0 -> 81 bytes .../55/6f8c827b8e4a02ad5cab77dca2bcb3e226b0b3 | Bin 0 -> 24 bytes .../58/19a185d77b03325aaf87cafc771db36f6ddca7 | Bin 0 -> 19 bytes .../60/5812ab7fe421fdd325a935d35cb06a9234a7d7 | 2 + .../6b/ab5c79cd5140d0f800917f550eb2a3dc32b0da | 3 + .../6d/968d62c89c7d9ea23a4c9a7b665d017c3d8ffd | Bin 0 -> 422 bytes .../71/7fc31f6b84f9d6fc3a4edbca259d7fc92beee2 | Bin 0 -> 422 bytes .../8d/0b9df9bd30be7910ddda60548d485bc302b911 | 1 + .../93/61f40bb97239cf55811892e14de2e344168ba1 | Bin 0 -> 45 bytes .../94/da4faa0a6bfb8ee6ccf7153801a69202b31857 | Bin 0 -> 124 bytes .../96/089fd31ce1d3ee2afb0ba09ba063066932f027 | Bin 0 -> 422 bytes .../99/eae476896f4907224978b88e5ecaa6c5bb67a9 | Bin 0 -> 95 bytes .../9e/5bdc47d6a80f2be0ea3049ad74231b94609242 | Bin 0 -> 20 bytes .../9f/b40b6675dde60b5697afceae91b66d908c02d9 | Bin 0 -> 151 bytes .../a0/f7217ae99f5ac3e88534f5cea267febc5fa85b | 1 + .../a5/6bbcecaeac760cc26239384d2d4c614e7e4320 | Bin 0 -> 351 bytes .../a5/d76cad53f66f1312bd995909a5bab3c0820770 | 4 + .../a9/7cc019851d401a4f1d091cb91a15890a0dd1ba | 2 + .../b4/35cd5689a0fb54afbeda4ac20368aa480e8f04 | Bin 0 -> 40 bytes .../c0/091889c0c77142b87a1fa5123a6398a61d33e7 | Bin 0 -> 290 bytes .../c4/85abe35abd4aa6fd83b076a78bbea9e2e7e06c | Bin 0 -> 129 bytes .../c7/aadd770d5907a8475c29e9ee21a27b88bf675d | Bin 0 -> 60 bytes .../c9/6bbb2c2557a8325ae1559e3ba79cdcecb23076 | 2 + .../ce/39a97a7fb1fa90bcf5e711249c1e507476ae0e | Bin 0 -> 446 bytes .../d5/7da33c16b14326ecb05d19bbea908f5e4c47d9 | Bin 0 -> 379 bytes .../d8/00886d9c86731ae5c4a62b0b77c437015e00d2 | Bin 0 -> 18 bytes .../dc/cada462d3df8ac6de596fb8c896aba9344f941 | Bin 0 -> 35 bytes .../de/863bff4976c9ed7e17a4da0fd524908dc84049 | Bin 0 -> 4115 bytes .../e5/63cf4758f0d646f1b14b76016aa17fa9e549a4 | Bin 0 -> 39 bytes .../ec/b97df2a174987475ac816e3847fc8e9f6c596b | Bin 0 -> 171 bytes .../ed/f3dcee4003d71f139777898882ccd097e34c53 | Bin 0 -> 6289 bytes .../f2/c6d717cf4a5a3e6b02684155ab07b766982165 | Bin 0 -> 44 bytes .../f5/b0af1fb4f5c0cd7aad880711d368a07333c307 | 2 + .../fb/5067b1aef3ac1ada4b379dbcb7d17255df7d78 | Bin 0 -> 28 bytes .../fe/773770c5a6cc7185580c9204b1ff18a33ff3fc | 1 + .../ff/69f8639ce2e6010b3f33a74160aad98b48da2b | Bin 0 -> 18 bytes tests/resources/attr/.gitted/refs/heads/master | 1 + tests/resources/attr/attr0 | 1 + tests/resources/attr/attr1 | 29 + tests/resources/attr/attr2 | 21 + tests/resources/attr/attr3 | 4 + tests/resources/attr/binfile | 1 + tests/resources/attr/dir/file | 0 tests/resources/attr/file | 1 + tests/resources/attr/gitattributes | 29 + tests/resources/attr/gitignore | 2 + tests/resources/attr/ign | 1 + tests/resources/attr/macro_bad | 1 + tests/resources/attr/macro_test | 1 + tests/resources/attr/root_test1 | 1 + tests/resources/attr/root_test2 | 6 + tests/resources/attr/root_test3 | 19 + tests/resources/attr/root_test4.txt | 14 + tests/resources/attr/sub/.gitattributes | 7 + tests/resources/attr/sub/abc | 37 + tests/resources/attr/sub/dir/file | 0 tests/resources/attr/sub/file | 1 + tests/resources/attr/sub/ign/file | 1 + tests/resources/attr/sub/ign/sub/file | 1 + tests/resources/attr/sub/sub/.gitattributes | 3 + tests/resources/attr/sub/sub/dir | 0 tests/resources/attr/sub/sub/file | 1 + tests/resources/attr/sub/sub/subsub.txt | 1 + tests/resources/attr/sub/subdir_test1 | 2 + tests/resources/attr/sub/subdir_test2.txt | 1 + tests/resources/attr_index/.gitted/HEAD | 1 + tests/resources/attr_index/.gitted/config | 6 + tests/resources/attr_index/.gitted/description | 1 + tests/resources/attr_index/.gitted/index | Bin 0 -> 520 bytes tests/resources/attr_index/.gitted/info/exclude | 6 + tests/resources/attr_index/.gitted/info/refs | 1 + tests/resources/attr_index/.gitted/logs/HEAD | 4 + .../attr_index/.gitted/logs/refs/heads/master | 4 + .../38/12cfef36615db1788d4e63f90028007e17a348 | 3 + .../59/d942b8be2784bc96db9b22202c10815c9a077b | 1 + .../cd/f17ea3fe625ef812f4dce7f423f4f299287505 | Bin 0 -> 61 bytes .../f7/2502ddd01412bb20796ff812af56fd53b82b52 | Bin 0 -> 149 bytes .../attr_index/.gitted/objects/info/packs | 2 + ...ck-4e6438607204ce78827e3885594b2c0bb4f13895.idx | Bin 0 -> 1492 bytes ...k-4e6438607204ce78827e3885594b2c0bb4f13895.pack | Bin 0 -> 1106 bytes tests/resources/attr_index/.gitted/packed-refs | 2 + .../resources/attr_index/.gitted/refs/heads/master | 1 + tests/resources/attr_index/README.md | 1 + tests/resources/attr_index/README.txt | 1 + tests/resources/attr_index/gitattributes | 4 + tests/resources/attr_index/sub/sub/.gitattributes | 3 + tests/resources/attr_index/sub/sub/README.md | 1 + tests/resources/attr_index/sub/sub/README.txt | 1 + tests/resources/bad_tag.git/HEAD | 1 + tests/resources/bad_tag.git/config | 5 + ...ck-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.idx | Bin 0 -> 1268 bytes ...k-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.pack | Bin 0 -> 596 bytes tests/resources/bad_tag.git/packed-refs | 5 + tests/resources/bad_tag.git/refs/dummy-marker.txt | 0 tests/resources/big.index | Bin 0 -> 335272 bytes tests/resources/binaryunicode/.gitted/HEAD | 1 + tests/resources/binaryunicode/.gitted/config | 6 + tests/resources/binaryunicode/.gitted/description | 1 + tests/resources/binaryunicode/.gitted/index | Bin 0 -> 104 bytes tests/resources/binaryunicode/.gitted/info/exclude | 6 + tests/resources/binaryunicode/.gitted/info/refs | 3 + .../binaryunicode/.gitted/objects/info/packs | 2 + ...ck-c5bfca875b4995d7aba6e5abf36241f3c397327d.idx | Bin 0 -> 1380 bytes ...k-c5bfca875b4995d7aba6e5abf36241f3c397327d.pack | Bin 0 -> 20879 bytes .../binaryunicode/.gitted/refs/heads/branch1 | 1 + .../binaryunicode/.gitted/refs/heads/branch2 | 1 + .../binaryunicode/.gitted/refs/heads/master | 1 + tests/resources/binaryunicode/file.txt | 1 + tests/resources/blametest.git/HEAD | 1 + tests/resources/blametest.git/config | 5 + tests/resources/blametest.git/description | 1 + .../0c/bab4d45fd61e55a1c9697f9f9cb07a12e15448 | Bin 0 -> 46 bytes .../1a/ac69ae5d96461afc4d81d0066cb12f5b05a35b | Bin 0 -> 28 bytes .../1b/5f0775af166331c854bd8d1bca3450eaf2532a | Bin 0 -> 35 bytes .../48/2f2c370e35c2c314fc1f96db2beb33f955a26a | Bin 0 -> 35 bytes .../63/d671eb32d250e4a83766ebbc60e818c1e1e93a | 3 + .../63/eb57322e363e18d460da5ea8284f3cd2340b36 | Bin 0 -> 76 bytes .../8b/137891791fe96927ad78e64b0aad7bded08bdc | Bin 0 -> 16 bytes .../96/679d59cf9f74d69b3c920f258559b5e8c9a18a | Bin 0 -> 47 bytes .../98/89d6e5557761aa8e3607e80c874a6dc51ada7c | Bin 0 -> 43 bytes .../aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 | 1 + .../b1/76dfc3a4dc8734e4c579f77236a9c8d0a965d2 | Bin 0 -> 76 bytes .../b9/0bb887b7c03750ae6b352ffe76ab9d2e86ee7d | Bin 0 -> 56 bytes .../b9/9f7ac0b88909253d829554c14af488c3b0f3a5 | 2 + .../bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 | 3 + .../cf/e0e1e1e3ba18f149fd47f5e1aef6016b2260c3 | Bin 0 -> 76 bytes .../d0/67729932057cdb7527a833d6799c4ddc520640 | 1 + .../da/237394e6132d20d30f175b9b73c8638fddddda | 4 + .../e5/b41c1ea533f87388ab69b13baf0b5a562d6243 | Bin 0 -> 76 bytes .../ef/32df4d259143933715c74951f932d9892364d1 | Bin 0 -> 42 bytes tests/resources/blametest.git/refs/heads/master | 1 + tests/resources/config/.gitconfig | 3 + tests/resources/config/config-include | 2 + tests/resources/config/config-included | 2 + tests/resources/config/config0 | 7 + tests/resources/config/config1 | 5 + tests/resources/config/config10 | 1 + tests/resources/config/config11 | 5 + tests/resources/config/config12 | 7 + tests/resources/config/config13 | 2 + tests/resources/config/config14 | 4 + tests/resources/config/config15 | 3 + tests/resources/config/config16 | 3 + tests/resources/config/config17 | 3 + tests/resources/config/config18 | 5 + tests/resources/config/config19 | 5 + tests/resources/config/config2 | 5 + tests/resources/config/config20 | 11 + tests/resources/config/config3 | 3 + tests/resources/config/config4 | 5 + tests/resources/config/config5 | 9 + tests/resources/config/config6 | 5 + tests/resources/config/config7 | 5 + tests/resources/config/config8 | 0 tests/resources/config/config9 | 9 + tests/resources/crlf/.gitted/HEAD | 1 + tests/resources/crlf/.gitted/config | 0 .../04/de00b358f13389948756732158eaaaefa1448c | Bin 0 -> 28 bytes .../0a/a76e474d259bd7c13eb726a1396c381db55c88 | Bin 0 -> 27 bytes .../0d/06894e14df22e066763ae906e0ed3eb79c205f | Bin 0 -> 134 bytes .../0f/f5a53f19bfd2b5eea1ba550295c47515678987 | Bin 0 -> 29 bytes .../12/faf3c1ea55f572473cec9052fca468c3584ccb | 1 + .../38/1cfe630df902bc29271a202d3277981180e4a6 | Bin 0 -> 25 bytes .../79/9770d1cff46753a57db7a066159b5610da6e3a | Bin 0 -> 20 bytes .../7c/ce67e58173e2b01f7db124ceaabe3183d19c49 | Bin 0 -> 24 bytes .../a9/a2e8913c1dbe2812fac5e6b4e0a4bd5d0d5966 | 1 + .../ba/aa042ab2976f8264e467988e6112ee518ec62e | Bin 0 -> 159 bytes .../dc/88e3b917de821e25962bea7ec1f55c4ce2112c | Bin 0 -> 32 bytes .../ea/030d3c6cec212069eca698cabaa5b4550f1511 | Bin 0 -> 32 bytes .../fe/085d9ace90cc675b87df15e1aeed0c3a31407f | Bin 0 -> 139 bytes tests/resources/crlf/.gitted/refs/heads/master | 1 + tests/resources/crlf/.gitted/refs/heads/utf8 | 1 + tests/resources/deprecated-mode.git/HEAD | 1 + tests/resources/deprecated-mode.git/config | 6 + tests/resources/deprecated-mode.git/description | 1 + tests/resources/deprecated-mode.git/index | Bin 0 -> 112 bytes tests/resources/deprecated-mode.git/info/exclude | 2 + .../06/262edc257418e9987caf999f9a7a3e1547adff | Bin 0 -> 124 bytes .../08/10fb7818088ff5ac41ee49199b51473b1bd6c7 | Bin 0 -> 350 bytes .../1b/05fdaa881ee45b48cbaa5e9b037d667a47745e | Bin 0 -> 57 bytes .../3d/0970ec547fc41ef8a5882dde99c6adce65b021 | Bin 0 -> 29 bytes .../deprecated-mode.git/refs/heads/master | 1 + tests/resources/diff/.gitted/HEAD | 1 + tests/resources/diff/.gitted/config | 6 + tests/resources/diff/.gitted/description | 1 + tests/resources/diff/.gitted/index | Bin 0 -> 225 bytes tests/resources/diff/.gitted/info/exclude | 6 + tests/resources/diff/.gitted/logs/HEAD | 2 + .../resources/diff/.gitted/logs/refs/heads/master | 2 + .../29/ab7053bb4dde0298e03e2c179e890b7dd465a7 | Bin 0 -> 730 bytes .../3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847 | Bin 0 -> 1108 bytes .../54/6c735f16a3b44d9784075c2c0dab2ac9bf1989 | Bin 0 -> 1110 bytes .../7a/9e0b02e63179929fed24f0a3e0f19168114d10 | Bin 0 -> 160 bytes .../7b/808f723a8ca90df319682c221187235af76693 | Bin 0 -> 922 bytes .../88/789109439c1e1c3cd45224001edee5304ed53c | 1 + .../cb/8294e696339863df760b2ff5d1e275bee72455 | Bin 0 -> 86 bytes .../d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69 | 1 + tests/resources/diff/.gitted/refs/heads/master | 1 + tests/resources/diff/another.txt | 38 + tests/resources/diff/readme.txt | 36 + tests/resources/duplicate.git/COMMIT_EDITMSG | 1 + tests/resources/duplicate.git/HEAD | 1 + tests/resources/duplicate.git/config | 5 + tests/resources/duplicate.git/description | 1 + tests/resources/duplicate.git/index | Bin 0 -> 104 bytes tests/resources/duplicate.git/info/exclude | 6 + tests/resources/duplicate.git/info/refs | 1 + tests/resources/duplicate.git/logs/HEAD | 1 + .../resources/duplicate.git/logs/refs/heads/master | 1 + .../0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea | Bin 0 -> 22 bytes .../ce/013625030ba8dba906f756967f9e9ca394464a | Bin 0 -> 21 bytes tests/resources/duplicate.git/objects/info/packs | 3 + ...ck-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx | Bin 0 -> 1184 bytes ...k-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack | Bin 0 -> 249 bytes ...ck-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx | Bin 0 -> 1268 bytes ...k-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack | Bin 0 -> 369 bytes ...ck-e87994ad581c9af946de0eb890175c08cd005f38.idx | Bin 0 -> 1156 bytes ...k-e87994ad581c9af946de0eb890175c08cd005f38.pack | Bin 0 -> 213 bytes ...ck-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx | Bin 0 -> 1100 bytes ...k-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack | Bin 0 -> 47 bytes tests/resources/duplicate.git/packed-refs | 2 + .../duplicate.git/refs/heads/dummy-marker.txt | 1 + tests/resources/empty_bare.git/HEAD | 1 + tests/resources/empty_bare.git/config | 7 + tests/resources/empty_bare.git/description | 1 + tests/resources/empty_bare.git/info/exclude | 6 + .../empty_bare.git/objects/info/dummy-marker.txt | 0 .../empty_bare.git/objects/pack/dummy-marker.txt | 0 .../empty_bare.git/refs/heads/dummy-marker.txt | 0 .../empty_bare.git/refs/tags/dummy-marker.txt | 0 tests/resources/empty_standard_repo/.gitted/HEAD | 1 + tests/resources/empty_standard_repo/.gitted/config | 8 + .../empty_standard_repo/.gitted/description | 1 + .../empty_standard_repo/.gitted/info/exclude | 6 + .../.gitted/objects/info/dummy-marker.txt | 0 .../.gitted/objects/pack/dummy-marker.txt | 0 .../.gitted/refs/heads/dummy-marker.txt | 0 .../.gitted/refs/tags/dummy-marker.txt | 0 tests/resources/filemodes/.gitted/HEAD | 1 + tests/resources/filemodes/.gitted/config | 6 + tests/resources/filemodes/.gitted/description | 1 + tests/resources/filemodes/.gitted/index | Bin 0 -> 528 bytes tests/resources/filemodes/.gitted/info/exclude | 6 + tests/resources/filemodes/.gitted/logs/HEAD | 1 + .../filemodes/.gitted/logs/refs/heads/master | 1 + .../99/62c8453ba6f0cf8dac7c5dcc2fa2897fa9964a | Bin 0 -> 139 bytes .../a5/c5dd0fc6c313159a69b1d19d7f61a9f978e8f1 | Bin 0 -> 21 bytes .../e7/48d196331bcb20267eaaee4ff3326cb73b8182 | Bin 0 -> 99 bytes .../resources/filemodes/.gitted/refs/heads/master | 1 + tests/resources/filemodes/exec_off | 1 + tests/resources/filemodes/exec_off2on_staged | 1 + tests/resources/filemodes/exec_off2on_workdir | 1 + tests/resources/filemodes/exec_off_untracked | 1 + tests/resources/filemodes/exec_on | 1 + tests/resources/filemodes/exec_on2off_staged | 1 + tests/resources/filemodes/exec_on2off_workdir | 1 + tests/resources/filemodes/exec_on_untracked | 1 + tests/resources/gitgit.index | Bin 0 -> 134799 bytes tests/resources/icase/.gitted/HEAD | 1 + tests/resources/icase/.gitted/config | 7 + tests/resources/icase/.gitted/description | 1 + tests/resources/icase/.gitted/index | Bin 0 -> 1392 bytes tests/resources/icase/.gitted/info/exclude | 6 + tests/resources/icase/.gitted/logs/HEAD | 1 + .../resources/icase/.gitted/logs/refs/heads/master | 1 + .../3e/257c57f136a1cb8f2b8e9a2e5bc8ec0258bdce | Bin 0 -> 114 bytes .../4d/d6027d083575c7431396dc2a3174afeb393c93 | Bin 0 -> 61 bytes .../62/e0af52c199ec731fe4ad230041cd3286192d49 | Bin 0 -> 19 bytes .../76/d6e1d231b1085fcce151427e9899335de74be6 | 3 + .../d4/4e18fb93b7107b5cd1b95d601591d77869a1b6 | Bin 0 -> 21 bytes tests/resources/icase/.gitted/refs/heads/master | 1 + tests/resources/icase/B | 1 + tests/resources/icase/D | 1 + tests/resources/icase/F | 1 + tests/resources/icase/H | 1 + tests/resources/icase/J | 1 + tests/resources/icase/L/1 | 1 + tests/resources/icase/L/B | 1 + tests/resources/icase/L/D | 1 + tests/resources/icase/L/a | 1 + tests/resources/icase/L/c | 1 + tests/resources/icase/a | 1 + tests/resources/icase/c | 1 + tests/resources/icase/e | 1 + tests/resources/icase/g | 1 + tests/resources/icase/i | 1 + tests/resources/icase/k/1 | 1 + tests/resources/icase/k/B | 1 + tests/resources/icase/k/D | 1 + tests/resources/icase/k/a | 1 + tests/resources/icase/k/c | 1 + tests/resources/issue_1397/.gitted/HEAD | 1 + tests/resources/issue_1397/.gitted/config | 6 + tests/resources/issue_1397/.gitted/index | Bin 0 -> 233 bytes .../7f/483a738f867e5b21c8f377d70311f011eb48b5 | 3 + .../83/12e0889a9cbab77c732b6bc39b51a683e3a318 | Bin 0 -> 48 bytes .../8a/7ef047fc933edb62e84e7977b0612ec3f6f283 | Bin 0 -> 141 bytes .../8e/8f80088a9274fd23584992f587083ca1bcbbac | Bin 0 -> 63 bytes .../f2/c62dea0372a0578e053697d5c1ba1ac05e774a | Bin 0 -> 94 bytes .../ff/3578d64d199d5b48d92bbb569e0a273e411741 | Bin 0 -> 73 bytes .../resources/issue_1397/.gitted/refs/heads/master | 1 + tests/resources/issue_1397/crlf_file.txt | 3 + .../resources/issue_1397/some_other_crlf_file.txt | 3 + tests/resources/issue_592/.gitted/COMMIT_EDITMSG | 1 + tests/resources/issue_592/.gitted/HEAD | 1 + tests/resources/issue_592/.gitted/config | 8 + tests/resources/issue_592/.gitted/index | Bin 0 -> 392 bytes tests/resources/issue_592/.gitted/info/exclude | 6 + tests/resources/issue_592/.gitted/logs/HEAD | 2 + .../issue_592/.gitted/logs/refs/heads/master | 2 + .../06/07ee9d4ccce8e4c4fa13c2c7d727e7faba4e0e | Bin 0 -> 87 bytes .../49/363a72a90d9424240258cd3759f23788ecf1d8 | Bin 0 -> 55 bytes .../4d/383e87f0371ba8fa353f3912db6862b2625e85 | 2 + .../71/44be264b61825fbff68046fe999bdfe96a1792 | Bin 0 -> 50 bytes .../be/de83ee10b5b3f00239660b00acec2d55fd0b84 | Bin 0 -> 107 bytes .../e3/8fcc7a6060f5eb5b876e836b52ae4769363f21 | Bin 0 -> 137 bytes .../f1/adef63cb08891a0942b76fc4b9c50c6c494bc7 | Bin 0 -> 29 bytes .../resources/issue_592/.gitted/refs/heads/master | 1 + tests/resources/issue_592/a.txt | 1 + tests/resources/issue_592/c/a.txt | 1 + tests/resources/issue_592/l.txt | 1 + tests/resources/issue_592/t/a.txt | 1 + tests/resources/issue_592/t/b.txt | 1 + tests/resources/issue_592b/.gitted/HEAD | 1 + tests/resources/issue_592b/.gitted/config | 6 + tests/resources/issue_592b/.gitted/description | 1 + tests/resources/issue_592b/.gitted/index | Bin 0 -> 376 bytes tests/resources/issue_592b/.gitted/info/exclude | 6 + tests/resources/issue_592b/.gitted/logs/HEAD | 1 + .../issue_592b/.gitted/logs/refs/heads/master | 1 + .../3f/bf1852f72fd268e36457b13a18cdd9a4c9ea35 | 2 + .../6f/a891d3e578c83e1c03bdb9e0fdd8e6e934157f | Bin 0 -> 28 bytes .../80/07d41d5794e6ce4d4d2c97e370d5a9aa6d5213 | Bin 0 -> 24 bytes .../a6/5fb6583a7c425284142f285bc359a2d6565513 | Bin 0 -> 93 bytes .../ae/be7a55922c7097ef91ca3a7bc327a901d87c2c | Bin 0 -> 122 bytes .../b3/44b055867fcdc1f01eaa75056a43e868eb4fbc | Bin 0 -> 36 bytes .../f7/d75fbfad8b1d2e307ced287ea78aad403cdce3 | Bin 0 -> 57 bytes .../resources/issue_592b/.gitted/refs/heads/master | 1 + tests/resources/issue_592b/gitignore | 1 + .../issue_592b/ignored/contained/ignored3.txt | 1 + .../issue_592b/ignored/contained/tracked3.txt | 1 + tests/resources/issue_592b/ignored/ignored2.txt | 1 + tests/resources/issue_592b/ignored/tracked2.txt | 1 + tests/resources/issue_592b/ignored1.txt | 1 + tests/resources/issue_592b/tracked1.txt | 1 + .../resources/merge-resolve/.gitted/COMMIT_EDITMSG | 1 + tests/resources/merge-resolve/.gitted/HEAD | 1 + tests/resources/merge-resolve/.gitted/ORIG_HEAD | 1 + tests/resources/merge-resolve/.gitted/config | 6 + tests/resources/merge-resolve/.gitted/description | 1 + tests/resources/merge-resolve/.gitted/index | Bin 0 -> 624 bytes tests/resources/merge-resolve/.gitted/logs/HEAD | 236 ++++ .../merge-resolve/.gitted/logs/refs/heads/branch | 2 + .../.gitted/logs/refs/heads/df_ancestor | 5 + .../merge-resolve/.gitted/logs/refs/heads/df_side1 | 14 + .../merge-resolve/.gitted/logs/refs/heads/df_side2 | 9 + .../.gitted/logs/refs/heads/ff_branch | 5 + .../merge-resolve/.gitted/logs/refs/heads/master | 5 + .../merge-resolve/.gitted/logs/refs/heads/octo1 | 2 + .../merge-resolve/.gitted/logs/refs/heads/octo2 | 2 + .../merge-resolve/.gitted/logs/refs/heads/octo3 | 2 + .../merge-resolve/.gitted/logs/refs/heads/octo4 | 2 + .../merge-resolve/.gitted/logs/refs/heads/octo5 | 2 + .../merge-resolve/.gitted/logs/refs/heads/octo6 | 3 + .../merge-resolve/.gitted/logs/refs/heads/renames1 | 2 + .../merge-resolve/.gitted/logs/refs/heads/renames2 | 3 + .../.gitted/logs/refs/heads/trivial-10 | 3 + .../.gitted/logs/refs/heads/trivial-10-branch | 2 + .../.gitted/logs/refs/heads/trivial-11 | 3 + .../.gitted/logs/refs/heads/trivial-11-branch | 2 + .../.gitted/logs/refs/heads/trivial-13 | 3 + .../.gitted/logs/refs/heads/trivial-13-branch | 2 + .../.gitted/logs/refs/heads/trivial-14 | 3 + .../.gitted/logs/refs/heads/trivial-14-branch | 2 + .../.gitted/logs/refs/heads/trivial-2alt | 2 + .../.gitted/logs/refs/heads/trivial-2alt-branch | 2 + .../.gitted/logs/refs/heads/trivial-3alt | 3 + .../.gitted/logs/refs/heads/trivial-3alt-branch | 1 + .../.gitted/logs/refs/heads/trivial-4 | 2 + .../.gitted/logs/refs/heads/trivial-4-branch | 2 + .../.gitted/logs/refs/heads/trivial-5alt-1 | 2 + .../.gitted/logs/refs/heads/trivial-5alt-1-branch | 2 + .../.gitted/logs/refs/heads/trivial-5alt-2 | 3 + .../.gitted/logs/refs/heads/trivial-5alt-2-branch | 2 + .../.gitted/logs/refs/heads/trivial-6 | 3 + .../.gitted/logs/refs/heads/trivial-6-branch | 2 + .../.gitted/logs/refs/heads/trivial-7 | 3 + .../.gitted/logs/refs/heads/trivial-7-branch | 5 + .../.gitted/logs/refs/heads/trivial-8 | 3 + .../.gitted/logs/refs/heads/trivial-8-branch | 2 + .../.gitted/logs/refs/heads/trivial-9 | 3 + .../.gitted/logs/refs/heads/trivial-9-branch | 2 + .../.gitted/logs/refs/heads/unrelated | 1 + .../00/5b6fcc8fec71d2550bef8462d169b3c26aa14b | Bin 0 -> 168 bytes .../00/9b9cab6fdac02915a88ecd078b7a792ed802d8 | Bin 0 -> 164 bytes .../00/c7d33f1ffa79d19c2272b370fcaeaadba49c08 | Bin 0 -> 147 bytes .../01/f149e1b8f84bd8896aaff6d6b22af88459ded0 | Bin 0 -> 166 bytes .../02/04a84f822acbf6386b36d33f1f6bc68bbbf858 | Bin 0 -> 168 bytes .../02/251f990ca8e92e7ae61d3426163fa821c64001 | Bin 0 -> 264 bytes .../03/21415405cb906c46869919af56d51dbbe5e85c | Bin 0 -> 271 bytes .../03/2ebc5ab85d9553bb187d3cd40875ff23a63ed0 | Bin 0 -> 29 bytes .../03/b87706555accbf874ccd410dbda01e8e70a67f | Bin 0 -> 353 bytes .../03/dad1005e5d06d418f50b12e0bcd48ff2306a03 | Bin 0 -> 264 bytes .../05/1ffd7901a442faf56b226161649074f15c7c47 | 1 + .../05/8541fc37114bfc1dddf6bd6bffc7fae5c2e6fe | Bin 0 -> 63 bytes .../05/f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c | Bin 0 -> 170 bytes .../07/a759da919f737221791d542f176ab49c88837f | Bin 0 -> 165 bytes .../07/c514b04698e068892b31c8d352b85813b99c6e | Bin 0 -> 32 bytes .../09/055301463b7f2f8ee5d368f8ed5c0a40ad8515 | Bin 0 -> 41 bytes .../09/17bb159596aea4d295f4857da77e8f96b3c7dc | Bin 0 -> 36 bytes .../09/2ce8682d7f3a2a3a769a6daca58950168ba5c4 | Bin 0 -> 163 bytes .../09/3bebf072dd4bbba88833667d6ffe454df199e1 | Bin 0 -> 266 bytes .../09/768bed22680cdb0859683fa9677ccc8d5a25c1 | Bin 0 -> 275 bytes .../0a/75d9aac1dc84fb5aa51f7325c0ab53242ddef7 | Bin 0 -> 275 bytes .../0c/fd6c54ef6532d862408f562309dc9c74a401e8 | Bin 0 -> 28 bytes .../0d/52e3a556e189ba0948ae56780918011c1b167d | Bin 0 -> 235 bytes .../0d/872f8e871a30208305978ecbf9e66d864f1638 | Bin 0 -> 89 bytes .../0e/c5f433959cd46177f745903353efb5be08d151 | Bin 0 -> 165 bytes .../11/deab00b2d3a6f5a3073988ac050c2d7b6655e2 | Bin 0 -> 34 bytes .../11/f4f3c08b737f5fd896cbefa1425ee63b21b2fa | 1 + .../13/d1be4ea52a6ced1d7a1d832f0ee3c399348e5e | Bin 0 -> 168 bytes .../14/39088f509b79b1535b64193137d3ce4b240734 | Bin 0 -> 58 bytes .../15/8dc7bedb202f5b26502bf3574faa7f4238d56c | 2 + .../16/f825815cfd20a07a75c71554e82d8eede0b061 | 1 + .../17/8940b450f238a56c0d75b7955cb57b38191982 | Bin 0 -> 65 bytes .../18/3310e30fb1499af8c619108ffea4d300b5e778 | Bin 0 -> 170 bytes .../18/cb316b1cefa0f8a6946f0e201a8e1a6f845ab9 | Bin 0 -> 68 bytes .../19/b7ac485269b672a101060894de3ba9c2a24dd1 | Bin 0 -> 53 bytes .../1a/010b1c0f081b2e8901d55307a15c29ff30af0e | Bin 0 -> 19 bytes .../1c/ff9ec6a47a537380dedfdd17c9e76d74259a2b | Bin 0 -> 33 bytes .../1e/4ff029aee68d0d69ef9eb6efa6cbf1ec732f99 | Bin 0 -> 29 bytes .../1f/81433e3161efbf250576c58fede7f6b836f3d3 | Bin 0 -> 262 bytes .../20/91d94c8bd3eb0835dc5220de5e8bb310fa1513 | Bin 0 -> 271 bytes .../21/671e290278286fb2ce4c63d01699b67adce331 | Bin 0 -> 79 bytes .../22/7792b52aaa0b238bea00ec7e509b02623f168c | Bin 0 -> 102 bytes .../23/3c0919c998ed110a4b6ff36f353aec8b713487 | Bin 0 -> 43 bytes .../23/92a2dacc9efb562b8635d6579fb458751c7c5b | Bin 0 -> 142 bytes .../24/1a1005cd9b980732741b74385b891142bcba28 | Bin 0 -> 67 bytes .../24/2591eb280ee9eeb2ce63524b9a8b9bc4cb515d | Bin 0 -> 30 bytes .../24/90b9f1a079420870027deefb49f51d6656cf74 | Bin 0 -> 268 bytes .../25/9d08ca43af9200e9ea9a098e44a5a350ebd9b3 | Bin 0 -> 381 bytes .../25/c40b7660c08c8fb581f770312f41b9b03119d1 | Bin 0 -> 31 bytes .../26/153a3ff3649b6c2bb652d3f06878c6e0a172f9 | Bin 0 -> 48 bytes .../27/133da702ba3c60af2a01e96c2555ff4045d692 | Bin 0 -> 32 bytes .../2b/0de5dc27505dcdd83a75c8bf1fcd9462cd7add | Bin 0 -> 147 bytes .../2b/5f1f181ee3b58ea751f5dd5d8f9b445520a136 | Bin 0 -> 53 bytes .../2b/d0a343aeef7a2cf0d158478966a6e587ff3863 | Bin 0 -> 56 bytes .../2d/a538570bc1e5b2c3e855bf702f35248ad0735f | 2 + .../2f/2e37b7ebbae467978610896ca3aafcdad2ee67 | Bin 0 -> 52 bytes .../2f/4024ce528d36d8670c289cce5a7963e625bb0c | Bin 0 -> 179 bytes .../2f/56120107d680129a5d9791b521cb1e73a2ed31 | 3 + .../2f/598248eeccfc27e5ca44d9d96383f6dfea7b16 | 1 + .../31/68dca1a561889b045a6441909f4c56145e666d | 2 + .../31/d5472536041a83d986829240bbbdc897c6f8a6 | Bin 0 -> 41 bytes .../32/21dd512b7e2dc4b5bd03046df6c81b2ab2070b | Bin 0 -> 47 bytes .../33/46d64325b39e5323733492cd55f808994a2475 | Bin 0 -> 33 bytes .../33/d500f588fbbe65901d82b4e6b008e549064be0 | 2 + .../34/bfafff88eaf118402b44e6f3e2dbbf1a582b05 | 1 + .../35/0c6eb3010efc403a6bed682332635314e9ed58 | Bin 0 -> 92 bytes .../35/411bfb77cd2cc431f3a03a2b4976ed94b5d241 | Bin 0 -> 31 bytes .../35/4704d3613ad4228e4786fc76656b11e98236c4 | Bin 0 -> 41 bytes .../35/632e43612c06a3ea924bfbacd48333da874c29 | 1 + .../35/75826c96a975031d2c14368529cc5c4353a8fd | Bin 0 -> 163 bytes .../36/219b49367146cb2e6a1555b5a9ebd4d0328495 | Bin 0 -> 68 bytes .../36/4bbe4ce80c7bd31e6307dce77d46e3e1759fb3 | Bin 0 -> 35 bytes .../37/48859b001c6e627e712a07951aee40afd19b41 | Bin 0 -> 41 bytes .../38/5c8a0f26ddf79e9041e15e17dc352ed2c4cced | 2 + .../3b/47b031b3e55ae11e14a05260b1c3ffd6838d55 | Bin 0 -> 161 bytes .../3b/bf0bf59b20df5d5fc58b9fc1dc07be637c301f | Bin 0 -> 269 bytes .../3e/f4d30382ca33fdeba9fda895a99e0891ba37aa | Bin 0 -> 36 bytes .../3e/f9bfe82f9635518ae89152322f3b46fd4ba25b | Bin 0 -> 172 bytes .../40/2784a46a4a3982294231594cbeb431f506d22c | Bin 0 -> 83 bytes .../41/2b32fb66137366147f1801ecc962452757d48a | 2 + .../43/aafd43bea779ec74317dc361f45ae3f532a505 | Bin 0 -> 37 bytes .../43/c338656342227a3a3cd3aa85cbf784061f5425 | Bin 0 -> 266 bytes .../45/299c1ca5e07bba1fd90843056fb559f96b1f5a | Bin 0 -> 58 bytes .../46/6daf8552b891e5c22bc58c9d7fc1a2eb8f0289 | Bin 0 -> 382 bytes .../47/6dbb3e207313d1d8aaa120c6ad204bf1295e53 | Bin 0 -> 522 bytes .../47/8172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 | Bin 0 -> 165 bytes .../49/130a28ef567af9a6a6104c38773fedfa5f9742 | Bin 0 -> 37 bytes .../49/9df817155e4bdd3c6ee192a72c52f481818230 | Bin 0 -> 35 bytes .../4a/9550ebcc97ce22b22f45af7b829bb030d003f5 | Bin 0 -> 53 bytes .../4b/253da36a0ae8bfce63aeabd8c5b58429925594 | 2 + .../4b/48deed3a433909bfd6b6ab3d4b91348b6af464 | Bin 0 -> 24 bytes .../4b/825dc642cb6eb9a060e54bf8d69288fbee4904 | Bin 0 -> 15 bytes .../4c/9fac0707f8d4195037ae5a681aa48626491541 | Bin 0 -> 167 bytes .../4c/a408a8c88655f7586a1b580be6fad138121e98 | Bin 0 -> 159 bytes .../4e/0d9401aee78eb345a8685a859d37c8c3c0bbed | Bin 0 -> 262 bytes .../4e/886e602529caa9ab11d71f86634bd1b6e0de10 | Bin 0 -> 56 bytes .../4e/b04c9e79e88f6640d01ff5b25ca2a60764f216 | Bin 0 -> 34 bytes .../4f/e93c0ec83eb6305cbace3dace88ecee1b63cb6 | Bin 0 -> 161 bytes .../50/12fd565b1393bdfda1805d4ec38ce6619e1fd1 | Bin 0 -> 29 bytes .../50/4f75ac95a71ef98051817618576a68505b92f9 | Bin 0 -> 93 bytes .../50/84fc2a88b6bdba8db93bd3953a8f4fdb470238 | Bin 0 -> 53 bytes .../50/ce7d7d01217679e26c55939eef119e0c93e272 | Bin 0 -> 159 bytes .../51/95a1b480f66691b667f10a9e41e70115a78351 | Bin 0 -> 170 bytes .../52/d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 | 3 + .../53/825f41ac8d640612f9423a2f03a69f3d96809a | Bin 0 -> 164 bytes .../54/269b3f6ec3d7d4ede24dd350dd5d605495c3ae | 2 + .../54/59c89aa0026d543ce8343bd89871bce543f9c2 | 3 + .../54/7607c690372fe81fab8e3bb44c530e129118fd | Bin 0 -> 58 bytes .../55/b4e4687e7a0d9ca367016ed930f385d4022e6f | 1 + .../56/6ab53c220a2eafc1212af1a024513230280ab9 | 3 + .../56/a638b76b75e068590ac999c2f8621e7f3e264c | 1 + .../57/079a46233ae2b6df62e9ade71c4948512abefb | Bin 0 -> 168 bytes .../58/43febcb23480df0b5edb22a21c59c772bb8e29 | Bin 0 -> 71 bytes .../58/e853f66699fd02629fd50bde08082bc005933a | Bin 0 -> 160 bytes .../59/6803b523203a4851c824c07366906f8353f4ad | Bin 0 -> 163 bytes .../5c/2411f8075f48a6b2fdb85ebc0d371747c4df15 | Bin 0 -> 37 bytes .../5c/341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d | Bin 0 -> 37 bytes .../5c/3b68a71fc4fa5d362fd3875e53137c6a5ab7a5 | Bin 0 -> 40 bytes .../5d/c1018e90b19654bee986b7a0c268804d39659d | Bin 0 -> 168 bytes .../5d/dd0fe66f990dc0e5cf9fec6d9b465240e9537f | Bin 0 -> 43 bytes .../5e/b7bb6a146eb3c7fd3990b240a2308eceb1cf8d | Bin 0 -> 268 bytes .../5f/bfbdc04b4eca46f54f4853a3c5a1dce28f5165 | Bin 0 -> 283 bytes .../60/91fc2c036a382a69489e3f518ee5aae9a4e567 | Bin 0 -> 258 bytes .../61/340eeed7340fa6a8792def9a5938bb5d4434bb | Bin 0 -> 92 bytes .../61/78885b38fe96e825ac0f492c0a941f288b37f6 | Bin 0 -> 289 bytes .../62/12c31dab5e482247d7977e4f0dd3601decf13b | Bin 0 -> 45 bytes .../62/269111c3b02a9355badcb9da8678b1bf41787b | Bin 0 -> 269 bytes .../62/c4f6533c9a3894191fdcb96a3be935ade63f1a | Bin 0 -> 53 bytes .../63/247125386de9ec90a27ad36169307bf8a11a38 | 1 + .../67/18a45909532d1fcf5600d0877f7fe7e78f0b86 | 1 + .../68/c6c84b091926c7d90aa6a79b2bc3bb6adccd8e | Bin 0 -> 55 bytes .../69/f570c57b24ea7c086e94c5e574964798321435 | Bin 0 -> 266 bytes .../6a/e1a3967031a42cf955d9d5c2395211ac82f6cf | Bin 0 -> 272 bytes .../6b/7e37be8ce0b897093f2878a9dcd8f396beda2c | Bin 0 -> 53 bytes .../6c/06dcd163587c2cc18be44857e0b71116382aeb | Bin 0 -> 30 bytes .../6f/32739c3724d1d5f855299309f388606f407468 | Bin 0 -> 630 bytes .../6f/a33014764bf1120a454eb8437ae098238e409b | Bin 0 -> 168 bytes .../6f/be9fb85c86d7d1435f728da418bdff52c640a9 | Bin 0 -> 83 bytes .../71/17467b18605a660ebe5586df69e2311ed5609f | Bin 0 -> 265 bytes .../71/2ebba6669ea847d9829e4f1059d6c830c8b531 | Bin 0 -> 152 bytes .../71/add2d7b93d55bf3600f8a1582beceebbd050c8 | Bin 0 -> 264 bytes .../72/ea499e108df5ff0a4a913e7655bbeeb1fb69f2 | Bin 0 -> 26 bytes .../74/df13f0793afdaa972150bba976f7de8284914e | Bin 0 -> 26 bytes .../75/a811bf6bc57694adb3fe604786f3a4efd1cd1b | 2 + .../76/63fce0130db092936b137cabd693ec234eb060 | Bin 0 -> 49 bytes .../76/ab0e2868197ec158ddd6c78d8a0d2fd73d38f9 | Bin 0 -> 37 bytes .../7a/a3edf2bcfee22398e6b55295aa56366b7aaf76 | Bin 0 -> 271 bytes .../7c/2c5228c9e90170d4a35e6558e47163daf092e5 | Bin 0 -> 172 bytes .../7c/b63eed597130ba4abb87b3e544b85021905520 | 3 + .../7e/2d058d5fedf8329db44db4fac610d6b1a89159 | Bin 0 -> 165 bytes .../7f/7a2da58126226986d71c6ddfab4afba693280d | Bin 0 -> 199 bytes .../80/a8fbb3abb1ba423d554e9630b8fc2e5698f86b | Bin 0 -> 168 bytes .../81/87117062b750eed4f93fd7e899f17b52ce554d | Bin 0 -> 170 bytes .../83/07d93a155903a5c49576583f0ce1f6ff897c0e | Bin 0 -> 30 bytes .../83/824a8c6658768e2013905219cc8c64cc3d9a2e | Bin 0 -> 382 bytes .../84/9619b03ae540acee4d1edec96b86993da6b497 | 3 + .../84/de84f8f3a6d63e636ee9ad81f4b80512fa9bbe | Bin 0 -> 41 bytes .../86/088dae8bade454995b21a1c88107b0e1accdab | Bin 0 -> 47 bytes .../87/b4926260d77a3b851e71ecce06839bd650b231 | Bin 0 -> 43 bytes .../88/e185910a15cd13bdf44854ad037f4842b03b29 | Bin 0 -> 177 bytes .../8a/ad9d0ea334951da47b621a475b39cc6ed759bf | Bin 0 -> 51 bytes .../8a/ae714f7d939309d7f132b30646d96743134a9f | 1 + .../8b/095d8fd01594f4d14454d073e3ac57b9ce485f | Bin 0 -> 201 bytes .../8b/5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a | 1 + .../8b/fb012a6d809e499bd8d3e194a3929bc8995b93 | Bin 0 -> 34 bytes .../8c/749d9968d4b10dcfb06c9f97d0e5d92d337071 | 2 + .../8f/4433f8593ddd65b7dd43dd4564d841f4d9c8aa | Bin 0 -> 164 bytes .../90/a336c7dacbe295159413559b0043b8bdc60d57 | Bin 0 -> 271 bytes .../91/2b2d7819cf9c1029e414883857ed61d597a1a5 | Bin 0 -> 295 bytes .../91/8bb3e09090a9995d48af9a2a6296d7e6088d1c | Bin 0 -> 38 bytes .../92/7d4943cdbdc9a667db8e62cfd0a41870235c51 | Bin 0 -> 535 bytes .../93/77fccdb210540b8c0520cc6e80eb632c20bd25 | Bin 0 -> 53 bytes .../94/4f5dd1a867cab4c2bbcb896493435cae1dcc1a | 2 + .../94/8ba6e701c1edab0c2d394fb7c5538334129793 | Bin 0 -> 71 bytes .../95/646149ab6b6ba6edc83cff678582538b457b2b | 3 + .../95/9de65e568274120fdf9e3af9f77b1550122149 | Bin 0 -> 40 bytes .../96/8ca794a4597f7f6abbb2b8d940b4078a0f3fd4 | Bin 0 -> 53 bytes .../97/7c696519c5a3004c5f1d15d60c89dbeb8f235f | Bin 0 -> 160 bytes .../98/ba4205fcf31f5dd93c916d35fe3f3b3d0e6714 | 1 + .../98/d52d07c0b0bbf2b46548f6aa521295c2cb55db | 3 + .../99/b4f7e4f24470fa06b980bc21f1095c2a9425c0 | Bin 0 -> 164 bytes .../9a/301fbe6fada7dcb74fcd7c20269b5c743459a7 | Bin 0 -> 163 bytes .../9a/f731fa116d1eb9a6c0109562472cfee6f5a979 | Bin 0 -> 48 bytes .../9c/0b6c34ef379a42d858f03fef38630f476b9102 | Bin 0 -> 38 bytes .../9e/7f4359c469f309b6057febf4c6e80742cbed5b | Bin 0 -> 539 bytes .../9e/fe7723802d4305142eee177e018fee1572c4f4 | Bin 0 -> 36 bytes .../9f/74397a3397b3585faf09e9926b110d7f654254 | Bin 0 -> 621 bytes .../a0/31a28ae70e33a641ce4b8a8f6317f1ab79dee4 | Bin 0 -> 37 bytes .../a3/9a620dae5bc8b4e771cd4d251b7d080401a21e | Bin 0 -> 29 bytes .../a3/fabece9eb8748da810e1e08266fef9b7136ad4 | Bin 0 -> 164 bytes .../a4/1b1bb6d0be3c22fb654234c33b428e15c8cc27 | Bin 0 -> 92 bytes .../a4/3150a738849c59376cf30bb2a68348a83c8f48 | Bin 0 -> 162 bytes .../a5/563304ddf6caba25cb50323a2ea6f7dbfcadca | Bin 0 -> 48 bytes .../a7/08b253bd507417ec42d1467a7fd2d7519c4956 | Bin 0 -> 40 bytes .../a7/65fb87eb2f7a1920b73b2d5a057f8f8476a42b | Bin 0 -> 170 bytes .../a7/7a56a49f8f3ae242e02717f18ebbc60c5cc543 | Bin 0 -> 65 bytes .../a7/dbfcbfc1a60709cb80b5ca24539008456531d0 | 1 + .../a8/02e06f1782a9645b9851bc7202cee74a8a4972 | Bin 0 -> 172 bytes .../a8/87dd39ad3edd610fc9083dcb61e40ab50673d1 | 1 + .../a9/0bc3fb6f15181972a2959a921429efbd81a473 | 2 + .../ab/40af3cb8a3ed2e2843e96d9aa7871336b94573 | Bin 0 -> 161 bytes .../ab/6c44a2e84492ad4b41bb6bac87353e9d02ac8b | Bin 0 -> 33 bytes .../ab/929391ac42572f92110f3deeb4f0844a951e22 | Bin 0 -> 40 bytes .../ac/4045f965119e6998f4340ed0f411decfb3ec05 | Bin 0 -> 29 bytes .../ad/a14492498136771f69dd451866cabcb0e9ef9a | Bin 0 -> 39 bytes .../ad/a55a45d14527dc3dfc714ea1c65d2e1e6fbe87 | 1 + .../b2/d399ae15224e1d58066e3c8df70ce37de7a656 | 2 + .../b4/2712cfe99a1a500b2a51fe984e0b8a7702ba11 | 5 + .../b6/9fe837e4cecfd4c9a40cdca7c138468687df07 | 2 + .../b6/f610aef53bd343e6c96227de874c66f00ee8e8 | Bin 0 -> 162 bytes .../b7/a2576f9fc20024ac9ef17cb134acbd1ac73127 | Bin 0 -> 320 bytes .../b8/a3a806d3950e8c0a03a34f234a92eff0e2c68d | Bin 0 -> 286 bytes .../ba/cac9b3493509aa15e1730e1545fc0919d1dae0 | Bin 0 -> 29 bytes .../bc/744705e1d8a019993cf88f62bc4020f1b80919 | 2 + .../bc/95c75d59386147d1e79a87c33068d8dbfd71f2 | Bin 0 -> 348 bytes .../bd/593285fc7fe4ca18ccdbabf027f5d689101452 | Bin 0 -> 159 bytes .../bd/867fbae2faa80b920b002b80b1c91bcade7784 | Bin 0 -> 48 bytes .../bd/9cb4cd0a770cb9adcb5fce212142ef40ea1c35 | Bin 0 -> 51 bytes .../be/f6e37b3ee632ba74159168836f382fed21d77d | 2 + .../c0/6a9be584ac49aa02c5551312d9e2982c91df10 | Bin 0 -> 348 bytes .../c1/b17981db0840109a820dae8674ee29684134ff | Bin 0 -> 348 bytes .../c1/b6a51bbb87c2f82b161412c3d20b59fc69b090 | Bin 0 -> 47 bytes .../c3/5dee9bcc0e989f3b0c40f68372a9a51b6c4e6a | Bin 0 -> 162 bytes .../c3/d02eeef75183df7584d8d13ac03053910c1301 | Bin 0 -> 67 bytes .../c4/efe31e9decccc8b2b4d3df9aac2cdfe2995618 | Bin 0 -> 538 bytes .../c5/0d0f1cb60b8b0fe1615ad20ace557e9d68d7bd | 1 + .../c5/bbe550b9f09444bdddd3ecf3d97c0b42aa786c | Bin 0 -> 269 bytes .../c6/07fc30883e335def28cd686b51f6cfa02b06ec | 2 + .../c6/92ecf62007c0ac9fb26e2aa884de2933de15ed | Bin 0 -> 40 bytes .../c8/f06f2e3bb2964174677e91f0abead0e43c9e5d | Bin 0 -> 45 bytes .../c9/174cef549ec94ecbc43ef03cdc775b4950becb | 2 + .../c9/4b27e41064c521120627e07e2035cca1d24ffa | Bin 0 -> 162 bytes .../ca/b2cf23998b40f1af2d9d9a756dc9e285a8df4b | Bin 0 -> 40 bytes .../cb/491780d82e46dc88a065b965ab307a038f2bc2 | Bin 0 -> 163 bytes .../cb/6693a788715b82440a54e0eacd19ba9f6ec559 | Bin 0 -> 41 bytes .../cc/3e3009134cb88014129fc8858d1101359e5e2f | 2 + .../ce/8860d49e3bea6fd745874a01b7c3e46da8cbc3 | Bin 0 -> 48 bytes .../ce/e656c392ad0557b3aae0fb411475c206e2926f | Bin 0 -> 32 bytes .../cf/8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d | Bin 0 -> 29 bytes .../d0/7ec190c306ec690bac349e87d01c4358e49bb2 | 2 + .../d0/d4594e16f2e19107e3fa7ea63e7aaaff305ffb | Bin 0 -> 51 bytes .../d2/f8637f2eab2507a1e13cbc9df4729ec386627e | Bin 0 -> 268 bytes .../d3/719a5ae8e4d92276b5313ce976f6ee5af2b436 | 2 + .../d3/7aa3bbfe1c0c49b909781251b956dbabe85f96 | Bin 0 -> 80 bytes .../d3/7ad72a2052685fc6201c2af90103ad42d2079b | Bin 0 -> 233 bytes .../d4/207f77243500bec335ab477f9227fcdb1e271a | 2 + .../d4/27e0b2e138501a3d15cc376077a3631e15bd46 | Bin 0 -> 38 bytes .../d5/093787ef302b941b6aab081b99fb4880038bd8 | Bin 0 -> 30 bytes .../d5/a61b0b4992a4f0caa887fa08b52431e727bb6f | Bin 0 -> 81 bytes .../d5/b6fc965c926a1bfc9ee456042b94088b5c5d21 | Bin 0 -> 319 bytes .../d5/ec1152fe25e9fec00189eb00b3db71db24c218 | Bin 0 -> 24 bytes .../d6/42b9770c66bba94a08df09b5efb095001f76d7 | Bin 0 -> 539 bytes .../d6/462fa3f5292857db599c54aea2bf91616230c5 | Bin 0 -> 48 bytes .../d6/cf6c7741b3316826af1314042550c97ded1d50 | 2 + .../d8/74671ef5b20184836cb983bb273e5280384d0b | Bin 0 -> 162 bytes .../d8/fa77b6833082c1ea36b7828a582d4c43882450 | 1 + .../d9/63979c237d08b6ba39062ee7bf64c7d34a27f8 | Bin 0 -> 48 bytes .../da/178208145ef585a1bd5ca5f4c9785d738df2cf | Bin 0 -> 41 bytes .../db/6261a7c65c7fd678520c9bb6f2c47582ab9ed5 | Bin 0 -> 624 bytes .../dd/9a570c3400e6e07bc4d7651d6e20b08926b3d9 | Bin 0 -> 36 bytes .../de/872ee3618b894992e9d1e18ba2ebe256a112f9 | 1 + .../df/e3f22baa1f6fce5447901c3086bae368de6bdd | Bin 0 -> 40 bytes .../e0/67f9361140f19391472df8a82d6610813c73b7 | Bin 0 -> 53 bytes .../e1/129b3cfb5898e0fbd606e0cb80b2755e50d161 | Bin 0 -> 92 bytes .../e1/7ace1492648c9dc5701bad5c47af9d1b60c4e9 | Bin 0 -> 264 bytes .../e2/c6abbd55fed5ac71a5f2751e29b4a34726a595 | 1 + .../e3/1e7ad3ed298f24e383c4950f4671993ec078e4 | Bin 0 -> 210 bytes .../e3/76fbdd06ebf021c92724da9f26f44212734e3e | 3 + .../e4/9f917b448d1340b31d76e54ba388268fd4c922 | Bin 0 -> 36 bytes .../e4/f618a2c3ed0669308735727df5ebf2447f022f | 2 + .../e6/5a9bb2af9f4c2d1c375dd0f8f8a46cf9c68812 | Bin 0 -> 160 bytes .../e8/107f24196736b870a318a0e28f048e29f6feff | 3 + .../e9/2cdb7017dc6c5aed25cb4202c5b0104b872246 | Bin 0 -> 48 bytes .../e9/ad6ec3e38364a3d07feda7c4197d4d845c53b5 | Bin 0 -> 36 bytes .../e9/f48beccc62d535739bfbdebe0a55ed716d8366 | Bin 0 -> 382 bytes .../eb/c09d0137cfb0c26697aed0109fb943ad906f3f | Bin 0 -> 166 bytes .../ec/67e5a86adff465359f1c8f995e12dbdfa08d8a | Bin 0 -> 166 bytes .../ed/9523e62e453e50dd9be1606af19399b96e397a | Bin 0 -> 87 bytes .../ee/1d6f164893c1866a323f072eeed36b855656be | Bin 0 -> 291 bytes .../ee/3fa1b8c00aff7fe02065fdb50864bb0d932ccf | Bin 0 -> 64 bytes .../ee/a9286df54245fea72c5b557291470eb825f38f | Bin 0 -> 235 bytes .../ef/58fdd8086c243bdc81f99e379acacfd21d32d6 | 2 + .../ef/c499524cf105d5264ac7fc54e07e95764e8075 | Bin 0 -> 32 bytes .../ef/c9121fdedaf08ba180b53ebfbcf71bd488ed09 | Bin 0 -> 160 bytes .../f0/053b8060bb3f0be5cbcc3147a07ece26bf097e | Bin 0 -> 163 bytes .../f0/ce2b8e4986084d9b308fb72709e414c23eb5e6 | Bin 0 -> 125 bytes .../f2/0c9063fa0bda9a397c96947a7b687305c49753 | Bin 0 -> 29 bytes .../f2/9e7fb590551095230c6149cbe72f2e9104a796 | Bin 0 -> 41 bytes .../f3/293571dcd708b6a3faf03818cd2844d000e198 | 1 + .../f3/f1164b68b57b1995b658a828320e6df3081fae | Bin 0 -> 310 bytes .../f4/15caf3fcad16304cb424b67f0ee6b12dc03aae | Bin 0 -> 320 bytes .../f4/8097eb340dc5a7cae55aabcf1faf4548aa821f | Bin 0 -> 165 bytes .../f5/504f36e6f4eb797a56fc5bac6c6c7f32969bf2 | Bin 0 -> 42 bytes .../f5/b50c85a87cac64d7eb3254cdd1aec9564c0293 | Bin 0 -> 35 bytes .../f5/f9dd5886a6ee20272be0aafc790cba43b31931 | Bin 0 -> 244 bytes .../f6/be049e284c0f9dcbbc745543885be3502ea521 | Bin 0 -> 265 bytes .../f7/c332bd4d4d4b777366cae4d24d1687477576bf | Bin 0 -> 156 bytes .../f8/958bdf4d365a84a9a178b1f5f35ff1dacbd884 | 2 + .../fa/c03f2c5139618d87d53614c153823bf1f31396 | Bin 0 -> 76 bytes .../fa/da9356aa3f74622327a3038ae9c6f92e1c5c1d | Bin 0 -> 168 bytes .../fb/738a106cfd097a4acb96ce132ecb1ad6c46b03 | Bin 0 -> 264 bytes .../fc/4c636d6515e9e261f9260dbcf3cc6eca97ea08 | Bin 0 -> 29 bytes .../fc/7d7b805f7a9428574f4f802b2e34cd20ab9d99 | Bin 0 -> 575 bytes .../fc/90237dc4891fa6c69827fc465632225e391618 | Bin 0 -> 163 bytes .../fd/57d2d6770fad8e9959124793a17f441b571e66 | Bin 0 -> 279 bytes .../fd/89f8cffb663ac89095a0f9764902e93ceaca6a | 2 + .../fe/5407fc50a53aecb41d1a6e9ea7b612e581af87 | Bin 0 -> 48 bytes .../ff/49d07869831ad761bbdaea026086f8789bcb00 | Bin 0 -> 24 bytes .../ff/b312248d607284c290023f9502eea010d34efd | Bin 0 -> 68 bytes .../merge-resolve/.gitted/refs/heads/branch | 1 + .../merge-resolve/.gitted/refs/heads/df_ancestor | 1 + .../merge-resolve/.gitted/refs/heads/df_side1 | 1 + .../merge-resolve/.gitted/refs/heads/df_side2 | 1 + .../merge-resolve/.gitted/refs/heads/ff_branch | 1 + .../merge-resolve/.gitted/refs/heads/master | 1 + .../merge-resolve/.gitted/refs/heads/octo1 | 1 + .../merge-resolve/.gitted/refs/heads/octo2 | 1 + .../merge-resolve/.gitted/refs/heads/octo3 | 1 + .../merge-resolve/.gitted/refs/heads/octo4 | 1 + .../merge-resolve/.gitted/refs/heads/octo5 | 1 + .../merge-resolve/.gitted/refs/heads/octo6 | 1 + .../.gitted/refs/heads/rename_conflict_ancestor | 1 + .../.gitted/refs/heads/rename_conflict_ours | 1 + .../.gitted/refs/heads/rename_conflict_theirs | 1 + .../merge-resolve/.gitted/refs/heads/renames1 | 1 + .../merge-resolve/.gitted/refs/heads/renames2 | 1 + .../merge-resolve/.gitted/refs/heads/trivial-10 | 1 + .../.gitted/refs/heads/trivial-10-branch | 1 + .../merge-resolve/.gitted/refs/heads/trivial-11 | 1 + .../.gitted/refs/heads/trivial-11-branch | 1 + .../merge-resolve/.gitted/refs/heads/trivial-13 | 1 + .../.gitted/refs/heads/trivial-13-branch | 1 + .../merge-resolve/.gitted/refs/heads/trivial-14 | 1 + .../.gitted/refs/heads/trivial-14-branch | 1 + .../merge-resolve/.gitted/refs/heads/trivial-2alt | 1 + .../.gitted/refs/heads/trivial-2alt-branch | 1 + .../merge-resolve/.gitted/refs/heads/trivial-3alt | 1 + .../.gitted/refs/heads/trivial-3alt-branch | 1 + .../merge-resolve/.gitted/refs/heads/trivial-4 | 1 + .../.gitted/refs/heads/trivial-4-branch | 1 + .../.gitted/refs/heads/trivial-5alt-1 | 1 + .../.gitted/refs/heads/trivial-5alt-1-branch | 1 + .../.gitted/refs/heads/trivial-5alt-2 | 1 + .../.gitted/refs/heads/trivial-5alt-2-branch | 1 + .../merge-resolve/.gitted/refs/heads/trivial-6 | 1 + .../.gitted/refs/heads/trivial-6-branch | 1 + .../merge-resolve/.gitted/refs/heads/trivial-7 | 1 + .../.gitted/refs/heads/trivial-7-branch | 1 + .../merge-resolve/.gitted/refs/heads/trivial-8 | 1 + .../.gitted/refs/heads/trivial-8-branch | 1 + .../merge-resolve/.gitted/refs/heads/trivial-9 | 1 + .../.gitted/refs/heads/trivial-9-branch | 1 + .../merge-resolve/.gitted/refs/heads/unrelated | 1 + tests/resources/merge-resolve/added-in-master.txt | 1 + tests/resources/merge-resolve/automergeable.txt | 9 + .../resources/merge-resolve/changed-in-branch.txt | 1 + .../resources/merge-resolve/changed-in-master.txt | 1 + tests/resources/merge-resolve/conflicting.txt | 1 + .../resources/merge-resolve/removed-in-branch.txt | 1 + tests/resources/merge-resolve/unchanged.txt | 1 + tests/resources/mergedrepo/.gitted/COMMIT_EDITMSG | 1 + tests/resources/mergedrepo/.gitted/HEAD | 1 + tests/resources/mergedrepo/.gitted/MERGE_HEAD | 1 + tests/resources/mergedrepo/.gitted/MERGE_MODE | 0 tests/resources/mergedrepo/.gitted/MERGE_MSG | 5 + tests/resources/mergedrepo/.gitted/ORIG_HEAD | 1 + tests/resources/mergedrepo/.gitted/config | 6 + tests/resources/mergedrepo/.gitted/description | 1 + tests/resources/mergedrepo/.gitted/index | Bin 0 -> 842 bytes tests/resources/mergedrepo/.gitted/info/exclude | 6 + tests/resources/mergedrepo/.gitted/logs/HEAD | 5 + .../mergedrepo/.gitted/logs/refs/heads/branch | 2 + .../mergedrepo/.gitted/logs/refs/heads/master | 2 + .../03/db1d37504ca0c4f7c26d7776b0e28bdea08712 | Bin 0 -> 141 bytes .../17/0efc1023e0ed2390150bb4469c8456b63e8f91 | Bin 0 -> 141 bytes .../1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 | Bin 0 -> 34 bytes .../22/0bd62631c8cf7a83ef39c6b94595f00517211e | Bin 0 -> 42 bytes .../32/d55d59265db86dd690f0a7fc563db43e2bc6a6 | Bin 0 -> 159 bytes .../38/e2d82b9065a237904af4b780b4d68da6950534 | Bin 0 -> 74 bytes .../3a/34580a35add43a4cf361e8e9a30060a905c876 | 2 + .../44/58b8bc9e72b6c8755ae456f60e9844d0538d8c | Bin 0 -> 39 bytes .../47/8871385b9cd03908c5383acfd568bef023c6b3 | Bin 0 -> 36 bytes .../51/6bd85f78061e09ccc714561d7b504672cb52da | Bin 0 -> 36 bytes .../53/c1d95a01f4514b162066fc98564500c96c46ad | Bin 0 -> 45 bytes .../6a/ea5f295304c36144ad6e9247a291b7f8112399 | Bin 0 -> 49 bytes .../70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 | Bin 0 -> 85 bytes .../75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 | Bin 0 -> 41 bytes .../7b/26923aaf452b1977eb08617c59475fb3f74b71 | Bin 0 -> 41 bytes .../84/af62840be1b1c47b778a8a249f3ff45155038c | Bin 0 -> 40 bytes .../88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda | Bin 0 -> 66 bytes .../88/7b153b165d32409c70163e0f734c090f12f673 | Bin 0 -> 38 bytes .../8a/ad34cc83733590e74b93d0f7cf00375e2a735a | Bin 0 -> 78 bytes .../8b/3f43d2402825c200f835ca1762413e386fd0b2 | Bin 0 -> 57 bytes .../8b/72416545c7e761b64cecad4f1686eae4078aa8 | Bin 0 -> 38 bytes .../8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 | Bin 0 -> 39 bytes .../8f/fcc405925511824a2240a6d3686aa7f8c7ac50 | Bin 0 -> 140 bytes .../9a/05ccb4e0f948de03128e095f39dae6976751c5 | 1 + .../9d/81f82fccc7dcd7de7a1ffead1815294c2e092c | Bin 0 -> 36 bytes .../b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d | Bin 0 -> 66 bytes .../d0/1885ea594926eae9ba5b54ad76692af5969f51 | Bin 0 -> 55 bytes .../e2/809157a7766f272e4cfe26e61ef2678a5357ff | 3 + .../e6/2cac5c88b9928f2695b934c70efa4285324478 | Bin 0 -> 87 bytes .../f7/2784290c151092abf04ce6b875068547f70406 | Bin 0 -> 141 bytes .../resources/mergedrepo/.gitted/refs/heads/branch | 1 + .../resources/mergedrepo/.gitted/refs/heads/master | 1 + tests/resources/mergedrepo/conflicts-one.txt | 5 + tests/resources/mergedrepo/conflicts-two.txt | 5 + tests/resources/mergedrepo/one.txt | 10 + tests/resources/mergedrepo/two.txt | 12 + tests/resources/partial-testrepo/.gitted/HEAD | 1 + tests/resources/partial-testrepo/.gitted/config | 7 + tests/resources/partial-testrepo/.gitted/index | Bin 0 -> 328 bytes .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 0 -> 19 bytes .../14/4344043ba4d4a405da03de3844aa829ae8be0e | Bin 0 -> 163 bytes .../16/8e4ebd1c667499548ae12403b19b22a5c5e925 | Bin 0 -> 147 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 0 -> 51 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 0 -> 119 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 0 -> 18 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 + .../4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 | Bin 0 -> 50 bytes .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 + .../62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc | Bin 0 -> 50 bytes .../66/3adb09143767984f7be83a91effa47e128c735 | Bin 0 -> 19 bytes .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 0 -> 119 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 0 -> 82 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 0 -> 126 bytes .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 + .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 + .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 0 -> 28 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 0 -> 26 bytes .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 + .../cf/80f8de9f1185bf3a05f993f6121880dd0cfbc9 | Bin 0 -> 162 bytes .../d5/2a8fe84ceedf260afe4f0287bbfca04a117e83 | Bin 0 -> 147 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 0 -> 82 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 0 -> 24 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 0 -> 82 bytes .../partial-testrepo/.gitted/objects/pack/.gitkeep | 0 .../partial-testrepo/.gitted/refs/heads/dir | 1 + tests/resources/peeled.git/HEAD | 1 + tests/resources/peeled.git/config | 8 + tests/resources/peeled.git/objects/info/packs | 2 + ...ck-e84773eaf3fce1774755580e3dbb8d9f3a1adc45.idx | Bin 0 -> 1156 bytes ...k-e84773eaf3fce1774755580e3dbb8d9f3a1adc45.pack | Bin 0 -> 274 bytes tests/resources/peeled.git/packed-refs | 6 + tests/resources/peeled.git/refs/heads/master | 1 + tests/resources/push.sh | 55 + tests/resources/push_src/.gitted/COMMIT_EDITMSG | 1 + tests/resources/push_src/.gitted/HEAD | 1 + tests/resources/push_src/.gitted/ORIG_HEAD | 1 + tests/resources/push_src/.gitted/config | 10 + tests/resources/push_src/.gitted/description | 1 + tests/resources/push_src/.gitted/index | Bin 0 -> 470 bytes tests/resources/push_src/.gitted/info/exclude | 6 + tests/resources/push_src/.gitted/logs/HEAD | 10 + .../resources/push_src/.gitted/logs/refs/heads/b1 | 1 + .../resources/push_src/.gitted/logs/refs/heads/b2 | 1 + .../resources/push_src/.gitted/logs/refs/heads/b3 | 2 + .../resources/push_src/.gitted/logs/refs/heads/b4 | 2 + .../resources/push_src/.gitted/logs/refs/heads/b5 | 2 + .../push_src/.gitted/logs/refs/heads/master | 3 + .../push_src/.gitted/modules/submodule/HEAD | 1 + .../push_src/.gitted/modules/submodule/config | 15 + .../push_src/.gitted/modules/submodule/description | 1 + .../push_src/.gitted/modules/submodule/index | Bin 0 -> 256 bytes .../.gitted/modules/submodule/info/exclude | 6 + .../push_src/.gitted/modules/submodule/logs/HEAD | 1 + .../modules/submodule/logs/refs/heads/master | 1 + .../submodule/logs/refs/remotes/origin/HEAD | 1 + .../08/b041783f40edfe12bb406c9c9a8a040177c125 | Bin 0 -> 54 bytes .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 0 -> 19 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 0 -> 51 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 0 -> 119 bytes .../1a/443023183e3f2bfbef8ac923cd81c1018a18fd | Bin 0 -> 122 bytes .../1b/8cbad43e867676df601306689fe7c3def5e689 | Bin 0 -> 51 bytes .../1f/67fc4386b2d171e0d21be1c447e12660561f9b | Bin 0 -> 21 bytes .../25/8f0e2a959a364e40ed6603d5d44fbb24765b10 | Bin 0 -> 168 bytes .../27/0b8ea76056d5cad83af921837702d3e3c2924d | Bin 0 -> 21 bytes .../2d/59075e0681f540482d4f6223a68e0fef790bc7 | Bin 0 -> 44 bytes .../32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 | Bin 0 -> 50 bytes .../36/97d64be941a53d4ae8f6a271e4e3fa56b022cc | Bin 0 -> 23 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 0 -> 18 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 + .../4b/22b35d44b5a4f589edf3dc89196399771796ea | Bin 0 -> 44 bytes .../52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 | Bin 0 -> 152 bytes .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 + .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 0 -> 119 bytes .../76/3d71aadf09a7951596c9746c024e7eece7c7af | 1 + .../7b/4384978d2493e851f9cca7858815fac9b10980 | Bin 0 -> 145 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 0 -> 82 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 0 -> 126 bytes .../84/9a5e34a26815e821f865b8479f5815a47af0fe | 2 + .../94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 | 1 + .../9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 | Bin 0 -> 50 bytes .../9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 | 2 + .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 + .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 + .../a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 | 3 + .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 0 -> 28 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 0 -> 26 bytes .../ae/90f12eea699729ed24555e40b9fd669da12a12 | Bin 0 -> 148 bytes .../b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 | 2 + .../b6/361fc6a97178d8fc8639fdeed71c775ab52593 | Bin 0 -> 80 bytes .../be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 | 3 + .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 + .../d0/7b0f9a8c89f1d9e74dc4fce6421dec5ef8a659 | Bin 0 -> 149 bytes .../d6/c93164c249c8000205dd4ec5cbca1b516d487f | Bin 0 -> 21 bytes .../d7/1aab4f9b04b45ce09bcaa636a9be6231474759 | Bin 0 -> 79 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes .../e7/b4ad382349ff96dd8199000580b9b1e2042eb0 | Bin 0 -> 21 bytes .../f1/425cef211cc08caa31e7b545ffb232acb098c3 | Bin 0 -> 103 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 0 -> 82 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 0 -> 24 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 0 -> 82 bytes .../fd/4959ce7510db09d4d8217fa2d1780413e05a09 | Bin 0 -> 152 bytes ...ck-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx | Bin 0 -> 46656 bytes ...k-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack | Bin 0 -> 386089 bytes ...ck-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx | Bin 0 -> 1240 bytes ...k-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack | Bin 0 -> 491 bytes ...ck-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx | Bin 0 -> 1240 bytes ...k-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack | Bin 0 -> 498 bytes .../push_src/.gitted/modules/submodule/packed-refs | 24 + .../.gitted/modules/submodule/refs/heads/master | 1 + .../modules/submodule/refs/remotes/origin/HEAD | 1 + .../08/585692ce06452da6f82ae66b90d98b55536fca | 1 + .../27/b7ce66243eb1403862d05f958c002312df173d | 4 + .../28/905c54ea45a4bed8d7b90f51bd8bd81eec8840 | Bin 0 -> 109 bytes .../36/6226fb970ac0caa9d3f55967ab01334a548f60 | Bin 0 -> 20 bytes .../36/f79b2846017d3761e0a02d0bccd573e0f90c57 | 2 + .../5c/0bb3d1b9449d1cc69d7519fd05166f01840915 | Bin 0 -> 128 bytes .../61/780798228d17af2d34fce4cfbdf35556832472 | Bin 0 -> 17 bytes .../64/fd55f9b6390202db5e5666fd1fb339089fba4d | Bin 0 -> 176 bytes .../78/981922613b2afb6025042ff6bd878ac1994e85 | Bin 0 -> 17 bytes .../80/5c54522e614f29f70d2413a0470247d8b424ac | Bin 0 -> 131 bytes .../95/1bbbb90e2259a4c8950db78946784fb53fcbce | 2 + .../a7/8705c3b2725f931d3ee05348d83cc26700f247 | Bin 0 -> 166 bytes .../b4/83ae7ba66decee9aee971f501221dea84b1498 | 3 + .../b4/e1f2b375a64c1ccd40c5ff6aa8bc96839ba4fd | Bin 0 -> 148 bytes .../c1/0409136a7a75e025fa502a1b2fd7b62b77d279 | Bin 0 -> 22 bytes .../cd/881f90f2933db2e4cc26b8c71fe6037ac7fe4c | Bin 0 -> 80 bytes .../d9/b63a88223d8367516f50bd131a5f7349b7f3e4 | 2 + .../dc/ab83249f6f9d1ed735d651352a80519339b591 | Bin 0 -> 80 bytes .../ee/a4f2705eeec2db3813f2430829afce99cd00b5 | Bin 0 -> 141 bytes .../f7/8a3106c85fb549c65198b2a2086276c6174928 | Bin 0 -> 65 bytes .../f8/f7aefc2900a3d737cea9eee45729fd55761e1a | Bin 0 -> 50 bytes .../fa/38b91f199934685819bea316186d8b008c52a2 | 2 + .../ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e | 4 + .../ff/fe95c7fd0a37fa2ed702f8f93b56b2196b3925 | Bin 0 -> 109 bytes .../resources/push_src/.gitted/objects/pack/dummy | 0 tests/resources/push_src/.gitted/refs/heads/b1 | 1 + tests/resources/push_src/.gitted/refs/heads/b2 | 1 + tests/resources/push_src/.gitted/refs/heads/b3 | 1 + tests/resources/push_src/.gitted/refs/heads/b4 | 1 + tests/resources/push_src/.gitted/refs/heads/b5 | 1 + tests/resources/push_src/.gitted/refs/heads/b6 | 1 + .../resources/push_src/.gitted/refs/tags/tag-blob | 1 + .../push_src/.gitted/refs/tags/tag-commit | 1 + .../push_src/.gitted/refs/tags/tag-commit-two | 1 + .../push_src/.gitted/refs/tags/tag-lightweight | 1 + tests/resources/push_src/.gitted/refs/tags/tag-tag | 1 + .../resources/push_src/.gitted/refs/tags/tag-tree | 1 + tests/resources/push_src/a.txt | 2 + tests/resources/push_src/fold/b.txt | 1 + tests/resources/push_src/foldb.txt | 1 + tests/resources/push_src/gitmodules | 3 + tests/resources/push_src/submodule/.gitted | 1 + tests/resources/push_src/submodule/README | 1 + tests/resources/push_src/submodule/branch_file.txt | 2 + tests/resources/push_src/submodule/new.txt | 1 + tests/resources/renames/.gitted/HEAD | 1 + tests/resources/renames/.gitted/config | 7 + tests/resources/renames/.gitted/description | 1 + tests/resources/renames/.gitted/index | Bin 0 -> 352 bytes tests/resources/renames/.gitted/info/exclude | 6 + tests/resources/renames/.gitted/logs/HEAD | 4 + .../renames/.gitted/logs/refs/heads/master | 4 + .../03/da7ad872536bd448da8d88eb7165338bf923a7 | Bin 0 -> 90 bytes .../17/58bdd7c16a72ff7c17d8de0c957ced3ccad645 | 5 + .../19/dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 | 1 + .../1c/068dee5790ef1580cfc4cd670915b48d790084 | Bin 0 -> 176 bytes .../2b/c7f351d20b53f1c72c16c4b036e491c478c49a | Bin 0 -> 173 bytes .../31/e47d8c1fa36d7f8d537b96158e3f024de0a9f2 | Bin 0 -> 131 bytes .../35/92953ff3ea5e8ba700c429f3aefe33c8806754 | Bin 0 -> 80 bytes .../36/020db6cdacaa93497f31edcd8f242ff9bc366d | Bin 0 -> 431 bytes .../3c/04741dd4b96c4ae4b00ec0f6e10c816a30aad2 | Bin 0 -> 159 bytes .../42/10ffd5c390b21dd5483375e75288dea9ede512 | Bin 0 -> 1145 bytes .../44/4a76ed3e45b183753f49376af30da8c3fe276a | Bin 0 -> 135 bytes .../47/184c1e7eb22abcbed2bf4ee87d4e38096f7951 | Bin 0 -> 229 bytes .../4e/4cae3e7dd56ed74bff39526d0469e554432953 | Bin 0 -> 452 bytes .../50/e90273af7d826ff0a95865bcd3ba8412c447d9 | 3 + .../5e/26abc56a5a84d89790f45416648899cbe13109 | Bin 0 -> 163 bytes .../61/8c6f2f8740bd6049b2fb9eb93fc15726462745 | Bin 0 -> 106 bytes .../66/311f5cfbe7836c27510a3ba2f43e282e2c8bba | Bin 0 -> 1155 bytes .../93/f538c45a57a87eb4c1e86f91c6ee41d66c7ba7 | Bin 0 -> 229 bytes .../9a/69d960ae94b060f56c2a8702545e2bb1abb935 | Bin 0 -> 464 bytes .../ad/0a8e55a104ac54a8a29ed4b84b49e76837a113 | Bin 0 -> 415 bytes .../b9/25b224cc91f897001a9993fbce169fdaa8858f | Bin 0 -> 76 bytes .../d7/9b202de198fa61b02424b9e25e840dc75e1323 | Bin 0 -> 421 bytes .../ea/c43f5195a2cee53b7458d8dad16aedde10711b | Bin 0 -> 118 bytes .../ea/f4a3e3bfe68585e90cada20736ace491cd100b | 5 + .../f9/0d4fc20ecddf21eebe6a37e9225d244339d2b5 | Bin 0 -> 441 bytes tests/resources/renames/.gitted/refs/heads/master | 1 + .../renames/.gitted/refs/heads/renames_similar | 1 + .../renames/.gitted/refs/heads/renames_similar_two | 1 + tests/resources/renames/ikeepsix.txt | 27 + tests/resources/renames/sixserving.txt | 25 + tests/resources/renames/songof7cities.txt | 49 + tests/resources/renames/untimely.txt | 24 + tests/resources/shallow.git/HEAD | 1 + tests/resources/shallow.git/config | 8 + ...ck-706e49b161700946489570d96153e5be4dc31ad4.idx | Bin 0 -> 1324 bytes ...k-706e49b161700946489570d96153e5be4dc31ad4.pack | Bin 0 -> 791 bytes tests/resources/shallow.git/packed-refs | 2 + tests/resources/shallow.git/refs/.gitkeep | 0 tests/resources/shallow.git/shallow | 1 + tests/resources/short_tag.git/HEAD | 1 + tests/resources/short_tag.git/config | 5 + tests/resources/short_tag.git/index | Bin 0 -> 104 bytes .../4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c | Bin 0 -> 169 bytes .../4d/5fcadc293a348e88f777dc0920f11e7d71441c | Bin 0 -> 48 bytes .../5d/a7760512a953e3c7c4e47e4392c7a4338fb729 | 1 + .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes tests/resources/short_tag.git/packed-refs | 1 + tests/resources/short_tag.git/refs/heads/master | 1 + tests/resources/status/.gitted/COMMIT_EDITMSG | 1 + tests/resources/status/.gitted/HEAD | 1 + tests/resources/status/.gitted/ORIG_HEAD | 1 + tests/resources/status/.gitted/config | 6 + tests/resources/status/.gitted/description | 1 + tests/resources/status/.gitted/index | Bin 0 -> 1160 bytes tests/resources/status/.gitted/info/exclude | 8 + tests/resources/status/.gitted/logs/HEAD | 3 + .../status/.gitted/logs/refs/heads/master | 3 + .../00/17bd4ab1ec30440b17bae1680cff124ab5f1f6 | 2 + .../06/1d42a44cacde5726057b67558821d95db96f19 | Bin 0 -> 44 bytes .../18/88c805345ba265b0ee9449b8877b6064592058 | Bin 0 -> 36 bytes .../19/d9cc8584ac2c7dcf57d2680375e80f099dc481 | Bin 0 -> 22 bytes .../26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f | 2 + .../32/504b727382542f9f089e24fddac5e78533e96c | Bin 0 -> 31 bytes .../37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0 | Bin 0 -> 331 bytes .../45/2e4244b5d083ddf0460acf1ecc74db9dcfa11a | Bin 0 -> 30 bytes .../52/9a16e8e762d4acb7b9636ff540a00831f9155a | Bin 0 -> 32 bytes .../53/ace0d1cc1145a5f4fe4f78a186a60263190733 | Bin 0 -> 36 bytes .../54/52d32f1dd538eb0405e8a83cc185f79e25e80f | Bin 0 -> 29 bytes .../55/d316c9ba708999f1918e9677d01dfcae69c6b9 | Bin 0 -> 33 bytes .../70/bd9443ada07063e7fbf0b3ff5c13f7494d89c2 | Bin 0 -> 44 bytes .../73/5b6a258cd196a8f7c9428419b02c1dca93fd75 | Bin 0 -> 160 bytes .../75/6e27627e67bfbc048d01ece5819c6de733d7ea | Bin 0 -> 301 bytes .../90/6ee7711f4f4928ddcb2a5f8fbc500deba0d2a8 | Bin 0 -> 46 bytes .../90/b8c29d8ba39434d1c63e1b093daaa26e5bd972 | Bin 0 -> 41 bytes .../9c/2e02cdffa8d73e6c189074594477a6baf87960 | Bin 0 -> 268 bytes .../a0/de7e0ac200c489c41c59dfa910154a70264e6e | Bin 0 -> 29 bytes .../a6/191982709b746d5650e93c2acf34ef74e11504 | Bin 0 -> 37 bytes .../a6/be623522ce87a1d862128ac42672604f7b468b | Bin 0 -> 46 bytes .../aa/27a641456848200fdb7f7c99ba36f8a0952877 | Bin 0 -> 120 bytes .../da/bc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 | Bin 0 -> 42 bytes .../e8/ee89e15bbe9b20137715232387b3de5b28972e | Bin 0 -> 38 bytes .../e9/b9107f290627c04d097733a10055af941f6bca | Bin 0 -> 37 bytes .../ed/062903b8f6f3dccb2fa81117ba6590944ef9bd | Bin 0 -> 42 bytes tests/resources/status/.gitted/refs/heads/master | 1 + tests/resources/status/current_file | 1 + tests/resources/status/ignored_file | 1 + tests/resources/status/modified_file | 2 + tests/resources/status/new_file | 1 + tests/resources/status/staged_changes | 2 + .../resources/status/staged_changes_modified_file | 3 + tests/resources/status/staged_delete_modified_file | 1 + tests/resources/status/staged_new_file | 1 + .../resources/status/staged_new_file_modified_file | 2 + tests/resources/status/subdir.txt | 2 + tests/resources/status/subdir/current_file | 1 + tests/resources/status/subdir/modified_file | 2 + tests/resources/status/subdir/new_file | 1 + "tests/resources/status/\350\277\231" | 1 + tests/resources/submod2/.gitted/HEAD | 1 + tests/resources/submod2/.gitted/config | 20 + tests/resources/submod2/.gitted/description | 1 + tests/resources/submod2/.gitted/index | Bin 0 -> 944 bytes tests/resources/submod2/.gitted/info/exclude | 6 + tests/resources/submod2/.gitted/logs/HEAD | 4 + .../submod2/.gitted/logs/refs/heads/master | 4 + .../.gitted/modules/sm_added_and_uncommited/HEAD | 1 + .../.gitted/modules/sm_added_and_uncommited/config | 13 + .../modules/sm_added_and_uncommited/description | 1 + .../.gitted/modules/sm_added_and_uncommited/index | Bin 0 -> 192 bytes .../modules/sm_added_and_uncommited/info/exclude | 6 + .../modules/sm_added_and_uncommited/logs/HEAD | 1 + .../sm_added_and_uncommited/logs/refs/heads/master | 1 + .../logs/refs/remotes/origin/HEAD | 1 + .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 0 -> 55 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 0 -> 53 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 0 -> 93 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 0 -> 163 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 0 -> 163 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 0 -> 167 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 + .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 0 -> 93 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 + .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 + .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 0 -> 81 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 0 -> 93 bytes .../modules/sm_added_and_uncommited/packed-refs | 2 + .../sm_added_and_uncommited/refs/heads/master | 1 + .../refs/remotes/origin/HEAD | 1 + .../submod2/.gitted/modules/sm_changed_file/HEAD | 1 + .../submod2/.gitted/modules/sm_changed_file/config | 13 + .../.gitted/modules/sm_changed_file/description | 1 + .../submod2/.gitted/modules/sm_changed_file/index | Bin 0 -> 192 bytes .../.gitted/modules/sm_changed_file/info/exclude | 6 + .../.gitted/modules/sm_changed_file/logs/HEAD | 1 + .../modules/sm_changed_file/logs/refs/heads/master | 1 + .../sm_changed_file/logs/refs/remotes/origin/HEAD | 1 + .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 0 -> 55 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 0 -> 53 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 0 -> 93 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 0 -> 163 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 0 -> 163 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 0 -> 167 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 + .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 0 -> 93 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 + .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 + .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 0 -> 81 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 0 -> 93 bytes .../.gitted/modules/sm_changed_file/packed-refs | 2 + .../modules/sm_changed_file/refs/heads/master | 1 + .../sm_changed_file/refs/remotes/origin/HEAD | 1 + .../.gitted/modules/sm_changed_head/COMMIT_EDITMSG | 1 + .../submod2/.gitted/modules/sm_changed_head/HEAD | 1 + .../submod2/.gitted/modules/sm_changed_head/config | 13 + .../.gitted/modules/sm_changed_head/description | 1 + .../submod2/.gitted/modules/sm_changed_head/index | Bin 0 -> 192 bytes .../.gitted/modules/sm_changed_head/info/exclude | 6 + .../.gitted/modules/sm_changed_head/logs/HEAD | 2 + .../modules/sm_changed_head/logs/refs/heads/master | 2 + .../sm_changed_head/logs/refs/remotes/origin/HEAD | 1 + .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 0 -> 55 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 0 -> 53 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 0 -> 93 bytes .../3d/9386c507f6b093471a3e324085657a3c2b4247 | 3 + .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 0 -> 163 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 0 -> 163 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 0 -> 167 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 + .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 0 -> 93 bytes .../77/fb0ed3e58568d6ad362c78de08ab8649d76e29 | Bin 0 -> 93 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 + .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 + .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 0 -> 81 bytes .../8e/b1e637ed9fc8e5454fa20d38f809091f9395f4 | 2 + .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 0 -> 93 bytes .../.gitted/modules/sm_changed_head/packed-refs | 2 + .../modules/sm_changed_head/refs/heads/master | 1 + .../sm_changed_head/refs/remotes/origin/HEAD | 1 + .../submod2/.gitted/modules/sm_changed_index/HEAD | 1 + .../.gitted/modules/sm_changed_index/config | 13 + .../.gitted/modules/sm_changed_index/description | 1 + .../submod2/.gitted/modules/sm_changed_index/index | Bin 0 -> 192 bytes .../.gitted/modules/sm_changed_index/info/exclude | 6 + .../.gitted/modules/sm_changed_index/logs/HEAD | 1 + .../sm_changed_index/logs/refs/heads/master | 1 + .../sm_changed_index/logs/refs/remotes/origin/HEAD | 1 + .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 0 -> 55 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 0 -> 53 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 0 -> 93 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 0 -> 163 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 0 -> 163 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 0 -> 167 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 + .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 0 -> 93 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 + .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 + .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 0 -> 81 bytes .../a0/2d31770687965547ab7a04cee199b29ee458d6 | Bin 0 -> 134 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 0 -> 93 bytes .../.gitted/modules/sm_changed_index/packed-refs | 2 + .../modules/sm_changed_index/refs/heads/master | 1 + .../sm_changed_index/refs/remotes/origin/HEAD | 1 + .../.gitted/modules/sm_changed_untracked_file/HEAD | 1 + .../modules/sm_changed_untracked_file/config | 13 + .../modules/sm_changed_untracked_file/description | 1 + .../modules/sm_changed_untracked_file/index | Bin 0 -> 192 bytes .../modules/sm_changed_untracked_file/info/exclude | 6 + .../modules/sm_changed_untracked_file/logs/HEAD | 1 + .../logs/refs/heads/master | 1 + .../logs/refs/remotes/origin/HEAD | 1 + .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 0 -> 55 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 0 -> 53 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 0 -> 93 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 0 -> 163 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 0 -> 163 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 0 -> 167 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 + .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 0 -> 93 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 + .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 + .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 0 -> 81 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 0 -> 93 bytes .../modules/sm_changed_untracked_file/packed-refs | 2 + .../sm_changed_untracked_file/refs/heads/master | 1 + .../refs/remotes/origin/HEAD | 1 + .../.gitted/modules/sm_missing_commits/HEAD | 1 + .../.gitted/modules/sm_missing_commits/config | 13 + .../.gitted/modules/sm_missing_commits/description | 1 + .../.gitted/modules/sm_missing_commits/index | Bin 0 -> 192 bytes .../modules/sm_missing_commits/info/exclude | 6 + .../.gitted/modules/sm_missing_commits/logs/HEAD | 1 + .../sm_missing_commits/logs/refs/heads/master | 1 + .../logs/refs/remotes/origin/HEAD | 1 + .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 0 -> 55 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 0 -> 53 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 0 -> 93 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 0 -> 163 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 0 -> 167 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 + .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 + .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 0 -> 81 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 0 -> 93 bytes .../.gitted/modules/sm_missing_commits/packed-refs | 2 + .../modules/sm_missing_commits/refs/heads/master | 1 + .../sm_missing_commits/refs/remotes/origin/HEAD | 1 + .../submod2/.gitted/modules/sm_unchanged/HEAD | 1 + .../submod2/.gitted/modules/sm_unchanged/config | 13 + .../.gitted/modules/sm_unchanged/description | 1 + .../submod2/.gitted/modules/sm_unchanged/index | Bin 0 -> 192 bytes .../.gitted/modules/sm_unchanged/info/exclude | 6 + .../submod2/.gitted/modules/sm_unchanged/logs/HEAD | 1 + .../modules/sm_unchanged/logs/refs/heads/master | 1 + .../sm_unchanged/logs/refs/remotes/origin/HEAD | 1 + .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 0 -> 55 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 0 -> 53 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 0 -> 93 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 0 -> 163 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 0 -> 163 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 0 -> 167 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 + .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 0 -> 93 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 + .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 + .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 0 -> 81 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 0 -> 93 bytes .../.gitted/modules/sm_unchanged/packed-refs | 2 + .../.gitted/modules/sm_unchanged/refs/heads/master | 1 + .../modules/sm_unchanged/refs/remotes/origin/HEAD | 1 + .../09/460e5b6cbcb05a3e404593c32a3aa7221eca0e | Bin 0 -> 197 bytes .../14/fe9ccf104058df25e0a08361c4494e167ef243 | 1 + .../22/ce3e0311dda73a5992d54a4a595518d3876ea7 | 4 + .../25/5546424b0efb847b1bfc91dbf7348b277f8970 | Bin 0 -> 157 bytes .../2a/30f1e6f94b20917005a21273f65b406d0f8bad | Bin 0 -> 144 bytes .../42/cfb95cd01bf9225b659b5ee3edcc78e8eeb478 | Bin 0 -> 40 bytes .../57/958699c2dc394f81cfc76950e9c3ac3025c398 | Bin 0 -> 136 bytes .../59/01da4f1c67756eeadc5121d206bec2431f253b | 2 + .../60/7d96653d4d0a4f733107f7890c2e67b55b620d | Bin 0 -> 53 bytes .../74/84482eb8db738cafa696993664607500a3f2b9 | Bin 0 -> 173 bytes .../7b/a4c5c3561daa5ab1a86215cfb0587e96d404d6 | Bin 0 -> 48 bytes .../87/3585b94bdeabccea991ea5e3ec1a277895b698 | Bin 0 -> 137 bytes .../97/4cf7c73de336b0c4e019f918f3cee367d72e84 | 2 + .../9d/bc299bc013ea253583b40bf327b5a6e4037b89 | Bin 0 -> 80 bytes .../a9/104bf89e911387244ef499413960ba472066d9 | Bin 0 -> 165 bytes .../b6/14088620bbdc1d29549d223ceba0f4419fd4cb | Bin 0 -> 110 bytes .../d4/07f19e50c1da1ff584beafe0d6dac7237c5d06 | Bin 0 -> 55 bytes .../d9/3e95571d92cceb5de28c205f1d5f3cc8b88bc8 | 2 + .../e3/b83bf274ee065eee48734cf8c6dfaf5e81471c | Bin 0 -> 246 bytes .../f5/4414c25e6d24fe39f5c3f128d7c8a17bc23833 | 2 + .../f9/90a25a74d1a8281ce2ab018ea8df66795cd60b | 1 + tests/resources/submod2/.gitted/refs/heads/master | 1 + tests/resources/submod2/README.txt | 3 + tests/resources/submod2/gitmodules | 24 + tests/resources/submod2/just_a_dir/contents | 1 + tests/resources/submod2/just_a_file | 1 + tests/resources/submod2/not-submodule/.gitted/HEAD | 1 + .../resources/submod2/not-submodule/.gitted/config | 6 + .../submod2/not-submodule/.gitted/description | 1 + .../resources/submod2/not-submodule/.gitted/index | Bin 0 -> 112 bytes .../submod2/not-submodule/.gitted/info/exclude | 6 + .../submod2/not-submodule/.gitted/logs/HEAD | 1 + .../not-submodule/.gitted/logs/refs/heads/master | 1 + .../68/e92c611b80ee1ed8f38314ff9577f0d15b2444 | Bin 0 -> 132 bytes .../71/ff9927d7c8a5639e062c38a7d35c433c424627 | Bin 0 -> 52 bytes .../f0/1d56b18efd353ef2bb93a4585d590a0847195e | Bin 0 -> 55 bytes .../not-submodule/.gitted/refs/heads/master | 1 + tests/resources/submod2/not-submodule/README.txt | 1 + tests/resources/submod2/not/.gitted/notempty | 1 + tests/resources/submod2/not/README.txt | 1 + .../submod2/sm_added_and_uncommited/.gitted | 1 + .../submod2/sm_added_and_uncommited/README.txt | 3 + .../submod2/sm_added_and_uncommited/file_to_modify | 3 + tests/resources/submod2/sm_changed_file/.gitted | 1 + tests/resources/submod2/sm_changed_file/README.txt | 3 + .../submod2/sm_changed_file/file_to_modify | 4 + tests/resources/submod2/sm_changed_head/.gitted | 1 + tests/resources/submod2/sm_changed_head/README.txt | 3 + .../submod2/sm_changed_head/file_to_modify | 4 + tests/resources/submod2/sm_changed_index/.gitted | 1 + .../resources/submod2/sm_changed_index/README.txt | 3 + .../submod2/sm_changed_index/file_to_modify | 4 + .../submod2/sm_changed_untracked_file/.gitted | 1 + .../submod2/sm_changed_untracked_file/README.txt | 3 + .../sm_changed_untracked_file/file_to_modify | 3 + .../sm_changed_untracked_file/i_am_untracked | 1 + tests/resources/submod2/sm_missing_commits/.gitted | 1 + .../submod2/sm_missing_commits/README.txt | 3 + .../submod2/sm_missing_commits/file_to_modify | 3 + tests/resources/submod2/sm_unchanged/.gitted | 1 + tests/resources/submod2/sm_unchanged/README.txt | 3 + .../resources/submod2/sm_unchanged/file_to_modify | 3 + tests/resources/submod2_target/.gitted/HEAD | 1 + tests/resources/submod2_target/.gitted/config | 6 + tests/resources/submod2_target/.gitted/description | 1 + tests/resources/submod2_target/.gitted/index | Bin 0 -> 192 bytes .../resources/submod2_target/.gitted/info/exclude | 6 + tests/resources/submod2_target/.gitted/logs/HEAD | 4 + .../submod2_target/.gitted/logs/refs/heads/master | 4 + .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 0 -> 55 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 0 -> 53 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 0 -> 93 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 0 -> 163 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 0 -> 163 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 0 -> 167 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 + .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 0 -> 93 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 + .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 + .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 0 -> 81 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 0 -> 93 bytes .../submod2_target/.gitted/refs/heads/master | 1 + tests/resources/submod2_target/README.txt | 3 + tests/resources/submod2_target/file_to_modify | 3 + tests/resources/submodules/.gitted/HEAD | 1 + tests/resources/submodules/.gitted/config | 6 + tests/resources/submodules/.gitted/description | 1 + tests/resources/submodules/.gitted/index | Bin 0 -> 408 bytes tests/resources/submodules/.gitted/info/exclude | 8 + tests/resources/submodules/.gitted/info/refs | 1 + tests/resources/submodules/.gitted/logs/HEAD | 2 + .../submodules/.gitted/logs/refs/heads/master | 2 + .../26/a3b32a9b7d97486c5557f5902e8ac94638145e | 2 + .../78/308c9251cf4eee8b25a76c7d2790c73d797357 | Bin 0 -> 97 bytes .../97/896810b3210244a62a82458b8e0819ecfc6850 | 3 + .../b6/0fd986699ba4e9e68bea07cf8e793f323ef888 | Bin 0 -> 138 bytes .../d5/f7fc3f74f7dec08280f370a975b112e8f60818 | Bin 0 -> 21 bytes .../e3/50052cc767cd1fcb37e84e9a89e701925be4ae | Bin 0 -> 120 bytes .../submodules/.gitted/objects/info/packs | 2 + ...ck-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx | Bin 0 -> 1156 bytes ...k-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack | Bin 0 -> 228 bytes tests/resources/submodules/.gitted/packed-refs | 2 + .../resources/submodules/.gitted/refs/heads/master | 1 + tests/resources/submodules/added | 1 + tests/resources/submodules/gitmodules | 6 + tests/resources/submodules/ignored | 1 + tests/resources/submodules/modified | 2 + tests/resources/submodules/testrepo/.gitted/HEAD | 1 + tests/resources/submodules/testrepo/.gitted/config | 12 + .../submodules/testrepo/.gitted/description | 1 + tests/resources/submodules/testrepo/.gitted/index | Bin 0 -> 256 bytes .../submodules/testrepo/.gitted/info/exclude | 6 + .../submodules/testrepo/.gitted/logs/HEAD | 1 + .../testrepo/.gitted/logs/refs/heads/master | 1 + .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 0 -> 19 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 0 -> 51 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 0 -> 119 bytes .../1f/67fc4386b2d171e0d21be1c447e12660561f9b | Bin 0 -> 21 bytes .../27/0b8ea76056d5cad83af921837702d3e3c2924d | Bin 0 -> 21 bytes .../32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 | Bin 0 -> 50 bytes .../36/97d64be941a53d4ae8f6a271e4e3fa56b022cc | Bin 0 -> 23 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 0 -> 18 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 + .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 + .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 0 -> 119 bytes .../76/3d71aadf09a7951596c9746c024e7eece7c7af | 1 + .../7b/4384978d2493e851f9cca7858815fac9b10980 | Bin 0 -> 145 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 0 -> 82 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 0 -> 126 bytes .../94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 | 1 + .../9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 | Bin 0 -> 50 bytes .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 + .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 + .../a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 | 3 + .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 0 -> 28 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 0 -> 26 bytes .../ae/90f12eea699729ed24555e40b9fd669da12a12 | Bin 0 -> 148 bytes .../b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 | 2 + .../b6/361fc6a97178d8fc8639fdeed71c775ab52593 | Bin 0 -> 80 bytes .../be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 | 3 + .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 + .../d6/c93164c249c8000205dd4ec5cbca1b516d487f | Bin 0 -> 21 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes .../e7/b4ad382349ff96dd8199000580b9b1e2042eb0 | Bin 0 -> 21 bytes .../f1/425cef211cc08caa31e7b545ffb232acb098c3 | Bin 0 -> 103 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 0 -> 82 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 0 -> 24 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 0 -> 82 bytes ...ck-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx | Bin 0 -> 46656 bytes ...k-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack | Bin 0 -> 386089 bytes ...ck-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx | Bin 0 -> 1240 bytes ...k-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack | Bin 0 -> 491 bytes ...ck-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx | Bin 0 -> 1240 bytes ...k-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack | Bin 0 -> 498 bytes .../submodules/testrepo/.gitted/packed-refs | 12 + .../submodules/testrepo/.gitted/refs/heads/master | 1 + .../testrepo/.gitted/refs/remotes/origin/HEAD | 1 + tests/resources/submodules/testrepo/README | 1 + .../resources/submodules/testrepo/branch_file.txt | 2 + tests/resources/submodules/testrepo/new.txt | 1 + tests/resources/submodules/unmodified | 1 + tests/resources/submodules/untracked | 1 + tests/resources/template/branches/.gitignore | 2 + tests/resources/template/description | 1 + tests/resources/template/hooks/link.sample | 1 + tests/resources/template/hooks/update.sample | 9 + tests/resources/template/info/exclude | 6 + tests/resources/testrepo.git/FETCH_HEAD | 2 + tests/resources/testrepo.git/HEAD | 1 + tests/resources/testrepo.git/HEAD_TRACKER | 1 + tests/resources/testrepo.git/config | 40 + tests/resources/testrepo.git/index | Bin 0 -> 10041 bytes tests/resources/testrepo.git/logs/HEAD | 7 + tests/resources/testrepo.git/logs/refs/heads/br2 | 2 + .../resources/testrepo.git/logs/refs/heads/master | 2 + .../testrepo.git/logs/refs/heads/not-good | 1 + .../testrepo.git/logs/refs/remotes/origin/HEAD | 1 + .../testrepo.git/logs/refs/remotes/test/master | 2 + .../08/b041783f40edfe12bb406c9c9a8a040177c125 | Bin 0 -> 54 bytes .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 0 -> 19 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 0 -> 51 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 0 -> 119 bytes .../1a/443023183e3f2bfbef8ac923cd81c1018a18fd | Bin 0 -> 122 bytes .../1b/8cbad43e867676df601306689fe7c3def5e689 | Bin 0 -> 51 bytes .../1f/67fc4386b2d171e0d21be1c447e12660561f9b | Bin 0 -> 21 bytes .../25/8f0e2a959a364e40ed6603d5d44fbb24765b10 | Bin 0 -> 168 bytes .../27/0b8ea76056d5cad83af921837702d3e3c2924d | Bin 0 -> 21 bytes .../2d/59075e0681f540482d4f6223a68e0fef790bc7 | Bin 0 -> 44 bytes .../32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 | Bin 0 -> 50 bytes .../36/97d64be941a53d4ae8f6a271e4e3fa56b022cc | Bin 0 -> 23 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 0 -> 18 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 + .../4a/23e2e65ad4e31c4c9db7dc746650bfad082679 | Bin 0 -> 83 bytes .../4b/22b35d44b5a4f589edf3dc89196399771796ea | Bin 0 -> 44 bytes .../52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 | Bin 0 -> 152 bytes .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 + .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 0 -> 119 bytes .../76/3d71aadf09a7951596c9746c024e7eece7c7af | 1 + .../7b/4384978d2493e851f9cca7858815fac9b10980 | Bin 0 -> 145 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 0 -> 82 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 0 -> 126 bytes .../84/9a5e34a26815e821f865b8479f5815a47af0fe | 2 + .../94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 | 1 + .../9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 | Bin 0 -> 50 bytes .../9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 | 2 + .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 + .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 + .../a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 | 3 + .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 0 -> 28 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 0 -> 26 bytes .../ae/90f12eea699729ed24555e40b9fd669da12a12 | Bin 0 -> 148 bytes .../b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 | 2 + .../b6/361fc6a97178d8fc8639fdeed71c775ab52593 | Bin 0 -> 80 bytes .../be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 | 3 + .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 + .../d0/7b0f9a8c89f1d9e74dc4fce6421dec5ef8a659 | Bin 0 -> 149 bytes .../d6/c93164c249c8000205dd4ec5cbca1b516d487f | Bin 0 -> 21 bytes .../d7/1aab4f9b04b45ce09bcaa636a9be6231474759 | Bin 0 -> 79 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes .../e7/b4ad382349ff96dd8199000580b9b1e2042eb0 | Bin 0 -> 21 bytes .../f1/425cef211cc08caa31e7b545ffb232acb098c3 | Bin 0 -> 103 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 0 -> 82 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 0 -> 24 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 0 -> 82 bytes .../fd/4959ce7510db09d4d8217fa2d1780413e05a09 | Bin 0 -> 152 bytes ...ck-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx | Bin 0 -> 46656 bytes ...k-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack | Bin 0 -> 386089 bytes ...ck-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx | Bin 0 -> 1240 bytes ...k-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack | Bin 0 -> 491 bytes ...ck-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx | Bin 0 -> 1240 bytes ...k-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack | Bin 0 -> 498 bytes tests/resources/testrepo.git/packed-refs | 3 + tests/resources/testrepo.git/refs/heads/br2 | 1 + .../resources/testrepo.git/refs/heads/cannot-fetch | 1 + tests/resources/testrepo.git/refs/heads/chomped | 1 + tests/resources/testrepo.git/refs/heads/haacked | 1 + tests/resources/testrepo.git/refs/heads/master | 1 + tests/resources/testrepo.git/refs/heads/not-good | 1 + .../resources/testrepo.git/refs/heads/packed-test | 1 + tests/resources/testrepo.git/refs/heads/subtrees | 1 + tests/resources/testrepo.git/refs/heads/test | 1 + .../resources/testrepo.git/refs/heads/track-local | 1 + tests/resources/testrepo.git/refs/heads/trailing | 1 + tests/resources/testrepo.git/refs/notes/fanout | 1 + .../testrepo.git/refs/remotes/test/master | 1 + .../testrepo.git/refs/tags/annotated_tag_to_blob | 1 + tests/resources/testrepo.git/refs/tags/e90810b | 1 + tests/resources/testrepo.git/refs/tags/hard_tag | 1 + .../resources/testrepo.git/refs/tags/point_to_blob | 1 + tests/resources/testrepo.git/refs/tags/taggerless | 1 + tests/resources/testrepo.git/refs/tags/test | 1 + tests/resources/testrepo.git/refs/tags/wrapped_tag | 1 + tests/resources/testrepo/.gitted/HEAD | 1 + tests/resources/testrepo/.gitted/HEAD_TRACKER | 1 + tests/resources/testrepo/.gitted/config | 8 + tests/resources/testrepo/.gitted/index | Bin 0 -> 10041 bytes .../09/9fabac3a9ea935598528c27f866e34089c2eff | 1 + .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 0 -> 19 bytes .../14/4344043ba4d4a405da03de3844aa829ae8be0e | Bin 0 -> 163 bytes .../16/8e4ebd1c667499548ae12403b19b22a5c5e925 | Bin 0 -> 147 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 0 -> 51 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 0 -> 119 bytes .../1f/67fc4386b2d171e0d21be1c447e12660561f9b | Bin 0 -> 21 bytes .../27/0b8ea76056d5cad83af921837702d3e3c2924d | Bin 0 -> 21 bytes .../32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 | Bin 0 -> 50 bytes .../36/97d64be941a53d4ae8f6a271e4e3fa56b022cc | Bin 0 -> 23 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 0 -> 18 bytes .../45/dd856fdd4d89b884c340ba0e047752d9b085d6 | Bin 0 -> 156 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 + .../4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 | Bin 0 -> 50 bytes .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 + .../62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc | Bin 0 -> 50 bytes .../66/3adb09143767984f7be83a91effa47e128c735 | Bin 0 -> 19 bytes .../6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 | Bin 0 -> 167 bytes .../6b/9b767af9992b4abad5e24ffb1ba2d688ca602e | Bin 0 -> 41 bytes .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 0 -> 119 bytes .../76/3d71aadf09a7951596c9746c024e7eece7c7af | 1 + .../7b/2417a23b63e1fdde88c80e14b33247c6e5785a | Bin 0 -> 187 bytes .../7b/4384978d2493e851f9cca7858815fac9b10980 | Bin 0 -> 145 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 0 -> 82 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 0 -> 126 bytes .../87/380ae84009e9c503506c2f6143a4fc6c60bf80 | Bin 0 -> 161 bytes .../94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 | 1 + .../9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 | Bin 0 -> 50 bytes .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 + .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 + .../a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 | 3 + .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 0 -> 28 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 0 -> 26 bytes .../ae/90f12eea699729ed24555e40b9fd669da12a12 | Bin 0 -> 148 bytes .../b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 | 2 + .../b6/361fc6a97178d8fc8639fdeed71c775ab52593 | Bin 0 -> 80 bytes .../be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 | 3 + .../c0/528fd6cc988c0a40ce0be11bc192fc8dc5346e | Bin 0 -> 22 bytes .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 + .../cf/80f8de9f1185bf3a05f993f6121880dd0cfbc9 | Bin 0 -> 162 bytes .../d5/2a8fe84ceedf260afe4f0287bbfca04a117e83 | Bin 0 -> 147 bytes .../d6/c93164c249c8000205dd4ec5cbca1b516d487f | Bin 0 -> 21 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes .../e7/b4ad382349ff96dd8199000580b9b1e2042eb0 | Bin 0 -> 21 bytes .../f1/425cef211cc08caa31e7b545ffb232acb098c3 | Bin 0 -> 103 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 0 -> 82 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 0 -> 24 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 0 -> 82 bytes ...ck-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx | Bin 0 -> 46656 bytes ...k-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack | Bin 0 -> 386089 bytes ...ck-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx | Bin 0 -> 1240 bytes ...k-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack | Bin 0 -> 491 bytes ...ck-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx | Bin 0 -> 1240 bytes ...k-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack | Bin 0 -> 498 bytes tests/resources/testrepo/.gitted/packed-refs | 4 + tests/resources/testrepo/.gitted/refs/heads/br2 | 1 + tests/resources/testrepo/.gitted/refs/heads/dir | 1 + .../testrepo/.gitted/refs/heads/long-file-name | 1 + tests/resources/testrepo/.gitted/refs/heads/master | 1 + .../testrepo/.gitted/refs/heads/packed-test | 1 + .../resources/testrepo/.gitted/refs/heads/subtrees | 1 + tests/resources/testrepo/.gitted/refs/heads/test | 1 + tests/resources/testrepo/.gitted/refs/tags/e90810b | 1 + tests/resources/testrepo/.gitted/refs/tags/foo/bar | 1 + .../testrepo/.gitted/refs/tags/foo/foo/bar | 1 + .../testrepo/.gitted/refs/tags/point_to_blob | 1 + tests/resources/testrepo/.gitted/refs/tags/test | 1 + tests/resources/testrepo2/.gitted/HEAD | 1 + tests/resources/testrepo2/.gitted/config | 14 + tests/resources/testrepo2/.gitted/description | 1 + tests/resources/testrepo2/.gitted/index | Bin 0 -> 512 bytes tests/resources/testrepo2/.gitted/info/exclude | 6 + tests/resources/testrepo2/.gitted/logs/HEAD | 1 + .../testrepo2/.gitted/logs/refs/heads/master | 1 + .../.gitted/logs/refs/remotes/origin/HEAD | 1 + .../0c/37a5391bbff43c37f0d0371823a5509eed5b1d | Bin 0 -> 134 bytes .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 0 -> 19 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 0 -> 51 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 0 -> 119 bytes .../2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 | Bin 0 -> 125 bytes .../36/060c58702ed4c2a40832c51758d5344201d89a | 2 + .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 0 -> 18 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 + .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 + .../61/9f9935957e010c419cb9d15621916ddfcc0b96 | Bin 0 -> 116 bytes .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 0 -> 119 bytes .../7f/043268ea43ce18e3540acaabf9e090c91965b0 | Bin 0 -> 55 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 0 -> 82 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 0 -> 126 bytes .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 + .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 + .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 0 -> 28 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 0 -> 26 bytes .../be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 | 3 + .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 + .../c4/dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b | Bin 0 -> 116 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 0 -> 82 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 0 -> 24 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 0 -> 82 bytes ...ck-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx | Bin 0 -> 1240 bytes ...k-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack | Bin 0 -> 491 bytes tests/resources/testrepo2/.gitted/packed-refs | 6 + .../resources/testrepo2/.gitted/refs/heads/master | 1 + .../testrepo2/.gitted/refs/remotes/origin/HEAD | 1 + tests/resources/testrepo2/README | 1 + tests/resources/testrepo2/new.txt | 1 + tests/resources/testrepo2/subdir/README | 1 + tests/resources/testrepo2/subdir/new.txt | 1 + tests/resources/testrepo2/subdir/subdir2/README | 1 + tests/resources/testrepo2/subdir/subdir2/new.txt | 1 + tests/resources/twowaymerge.git/HEAD | 1 + tests/resources/twowaymerge.git/config | 5 + tests/resources/twowaymerge.git/description | 1 + tests/resources/twowaymerge.git/info/exclude | 6 + .../0c/8a3f1f3d5f421cf83048c7c73ee3b55a5e0f29 | Bin 0 -> 157 bytes .../10/2dce8e3081f398e4bdd9fd894dc85ac3ca6a67 | Bin 0 -> 54 bytes .../17/7d8634a28e26ec7819284752757ebe01a479d5 | Bin 0 -> 80 bytes .../1c/30b88f5f3ee66d78df6520a7de9e89b890818b | 3 + .../1f/4c0311a24b63f6fc209a59a1e404942d4a5006 | 2 + .../22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 | 3 + .../29/6e56023cdc034d2735fee8c0d85a659d1b07f4 | Bin 0 -> 51 bytes .../31/51880ae2b363f1c262cf98b750c1f169a0d432 | Bin 0 -> 68 bytes .../3b/287f8730c81d0b763c2d294618a5e32b67b4f8 | Bin 0 -> 54 bytes .../42/b7311aa626e712891940c1ec5d5cba201946a4 | 3 + .../49/6d6428b9cf92981dc9495211e6e1120fb6f2ba | Bin 0 -> 46 bytes .../59/b0cf7d74659e1cdb13305319d6d4ce2733c118 | Bin 0 -> 65 bytes .../6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f | 1 + .../6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 | Bin 0 -> 68 bytes .../76/5b32c65d38f04c4f287abda055818ec0f26912 | Bin 0 -> 54 bytes .../7b/8c336c45fc6895c1c60827260fe5d798e5d247 | 3 + .../82/bf9a1a10a4b25c1f14c9607b60970705e92545 | 1 + .../8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 | 3 + .../9a/40a2f11c191f180c47e54b11567cb3c1e89b30 | Bin 0 -> 62 bytes .../9b/219343610c88a1187c996d0dc58330b55cee28 | 2 + .../9f/e06a50f4d1634d6c6879854d01d80857388706 | Bin 0 -> 65 bytes .../a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 | 3 + .../a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 | 1 + .../a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c | 1 + .../bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 | Bin 0 -> 158 bytes .../c3/7a783c20d92ac92362a78a32860f7eebf938ef | Bin 0 -> 158 bytes .../cb/dd40facab1682754eb67f7a43f29e672903cf6 | Bin 0 -> 51 bytes .../cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 | Bin 0 -> 158 bytes .../d6/f10d549cb335b9e6d38afc1f0088be69b50494 | Bin 0 -> 62 bytes .../d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e | 1 + .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes .../ef/0488f0b722f0be8bcb90a7730ac7efafd1d694 | 1 + .../fc/f7e3f51c11d199ab7a78403ee4f9ccd028da25 | Bin 0 -> 62 bytes .../twowaymerge.git/refs/heads/first-branch | 1 + tests/resources/twowaymerge.git/refs/heads/master | 1 + .../twowaymerge.git/refs/heads/second-branch | 1 + tests/resources/typechanges/.gitted/HEAD | 1 + tests/resources/typechanges/.gitted/config | 12 + tests/resources/typechanges/.gitted/description | 1 + tests/resources/typechanges/.gitted/index | Bin 0 -> 184 bytes tests/resources/typechanges/.gitted/info/exclude | 6 + tests/resources/typechanges/.gitted/modules/b/HEAD | 1 + .../resources/typechanges/.gitted/modules/b/config | 13 + .../typechanges/.gitted/modules/b/description | 1 + .../resources/typechanges/.gitted/modules/b/index | Bin 0 -> 192 bytes .../typechanges/.gitted/modules/b/info/exclude | 6 + .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 0 -> 55 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 0 -> 53 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 0 -> 93 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 0 -> 163 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 0 -> 163 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 0 -> 167 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 + .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 0 -> 93 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 + .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 + .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 0 -> 81 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 0 -> 93 bytes .../typechanges/.gitted/modules/b/packed-refs | 2 + .../.gitted/modules/b/refs/heads/master | 1 + .../.gitted/modules/b/refs/remotes/origin/HEAD | 1 + tests/resources/typechanges/.gitted/modules/d/HEAD | 1 + .../resources/typechanges/.gitted/modules/d/config | 13 + .../typechanges/.gitted/modules/d/description | 1 + .../resources/typechanges/.gitted/modules/d/index | Bin 0 -> 192 bytes .../typechanges/.gitted/modules/d/info/exclude | 6 + .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 0 -> 55 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 0 -> 53 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 0 -> 93 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 0 -> 163 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 0 -> 163 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 0 -> 167 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 + .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 0 -> 93 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 + .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 + .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 0 -> 81 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 0 -> 93 bytes .../typechanges/.gitted/modules/d/packed-refs | 2 + .../.gitted/modules/d/refs/heads/master | 1 + .../.gitted/modules/d/refs/remotes/origin/HEAD | 1 + tests/resources/typechanges/.gitted/modules/e/HEAD | 1 + .../resources/typechanges/.gitted/modules/e/config | 13 + .../typechanges/.gitted/modules/e/description | 1 + .../resources/typechanges/.gitted/modules/e/index | Bin 0 -> 192 bytes .../typechanges/.gitted/modules/e/info/exclude | 6 + .../06/362fe2fdb7010d0e447b4fb450d405420479a1 | Bin 0 -> 55 bytes .../0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 | Bin 0 -> 53 bytes .../17/d0ece6e96460a06592d9d9d000de37ba4232c5 | Bin 0 -> 93 bytes .../41/bd4bc3df978de695f67ace64c560913da11653 | Bin 0 -> 163 bytes .../48/0095882d281ed676fe5b863569520e54a7d5c0 | Bin 0 -> 163 bytes .../5e/4963595a9774b90524d35a807169049de8ccad | Bin 0 -> 167 bytes .../6b/31c659545507c381e9cd34ec508f16c04e149e | 2 + .../73/ba924a80437097795ae839e66e187c55d3babf | Bin 0 -> 93 bytes .../78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a | 2 + .../78/9efbdadaa4a582778d4584385495559ea0994b | 2 + .../88/34b635dd468a83cb012f6feace968c1c9f5d6e | Bin 0 -> 81 bytes .../d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 | Bin 0 -> 93 bytes .../typechanges/.gitted/modules/e/packed-refs | 2 + .../.gitted/modules/e/refs/heads/master | 1 + .../.gitted/modules/e/refs/remotes/origin/HEAD | 1 + .../0d/78578795b7ca49fd8df6c4b6d27c5c02d991d8 | Bin 0 -> 76 bytes .../0e/7ed140b514b8cae23254cb8656fe1674403aff | Bin 0 -> 162 bytes .../0f/f461da9689266f482d8f6654a4400b4e33c586 | Bin 0 -> 486 bytes .../18/aa7e45bbe4c3cc24a0b079696c59d36675af97 | Bin 0 -> 89 bytes .../1b/63caae4a5ca96f78e8dfefc376c6a39a142475 | Bin 0 -> 161 bytes .../1e/abe82aa3b2365a394f6108f24435df6e193d02 | Bin 0 -> 549 bytes .../42/061c01a1c70097d1e4579f29a5adf40abdec95 | Bin 0 -> 24 bytes .../46/2838cee476a87e7cff32196b66fa18ed756592 | Bin 0 -> 76 bytes .../63/499e4ea8e096b831515ceb1d5a7593e4d87ae5 | Bin 0 -> 18 bytes .../68/1af94e10eaf262f3ab7cb9b8fd5f4158ba4d3e | Bin 0 -> 24 bytes .../6a/9008602b811e69a9b7a2d83496f39a794fdeeb | Bin 0 -> 602 bytes .../6e/ae26c90e8ccc4d16208972119c40635489c6f0 | Bin 0 -> 160 bytes .../6f/39eabbb8a7541515e0d35971078bccb502e7e0 | Bin 0 -> 66 bytes .../71/54d3083461536dfc71ad5542f3e65e723a06c4 | Bin 0 -> 657 bytes .../75/56c1d893a4c0ca85ac8ac51de47ff399758729 | Bin 0 -> 226 bytes .../76/fef844064c26d5e06c2508240dae661e7231b2 | Bin 0 -> 66 bytes .../79/b9f23e85f55ea36a472a902e875bc1121a94cb | 2 + .../85/28da0ea65eacf1f74f9ed6696adbac547963ad | Bin 0 -> 451 bytes .../8b/3726b365824ad5a07c537247f4bc73ed7d37ea | Bin 0 -> 76 bytes .../93/3e28c1c8a68838a763d250bdf0b2c6068289c3 | Bin 0 -> 226 bytes .../96/2710fe5b4e453e9e827945b3487c525968ec4a | Bin 0 -> 76 bytes .../96/6cf1b3598e195b31b2cde3784f9a19f0728a6f | Bin 0 -> 226 bytes .../99/e8bab9ece009f0fba7eb41f850f4c12bedb9b7 | Bin 0 -> 701 bytes .../9b/19edf33a03a0c59cdfc113bfa5c06179bf9b1a | 5 + .../9b/db75b73836a99e3dbeea640a81de81031fdc29 | Bin 0 -> 162 bytes .../9d/0235c7a7edc0889a18f97a42ee6db9fe688447 | Bin 0 -> 160 bytes .../9e/ffc457877f109b2a4319e14bee613a15f2a00d | Bin 0 -> 226 bytes .../a0/a9bad6f6f40325198f938a0e3ae981622d7707 | Bin 0 -> 54 bytes .../b1/977dc4e573b812d4619754c98138c56999dc0d | Bin 0 -> 518 bytes .../d7/5992dd02391e128dac332dcc78d649dd9ab095 | Bin 0 -> 577 bytes .../da/e2709d638df52212b1f43ff61797ebfedfcc7c | Bin 0 -> 78 bytes .../e1/152adcb9adf37ec551ada9ba377ab53aec3bad | Bin 0 -> 19 bytes .../e4/ed436a9eb0f198cda722886a5f8d6d6c836b7b | Bin 0 -> 225 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes .../f2/0b79342712e0b2315647cd8227a573fd3bc46e | Bin 0 -> 66 bytes .../fd/e0147e3b59f381635a3b016e3fe6dacb70779d | Bin 0 -> 53 bytes .../typechanges/.gitted/refs/heads/master | 1 + tests/resources/typechanges/README.md | 43 + tests/resources/typechanges/gitmodules | 0 tests/resources/unsymlinked.git/HEAD | 1 + tests/resources/unsymlinked.git/config | 6 + tests/resources/unsymlinked.git/description | 1 + tests/resources/unsymlinked.git/info/exclude | 2 + .../08/8b64704e0d6b8bd061dea879418cb5442a3fbf | Bin 0 -> 49 bytes .../13/a5e939bca25940c069fd2169d993dba328e30b | Bin 0 -> 44 bytes .../19/bf568e59e3a0b363cafb4106226e62d4a4c41c | Bin 0 -> 29 bytes .../58/1fadd35b4cf320d102a152f918729011604773 | Bin 0 -> 47 bytes .../5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c | Bin 0 -> 78 bytes .../6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 | Bin 0 -> 49 bytes .../7f/ccd75616ec188b8f1b23d67506a334cc34a49d | Bin 0 -> 132 bytes .../80/6999882bf91d24241e4077906b9017605eb1f3 | Bin 0 -> 170 bytes .../83/7d176303c5005505ec1e4a30231c40930c0230 | Bin 0 -> 44 bytes .../a8/595ccca04f40818ae0155c8f9c77a230e597b6 | 2 + .../cf/8f1cf5cce859c438d6cc067284cb5e161206e7 | Bin 0 -> 49 bytes .../d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a | Bin 0 -> 49 bytes .../f4/e16fb76536591a41454194058d048d8e4dd2e9 | Bin 0 -> 44 bytes .../f9/e65619d93fdf2673882e0a261c5e93b1a84006 | Bin 0 -> 32 bytes .../resources/unsymlinked.git/refs/heads/exe-file | 1 + tests/resources/unsymlinked.git/refs/heads/master | 1 + .../resources/unsymlinked.git/refs/heads/reg-file | 1 + tests/revwalk/basic.c | 254 ++++ tests/revwalk/mergebase.c | 392 +++++ tests/revwalk/signatureparsing.c | 47 + tests/revwalk/simplify.c | 55 + tests/stash/drop.c | 174 +++ tests/stash/foreach.c | 124 ++ tests/stash/save.c | 354 +++++ tests/stash/stash_helpers.c | 56 + tests/stash/stash_helpers.h | 8 + tests/stash/submodules.c | 80 ++ tests/status/ignore.c | 582 ++++++++ tests/status/renames.c | 557 ++++++++ tests/status/single.c | 45 + tests/status/status_data.h | 326 +++++ tests/status/status_helpers.c | 101 ++ tests/status/status_helpers.h | 39 + tests/status/submodules.c | 223 +++ tests/status/worktree.c | 875 ++++++++++++ tests/status/worktree_init.c | 341 +++++ tests/stress/diff.c | 146 ++ tests/submodule/lookup.c | 172 +++ tests/submodule/modify.c | 253 ++++ tests/submodule/status.c | 425 ++++++ tests/submodule/submodule_helpers.c | 127 ++ tests/submodule/submodule_helpers.h | 5 + tests/threads/basic.c | 36 + tests/threads/refdb.c | 213 +++ tests/trace/trace.c | 87 ++ tests/valgrind-supp-mac.txt | 184 +++ 4124 files changed, 55912 insertions(+), 55912 deletions(-) delete mode 100644 tests-clar/README.md delete mode 100644 tests-clar/attr/attr_expect.h delete mode 100644 tests-clar/attr/file.c delete mode 100644 tests-clar/attr/flags.c delete mode 100644 tests-clar/attr/ignore.c delete mode 100644 tests-clar/attr/lookup.c delete mode 100644 tests-clar/attr/repo.c delete mode 100644 tests-clar/blame/blame_helpers.c delete mode 100644 tests-clar/blame/blame_helpers.h delete mode 100644 tests-clar/blame/buffer.c delete mode 100644 tests-clar/blame/getters.c delete mode 100644 tests-clar/blame/harder.c delete mode 100644 tests-clar/blame/simple.c delete mode 100644 tests-clar/buf/basic.c delete mode 100644 tests-clar/buf/splice.c delete mode 100644 tests-clar/checkout/binaryunicode.c delete mode 100644 tests-clar/checkout/checkout_helpers.c delete mode 100644 tests-clar/checkout/checkout_helpers.h delete mode 100644 tests-clar/checkout/conflict.c delete mode 100644 tests-clar/checkout/crlf.c delete mode 100644 tests-clar/checkout/head.c delete mode 100644 tests-clar/checkout/index.c delete mode 100644 tests-clar/checkout/tree.c delete mode 100644 tests-clar/checkout/typechange.c delete mode 100644 tests-clar/clar.c delete mode 100644 tests-clar/clar.h delete mode 100644 tests-clar/clar/fixtures.h delete mode 100644 tests-clar/clar/fs.h delete mode 100644 tests-clar/clar/print.h delete mode 100644 tests-clar/clar/sandbox.h delete mode 100644 tests-clar/clar_libgit2.c delete mode 100644 tests-clar/clar_libgit2.h delete mode 100644 tests-clar/clone/empty.c delete mode 100644 tests-clar/clone/nonetwork.c delete mode 100644 tests-clar/commit/commit.c delete mode 100644 tests-clar/commit/parent.c delete mode 100644 tests-clar/commit/parse.c delete mode 100644 tests-clar/commit/signature.c delete mode 100644 tests-clar/commit/write.c delete mode 100644 tests-clar/config/add.c delete mode 100644 tests-clar/config/backend.c delete mode 100644 tests-clar/config/config_helpers.c delete mode 100644 tests-clar/config/config_helpers.h delete mode 100644 tests-clar/config/configlevel.c delete mode 100644 tests-clar/config/global.c delete mode 100644 tests-clar/config/include.c delete mode 100644 tests-clar/config/multivar.c delete mode 100644 tests-clar/config/new.c delete mode 100644 tests-clar/config/read.c delete mode 100644 tests-clar/config/refresh.c delete mode 100644 tests-clar/config/stress.c delete mode 100644 tests-clar/config/validkeyname.c delete mode 100644 tests-clar/config/write.c delete mode 100644 tests-clar/core/bitvec.c delete mode 100644 tests-clar/core/buffer.c delete mode 100644 tests-clar/core/caps.c delete mode 100644 tests-clar/core/copy.c delete mode 100644 tests-clar/core/dirent.c delete mode 100644 tests-clar/core/env.c delete mode 100644 tests-clar/core/errors.c delete mode 100644 tests-clar/core/filebuf.c delete mode 100644 tests-clar/core/hex.c delete mode 100644 tests-clar/core/iconv.c delete mode 100644 tests-clar/core/mkdir.c delete mode 100644 tests-clar/core/oid.c delete mode 100644 tests-clar/core/oidmap.c delete mode 100644 tests-clar/core/opts.c delete mode 100644 tests-clar/core/path.c delete mode 100644 tests-clar/core/pool.c delete mode 100644 tests-clar/core/posix.c delete mode 100644 tests-clar/core/rmdir.c delete mode 100644 tests-clar/core/sortedcache.c delete mode 100644 tests-clar/core/stat.c delete mode 100644 tests-clar/core/string.c delete mode 100644 tests-clar/core/strmap.c delete mode 100644 tests-clar/core/strtol.c delete mode 100644 tests-clar/core/vector.c delete mode 100644 tests-clar/date/date.c delete mode 100644 tests-clar/diff/blob.c delete mode 100644 tests-clar/diff/diff_helpers.c delete mode 100644 tests-clar/diff/diff_helpers.h delete mode 100644 tests-clar/diff/diffiter.c delete mode 100644 tests-clar/diff/drivers.c delete mode 100644 tests-clar/diff/index.c delete mode 100644 tests-clar/diff/iterator.c delete mode 100644 tests-clar/diff/notify.c delete mode 100644 tests-clar/diff/patch.c delete mode 100644 tests-clar/diff/pathspec.c delete mode 100644 tests-clar/diff/rename.c delete mode 100644 tests-clar/diff/submodules.c delete mode 100644 tests-clar/diff/tree.c delete mode 100644 tests-clar/diff/workdir.c delete mode 100644 tests-clar/fetchhead/fetchhead_data.h delete mode 100644 tests-clar/fetchhead/nonetwork.c delete mode 100644 tests-clar/filter/blob.c delete mode 100644 tests-clar/filter/crlf.c delete mode 100644 tests-clar/filter/crlf.h delete mode 100644 tests-clar/filter/custom.c delete mode 100644 tests-clar/filter/ident.c delete mode 100644 tests-clar/generate.py delete mode 100644 tests-clar/index/addall.c delete mode 100644 tests-clar/index/conflicts.c delete mode 100644 tests-clar/index/filemodes.c delete mode 100644 tests-clar/index/inmemory.c delete mode 100644 tests-clar/index/names.c delete mode 100644 tests-clar/index/read_tree.c delete mode 100644 tests-clar/index/rename.c delete mode 100644 tests-clar/index/reuc.c delete mode 100644 tests-clar/index/stage.c delete mode 100644 tests-clar/index/tests.c delete mode 100644 tests-clar/main.c delete mode 100644 tests-clar/merge/merge_helpers.c delete mode 100644 tests-clar/merge/merge_helpers.h delete mode 100644 tests-clar/merge/trees/automerge.c delete mode 100644 tests-clar/merge/trees/modeconflict.c delete mode 100644 tests-clar/merge/trees/renames.c delete mode 100644 tests-clar/merge/trees/treediff.c delete mode 100644 tests-clar/merge/trees/trivial.c delete mode 100644 tests-clar/merge/workdir/fastforward.c delete mode 100644 tests-clar/merge/workdir/renames.c delete mode 100644 tests-clar/merge/workdir/setup.c delete mode 100644 tests-clar/merge/workdir/simple.c delete mode 100644 tests-clar/merge/workdir/trivial.c delete mode 100644 tests-clar/network/cred.c delete mode 100644 tests-clar/network/fetchlocal.c delete mode 100644 tests-clar/network/refspecs.c delete mode 100644 tests-clar/network/remote/createthenload.c delete mode 100644 tests-clar/network/remote/isvalidname.c delete mode 100644 tests-clar/network/remote/local.c delete mode 100644 tests-clar/network/remote/remotes.c delete mode 100644 tests-clar/network/remote/rename.c delete mode 100644 tests-clar/network/urlparse.c delete mode 100644 tests-clar/notes/notes.c delete mode 100644 tests-clar/notes/notesref.c delete mode 100644 tests-clar/object/blob/filter.c delete mode 100644 tests-clar/object/blob/fromchunks.c delete mode 100644 tests-clar/object/blob/write.c delete mode 100644 tests-clar/object/cache.c delete mode 100644 tests-clar/object/commit/commitstagedfile.c delete mode 100644 tests-clar/object/lookup.c delete mode 100644 tests-clar/object/lookupbypath.c delete mode 100644 tests-clar/object/message.c delete mode 100644 tests-clar/object/peel.c delete mode 100644 tests-clar/object/raw/chars.c delete mode 100644 tests-clar/object/raw/compare.c delete mode 100644 tests-clar/object/raw/convert.c delete mode 100644 tests-clar/object/raw/data.h delete mode 100644 tests-clar/object/raw/fromstr.c delete mode 100644 tests-clar/object/raw/hash.c delete mode 100644 tests-clar/object/raw/short.c delete mode 100644 tests-clar/object/raw/size.c delete mode 100644 tests-clar/object/raw/type2string.c delete mode 100644 tests-clar/object/raw/write.c delete mode 100644 tests-clar/object/tag/list.c delete mode 100644 tests-clar/object/tag/peel.c delete mode 100644 tests-clar/object/tag/read.c delete mode 100644 tests-clar/object/tag/write.c delete mode 100644 tests-clar/object/tree/attributes.c delete mode 100644 tests-clar/object/tree/duplicateentries.c delete mode 100644 tests-clar/object/tree/frompath.c delete mode 100644 tests-clar/object/tree/read.c delete mode 100644 tests-clar/object/tree/walk.c delete mode 100644 tests-clar/object/tree/write.c delete mode 100644 tests-clar/odb/alternates.c delete mode 100644 tests-clar/odb/backend/nonrefreshing.c delete mode 100644 tests-clar/odb/foreach.c delete mode 100644 tests-clar/odb/loose.c delete mode 100644 tests-clar/odb/loose_data.h delete mode 100644 tests-clar/odb/mixed.c delete mode 100644 tests-clar/odb/pack_data.h delete mode 100644 tests-clar/odb/pack_data_one.h delete mode 100644 tests-clar/odb/packed.c delete mode 100644 tests-clar/odb/packed_one.c delete mode 100644 tests-clar/odb/sorting.c delete mode 100644 tests-clar/odb/streamwrite.c delete mode 100644 tests-clar/online/clone.c delete mode 100644 tests-clar/online/fetch.c delete mode 100644 tests-clar/online/fetchhead.c delete mode 100644 tests-clar/online/push.c delete mode 100644 tests-clar/online/push_util.c delete mode 100644 tests-clar/online/push_util.h delete mode 100644 tests-clar/pack/indexer.c delete mode 100644 tests-clar/pack/packbuilder.c delete mode 100644 tests-clar/refs/branches/create.c delete mode 100644 tests-clar/refs/branches/delete.c delete mode 100644 tests-clar/refs/branches/ishead.c delete mode 100644 tests-clar/refs/branches/iterator.c delete mode 100644 tests-clar/refs/branches/lookup.c delete mode 100644 tests-clar/refs/branches/move.c delete mode 100644 tests-clar/refs/branches/name.c delete mode 100644 tests-clar/refs/branches/remote.c delete mode 100644 tests-clar/refs/branches/upstream.c delete mode 100644 tests-clar/refs/branches/upstreamname.c delete mode 100644 tests-clar/refs/crashes.c delete mode 100644 tests-clar/refs/create.c delete mode 100644 tests-clar/refs/delete.c delete mode 100644 tests-clar/refs/foreachglob.c delete mode 100644 tests-clar/refs/isvalidname.c delete mode 100644 tests-clar/refs/iterator.c delete mode 100644 tests-clar/refs/list.c delete mode 100644 tests-clar/refs/listall.c delete mode 100644 tests-clar/refs/lookup.c delete mode 100644 tests-clar/refs/normalize.c delete mode 100644 tests-clar/refs/overwrite.c delete mode 100644 tests-clar/refs/pack.c delete mode 100644 tests-clar/refs/peel.c delete mode 100644 tests-clar/refs/read.c delete mode 100644 tests-clar/refs/ref_helpers.c delete mode 100644 tests-clar/refs/ref_helpers.h delete mode 100644 tests-clar/refs/reflog/drop.c delete mode 100644 tests-clar/refs/reflog/reflog.c delete mode 100644 tests-clar/refs/rename.c delete mode 100644 tests-clar/refs/revparse.c delete mode 100644 tests-clar/refs/setter.c delete mode 100644 tests-clar/refs/shorthand.c delete mode 100644 tests-clar/refs/unicode.c delete mode 100644 tests-clar/refs/update.c delete mode 100644 tests-clar/repo/config.c delete mode 100644 tests-clar/repo/discover.c delete mode 100644 tests-clar/repo/getters.c delete mode 100644 tests-clar/repo/hashfile.c delete mode 100644 tests-clar/repo/head.c delete mode 100644 tests-clar/repo/headtree.c delete mode 100644 tests-clar/repo/init.c delete mode 100644 tests-clar/repo/iterator.c delete mode 100644 tests-clar/repo/message.c delete mode 100644 tests-clar/repo/open.c delete mode 100644 tests-clar/repo/pathspec.c delete mode 100644 tests-clar/repo/repo_helpers.c delete mode 100644 tests-clar/repo/repo_helpers.h delete mode 100644 tests-clar/repo/setters.c delete mode 100644 tests-clar/repo/shallow.c delete mode 100644 tests-clar/repo/state.c delete mode 100644 tests-clar/reset/default.c delete mode 100644 tests-clar/reset/hard.c delete mode 100644 tests-clar/reset/mixed.c delete mode 100644 tests-clar/reset/reset_helpers.c delete mode 100644 tests-clar/reset/reset_helpers.h delete mode 100644 tests-clar/reset/soft.c delete mode 100644 tests-clar/resources/.gitattributes delete mode 100644 tests-clar/resources/.gitignore delete mode 100644 tests-clar/resources/attr/.gitted/HEAD delete mode 100644 tests-clar/resources/attr/.gitted/config delete mode 100644 tests-clar/resources/attr/.gitted/description delete mode 100644 tests-clar/resources/attr/.gitted/index delete mode 100644 tests-clar/resources/attr/.gitted/info/attributes delete mode 100644 tests-clar/resources/attr/.gitted/info/exclude delete mode 100644 tests-clar/resources/attr/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/attr/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/attr/.gitted/objects/10/8bb4e7fd7b16490dc33ff7d972151e73d7166e delete mode 100644 tests-clar/resources/attr/.gitted/objects/16/983da6643656bb44c43965ecb6855c6d574512 delete mode 100644 tests-clar/resources/attr/.gitted/objects/21/7878ab49e1314388ea2e32dc6fdb58a1b969e0 delete mode 100644 tests-clar/resources/attr/.gitted/objects/24/fa9a9fc4e202313e24b648087495441dab432b delete mode 100644 tests-clar/resources/attr/.gitted/objects/29/29de282ce999e95183aedac6451d3384559c4b delete mode 100644 tests-clar/resources/attr/.gitted/objects/2b/40c5aca159b04ea8d20ffe36cdf8b09369b14a delete mode 100644 tests-clar/resources/attr/.gitted/objects/2c/66e14f77196ea763fb1e41612c1aa2bc2d8ed2 delete mode 100644 tests-clar/resources/attr/.gitted/objects/2d/e7dfe3588f3c7e9ad59e7d50ba90e3329df9d9 delete mode 100644 tests-clar/resources/attr/.gitted/objects/37/0fe9ec224ce33e71f9e5ec2bd1142ce9937a6a delete mode 100644 tests-clar/resources/attr/.gitted/objects/3a/6df026462ebafe455af9867d27eda20a9e0974 delete mode 100644 tests-clar/resources/attr/.gitted/objects/3b/74db7ab381105dc0d28f8295a77f6a82989292 delete mode 100644 tests-clar/resources/attr/.gitted/objects/3e/42ffc54a663f9401cc25843d6c0e71a33e4249 delete mode 100644 tests-clar/resources/attr/.gitted/objects/45/141a79a77842c59a63229403220a4e4be74e3d delete mode 100644 tests-clar/resources/attr/.gitted/objects/45/5a314fa848d52ae1f11d254da4f60858fc97f4 delete mode 100644 tests-clar/resources/attr/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 delete mode 100644 tests-clar/resources/attr/.gitted/objects/4d/713dc48e6b1bd75b0d61ad078ba9ca3a56745d delete mode 100644 tests-clar/resources/attr/.gitted/objects/4e/49ba8c5b6c32ff28cd9dcb60be34df50fcc485 delete mode 100644 tests-clar/resources/attr/.gitted/objects/55/6f8c827b8e4a02ad5cab77dca2bcb3e226b0b3 delete mode 100644 tests-clar/resources/attr/.gitted/objects/58/19a185d77b03325aaf87cafc771db36f6ddca7 delete mode 100644 tests-clar/resources/attr/.gitted/objects/60/5812ab7fe421fdd325a935d35cb06a9234a7d7 delete mode 100644 tests-clar/resources/attr/.gitted/objects/6b/ab5c79cd5140d0f800917f550eb2a3dc32b0da delete mode 100644 tests-clar/resources/attr/.gitted/objects/6d/968d62c89c7d9ea23a4c9a7b665d017c3d8ffd delete mode 100644 tests-clar/resources/attr/.gitted/objects/71/7fc31f6b84f9d6fc3a4edbca259d7fc92beee2 delete mode 100644 tests-clar/resources/attr/.gitted/objects/8d/0b9df9bd30be7910ddda60548d485bc302b911 delete mode 100644 tests-clar/resources/attr/.gitted/objects/93/61f40bb97239cf55811892e14de2e344168ba1 delete mode 100644 tests-clar/resources/attr/.gitted/objects/94/da4faa0a6bfb8ee6ccf7153801a69202b31857 delete mode 100644 tests-clar/resources/attr/.gitted/objects/96/089fd31ce1d3ee2afb0ba09ba063066932f027 delete mode 100644 tests-clar/resources/attr/.gitted/objects/99/eae476896f4907224978b88e5ecaa6c5bb67a9 delete mode 100644 tests-clar/resources/attr/.gitted/objects/9e/5bdc47d6a80f2be0ea3049ad74231b94609242 delete mode 100644 tests-clar/resources/attr/.gitted/objects/9f/b40b6675dde60b5697afceae91b66d908c02d9 delete mode 100644 tests-clar/resources/attr/.gitted/objects/a0/f7217ae99f5ac3e88534f5cea267febc5fa85b delete mode 100644 tests-clar/resources/attr/.gitted/objects/a5/6bbcecaeac760cc26239384d2d4c614e7e4320 delete mode 100644 tests-clar/resources/attr/.gitted/objects/a5/d76cad53f66f1312bd995909a5bab3c0820770 delete mode 100644 tests-clar/resources/attr/.gitted/objects/a9/7cc019851d401a4f1d091cb91a15890a0dd1ba delete mode 100644 tests-clar/resources/attr/.gitted/objects/b4/35cd5689a0fb54afbeda4ac20368aa480e8f04 delete mode 100644 tests-clar/resources/attr/.gitted/objects/c0/091889c0c77142b87a1fa5123a6398a61d33e7 delete mode 100644 tests-clar/resources/attr/.gitted/objects/c4/85abe35abd4aa6fd83b076a78bbea9e2e7e06c delete mode 100644 tests-clar/resources/attr/.gitted/objects/c7/aadd770d5907a8475c29e9ee21a27b88bf675d delete mode 100644 tests-clar/resources/attr/.gitted/objects/c9/6bbb2c2557a8325ae1559e3ba79cdcecb23076 delete mode 100644 tests-clar/resources/attr/.gitted/objects/ce/39a97a7fb1fa90bcf5e711249c1e507476ae0e delete mode 100644 tests-clar/resources/attr/.gitted/objects/d5/7da33c16b14326ecb05d19bbea908f5e4c47d9 delete mode 100644 tests-clar/resources/attr/.gitted/objects/d8/00886d9c86731ae5c4a62b0b77c437015e00d2 delete mode 100644 tests-clar/resources/attr/.gitted/objects/dc/cada462d3df8ac6de596fb8c896aba9344f941 delete mode 100644 tests-clar/resources/attr/.gitted/objects/de/863bff4976c9ed7e17a4da0fd524908dc84049 delete mode 100644 tests-clar/resources/attr/.gitted/objects/e5/63cf4758f0d646f1b14b76016aa17fa9e549a4 delete mode 100644 tests-clar/resources/attr/.gitted/objects/ec/b97df2a174987475ac816e3847fc8e9f6c596b delete mode 100644 tests-clar/resources/attr/.gitted/objects/ed/f3dcee4003d71f139777898882ccd097e34c53 delete mode 100644 tests-clar/resources/attr/.gitted/objects/f2/c6d717cf4a5a3e6b02684155ab07b766982165 delete mode 100644 tests-clar/resources/attr/.gitted/objects/f5/b0af1fb4f5c0cd7aad880711d368a07333c307 delete mode 100644 tests-clar/resources/attr/.gitted/objects/fb/5067b1aef3ac1ada4b379dbcb7d17255df7d78 delete mode 100644 tests-clar/resources/attr/.gitted/objects/fe/773770c5a6cc7185580c9204b1ff18a33ff3fc delete mode 100644 tests-clar/resources/attr/.gitted/objects/ff/69f8639ce2e6010b3f33a74160aad98b48da2b delete mode 100644 tests-clar/resources/attr/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/attr/attr0 delete mode 100644 tests-clar/resources/attr/attr1 delete mode 100644 tests-clar/resources/attr/attr2 delete mode 100644 tests-clar/resources/attr/attr3 delete mode 100644 tests-clar/resources/attr/binfile delete mode 100644 tests-clar/resources/attr/dir/file delete mode 100644 tests-clar/resources/attr/file delete mode 100644 tests-clar/resources/attr/gitattributes delete mode 100644 tests-clar/resources/attr/gitignore delete mode 100644 tests-clar/resources/attr/ign delete mode 100644 tests-clar/resources/attr/macro_bad delete mode 100644 tests-clar/resources/attr/macro_test delete mode 100644 tests-clar/resources/attr/root_test1 delete mode 100644 tests-clar/resources/attr/root_test2 delete mode 100644 tests-clar/resources/attr/root_test3 delete mode 100644 tests-clar/resources/attr/root_test4.txt delete mode 100644 tests-clar/resources/attr/sub/.gitattributes delete mode 100644 tests-clar/resources/attr/sub/abc delete mode 100644 tests-clar/resources/attr/sub/dir/file delete mode 100644 tests-clar/resources/attr/sub/file delete mode 100644 tests-clar/resources/attr/sub/ign/file delete mode 100644 tests-clar/resources/attr/sub/ign/sub/file delete mode 100644 tests-clar/resources/attr/sub/sub/.gitattributes delete mode 100644 tests-clar/resources/attr/sub/sub/dir delete mode 100644 tests-clar/resources/attr/sub/sub/file delete mode 100644 tests-clar/resources/attr/sub/sub/subsub.txt delete mode 100644 tests-clar/resources/attr/sub/subdir_test1 delete mode 100644 tests-clar/resources/attr/sub/subdir_test2.txt delete mode 100644 tests-clar/resources/attr_index/.gitted/HEAD delete mode 100644 tests-clar/resources/attr_index/.gitted/config delete mode 100644 tests-clar/resources/attr_index/.gitted/description delete mode 100644 tests-clar/resources/attr_index/.gitted/index delete mode 100644 tests-clar/resources/attr_index/.gitted/info/exclude delete mode 100644 tests-clar/resources/attr_index/.gitted/info/refs delete mode 100644 tests-clar/resources/attr_index/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/attr_index/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/attr_index/.gitted/objects/38/12cfef36615db1788d4e63f90028007e17a348 delete mode 100644 tests-clar/resources/attr_index/.gitted/objects/59/d942b8be2784bc96db9b22202c10815c9a077b delete mode 100644 tests-clar/resources/attr_index/.gitted/objects/cd/f17ea3fe625ef812f4dce7f423f4f299287505 delete mode 100644 tests-clar/resources/attr_index/.gitted/objects/f7/2502ddd01412bb20796ff812af56fd53b82b52 delete mode 100644 tests-clar/resources/attr_index/.gitted/objects/info/packs delete mode 100644 tests-clar/resources/attr_index/.gitted/objects/pack/pack-4e6438607204ce78827e3885594b2c0bb4f13895.idx delete mode 100644 tests-clar/resources/attr_index/.gitted/objects/pack/pack-4e6438607204ce78827e3885594b2c0bb4f13895.pack delete mode 100644 tests-clar/resources/attr_index/.gitted/packed-refs delete mode 100644 tests-clar/resources/attr_index/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/attr_index/README.md delete mode 100644 tests-clar/resources/attr_index/README.txt delete mode 100644 tests-clar/resources/attr_index/gitattributes delete mode 100644 tests-clar/resources/attr_index/sub/sub/.gitattributes delete mode 100644 tests-clar/resources/attr_index/sub/sub/README.md delete mode 100644 tests-clar/resources/attr_index/sub/sub/README.txt delete mode 100644 tests-clar/resources/bad_tag.git/HEAD delete mode 100644 tests-clar/resources/bad_tag.git/config delete mode 100644 tests-clar/resources/bad_tag.git/objects/pack/pack-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.idx delete mode 100644 tests-clar/resources/bad_tag.git/objects/pack/pack-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.pack delete mode 100644 tests-clar/resources/bad_tag.git/packed-refs delete mode 100644 tests-clar/resources/bad_tag.git/refs/dummy-marker.txt delete mode 100644 tests-clar/resources/big.index delete mode 100644 tests-clar/resources/binaryunicode/.gitted/HEAD delete mode 100644 tests-clar/resources/binaryunicode/.gitted/config delete mode 100644 tests-clar/resources/binaryunicode/.gitted/description delete mode 100644 tests-clar/resources/binaryunicode/.gitted/index delete mode 100644 tests-clar/resources/binaryunicode/.gitted/info/exclude delete mode 100644 tests-clar/resources/binaryunicode/.gitted/info/refs delete mode 100644 tests-clar/resources/binaryunicode/.gitted/objects/info/packs delete mode 100644 tests-clar/resources/binaryunicode/.gitted/objects/pack/pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.idx delete mode 100644 tests-clar/resources/binaryunicode/.gitted/objects/pack/pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.pack delete mode 100644 tests-clar/resources/binaryunicode/.gitted/refs/heads/branch1 delete mode 100644 tests-clar/resources/binaryunicode/.gitted/refs/heads/branch2 delete mode 100644 tests-clar/resources/binaryunicode/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/binaryunicode/file.txt delete mode 100644 tests-clar/resources/blametest.git/HEAD delete mode 100644 tests-clar/resources/blametest.git/config delete mode 100644 tests-clar/resources/blametest.git/description delete mode 100644 tests-clar/resources/blametest.git/objects/0c/bab4d45fd61e55a1c9697f9f9cb07a12e15448 delete mode 100644 tests-clar/resources/blametest.git/objects/1a/ac69ae5d96461afc4d81d0066cb12f5b05a35b delete mode 100644 tests-clar/resources/blametest.git/objects/1b/5f0775af166331c854bd8d1bca3450eaf2532a delete mode 100644 tests-clar/resources/blametest.git/objects/48/2f2c370e35c2c314fc1f96db2beb33f955a26a delete mode 100644 tests-clar/resources/blametest.git/objects/63/d671eb32d250e4a83766ebbc60e818c1e1e93a delete mode 100644 tests-clar/resources/blametest.git/objects/63/eb57322e363e18d460da5ea8284f3cd2340b36 delete mode 100644 tests-clar/resources/blametest.git/objects/8b/137891791fe96927ad78e64b0aad7bded08bdc delete mode 100644 tests-clar/resources/blametest.git/objects/96/679d59cf9f74d69b3c920f258559b5e8c9a18a delete mode 100644 tests-clar/resources/blametest.git/objects/98/89d6e5557761aa8e3607e80c874a6dc51ada7c delete mode 100644 tests-clar/resources/blametest.git/objects/aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 delete mode 100644 tests-clar/resources/blametest.git/objects/b1/76dfc3a4dc8734e4c579f77236a9c8d0a965d2 delete mode 100644 tests-clar/resources/blametest.git/objects/b9/0bb887b7c03750ae6b352ffe76ab9d2e86ee7d delete mode 100644 tests-clar/resources/blametest.git/objects/b9/9f7ac0b88909253d829554c14af488c3b0f3a5 delete mode 100644 tests-clar/resources/blametest.git/objects/bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 delete mode 100644 tests-clar/resources/blametest.git/objects/cf/e0e1e1e3ba18f149fd47f5e1aef6016b2260c3 delete mode 100644 tests-clar/resources/blametest.git/objects/d0/67729932057cdb7527a833d6799c4ddc520640 delete mode 100644 tests-clar/resources/blametest.git/objects/da/237394e6132d20d30f175b9b73c8638fddddda delete mode 100644 tests-clar/resources/blametest.git/objects/e5/b41c1ea533f87388ab69b13baf0b5a562d6243 delete mode 100644 tests-clar/resources/blametest.git/objects/ef/32df4d259143933715c74951f932d9892364d1 delete mode 100644 tests-clar/resources/blametest.git/refs/heads/master delete mode 100644 tests-clar/resources/config/.gitconfig delete mode 100644 tests-clar/resources/config/config-include delete mode 100644 tests-clar/resources/config/config-included delete mode 100644 tests-clar/resources/config/config0 delete mode 100644 tests-clar/resources/config/config1 delete mode 100644 tests-clar/resources/config/config10 delete mode 100644 tests-clar/resources/config/config11 delete mode 100644 tests-clar/resources/config/config12 delete mode 100644 tests-clar/resources/config/config13 delete mode 100644 tests-clar/resources/config/config14 delete mode 100644 tests-clar/resources/config/config15 delete mode 100644 tests-clar/resources/config/config16 delete mode 100644 tests-clar/resources/config/config17 delete mode 100644 tests-clar/resources/config/config18 delete mode 100644 tests-clar/resources/config/config19 delete mode 100644 tests-clar/resources/config/config2 delete mode 100644 tests-clar/resources/config/config20 delete mode 100644 tests-clar/resources/config/config3 delete mode 100644 tests-clar/resources/config/config4 delete mode 100644 tests-clar/resources/config/config5 delete mode 100644 tests-clar/resources/config/config6 delete mode 100644 tests-clar/resources/config/config7 delete mode 100644 tests-clar/resources/config/config8 delete mode 100644 tests-clar/resources/config/config9 delete mode 100644 tests-clar/resources/crlf/.gitted/HEAD delete mode 100644 tests-clar/resources/crlf/.gitted/config delete mode 100644 tests-clar/resources/crlf/.gitted/objects/04/de00b358f13389948756732158eaaaefa1448c delete mode 100644 tests-clar/resources/crlf/.gitted/objects/0a/a76e474d259bd7c13eb726a1396c381db55c88 delete mode 100644 tests-clar/resources/crlf/.gitted/objects/0d/06894e14df22e066763ae906e0ed3eb79c205f delete mode 100644 tests-clar/resources/crlf/.gitted/objects/0f/f5a53f19bfd2b5eea1ba550295c47515678987 delete mode 100644 tests-clar/resources/crlf/.gitted/objects/12/faf3c1ea55f572473cec9052fca468c3584ccb delete mode 100644 tests-clar/resources/crlf/.gitted/objects/38/1cfe630df902bc29271a202d3277981180e4a6 delete mode 100644 tests-clar/resources/crlf/.gitted/objects/79/9770d1cff46753a57db7a066159b5610da6e3a delete mode 100644 tests-clar/resources/crlf/.gitted/objects/7c/ce67e58173e2b01f7db124ceaabe3183d19c49 delete mode 100644 tests-clar/resources/crlf/.gitted/objects/a9/a2e8913c1dbe2812fac5e6b4e0a4bd5d0d5966 delete mode 100644 tests-clar/resources/crlf/.gitted/objects/ba/aa042ab2976f8264e467988e6112ee518ec62e delete mode 100644 tests-clar/resources/crlf/.gitted/objects/dc/88e3b917de821e25962bea7ec1f55c4ce2112c delete mode 100644 tests-clar/resources/crlf/.gitted/objects/ea/030d3c6cec212069eca698cabaa5b4550f1511 delete mode 100644 tests-clar/resources/crlf/.gitted/objects/fe/085d9ace90cc675b87df15e1aeed0c3a31407f delete mode 100644 tests-clar/resources/crlf/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/crlf/.gitted/refs/heads/utf8 delete mode 100644 tests-clar/resources/deprecated-mode.git/HEAD delete mode 100644 tests-clar/resources/deprecated-mode.git/config delete mode 100644 tests-clar/resources/deprecated-mode.git/description delete mode 100644 tests-clar/resources/deprecated-mode.git/index delete mode 100644 tests-clar/resources/deprecated-mode.git/info/exclude delete mode 100644 tests-clar/resources/deprecated-mode.git/objects/06/262edc257418e9987caf999f9a7a3e1547adff delete mode 100644 tests-clar/resources/deprecated-mode.git/objects/08/10fb7818088ff5ac41ee49199b51473b1bd6c7 delete mode 100644 tests-clar/resources/deprecated-mode.git/objects/1b/05fdaa881ee45b48cbaa5e9b037d667a47745e delete mode 100644 tests-clar/resources/deprecated-mode.git/objects/3d/0970ec547fc41ef8a5882dde99c6adce65b021 delete mode 100644 tests-clar/resources/deprecated-mode.git/refs/heads/master delete mode 100644 tests-clar/resources/diff/.gitted/HEAD delete mode 100644 tests-clar/resources/diff/.gitted/config delete mode 100644 tests-clar/resources/diff/.gitted/description delete mode 100644 tests-clar/resources/diff/.gitted/index delete mode 100644 tests-clar/resources/diff/.gitted/info/exclude delete mode 100644 tests-clar/resources/diff/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/diff/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/diff/.gitted/objects/29/ab7053bb4dde0298e03e2c179e890b7dd465a7 delete mode 100644 tests-clar/resources/diff/.gitted/objects/3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847 delete mode 100644 tests-clar/resources/diff/.gitted/objects/54/6c735f16a3b44d9784075c2c0dab2ac9bf1989 delete mode 100644 tests-clar/resources/diff/.gitted/objects/7a/9e0b02e63179929fed24f0a3e0f19168114d10 delete mode 100644 tests-clar/resources/diff/.gitted/objects/7b/808f723a8ca90df319682c221187235af76693 delete mode 100644 tests-clar/resources/diff/.gitted/objects/88/789109439c1e1c3cd45224001edee5304ed53c delete mode 100644 tests-clar/resources/diff/.gitted/objects/cb/8294e696339863df760b2ff5d1e275bee72455 delete mode 100644 tests-clar/resources/diff/.gitted/objects/d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69 delete mode 100644 tests-clar/resources/diff/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/diff/another.txt delete mode 100644 tests-clar/resources/diff/readme.txt delete mode 100644 tests-clar/resources/duplicate.git/COMMIT_EDITMSG delete mode 100644 tests-clar/resources/duplicate.git/HEAD delete mode 100644 tests-clar/resources/duplicate.git/config delete mode 100644 tests-clar/resources/duplicate.git/description delete mode 100644 tests-clar/resources/duplicate.git/index delete mode 100644 tests-clar/resources/duplicate.git/info/exclude delete mode 100644 tests-clar/resources/duplicate.git/info/refs delete mode 100644 tests-clar/resources/duplicate.git/logs/HEAD delete mode 100644 tests-clar/resources/duplicate.git/logs/refs/heads/master delete mode 100644 tests-clar/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea delete mode 100644 tests-clar/resources/duplicate.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a delete mode 100644 tests-clar/resources/duplicate.git/objects/info/packs delete mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx delete mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack delete mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx delete mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack delete mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.idx delete mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.pack delete mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx delete mode 100644 tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack delete mode 100644 tests-clar/resources/duplicate.git/packed-refs delete mode 100644 tests-clar/resources/duplicate.git/refs/heads/dummy-marker.txt delete mode 100644 tests-clar/resources/empty_bare.git/HEAD delete mode 100644 tests-clar/resources/empty_bare.git/config delete mode 100644 tests-clar/resources/empty_bare.git/description delete mode 100644 tests-clar/resources/empty_bare.git/info/exclude delete mode 100644 tests-clar/resources/empty_bare.git/objects/info/dummy-marker.txt delete mode 100644 tests-clar/resources/empty_bare.git/objects/pack/dummy-marker.txt delete mode 100644 tests-clar/resources/empty_bare.git/refs/heads/dummy-marker.txt delete mode 100644 tests-clar/resources/empty_bare.git/refs/tags/dummy-marker.txt delete mode 100644 tests-clar/resources/empty_standard_repo/.gitted/HEAD delete mode 100644 tests-clar/resources/empty_standard_repo/.gitted/config delete mode 100644 tests-clar/resources/empty_standard_repo/.gitted/description delete mode 100644 tests-clar/resources/empty_standard_repo/.gitted/info/exclude delete mode 100644 tests-clar/resources/empty_standard_repo/.gitted/objects/info/dummy-marker.txt delete mode 100644 tests-clar/resources/empty_standard_repo/.gitted/objects/pack/dummy-marker.txt delete mode 100644 tests-clar/resources/empty_standard_repo/.gitted/refs/heads/dummy-marker.txt delete mode 100644 tests-clar/resources/empty_standard_repo/.gitted/refs/tags/dummy-marker.txt delete mode 100644 tests-clar/resources/filemodes/.gitted/HEAD delete mode 100644 tests-clar/resources/filemodes/.gitted/config delete mode 100644 tests-clar/resources/filemodes/.gitted/description delete mode 100644 tests-clar/resources/filemodes/.gitted/index delete mode 100644 tests-clar/resources/filemodes/.gitted/info/exclude delete mode 100644 tests-clar/resources/filemodes/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/filemodes/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/filemodes/.gitted/objects/99/62c8453ba6f0cf8dac7c5dcc2fa2897fa9964a delete mode 100644 tests-clar/resources/filemodes/.gitted/objects/a5/c5dd0fc6c313159a69b1d19d7f61a9f978e8f1 delete mode 100644 tests-clar/resources/filemodes/.gitted/objects/e7/48d196331bcb20267eaaee4ff3326cb73b8182 delete mode 100644 tests-clar/resources/filemodes/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/filemodes/exec_off delete mode 100755 tests-clar/resources/filemodes/exec_off2on_staged delete mode 100755 tests-clar/resources/filemodes/exec_off2on_workdir delete mode 100644 tests-clar/resources/filemodes/exec_off_untracked delete mode 100755 tests-clar/resources/filemodes/exec_on delete mode 100644 tests-clar/resources/filemodes/exec_on2off_staged delete mode 100644 tests-clar/resources/filemodes/exec_on2off_workdir delete mode 100755 tests-clar/resources/filemodes/exec_on_untracked delete mode 100644 tests-clar/resources/gitgit.index delete mode 100644 tests-clar/resources/icase/.gitted/HEAD delete mode 100644 tests-clar/resources/icase/.gitted/config delete mode 100644 tests-clar/resources/icase/.gitted/description delete mode 100644 tests-clar/resources/icase/.gitted/index delete mode 100644 tests-clar/resources/icase/.gitted/info/exclude delete mode 100644 tests-clar/resources/icase/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/icase/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/icase/.gitted/objects/3e/257c57f136a1cb8f2b8e9a2e5bc8ec0258bdce delete mode 100644 tests-clar/resources/icase/.gitted/objects/4d/d6027d083575c7431396dc2a3174afeb393c93 delete mode 100644 tests-clar/resources/icase/.gitted/objects/62/e0af52c199ec731fe4ad230041cd3286192d49 delete mode 100644 tests-clar/resources/icase/.gitted/objects/76/d6e1d231b1085fcce151427e9899335de74be6 delete mode 100644 tests-clar/resources/icase/.gitted/objects/d4/4e18fb93b7107b5cd1b95d601591d77869a1b6 delete mode 100644 tests-clar/resources/icase/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/icase/B delete mode 100644 tests-clar/resources/icase/D delete mode 100644 tests-clar/resources/icase/F delete mode 100644 tests-clar/resources/icase/H delete mode 100644 tests-clar/resources/icase/J delete mode 100644 tests-clar/resources/icase/L/1 delete mode 100644 tests-clar/resources/icase/L/B delete mode 100644 tests-clar/resources/icase/L/D delete mode 100644 tests-clar/resources/icase/L/a delete mode 100644 tests-clar/resources/icase/L/c delete mode 100644 tests-clar/resources/icase/a delete mode 100644 tests-clar/resources/icase/c delete mode 100644 tests-clar/resources/icase/e delete mode 100644 tests-clar/resources/icase/g delete mode 100644 tests-clar/resources/icase/i delete mode 100644 tests-clar/resources/icase/k/1 delete mode 100644 tests-clar/resources/icase/k/B delete mode 100644 tests-clar/resources/icase/k/D delete mode 100644 tests-clar/resources/icase/k/a delete mode 100644 tests-clar/resources/icase/k/c delete mode 100644 tests-clar/resources/issue_1397/.gitted/HEAD delete mode 100644 tests-clar/resources/issue_1397/.gitted/config delete mode 100644 tests-clar/resources/issue_1397/.gitted/index delete mode 100644 tests-clar/resources/issue_1397/.gitted/objects/7f/483a738f867e5b21c8f377d70311f011eb48b5 delete mode 100644 tests-clar/resources/issue_1397/.gitted/objects/83/12e0889a9cbab77c732b6bc39b51a683e3a318 delete mode 100644 tests-clar/resources/issue_1397/.gitted/objects/8a/7ef047fc933edb62e84e7977b0612ec3f6f283 delete mode 100644 tests-clar/resources/issue_1397/.gitted/objects/8e/8f80088a9274fd23584992f587083ca1bcbbac delete mode 100644 tests-clar/resources/issue_1397/.gitted/objects/f2/c62dea0372a0578e053697d5c1ba1ac05e774a delete mode 100644 tests-clar/resources/issue_1397/.gitted/objects/ff/3578d64d199d5b48d92bbb569e0a273e411741 delete mode 100644 tests-clar/resources/issue_1397/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/issue_1397/crlf_file.txt delete mode 100644 tests-clar/resources/issue_1397/some_other_crlf_file.txt delete mode 100644 tests-clar/resources/issue_592/.gitted/COMMIT_EDITMSG delete mode 100644 tests-clar/resources/issue_592/.gitted/HEAD delete mode 100644 tests-clar/resources/issue_592/.gitted/config delete mode 100644 tests-clar/resources/issue_592/.gitted/index delete mode 100644 tests-clar/resources/issue_592/.gitted/info/exclude delete mode 100644 tests-clar/resources/issue_592/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/issue_592/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/issue_592/.gitted/objects/06/07ee9d4ccce8e4c4fa13c2c7d727e7faba4e0e delete mode 100644 tests-clar/resources/issue_592/.gitted/objects/49/363a72a90d9424240258cd3759f23788ecf1d8 delete mode 100644 tests-clar/resources/issue_592/.gitted/objects/4d/383e87f0371ba8fa353f3912db6862b2625e85 delete mode 100644 tests-clar/resources/issue_592/.gitted/objects/71/44be264b61825fbff68046fe999bdfe96a1792 delete mode 100644 tests-clar/resources/issue_592/.gitted/objects/be/de83ee10b5b3f00239660b00acec2d55fd0b84 delete mode 100644 tests-clar/resources/issue_592/.gitted/objects/e3/8fcc7a6060f5eb5b876e836b52ae4769363f21 delete mode 100644 tests-clar/resources/issue_592/.gitted/objects/f1/adef63cb08891a0942b76fc4b9c50c6c494bc7 delete mode 100644 tests-clar/resources/issue_592/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/issue_592/a.txt delete mode 100644 tests-clar/resources/issue_592/c/a.txt delete mode 100644 tests-clar/resources/issue_592/l.txt delete mode 100644 tests-clar/resources/issue_592/t/a.txt delete mode 100644 tests-clar/resources/issue_592/t/b.txt delete mode 100644 tests-clar/resources/issue_592b/.gitted/HEAD delete mode 100644 tests-clar/resources/issue_592b/.gitted/config delete mode 100644 tests-clar/resources/issue_592b/.gitted/description delete mode 100644 tests-clar/resources/issue_592b/.gitted/index delete mode 100644 tests-clar/resources/issue_592b/.gitted/info/exclude delete mode 100644 tests-clar/resources/issue_592b/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/issue_592b/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/issue_592b/.gitted/objects/3f/bf1852f72fd268e36457b13a18cdd9a4c9ea35 delete mode 100644 tests-clar/resources/issue_592b/.gitted/objects/6f/a891d3e578c83e1c03bdb9e0fdd8e6e934157f delete mode 100644 tests-clar/resources/issue_592b/.gitted/objects/80/07d41d5794e6ce4d4d2c97e370d5a9aa6d5213 delete mode 100644 tests-clar/resources/issue_592b/.gitted/objects/a6/5fb6583a7c425284142f285bc359a2d6565513 delete mode 100644 tests-clar/resources/issue_592b/.gitted/objects/ae/be7a55922c7097ef91ca3a7bc327a901d87c2c delete mode 100644 tests-clar/resources/issue_592b/.gitted/objects/b3/44b055867fcdc1f01eaa75056a43e868eb4fbc delete mode 100644 tests-clar/resources/issue_592b/.gitted/objects/f7/d75fbfad8b1d2e307ced287ea78aad403cdce3 delete mode 100644 tests-clar/resources/issue_592b/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/issue_592b/gitignore delete mode 100644 tests-clar/resources/issue_592b/ignored/contained/ignored3.txt delete mode 100644 tests-clar/resources/issue_592b/ignored/contained/tracked3.txt delete mode 100644 tests-clar/resources/issue_592b/ignored/ignored2.txt delete mode 100644 tests-clar/resources/issue_592b/ignored/tracked2.txt delete mode 100644 tests-clar/resources/issue_592b/ignored1.txt delete mode 100644 tests-clar/resources/issue_592b/tracked1.txt delete mode 100644 tests-clar/resources/merge-resolve/.gitted/COMMIT_EDITMSG delete mode 100644 tests-clar/resources/merge-resolve/.gitted/HEAD delete mode 100644 tests-clar/resources/merge-resolve/.gitted/ORIG_HEAD delete mode 100644 tests-clar/resources/merge-resolve/.gitted/config delete mode 100644 tests-clar/resources/merge-resolve/.gitted/description delete mode 100644 tests-clar/resources/merge-resolve/.gitted/index delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/df_ancestor delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/df_side1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/df_side2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/ff_branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo3 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo4 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo5 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo6 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/renames1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/renames2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/unrelated delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/00/5b6fcc8fec71d2550bef8462d169b3c26aa14b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/00/9b9cab6fdac02915a88ecd078b7a792ed802d8 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/00/c7d33f1ffa79d19c2272b370fcaeaadba49c08 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/01/f149e1b8f84bd8896aaff6d6b22af88459ded0 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/02/04a84f822acbf6386b36d33f1f6bc68bbbf858 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/02/251f990ca8e92e7ae61d3426163fa821c64001 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/03/21415405cb906c46869919af56d51dbbe5e85c delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/03/2ebc5ab85d9553bb187d3cd40875ff23a63ed0 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/03/b87706555accbf874ccd410dbda01e8e70a67f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/03/dad1005e5d06d418f50b12e0bcd48ff2306a03 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/05/1ffd7901a442faf56b226161649074f15c7c47 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/05/8541fc37114bfc1dddf6bd6bffc7fae5c2e6fe delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/05/f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/07/a759da919f737221791d542f176ab49c88837f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/07/c514b04698e068892b31c8d352b85813b99c6e delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/09/055301463b7f2f8ee5d368f8ed5c0a40ad8515 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/09/17bb159596aea4d295f4857da77e8f96b3c7dc delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/09/2ce8682d7f3a2a3a769a6daca58950168ba5c4 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/09/3bebf072dd4bbba88833667d6ffe454df199e1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/09/768bed22680cdb0859683fa9677ccc8d5a25c1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/0a/75d9aac1dc84fb5aa51f7325c0ab53242ddef7 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/0c/fd6c54ef6532d862408f562309dc9c74a401e8 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/0d/52e3a556e189ba0948ae56780918011c1b167d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/0d/872f8e871a30208305978ecbf9e66d864f1638 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/0e/c5f433959cd46177f745903353efb5be08d151 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/11/deab00b2d3a6f5a3073988ac050c2d7b6655e2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/11/f4f3c08b737f5fd896cbefa1425ee63b21b2fa delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/13/d1be4ea52a6ced1d7a1d832f0ee3c399348e5e delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/14/39088f509b79b1535b64193137d3ce4b240734 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/15/8dc7bedb202f5b26502bf3574faa7f4238d56c delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/16/f825815cfd20a07a75c71554e82d8eede0b061 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/17/8940b450f238a56c0d75b7955cb57b38191982 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/18/3310e30fb1499af8c619108ffea4d300b5e778 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/18/cb316b1cefa0f8a6946f0e201a8e1a6f845ab9 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/19/b7ac485269b672a101060894de3ba9c2a24dd1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/1a/010b1c0f081b2e8901d55307a15c29ff30af0e delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/1c/ff9ec6a47a537380dedfdd17c9e76d74259a2b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/1e/4ff029aee68d0d69ef9eb6efa6cbf1ec732f99 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/1f/81433e3161efbf250576c58fede7f6b836f3d3 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/20/91d94c8bd3eb0835dc5220de5e8bb310fa1513 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/21/671e290278286fb2ce4c63d01699b67adce331 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/22/7792b52aaa0b238bea00ec7e509b02623f168c delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/23/3c0919c998ed110a4b6ff36f353aec8b713487 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/23/92a2dacc9efb562b8635d6579fb458751c7c5b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/24/1a1005cd9b980732741b74385b891142bcba28 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/24/2591eb280ee9eeb2ce63524b9a8b9bc4cb515d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/24/90b9f1a079420870027deefb49f51d6656cf74 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/25/9d08ca43af9200e9ea9a098e44a5a350ebd9b3 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/25/c40b7660c08c8fb581f770312f41b9b03119d1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/26/153a3ff3649b6c2bb652d3f06878c6e0a172f9 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/27/133da702ba3c60af2a01e96c2555ff4045d692 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/2b/0de5dc27505dcdd83a75c8bf1fcd9462cd7add delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/2b/5f1f181ee3b58ea751f5dd5d8f9b445520a136 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/2b/d0a343aeef7a2cf0d158478966a6e587ff3863 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/2d/a538570bc1e5b2c3e855bf702f35248ad0735f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/2f/2e37b7ebbae467978610896ca3aafcdad2ee67 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/2f/4024ce528d36d8670c289cce5a7963e625bb0c delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/2f/56120107d680129a5d9791b521cb1e73a2ed31 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/2f/598248eeccfc27e5ca44d9d96383f6dfea7b16 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/31/68dca1a561889b045a6441909f4c56145e666d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/31/d5472536041a83d986829240bbbdc897c6f8a6 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/32/21dd512b7e2dc4b5bd03046df6c81b2ab2070b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/33/46d64325b39e5323733492cd55f808994a2475 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/33/d500f588fbbe65901d82b4e6b008e549064be0 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/34/bfafff88eaf118402b44e6f3e2dbbf1a582b05 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/35/0c6eb3010efc403a6bed682332635314e9ed58 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/35/411bfb77cd2cc431f3a03a2b4976ed94b5d241 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/35/4704d3613ad4228e4786fc76656b11e98236c4 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/35/632e43612c06a3ea924bfbacd48333da874c29 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/35/75826c96a975031d2c14368529cc5c4353a8fd delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/36/219b49367146cb2e6a1555b5a9ebd4d0328495 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/36/4bbe4ce80c7bd31e6307dce77d46e3e1759fb3 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/37/48859b001c6e627e712a07951aee40afd19b41 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/38/5c8a0f26ddf79e9041e15e17dc352ed2c4cced delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/3b/47b031b3e55ae11e14a05260b1c3ffd6838d55 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/3b/bf0bf59b20df5d5fc58b9fc1dc07be637c301f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/3e/f4d30382ca33fdeba9fda895a99e0891ba37aa delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/3e/f9bfe82f9635518ae89152322f3b46fd4ba25b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/40/2784a46a4a3982294231594cbeb431f506d22c delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/41/2b32fb66137366147f1801ecc962452757d48a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/43/aafd43bea779ec74317dc361f45ae3f532a505 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/43/c338656342227a3a3cd3aa85cbf784061f5425 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/45/299c1ca5e07bba1fd90843056fb559f96b1f5a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/46/6daf8552b891e5c22bc58c9d7fc1a2eb8f0289 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/47/6dbb3e207313d1d8aaa120c6ad204bf1295e53 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/47/8172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/49/130a28ef567af9a6a6104c38773fedfa5f9742 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/49/9df817155e4bdd3c6ee192a72c52f481818230 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/4a/9550ebcc97ce22b22f45af7b829bb030d003f5 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/4b/253da36a0ae8bfce63aeabd8c5b58429925594 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/4b/48deed3a433909bfd6b6ab3d4b91348b6af464 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/4c/9fac0707f8d4195037ae5a681aa48626491541 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/4c/a408a8c88655f7586a1b580be6fad138121e98 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/4e/0d9401aee78eb345a8685a859d37c8c3c0bbed delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/4e/886e602529caa9ab11d71f86634bd1b6e0de10 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/4e/b04c9e79e88f6640d01ff5b25ca2a60764f216 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/4f/e93c0ec83eb6305cbace3dace88ecee1b63cb6 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/50/12fd565b1393bdfda1805d4ec38ce6619e1fd1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/50/4f75ac95a71ef98051817618576a68505b92f9 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/50/84fc2a88b6bdba8db93bd3953a8f4fdb470238 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/50/ce7d7d01217679e26c55939eef119e0c93e272 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/51/95a1b480f66691b667f10a9e41e70115a78351 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/52/d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/53/825f41ac8d640612f9423a2f03a69f3d96809a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/54/269b3f6ec3d7d4ede24dd350dd5d605495c3ae delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/54/59c89aa0026d543ce8343bd89871bce543f9c2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/54/7607c690372fe81fab8e3bb44c530e129118fd delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/55/b4e4687e7a0d9ca367016ed930f385d4022e6f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/56/6ab53c220a2eafc1212af1a024513230280ab9 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/56/a638b76b75e068590ac999c2f8621e7f3e264c delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/57/079a46233ae2b6df62e9ade71c4948512abefb delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/58/43febcb23480df0b5edb22a21c59c772bb8e29 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/58/e853f66699fd02629fd50bde08082bc005933a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/59/6803b523203a4851c824c07366906f8353f4ad delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/5c/2411f8075f48a6b2fdb85ebc0d371747c4df15 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/5c/341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/5c/3b68a71fc4fa5d362fd3875e53137c6a5ab7a5 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/5d/c1018e90b19654bee986b7a0c268804d39659d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/5d/dd0fe66f990dc0e5cf9fec6d9b465240e9537f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/5e/b7bb6a146eb3c7fd3990b240a2308eceb1cf8d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/5f/bfbdc04b4eca46f54f4853a3c5a1dce28f5165 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/60/91fc2c036a382a69489e3f518ee5aae9a4e567 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/61/340eeed7340fa6a8792def9a5938bb5d4434bb delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/61/78885b38fe96e825ac0f492c0a941f288b37f6 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/62/12c31dab5e482247d7977e4f0dd3601decf13b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/62/269111c3b02a9355badcb9da8678b1bf41787b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/62/c4f6533c9a3894191fdcb96a3be935ade63f1a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/63/247125386de9ec90a27ad36169307bf8a11a38 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/67/18a45909532d1fcf5600d0877f7fe7e78f0b86 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/68/c6c84b091926c7d90aa6a79b2bc3bb6adccd8e delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/69/f570c57b24ea7c086e94c5e574964798321435 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/6a/e1a3967031a42cf955d9d5c2395211ac82f6cf delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/6b/7e37be8ce0b897093f2878a9dcd8f396beda2c delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/6c/06dcd163587c2cc18be44857e0b71116382aeb delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/6f/32739c3724d1d5f855299309f388606f407468 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/6f/a33014764bf1120a454eb8437ae098238e409b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/6f/be9fb85c86d7d1435f728da418bdff52c640a9 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/71/17467b18605a660ebe5586df69e2311ed5609f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/71/2ebba6669ea847d9829e4f1059d6c830c8b531 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/71/add2d7b93d55bf3600f8a1582beceebbd050c8 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/72/ea499e108df5ff0a4a913e7655bbeeb1fb69f2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/74/df13f0793afdaa972150bba976f7de8284914e delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/75/a811bf6bc57694adb3fe604786f3a4efd1cd1b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/76/63fce0130db092936b137cabd693ec234eb060 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/76/ab0e2868197ec158ddd6c78d8a0d2fd73d38f9 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/7a/a3edf2bcfee22398e6b55295aa56366b7aaf76 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/7c/2c5228c9e90170d4a35e6558e47163daf092e5 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/7c/b63eed597130ba4abb87b3e544b85021905520 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/7e/2d058d5fedf8329db44db4fac610d6b1a89159 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/7f/7a2da58126226986d71c6ddfab4afba693280d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/80/a8fbb3abb1ba423d554e9630b8fc2e5698f86b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/81/87117062b750eed4f93fd7e899f17b52ce554d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/83/07d93a155903a5c49576583f0ce1f6ff897c0e delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/83/824a8c6658768e2013905219cc8c64cc3d9a2e delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/84/9619b03ae540acee4d1edec96b86993da6b497 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/84/de84f8f3a6d63e636ee9ad81f4b80512fa9bbe delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/86/088dae8bade454995b21a1c88107b0e1accdab delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/87/b4926260d77a3b851e71ecce06839bd650b231 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/88/e185910a15cd13bdf44854ad037f4842b03b29 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/8a/ad9d0ea334951da47b621a475b39cc6ed759bf delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/8a/ae714f7d939309d7f132b30646d96743134a9f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/8b/095d8fd01594f4d14454d073e3ac57b9ce485f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/8b/5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/8b/fb012a6d809e499bd8d3e194a3929bc8995b93 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/8c/749d9968d4b10dcfb06c9f97d0e5d92d337071 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/8f/4433f8593ddd65b7dd43dd4564d841f4d9c8aa delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/90/a336c7dacbe295159413559b0043b8bdc60d57 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/91/2b2d7819cf9c1029e414883857ed61d597a1a5 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/91/8bb3e09090a9995d48af9a2a6296d7e6088d1c delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/92/7d4943cdbdc9a667db8e62cfd0a41870235c51 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/93/77fccdb210540b8c0520cc6e80eb632c20bd25 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/94/4f5dd1a867cab4c2bbcb896493435cae1dcc1a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/94/8ba6e701c1edab0c2d394fb7c5538334129793 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/95/646149ab6b6ba6edc83cff678582538b457b2b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/95/9de65e568274120fdf9e3af9f77b1550122149 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/96/8ca794a4597f7f6abbb2b8d940b4078a0f3fd4 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/97/7c696519c5a3004c5f1d15d60c89dbeb8f235f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/98/ba4205fcf31f5dd93c916d35fe3f3b3d0e6714 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/98/d52d07c0b0bbf2b46548f6aa521295c2cb55db delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/99/b4f7e4f24470fa06b980bc21f1095c2a9425c0 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/9a/301fbe6fada7dcb74fcd7c20269b5c743459a7 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/9a/f731fa116d1eb9a6c0109562472cfee6f5a979 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/9c/0b6c34ef379a42d858f03fef38630f476b9102 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/9e/7f4359c469f309b6057febf4c6e80742cbed5b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/9e/fe7723802d4305142eee177e018fee1572c4f4 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/9f/74397a3397b3585faf09e9926b110d7f654254 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a0/31a28ae70e33a641ce4b8a8f6317f1ab79dee4 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a3/9a620dae5bc8b4e771cd4d251b7d080401a21e delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a3/fabece9eb8748da810e1e08266fef9b7136ad4 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a4/1b1bb6d0be3c22fb654234c33b428e15c8cc27 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a4/3150a738849c59376cf30bb2a68348a83c8f48 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a5/563304ddf6caba25cb50323a2ea6f7dbfcadca delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a7/08b253bd507417ec42d1467a7fd2d7519c4956 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a7/65fb87eb2f7a1920b73b2d5a057f8f8476a42b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a7/7a56a49f8f3ae242e02717f18ebbc60c5cc543 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a7/dbfcbfc1a60709cb80b5ca24539008456531d0 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a8/02e06f1782a9645b9851bc7202cee74a8a4972 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a8/87dd39ad3edd610fc9083dcb61e40ab50673d1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/a9/0bc3fb6f15181972a2959a921429efbd81a473 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ab/40af3cb8a3ed2e2843e96d9aa7871336b94573 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ab/6c44a2e84492ad4b41bb6bac87353e9d02ac8b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ab/929391ac42572f92110f3deeb4f0844a951e22 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ac/4045f965119e6998f4340ed0f411decfb3ec05 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ad/a14492498136771f69dd451866cabcb0e9ef9a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ad/a55a45d14527dc3dfc714ea1c65d2e1e6fbe87 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/b2/d399ae15224e1d58066e3c8df70ce37de7a656 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/b4/2712cfe99a1a500b2a51fe984e0b8a7702ba11 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/b6/9fe837e4cecfd4c9a40cdca7c138468687df07 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/b6/f610aef53bd343e6c96227de874c66f00ee8e8 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/b7/a2576f9fc20024ac9ef17cb134acbd1ac73127 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/b8/a3a806d3950e8c0a03a34f234a92eff0e2c68d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ba/cac9b3493509aa15e1730e1545fc0919d1dae0 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/bc/744705e1d8a019993cf88f62bc4020f1b80919 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/bc/95c75d59386147d1e79a87c33068d8dbfd71f2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/bd/593285fc7fe4ca18ccdbabf027f5d689101452 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/bd/867fbae2faa80b920b002b80b1c91bcade7784 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/bd/9cb4cd0a770cb9adcb5fce212142ef40ea1c35 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/be/f6e37b3ee632ba74159168836f382fed21d77d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c0/6a9be584ac49aa02c5551312d9e2982c91df10 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c1/b17981db0840109a820dae8674ee29684134ff delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c1/b6a51bbb87c2f82b161412c3d20b59fc69b090 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c3/5dee9bcc0e989f3b0c40f68372a9a51b6c4e6a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c3/d02eeef75183df7584d8d13ac03053910c1301 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c4/efe31e9decccc8b2b4d3df9aac2cdfe2995618 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c5/0d0f1cb60b8b0fe1615ad20ace557e9d68d7bd delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c5/bbe550b9f09444bdddd3ecf3d97c0b42aa786c delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c6/07fc30883e335def28cd686b51f6cfa02b06ec delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c6/92ecf62007c0ac9fb26e2aa884de2933de15ed delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c8/f06f2e3bb2964174677e91f0abead0e43c9e5d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c9/174cef549ec94ecbc43ef03cdc775b4950becb delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/c9/4b27e41064c521120627e07e2035cca1d24ffa delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ca/b2cf23998b40f1af2d9d9a756dc9e285a8df4b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/cb/491780d82e46dc88a065b965ab307a038f2bc2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/cb/6693a788715b82440a54e0eacd19ba9f6ec559 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/cc/3e3009134cb88014129fc8858d1101359e5e2f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ce/8860d49e3bea6fd745874a01b7c3e46da8cbc3 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ce/e656c392ad0557b3aae0fb411475c206e2926f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/cf/8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d0/7ec190c306ec690bac349e87d01c4358e49bb2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d0/d4594e16f2e19107e3fa7ea63e7aaaff305ffb delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d2/f8637f2eab2507a1e13cbc9df4729ec386627e delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d3/719a5ae8e4d92276b5313ce976f6ee5af2b436 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d3/7aa3bbfe1c0c49b909781251b956dbabe85f96 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d3/7ad72a2052685fc6201c2af90103ad42d2079b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d4/207f77243500bec335ab477f9227fcdb1e271a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d4/27e0b2e138501a3d15cc376077a3631e15bd46 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d5/093787ef302b941b6aab081b99fb4880038bd8 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d5/a61b0b4992a4f0caa887fa08b52431e727bb6f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d5/b6fc965c926a1bfc9ee456042b94088b5c5d21 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d5/ec1152fe25e9fec00189eb00b3db71db24c218 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d6/42b9770c66bba94a08df09b5efb095001f76d7 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d6/462fa3f5292857db599c54aea2bf91616230c5 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d6/cf6c7741b3316826af1314042550c97ded1d50 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d8/74671ef5b20184836cb983bb273e5280384d0b delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d8/fa77b6833082c1ea36b7828a582d4c43882450 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/d9/63979c237d08b6ba39062ee7bf64c7d34a27f8 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/da/178208145ef585a1bd5ca5f4c9785d738df2cf delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/db/6261a7c65c7fd678520c9bb6f2c47582ab9ed5 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/dd/9a570c3400e6e07bc4d7651d6e20b08926b3d9 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/de/872ee3618b894992e9d1e18ba2ebe256a112f9 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/df/e3f22baa1f6fce5447901c3086bae368de6bdd delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e0/67f9361140f19391472df8a82d6610813c73b7 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e1/129b3cfb5898e0fbd606e0cb80b2755e50d161 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e1/7ace1492648c9dc5701bad5c47af9d1b60c4e9 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e2/c6abbd55fed5ac71a5f2751e29b4a34726a595 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e3/1e7ad3ed298f24e383c4950f4671993ec078e4 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e3/76fbdd06ebf021c92724da9f26f44212734e3e delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e4/9f917b448d1340b31d76e54ba388268fd4c922 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e4/f618a2c3ed0669308735727df5ebf2447f022f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e6/5a9bb2af9f4c2d1c375dd0f8f8a46cf9c68812 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e8/107f24196736b870a318a0e28f048e29f6feff delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e9/2cdb7017dc6c5aed25cb4202c5b0104b872246 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e9/ad6ec3e38364a3d07feda7c4197d4d845c53b5 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/e9/f48beccc62d535739bfbdebe0a55ed716d8366 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/eb/c09d0137cfb0c26697aed0109fb943ad906f3f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ec/67e5a86adff465359f1c8f995e12dbdfa08d8a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ed/9523e62e453e50dd9be1606af19399b96e397a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ee/1d6f164893c1866a323f072eeed36b855656be delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ee/3fa1b8c00aff7fe02065fdb50864bb0d932ccf delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ee/a9286df54245fea72c5b557291470eb825f38f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ef/58fdd8086c243bdc81f99e379acacfd21d32d6 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ef/c499524cf105d5264ac7fc54e07e95764e8075 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ef/c9121fdedaf08ba180b53ebfbcf71bd488ed09 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f0/053b8060bb3f0be5cbcc3147a07ece26bf097e delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f0/ce2b8e4986084d9b308fb72709e414c23eb5e6 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f2/0c9063fa0bda9a397c96947a7b687305c49753 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f2/9e7fb590551095230c6149cbe72f2e9104a796 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f3/293571dcd708b6a3faf03818cd2844d000e198 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f3/f1164b68b57b1995b658a828320e6df3081fae delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f4/15caf3fcad16304cb424b67f0ee6b12dc03aae delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f4/8097eb340dc5a7cae55aabcf1faf4548aa821f delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f5/504f36e6f4eb797a56fc5bac6c6c7f32969bf2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f5/b50c85a87cac64d7eb3254cdd1aec9564c0293 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f5/f9dd5886a6ee20272be0aafc790cba43b31931 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f6/be049e284c0f9dcbbc745543885be3502ea521 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f7/c332bd4d4d4b777366cae4d24d1687477576bf delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/f8/958bdf4d365a84a9a178b1f5f35ff1dacbd884 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/fa/c03f2c5139618d87d53614c153823bf1f31396 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/fa/da9356aa3f74622327a3038ae9c6f92e1c5c1d delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/fb/738a106cfd097a4acb96ce132ecb1ad6c46b03 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/fc/4c636d6515e9e261f9260dbcf3cc6eca97ea08 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/fc/7d7b805f7a9428574f4f802b2e34cd20ab9d99 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/fc/90237dc4891fa6c69827fc465632225e391618 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/fd/57d2d6770fad8e9959124793a17f441b571e66 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/fd/89f8cffb663ac89095a0f9764902e93ceaca6a delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/fe/5407fc50a53aecb41d1a6e9ea7b612e581af87 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ff/49d07869831ad761bbdaea026086f8789bcb00 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/objects/ff/b312248d607284c290023f9502eea010d34efd delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/df_ancestor delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/df_side1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/df_side2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/ff_branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/octo1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/octo2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/octo3 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/octo4 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/octo5 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/octo6 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ancestor delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ours delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/rename_conflict_theirs delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/renames1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/renames2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-10 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-10-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-11 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-11-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-13 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-13-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-14 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-14-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-2alt delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-2alt-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-3alt delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-3alt-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-4 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-4-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-6 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-6-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-7 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-7-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-8 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-8-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-9 delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-9-branch delete mode 100644 tests-clar/resources/merge-resolve/.gitted/refs/heads/unrelated delete mode 100644 tests-clar/resources/merge-resolve/added-in-master.txt delete mode 100644 tests-clar/resources/merge-resolve/automergeable.txt delete mode 100644 tests-clar/resources/merge-resolve/changed-in-branch.txt delete mode 100644 tests-clar/resources/merge-resolve/changed-in-master.txt delete mode 100644 tests-clar/resources/merge-resolve/conflicting.txt delete mode 100644 tests-clar/resources/merge-resolve/removed-in-branch.txt delete mode 100644 tests-clar/resources/merge-resolve/unchanged.txt delete mode 100644 tests-clar/resources/mergedrepo/.gitted/COMMIT_EDITMSG delete mode 100644 tests-clar/resources/mergedrepo/.gitted/HEAD delete mode 100644 tests-clar/resources/mergedrepo/.gitted/MERGE_HEAD delete mode 100644 tests-clar/resources/mergedrepo/.gitted/MERGE_MODE delete mode 100644 tests-clar/resources/mergedrepo/.gitted/MERGE_MSG delete mode 100644 tests-clar/resources/mergedrepo/.gitted/ORIG_HEAD delete mode 100644 tests-clar/resources/mergedrepo/.gitted/config delete mode 100644 tests-clar/resources/mergedrepo/.gitted/description delete mode 100644 tests-clar/resources/mergedrepo/.gitted/index delete mode 100644 tests-clar/resources/mergedrepo/.gitted/info/exclude delete mode 100644 tests-clar/resources/mergedrepo/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/branch delete mode 100644 tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211e delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/3a/34580a35add43a4cf361e8e9a30060a905c876 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8c delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52da delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46ad delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038c delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735a delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/9a/05ccb4e0f948de03128e095f39dae6976751c5 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092c delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/e2/809157a7766f272e4cfe26e61ef2678a5357ff delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406 delete mode 100644 tests-clar/resources/mergedrepo/.gitted/refs/heads/branch delete mode 100644 tests-clar/resources/mergedrepo/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/mergedrepo/conflicts-one.txt delete mode 100644 tests-clar/resources/mergedrepo/conflicts-two.txt delete mode 100644 tests-clar/resources/mergedrepo/one.txt delete mode 100644 tests-clar/resources/mergedrepo/two.txt delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/HEAD delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/config delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/index delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/16/8e4ebd1c667499548ae12403b19b22a5c5e925 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/cf/80f8de9f1185bf3a05f993f6121880dd0cfbc9 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/d5/2a8fe84ceedf260afe4f0287bbfca04a117e83 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/fd/093bff70906175335656e6ce6ae05783708765 delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/pack/.gitkeep delete mode 100644 tests-clar/resources/partial-testrepo/.gitted/refs/heads/dir delete mode 100644 tests-clar/resources/peeled.git/HEAD delete mode 100644 tests-clar/resources/peeled.git/config delete mode 100644 tests-clar/resources/peeled.git/objects/info/packs delete mode 100644 tests-clar/resources/peeled.git/objects/pack/pack-e84773eaf3fce1774755580e3dbb8d9f3a1adc45.idx delete mode 100644 tests-clar/resources/peeled.git/objects/pack/pack-e84773eaf3fce1774755580e3dbb8d9f3a1adc45.pack delete mode 100644 tests-clar/resources/peeled.git/packed-refs delete mode 100644 tests-clar/resources/peeled.git/refs/heads/master delete mode 100644 tests-clar/resources/push.sh delete mode 100644 tests-clar/resources/push_src/.gitted/COMMIT_EDITMSG delete mode 100644 tests-clar/resources/push_src/.gitted/HEAD delete mode 100644 tests-clar/resources/push_src/.gitted/ORIG_HEAD delete mode 100644 tests-clar/resources/push_src/.gitted/config delete mode 100644 tests-clar/resources/push_src/.gitted/description delete mode 100644 tests-clar/resources/push_src/.gitted/index delete mode 100644 tests-clar/resources/push_src/.gitted/info/exclude delete mode 100644 tests-clar/resources/push_src/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/push_src/.gitted/logs/refs/heads/b1 delete mode 100644 tests-clar/resources/push_src/.gitted/logs/refs/heads/b2 delete mode 100644 tests-clar/resources/push_src/.gitted/logs/refs/heads/b3 delete mode 100644 tests-clar/resources/push_src/.gitted/logs/refs/heads/b4 delete mode 100644 tests-clar/resources/push_src/.gitted/logs/refs/heads/b5 delete mode 100644 tests-clar/resources/push_src/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/HEAD delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/config delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/description delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/index delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/info/exclude delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/logs/HEAD delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/logs/refs/heads/master delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/logs/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/18/10dff58d8a660512d4832e740f692884338ccd delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/1b/8cbad43e867676df601306689fe7c3def5e689 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/7b/4384978d2493e851f9cca7858815fac9b10980 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/81/4889a078c031f61ed08ab5fa863aea9314344d delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/84/96071c1b46c854b31185ea97743be6a8774479 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/ae/90f12eea699729ed24555e40b9fd669da12a12 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/b6/361fc6a97178d8fc8639fdeed71c775ab52593 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/d0/7b0f9a8c89f1d9e74dc4fce6421dec5ef8a659 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/d6/c93164c249c8000205dd4ec5cbca1b516d487f delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/d7/1aab4f9b04b45ce09bcaa636a9be6231474759 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/e7/b4ad382349ff96dd8199000580b9b1e2042eb0 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/f1/425cef211cc08caa31e7b545ffb232acb098c3 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/fa/49b077972391ad58037050f2a75f74e3671e92 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/fd/093bff70906175335656e6ce6ae05783708765 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/fd/4959ce7510db09d4d8217fa2d1780413e05a09 delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/packed-refs delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/refs/heads/master delete mode 100644 tests-clar/resources/push_src/.gitted/modules/submodule/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/push_src/.gitted/objects/08/585692ce06452da6f82ae66b90d98b55536fca delete mode 100644 tests-clar/resources/push_src/.gitted/objects/27/b7ce66243eb1403862d05f958c002312df173d delete mode 100644 tests-clar/resources/push_src/.gitted/objects/28/905c54ea45a4bed8d7b90f51bd8bd81eec8840 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/36/6226fb970ac0caa9d3f55967ab01334a548f60 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/5c/0bb3d1b9449d1cc69d7519fd05166f01840915 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/61/780798228d17af2d34fce4cfbdf35556832472 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/64/fd55f9b6390202db5e5666fd1fb339089fba4d delete mode 100644 tests-clar/resources/push_src/.gitted/objects/78/981922613b2afb6025042ff6bd878ac1994e85 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/80/5c54522e614f29f70d2413a0470247d8b424ac delete mode 100644 tests-clar/resources/push_src/.gitted/objects/95/1bbbb90e2259a4c8950db78946784fb53fcbce delete mode 100644 tests-clar/resources/push_src/.gitted/objects/a7/8705c3b2725f931d3ee05348d83cc26700f247 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/b4/e1f2b375a64c1ccd40c5ff6aa8bc96839ba4fd delete mode 100644 tests-clar/resources/push_src/.gitted/objects/c1/0409136a7a75e025fa502a1b2fd7b62b77d279 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/cd/881f90f2933db2e4cc26b8c71fe6037ac7fe4c delete mode 100644 tests-clar/resources/push_src/.gitted/objects/d9/b63a88223d8367516f50bd131a5f7349b7f3e4 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/dc/ab83249f6f9d1ed735d651352a80519339b591 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/f7/8a3106c85fb549c65198b2a2086276c6174928 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/f8/f7aefc2900a3d737cea9eee45729fd55761e1a delete mode 100644 tests-clar/resources/push_src/.gitted/objects/fa/38b91f199934685819bea316186d8b008c52a2 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e delete mode 100644 tests-clar/resources/push_src/.gitted/objects/ff/fe95c7fd0a37fa2ed702f8f93b56b2196b3925 delete mode 100644 tests-clar/resources/push_src/.gitted/objects/pack/dummy delete mode 100644 tests-clar/resources/push_src/.gitted/refs/heads/b1 delete mode 100644 tests-clar/resources/push_src/.gitted/refs/heads/b2 delete mode 100644 tests-clar/resources/push_src/.gitted/refs/heads/b3 delete mode 100644 tests-clar/resources/push_src/.gitted/refs/heads/b4 delete mode 100644 tests-clar/resources/push_src/.gitted/refs/heads/b5 delete mode 100644 tests-clar/resources/push_src/.gitted/refs/heads/b6 delete mode 100644 tests-clar/resources/push_src/.gitted/refs/tags/tag-blob delete mode 100644 tests-clar/resources/push_src/.gitted/refs/tags/tag-commit delete mode 100644 tests-clar/resources/push_src/.gitted/refs/tags/tag-commit-two delete mode 100644 tests-clar/resources/push_src/.gitted/refs/tags/tag-lightweight delete mode 100644 tests-clar/resources/push_src/.gitted/refs/tags/tag-tag delete mode 100644 tests-clar/resources/push_src/.gitted/refs/tags/tag-tree delete mode 100644 tests-clar/resources/push_src/a.txt delete mode 100644 tests-clar/resources/push_src/fold/b.txt delete mode 100644 tests-clar/resources/push_src/foldb.txt delete mode 100644 tests-clar/resources/push_src/gitmodules delete mode 100644 tests-clar/resources/push_src/submodule/.gitted delete mode 100644 tests-clar/resources/push_src/submodule/README delete mode 100644 tests-clar/resources/push_src/submodule/branch_file.txt delete mode 100644 tests-clar/resources/push_src/submodule/new.txt delete mode 100644 tests-clar/resources/renames/.gitted/HEAD delete mode 100644 tests-clar/resources/renames/.gitted/config delete mode 100644 tests-clar/resources/renames/.gitted/description delete mode 100644 tests-clar/resources/renames/.gitted/index delete mode 100644 tests-clar/resources/renames/.gitted/info/exclude delete mode 100644 tests-clar/resources/renames/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/renames/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/renames/.gitted/objects/03/da7ad872536bd448da8d88eb7165338bf923a7 delete mode 100644 tests-clar/resources/renames/.gitted/objects/17/58bdd7c16a72ff7c17d8de0c957ced3ccad645 delete mode 100644 tests-clar/resources/renames/.gitted/objects/19/dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 delete mode 100644 tests-clar/resources/renames/.gitted/objects/1c/068dee5790ef1580cfc4cd670915b48d790084 delete mode 100644 tests-clar/resources/renames/.gitted/objects/2b/c7f351d20b53f1c72c16c4b036e491c478c49a delete mode 100644 tests-clar/resources/renames/.gitted/objects/31/e47d8c1fa36d7f8d537b96158e3f024de0a9f2 delete mode 100644 tests-clar/resources/renames/.gitted/objects/35/92953ff3ea5e8ba700c429f3aefe33c8806754 delete mode 100644 tests-clar/resources/renames/.gitted/objects/36/020db6cdacaa93497f31edcd8f242ff9bc366d delete mode 100644 tests-clar/resources/renames/.gitted/objects/3c/04741dd4b96c4ae4b00ec0f6e10c816a30aad2 delete mode 100644 tests-clar/resources/renames/.gitted/objects/42/10ffd5c390b21dd5483375e75288dea9ede512 delete mode 100644 tests-clar/resources/renames/.gitted/objects/44/4a76ed3e45b183753f49376af30da8c3fe276a delete mode 100644 tests-clar/resources/renames/.gitted/objects/47/184c1e7eb22abcbed2bf4ee87d4e38096f7951 delete mode 100644 tests-clar/resources/renames/.gitted/objects/4e/4cae3e7dd56ed74bff39526d0469e554432953 delete mode 100644 tests-clar/resources/renames/.gitted/objects/50/e90273af7d826ff0a95865bcd3ba8412c447d9 delete mode 100644 tests-clar/resources/renames/.gitted/objects/5e/26abc56a5a84d89790f45416648899cbe13109 delete mode 100644 tests-clar/resources/renames/.gitted/objects/61/8c6f2f8740bd6049b2fb9eb93fc15726462745 delete mode 100644 tests-clar/resources/renames/.gitted/objects/66/311f5cfbe7836c27510a3ba2f43e282e2c8bba delete mode 100644 tests-clar/resources/renames/.gitted/objects/93/f538c45a57a87eb4c1e86f91c6ee41d66c7ba7 delete mode 100644 tests-clar/resources/renames/.gitted/objects/9a/69d960ae94b060f56c2a8702545e2bb1abb935 delete mode 100644 tests-clar/resources/renames/.gitted/objects/ad/0a8e55a104ac54a8a29ed4b84b49e76837a113 delete mode 100644 tests-clar/resources/renames/.gitted/objects/b9/25b224cc91f897001a9993fbce169fdaa8858f delete mode 100644 tests-clar/resources/renames/.gitted/objects/d7/9b202de198fa61b02424b9e25e840dc75e1323 delete mode 100644 tests-clar/resources/renames/.gitted/objects/ea/c43f5195a2cee53b7458d8dad16aedde10711b delete mode 100644 tests-clar/resources/renames/.gitted/objects/ea/f4a3e3bfe68585e90cada20736ace491cd100b delete mode 100644 tests-clar/resources/renames/.gitted/objects/f9/0d4fc20ecddf21eebe6a37e9225d244339d2b5 delete mode 100644 tests-clar/resources/renames/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/renames/.gitted/refs/heads/renames_similar delete mode 100644 tests-clar/resources/renames/.gitted/refs/heads/renames_similar_two delete mode 100644 tests-clar/resources/renames/ikeepsix.txt delete mode 100644 tests-clar/resources/renames/sixserving.txt delete mode 100644 tests-clar/resources/renames/songof7cities.txt delete mode 100644 tests-clar/resources/renames/untimely.txt delete mode 100644 tests-clar/resources/shallow.git/HEAD delete mode 100644 tests-clar/resources/shallow.git/config delete mode 100644 tests-clar/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.idx delete mode 100644 tests-clar/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.pack delete mode 100644 tests-clar/resources/shallow.git/packed-refs delete mode 100644 tests-clar/resources/shallow.git/refs/.gitkeep delete mode 100644 tests-clar/resources/shallow.git/shallow delete mode 100644 tests-clar/resources/short_tag.git/HEAD delete mode 100644 tests-clar/resources/short_tag.git/config delete mode 100644 tests-clar/resources/short_tag.git/index delete mode 100644 tests-clar/resources/short_tag.git/objects/4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c delete mode 100644 tests-clar/resources/short_tag.git/objects/4d/5fcadc293a348e88f777dc0920f11e7d71441c delete mode 100644 tests-clar/resources/short_tag.git/objects/5d/a7760512a953e3c7c4e47e4392c7a4338fb729 delete mode 100644 tests-clar/resources/short_tag.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 delete mode 100644 tests-clar/resources/short_tag.git/packed-refs delete mode 100644 tests-clar/resources/short_tag.git/refs/heads/master delete mode 100644 tests-clar/resources/status/.gitted/COMMIT_EDITMSG delete mode 100644 tests-clar/resources/status/.gitted/HEAD delete mode 100644 tests-clar/resources/status/.gitted/ORIG_HEAD delete mode 100644 tests-clar/resources/status/.gitted/config delete mode 100644 tests-clar/resources/status/.gitted/description delete mode 100644 tests-clar/resources/status/.gitted/index delete mode 100644 tests-clar/resources/status/.gitted/info/exclude delete mode 100644 tests-clar/resources/status/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/status/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/status/.gitted/objects/00/17bd4ab1ec30440b17bae1680cff124ab5f1f6 delete mode 100644 tests-clar/resources/status/.gitted/objects/06/1d42a44cacde5726057b67558821d95db96f19 delete mode 100644 tests-clar/resources/status/.gitted/objects/18/88c805345ba265b0ee9449b8877b6064592058 delete mode 100644 tests-clar/resources/status/.gitted/objects/19/d9cc8584ac2c7dcf57d2680375e80f099dc481 delete mode 100644 tests-clar/resources/status/.gitted/objects/26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f delete mode 100644 tests-clar/resources/status/.gitted/objects/32/504b727382542f9f089e24fddac5e78533e96c delete mode 100644 tests-clar/resources/status/.gitted/objects/37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0 delete mode 100644 tests-clar/resources/status/.gitted/objects/45/2e4244b5d083ddf0460acf1ecc74db9dcfa11a delete mode 100644 tests-clar/resources/status/.gitted/objects/52/9a16e8e762d4acb7b9636ff540a00831f9155a delete mode 100644 tests-clar/resources/status/.gitted/objects/53/ace0d1cc1145a5f4fe4f78a186a60263190733 delete mode 100644 tests-clar/resources/status/.gitted/objects/54/52d32f1dd538eb0405e8a83cc185f79e25e80f delete mode 100644 tests-clar/resources/status/.gitted/objects/55/d316c9ba708999f1918e9677d01dfcae69c6b9 delete mode 100644 tests-clar/resources/status/.gitted/objects/70/bd9443ada07063e7fbf0b3ff5c13f7494d89c2 delete mode 100644 tests-clar/resources/status/.gitted/objects/73/5b6a258cd196a8f7c9428419b02c1dca93fd75 delete mode 100644 tests-clar/resources/status/.gitted/objects/75/6e27627e67bfbc048d01ece5819c6de733d7ea delete mode 100644 tests-clar/resources/status/.gitted/objects/90/6ee7711f4f4928ddcb2a5f8fbc500deba0d2a8 delete mode 100644 tests-clar/resources/status/.gitted/objects/90/b8c29d8ba39434d1c63e1b093daaa26e5bd972 delete mode 100644 tests-clar/resources/status/.gitted/objects/9c/2e02cdffa8d73e6c189074594477a6baf87960 delete mode 100644 tests-clar/resources/status/.gitted/objects/a0/de7e0ac200c489c41c59dfa910154a70264e6e delete mode 100644 tests-clar/resources/status/.gitted/objects/a6/191982709b746d5650e93c2acf34ef74e11504 delete mode 100644 tests-clar/resources/status/.gitted/objects/a6/be623522ce87a1d862128ac42672604f7b468b delete mode 100644 tests-clar/resources/status/.gitted/objects/aa/27a641456848200fdb7f7c99ba36f8a0952877 delete mode 100644 tests-clar/resources/status/.gitted/objects/da/bc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 delete mode 100644 tests-clar/resources/status/.gitted/objects/e8/ee89e15bbe9b20137715232387b3de5b28972e delete mode 100644 tests-clar/resources/status/.gitted/objects/e9/b9107f290627c04d097733a10055af941f6bca delete mode 100644 tests-clar/resources/status/.gitted/objects/ed/062903b8f6f3dccb2fa81117ba6590944ef9bd delete mode 100644 tests-clar/resources/status/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/status/current_file delete mode 100644 tests-clar/resources/status/ignored_file delete mode 100644 tests-clar/resources/status/modified_file delete mode 100644 tests-clar/resources/status/new_file delete mode 100644 tests-clar/resources/status/staged_changes delete mode 100644 tests-clar/resources/status/staged_changes_modified_file delete mode 100644 tests-clar/resources/status/staged_delete_modified_file delete mode 100644 tests-clar/resources/status/staged_new_file delete mode 100644 tests-clar/resources/status/staged_new_file_modified_file delete mode 100644 tests-clar/resources/status/subdir.txt delete mode 100644 tests-clar/resources/status/subdir/current_file delete mode 100644 tests-clar/resources/status/subdir/modified_file delete mode 100644 tests-clar/resources/status/subdir/new_file delete mode 100644 "tests-clar/resources/status/\350\277\231" delete mode 100644 tests-clar/resources/submod2/.gitted/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/config delete mode 100644 tests-clar/resources/submod2/.gitted/description delete mode 100644 tests-clar/resources/submod2/.gitted/index delete mode 100644 tests-clar/resources/submod2/.gitted/info/exclude delete mode 100644 tests-clar/resources/submod2/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/config delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/description delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/index delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/info/exclude delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/41/bd4bc3df978de695f67ace64c560913da11653 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/5e/4963595a9774b90524d35a807169049de8ccad delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/6b/31c659545507c381e9cd34ec508f16c04e149e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/73/ba924a80437097795ae839e66e187c55d3babf delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/9efbdadaa4a582778d4584385495559ea0994b delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/packed-refs delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/config delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/description delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/index delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/info/exclude delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/logs/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/5e/4963595a9774b90524d35a807169049de8ccad delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/73/ba924a80437097795ae839e66e187c55d3babf delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/packed-refs delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_file/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/COMMIT_EDITMSG delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/config delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/description delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/index delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/info/exclude delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/logs/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/3d/9386c507f6b093471a3e324085657a3c2b4247 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/41/bd4bc3df978de695f67ace64c560913da11653 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/5e/4963595a9774b90524d35a807169049de8ccad delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/6b/31c659545507c381e9cd34ec508f16c04e149e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/73/ba924a80437097795ae839e66e187c55d3babf delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/77/fb0ed3e58568d6ad362c78de08ab8649d76e29 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/78/9efbdadaa4a582778d4584385495559ea0994b delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/8e/b1e637ed9fc8e5454fa20d38f809091f9395f4 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/packed-refs delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_head/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/config delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/description delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/index delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/info/exclude delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/logs/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/41/bd4bc3df978de695f67ace64c560913da11653 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/5e/4963595a9774b90524d35a807169049de8ccad delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/6b/31c659545507c381e9cd34ec508f16c04e149e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/73/ba924a80437097795ae839e66e187c55d3babf delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/78/9efbdadaa4a582778d4584385495559ea0994b delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/a0/2d31770687965547ab7a04cee199b29ee458d6 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/packed-refs delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_index/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/config delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/description delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/index delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/info/exclude delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/5e/4963595a9774b90524d35a807169049de8ccad delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/73/ba924a80437097795ae839e66e187c55d3babf delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/packed-refs delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/config delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/description delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/index delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/info/exclude delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/logs/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/41/bd4bc3df978de695f67ace64c560913da11653 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/5e/4963595a9774b90524d35a807169049de8ccad delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/6b/31c659545507c381e9cd34ec508f16c04e149e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/packed-refs delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/config delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/description delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/index delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/info/exclude delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/logs/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/41/bd4bc3df978de695f67ace64c560913da11653 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/5e/4963595a9774b90524d35a807169049de8ccad delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/6b/31c659545507c381e9cd34ec508f16c04e149e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/73/ba924a80437097795ae839e66e187c55d3babf delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/78/9efbdadaa4a582778d4584385495559ea0994b delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/packed-refs delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/refs/heads/master delete mode 100644 tests-clar/resources/submod2/.gitted/modules/sm_unchanged/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submod2/.gitted/objects/09/460e5b6cbcb05a3e404593c32a3aa7221eca0e delete mode 100644 tests-clar/resources/submod2/.gitted/objects/14/fe9ccf104058df25e0a08361c4494e167ef243 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/22/ce3e0311dda73a5992d54a4a595518d3876ea7 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/25/5546424b0efb847b1bfc91dbf7348b277f8970 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/2a/30f1e6f94b20917005a21273f65b406d0f8bad delete mode 100644 tests-clar/resources/submod2/.gitted/objects/42/cfb95cd01bf9225b659b5ee3edcc78e8eeb478 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/57/958699c2dc394f81cfc76950e9c3ac3025c398 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/59/01da4f1c67756eeadc5121d206bec2431f253b delete mode 100644 tests-clar/resources/submod2/.gitted/objects/60/7d96653d4d0a4f733107f7890c2e67b55b620d delete mode 100644 tests-clar/resources/submod2/.gitted/objects/74/84482eb8db738cafa696993664607500a3f2b9 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/7b/a4c5c3561daa5ab1a86215cfb0587e96d404d6 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/87/3585b94bdeabccea991ea5e3ec1a277895b698 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/97/4cf7c73de336b0c4e019f918f3cee367d72e84 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/9d/bc299bc013ea253583b40bf327b5a6e4037b89 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/a9/104bf89e911387244ef499413960ba472066d9 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/b6/14088620bbdc1d29549d223ceba0f4419fd4cb delete mode 100644 tests-clar/resources/submod2/.gitted/objects/d4/07f19e50c1da1ff584beafe0d6dac7237c5d06 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/d9/3e95571d92cceb5de28c205f1d5f3cc8b88bc8 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/e3/b83bf274ee065eee48734cf8c6dfaf5e81471c delete mode 100644 tests-clar/resources/submod2/.gitted/objects/f5/4414c25e6d24fe39f5c3f128d7c8a17bc23833 delete mode 100644 tests-clar/resources/submod2/.gitted/objects/f9/90a25a74d1a8281ce2ab018ea8df66795cd60b delete mode 100644 tests-clar/resources/submod2/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/submod2/README.txt delete mode 100644 tests-clar/resources/submod2/gitmodules delete mode 100644 tests-clar/resources/submod2/just_a_dir/contents delete mode 100644 tests-clar/resources/submod2/just_a_file delete mode 100644 tests-clar/resources/submod2/not-submodule/.gitted/HEAD delete mode 100644 tests-clar/resources/submod2/not-submodule/.gitted/config delete mode 100644 tests-clar/resources/submod2/not-submodule/.gitted/description delete mode 100644 tests-clar/resources/submod2/not-submodule/.gitted/index delete mode 100644 tests-clar/resources/submod2/not-submodule/.gitted/info/exclude delete mode 100644 tests-clar/resources/submod2/not-submodule/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/submod2/not-submodule/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/submod2/not-submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 delete mode 100644 tests-clar/resources/submod2/not-submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 delete mode 100644 tests-clar/resources/submod2/not-submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e delete mode 100644 tests-clar/resources/submod2/not-submodule/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/submod2/not-submodule/README.txt delete mode 100644 tests-clar/resources/submod2/not/.gitted/notempty delete mode 100644 tests-clar/resources/submod2/not/README.txt delete mode 100644 tests-clar/resources/submod2/sm_added_and_uncommited/.gitted delete mode 100644 tests-clar/resources/submod2/sm_added_and_uncommited/README.txt delete mode 100644 tests-clar/resources/submod2/sm_added_and_uncommited/file_to_modify delete mode 100644 tests-clar/resources/submod2/sm_changed_file/.gitted delete mode 100644 tests-clar/resources/submod2/sm_changed_file/README.txt delete mode 100644 tests-clar/resources/submod2/sm_changed_file/file_to_modify delete mode 100644 tests-clar/resources/submod2/sm_changed_head/.gitted delete mode 100644 tests-clar/resources/submod2/sm_changed_head/README.txt delete mode 100644 tests-clar/resources/submod2/sm_changed_head/file_to_modify delete mode 100644 tests-clar/resources/submod2/sm_changed_index/.gitted delete mode 100644 tests-clar/resources/submod2/sm_changed_index/README.txt delete mode 100644 tests-clar/resources/submod2/sm_changed_index/file_to_modify delete mode 100644 tests-clar/resources/submod2/sm_changed_untracked_file/.gitted delete mode 100644 tests-clar/resources/submod2/sm_changed_untracked_file/README.txt delete mode 100644 tests-clar/resources/submod2/sm_changed_untracked_file/file_to_modify delete mode 100644 tests-clar/resources/submod2/sm_changed_untracked_file/i_am_untracked delete mode 100644 tests-clar/resources/submod2/sm_missing_commits/.gitted delete mode 100644 tests-clar/resources/submod2/sm_missing_commits/README.txt delete mode 100644 tests-clar/resources/submod2/sm_missing_commits/file_to_modify delete mode 100644 tests-clar/resources/submod2/sm_unchanged/.gitted delete mode 100644 tests-clar/resources/submod2/sm_unchanged/README.txt delete mode 100644 tests-clar/resources/submod2/sm_unchanged/file_to_modify delete mode 100644 tests-clar/resources/submod2_target/.gitted/HEAD delete mode 100644 tests-clar/resources/submod2_target/.gitted/config delete mode 100644 tests-clar/resources/submod2_target/.gitted/description delete mode 100644 tests-clar/resources/submod2_target/.gitted/index delete mode 100644 tests-clar/resources/submod2_target/.gitted/info/exclude delete mode 100644 tests-clar/resources/submod2_target/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/submod2_target/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/submod2_target/.gitted/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 delete mode 100644 tests-clar/resources/submod2_target/.gitted/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 delete mode 100644 tests-clar/resources/submod2_target/.gitted/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 delete mode 100644 tests-clar/resources/submod2_target/.gitted/objects/41/bd4bc3df978de695f67ace64c560913da11653 delete mode 100644 tests-clar/resources/submod2_target/.gitted/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 delete mode 100644 tests-clar/resources/submod2_target/.gitted/objects/5e/4963595a9774b90524d35a807169049de8ccad delete mode 100644 tests-clar/resources/submod2_target/.gitted/objects/6b/31c659545507c381e9cd34ec508f16c04e149e delete mode 100644 tests-clar/resources/submod2_target/.gitted/objects/73/ba924a80437097795ae839e66e187c55d3babf delete mode 100644 tests-clar/resources/submod2_target/.gitted/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a delete mode 100644 tests-clar/resources/submod2_target/.gitted/objects/78/9efbdadaa4a582778d4584385495559ea0994b delete mode 100644 tests-clar/resources/submod2_target/.gitted/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e delete mode 100644 tests-clar/resources/submod2_target/.gitted/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 delete mode 100644 tests-clar/resources/submod2_target/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/submod2_target/README.txt delete mode 100644 tests-clar/resources/submod2_target/file_to_modify delete mode 100644 tests-clar/resources/submodules/.gitted/HEAD delete mode 100644 tests-clar/resources/submodules/.gitted/config delete mode 100644 tests-clar/resources/submodules/.gitted/description delete mode 100644 tests-clar/resources/submodules/.gitted/index delete mode 100644 tests-clar/resources/submodules/.gitted/info/exclude delete mode 100644 tests-clar/resources/submodules/.gitted/info/refs delete mode 100644 tests-clar/resources/submodules/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/submodules/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/submodules/.gitted/objects/26/a3b32a9b7d97486c5557f5902e8ac94638145e delete mode 100644 tests-clar/resources/submodules/.gitted/objects/78/308c9251cf4eee8b25a76c7d2790c73d797357 delete mode 100644 tests-clar/resources/submodules/.gitted/objects/97/896810b3210244a62a82458b8e0819ecfc6850 delete mode 100644 tests-clar/resources/submodules/.gitted/objects/b6/0fd986699ba4e9e68bea07cf8e793f323ef888 delete mode 100644 tests-clar/resources/submodules/.gitted/objects/d5/f7fc3f74f7dec08280f370a975b112e8f60818 delete mode 100644 tests-clar/resources/submodules/.gitted/objects/e3/50052cc767cd1fcb37e84e9a89e701925be4ae delete mode 100644 tests-clar/resources/submodules/.gitted/objects/info/packs delete mode 100644 tests-clar/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx delete mode 100644 tests-clar/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack delete mode 100644 tests-clar/resources/submodules/.gitted/packed-refs delete mode 100644 tests-clar/resources/submodules/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/submodules/added delete mode 100644 tests-clar/resources/submodules/gitmodules delete mode 100644 tests-clar/resources/submodules/ignored delete mode 100644 tests-clar/resources/submodules/modified delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/HEAD delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/config delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/description delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/index delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/info/exclude delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/ae/90f12eea699729ed24555e40b9fd669da12a12 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/b6/361fc6a97178d8fc8639fdeed71c775ab52593 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/d6/c93164c249c8000205dd4ec5cbca1b516d487f delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/e7/b4ad382349ff96dd8199000580b9b1e2042eb0 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/f1/425cef211cc08caa31e7b545ffb232acb098c3 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/fd/093bff70906175335656e6ce6ae05783708765 delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/packed-refs delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/submodules/testrepo/.gitted/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/submodules/testrepo/README delete mode 100644 tests-clar/resources/submodules/testrepo/branch_file.txt delete mode 100644 tests-clar/resources/submodules/testrepo/new.txt delete mode 100644 tests-clar/resources/submodules/unmodified delete mode 100644 tests-clar/resources/submodules/untracked delete mode 100644 tests-clar/resources/template/branches/.gitignore delete mode 100644 tests-clar/resources/template/description delete mode 120000 tests-clar/resources/template/hooks/link.sample delete mode 100755 tests-clar/resources/template/hooks/update.sample delete mode 100644 tests-clar/resources/template/info/exclude delete mode 100644 tests-clar/resources/testrepo.git/FETCH_HEAD delete mode 100644 tests-clar/resources/testrepo.git/HEAD delete mode 100644 tests-clar/resources/testrepo.git/HEAD_TRACKER delete mode 100644 tests-clar/resources/testrepo.git/config delete mode 100644 tests-clar/resources/testrepo.git/index delete mode 100644 tests-clar/resources/testrepo.git/logs/HEAD delete mode 100644 tests-clar/resources/testrepo.git/logs/refs/heads/br2 delete mode 100644 tests-clar/resources/testrepo.git/logs/refs/heads/master delete mode 100644 tests-clar/resources/testrepo.git/logs/refs/heads/not-good delete mode 100644 tests-clar/resources/testrepo.git/logs/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/testrepo.git/logs/refs/remotes/test/master delete mode 100644 tests-clar/resources/testrepo.git/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 delete mode 100644 tests-clar/resources/testrepo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 delete mode 100644 tests-clar/resources/testrepo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 delete mode 100644 tests-clar/resources/testrepo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd delete mode 100644 tests-clar/resources/testrepo.git/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd delete mode 100644 tests-clar/resources/testrepo.git/objects/1b/8cbad43e867676df601306689fe7c3def5e689 delete mode 100644 tests-clar/resources/testrepo.git/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b delete mode 100644 tests-clar/resources/testrepo.git/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 delete mode 100644 tests-clar/resources/testrepo.git/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d delete mode 100644 tests-clar/resources/testrepo.git/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 delete mode 100644 tests-clar/resources/testrepo.git/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 delete mode 100644 tests-clar/resources/testrepo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc delete mode 100644 tests-clar/resources/testrepo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 delete mode 100644 tests-clar/resources/testrepo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 delete mode 100644 tests-clar/resources/testrepo.git/objects/4a/23e2e65ad4e31c4c9db7dc746650bfad082679 delete mode 100644 tests-clar/resources/testrepo.git/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea delete mode 100644 tests-clar/resources/testrepo.git/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 delete mode 100644 tests-clar/resources/testrepo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 delete mode 100644 tests-clar/resources/testrepo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a delete mode 100644 tests-clar/resources/testrepo.git/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af delete mode 100644 tests-clar/resources/testrepo.git/objects/7b/4384978d2493e851f9cca7858815fac9b10980 delete mode 100644 tests-clar/resources/testrepo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d delete mode 100644 tests-clar/resources/testrepo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 delete mode 100644 tests-clar/resources/testrepo.git/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe delete mode 100644 tests-clar/resources/testrepo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 delete mode 100644 tests-clar/resources/testrepo.git/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 delete mode 100644 tests-clar/resources/testrepo.git/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 delete mode 100644 tests-clar/resources/testrepo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a delete mode 100644 tests-clar/resources/testrepo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f delete mode 100644 tests-clar/resources/testrepo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 delete mode 100644 tests-clar/resources/testrepo.git/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd delete mode 100644 tests-clar/resources/testrepo.git/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 delete mode 100644 tests-clar/resources/testrepo.git/objects/ae/90f12eea699729ed24555e40b9fd669da12a12 delete mode 100644 tests-clar/resources/testrepo.git/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 delete mode 100644 tests-clar/resources/testrepo.git/objects/b6/361fc6a97178d8fc8639fdeed71c775ab52593 delete mode 100644 tests-clar/resources/testrepo.git/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 delete mode 100644 tests-clar/resources/testrepo.git/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd delete mode 100644 tests-clar/resources/testrepo.git/objects/d0/7b0f9a8c89f1d9e74dc4fce6421dec5ef8a659 delete mode 100644 tests-clar/resources/testrepo.git/objects/d6/c93164c249c8000205dd4ec5cbca1b516d487f delete mode 100644 tests-clar/resources/testrepo.git/objects/d7/1aab4f9b04b45ce09bcaa636a9be6231474759 delete mode 100644 tests-clar/resources/testrepo.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 delete mode 100644 tests-clar/resources/testrepo.git/objects/e7/b4ad382349ff96dd8199000580b9b1e2042eb0 delete mode 100644 tests-clar/resources/testrepo.git/objects/f1/425cef211cc08caa31e7b545ffb232acb098c3 delete mode 100644 tests-clar/resources/testrepo.git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 delete mode 100644 tests-clar/resources/testrepo.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 delete mode 100644 tests-clar/resources/testrepo.git/objects/fd/093bff70906175335656e6ce6ae05783708765 delete mode 100644 tests-clar/resources/testrepo.git/objects/fd/4959ce7510db09d4d8217fa2d1780413e05a09 delete mode 100644 tests-clar/resources/testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx delete mode 100644 tests-clar/resources/testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack delete mode 100644 tests-clar/resources/testrepo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx delete mode 100644 tests-clar/resources/testrepo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack delete mode 100644 tests-clar/resources/testrepo.git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx delete mode 100644 tests-clar/resources/testrepo.git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack delete mode 100644 tests-clar/resources/testrepo.git/packed-refs delete mode 100644 tests-clar/resources/testrepo.git/refs/heads/br2 delete mode 100644 tests-clar/resources/testrepo.git/refs/heads/cannot-fetch delete mode 100644 tests-clar/resources/testrepo.git/refs/heads/chomped delete mode 100644 tests-clar/resources/testrepo.git/refs/heads/haacked delete mode 100644 tests-clar/resources/testrepo.git/refs/heads/master delete mode 100644 tests-clar/resources/testrepo.git/refs/heads/not-good delete mode 100644 tests-clar/resources/testrepo.git/refs/heads/packed-test delete mode 100644 tests-clar/resources/testrepo.git/refs/heads/subtrees delete mode 100644 tests-clar/resources/testrepo.git/refs/heads/test delete mode 100644 tests-clar/resources/testrepo.git/refs/heads/track-local delete mode 100644 tests-clar/resources/testrepo.git/refs/heads/trailing delete mode 100644 tests-clar/resources/testrepo.git/refs/notes/fanout delete mode 100644 tests-clar/resources/testrepo.git/refs/remotes/test/master delete mode 100644 tests-clar/resources/testrepo.git/refs/tags/annotated_tag_to_blob delete mode 100644 tests-clar/resources/testrepo.git/refs/tags/e90810b delete mode 100644 tests-clar/resources/testrepo.git/refs/tags/hard_tag delete mode 100644 tests-clar/resources/testrepo.git/refs/tags/point_to_blob delete mode 100644 tests-clar/resources/testrepo.git/refs/tags/taggerless delete mode 100644 tests-clar/resources/testrepo.git/refs/tags/test delete mode 100644 tests-clar/resources/testrepo.git/refs/tags/wrapped_tag delete mode 100644 tests-clar/resources/testrepo/.gitted/HEAD delete mode 100644 tests-clar/resources/testrepo/.gitted/HEAD_TRACKER delete mode 100644 tests-clar/resources/testrepo/.gitted/config delete mode 100644 tests-clar/resources/testrepo/.gitted/index delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/09/9fabac3a9ea935598528c27f866e34089c2eff delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/16/8e4ebd1c667499548ae12403b19b22a5c5e925 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/45/dd856fdd4d89b884c340ba0e047752d9b085d6 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/87/380ae84009e9c503506c2f6143a4fc6c60bf80 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/ae/90f12eea699729ed24555e40b9fd669da12a12 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/b6/361fc6a97178d8fc8639fdeed71c775ab52593 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/c0/528fd6cc988c0a40ce0be11bc192fc8dc5346e delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/cf/80f8de9f1185bf3a05f993f6121880dd0cfbc9 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/d5/2a8fe84ceedf260afe4f0287bbfca04a117e83 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/d6/c93164c249c8000205dd4ec5cbca1b516d487f delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/e7/b4ad382349ff96dd8199000580b9b1e2042eb0 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/f1/425cef211cc08caa31e7b545ffb232acb098c3 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/fd/093bff70906175335656e6ce6ae05783708765 delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx delete mode 100644 tests-clar/resources/testrepo/.gitted/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack delete mode 100644 tests-clar/resources/testrepo/.gitted/packed-refs delete mode 100644 tests-clar/resources/testrepo/.gitted/refs/heads/br2 delete mode 100644 tests-clar/resources/testrepo/.gitted/refs/heads/dir delete mode 100644 tests-clar/resources/testrepo/.gitted/refs/heads/long-file-name delete mode 100644 tests-clar/resources/testrepo/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/testrepo/.gitted/refs/heads/packed-test delete mode 100644 tests-clar/resources/testrepo/.gitted/refs/heads/subtrees delete mode 100644 tests-clar/resources/testrepo/.gitted/refs/heads/test delete mode 100644 tests-clar/resources/testrepo/.gitted/refs/tags/e90810b delete mode 100644 tests-clar/resources/testrepo/.gitted/refs/tags/foo/bar delete mode 100644 tests-clar/resources/testrepo/.gitted/refs/tags/foo/foo/bar delete mode 100644 tests-clar/resources/testrepo/.gitted/refs/tags/point_to_blob delete mode 100644 tests-clar/resources/testrepo/.gitted/refs/tags/test delete mode 100644 tests-clar/resources/testrepo2/.gitted/HEAD delete mode 100644 tests-clar/resources/testrepo2/.gitted/config delete mode 100644 tests-clar/resources/testrepo2/.gitted/description delete mode 100644 tests-clar/resources/testrepo2/.gitted/index delete mode 100644 tests-clar/resources/testrepo2/.gitted/info/exclude delete mode 100644 tests-clar/resources/testrepo2/.gitted/logs/HEAD delete mode 100644 tests-clar/resources/testrepo2/.gitted/logs/refs/heads/master delete mode 100644 tests-clar/resources/testrepo2/.gitted/logs/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/36/060c58702ed4c2a40832c51758d5344201d89a delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/c4/dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/fd/093bff70906175335656e6ce6ae05783708765 delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx delete mode 100644 tests-clar/resources/testrepo2/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack delete mode 100644 tests-clar/resources/testrepo2/.gitted/packed-refs delete mode 100644 tests-clar/resources/testrepo2/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/testrepo2/.gitted/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/testrepo2/README delete mode 100644 tests-clar/resources/testrepo2/new.txt delete mode 100644 tests-clar/resources/testrepo2/subdir/README delete mode 100644 tests-clar/resources/testrepo2/subdir/new.txt delete mode 100644 tests-clar/resources/testrepo2/subdir/subdir2/README delete mode 100644 tests-clar/resources/testrepo2/subdir/subdir2/new.txt delete mode 100644 tests-clar/resources/twowaymerge.git/HEAD delete mode 100644 tests-clar/resources/twowaymerge.git/config delete mode 100644 tests-clar/resources/twowaymerge.git/description delete mode 100644 tests-clar/resources/twowaymerge.git/info/exclude delete mode 100644 tests-clar/resources/twowaymerge.git/objects/0c/8a3f1f3d5f421cf83048c7c73ee3b55a5e0f29 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/10/2dce8e3081f398e4bdd9fd894dc85ac3ca6a67 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/17/7d8634a28e26ec7819284752757ebe01a479d5 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/1c/30b88f5f3ee66d78df6520a7de9e89b890818b delete mode 100644 tests-clar/resources/twowaymerge.git/objects/1f/4c0311a24b63f6fc209a59a1e404942d4a5006 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/29/6e56023cdc034d2735fee8c0d85a659d1b07f4 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/31/51880ae2b363f1c262cf98b750c1f169a0d432 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/3b/287f8730c81d0b763c2d294618a5e32b67b4f8 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/42/b7311aa626e712891940c1ec5d5cba201946a4 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/49/6d6428b9cf92981dc9495211e6e1120fb6f2ba delete mode 100644 tests-clar/resources/twowaymerge.git/objects/59/b0cf7d74659e1cdb13305319d6d4ce2733c118 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f delete mode 100644 tests-clar/resources/twowaymerge.git/objects/6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/76/5b32c65d38f04c4f287abda055818ec0f26912 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/7b/8c336c45fc6895c1c60827260fe5d798e5d247 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/82/bf9a1a10a4b25c1f14c9607b60970705e92545 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/9a/40a2f11c191f180c47e54b11567cb3c1e89b30 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/9b/219343610c88a1187c996d0dc58330b55cee28 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/9f/e06a50f4d1634d6c6879854d01d80857388706 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c delete mode 100644 tests-clar/resources/twowaymerge.git/objects/bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/c3/7a783c20d92ac92362a78a32860f7eebf938ef delete mode 100644 tests-clar/resources/twowaymerge.git/objects/cb/dd40facab1682754eb67f7a43f29e672903cf6 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/d6/f10d549cb335b9e6d38afc1f0088be69b50494 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e delete mode 100644 tests-clar/resources/twowaymerge.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/ef/0488f0b722f0be8bcb90a7730ac7efafd1d694 delete mode 100644 tests-clar/resources/twowaymerge.git/objects/fc/f7e3f51c11d199ab7a78403ee4f9ccd028da25 delete mode 100644 tests-clar/resources/twowaymerge.git/refs/heads/first-branch delete mode 100644 tests-clar/resources/twowaymerge.git/refs/heads/master delete mode 100644 tests-clar/resources/twowaymerge.git/refs/heads/second-branch delete mode 100644 tests-clar/resources/typechanges/.gitted/HEAD delete mode 100644 tests-clar/resources/typechanges/.gitted/config delete mode 100644 tests-clar/resources/typechanges/.gitted/description delete mode 100644 tests-clar/resources/typechanges/.gitted/index delete mode 100644 tests-clar/resources/typechanges/.gitted/info/exclude delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/HEAD delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/config delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/description delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/index delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/info/exclude delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/objects/41/bd4bc3df978de695f67ace64c560913da11653 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/objects/5e/4963595a9774b90524d35a807169049de8ccad delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/objects/6b/31c659545507c381e9cd34ec508f16c04e149e delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/objects/73/ba924a80437097795ae839e66e187c55d3babf delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/objects/78/9efbdadaa4a582778d4584385495559ea0994b delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/packed-refs delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/refs/heads/master delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/b/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/HEAD delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/config delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/description delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/index delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/info/exclude delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/objects/41/bd4bc3df978de695f67ace64c560913da11653 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/objects/5e/4963595a9774b90524d35a807169049de8ccad delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/objects/6b/31c659545507c381e9cd34ec508f16c04e149e delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/objects/73/ba924a80437097795ae839e66e187c55d3babf delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/objects/78/9efbdadaa4a582778d4584385495559ea0994b delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/packed-refs delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/refs/heads/master delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/d/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/HEAD delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/config delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/description delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/index delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/info/exclude delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/objects/41/bd4bc3df978de695f67ace64c560913da11653 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/objects/5e/4963595a9774b90524d35a807169049de8ccad delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/objects/6b/31c659545507c381e9cd34ec508f16c04e149e delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/objects/73/ba924a80437097795ae839e66e187c55d3babf delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/objects/78/9efbdadaa4a582778d4584385495559ea0994b delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/packed-refs delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/refs/heads/master delete mode 100644 tests-clar/resources/typechanges/.gitted/modules/e/refs/remotes/origin/HEAD delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/0d/78578795b7ca49fd8df6c4b6d27c5c02d991d8 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/0e/7ed140b514b8cae23254cb8656fe1674403aff delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/0f/f461da9689266f482d8f6654a4400b4e33c586 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/18/aa7e45bbe4c3cc24a0b079696c59d36675af97 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/1b/63caae4a5ca96f78e8dfefc376c6a39a142475 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/1e/abe82aa3b2365a394f6108f24435df6e193d02 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/42/061c01a1c70097d1e4579f29a5adf40abdec95 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/46/2838cee476a87e7cff32196b66fa18ed756592 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/63/499e4ea8e096b831515ceb1d5a7593e4d87ae5 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/68/1af94e10eaf262f3ab7cb9b8fd5f4158ba4d3e delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/6a/9008602b811e69a9b7a2d83496f39a794fdeeb delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/6e/ae26c90e8ccc4d16208972119c40635489c6f0 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/6f/39eabbb8a7541515e0d35971078bccb502e7e0 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/71/54d3083461536dfc71ad5542f3e65e723a06c4 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/75/56c1d893a4c0ca85ac8ac51de47ff399758729 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/76/fef844064c26d5e06c2508240dae661e7231b2 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/79/b9f23e85f55ea36a472a902e875bc1121a94cb delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/85/28da0ea65eacf1f74f9ed6696adbac547963ad delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/8b/3726b365824ad5a07c537247f4bc73ed7d37ea delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/93/3e28c1c8a68838a763d250bdf0b2c6068289c3 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/96/2710fe5b4e453e9e827945b3487c525968ec4a delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/96/6cf1b3598e195b31b2cde3784f9a19f0728a6f delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/99/e8bab9ece009f0fba7eb41f850f4c12bedb9b7 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/9b/19edf33a03a0c59cdfc113bfa5c06179bf9b1a delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/9b/db75b73836a99e3dbeea640a81de81031fdc29 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/9d/0235c7a7edc0889a18f97a42ee6db9fe688447 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/9e/ffc457877f109b2a4319e14bee613a15f2a00d delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/a0/a9bad6f6f40325198f938a0e3ae981622d7707 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/b1/977dc4e573b812d4619754c98138c56999dc0d delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/d7/5992dd02391e128dac332dcc78d649dd9ab095 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/da/e2709d638df52212b1f43ff61797ebfedfcc7c delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/e1/152adcb9adf37ec551ada9ba377ab53aec3bad delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/e4/ed436a9eb0f198cda722886a5f8d6d6c836b7b delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/f2/0b79342712e0b2315647cd8227a573fd3bc46e delete mode 100644 tests-clar/resources/typechanges/.gitted/objects/fd/e0147e3b59f381635a3b016e3fe6dacb70779d delete mode 100644 tests-clar/resources/typechanges/.gitted/refs/heads/master delete mode 100644 tests-clar/resources/typechanges/README.md delete mode 100644 tests-clar/resources/typechanges/gitmodules delete mode 100644 tests-clar/resources/unsymlinked.git/HEAD delete mode 100644 tests-clar/resources/unsymlinked.git/config delete mode 100644 tests-clar/resources/unsymlinked.git/description delete mode 100644 tests-clar/resources/unsymlinked.git/info/exclude delete mode 100644 tests-clar/resources/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf delete mode 100644 tests-clar/resources/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b delete mode 100644 tests-clar/resources/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c delete mode 100644 tests-clar/resources/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 delete mode 100644 tests-clar/resources/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c delete mode 100644 tests-clar/resources/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 delete mode 100644 tests-clar/resources/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d delete mode 100644 tests-clar/resources/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 delete mode 100644 tests-clar/resources/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 delete mode 100644 tests-clar/resources/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 delete mode 100644 tests-clar/resources/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 delete mode 100644 tests-clar/resources/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a delete mode 100644 tests-clar/resources/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 delete mode 100644 tests-clar/resources/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 delete mode 100644 tests-clar/resources/unsymlinked.git/refs/heads/exe-file delete mode 100644 tests-clar/resources/unsymlinked.git/refs/heads/master delete mode 100644 tests-clar/resources/unsymlinked.git/refs/heads/reg-file delete mode 100644 tests-clar/revwalk/basic.c delete mode 100644 tests-clar/revwalk/mergebase.c delete mode 100644 tests-clar/revwalk/signatureparsing.c delete mode 100644 tests-clar/revwalk/simplify.c delete mode 100644 tests-clar/stash/drop.c delete mode 100644 tests-clar/stash/foreach.c delete mode 100644 tests-clar/stash/save.c delete mode 100644 tests-clar/stash/stash_helpers.c delete mode 100644 tests-clar/stash/stash_helpers.h delete mode 100644 tests-clar/stash/submodules.c delete mode 100644 tests-clar/status/ignore.c delete mode 100644 tests-clar/status/renames.c delete mode 100644 tests-clar/status/single.c delete mode 100644 tests-clar/status/status_data.h delete mode 100644 tests-clar/status/status_helpers.c delete mode 100644 tests-clar/status/status_helpers.h delete mode 100644 tests-clar/status/submodules.c delete mode 100644 tests-clar/status/worktree.c delete mode 100644 tests-clar/status/worktree_init.c delete mode 100644 tests-clar/stress/diff.c delete mode 100644 tests-clar/submodule/lookup.c delete mode 100644 tests-clar/submodule/modify.c delete mode 100644 tests-clar/submodule/status.c delete mode 100644 tests-clar/submodule/submodule_helpers.c delete mode 100644 tests-clar/submodule/submodule_helpers.h delete mode 100644 tests-clar/threads/basic.c delete mode 100644 tests-clar/threads/refdb.c delete mode 100644 tests-clar/trace/trace.c delete mode 100644 tests-clar/valgrind-supp-mac.txt create mode 100644 tests/README.md create mode 100644 tests/attr/attr_expect.h create mode 100644 tests/attr/file.c create mode 100644 tests/attr/flags.c create mode 100644 tests/attr/ignore.c create mode 100644 tests/attr/lookup.c create mode 100644 tests/attr/repo.c create mode 100644 tests/blame/blame_helpers.c create mode 100644 tests/blame/blame_helpers.h create mode 100644 tests/blame/buffer.c create mode 100644 tests/blame/getters.c create mode 100644 tests/blame/harder.c create mode 100644 tests/blame/simple.c create mode 100644 tests/buf/basic.c create mode 100644 tests/buf/splice.c create mode 100644 tests/checkout/binaryunicode.c create mode 100644 tests/checkout/checkout_helpers.c create mode 100644 tests/checkout/checkout_helpers.h create mode 100644 tests/checkout/conflict.c create mode 100644 tests/checkout/crlf.c create mode 100644 tests/checkout/head.c create mode 100644 tests/checkout/index.c create mode 100644 tests/checkout/tree.c create mode 100644 tests/checkout/typechange.c create mode 100644 tests/clar.c create mode 100644 tests/clar.h create mode 100644 tests/clar/fixtures.h create mode 100644 tests/clar/fs.h create mode 100644 tests/clar/print.h create mode 100644 tests/clar/sandbox.h create mode 100644 tests/clar_libgit2.c create mode 100644 tests/clar_libgit2.h create mode 100644 tests/clone/empty.c create mode 100644 tests/clone/nonetwork.c create mode 100644 tests/commit/commit.c create mode 100644 tests/commit/parent.c create mode 100644 tests/commit/parse.c create mode 100644 tests/commit/signature.c create mode 100644 tests/commit/write.c create mode 100644 tests/config/add.c create mode 100644 tests/config/backend.c create mode 100644 tests/config/config_helpers.c create mode 100644 tests/config/config_helpers.h create mode 100644 tests/config/configlevel.c create mode 100644 tests/config/global.c create mode 100644 tests/config/include.c create mode 100644 tests/config/multivar.c create mode 100644 tests/config/new.c create mode 100644 tests/config/read.c create mode 100644 tests/config/refresh.c create mode 100644 tests/config/stress.c create mode 100644 tests/config/validkeyname.c create mode 100644 tests/config/write.c create mode 100644 tests/core/bitvec.c create mode 100644 tests/core/buffer.c create mode 100644 tests/core/caps.c create mode 100644 tests/core/copy.c create mode 100644 tests/core/dirent.c create mode 100644 tests/core/env.c create mode 100644 tests/core/errors.c create mode 100644 tests/core/filebuf.c create mode 100644 tests/core/hex.c create mode 100644 tests/core/iconv.c create mode 100644 tests/core/mkdir.c create mode 100644 tests/core/oid.c create mode 100644 tests/core/oidmap.c create mode 100644 tests/core/opts.c create mode 100644 tests/core/path.c create mode 100644 tests/core/pool.c create mode 100644 tests/core/posix.c create mode 100644 tests/core/rmdir.c create mode 100644 tests/core/sortedcache.c create mode 100644 tests/core/stat.c create mode 100644 tests/core/string.c create mode 100644 tests/core/strmap.c create mode 100644 tests/core/strtol.c create mode 100644 tests/core/vector.c create mode 100644 tests/date/date.c create mode 100644 tests/diff/blob.c create mode 100644 tests/diff/diff_helpers.c create mode 100644 tests/diff/diff_helpers.h create mode 100644 tests/diff/diffiter.c create mode 100644 tests/diff/drivers.c create mode 100644 tests/diff/index.c create mode 100644 tests/diff/iterator.c create mode 100644 tests/diff/notify.c create mode 100644 tests/diff/patch.c create mode 100644 tests/diff/pathspec.c create mode 100644 tests/diff/rename.c create mode 100644 tests/diff/submodules.c create mode 100644 tests/diff/tree.c create mode 100644 tests/diff/workdir.c create mode 100644 tests/fetchhead/fetchhead_data.h create mode 100644 tests/fetchhead/nonetwork.c create mode 100644 tests/filter/blob.c create mode 100644 tests/filter/crlf.c create mode 100644 tests/filter/crlf.h create mode 100644 tests/filter/custom.c create mode 100644 tests/filter/ident.c create mode 100644 tests/generate.py create mode 100644 tests/index/addall.c create mode 100644 tests/index/conflicts.c create mode 100644 tests/index/filemodes.c create mode 100644 tests/index/inmemory.c create mode 100644 tests/index/names.c create mode 100644 tests/index/read_tree.c create mode 100644 tests/index/rename.c create mode 100644 tests/index/reuc.c create mode 100644 tests/index/stage.c create mode 100644 tests/index/tests.c create mode 100644 tests/main.c create mode 100644 tests/merge/merge_helpers.c create mode 100644 tests/merge/merge_helpers.h create mode 100644 tests/merge/trees/automerge.c create mode 100644 tests/merge/trees/modeconflict.c create mode 100644 tests/merge/trees/renames.c create mode 100644 tests/merge/trees/treediff.c create mode 100644 tests/merge/trees/trivial.c create mode 100644 tests/merge/workdir/fastforward.c create mode 100644 tests/merge/workdir/renames.c create mode 100644 tests/merge/workdir/setup.c create mode 100644 tests/merge/workdir/simple.c create mode 100644 tests/merge/workdir/trivial.c create mode 100644 tests/network/cred.c create mode 100644 tests/network/fetchlocal.c create mode 100644 tests/network/refspecs.c create mode 100644 tests/network/remote/createthenload.c create mode 100644 tests/network/remote/isvalidname.c create mode 100644 tests/network/remote/local.c create mode 100644 tests/network/remote/remotes.c create mode 100644 tests/network/remote/rename.c create mode 100644 tests/network/urlparse.c create mode 100644 tests/notes/notes.c create mode 100644 tests/notes/notesref.c create mode 100644 tests/object/blob/filter.c create mode 100644 tests/object/blob/fromchunks.c create mode 100644 tests/object/blob/write.c create mode 100644 tests/object/cache.c create mode 100644 tests/object/commit/commitstagedfile.c create mode 100644 tests/object/lookup.c create mode 100644 tests/object/lookupbypath.c create mode 100644 tests/object/message.c create mode 100644 tests/object/peel.c create mode 100644 tests/object/raw/chars.c create mode 100644 tests/object/raw/compare.c create mode 100644 tests/object/raw/convert.c create mode 100644 tests/object/raw/data.h create mode 100644 tests/object/raw/fromstr.c create mode 100644 tests/object/raw/hash.c create mode 100644 tests/object/raw/short.c create mode 100644 tests/object/raw/size.c create mode 100644 tests/object/raw/type2string.c create mode 100644 tests/object/raw/write.c create mode 100644 tests/object/tag/list.c create mode 100644 tests/object/tag/peel.c create mode 100644 tests/object/tag/read.c create mode 100644 tests/object/tag/write.c create mode 100644 tests/object/tree/attributes.c create mode 100644 tests/object/tree/duplicateentries.c create mode 100644 tests/object/tree/frompath.c create mode 100644 tests/object/tree/read.c create mode 100644 tests/object/tree/walk.c create mode 100644 tests/object/tree/write.c create mode 100644 tests/odb/alternates.c create mode 100644 tests/odb/backend/nonrefreshing.c create mode 100644 tests/odb/foreach.c create mode 100644 tests/odb/loose.c create mode 100644 tests/odb/loose_data.h create mode 100644 tests/odb/mixed.c create mode 100644 tests/odb/pack_data.h create mode 100644 tests/odb/pack_data_one.h create mode 100644 tests/odb/packed.c create mode 100644 tests/odb/packed_one.c create mode 100644 tests/odb/sorting.c create mode 100644 tests/odb/streamwrite.c create mode 100644 tests/online/clone.c create mode 100644 tests/online/fetch.c create mode 100644 tests/online/fetchhead.c create mode 100644 tests/online/push.c create mode 100644 tests/online/push_util.c create mode 100644 tests/online/push_util.h create mode 100644 tests/pack/indexer.c create mode 100644 tests/pack/packbuilder.c create mode 100644 tests/refs/branches/create.c create mode 100644 tests/refs/branches/delete.c create mode 100644 tests/refs/branches/ishead.c create mode 100644 tests/refs/branches/iterator.c create mode 100644 tests/refs/branches/lookup.c create mode 100644 tests/refs/branches/move.c create mode 100644 tests/refs/branches/name.c create mode 100644 tests/refs/branches/remote.c create mode 100644 tests/refs/branches/upstream.c create mode 100644 tests/refs/branches/upstreamname.c create mode 100644 tests/refs/crashes.c create mode 100644 tests/refs/create.c create mode 100644 tests/refs/delete.c create mode 100644 tests/refs/foreachglob.c create mode 100644 tests/refs/isvalidname.c create mode 100644 tests/refs/iterator.c create mode 100644 tests/refs/list.c create mode 100644 tests/refs/listall.c create mode 100644 tests/refs/lookup.c create mode 100644 tests/refs/normalize.c create mode 100644 tests/refs/overwrite.c create mode 100644 tests/refs/pack.c create mode 100644 tests/refs/peel.c create mode 100644 tests/refs/read.c create mode 100644 tests/refs/ref_helpers.c create mode 100644 tests/refs/ref_helpers.h create mode 100644 tests/refs/reflog/drop.c create mode 100644 tests/refs/reflog/reflog.c create mode 100644 tests/refs/rename.c create mode 100644 tests/refs/revparse.c create mode 100644 tests/refs/setter.c create mode 100644 tests/refs/shorthand.c create mode 100644 tests/refs/unicode.c create mode 100644 tests/refs/update.c create mode 100644 tests/repo/config.c create mode 100644 tests/repo/discover.c create mode 100644 tests/repo/getters.c create mode 100644 tests/repo/hashfile.c create mode 100644 tests/repo/head.c create mode 100644 tests/repo/headtree.c create mode 100644 tests/repo/init.c create mode 100644 tests/repo/iterator.c create mode 100644 tests/repo/message.c create mode 100644 tests/repo/open.c create mode 100644 tests/repo/pathspec.c create mode 100644 tests/repo/repo_helpers.c create mode 100644 tests/repo/repo_helpers.h create mode 100644 tests/repo/setters.c create mode 100644 tests/repo/shallow.c create mode 100644 tests/repo/state.c create mode 100644 tests/reset/default.c create mode 100644 tests/reset/hard.c create mode 100644 tests/reset/mixed.c create mode 100644 tests/reset/reset_helpers.c create mode 100644 tests/reset/reset_helpers.h create mode 100644 tests/reset/soft.c create mode 100644 tests/resources/.gitattributes create mode 100644 tests/resources/.gitignore create mode 100644 tests/resources/attr/.gitted/HEAD create mode 100644 tests/resources/attr/.gitted/config create mode 100644 tests/resources/attr/.gitted/description create mode 100644 tests/resources/attr/.gitted/index create mode 100644 tests/resources/attr/.gitted/info/attributes create mode 100644 tests/resources/attr/.gitted/info/exclude create mode 100644 tests/resources/attr/.gitted/logs/HEAD create mode 100644 tests/resources/attr/.gitted/logs/refs/heads/master create mode 100644 tests/resources/attr/.gitted/objects/10/8bb4e7fd7b16490dc33ff7d972151e73d7166e create mode 100644 tests/resources/attr/.gitted/objects/16/983da6643656bb44c43965ecb6855c6d574512 create mode 100644 tests/resources/attr/.gitted/objects/21/7878ab49e1314388ea2e32dc6fdb58a1b969e0 create mode 100644 tests/resources/attr/.gitted/objects/24/fa9a9fc4e202313e24b648087495441dab432b create mode 100644 tests/resources/attr/.gitted/objects/29/29de282ce999e95183aedac6451d3384559c4b create mode 100644 tests/resources/attr/.gitted/objects/2b/40c5aca159b04ea8d20ffe36cdf8b09369b14a create mode 100644 tests/resources/attr/.gitted/objects/2c/66e14f77196ea763fb1e41612c1aa2bc2d8ed2 create mode 100644 tests/resources/attr/.gitted/objects/2d/e7dfe3588f3c7e9ad59e7d50ba90e3329df9d9 create mode 100644 tests/resources/attr/.gitted/objects/37/0fe9ec224ce33e71f9e5ec2bd1142ce9937a6a create mode 100644 tests/resources/attr/.gitted/objects/3a/6df026462ebafe455af9867d27eda20a9e0974 create mode 100644 tests/resources/attr/.gitted/objects/3b/74db7ab381105dc0d28f8295a77f6a82989292 create mode 100644 tests/resources/attr/.gitted/objects/3e/42ffc54a663f9401cc25843d6c0e71a33e4249 create mode 100644 tests/resources/attr/.gitted/objects/45/141a79a77842c59a63229403220a4e4be74e3d create mode 100644 tests/resources/attr/.gitted/objects/45/5a314fa848d52ae1f11d254da4f60858fc97f4 create mode 100644 tests/resources/attr/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 create mode 100644 tests/resources/attr/.gitted/objects/4d/713dc48e6b1bd75b0d61ad078ba9ca3a56745d create mode 100644 tests/resources/attr/.gitted/objects/4e/49ba8c5b6c32ff28cd9dcb60be34df50fcc485 create mode 100644 tests/resources/attr/.gitted/objects/55/6f8c827b8e4a02ad5cab77dca2bcb3e226b0b3 create mode 100644 tests/resources/attr/.gitted/objects/58/19a185d77b03325aaf87cafc771db36f6ddca7 create mode 100644 tests/resources/attr/.gitted/objects/60/5812ab7fe421fdd325a935d35cb06a9234a7d7 create mode 100644 tests/resources/attr/.gitted/objects/6b/ab5c79cd5140d0f800917f550eb2a3dc32b0da create mode 100644 tests/resources/attr/.gitted/objects/6d/968d62c89c7d9ea23a4c9a7b665d017c3d8ffd create mode 100644 tests/resources/attr/.gitted/objects/71/7fc31f6b84f9d6fc3a4edbca259d7fc92beee2 create mode 100644 tests/resources/attr/.gitted/objects/8d/0b9df9bd30be7910ddda60548d485bc302b911 create mode 100644 tests/resources/attr/.gitted/objects/93/61f40bb97239cf55811892e14de2e344168ba1 create mode 100644 tests/resources/attr/.gitted/objects/94/da4faa0a6bfb8ee6ccf7153801a69202b31857 create mode 100644 tests/resources/attr/.gitted/objects/96/089fd31ce1d3ee2afb0ba09ba063066932f027 create mode 100644 tests/resources/attr/.gitted/objects/99/eae476896f4907224978b88e5ecaa6c5bb67a9 create mode 100644 tests/resources/attr/.gitted/objects/9e/5bdc47d6a80f2be0ea3049ad74231b94609242 create mode 100644 tests/resources/attr/.gitted/objects/9f/b40b6675dde60b5697afceae91b66d908c02d9 create mode 100644 tests/resources/attr/.gitted/objects/a0/f7217ae99f5ac3e88534f5cea267febc5fa85b create mode 100644 tests/resources/attr/.gitted/objects/a5/6bbcecaeac760cc26239384d2d4c614e7e4320 create mode 100644 tests/resources/attr/.gitted/objects/a5/d76cad53f66f1312bd995909a5bab3c0820770 create mode 100644 tests/resources/attr/.gitted/objects/a9/7cc019851d401a4f1d091cb91a15890a0dd1ba create mode 100644 tests/resources/attr/.gitted/objects/b4/35cd5689a0fb54afbeda4ac20368aa480e8f04 create mode 100644 tests/resources/attr/.gitted/objects/c0/091889c0c77142b87a1fa5123a6398a61d33e7 create mode 100644 tests/resources/attr/.gitted/objects/c4/85abe35abd4aa6fd83b076a78bbea9e2e7e06c create mode 100644 tests/resources/attr/.gitted/objects/c7/aadd770d5907a8475c29e9ee21a27b88bf675d create mode 100644 tests/resources/attr/.gitted/objects/c9/6bbb2c2557a8325ae1559e3ba79cdcecb23076 create mode 100644 tests/resources/attr/.gitted/objects/ce/39a97a7fb1fa90bcf5e711249c1e507476ae0e create mode 100644 tests/resources/attr/.gitted/objects/d5/7da33c16b14326ecb05d19bbea908f5e4c47d9 create mode 100644 tests/resources/attr/.gitted/objects/d8/00886d9c86731ae5c4a62b0b77c437015e00d2 create mode 100644 tests/resources/attr/.gitted/objects/dc/cada462d3df8ac6de596fb8c896aba9344f941 create mode 100644 tests/resources/attr/.gitted/objects/de/863bff4976c9ed7e17a4da0fd524908dc84049 create mode 100644 tests/resources/attr/.gitted/objects/e5/63cf4758f0d646f1b14b76016aa17fa9e549a4 create mode 100644 tests/resources/attr/.gitted/objects/ec/b97df2a174987475ac816e3847fc8e9f6c596b create mode 100644 tests/resources/attr/.gitted/objects/ed/f3dcee4003d71f139777898882ccd097e34c53 create mode 100644 tests/resources/attr/.gitted/objects/f2/c6d717cf4a5a3e6b02684155ab07b766982165 create mode 100644 tests/resources/attr/.gitted/objects/f5/b0af1fb4f5c0cd7aad880711d368a07333c307 create mode 100644 tests/resources/attr/.gitted/objects/fb/5067b1aef3ac1ada4b379dbcb7d17255df7d78 create mode 100644 tests/resources/attr/.gitted/objects/fe/773770c5a6cc7185580c9204b1ff18a33ff3fc create mode 100644 tests/resources/attr/.gitted/objects/ff/69f8639ce2e6010b3f33a74160aad98b48da2b create mode 100644 tests/resources/attr/.gitted/refs/heads/master create mode 100644 tests/resources/attr/attr0 create mode 100644 tests/resources/attr/attr1 create mode 100644 tests/resources/attr/attr2 create mode 100644 tests/resources/attr/attr3 create mode 100644 tests/resources/attr/binfile create mode 100644 tests/resources/attr/dir/file create mode 100644 tests/resources/attr/file create mode 100644 tests/resources/attr/gitattributes create mode 100644 tests/resources/attr/gitignore create mode 100644 tests/resources/attr/ign create mode 100644 tests/resources/attr/macro_bad create mode 100644 tests/resources/attr/macro_test create mode 100644 tests/resources/attr/root_test1 create mode 100644 tests/resources/attr/root_test2 create mode 100644 tests/resources/attr/root_test3 create mode 100644 tests/resources/attr/root_test4.txt create mode 100644 tests/resources/attr/sub/.gitattributes create mode 100644 tests/resources/attr/sub/abc create mode 100644 tests/resources/attr/sub/dir/file create mode 100644 tests/resources/attr/sub/file create mode 100644 tests/resources/attr/sub/ign/file create mode 100644 tests/resources/attr/sub/ign/sub/file create mode 100644 tests/resources/attr/sub/sub/.gitattributes create mode 100644 tests/resources/attr/sub/sub/dir create mode 100644 tests/resources/attr/sub/sub/file create mode 100644 tests/resources/attr/sub/sub/subsub.txt create mode 100644 tests/resources/attr/sub/subdir_test1 create mode 100644 tests/resources/attr/sub/subdir_test2.txt create mode 100644 tests/resources/attr_index/.gitted/HEAD create mode 100644 tests/resources/attr_index/.gitted/config create mode 100644 tests/resources/attr_index/.gitted/description create mode 100644 tests/resources/attr_index/.gitted/index create mode 100644 tests/resources/attr_index/.gitted/info/exclude create mode 100644 tests/resources/attr_index/.gitted/info/refs create mode 100644 tests/resources/attr_index/.gitted/logs/HEAD create mode 100644 tests/resources/attr_index/.gitted/logs/refs/heads/master create mode 100644 tests/resources/attr_index/.gitted/objects/38/12cfef36615db1788d4e63f90028007e17a348 create mode 100644 tests/resources/attr_index/.gitted/objects/59/d942b8be2784bc96db9b22202c10815c9a077b create mode 100644 tests/resources/attr_index/.gitted/objects/cd/f17ea3fe625ef812f4dce7f423f4f299287505 create mode 100644 tests/resources/attr_index/.gitted/objects/f7/2502ddd01412bb20796ff812af56fd53b82b52 create mode 100644 tests/resources/attr_index/.gitted/objects/info/packs create mode 100644 tests/resources/attr_index/.gitted/objects/pack/pack-4e6438607204ce78827e3885594b2c0bb4f13895.idx create mode 100644 tests/resources/attr_index/.gitted/objects/pack/pack-4e6438607204ce78827e3885594b2c0bb4f13895.pack create mode 100644 tests/resources/attr_index/.gitted/packed-refs create mode 100644 tests/resources/attr_index/.gitted/refs/heads/master create mode 100644 tests/resources/attr_index/README.md create mode 100644 tests/resources/attr_index/README.txt create mode 100644 tests/resources/attr_index/gitattributes create mode 100644 tests/resources/attr_index/sub/sub/.gitattributes create mode 100644 tests/resources/attr_index/sub/sub/README.md create mode 100644 tests/resources/attr_index/sub/sub/README.txt create mode 100644 tests/resources/bad_tag.git/HEAD create mode 100644 tests/resources/bad_tag.git/config create mode 100644 tests/resources/bad_tag.git/objects/pack/pack-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.idx create mode 100644 tests/resources/bad_tag.git/objects/pack/pack-7a28f4e000a17f49a41d7a79fc2f762a8a7d9164.pack create mode 100644 tests/resources/bad_tag.git/packed-refs create mode 100644 tests/resources/bad_tag.git/refs/dummy-marker.txt create mode 100644 tests/resources/big.index create mode 100644 tests/resources/binaryunicode/.gitted/HEAD create mode 100644 tests/resources/binaryunicode/.gitted/config create mode 100644 tests/resources/binaryunicode/.gitted/description create mode 100644 tests/resources/binaryunicode/.gitted/index create mode 100644 tests/resources/binaryunicode/.gitted/info/exclude create mode 100644 tests/resources/binaryunicode/.gitted/info/refs create mode 100644 tests/resources/binaryunicode/.gitted/objects/info/packs create mode 100644 tests/resources/binaryunicode/.gitted/objects/pack/pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.idx create mode 100644 tests/resources/binaryunicode/.gitted/objects/pack/pack-c5bfca875b4995d7aba6e5abf36241f3c397327d.pack create mode 100644 tests/resources/binaryunicode/.gitted/refs/heads/branch1 create mode 100644 tests/resources/binaryunicode/.gitted/refs/heads/branch2 create mode 100644 tests/resources/binaryunicode/.gitted/refs/heads/master create mode 100644 tests/resources/binaryunicode/file.txt create mode 100644 tests/resources/blametest.git/HEAD create mode 100644 tests/resources/blametest.git/config create mode 100644 tests/resources/blametest.git/description create mode 100644 tests/resources/blametest.git/objects/0c/bab4d45fd61e55a1c9697f9f9cb07a12e15448 create mode 100644 tests/resources/blametest.git/objects/1a/ac69ae5d96461afc4d81d0066cb12f5b05a35b create mode 100644 tests/resources/blametest.git/objects/1b/5f0775af166331c854bd8d1bca3450eaf2532a create mode 100644 tests/resources/blametest.git/objects/48/2f2c370e35c2c314fc1f96db2beb33f955a26a create mode 100644 tests/resources/blametest.git/objects/63/d671eb32d250e4a83766ebbc60e818c1e1e93a create mode 100644 tests/resources/blametest.git/objects/63/eb57322e363e18d460da5ea8284f3cd2340b36 create mode 100644 tests/resources/blametest.git/objects/8b/137891791fe96927ad78e64b0aad7bded08bdc create mode 100644 tests/resources/blametest.git/objects/96/679d59cf9f74d69b3c920f258559b5e8c9a18a create mode 100644 tests/resources/blametest.git/objects/98/89d6e5557761aa8e3607e80c874a6dc51ada7c create mode 100644 tests/resources/blametest.git/objects/aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 create mode 100644 tests/resources/blametest.git/objects/b1/76dfc3a4dc8734e4c579f77236a9c8d0a965d2 create mode 100644 tests/resources/blametest.git/objects/b9/0bb887b7c03750ae6b352ffe76ab9d2e86ee7d create mode 100644 tests/resources/blametest.git/objects/b9/9f7ac0b88909253d829554c14af488c3b0f3a5 create mode 100644 tests/resources/blametest.git/objects/bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 create mode 100644 tests/resources/blametest.git/objects/cf/e0e1e1e3ba18f149fd47f5e1aef6016b2260c3 create mode 100644 tests/resources/blametest.git/objects/d0/67729932057cdb7527a833d6799c4ddc520640 create mode 100644 tests/resources/blametest.git/objects/da/237394e6132d20d30f175b9b73c8638fddddda create mode 100644 tests/resources/blametest.git/objects/e5/b41c1ea533f87388ab69b13baf0b5a562d6243 create mode 100644 tests/resources/blametest.git/objects/ef/32df4d259143933715c74951f932d9892364d1 create mode 100644 tests/resources/blametest.git/refs/heads/master create mode 100644 tests/resources/config/.gitconfig create mode 100644 tests/resources/config/config-include create mode 100644 tests/resources/config/config-included create mode 100644 tests/resources/config/config0 create mode 100644 tests/resources/config/config1 create mode 100644 tests/resources/config/config10 create mode 100644 tests/resources/config/config11 create mode 100644 tests/resources/config/config12 create mode 100644 tests/resources/config/config13 create mode 100644 tests/resources/config/config14 create mode 100644 tests/resources/config/config15 create mode 100644 tests/resources/config/config16 create mode 100644 tests/resources/config/config17 create mode 100644 tests/resources/config/config18 create mode 100644 tests/resources/config/config19 create mode 100644 tests/resources/config/config2 create mode 100644 tests/resources/config/config20 create mode 100644 tests/resources/config/config3 create mode 100644 tests/resources/config/config4 create mode 100644 tests/resources/config/config5 create mode 100644 tests/resources/config/config6 create mode 100644 tests/resources/config/config7 create mode 100644 tests/resources/config/config8 create mode 100644 tests/resources/config/config9 create mode 100644 tests/resources/crlf/.gitted/HEAD create mode 100644 tests/resources/crlf/.gitted/config create mode 100644 tests/resources/crlf/.gitted/objects/04/de00b358f13389948756732158eaaaefa1448c create mode 100644 tests/resources/crlf/.gitted/objects/0a/a76e474d259bd7c13eb726a1396c381db55c88 create mode 100644 tests/resources/crlf/.gitted/objects/0d/06894e14df22e066763ae906e0ed3eb79c205f create mode 100644 tests/resources/crlf/.gitted/objects/0f/f5a53f19bfd2b5eea1ba550295c47515678987 create mode 100644 tests/resources/crlf/.gitted/objects/12/faf3c1ea55f572473cec9052fca468c3584ccb create mode 100644 tests/resources/crlf/.gitted/objects/38/1cfe630df902bc29271a202d3277981180e4a6 create mode 100644 tests/resources/crlf/.gitted/objects/79/9770d1cff46753a57db7a066159b5610da6e3a create mode 100644 tests/resources/crlf/.gitted/objects/7c/ce67e58173e2b01f7db124ceaabe3183d19c49 create mode 100644 tests/resources/crlf/.gitted/objects/a9/a2e8913c1dbe2812fac5e6b4e0a4bd5d0d5966 create mode 100644 tests/resources/crlf/.gitted/objects/ba/aa042ab2976f8264e467988e6112ee518ec62e create mode 100644 tests/resources/crlf/.gitted/objects/dc/88e3b917de821e25962bea7ec1f55c4ce2112c create mode 100644 tests/resources/crlf/.gitted/objects/ea/030d3c6cec212069eca698cabaa5b4550f1511 create mode 100644 tests/resources/crlf/.gitted/objects/fe/085d9ace90cc675b87df15e1aeed0c3a31407f create mode 100644 tests/resources/crlf/.gitted/refs/heads/master create mode 100644 tests/resources/crlf/.gitted/refs/heads/utf8 create mode 100644 tests/resources/deprecated-mode.git/HEAD create mode 100644 tests/resources/deprecated-mode.git/config create mode 100644 tests/resources/deprecated-mode.git/description create mode 100644 tests/resources/deprecated-mode.git/index create mode 100644 tests/resources/deprecated-mode.git/info/exclude create mode 100644 tests/resources/deprecated-mode.git/objects/06/262edc257418e9987caf999f9a7a3e1547adff create mode 100644 tests/resources/deprecated-mode.git/objects/08/10fb7818088ff5ac41ee49199b51473b1bd6c7 create mode 100644 tests/resources/deprecated-mode.git/objects/1b/05fdaa881ee45b48cbaa5e9b037d667a47745e create mode 100644 tests/resources/deprecated-mode.git/objects/3d/0970ec547fc41ef8a5882dde99c6adce65b021 create mode 100644 tests/resources/deprecated-mode.git/refs/heads/master create mode 100644 tests/resources/diff/.gitted/HEAD create mode 100644 tests/resources/diff/.gitted/config create mode 100644 tests/resources/diff/.gitted/description create mode 100644 tests/resources/diff/.gitted/index create mode 100644 tests/resources/diff/.gitted/info/exclude create mode 100644 tests/resources/diff/.gitted/logs/HEAD create mode 100644 tests/resources/diff/.gitted/logs/refs/heads/master create mode 100644 tests/resources/diff/.gitted/objects/29/ab7053bb4dde0298e03e2c179e890b7dd465a7 create mode 100644 tests/resources/diff/.gitted/objects/3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847 create mode 100644 tests/resources/diff/.gitted/objects/54/6c735f16a3b44d9784075c2c0dab2ac9bf1989 create mode 100644 tests/resources/diff/.gitted/objects/7a/9e0b02e63179929fed24f0a3e0f19168114d10 create mode 100644 tests/resources/diff/.gitted/objects/7b/808f723a8ca90df319682c221187235af76693 create mode 100644 tests/resources/diff/.gitted/objects/88/789109439c1e1c3cd45224001edee5304ed53c create mode 100644 tests/resources/diff/.gitted/objects/cb/8294e696339863df760b2ff5d1e275bee72455 create mode 100644 tests/resources/diff/.gitted/objects/d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69 create mode 100644 tests/resources/diff/.gitted/refs/heads/master create mode 100644 tests/resources/diff/another.txt create mode 100644 tests/resources/diff/readme.txt create mode 100644 tests/resources/duplicate.git/COMMIT_EDITMSG create mode 100644 tests/resources/duplicate.git/HEAD create mode 100644 tests/resources/duplicate.git/config create mode 100644 tests/resources/duplicate.git/description create mode 100644 tests/resources/duplicate.git/index create mode 100644 tests/resources/duplicate.git/info/exclude create mode 100644 tests/resources/duplicate.git/info/refs create mode 100644 tests/resources/duplicate.git/logs/HEAD create mode 100644 tests/resources/duplicate.git/logs/refs/heads/master create mode 100644 tests/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea create mode 100644 tests/resources/duplicate.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a create mode 100644 tests/resources/duplicate.git/objects/info/packs create mode 100644 tests/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx create mode 100644 tests/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack create mode 100644 tests/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx create mode 100644 tests/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack create mode 100644 tests/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.idx create mode 100644 tests/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.pack create mode 100644 tests/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx create mode 100644 tests/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack create mode 100644 tests/resources/duplicate.git/packed-refs create mode 100644 tests/resources/duplicate.git/refs/heads/dummy-marker.txt create mode 100644 tests/resources/empty_bare.git/HEAD create mode 100644 tests/resources/empty_bare.git/config create mode 100644 tests/resources/empty_bare.git/description create mode 100644 tests/resources/empty_bare.git/info/exclude create mode 100644 tests/resources/empty_bare.git/objects/info/dummy-marker.txt create mode 100644 tests/resources/empty_bare.git/objects/pack/dummy-marker.txt create mode 100644 tests/resources/empty_bare.git/refs/heads/dummy-marker.txt create mode 100644 tests/resources/empty_bare.git/refs/tags/dummy-marker.txt create mode 100644 tests/resources/empty_standard_repo/.gitted/HEAD create mode 100644 tests/resources/empty_standard_repo/.gitted/config create mode 100644 tests/resources/empty_standard_repo/.gitted/description create mode 100644 tests/resources/empty_standard_repo/.gitted/info/exclude create mode 100644 tests/resources/empty_standard_repo/.gitted/objects/info/dummy-marker.txt create mode 100644 tests/resources/empty_standard_repo/.gitted/objects/pack/dummy-marker.txt create mode 100644 tests/resources/empty_standard_repo/.gitted/refs/heads/dummy-marker.txt create mode 100644 tests/resources/empty_standard_repo/.gitted/refs/tags/dummy-marker.txt create mode 100644 tests/resources/filemodes/.gitted/HEAD create mode 100644 tests/resources/filemodes/.gitted/config create mode 100644 tests/resources/filemodes/.gitted/description create mode 100644 tests/resources/filemodes/.gitted/index create mode 100644 tests/resources/filemodes/.gitted/info/exclude create mode 100644 tests/resources/filemodes/.gitted/logs/HEAD create mode 100644 tests/resources/filemodes/.gitted/logs/refs/heads/master create mode 100644 tests/resources/filemodes/.gitted/objects/99/62c8453ba6f0cf8dac7c5dcc2fa2897fa9964a create mode 100644 tests/resources/filemodes/.gitted/objects/a5/c5dd0fc6c313159a69b1d19d7f61a9f978e8f1 create mode 100644 tests/resources/filemodes/.gitted/objects/e7/48d196331bcb20267eaaee4ff3326cb73b8182 create mode 100644 tests/resources/filemodes/.gitted/refs/heads/master create mode 100644 tests/resources/filemodes/exec_off create mode 100755 tests/resources/filemodes/exec_off2on_staged create mode 100755 tests/resources/filemodes/exec_off2on_workdir create mode 100644 tests/resources/filemodes/exec_off_untracked create mode 100755 tests/resources/filemodes/exec_on create mode 100644 tests/resources/filemodes/exec_on2off_staged create mode 100644 tests/resources/filemodes/exec_on2off_workdir create mode 100755 tests/resources/filemodes/exec_on_untracked create mode 100644 tests/resources/gitgit.index create mode 100644 tests/resources/icase/.gitted/HEAD create mode 100644 tests/resources/icase/.gitted/config create mode 100644 tests/resources/icase/.gitted/description create mode 100644 tests/resources/icase/.gitted/index create mode 100644 tests/resources/icase/.gitted/info/exclude create mode 100644 tests/resources/icase/.gitted/logs/HEAD create mode 100644 tests/resources/icase/.gitted/logs/refs/heads/master create mode 100644 tests/resources/icase/.gitted/objects/3e/257c57f136a1cb8f2b8e9a2e5bc8ec0258bdce create mode 100644 tests/resources/icase/.gitted/objects/4d/d6027d083575c7431396dc2a3174afeb393c93 create mode 100644 tests/resources/icase/.gitted/objects/62/e0af52c199ec731fe4ad230041cd3286192d49 create mode 100644 tests/resources/icase/.gitted/objects/76/d6e1d231b1085fcce151427e9899335de74be6 create mode 100644 tests/resources/icase/.gitted/objects/d4/4e18fb93b7107b5cd1b95d601591d77869a1b6 create mode 100644 tests/resources/icase/.gitted/refs/heads/master create mode 100644 tests/resources/icase/B create mode 100644 tests/resources/icase/D create mode 100644 tests/resources/icase/F create mode 100644 tests/resources/icase/H create mode 100644 tests/resources/icase/J create mode 100644 tests/resources/icase/L/1 create mode 100644 tests/resources/icase/L/B create mode 100644 tests/resources/icase/L/D create mode 100644 tests/resources/icase/L/a create mode 100644 tests/resources/icase/L/c create mode 100644 tests/resources/icase/a create mode 100644 tests/resources/icase/c create mode 100644 tests/resources/icase/e create mode 100644 tests/resources/icase/g create mode 100644 tests/resources/icase/i create mode 100644 tests/resources/icase/k/1 create mode 100644 tests/resources/icase/k/B create mode 100644 tests/resources/icase/k/D create mode 100644 tests/resources/icase/k/a create mode 100644 tests/resources/icase/k/c create mode 100644 tests/resources/issue_1397/.gitted/HEAD create mode 100644 tests/resources/issue_1397/.gitted/config create mode 100644 tests/resources/issue_1397/.gitted/index create mode 100644 tests/resources/issue_1397/.gitted/objects/7f/483a738f867e5b21c8f377d70311f011eb48b5 create mode 100644 tests/resources/issue_1397/.gitted/objects/83/12e0889a9cbab77c732b6bc39b51a683e3a318 create mode 100644 tests/resources/issue_1397/.gitted/objects/8a/7ef047fc933edb62e84e7977b0612ec3f6f283 create mode 100644 tests/resources/issue_1397/.gitted/objects/8e/8f80088a9274fd23584992f587083ca1bcbbac create mode 100644 tests/resources/issue_1397/.gitted/objects/f2/c62dea0372a0578e053697d5c1ba1ac05e774a create mode 100644 tests/resources/issue_1397/.gitted/objects/ff/3578d64d199d5b48d92bbb569e0a273e411741 create mode 100644 tests/resources/issue_1397/.gitted/refs/heads/master create mode 100644 tests/resources/issue_1397/crlf_file.txt create mode 100644 tests/resources/issue_1397/some_other_crlf_file.txt create mode 100644 tests/resources/issue_592/.gitted/COMMIT_EDITMSG create mode 100644 tests/resources/issue_592/.gitted/HEAD create mode 100644 tests/resources/issue_592/.gitted/config create mode 100644 tests/resources/issue_592/.gitted/index create mode 100644 tests/resources/issue_592/.gitted/info/exclude create mode 100644 tests/resources/issue_592/.gitted/logs/HEAD create mode 100644 tests/resources/issue_592/.gitted/logs/refs/heads/master create mode 100644 tests/resources/issue_592/.gitted/objects/06/07ee9d4ccce8e4c4fa13c2c7d727e7faba4e0e create mode 100644 tests/resources/issue_592/.gitted/objects/49/363a72a90d9424240258cd3759f23788ecf1d8 create mode 100644 tests/resources/issue_592/.gitted/objects/4d/383e87f0371ba8fa353f3912db6862b2625e85 create mode 100644 tests/resources/issue_592/.gitted/objects/71/44be264b61825fbff68046fe999bdfe96a1792 create mode 100644 tests/resources/issue_592/.gitted/objects/be/de83ee10b5b3f00239660b00acec2d55fd0b84 create mode 100644 tests/resources/issue_592/.gitted/objects/e3/8fcc7a6060f5eb5b876e836b52ae4769363f21 create mode 100644 tests/resources/issue_592/.gitted/objects/f1/adef63cb08891a0942b76fc4b9c50c6c494bc7 create mode 100644 tests/resources/issue_592/.gitted/refs/heads/master create mode 100644 tests/resources/issue_592/a.txt create mode 100644 tests/resources/issue_592/c/a.txt create mode 100644 tests/resources/issue_592/l.txt create mode 100644 tests/resources/issue_592/t/a.txt create mode 100644 tests/resources/issue_592/t/b.txt create mode 100644 tests/resources/issue_592b/.gitted/HEAD create mode 100644 tests/resources/issue_592b/.gitted/config create mode 100644 tests/resources/issue_592b/.gitted/description create mode 100644 tests/resources/issue_592b/.gitted/index create mode 100644 tests/resources/issue_592b/.gitted/info/exclude create mode 100644 tests/resources/issue_592b/.gitted/logs/HEAD create mode 100644 tests/resources/issue_592b/.gitted/logs/refs/heads/master create mode 100644 tests/resources/issue_592b/.gitted/objects/3f/bf1852f72fd268e36457b13a18cdd9a4c9ea35 create mode 100644 tests/resources/issue_592b/.gitted/objects/6f/a891d3e578c83e1c03bdb9e0fdd8e6e934157f create mode 100644 tests/resources/issue_592b/.gitted/objects/80/07d41d5794e6ce4d4d2c97e370d5a9aa6d5213 create mode 100644 tests/resources/issue_592b/.gitted/objects/a6/5fb6583a7c425284142f285bc359a2d6565513 create mode 100644 tests/resources/issue_592b/.gitted/objects/ae/be7a55922c7097ef91ca3a7bc327a901d87c2c create mode 100644 tests/resources/issue_592b/.gitted/objects/b3/44b055867fcdc1f01eaa75056a43e868eb4fbc create mode 100644 tests/resources/issue_592b/.gitted/objects/f7/d75fbfad8b1d2e307ced287ea78aad403cdce3 create mode 100644 tests/resources/issue_592b/.gitted/refs/heads/master create mode 100644 tests/resources/issue_592b/gitignore create mode 100644 tests/resources/issue_592b/ignored/contained/ignored3.txt create mode 100644 tests/resources/issue_592b/ignored/contained/tracked3.txt create mode 100644 tests/resources/issue_592b/ignored/ignored2.txt create mode 100644 tests/resources/issue_592b/ignored/tracked2.txt create mode 100644 tests/resources/issue_592b/ignored1.txt create mode 100644 tests/resources/issue_592b/tracked1.txt create mode 100644 tests/resources/merge-resolve/.gitted/COMMIT_EDITMSG create mode 100644 tests/resources/merge-resolve/.gitted/HEAD create mode 100644 tests/resources/merge-resolve/.gitted/ORIG_HEAD create mode 100644 tests/resources/merge-resolve/.gitted/config create mode 100644 tests/resources/merge-resolve/.gitted/description create mode 100644 tests/resources/merge-resolve/.gitted/index create mode 100644 tests/resources/merge-resolve/.gitted/logs/HEAD create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/df_ancestor create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/df_side1 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/df_side2 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/ff_branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/master create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/octo1 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/octo2 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/octo3 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/octo4 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/octo5 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/octo6 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/renames1 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/renames2 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9 create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9-branch create mode 100644 tests/resources/merge-resolve/.gitted/logs/refs/heads/unrelated create mode 100644 tests/resources/merge-resolve/.gitted/objects/00/5b6fcc8fec71d2550bef8462d169b3c26aa14b create mode 100644 tests/resources/merge-resolve/.gitted/objects/00/9b9cab6fdac02915a88ecd078b7a792ed802d8 create mode 100644 tests/resources/merge-resolve/.gitted/objects/00/c7d33f1ffa79d19c2272b370fcaeaadba49c08 create mode 100644 tests/resources/merge-resolve/.gitted/objects/01/f149e1b8f84bd8896aaff6d6b22af88459ded0 create mode 100644 tests/resources/merge-resolve/.gitted/objects/02/04a84f822acbf6386b36d33f1f6bc68bbbf858 create mode 100644 tests/resources/merge-resolve/.gitted/objects/02/251f990ca8e92e7ae61d3426163fa821c64001 create mode 100644 tests/resources/merge-resolve/.gitted/objects/03/21415405cb906c46869919af56d51dbbe5e85c create mode 100644 tests/resources/merge-resolve/.gitted/objects/03/2ebc5ab85d9553bb187d3cd40875ff23a63ed0 create mode 100644 tests/resources/merge-resolve/.gitted/objects/03/b87706555accbf874ccd410dbda01e8e70a67f create mode 100644 tests/resources/merge-resolve/.gitted/objects/03/dad1005e5d06d418f50b12e0bcd48ff2306a03 create mode 100644 tests/resources/merge-resolve/.gitted/objects/05/1ffd7901a442faf56b226161649074f15c7c47 create mode 100644 tests/resources/merge-resolve/.gitted/objects/05/8541fc37114bfc1dddf6bd6bffc7fae5c2e6fe create mode 100644 tests/resources/merge-resolve/.gitted/objects/05/f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c create mode 100644 tests/resources/merge-resolve/.gitted/objects/07/a759da919f737221791d542f176ab49c88837f create mode 100644 tests/resources/merge-resolve/.gitted/objects/07/c514b04698e068892b31c8d352b85813b99c6e create mode 100644 tests/resources/merge-resolve/.gitted/objects/09/055301463b7f2f8ee5d368f8ed5c0a40ad8515 create mode 100644 tests/resources/merge-resolve/.gitted/objects/09/17bb159596aea4d295f4857da77e8f96b3c7dc create mode 100644 tests/resources/merge-resolve/.gitted/objects/09/2ce8682d7f3a2a3a769a6daca58950168ba5c4 create mode 100644 tests/resources/merge-resolve/.gitted/objects/09/3bebf072dd4bbba88833667d6ffe454df199e1 create mode 100644 tests/resources/merge-resolve/.gitted/objects/09/768bed22680cdb0859683fa9677ccc8d5a25c1 create mode 100644 tests/resources/merge-resolve/.gitted/objects/0a/75d9aac1dc84fb5aa51f7325c0ab53242ddef7 create mode 100644 tests/resources/merge-resolve/.gitted/objects/0c/fd6c54ef6532d862408f562309dc9c74a401e8 create mode 100644 tests/resources/merge-resolve/.gitted/objects/0d/52e3a556e189ba0948ae56780918011c1b167d create mode 100644 tests/resources/merge-resolve/.gitted/objects/0d/872f8e871a30208305978ecbf9e66d864f1638 create mode 100644 tests/resources/merge-resolve/.gitted/objects/0e/c5f433959cd46177f745903353efb5be08d151 create mode 100644 tests/resources/merge-resolve/.gitted/objects/11/deab00b2d3a6f5a3073988ac050c2d7b6655e2 create mode 100644 tests/resources/merge-resolve/.gitted/objects/11/f4f3c08b737f5fd896cbefa1425ee63b21b2fa create mode 100644 tests/resources/merge-resolve/.gitted/objects/13/d1be4ea52a6ced1d7a1d832f0ee3c399348e5e create mode 100644 tests/resources/merge-resolve/.gitted/objects/14/39088f509b79b1535b64193137d3ce4b240734 create mode 100644 tests/resources/merge-resolve/.gitted/objects/15/8dc7bedb202f5b26502bf3574faa7f4238d56c create mode 100644 tests/resources/merge-resolve/.gitted/objects/16/f825815cfd20a07a75c71554e82d8eede0b061 create mode 100644 tests/resources/merge-resolve/.gitted/objects/17/8940b450f238a56c0d75b7955cb57b38191982 create mode 100644 tests/resources/merge-resolve/.gitted/objects/18/3310e30fb1499af8c619108ffea4d300b5e778 create mode 100644 tests/resources/merge-resolve/.gitted/objects/18/cb316b1cefa0f8a6946f0e201a8e1a6f845ab9 create mode 100644 tests/resources/merge-resolve/.gitted/objects/19/b7ac485269b672a101060894de3ba9c2a24dd1 create mode 100644 tests/resources/merge-resolve/.gitted/objects/1a/010b1c0f081b2e8901d55307a15c29ff30af0e create mode 100644 tests/resources/merge-resolve/.gitted/objects/1c/ff9ec6a47a537380dedfdd17c9e76d74259a2b create mode 100644 tests/resources/merge-resolve/.gitted/objects/1e/4ff029aee68d0d69ef9eb6efa6cbf1ec732f99 create mode 100644 tests/resources/merge-resolve/.gitted/objects/1f/81433e3161efbf250576c58fede7f6b836f3d3 create mode 100644 tests/resources/merge-resolve/.gitted/objects/20/91d94c8bd3eb0835dc5220de5e8bb310fa1513 create mode 100644 tests/resources/merge-resolve/.gitted/objects/21/671e290278286fb2ce4c63d01699b67adce331 create mode 100644 tests/resources/merge-resolve/.gitted/objects/22/7792b52aaa0b238bea00ec7e509b02623f168c create mode 100644 tests/resources/merge-resolve/.gitted/objects/23/3c0919c998ed110a4b6ff36f353aec8b713487 create mode 100644 tests/resources/merge-resolve/.gitted/objects/23/92a2dacc9efb562b8635d6579fb458751c7c5b create mode 100644 tests/resources/merge-resolve/.gitted/objects/24/1a1005cd9b980732741b74385b891142bcba28 create mode 100644 tests/resources/merge-resolve/.gitted/objects/24/2591eb280ee9eeb2ce63524b9a8b9bc4cb515d create mode 100644 tests/resources/merge-resolve/.gitted/objects/24/90b9f1a079420870027deefb49f51d6656cf74 create mode 100644 tests/resources/merge-resolve/.gitted/objects/25/9d08ca43af9200e9ea9a098e44a5a350ebd9b3 create mode 100644 tests/resources/merge-resolve/.gitted/objects/25/c40b7660c08c8fb581f770312f41b9b03119d1 create mode 100644 tests/resources/merge-resolve/.gitted/objects/26/153a3ff3649b6c2bb652d3f06878c6e0a172f9 create mode 100644 tests/resources/merge-resolve/.gitted/objects/27/133da702ba3c60af2a01e96c2555ff4045d692 create mode 100644 tests/resources/merge-resolve/.gitted/objects/2b/0de5dc27505dcdd83a75c8bf1fcd9462cd7add create mode 100644 tests/resources/merge-resolve/.gitted/objects/2b/5f1f181ee3b58ea751f5dd5d8f9b445520a136 create mode 100644 tests/resources/merge-resolve/.gitted/objects/2b/d0a343aeef7a2cf0d158478966a6e587ff3863 create mode 100644 tests/resources/merge-resolve/.gitted/objects/2d/a538570bc1e5b2c3e855bf702f35248ad0735f create mode 100644 tests/resources/merge-resolve/.gitted/objects/2f/2e37b7ebbae467978610896ca3aafcdad2ee67 create mode 100644 tests/resources/merge-resolve/.gitted/objects/2f/4024ce528d36d8670c289cce5a7963e625bb0c create mode 100644 tests/resources/merge-resolve/.gitted/objects/2f/56120107d680129a5d9791b521cb1e73a2ed31 create mode 100644 tests/resources/merge-resolve/.gitted/objects/2f/598248eeccfc27e5ca44d9d96383f6dfea7b16 create mode 100644 tests/resources/merge-resolve/.gitted/objects/31/68dca1a561889b045a6441909f4c56145e666d create mode 100644 tests/resources/merge-resolve/.gitted/objects/31/d5472536041a83d986829240bbbdc897c6f8a6 create mode 100644 tests/resources/merge-resolve/.gitted/objects/32/21dd512b7e2dc4b5bd03046df6c81b2ab2070b create mode 100644 tests/resources/merge-resolve/.gitted/objects/33/46d64325b39e5323733492cd55f808994a2475 create mode 100644 tests/resources/merge-resolve/.gitted/objects/33/d500f588fbbe65901d82b4e6b008e549064be0 create mode 100644 tests/resources/merge-resolve/.gitted/objects/34/bfafff88eaf118402b44e6f3e2dbbf1a582b05 create mode 100644 tests/resources/merge-resolve/.gitted/objects/35/0c6eb3010efc403a6bed682332635314e9ed58 create mode 100644 tests/resources/merge-resolve/.gitted/objects/35/411bfb77cd2cc431f3a03a2b4976ed94b5d241 create mode 100644 tests/resources/merge-resolve/.gitted/objects/35/4704d3613ad4228e4786fc76656b11e98236c4 create mode 100644 tests/resources/merge-resolve/.gitted/objects/35/632e43612c06a3ea924bfbacd48333da874c29 create mode 100644 tests/resources/merge-resolve/.gitted/objects/35/75826c96a975031d2c14368529cc5c4353a8fd create mode 100644 tests/resources/merge-resolve/.gitted/objects/36/219b49367146cb2e6a1555b5a9ebd4d0328495 create mode 100644 tests/resources/merge-resolve/.gitted/objects/36/4bbe4ce80c7bd31e6307dce77d46e3e1759fb3 create mode 100644 tests/resources/merge-resolve/.gitted/objects/37/48859b001c6e627e712a07951aee40afd19b41 create mode 100644 tests/resources/merge-resolve/.gitted/objects/38/5c8a0f26ddf79e9041e15e17dc352ed2c4cced create mode 100644 tests/resources/merge-resolve/.gitted/objects/3b/47b031b3e55ae11e14a05260b1c3ffd6838d55 create mode 100644 tests/resources/merge-resolve/.gitted/objects/3b/bf0bf59b20df5d5fc58b9fc1dc07be637c301f create mode 100644 tests/resources/merge-resolve/.gitted/objects/3e/f4d30382ca33fdeba9fda895a99e0891ba37aa create mode 100644 tests/resources/merge-resolve/.gitted/objects/3e/f9bfe82f9635518ae89152322f3b46fd4ba25b create mode 100644 tests/resources/merge-resolve/.gitted/objects/40/2784a46a4a3982294231594cbeb431f506d22c create mode 100644 tests/resources/merge-resolve/.gitted/objects/41/2b32fb66137366147f1801ecc962452757d48a create mode 100644 tests/resources/merge-resolve/.gitted/objects/43/aafd43bea779ec74317dc361f45ae3f532a505 create mode 100644 tests/resources/merge-resolve/.gitted/objects/43/c338656342227a3a3cd3aa85cbf784061f5425 create mode 100644 tests/resources/merge-resolve/.gitted/objects/45/299c1ca5e07bba1fd90843056fb559f96b1f5a create mode 100644 tests/resources/merge-resolve/.gitted/objects/46/6daf8552b891e5c22bc58c9d7fc1a2eb8f0289 create mode 100644 tests/resources/merge-resolve/.gitted/objects/47/6dbb3e207313d1d8aaa120c6ad204bf1295e53 create mode 100644 tests/resources/merge-resolve/.gitted/objects/47/8172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 create mode 100644 tests/resources/merge-resolve/.gitted/objects/49/130a28ef567af9a6a6104c38773fedfa5f9742 create mode 100644 tests/resources/merge-resolve/.gitted/objects/49/9df817155e4bdd3c6ee192a72c52f481818230 create mode 100644 tests/resources/merge-resolve/.gitted/objects/4a/9550ebcc97ce22b22f45af7b829bb030d003f5 create mode 100644 tests/resources/merge-resolve/.gitted/objects/4b/253da36a0ae8bfce63aeabd8c5b58429925594 create mode 100644 tests/resources/merge-resolve/.gitted/objects/4b/48deed3a433909bfd6b6ab3d4b91348b6af464 create mode 100644 tests/resources/merge-resolve/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 create mode 100644 tests/resources/merge-resolve/.gitted/objects/4c/9fac0707f8d4195037ae5a681aa48626491541 create mode 100644 tests/resources/merge-resolve/.gitted/objects/4c/a408a8c88655f7586a1b580be6fad138121e98 create mode 100644 tests/resources/merge-resolve/.gitted/objects/4e/0d9401aee78eb345a8685a859d37c8c3c0bbed create mode 100644 tests/resources/merge-resolve/.gitted/objects/4e/886e602529caa9ab11d71f86634bd1b6e0de10 create mode 100644 tests/resources/merge-resolve/.gitted/objects/4e/b04c9e79e88f6640d01ff5b25ca2a60764f216 create mode 100644 tests/resources/merge-resolve/.gitted/objects/4f/e93c0ec83eb6305cbace3dace88ecee1b63cb6 create mode 100644 tests/resources/merge-resolve/.gitted/objects/50/12fd565b1393bdfda1805d4ec38ce6619e1fd1 create mode 100644 tests/resources/merge-resolve/.gitted/objects/50/4f75ac95a71ef98051817618576a68505b92f9 create mode 100644 tests/resources/merge-resolve/.gitted/objects/50/84fc2a88b6bdba8db93bd3953a8f4fdb470238 create mode 100644 tests/resources/merge-resolve/.gitted/objects/50/ce7d7d01217679e26c55939eef119e0c93e272 create mode 100644 tests/resources/merge-resolve/.gitted/objects/51/95a1b480f66691b667f10a9e41e70115a78351 create mode 100644 tests/resources/merge-resolve/.gitted/objects/52/d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 create mode 100644 tests/resources/merge-resolve/.gitted/objects/53/825f41ac8d640612f9423a2f03a69f3d96809a create mode 100644 tests/resources/merge-resolve/.gitted/objects/54/269b3f6ec3d7d4ede24dd350dd5d605495c3ae create mode 100644 tests/resources/merge-resolve/.gitted/objects/54/59c89aa0026d543ce8343bd89871bce543f9c2 create mode 100644 tests/resources/merge-resolve/.gitted/objects/54/7607c690372fe81fab8e3bb44c530e129118fd create mode 100644 tests/resources/merge-resolve/.gitted/objects/55/b4e4687e7a0d9ca367016ed930f385d4022e6f create mode 100644 tests/resources/merge-resolve/.gitted/objects/56/6ab53c220a2eafc1212af1a024513230280ab9 create mode 100644 tests/resources/merge-resolve/.gitted/objects/56/a638b76b75e068590ac999c2f8621e7f3e264c create mode 100644 tests/resources/merge-resolve/.gitted/objects/57/079a46233ae2b6df62e9ade71c4948512abefb create mode 100644 tests/resources/merge-resolve/.gitted/objects/58/43febcb23480df0b5edb22a21c59c772bb8e29 create mode 100644 tests/resources/merge-resolve/.gitted/objects/58/e853f66699fd02629fd50bde08082bc005933a create mode 100644 tests/resources/merge-resolve/.gitted/objects/59/6803b523203a4851c824c07366906f8353f4ad create mode 100644 tests/resources/merge-resolve/.gitted/objects/5c/2411f8075f48a6b2fdb85ebc0d371747c4df15 create mode 100644 tests/resources/merge-resolve/.gitted/objects/5c/341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d create mode 100644 tests/resources/merge-resolve/.gitted/objects/5c/3b68a71fc4fa5d362fd3875e53137c6a5ab7a5 create mode 100644 tests/resources/merge-resolve/.gitted/objects/5d/c1018e90b19654bee986b7a0c268804d39659d create mode 100644 tests/resources/merge-resolve/.gitted/objects/5d/dd0fe66f990dc0e5cf9fec6d9b465240e9537f create mode 100644 tests/resources/merge-resolve/.gitted/objects/5e/b7bb6a146eb3c7fd3990b240a2308eceb1cf8d create mode 100644 tests/resources/merge-resolve/.gitted/objects/5f/bfbdc04b4eca46f54f4853a3c5a1dce28f5165 create mode 100644 tests/resources/merge-resolve/.gitted/objects/60/91fc2c036a382a69489e3f518ee5aae9a4e567 create mode 100644 tests/resources/merge-resolve/.gitted/objects/61/340eeed7340fa6a8792def9a5938bb5d4434bb create mode 100644 tests/resources/merge-resolve/.gitted/objects/61/78885b38fe96e825ac0f492c0a941f288b37f6 create mode 100644 tests/resources/merge-resolve/.gitted/objects/62/12c31dab5e482247d7977e4f0dd3601decf13b create mode 100644 tests/resources/merge-resolve/.gitted/objects/62/269111c3b02a9355badcb9da8678b1bf41787b create mode 100644 tests/resources/merge-resolve/.gitted/objects/62/c4f6533c9a3894191fdcb96a3be935ade63f1a create mode 100644 tests/resources/merge-resolve/.gitted/objects/63/247125386de9ec90a27ad36169307bf8a11a38 create mode 100644 tests/resources/merge-resolve/.gitted/objects/67/18a45909532d1fcf5600d0877f7fe7e78f0b86 create mode 100644 tests/resources/merge-resolve/.gitted/objects/68/c6c84b091926c7d90aa6a79b2bc3bb6adccd8e create mode 100644 tests/resources/merge-resolve/.gitted/objects/69/f570c57b24ea7c086e94c5e574964798321435 create mode 100644 tests/resources/merge-resolve/.gitted/objects/6a/e1a3967031a42cf955d9d5c2395211ac82f6cf create mode 100644 tests/resources/merge-resolve/.gitted/objects/6b/7e37be8ce0b897093f2878a9dcd8f396beda2c create mode 100644 tests/resources/merge-resolve/.gitted/objects/6c/06dcd163587c2cc18be44857e0b71116382aeb create mode 100644 tests/resources/merge-resolve/.gitted/objects/6f/32739c3724d1d5f855299309f388606f407468 create mode 100644 tests/resources/merge-resolve/.gitted/objects/6f/a33014764bf1120a454eb8437ae098238e409b create mode 100644 tests/resources/merge-resolve/.gitted/objects/6f/be9fb85c86d7d1435f728da418bdff52c640a9 create mode 100644 tests/resources/merge-resolve/.gitted/objects/71/17467b18605a660ebe5586df69e2311ed5609f create mode 100644 tests/resources/merge-resolve/.gitted/objects/71/2ebba6669ea847d9829e4f1059d6c830c8b531 create mode 100644 tests/resources/merge-resolve/.gitted/objects/71/add2d7b93d55bf3600f8a1582beceebbd050c8 create mode 100644 tests/resources/merge-resolve/.gitted/objects/72/ea499e108df5ff0a4a913e7655bbeeb1fb69f2 create mode 100644 tests/resources/merge-resolve/.gitted/objects/74/df13f0793afdaa972150bba976f7de8284914e create mode 100644 tests/resources/merge-resolve/.gitted/objects/75/a811bf6bc57694adb3fe604786f3a4efd1cd1b create mode 100644 tests/resources/merge-resolve/.gitted/objects/76/63fce0130db092936b137cabd693ec234eb060 create mode 100644 tests/resources/merge-resolve/.gitted/objects/76/ab0e2868197ec158ddd6c78d8a0d2fd73d38f9 create mode 100644 tests/resources/merge-resolve/.gitted/objects/7a/a3edf2bcfee22398e6b55295aa56366b7aaf76 create mode 100644 tests/resources/merge-resolve/.gitted/objects/7c/2c5228c9e90170d4a35e6558e47163daf092e5 create mode 100644 tests/resources/merge-resolve/.gitted/objects/7c/b63eed597130ba4abb87b3e544b85021905520 create mode 100644 tests/resources/merge-resolve/.gitted/objects/7e/2d058d5fedf8329db44db4fac610d6b1a89159 create mode 100644 tests/resources/merge-resolve/.gitted/objects/7f/7a2da58126226986d71c6ddfab4afba693280d create mode 100644 tests/resources/merge-resolve/.gitted/objects/80/a8fbb3abb1ba423d554e9630b8fc2e5698f86b create mode 100644 tests/resources/merge-resolve/.gitted/objects/81/87117062b750eed4f93fd7e899f17b52ce554d create mode 100644 tests/resources/merge-resolve/.gitted/objects/83/07d93a155903a5c49576583f0ce1f6ff897c0e create mode 100644 tests/resources/merge-resolve/.gitted/objects/83/824a8c6658768e2013905219cc8c64cc3d9a2e create mode 100644 tests/resources/merge-resolve/.gitted/objects/84/9619b03ae540acee4d1edec96b86993da6b497 create mode 100644 tests/resources/merge-resolve/.gitted/objects/84/de84f8f3a6d63e636ee9ad81f4b80512fa9bbe create mode 100644 tests/resources/merge-resolve/.gitted/objects/86/088dae8bade454995b21a1c88107b0e1accdab create mode 100644 tests/resources/merge-resolve/.gitted/objects/87/b4926260d77a3b851e71ecce06839bd650b231 create mode 100644 tests/resources/merge-resolve/.gitted/objects/88/e185910a15cd13bdf44854ad037f4842b03b29 create mode 100644 tests/resources/merge-resolve/.gitted/objects/8a/ad9d0ea334951da47b621a475b39cc6ed759bf create mode 100644 tests/resources/merge-resolve/.gitted/objects/8a/ae714f7d939309d7f132b30646d96743134a9f create mode 100644 tests/resources/merge-resolve/.gitted/objects/8b/095d8fd01594f4d14454d073e3ac57b9ce485f create mode 100644 tests/resources/merge-resolve/.gitted/objects/8b/5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a create mode 100644 tests/resources/merge-resolve/.gitted/objects/8b/fb012a6d809e499bd8d3e194a3929bc8995b93 create mode 100644 tests/resources/merge-resolve/.gitted/objects/8c/749d9968d4b10dcfb06c9f97d0e5d92d337071 create mode 100644 tests/resources/merge-resolve/.gitted/objects/8f/4433f8593ddd65b7dd43dd4564d841f4d9c8aa create mode 100644 tests/resources/merge-resolve/.gitted/objects/90/a336c7dacbe295159413559b0043b8bdc60d57 create mode 100644 tests/resources/merge-resolve/.gitted/objects/91/2b2d7819cf9c1029e414883857ed61d597a1a5 create mode 100644 tests/resources/merge-resolve/.gitted/objects/91/8bb3e09090a9995d48af9a2a6296d7e6088d1c create mode 100644 tests/resources/merge-resolve/.gitted/objects/92/7d4943cdbdc9a667db8e62cfd0a41870235c51 create mode 100644 tests/resources/merge-resolve/.gitted/objects/93/77fccdb210540b8c0520cc6e80eb632c20bd25 create mode 100644 tests/resources/merge-resolve/.gitted/objects/94/4f5dd1a867cab4c2bbcb896493435cae1dcc1a create mode 100644 tests/resources/merge-resolve/.gitted/objects/94/8ba6e701c1edab0c2d394fb7c5538334129793 create mode 100644 tests/resources/merge-resolve/.gitted/objects/95/646149ab6b6ba6edc83cff678582538b457b2b create mode 100644 tests/resources/merge-resolve/.gitted/objects/95/9de65e568274120fdf9e3af9f77b1550122149 create mode 100644 tests/resources/merge-resolve/.gitted/objects/96/8ca794a4597f7f6abbb2b8d940b4078a0f3fd4 create mode 100644 tests/resources/merge-resolve/.gitted/objects/97/7c696519c5a3004c5f1d15d60c89dbeb8f235f create mode 100644 tests/resources/merge-resolve/.gitted/objects/98/ba4205fcf31f5dd93c916d35fe3f3b3d0e6714 create mode 100644 tests/resources/merge-resolve/.gitted/objects/98/d52d07c0b0bbf2b46548f6aa521295c2cb55db create mode 100644 tests/resources/merge-resolve/.gitted/objects/99/b4f7e4f24470fa06b980bc21f1095c2a9425c0 create mode 100644 tests/resources/merge-resolve/.gitted/objects/9a/301fbe6fada7dcb74fcd7c20269b5c743459a7 create mode 100644 tests/resources/merge-resolve/.gitted/objects/9a/f731fa116d1eb9a6c0109562472cfee6f5a979 create mode 100644 tests/resources/merge-resolve/.gitted/objects/9c/0b6c34ef379a42d858f03fef38630f476b9102 create mode 100644 tests/resources/merge-resolve/.gitted/objects/9e/7f4359c469f309b6057febf4c6e80742cbed5b create mode 100644 tests/resources/merge-resolve/.gitted/objects/9e/fe7723802d4305142eee177e018fee1572c4f4 create mode 100644 tests/resources/merge-resolve/.gitted/objects/9f/74397a3397b3585faf09e9926b110d7f654254 create mode 100644 tests/resources/merge-resolve/.gitted/objects/a0/31a28ae70e33a641ce4b8a8f6317f1ab79dee4 create mode 100644 tests/resources/merge-resolve/.gitted/objects/a3/9a620dae5bc8b4e771cd4d251b7d080401a21e create mode 100644 tests/resources/merge-resolve/.gitted/objects/a3/fabece9eb8748da810e1e08266fef9b7136ad4 create mode 100644 tests/resources/merge-resolve/.gitted/objects/a4/1b1bb6d0be3c22fb654234c33b428e15c8cc27 create mode 100644 tests/resources/merge-resolve/.gitted/objects/a4/3150a738849c59376cf30bb2a68348a83c8f48 create mode 100644 tests/resources/merge-resolve/.gitted/objects/a5/563304ddf6caba25cb50323a2ea6f7dbfcadca create mode 100644 tests/resources/merge-resolve/.gitted/objects/a7/08b253bd507417ec42d1467a7fd2d7519c4956 create mode 100644 tests/resources/merge-resolve/.gitted/objects/a7/65fb87eb2f7a1920b73b2d5a057f8f8476a42b create mode 100644 tests/resources/merge-resolve/.gitted/objects/a7/7a56a49f8f3ae242e02717f18ebbc60c5cc543 create mode 100644 tests/resources/merge-resolve/.gitted/objects/a7/dbfcbfc1a60709cb80b5ca24539008456531d0 create mode 100644 tests/resources/merge-resolve/.gitted/objects/a8/02e06f1782a9645b9851bc7202cee74a8a4972 create mode 100644 tests/resources/merge-resolve/.gitted/objects/a8/87dd39ad3edd610fc9083dcb61e40ab50673d1 create mode 100644 tests/resources/merge-resolve/.gitted/objects/a9/0bc3fb6f15181972a2959a921429efbd81a473 create mode 100644 tests/resources/merge-resolve/.gitted/objects/ab/40af3cb8a3ed2e2843e96d9aa7871336b94573 create mode 100644 tests/resources/merge-resolve/.gitted/objects/ab/6c44a2e84492ad4b41bb6bac87353e9d02ac8b create mode 100644 tests/resources/merge-resolve/.gitted/objects/ab/929391ac42572f92110f3deeb4f0844a951e22 create mode 100644 tests/resources/merge-resolve/.gitted/objects/ac/4045f965119e6998f4340ed0f411decfb3ec05 create mode 100644 tests/resources/merge-resolve/.gitted/objects/ad/a14492498136771f69dd451866cabcb0e9ef9a create mode 100644 tests/resources/merge-resolve/.gitted/objects/ad/a55a45d14527dc3dfc714ea1c65d2e1e6fbe87 create mode 100644 tests/resources/merge-resolve/.gitted/objects/b2/d399ae15224e1d58066e3c8df70ce37de7a656 create mode 100644 tests/resources/merge-resolve/.gitted/objects/b4/2712cfe99a1a500b2a51fe984e0b8a7702ba11 create mode 100644 tests/resources/merge-resolve/.gitted/objects/b6/9fe837e4cecfd4c9a40cdca7c138468687df07 create mode 100644 tests/resources/merge-resolve/.gitted/objects/b6/f610aef53bd343e6c96227de874c66f00ee8e8 create mode 100644 tests/resources/merge-resolve/.gitted/objects/b7/a2576f9fc20024ac9ef17cb134acbd1ac73127 create mode 100644 tests/resources/merge-resolve/.gitted/objects/b8/a3a806d3950e8c0a03a34f234a92eff0e2c68d create mode 100644 tests/resources/merge-resolve/.gitted/objects/ba/cac9b3493509aa15e1730e1545fc0919d1dae0 create mode 100644 tests/resources/merge-resolve/.gitted/objects/bc/744705e1d8a019993cf88f62bc4020f1b80919 create mode 100644 tests/resources/merge-resolve/.gitted/objects/bc/95c75d59386147d1e79a87c33068d8dbfd71f2 create mode 100644 tests/resources/merge-resolve/.gitted/objects/bd/593285fc7fe4ca18ccdbabf027f5d689101452 create mode 100644 tests/resources/merge-resolve/.gitted/objects/bd/867fbae2faa80b920b002b80b1c91bcade7784 create mode 100644 tests/resources/merge-resolve/.gitted/objects/bd/9cb4cd0a770cb9adcb5fce212142ef40ea1c35 create mode 100644 tests/resources/merge-resolve/.gitted/objects/be/f6e37b3ee632ba74159168836f382fed21d77d create mode 100644 tests/resources/merge-resolve/.gitted/objects/c0/6a9be584ac49aa02c5551312d9e2982c91df10 create mode 100644 tests/resources/merge-resolve/.gitted/objects/c1/b17981db0840109a820dae8674ee29684134ff create mode 100644 tests/resources/merge-resolve/.gitted/objects/c1/b6a51bbb87c2f82b161412c3d20b59fc69b090 create mode 100644 tests/resources/merge-resolve/.gitted/objects/c3/5dee9bcc0e989f3b0c40f68372a9a51b6c4e6a create mode 100644 tests/resources/merge-resolve/.gitted/objects/c3/d02eeef75183df7584d8d13ac03053910c1301 create mode 100644 tests/resources/merge-resolve/.gitted/objects/c4/efe31e9decccc8b2b4d3df9aac2cdfe2995618 create mode 100644 tests/resources/merge-resolve/.gitted/objects/c5/0d0f1cb60b8b0fe1615ad20ace557e9d68d7bd create mode 100644 tests/resources/merge-resolve/.gitted/objects/c5/bbe550b9f09444bdddd3ecf3d97c0b42aa786c create mode 100644 tests/resources/merge-resolve/.gitted/objects/c6/07fc30883e335def28cd686b51f6cfa02b06ec create mode 100644 tests/resources/merge-resolve/.gitted/objects/c6/92ecf62007c0ac9fb26e2aa884de2933de15ed create mode 100644 tests/resources/merge-resolve/.gitted/objects/c8/f06f2e3bb2964174677e91f0abead0e43c9e5d create mode 100644 tests/resources/merge-resolve/.gitted/objects/c9/174cef549ec94ecbc43ef03cdc775b4950becb create mode 100644 tests/resources/merge-resolve/.gitted/objects/c9/4b27e41064c521120627e07e2035cca1d24ffa create mode 100644 tests/resources/merge-resolve/.gitted/objects/ca/b2cf23998b40f1af2d9d9a756dc9e285a8df4b create mode 100644 tests/resources/merge-resolve/.gitted/objects/cb/491780d82e46dc88a065b965ab307a038f2bc2 create mode 100644 tests/resources/merge-resolve/.gitted/objects/cb/6693a788715b82440a54e0eacd19ba9f6ec559 create mode 100644 tests/resources/merge-resolve/.gitted/objects/cc/3e3009134cb88014129fc8858d1101359e5e2f create mode 100644 tests/resources/merge-resolve/.gitted/objects/ce/8860d49e3bea6fd745874a01b7c3e46da8cbc3 create mode 100644 tests/resources/merge-resolve/.gitted/objects/ce/e656c392ad0557b3aae0fb411475c206e2926f create mode 100644 tests/resources/merge-resolve/.gitted/objects/cf/8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d create mode 100644 tests/resources/merge-resolve/.gitted/objects/d0/7ec190c306ec690bac349e87d01c4358e49bb2 create mode 100644 tests/resources/merge-resolve/.gitted/objects/d0/d4594e16f2e19107e3fa7ea63e7aaaff305ffb create mode 100644 tests/resources/merge-resolve/.gitted/objects/d2/f8637f2eab2507a1e13cbc9df4729ec386627e create mode 100644 tests/resources/merge-resolve/.gitted/objects/d3/719a5ae8e4d92276b5313ce976f6ee5af2b436 create mode 100644 tests/resources/merge-resolve/.gitted/objects/d3/7aa3bbfe1c0c49b909781251b956dbabe85f96 create mode 100644 tests/resources/merge-resolve/.gitted/objects/d3/7ad72a2052685fc6201c2af90103ad42d2079b create mode 100644 tests/resources/merge-resolve/.gitted/objects/d4/207f77243500bec335ab477f9227fcdb1e271a create mode 100644 tests/resources/merge-resolve/.gitted/objects/d4/27e0b2e138501a3d15cc376077a3631e15bd46 create mode 100644 tests/resources/merge-resolve/.gitted/objects/d5/093787ef302b941b6aab081b99fb4880038bd8 create mode 100644 tests/resources/merge-resolve/.gitted/objects/d5/a61b0b4992a4f0caa887fa08b52431e727bb6f create mode 100644 tests/resources/merge-resolve/.gitted/objects/d5/b6fc965c926a1bfc9ee456042b94088b5c5d21 create mode 100644 tests/resources/merge-resolve/.gitted/objects/d5/ec1152fe25e9fec00189eb00b3db71db24c218 create mode 100644 tests/resources/merge-resolve/.gitted/objects/d6/42b9770c66bba94a08df09b5efb095001f76d7 create mode 100644 tests/resources/merge-resolve/.gitted/objects/d6/462fa3f5292857db599c54aea2bf91616230c5 create mode 100644 tests/resources/merge-resolve/.gitted/objects/d6/cf6c7741b3316826af1314042550c97ded1d50 create mode 100644 tests/resources/merge-resolve/.gitted/objects/d8/74671ef5b20184836cb983bb273e5280384d0b create mode 100644 tests/resources/merge-resolve/.gitted/objects/d8/fa77b6833082c1ea36b7828a582d4c43882450 create mode 100644 tests/resources/merge-resolve/.gitted/objects/d9/63979c237d08b6ba39062ee7bf64c7d34a27f8 create mode 100644 tests/resources/merge-resolve/.gitted/objects/da/178208145ef585a1bd5ca5f4c9785d738df2cf create mode 100644 tests/resources/merge-resolve/.gitted/objects/db/6261a7c65c7fd678520c9bb6f2c47582ab9ed5 create mode 100644 tests/resources/merge-resolve/.gitted/objects/dd/9a570c3400e6e07bc4d7651d6e20b08926b3d9 create mode 100644 tests/resources/merge-resolve/.gitted/objects/de/872ee3618b894992e9d1e18ba2ebe256a112f9 create mode 100644 tests/resources/merge-resolve/.gitted/objects/df/e3f22baa1f6fce5447901c3086bae368de6bdd create mode 100644 tests/resources/merge-resolve/.gitted/objects/e0/67f9361140f19391472df8a82d6610813c73b7 create mode 100644 tests/resources/merge-resolve/.gitted/objects/e1/129b3cfb5898e0fbd606e0cb80b2755e50d161 create mode 100644 tests/resources/merge-resolve/.gitted/objects/e1/7ace1492648c9dc5701bad5c47af9d1b60c4e9 create mode 100644 tests/resources/merge-resolve/.gitted/objects/e2/c6abbd55fed5ac71a5f2751e29b4a34726a595 create mode 100644 tests/resources/merge-resolve/.gitted/objects/e3/1e7ad3ed298f24e383c4950f4671993ec078e4 create mode 100644 tests/resources/merge-resolve/.gitted/objects/e3/76fbdd06ebf021c92724da9f26f44212734e3e create mode 100644 tests/resources/merge-resolve/.gitted/objects/e4/9f917b448d1340b31d76e54ba388268fd4c922 create mode 100644 tests/resources/merge-resolve/.gitted/objects/e4/f618a2c3ed0669308735727df5ebf2447f022f create mode 100644 tests/resources/merge-resolve/.gitted/objects/e6/5a9bb2af9f4c2d1c375dd0f8f8a46cf9c68812 create mode 100644 tests/resources/merge-resolve/.gitted/objects/e8/107f24196736b870a318a0e28f048e29f6feff create mode 100644 tests/resources/merge-resolve/.gitted/objects/e9/2cdb7017dc6c5aed25cb4202c5b0104b872246 create mode 100644 tests/resources/merge-resolve/.gitted/objects/e9/ad6ec3e38364a3d07feda7c4197d4d845c53b5 create mode 100644 tests/resources/merge-resolve/.gitted/objects/e9/f48beccc62d535739bfbdebe0a55ed716d8366 create mode 100644 tests/resources/merge-resolve/.gitted/objects/eb/c09d0137cfb0c26697aed0109fb943ad906f3f create mode 100644 tests/resources/merge-resolve/.gitted/objects/ec/67e5a86adff465359f1c8f995e12dbdfa08d8a create mode 100644 tests/resources/merge-resolve/.gitted/objects/ed/9523e62e453e50dd9be1606af19399b96e397a create mode 100644 tests/resources/merge-resolve/.gitted/objects/ee/1d6f164893c1866a323f072eeed36b855656be create mode 100644 tests/resources/merge-resolve/.gitted/objects/ee/3fa1b8c00aff7fe02065fdb50864bb0d932ccf create mode 100644 tests/resources/merge-resolve/.gitted/objects/ee/a9286df54245fea72c5b557291470eb825f38f create mode 100644 tests/resources/merge-resolve/.gitted/objects/ef/58fdd8086c243bdc81f99e379acacfd21d32d6 create mode 100644 tests/resources/merge-resolve/.gitted/objects/ef/c499524cf105d5264ac7fc54e07e95764e8075 create mode 100644 tests/resources/merge-resolve/.gitted/objects/ef/c9121fdedaf08ba180b53ebfbcf71bd488ed09 create mode 100644 tests/resources/merge-resolve/.gitted/objects/f0/053b8060bb3f0be5cbcc3147a07ece26bf097e create mode 100644 tests/resources/merge-resolve/.gitted/objects/f0/ce2b8e4986084d9b308fb72709e414c23eb5e6 create mode 100644 tests/resources/merge-resolve/.gitted/objects/f2/0c9063fa0bda9a397c96947a7b687305c49753 create mode 100644 tests/resources/merge-resolve/.gitted/objects/f2/9e7fb590551095230c6149cbe72f2e9104a796 create mode 100644 tests/resources/merge-resolve/.gitted/objects/f3/293571dcd708b6a3faf03818cd2844d000e198 create mode 100644 tests/resources/merge-resolve/.gitted/objects/f3/f1164b68b57b1995b658a828320e6df3081fae create mode 100644 tests/resources/merge-resolve/.gitted/objects/f4/15caf3fcad16304cb424b67f0ee6b12dc03aae create mode 100644 tests/resources/merge-resolve/.gitted/objects/f4/8097eb340dc5a7cae55aabcf1faf4548aa821f create mode 100644 tests/resources/merge-resolve/.gitted/objects/f5/504f36e6f4eb797a56fc5bac6c6c7f32969bf2 create mode 100644 tests/resources/merge-resolve/.gitted/objects/f5/b50c85a87cac64d7eb3254cdd1aec9564c0293 create mode 100644 tests/resources/merge-resolve/.gitted/objects/f5/f9dd5886a6ee20272be0aafc790cba43b31931 create mode 100644 tests/resources/merge-resolve/.gitted/objects/f6/be049e284c0f9dcbbc745543885be3502ea521 create mode 100644 tests/resources/merge-resolve/.gitted/objects/f7/c332bd4d4d4b777366cae4d24d1687477576bf create mode 100644 tests/resources/merge-resolve/.gitted/objects/f8/958bdf4d365a84a9a178b1f5f35ff1dacbd884 create mode 100644 tests/resources/merge-resolve/.gitted/objects/fa/c03f2c5139618d87d53614c153823bf1f31396 create mode 100644 tests/resources/merge-resolve/.gitted/objects/fa/da9356aa3f74622327a3038ae9c6f92e1c5c1d create mode 100644 tests/resources/merge-resolve/.gitted/objects/fb/738a106cfd097a4acb96ce132ecb1ad6c46b03 create mode 100644 tests/resources/merge-resolve/.gitted/objects/fc/4c636d6515e9e261f9260dbcf3cc6eca97ea08 create mode 100644 tests/resources/merge-resolve/.gitted/objects/fc/7d7b805f7a9428574f4f802b2e34cd20ab9d99 create mode 100644 tests/resources/merge-resolve/.gitted/objects/fc/90237dc4891fa6c69827fc465632225e391618 create mode 100644 tests/resources/merge-resolve/.gitted/objects/fd/57d2d6770fad8e9959124793a17f441b571e66 create mode 100644 tests/resources/merge-resolve/.gitted/objects/fd/89f8cffb663ac89095a0f9764902e93ceaca6a create mode 100644 tests/resources/merge-resolve/.gitted/objects/fe/5407fc50a53aecb41d1a6e9ea7b612e581af87 create mode 100644 tests/resources/merge-resolve/.gitted/objects/ff/49d07869831ad761bbdaea026086f8789bcb00 create mode 100644 tests/resources/merge-resolve/.gitted/objects/ff/b312248d607284c290023f9502eea010d34efd create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/df_ancestor create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/df_side1 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/df_side2 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/ff_branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/master create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/octo1 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/octo2 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/octo3 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/octo4 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/octo5 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/octo6 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ancestor create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ours create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/rename_conflict_theirs create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/renames1 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/renames2 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-10 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-10-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-11 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-11-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-13 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-13-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-14 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-14-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-2alt create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-2alt-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-3alt create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-3alt-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-4 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-4-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-6 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-6-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-7 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-7-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-8 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-8-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-9 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/trivial-9-branch create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/unrelated create mode 100644 tests/resources/merge-resolve/added-in-master.txt create mode 100644 tests/resources/merge-resolve/automergeable.txt create mode 100644 tests/resources/merge-resolve/changed-in-branch.txt create mode 100644 tests/resources/merge-resolve/changed-in-master.txt create mode 100644 tests/resources/merge-resolve/conflicting.txt create mode 100644 tests/resources/merge-resolve/removed-in-branch.txt create mode 100644 tests/resources/merge-resolve/unchanged.txt create mode 100644 tests/resources/mergedrepo/.gitted/COMMIT_EDITMSG create mode 100644 tests/resources/mergedrepo/.gitted/HEAD create mode 100644 tests/resources/mergedrepo/.gitted/MERGE_HEAD create mode 100644 tests/resources/mergedrepo/.gitted/MERGE_MODE create mode 100644 tests/resources/mergedrepo/.gitted/MERGE_MSG create mode 100644 tests/resources/mergedrepo/.gitted/ORIG_HEAD create mode 100644 tests/resources/mergedrepo/.gitted/config create mode 100644 tests/resources/mergedrepo/.gitted/description create mode 100644 tests/resources/mergedrepo/.gitted/index create mode 100644 tests/resources/mergedrepo/.gitted/info/exclude create mode 100644 tests/resources/mergedrepo/.gitted/logs/HEAD create mode 100644 tests/resources/mergedrepo/.gitted/logs/refs/heads/branch create mode 100644 tests/resources/mergedrepo/.gitted/logs/refs/heads/master create mode 100644 tests/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712 create mode 100644 tests/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91 create mode 100644 tests/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 create mode 100644 tests/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211e create mode 100644 tests/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6 create mode 100644 tests/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534 create mode 100644 tests/resources/mergedrepo/.gitted/objects/3a/34580a35add43a4cf361e8e9a30060a905c876 create mode 100644 tests/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8c create mode 100644 tests/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3 create mode 100644 tests/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52da create mode 100644 tests/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46ad create mode 100644 tests/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399 create mode 100644 tests/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 create mode 100644 tests/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 create mode 100644 tests/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71 create mode 100644 tests/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038c create mode 100644 tests/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda create mode 100644 tests/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673 create mode 100644 tests/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735a create mode 100644 tests/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2 create mode 100644 tests/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8 create mode 100644 tests/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 create mode 100644 tests/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50 create mode 100644 tests/resources/mergedrepo/.gitted/objects/9a/05ccb4e0f948de03128e095f39dae6976751c5 create mode 100644 tests/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092c create mode 100644 tests/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d create mode 100644 tests/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51 create mode 100644 tests/resources/mergedrepo/.gitted/objects/e2/809157a7766f272e4cfe26e61ef2678a5357ff create mode 100644 tests/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478 create mode 100644 tests/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406 create mode 100644 tests/resources/mergedrepo/.gitted/refs/heads/branch create mode 100644 tests/resources/mergedrepo/.gitted/refs/heads/master create mode 100644 tests/resources/mergedrepo/conflicts-one.txt create mode 100644 tests/resources/mergedrepo/conflicts-two.txt create mode 100644 tests/resources/mergedrepo/one.txt create mode 100644 tests/resources/mergedrepo/two.txt create mode 100644 tests/resources/partial-testrepo/.gitted/HEAD create mode 100644 tests/resources/partial-testrepo/.gitted/config create mode 100644 tests/resources/partial-testrepo/.gitted/index create mode 100644 tests/resources/partial-testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e create mode 100644 tests/resources/partial-testrepo/.gitted/objects/16/8e4ebd1c667499548ae12403b19b22a5c5e925 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd create mode 100644 tests/resources/partial-testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc create mode 100644 tests/resources/partial-testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a create mode 100644 tests/resources/partial-testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d create mode 100644 tests/resources/partial-testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a create mode 100644 tests/resources/partial-testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f create mode 100644 tests/resources/partial-testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd create mode 100644 tests/resources/partial-testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd create mode 100644 tests/resources/partial-testrepo/.gitted/objects/cf/80f8de9f1185bf3a05f993f6121880dd0cfbc9 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/d5/2a8fe84ceedf260afe4f0287bbfca04a117e83 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/fd/093bff70906175335656e6ce6ae05783708765 create mode 100644 tests/resources/partial-testrepo/.gitted/objects/pack/.gitkeep create mode 100644 tests/resources/partial-testrepo/.gitted/refs/heads/dir create mode 100644 tests/resources/peeled.git/HEAD create mode 100644 tests/resources/peeled.git/config create mode 100644 tests/resources/peeled.git/objects/info/packs create mode 100644 tests/resources/peeled.git/objects/pack/pack-e84773eaf3fce1774755580e3dbb8d9f3a1adc45.idx create mode 100644 tests/resources/peeled.git/objects/pack/pack-e84773eaf3fce1774755580e3dbb8d9f3a1adc45.pack create mode 100644 tests/resources/peeled.git/packed-refs create mode 100644 tests/resources/peeled.git/refs/heads/master create mode 100644 tests/resources/push.sh create mode 100644 tests/resources/push_src/.gitted/COMMIT_EDITMSG create mode 100644 tests/resources/push_src/.gitted/HEAD create mode 100644 tests/resources/push_src/.gitted/ORIG_HEAD create mode 100644 tests/resources/push_src/.gitted/config create mode 100644 tests/resources/push_src/.gitted/description create mode 100644 tests/resources/push_src/.gitted/index create mode 100644 tests/resources/push_src/.gitted/info/exclude create mode 100644 tests/resources/push_src/.gitted/logs/HEAD create mode 100644 tests/resources/push_src/.gitted/logs/refs/heads/b1 create mode 100644 tests/resources/push_src/.gitted/logs/refs/heads/b2 create mode 100644 tests/resources/push_src/.gitted/logs/refs/heads/b3 create mode 100644 tests/resources/push_src/.gitted/logs/refs/heads/b4 create mode 100644 tests/resources/push_src/.gitted/logs/refs/heads/b5 create mode 100644 tests/resources/push_src/.gitted/logs/refs/heads/master create mode 100644 tests/resources/push_src/.gitted/modules/submodule/HEAD create mode 100644 tests/resources/push_src/.gitted/modules/submodule/config create mode 100644 tests/resources/push_src/.gitted/modules/submodule/description create mode 100644 tests/resources/push_src/.gitted/modules/submodule/index create mode 100644 tests/resources/push_src/.gitted/modules/submodule/info/exclude create mode 100644 tests/resources/push_src/.gitted/modules/submodule/logs/HEAD create mode 100644 tests/resources/push_src/.gitted/modules/submodule/logs/refs/heads/master create mode 100644 tests/resources/push_src/.gitted/modules/submodule/logs/refs/remotes/origin/HEAD create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/18/10dff58d8a660512d4832e740f692884338ccd create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/1b/8cbad43e867676df601306689fe7c3def5e689 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/7b/4384978d2493e851f9cca7858815fac9b10980 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/81/4889a078c031f61ed08ab5fa863aea9314344d create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/84/96071c1b46c854b31185ea97743be6a8774479 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/ae/90f12eea699729ed24555e40b9fd669da12a12 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/b6/361fc6a97178d8fc8639fdeed71c775ab52593 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/d0/7b0f9a8c89f1d9e74dc4fce6421dec5ef8a659 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/d6/c93164c249c8000205dd4ec5cbca1b516d487f create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/d7/1aab4f9b04b45ce09bcaa636a9be6231474759 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/e7/b4ad382349ff96dd8199000580b9b1e2042eb0 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/f1/425cef211cc08caa31e7b545ffb232acb098c3 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/fa/49b077972391ad58037050f2a75f74e3671e92 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/fd/093bff70906175335656e6ce6ae05783708765 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/fd/4959ce7510db09d4d8217fa2d1780413e05a09 create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx create mode 100644 tests/resources/push_src/.gitted/modules/submodule/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack create mode 100644 tests/resources/push_src/.gitted/modules/submodule/packed-refs create mode 100644 tests/resources/push_src/.gitted/modules/submodule/refs/heads/master create mode 100644 tests/resources/push_src/.gitted/modules/submodule/refs/remotes/origin/HEAD create mode 100644 tests/resources/push_src/.gitted/objects/08/585692ce06452da6f82ae66b90d98b55536fca create mode 100644 tests/resources/push_src/.gitted/objects/27/b7ce66243eb1403862d05f958c002312df173d create mode 100644 tests/resources/push_src/.gitted/objects/28/905c54ea45a4bed8d7b90f51bd8bd81eec8840 create mode 100644 tests/resources/push_src/.gitted/objects/36/6226fb970ac0caa9d3f55967ab01334a548f60 create mode 100644 tests/resources/push_src/.gitted/objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 create mode 100644 tests/resources/push_src/.gitted/objects/5c/0bb3d1b9449d1cc69d7519fd05166f01840915 create mode 100644 tests/resources/push_src/.gitted/objects/61/780798228d17af2d34fce4cfbdf35556832472 create mode 100644 tests/resources/push_src/.gitted/objects/64/fd55f9b6390202db5e5666fd1fb339089fba4d create mode 100644 tests/resources/push_src/.gitted/objects/78/981922613b2afb6025042ff6bd878ac1994e85 create mode 100644 tests/resources/push_src/.gitted/objects/80/5c54522e614f29f70d2413a0470247d8b424ac create mode 100644 tests/resources/push_src/.gitted/objects/95/1bbbb90e2259a4c8950db78946784fb53fcbce create mode 100644 tests/resources/push_src/.gitted/objects/a7/8705c3b2725f931d3ee05348d83cc26700f247 create mode 100644 tests/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498 create mode 100644 tests/resources/push_src/.gitted/objects/b4/e1f2b375a64c1ccd40c5ff6aa8bc96839ba4fd create mode 100644 tests/resources/push_src/.gitted/objects/c1/0409136a7a75e025fa502a1b2fd7b62b77d279 create mode 100644 tests/resources/push_src/.gitted/objects/cd/881f90f2933db2e4cc26b8c71fe6037ac7fe4c create mode 100644 tests/resources/push_src/.gitted/objects/d9/b63a88223d8367516f50bd131a5f7349b7f3e4 create mode 100644 tests/resources/push_src/.gitted/objects/dc/ab83249f6f9d1ed735d651352a80519339b591 create mode 100644 tests/resources/push_src/.gitted/objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 create mode 100644 tests/resources/push_src/.gitted/objects/f7/8a3106c85fb549c65198b2a2086276c6174928 create mode 100644 tests/resources/push_src/.gitted/objects/f8/f7aefc2900a3d737cea9eee45729fd55761e1a create mode 100644 tests/resources/push_src/.gitted/objects/fa/38b91f199934685819bea316186d8b008c52a2 create mode 100644 tests/resources/push_src/.gitted/objects/ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e create mode 100644 tests/resources/push_src/.gitted/objects/ff/fe95c7fd0a37fa2ed702f8f93b56b2196b3925 create mode 100644 tests/resources/push_src/.gitted/objects/pack/dummy create mode 100644 tests/resources/push_src/.gitted/refs/heads/b1 create mode 100644 tests/resources/push_src/.gitted/refs/heads/b2 create mode 100644 tests/resources/push_src/.gitted/refs/heads/b3 create mode 100644 tests/resources/push_src/.gitted/refs/heads/b4 create mode 100644 tests/resources/push_src/.gitted/refs/heads/b5 create mode 100644 tests/resources/push_src/.gitted/refs/heads/b6 create mode 100644 tests/resources/push_src/.gitted/refs/tags/tag-blob create mode 100644 tests/resources/push_src/.gitted/refs/tags/tag-commit create mode 100644 tests/resources/push_src/.gitted/refs/tags/tag-commit-two create mode 100644 tests/resources/push_src/.gitted/refs/tags/tag-lightweight create mode 100644 tests/resources/push_src/.gitted/refs/tags/tag-tag create mode 100644 tests/resources/push_src/.gitted/refs/tags/tag-tree create mode 100644 tests/resources/push_src/a.txt create mode 100644 tests/resources/push_src/fold/b.txt create mode 100644 tests/resources/push_src/foldb.txt create mode 100644 tests/resources/push_src/gitmodules create mode 100644 tests/resources/push_src/submodule/.gitted create mode 100644 tests/resources/push_src/submodule/README create mode 100644 tests/resources/push_src/submodule/branch_file.txt create mode 100644 tests/resources/push_src/submodule/new.txt create mode 100644 tests/resources/renames/.gitted/HEAD create mode 100644 tests/resources/renames/.gitted/config create mode 100644 tests/resources/renames/.gitted/description create mode 100644 tests/resources/renames/.gitted/index create mode 100644 tests/resources/renames/.gitted/info/exclude create mode 100644 tests/resources/renames/.gitted/logs/HEAD create mode 100644 tests/resources/renames/.gitted/logs/refs/heads/master create mode 100644 tests/resources/renames/.gitted/objects/03/da7ad872536bd448da8d88eb7165338bf923a7 create mode 100644 tests/resources/renames/.gitted/objects/17/58bdd7c16a72ff7c17d8de0c957ced3ccad645 create mode 100644 tests/resources/renames/.gitted/objects/19/dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 create mode 100644 tests/resources/renames/.gitted/objects/1c/068dee5790ef1580cfc4cd670915b48d790084 create mode 100644 tests/resources/renames/.gitted/objects/2b/c7f351d20b53f1c72c16c4b036e491c478c49a create mode 100644 tests/resources/renames/.gitted/objects/31/e47d8c1fa36d7f8d537b96158e3f024de0a9f2 create mode 100644 tests/resources/renames/.gitted/objects/35/92953ff3ea5e8ba700c429f3aefe33c8806754 create mode 100644 tests/resources/renames/.gitted/objects/36/020db6cdacaa93497f31edcd8f242ff9bc366d create mode 100644 tests/resources/renames/.gitted/objects/3c/04741dd4b96c4ae4b00ec0f6e10c816a30aad2 create mode 100644 tests/resources/renames/.gitted/objects/42/10ffd5c390b21dd5483375e75288dea9ede512 create mode 100644 tests/resources/renames/.gitted/objects/44/4a76ed3e45b183753f49376af30da8c3fe276a create mode 100644 tests/resources/renames/.gitted/objects/47/184c1e7eb22abcbed2bf4ee87d4e38096f7951 create mode 100644 tests/resources/renames/.gitted/objects/4e/4cae3e7dd56ed74bff39526d0469e554432953 create mode 100644 tests/resources/renames/.gitted/objects/50/e90273af7d826ff0a95865bcd3ba8412c447d9 create mode 100644 tests/resources/renames/.gitted/objects/5e/26abc56a5a84d89790f45416648899cbe13109 create mode 100644 tests/resources/renames/.gitted/objects/61/8c6f2f8740bd6049b2fb9eb93fc15726462745 create mode 100644 tests/resources/renames/.gitted/objects/66/311f5cfbe7836c27510a3ba2f43e282e2c8bba create mode 100644 tests/resources/renames/.gitted/objects/93/f538c45a57a87eb4c1e86f91c6ee41d66c7ba7 create mode 100644 tests/resources/renames/.gitted/objects/9a/69d960ae94b060f56c2a8702545e2bb1abb935 create mode 100644 tests/resources/renames/.gitted/objects/ad/0a8e55a104ac54a8a29ed4b84b49e76837a113 create mode 100644 tests/resources/renames/.gitted/objects/b9/25b224cc91f897001a9993fbce169fdaa8858f create mode 100644 tests/resources/renames/.gitted/objects/d7/9b202de198fa61b02424b9e25e840dc75e1323 create mode 100644 tests/resources/renames/.gitted/objects/ea/c43f5195a2cee53b7458d8dad16aedde10711b create mode 100644 tests/resources/renames/.gitted/objects/ea/f4a3e3bfe68585e90cada20736ace491cd100b create mode 100644 tests/resources/renames/.gitted/objects/f9/0d4fc20ecddf21eebe6a37e9225d244339d2b5 create mode 100644 tests/resources/renames/.gitted/refs/heads/master create mode 100644 tests/resources/renames/.gitted/refs/heads/renames_similar create mode 100644 tests/resources/renames/.gitted/refs/heads/renames_similar_two create mode 100644 tests/resources/renames/ikeepsix.txt create mode 100644 tests/resources/renames/sixserving.txt create mode 100644 tests/resources/renames/songof7cities.txt create mode 100644 tests/resources/renames/untimely.txt create mode 100644 tests/resources/shallow.git/HEAD create mode 100644 tests/resources/shallow.git/config create mode 100644 tests/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.idx create mode 100644 tests/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.pack create mode 100644 tests/resources/shallow.git/packed-refs create mode 100644 tests/resources/shallow.git/refs/.gitkeep create mode 100644 tests/resources/shallow.git/shallow create mode 100644 tests/resources/short_tag.git/HEAD create mode 100644 tests/resources/short_tag.git/config create mode 100644 tests/resources/short_tag.git/index create mode 100644 tests/resources/short_tag.git/objects/4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c create mode 100644 tests/resources/short_tag.git/objects/4d/5fcadc293a348e88f777dc0920f11e7d71441c create mode 100644 tests/resources/short_tag.git/objects/5d/a7760512a953e3c7c4e47e4392c7a4338fb729 create mode 100644 tests/resources/short_tag.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 tests/resources/short_tag.git/packed-refs create mode 100644 tests/resources/short_tag.git/refs/heads/master create mode 100644 tests/resources/status/.gitted/COMMIT_EDITMSG create mode 100644 tests/resources/status/.gitted/HEAD create mode 100644 tests/resources/status/.gitted/ORIG_HEAD create mode 100644 tests/resources/status/.gitted/config create mode 100644 tests/resources/status/.gitted/description create mode 100644 tests/resources/status/.gitted/index create mode 100644 tests/resources/status/.gitted/info/exclude create mode 100644 tests/resources/status/.gitted/logs/HEAD create mode 100644 tests/resources/status/.gitted/logs/refs/heads/master create mode 100644 tests/resources/status/.gitted/objects/00/17bd4ab1ec30440b17bae1680cff124ab5f1f6 create mode 100644 tests/resources/status/.gitted/objects/06/1d42a44cacde5726057b67558821d95db96f19 create mode 100644 tests/resources/status/.gitted/objects/18/88c805345ba265b0ee9449b8877b6064592058 create mode 100644 tests/resources/status/.gitted/objects/19/d9cc8584ac2c7dcf57d2680375e80f099dc481 create mode 100644 tests/resources/status/.gitted/objects/26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f create mode 100644 tests/resources/status/.gitted/objects/32/504b727382542f9f089e24fddac5e78533e96c create mode 100644 tests/resources/status/.gitted/objects/37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0 create mode 100644 tests/resources/status/.gitted/objects/45/2e4244b5d083ddf0460acf1ecc74db9dcfa11a create mode 100644 tests/resources/status/.gitted/objects/52/9a16e8e762d4acb7b9636ff540a00831f9155a create mode 100644 tests/resources/status/.gitted/objects/53/ace0d1cc1145a5f4fe4f78a186a60263190733 create mode 100644 tests/resources/status/.gitted/objects/54/52d32f1dd538eb0405e8a83cc185f79e25e80f create mode 100644 tests/resources/status/.gitted/objects/55/d316c9ba708999f1918e9677d01dfcae69c6b9 create mode 100644 tests/resources/status/.gitted/objects/70/bd9443ada07063e7fbf0b3ff5c13f7494d89c2 create mode 100644 tests/resources/status/.gitted/objects/73/5b6a258cd196a8f7c9428419b02c1dca93fd75 create mode 100644 tests/resources/status/.gitted/objects/75/6e27627e67bfbc048d01ece5819c6de733d7ea create mode 100644 tests/resources/status/.gitted/objects/90/6ee7711f4f4928ddcb2a5f8fbc500deba0d2a8 create mode 100644 tests/resources/status/.gitted/objects/90/b8c29d8ba39434d1c63e1b093daaa26e5bd972 create mode 100644 tests/resources/status/.gitted/objects/9c/2e02cdffa8d73e6c189074594477a6baf87960 create mode 100644 tests/resources/status/.gitted/objects/a0/de7e0ac200c489c41c59dfa910154a70264e6e create mode 100644 tests/resources/status/.gitted/objects/a6/191982709b746d5650e93c2acf34ef74e11504 create mode 100644 tests/resources/status/.gitted/objects/a6/be623522ce87a1d862128ac42672604f7b468b create mode 100644 tests/resources/status/.gitted/objects/aa/27a641456848200fdb7f7c99ba36f8a0952877 create mode 100644 tests/resources/status/.gitted/objects/da/bc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 create mode 100644 tests/resources/status/.gitted/objects/e8/ee89e15bbe9b20137715232387b3de5b28972e create mode 100644 tests/resources/status/.gitted/objects/e9/b9107f290627c04d097733a10055af941f6bca create mode 100644 tests/resources/status/.gitted/objects/ed/062903b8f6f3dccb2fa81117ba6590944ef9bd create mode 100644 tests/resources/status/.gitted/refs/heads/master create mode 100644 tests/resources/status/current_file create mode 100644 tests/resources/status/ignored_file create mode 100644 tests/resources/status/modified_file create mode 100644 tests/resources/status/new_file create mode 100644 tests/resources/status/staged_changes create mode 100644 tests/resources/status/staged_changes_modified_file create mode 100644 tests/resources/status/staged_delete_modified_file create mode 100644 tests/resources/status/staged_new_file create mode 100644 tests/resources/status/staged_new_file_modified_file create mode 100644 tests/resources/status/subdir.txt create mode 100644 tests/resources/status/subdir/current_file create mode 100644 tests/resources/status/subdir/modified_file create mode 100644 tests/resources/status/subdir/new_file create mode 100644 "tests/resources/status/\350\277\231" create mode 100644 tests/resources/submod2/.gitted/HEAD create mode 100644 tests/resources/submod2/.gitted/config create mode 100644 tests/resources/submod2/.gitted/description create mode 100644 tests/resources/submod2/.gitted/index create mode 100644 tests/resources/submod2/.gitted/info/exclude create mode 100644 tests/resources/submod2/.gitted/logs/HEAD create mode 100644 tests/resources/submod2/.gitted/logs/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/config create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/description create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/index create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/info/exclude create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/41/bd4bc3df978de695f67ace64c560913da11653 create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/5e/4963595a9774b90524d35a807169049de8ccad create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/6b/31c659545507c381e9cd34ec508f16c04e149e create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/73/ba924a80437097795ae839e66e187c55d3babf create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/9efbdadaa4a582778d4584385495559ea0994b create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/packed-refs create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/config create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/description create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/index create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/info/exclude create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/logs/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/objects/5e/4963595a9774b90524d35a807169049de8ccad create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/objects/73/ba924a80437097795ae839e66e187c55d3babf create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/packed-refs create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_file/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/COMMIT_EDITMSG create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/config create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/description create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/index create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/info/exclude create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/logs/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/3d/9386c507f6b093471a3e324085657a3c2b4247 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/41/bd4bc3df978de695f67ace64c560913da11653 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/5e/4963595a9774b90524d35a807169049de8ccad create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/6b/31c659545507c381e9cd34ec508f16c04e149e create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/73/ba924a80437097795ae839e66e187c55d3babf create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/77/fb0ed3e58568d6ad362c78de08ab8649d76e29 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/78/9efbdadaa4a582778d4584385495559ea0994b create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/8e/b1e637ed9fc8e5454fa20d38f809091f9395f4 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/packed-refs create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_head/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/config create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/description create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/index create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/info/exclude create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/logs/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/41/bd4bc3df978de695f67ace64c560913da11653 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/5e/4963595a9774b90524d35a807169049de8ccad create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/6b/31c659545507c381e9cd34ec508f16c04e149e create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/73/ba924a80437097795ae839e66e187c55d3babf create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/78/9efbdadaa4a582778d4584385495559ea0994b create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/a0/2d31770687965547ab7a04cee199b29ee458d6 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/packed-refs create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_index/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/config create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/description create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/index create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/info/exclude create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/5e/4963595a9774b90524d35a807169049de8ccad create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/73/ba924a80437097795ae839e66e187c55d3babf create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/packed-refs create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/config create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/description create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/index create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/info/exclude create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/logs/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/41/bd4bc3df978de695f67ace64c560913da11653 create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/5e/4963595a9774b90524d35a807169049de8ccad create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/6b/31c659545507c381e9cd34ec508f16c04e149e create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/packed-refs create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_missing_commits/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/config create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/description create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/index create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/info/exclude create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/logs/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/objects/41/bd4bc3df978de695f67ace64c560913da11653 create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/objects/5e/4963595a9774b90524d35a807169049de8ccad create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/objects/6b/31c659545507c381e9cd34ec508f16c04e149e create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/objects/73/ba924a80437097795ae839e66e187c55d3babf create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/objects/78/9efbdadaa4a582778d4584385495559ea0994b create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/packed-refs create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/refs/heads/master create mode 100644 tests/resources/submod2/.gitted/modules/sm_unchanged/refs/remotes/origin/HEAD create mode 100644 tests/resources/submod2/.gitted/objects/09/460e5b6cbcb05a3e404593c32a3aa7221eca0e create mode 100644 tests/resources/submod2/.gitted/objects/14/fe9ccf104058df25e0a08361c4494e167ef243 create mode 100644 tests/resources/submod2/.gitted/objects/22/ce3e0311dda73a5992d54a4a595518d3876ea7 create mode 100644 tests/resources/submod2/.gitted/objects/25/5546424b0efb847b1bfc91dbf7348b277f8970 create mode 100644 tests/resources/submod2/.gitted/objects/2a/30f1e6f94b20917005a21273f65b406d0f8bad create mode 100644 tests/resources/submod2/.gitted/objects/42/cfb95cd01bf9225b659b5ee3edcc78e8eeb478 create mode 100644 tests/resources/submod2/.gitted/objects/57/958699c2dc394f81cfc76950e9c3ac3025c398 create mode 100644 tests/resources/submod2/.gitted/objects/59/01da4f1c67756eeadc5121d206bec2431f253b create mode 100644 tests/resources/submod2/.gitted/objects/60/7d96653d4d0a4f733107f7890c2e67b55b620d create mode 100644 tests/resources/submod2/.gitted/objects/74/84482eb8db738cafa696993664607500a3f2b9 create mode 100644 tests/resources/submod2/.gitted/objects/7b/a4c5c3561daa5ab1a86215cfb0587e96d404d6 create mode 100644 tests/resources/submod2/.gitted/objects/87/3585b94bdeabccea991ea5e3ec1a277895b698 create mode 100644 tests/resources/submod2/.gitted/objects/97/4cf7c73de336b0c4e019f918f3cee367d72e84 create mode 100644 tests/resources/submod2/.gitted/objects/9d/bc299bc013ea253583b40bf327b5a6e4037b89 create mode 100644 tests/resources/submod2/.gitted/objects/a9/104bf89e911387244ef499413960ba472066d9 create mode 100644 tests/resources/submod2/.gitted/objects/b6/14088620bbdc1d29549d223ceba0f4419fd4cb create mode 100644 tests/resources/submod2/.gitted/objects/d4/07f19e50c1da1ff584beafe0d6dac7237c5d06 create mode 100644 tests/resources/submod2/.gitted/objects/d9/3e95571d92cceb5de28c205f1d5f3cc8b88bc8 create mode 100644 tests/resources/submod2/.gitted/objects/e3/b83bf274ee065eee48734cf8c6dfaf5e81471c create mode 100644 tests/resources/submod2/.gitted/objects/f5/4414c25e6d24fe39f5c3f128d7c8a17bc23833 create mode 100644 tests/resources/submod2/.gitted/objects/f9/90a25a74d1a8281ce2ab018ea8df66795cd60b create mode 100644 tests/resources/submod2/.gitted/refs/heads/master create mode 100644 tests/resources/submod2/README.txt create mode 100644 tests/resources/submod2/gitmodules create mode 100644 tests/resources/submod2/just_a_dir/contents create mode 100644 tests/resources/submod2/just_a_file create mode 100644 tests/resources/submod2/not-submodule/.gitted/HEAD create mode 100644 tests/resources/submod2/not-submodule/.gitted/config create mode 100644 tests/resources/submod2/not-submodule/.gitted/description create mode 100644 tests/resources/submod2/not-submodule/.gitted/index create mode 100644 tests/resources/submod2/not-submodule/.gitted/info/exclude create mode 100644 tests/resources/submod2/not-submodule/.gitted/logs/HEAD create mode 100644 tests/resources/submod2/not-submodule/.gitted/logs/refs/heads/master create mode 100644 tests/resources/submod2/not-submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 create mode 100644 tests/resources/submod2/not-submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 create mode 100644 tests/resources/submod2/not-submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e create mode 100644 tests/resources/submod2/not-submodule/.gitted/refs/heads/master create mode 100644 tests/resources/submod2/not-submodule/README.txt create mode 100644 tests/resources/submod2/not/.gitted/notempty create mode 100644 tests/resources/submod2/not/README.txt create mode 100644 tests/resources/submod2/sm_added_and_uncommited/.gitted create mode 100644 tests/resources/submod2/sm_added_and_uncommited/README.txt create mode 100644 tests/resources/submod2/sm_added_and_uncommited/file_to_modify create mode 100644 tests/resources/submod2/sm_changed_file/.gitted create mode 100644 tests/resources/submod2/sm_changed_file/README.txt create mode 100644 tests/resources/submod2/sm_changed_file/file_to_modify create mode 100644 tests/resources/submod2/sm_changed_head/.gitted create mode 100644 tests/resources/submod2/sm_changed_head/README.txt create mode 100644 tests/resources/submod2/sm_changed_head/file_to_modify create mode 100644 tests/resources/submod2/sm_changed_index/.gitted create mode 100644 tests/resources/submod2/sm_changed_index/README.txt create mode 100644 tests/resources/submod2/sm_changed_index/file_to_modify create mode 100644 tests/resources/submod2/sm_changed_untracked_file/.gitted create mode 100644 tests/resources/submod2/sm_changed_untracked_file/README.txt create mode 100644 tests/resources/submod2/sm_changed_untracked_file/file_to_modify create mode 100644 tests/resources/submod2/sm_changed_untracked_file/i_am_untracked create mode 100644 tests/resources/submod2/sm_missing_commits/.gitted create mode 100644 tests/resources/submod2/sm_missing_commits/README.txt create mode 100644 tests/resources/submod2/sm_missing_commits/file_to_modify create mode 100644 tests/resources/submod2/sm_unchanged/.gitted create mode 100644 tests/resources/submod2/sm_unchanged/README.txt create mode 100644 tests/resources/submod2/sm_unchanged/file_to_modify create mode 100644 tests/resources/submod2_target/.gitted/HEAD create mode 100644 tests/resources/submod2_target/.gitted/config create mode 100644 tests/resources/submod2_target/.gitted/description create mode 100644 tests/resources/submod2_target/.gitted/index create mode 100644 tests/resources/submod2_target/.gitted/info/exclude create mode 100644 tests/resources/submod2_target/.gitted/logs/HEAD create mode 100644 tests/resources/submod2_target/.gitted/logs/refs/heads/master create mode 100644 tests/resources/submod2_target/.gitted/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 create mode 100644 tests/resources/submod2_target/.gitted/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 create mode 100644 tests/resources/submod2_target/.gitted/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 create mode 100644 tests/resources/submod2_target/.gitted/objects/41/bd4bc3df978de695f67ace64c560913da11653 create mode 100644 tests/resources/submod2_target/.gitted/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 create mode 100644 tests/resources/submod2_target/.gitted/objects/5e/4963595a9774b90524d35a807169049de8ccad create mode 100644 tests/resources/submod2_target/.gitted/objects/6b/31c659545507c381e9cd34ec508f16c04e149e create mode 100644 tests/resources/submod2_target/.gitted/objects/73/ba924a80437097795ae839e66e187c55d3babf create mode 100644 tests/resources/submod2_target/.gitted/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a create mode 100644 tests/resources/submod2_target/.gitted/objects/78/9efbdadaa4a582778d4584385495559ea0994b create mode 100644 tests/resources/submod2_target/.gitted/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e create mode 100644 tests/resources/submod2_target/.gitted/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 create mode 100644 tests/resources/submod2_target/.gitted/refs/heads/master create mode 100644 tests/resources/submod2_target/README.txt create mode 100644 tests/resources/submod2_target/file_to_modify create mode 100644 tests/resources/submodules/.gitted/HEAD create mode 100644 tests/resources/submodules/.gitted/config create mode 100644 tests/resources/submodules/.gitted/description create mode 100644 tests/resources/submodules/.gitted/index create mode 100644 tests/resources/submodules/.gitted/info/exclude create mode 100644 tests/resources/submodules/.gitted/info/refs create mode 100644 tests/resources/submodules/.gitted/logs/HEAD create mode 100644 tests/resources/submodules/.gitted/logs/refs/heads/master create mode 100644 tests/resources/submodules/.gitted/objects/26/a3b32a9b7d97486c5557f5902e8ac94638145e create mode 100644 tests/resources/submodules/.gitted/objects/78/308c9251cf4eee8b25a76c7d2790c73d797357 create mode 100644 tests/resources/submodules/.gitted/objects/97/896810b3210244a62a82458b8e0819ecfc6850 create mode 100644 tests/resources/submodules/.gitted/objects/b6/0fd986699ba4e9e68bea07cf8e793f323ef888 create mode 100644 tests/resources/submodules/.gitted/objects/d5/f7fc3f74f7dec08280f370a975b112e8f60818 create mode 100644 tests/resources/submodules/.gitted/objects/e3/50052cc767cd1fcb37e84e9a89e701925be4ae create mode 100644 tests/resources/submodules/.gitted/objects/info/packs create mode 100644 tests/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx create mode 100644 tests/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack create mode 100644 tests/resources/submodules/.gitted/packed-refs create mode 100644 tests/resources/submodules/.gitted/refs/heads/master create mode 100644 tests/resources/submodules/added create mode 100644 tests/resources/submodules/gitmodules create mode 100644 tests/resources/submodules/ignored create mode 100644 tests/resources/submodules/modified create mode 100644 tests/resources/submodules/testrepo/.gitted/HEAD create mode 100644 tests/resources/submodules/testrepo/.gitted/config create mode 100644 tests/resources/submodules/testrepo/.gitted/description create mode 100644 tests/resources/submodules/testrepo/.gitted/index create mode 100644 tests/resources/submodules/testrepo/.gitted/info/exclude create mode 100644 tests/resources/submodules/testrepo/.gitted/logs/HEAD create mode 100644 tests/resources/submodules/testrepo/.gitted/logs/refs/heads/master create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/ae/90f12eea699729ed24555e40b9fd669da12a12 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/b6/361fc6a97178d8fc8639fdeed71c775ab52593 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/d6/c93164c249c8000205dd4ec5cbca1b516d487f create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/e7/b4ad382349ff96dd8199000580b9b1e2042eb0 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/f1/425cef211cc08caa31e7b545ffb232acb098c3 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/fd/093bff70906175335656e6ce6ae05783708765 create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx create mode 100644 tests/resources/submodules/testrepo/.gitted/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack create mode 100644 tests/resources/submodules/testrepo/.gitted/packed-refs create mode 100644 tests/resources/submodules/testrepo/.gitted/refs/heads/master create mode 100644 tests/resources/submodules/testrepo/.gitted/refs/remotes/origin/HEAD create mode 100644 tests/resources/submodules/testrepo/README create mode 100644 tests/resources/submodules/testrepo/branch_file.txt create mode 100644 tests/resources/submodules/testrepo/new.txt create mode 100644 tests/resources/submodules/unmodified create mode 100644 tests/resources/submodules/untracked create mode 100644 tests/resources/template/branches/.gitignore create mode 100644 tests/resources/template/description create mode 120000 tests/resources/template/hooks/link.sample create mode 100755 tests/resources/template/hooks/update.sample create mode 100644 tests/resources/template/info/exclude create mode 100644 tests/resources/testrepo.git/FETCH_HEAD create mode 100644 tests/resources/testrepo.git/HEAD create mode 100644 tests/resources/testrepo.git/HEAD_TRACKER create mode 100644 tests/resources/testrepo.git/config create mode 100644 tests/resources/testrepo.git/index create mode 100644 tests/resources/testrepo.git/logs/HEAD create mode 100644 tests/resources/testrepo.git/logs/refs/heads/br2 create mode 100644 tests/resources/testrepo.git/logs/refs/heads/master create mode 100644 tests/resources/testrepo.git/logs/refs/heads/not-good create mode 100644 tests/resources/testrepo.git/logs/refs/remotes/origin/HEAD create mode 100644 tests/resources/testrepo.git/logs/refs/remotes/test/master create mode 100644 tests/resources/testrepo.git/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 create mode 100644 tests/resources/testrepo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 create mode 100644 tests/resources/testrepo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 create mode 100644 tests/resources/testrepo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd create mode 100644 tests/resources/testrepo.git/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd create mode 100644 tests/resources/testrepo.git/objects/1b/8cbad43e867676df601306689fe7c3def5e689 create mode 100644 tests/resources/testrepo.git/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b create mode 100644 tests/resources/testrepo.git/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 create mode 100644 tests/resources/testrepo.git/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d create mode 100644 tests/resources/testrepo.git/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 create mode 100644 tests/resources/testrepo.git/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 create mode 100644 tests/resources/testrepo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc create mode 100644 tests/resources/testrepo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 create mode 100644 tests/resources/testrepo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 create mode 100644 tests/resources/testrepo.git/objects/4a/23e2e65ad4e31c4c9db7dc746650bfad082679 create mode 100644 tests/resources/testrepo.git/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea create mode 100644 tests/resources/testrepo.git/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 create mode 100644 tests/resources/testrepo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 create mode 100644 tests/resources/testrepo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a create mode 100644 tests/resources/testrepo.git/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af create mode 100644 tests/resources/testrepo.git/objects/7b/4384978d2493e851f9cca7858815fac9b10980 create mode 100644 tests/resources/testrepo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d create mode 100644 tests/resources/testrepo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 create mode 100644 tests/resources/testrepo.git/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe create mode 100644 tests/resources/testrepo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 create mode 100644 tests/resources/testrepo.git/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 create mode 100644 tests/resources/testrepo.git/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 create mode 100644 tests/resources/testrepo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a create mode 100644 tests/resources/testrepo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f create mode 100644 tests/resources/testrepo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 create mode 100644 tests/resources/testrepo.git/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd create mode 100644 tests/resources/testrepo.git/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 create mode 100644 tests/resources/testrepo.git/objects/ae/90f12eea699729ed24555e40b9fd669da12a12 create mode 100644 tests/resources/testrepo.git/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 create mode 100644 tests/resources/testrepo.git/objects/b6/361fc6a97178d8fc8639fdeed71c775ab52593 create mode 100644 tests/resources/testrepo.git/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 create mode 100644 tests/resources/testrepo.git/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd create mode 100644 tests/resources/testrepo.git/objects/d0/7b0f9a8c89f1d9e74dc4fce6421dec5ef8a659 create mode 100644 tests/resources/testrepo.git/objects/d6/c93164c249c8000205dd4ec5cbca1b516d487f create mode 100644 tests/resources/testrepo.git/objects/d7/1aab4f9b04b45ce09bcaa636a9be6231474759 create mode 100644 tests/resources/testrepo.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 tests/resources/testrepo.git/objects/e7/b4ad382349ff96dd8199000580b9b1e2042eb0 create mode 100644 tests/resources/testrepo.git/objects/f1/425cef211cc08caa31e7b545ffb232acb098c3 create mode 100644 tests/resources/testrepo.git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 create mode 100644 tests/resources/testrepo.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 create mode 100644 tests/resources/testrepo.git/objects/fd/093bff70906175335656e6ce6ae05783708765 create mode 100644 tests/resources/testrepo.git/objects/fd/4959ce7510db09d4d8217fa2d1780413e05a09 create mode 100644 tests/resources/testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx create mode 100644 tests/resources/testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack create mode 100644 tests/resources/testrepo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx create mode 100644 tests/resources/testrepo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack create mode 100644 tests/resources/testrepo.git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx create mode 100644 tests/resources/testrepo.git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack create mode 100644 tests/resources/testrepo.git/packed-refs create mode 100644 tests/resources/testrepo.git/refs/heads/br2 create mode 100644 tests/resources/testrepo.git/refs/heads/cannot-fetch create mode 100644 tests/resources/testrepo.git/refs/heads/chomped create mode 100644 tests/resources/testrepo.git/refs/heads/haacked create mode 100644 tests/resources/testrepo.git/refs/heads/master create mode 100644 tests/resources/testrepo.git/refs/heads/not-good create mode 100644 tests/resources/testrepo.git/refs/heads/packed-test create mode 100644 tests/resources/testrepo.git/refs/heads/subtrees create mode 100644 tests/resources/testrepo.git/refs/heads/test create mode 100644 tests/resources/testrepo.git/refs/heads/track-local create mode 100644 tests/resources/testrepo.git/refs/heads/trailing create mode 100644 tests/resources/testrepo.git/refs/notes/fanout create mode 100644 tests/resources/testrepo.git/refs/remotes/test/master create mode 100644 tests/resources/testrepo.git/refs/tags/annotated_tag_to_blob create mode 100644 tests/resources/testrepo.git/refs/tags/e90810b create mode 100644 tests/resources/testrepo.git/refs/tags/hard_tag create mode 100644 tests/resources/testrepo.git/refs/tags/point_to_blob create mode 100644 tests/resources/testrepo.git/refs/tags/taggerless create mode 100644 tests/resources/testrepo.git/refs/tags/test create mode 100644 tests/resources/testrepo.git/refs/tags/wrapped_tag create mode 100644 tests/resources/testrepo/.gitted/HEAD create mode 100644 tests/resources/testrepo/.gitted/HEAD_TRACKER create mode 100644 tests/resources/testrepo/.gitted/config create mode 100644 tests/resources/testrepo/.gitted/index create mode 100644 tests/resources/testrepo/.gitted/objects/09/9fabac3a9ea935598528c27f866e34089c2eff create mode 100644 tests/resources/testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 create mode 100644 tests/resources/testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e create mode 100644 tests/resources/testrepo/.gitted/objects/16/8e4ebd1c667499548ae12403b19b22a5c5e925 create mode 100644 tests/resources/testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 create mode 100644 tests/resources/testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd create mode 100644 tests/resources/testrepo/.gitted/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b create mode 100644 tests/resources/testrepo/.gitted/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d create mode 100644 tests/resources/testrepo/.gitted/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 create mode 100644 tests/resources/testrepo/.gitted/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc create mode 100644 tests/resources/testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 create mode 100644 tests/resources/testrepo/.gitted/objects/45/dd856fdd4d89b884c340ba0e047752d9b085d6 create mode 100644 tests/resources/testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 create mode 100644 tests/resources/testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 create mode 100644 tests/resources/testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 create mode 100644 tests/resources/testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc create mode 100644 tests/resources/testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 create mode 100644 tests/resources/testrepo/.gitted/objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 create mode 100644 tests/resources/testrepo/.gitted/objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e create mode 100644 tests/resources/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a create mode 100644 tests/resources/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af create mode 100644 tests/resources/testrepo/.gitted/objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a create mode 100644 tests/resources/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 create mode 100644 tests/resources/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d create mode 100644 tests/resources/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 create mode 100644 tests/resources/testrepo/.gitted/objects/87/380ae84009e9c503506c2f6143a4fc6c60bf80 create mode 100644 tests/resources/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 create mode 100644 tests/resources/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 create mode 100644 tests/resources/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a create mode 100644 tests/resources/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f create mode 100644 tests/resources/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 create mode 100644 tests/resources/testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd create mode 100644 tests/resources/testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 create mode 100644 tests/resources/testrepo/.gitted/objects/ae/90f12eea699729ed24555e40b9fd669da12a12 create mode 100644 tests/resources/testrepo/.gitted/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 create mode 100644 tests/resources/testrepo/.gitted/objects/b6/361fc6a97178d8fc8639fdeed71c775ab52593 create mode 100644 tests/resources/testrepo/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 create mode 100644 tests/resources/testrepo/.gitted/objects/c0/528fd6cc988c0a40ce0be11bc192fc8dc5346e create mode 100644 tests/resources/testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd create mode 100644 tests/resources/testrepo/.gitted/objects/cf/80f8de9f1185bf3a05f993f6121880dd0cfbc9 create mode 100644 tests/resources/testrepo/.gitted/objects/d5/2a8fe84ceedf260afe4f0287bbfca04a117e83 create mode 100644 tests/resources/testrepo/.gitted/objects/d6/c93164c249c8000205dd4ec5cbca1b516d487f create mode 100644 tests/resources/testrepo/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 tests/resources/testrepo/.gitted/objects/e7/b4ad382349ff96dd8199000580b9b1e2042eb0 create mode 100644 tests/resources/testrepo/.gitted/objects/f1/425cef211cc08caa31e7b545ffb232acb098c3 create mode 100644 tests/resources/testrepo/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 create mode 100644 tests/resources/testrepo/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92 create mode 100644 tests/resources/testrepo/.gitted/objects/fd/093bff70906175335656e6ce6ae05783708765 create mode 100644 tests/resources/testrepo/.gitted/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx create mode 100644 tests/resources/testrepo/.gitted/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack create mode 100644 tests/resources/testrepo/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx create mode 100644 tests/resources/testrepo/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack create mode 100644 tests/resources/testrepo/.gitted/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx create mode 100644 tests/resources/testrepo/.gitted/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack create mode 100644 tests/resources/testrepo/.gitted/packed-refs create mode 100644 tests/resources/testrepo/.gitted/refs/heads/br2 create mode 100644 tests/resources/testrepo/.gitted/refs/heads/dir create mode 100644 tests/resources/testrepo/.gitted/refs/heads/long-file-name create mode 100644 tests/resources/testrepo/.gitted/refs/heads/master create mode 100644 tests/resources/testrepo/.gitted/refs/heads/packed-test create mode 100644 tests/resources/testrepo/.gitted/refs/heads/subtrees create mode 100644 tests/resources/testrepo/.gitted/refs/heads/test create mode 100644 tests/resources/testrepo/.gitted/refs/tags/e90810b create mode 100644 tests/resources/testrepo/.gitted/refs/tags/foo/bar create mode 100644 tests/resources/testrepo/.gitted/refs/tags/foo/foo/bar create mode 100644 tests/resources/testrepo/.gitted/refs/tags/point_to_blob create mode 100644 tests/resources/testrepo/.gitted/refs/tags/test create mode 100644 tests/resources/testrepo2/.gitted/HEAD create mode 100644 tests/resources/testrepo2/.gitted/config create mode 100644 tests/resources/testrepo2/.gitted/description create mode 100644 tests/resources/testrepo2/.gitted/index create mode 100644 tests/resources/testrepo2/.gitted/info/exclude create mode 100644 tests/resources/testrepo2/.gitted/logs/HEAD create mode 100644 tests/resources/testrepo2/.gitted/logs/refs/heads/master create mode 100644 tests/resources/testrepo2/.gitted/logs/refs/remotes/origin/HEAD create mode 100644 tests/resources/testrepo2/.gitted/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d create mode 100644 tests/resources/testrepo2/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 create mode 100644 tests/resources/testrepo2/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 create mode 100644 tests/resources/testrepo2/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd create mode 100644 tests/resources/testrepo2/.gitted/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 create mode 100644 tests/resources/testrepo2/.gitted/objects/36/060c58702ed4c2a40832c51758d5344201d89a create mode 100644 tests/resources/testrepo2/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 create mode 100644 tests/resources/testrepo2/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 create mode 100644 tests/resources/testrepo2/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 create mode 100644 tests/resources/testrepo2/.gitted/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 create mode 100644 tests/resources/testrepo2/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a create mode 100644 tests/resources/testrepo2/.gitted/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 create mode 100644 tests/resources/testrepo2/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d create mode 100644 tests/resources/testrepo2/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 create mode 100644 tests/resources/testrepo2/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a create mode 100644 tests/resources/testrepo2/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f create mode 100644 tests/resources/testrepo2/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd create mode 100644 tests/resources/testrepo2/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 create mode 100644 tests/resources/testrepo2/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 create mode 100644 tests/resources/testrepo2/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd create mode 100644 tests/resources/testrepo2/.gitted/objects/c4/dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b create mode 100644 tests/resources/testrepo2/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 tests/resources/testrepo2/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 create mode 100644 tests/resources/testrepo2/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92 create mode 100644 tests/resources/testrepo2/.gitted/objects/fd/093bff70906175335656e6ce6ae05783708765 create mode 100644 tests/resources/testrepo2/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx create mode 100644 tests/resources/testrepo2/.gitted/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack create mode 100644 tests/resources/testrepo2/.gitted/packed-refs create mode 100644 tests/resources/testrepo2/.gitted/refs/heads/master create mode 100644 tests/resources/testrepo2/.gitted/refs/remotes/origin/HEAD create mode 100644 tests/resources/testrepo2/README create mode 100644 tests/resources/testrepo2/new.txt create mode 100644 tests/resources/testrepo2/subdir/README create mode 100644 tests/resources/testrepo2/subdir/new.txt create mode 100644 tests/resources/testrepo2/subdir/subdir2/README create mode 100644 tests/resources/testrepo2/subdir/subdir2/new.txt create mode 100644 tests/resources/twowaymerge.git/HEAD create mode 100644 tests/resources/twowaymerge.git/config create mode 100644 tests/resources/twowaymerge.git/description create mode 100644 tests/resources/twowaymerge.git/info/exclude create mode 100644 tests/resources/twowaymerge.git/objects/0c/8a3f1f3d5f421cf83048c7c73ee3b55a5e0f29 create mode 100644 tests/resources/twowaymerge.git/objects/10/2dce8e3081f398e4bdd9fd894dc85ac3ca6a67 create mode 100644 tests/resources/twowaymerge.git/objects/17/7d8634a28e26ec7819284752757ebe01a479d5 create mode 100644 tests/resources/twowaymerge.git/objects/1c/30b88f5f3ee66d78df6520a7de9e89b890818b create mode 100644 tests/resources/twowaymerge.git/objects/1f/4c0311a24b63f6fc209a59a1e404942d4a5006 create mode 100644 tests/resources/twowaymerge.git/objects/22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 create mode 100644 tests/resources/twowaymerge.git/objects/29/6e56023cdc034d2735fee8c0d85a659d1b07f4 create mode 100644 tests/resources/twowaymerge.git/objects/31/51880ae2b363f1c262cf98b750c1f169a0d432 create mode 100644 tests/resources/twowaymerge.git/objects/3b/287f8730c81d0b763c2d294618a5e32b67b4f8 create mode 100644 tests/resources/twowaymerge.git/objects/42/b7311aa626e712891940c1ec5d5cba201946a4 create mode 100644 tests/resources/twowaymerge.git/objects/49/6d6428b9cf92981dc9495211e6e1120fb6f2ba create mode 100644 tests/resources/twowaymerge.git/objects/59/b0cf7d74659e1cdb13305319d6d4ce2733c118 create mode 100644 tests/resources/twowaymerge.git/objects/6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f create mode 100644 tests/resources/twowaymerge.git/objects/6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 create mode 100644 tests/resources/twowaymerge.git/objects/76/5b32c65d38f04c4f287abda055818ec0f26912 create mode 100644 tests/resources/twowaymerge.git/objects/7b/8c336c45fc6895c1c60827260fe5d798e5d247 create mode 100644 tests/resources/twowaymerge.git/objects/82/bf9a1a10a4b25c1f14c9607b60970705e92545 create mode 100644 tests/resources/twowaymerge.git/objects/8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 create mode 100644 tests/resources/twowaymerge.git/objects/9a/40a2f11c191f180c47e54b11567cb3c1e89b30 create mode 100644 tests/resources/twowaymerge.git/objects/9b/219343610c88a1187c996d0dc58330b55cee28 create mode 100644 tests/resources/twowaymerge.git/objects/9f/e06a50f4d1634d6c6879854d01d80857388706 create mode 100644 tests/resources/twowaymerge.git/objects/a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 create mode 100644 tests/resources/twowaymerge.git/objects/a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 create mode 100644 tests/resources/twowaymerge.git/objects/a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c create mode 100644 tests/resources/twowaymerge.git/objects/bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 create mode 100644 tests/resources/twowaymerge.git/objects/c3/7a783c20d92ac92362a78a32860f7eebf938ef create mode 100644 tests/resources/twowaymerge.git/objects/cb/dd40facab1682754eb67f7a43f29e672903cf6 create mode 100644 tests/resources/twowaymerge.git/objects/cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 create mode 100644 tests/resources/twowaymerge.git/objects/d6/f10d549cb335b9e6d38afc1f0088be69b50494 create mode 100644 tests/resources/twowaymerge.git/objects/d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e create mode 100644 tests/resources/twowaymerge.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 tests/resources/twowaymerge.git/objects/ef/0488f0b722f0be8bcb90a7730ac7efafd1d694 create mode 100644 tests/resources/twowaymerge.git/objects/fc/f7e3f51c11d199ab7a78403ee4f9ccd028da25 create mode 100644 tests/resources/twowaymerge.git/refs/heads/first-branch create mode 100644 tests/resources/twowaymerge.git/refs/heads/master create mode 100644 tests/resources/twowaymerge.git/refs/heads/second-branch create mode 100644 tests/resources/typechanges/.gitted/HEAD create mode 100644 tests/resources/typechanges/.gitted/config create mode 100644 tests/resources/typechanges/.gitted/description create mode 100644 tests/resources/typechanges/.gitted/index create mode 100644 tests/resources/typechanges/.gitted/info/exclude create mode 100644 tests/resources/typechanges/.gitted/modules/b/HEAD create mode 100644 tests/resources/typechanges/.gitted/modules/b/config create mode 100644 tests/resources/typechanges/.gitted/modules/b/description create mode 100644 tests/resources/typechanges/.gitted/modules/b/index create mode 100644 tests/resources/typechanges/.gitted/modules/b/info/exclude create mode 100644 tests/resources/typechanges/.gitted/modules/b/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 create mode 100644 tests/resources/typechanges/.gitted/modules/b/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 create mode 100644 tests/resources/typechanges/.gitted/modules/b/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 create mode 100644 tests/resources/typechanges/.gitted/modules/b/objects/41/bd4bc3df978de695f67ace64c560913da11653 create mode 100644 tests/resources/typechanges/.gitted/modules/b/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 create mode 100644 tests/resources/typechanges/.gitted/modules/b/objects/5e/4963595a9774b90524d35a807169049de8ccad create mode 100644 tests/resources/typechanges/.gitted/modules/b/objects/6b/31c659545507c381e9cd34ec508f16c04e149e create mode 100644 tests/resources/typechanges/.gitted/modules/b/objects/73/ba924a80437097795ae839e66e187c55d3babf create mode 100644 tests/resources/typechanges/.gitted/modules/b/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a create mode 100644 tests/resources/typechanges/.gitted/modules/b/objects/78/9efbdadaa4a582778d4584385495559ea0994b create mode 100644 tests/resources/typechanges/.gitted/modules/b/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e create mode 100644 tests/resources/typechanges/.gitted/modules/b/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 create mode 100644 tests/resources/typechanges/.gitted/modules/b/packed-refs create mode 100644 tests/resources/typechanges/.gitted/modules/b/refs/heads/master create mode 100644 tests/resources/typechanges/.gitted/modules/b/refs/remotes/origin/HEAD create mode 100644 tests/resources/typechanges/.gitted/modules/d/HEAD create mode 100644 tests/resources/typechanges/.gitted/modules/d/config create mode 100644 tests/resources/typechanges/.gitted/modules/d/description create mode 100644 tests/resources/typechanges/.gitted/modules/d/index create mode 100644 tests/resources/typechanges/.gitted/modules/d/info/exclude create mode 100644 tests/resources/typechanges/.gitted/modules/d/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 create mode 100644 tests/resources/typechanges/.gitted/modules/d/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 create mode 100644 tests/resources/typechanges/.gitted/modules/d/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 create mode 100644 tests/resources/typechanges/.gitted/modules/d/objects/41/bd4bc3df978de695f67ace64c560913da11653 create mode 100644 tests/resources/typechanges/.gitted/modules/d/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 create mode 100644 tests/resources/typechanges/.gitted/modules/d/objects/5e/4963595a9774b90524d35a807169049de8ccad create mode 100644 tests/resources/typechanges/.gitted/modules/d/objects/6b/31c659545507c381e9cd34ec508f16c04e149e create mode 100644 tests/resources/typechanges/.gitted/modules/d/objects/73/ba924a80437097795ae839e66e187c55d3babf create mode 100644 tests/resources/typechanges/.gitted/modules/d/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a create mode 100644 tests/resources/typechanges/.gitted/modules/d/objects/78/9efbdadaa4a582778d4584385495559ea0994b create mode 100644 tests/resources/typechanges/.gitted/modules/d/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e create mode 100644 tests/resources/typechanges/.gitted/modules/d/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 create mode 100644 tests/resources/typechanges/.gitted/modules/d/packed-refs create mode 100644 tests/resources/typechanges/.gitted/modules/d/refs/heads/master create mode 100644 tests/resources/typechanges/.gitted/modules/d/refs/remotes/origin/HEAD create mode 100644 tests/resources/typechanges/.gitted/modules/e/HEAD create mode 100644 tests/resources/typechanges/.gitted/modules/e/config create mode 100644 tests/resources/typechanges/.gitted/modules/e/description create mode 100644 tests/resources/typechanges/.gitted/modules/e/index create mode 100644 tests/resources/typechanges/.gitted/modules/e/info/exclude create mode 100644 tests/resources/typechanges/.gitted/modules/e/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 create mode 100644 tests/resources/typechanges/.gitted/modules/e/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 create mode 100644 tests/resources/typechanges/.gitted/modules/e/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 create mode 100644 tests/resources/typechanges/.gitted/modules/e/objects/41/bd4bc3df978de695f67ace64c560913da11653 create mode 100644 tests/resources/typechanges/.gitted/modules/e/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 create mode 100644 tests/resources/typechanges/.gitted/modules/e/objects/5e/4963595a9774b90524d35a807169049de8ccad create mode 100644 tests/resources/typechanges/.gitted/modules/e/objects/6b/31c659545507c381e9cd34ec508f16c04e149e create mode 100644 tests/resources/typechanges/.gitted/modules/e/objects/73/ba924a80437097795ae839e66e187c55d3babf create mode 100644 tests/resources/typechanges/.gitted/modules/e/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a create mode 100644 tests/resources/typechanges/.gitted/modules/e/objects/78/9efbdadaa4a582778d4584385495559ea0994b create mode 100644 tests/resources/typechanges/.gitted/modules/e/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e create mode 100644 tests/resources/typechanges/.gitted/modules/e/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 create mode 100644 tests/resources/typechanges/.gitted/modules/e/packed-refs create mode 100644 tests/resources/typechanges/.gitted/modules/e/refs/heads/master create mode 100644 tests/resources/typechanges/.gitted/modules/e/refs/remotes/origin/HEAD create mode 100644 tests/resources/typechanges/.gitted/objects/0d/78578795b7ca49fd8df6c4b6d27c5c02d991d8 create mode 100644 tests/resources/typechanges/.gitted/objects/0e/7ed140b514b8cae23254cb8656fe1674403aff create mode 100644 tests/resources/typechanges/.gitted/objects/0f/f461da9689266f482d8f6654a4400b4e33c586 create mode 100644 tests/resources/typechanges/.gitted/objects/18/aa7e45bbe4c3cc24a0b079696c59d36675af97 create mode 100644 tests/resources/typechanges/.gitted/objects/1b/63caae4a5ca96f78e8dfefc376c6a39a142475 create mode 100644 tests/resources/typechanges/.gitted/objects/1e/abe82aa3b2365a394f6108f24435df6e193d02 create mode 100644 tests/resources/typechanges/.gitted/objects/42/061c01a1c70097d1e4579f29a5adf40abdec95 create mode 100644 tests/resources/typechanges/.gitted/objects/46/2838cee476a87e7cff32196b66fa18ed756592 create mode 100644 tests/resources/typechanges/.gitted/objects/63/499e4ea8e096b831515ceb1d5a7593e4d87ae5 create mode 100644 tests/resources/typechanges/.gitted/objects/68/1af94e10eaf262f3ab7cb9b8fd5f4158ba4d3e create mode 100644 tests/resources/typechanges/.gitted/objects/6a/9008602b811e69a9b7a2d83496f39a794fdeeb create mode 100644 tests/resources/typechanges/.gitted/objects/6e/ae26c90e8ccc4d16208972119c40635489c6f0 create mode 100644 tests/resources/typechanges/.gitted/objects/6f/39eabbb8a7541515e0d35971078bccb502e7e0 create mode 100644 tests/resources/typechanges/.gitted/objects/71/54d3083461536dfc71ad5542f3e65e723a06c4 create mode 100644 tests/resources/typechanges/.gitted/objects/75/56c1d893a4c0ca85ac8ac51de47ff399758729 create mode 100644 tests/resources/typechanges/.gitted/objects/76/fef844064c26d5e06c2508240dae661e7231b2 create mode 100644 tests/resources/typechanges/.gitted/objects/79/b9f23e85f55ea36a472a902e875bc1121a94cb create mode 100644 tests/resources/typechanges/.gitted/objects/85/28da0ea65eacf1f74f9ed6696adbac547963ad create mode 100644 tests/resources/typechanges/.gitted/objects/8b/3726b365824ad5a07c537247f4bc73ed7d37ea create mode 100644 tests/resources/typechanges/.gitted/objects/93/3e28c1c8a68838a763d250bdf0b2c6068289c3 create mode 100644 tests/resources/typechanges/.gitted/objects/96/2710fe5b4e453e9e827945b3487c525968ec4a create mode 100644 tests/resources/typechanges/.gitted/objects/96/6cf1b3598e195b31b2cde3784f9a19f0728a6f create mode 100644 tests/resources/typechanges/.gitted/objects/99/e8bab9ece009f0fba7eb41f850f4c12bedb9b7 create mode 100644 tests/resources/typechanges/.gitted/objects/9b/19edf33a03a0c59cdfc113bfa5c06179bf9b1a create mode 100644 tests/resources/typechanges/.gitted/objects/9b/db75b73836a99e3dbeea640a81de81031fdc29 create mode 100644 tests/resources/typechanges/.gitted/objects/9d/0235c7a7edc0889a18f97a42ee6db9fe688447 create mode 100644 tests/resources/typechanges/.gitted/objects/9e/ffc457877f109b2a4319e14bee613a15f2a00d create mode 100644 tests/resources/typechanges/.gitted/objects/a0/a9bad6f6f40325198f938a0e3ae981622d7707 create mode 100644 tests/resources/typechanges/.gitted/objects/b1/977dc4e573b812d4619754c98138c56999dc0d create mode 100644 tests/resources/typechanges/.gitted/objects/d7/5992dd02391e128dac332dcc78d649dd9ab095 create mode 100644 tests/resources/typechanges/.gitted/objects/da/e2709d638df52212b1f43ff61797ebfedfcc7c create mode 100644 tests/resources/typechanges/.gitted/objects/e1/152adcb9adf37ec551ada9ba377ab53aec3bad create mode 100644 tests/resources/typechanges/.gitted/objects/e4/ed436a9eb0f198cda722886a5f8d6d6c836b7b create mode 100644 tests/resources/typechanges/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 tests/resources/typechanges/.gitted/objects/f2/0b79342712e0b2315647cd8227a573fd3bc46e create mode 100644 tests/resources/typechanges/.gitted/objects/fd/e0147e3b59f381635a3b016e3fe6dacb70779d create mode 100644 tests/resources/typechanges/.gitted/refs/heads/master create mode 100644 tests/resources/typechanges/README.md create mode 100644 tests/resources/typechanges/gitmodules create mode 100644 tests/resources/unsymlinked.git/HEAD create mode 100644 tests/resources/unsymlinked.git/config create mode 100644 tests/resources/unsymlinked.git/description create mode 100644 tests/resources/unsymlinked.git/info/exclude create mode 100644 tests/resources/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf create mode 100644 tests/resources/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b create mode 100644 tests/resources/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c create mode 100644 tests/resources/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 create mode 100644 tests/resources/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c create mode 100644 tests/resources/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 create mode 100644 tests/resources/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d create mode 100644 tests/resources/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 create mode 100644 tests/resources/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 create mode 100644 tests/resources/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 create mode 100644 tests/resources/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 create mode 100644 tests/resources/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a create mode 100644 tests/resources/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 create mode 100644 tests/resources/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 create mode 100644 tests/resources/unsymlinked.git/refs/heads/exe-file create mode 100644 tests/resources/unsymlinked.git/refs/heads/master create mode 100644 tests/resources/unsymlinked.git/refs/heads/reg-file create mode 100644 tests/revwalk/basic.c create mode 100644 tests/revwalk/mergebase.c create mode 100644 tests/revwalk/signatureparsing.c create mode 100644 tests/revwalk/simplify.c create mode 100644 tests/stash/drop.c create mode 100644 tests/stash/foreach.c create mode 100644 tests/stash/save.c create mode 100644 tests/stash/stash_helpers.c create mode 100644 tests/stash/stash_helpers.h create mode 100644 tests/stash/submodules.c create mode 100644 tests/status/ignore.c create mode 100644 tests/status/renames.c create mode 100644 tests/status/single.c create mode 100644 tests/status/status_data.h create mode 100644 tests/status/status_helpers.c create mode 100644 tests/status/status_helpers.h create mode 100644 tests/status/submodules.c create mode 100644 tests/status/worktree.c create mode 100644 tests/status/worktree_init.c create mode 100644 tests/stress/diff.c create mode 100644 tests/submodule/lookup.c create mode 100644 tests/submodule/modify.c create mode 100644 tests/submodule/status.c create mode 100644 tests/submodule/submodule_helpers.c create mode 100644 tests/submodule/submodule_helpers.h create mode 100644 tests/threads/basic.c create mode 100644 tests/threads/refdb.c create mode 100644 tests/trace/trace.c create mode 100644 tests/valgrind-supp-mac.txt diff --git a/tests-clar/README.md b/tests-clar/README.md deleted file mode 100644 index 3aeaaf464..000000000 --- a/tests-clar/README.md +++ /dev/null @@ -1,22 +0,0 @@ -Writing Clar tests for libgit2 -============================== - -For information on the Clar testing framework and a detailed introduction -please visit: - -https://github.com/vmg/clar - - -* Write your modules and tests. Use good, meaningful names. - -* Make sure you actually build the tests by setting: - - cmake -DBUILD_CLAR=ON build/ - -* Test: - - ./build/libgit2_clar - -* Make sure everything is fine. - -* Send your pull request. That's it. diff --git a/tests-clar/attr/attr_expect.h b/tests-clar/attr/attr_expect.h deleted file mode 100644 index 70f1ab4f5..000000000 --- a/tests-clar/attr/attr_expect.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef __CLAR_TEST_ATTR_EXPECT__ -#define __CLAR_TEST_ATTR_EXPECT__ - -enum attr_expect_t { - EXPECT_FALSE, - EXPECT_TRUE, - EXPECT_UNDEFINED, - EXPECT_STRING -}; - -struct attr_expected { - const char *path; - const char *attr; - enum attr_expect_t expected; - const char *expected_str; -}; - -GIT_INLINE(void) attr_check_expected( - enum attr_expect_t expected, - const char *expected_str, - const char *name, - const char *value) -{ - switch (expected) { - case EXPECT_TRUE: - cl_assert_(GIT_ATTR_TRUE(value), name); - break; - - case EXPECT_FALSE: - cl_assert_(GIT_ATTR_FALSE(value), name); - break; - - case EXPECT_UNDEFINED: - cl_assert_(GIT_ATTR_UNSPECIFIED(value), name); - break; - - case EXPECT_STRING: - cl_assert_equal_s(expected_str, value); - break; - } -} - -#endif diff --git a/tests-clar/attr/file.c b/tests-clar/attr/file.c deleted file mode 100644 index 4eb1d22fe..000000000 --- a/tests-clar/attr/file.c +++ /dev/null @@ -1,224 +0,0 @@ -#include "clar_libgit2.h" -#include "attr_file.h" -#include "attr_expect.h" - -#define get_rule(X) ((git_attr_rule *)git_vector_get(&file->rules,(X))) -#define get_assign(R,Y) ((git_attr_assignment *)git_vector_get(&(R)->assigns,(Y))) - -void test_attr_file__simple_read(void) -{ - git_attr_file *file; - git_attr_assignment *assign; - git_attr_rule *rule; - - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr0"))); - - cl_assert_equal_s(cl_fixture("attr/attr0"), file->key + 2); - cl_assert(file->rules.length == 1); - - rule = get_rule(0); - cl_assert(rule != NULL); - cl_assert_equal_s("*", rule->match.pattern); - cl_assert(rule->match.length == 1); - cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_HASWILD) != 0); - - cl_assert(rule->assigns.length == 1); - assign = get_assign(rule, 0); - cl_assert(assign != NULL); - cl_assert_equal_s("binary", assign->name); - cl_assert(GIT_ATTR_TRUE(assign->value)); - - git_attr_file__free(file); -} - -void test_attr_file__match_variants(void) -{ - git_attr_file *file; - git_attr_rule *rule; - git_attr_assignment *assign; - - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr1"))); - - cl_assert_equal_s(cl_fixture("attr/attr1"), file->key + 2); - cl_assert(file->rules.length == 10); - - /* let's do a thorough check of this rule, then just verify - * the things that are unique for the later rules - */ - rule = get_rule(0); - cl_assert(rule); - cl_assert_equal_s("pat0", rule->match.pattern); - cl_assert(rule->match.length == strlen("pat0")); - cl_assert(rule->assigns.length == 1); - assign = get_assign(rule,0); - cl_assert_equal_s("attr0", assign->name); - cl_assert(assign->name_hash == git_attr_file__name_hash(assign->name)); - cl_assert(GIT_ATTR_TRUE(assign->value)); - - rule = get_rule(1); - cl_assert_equal_s("pat1", rule->match.pattern); - cl_assert(rule->match.length == strlen("pat1")); - cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_NEGATIVE) != 0); - - rule = get_rule(2); - cl_assert_equal_s("pat2", rule->match.pattern); - cl_assert(rule->match.length == strlen("pat2")); - cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_DIRECTORY) != 0); - - rule = get_rule(3); - cl_assert_equal_s("pat3dir/pat3file", rule->match.pattern); - cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_FULLPATH) != 0); - - rule = get_rule(4); - cl_assert_equal_s("pat4.*", rule->match.pattern); - cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_HASWILD) != 0); - - rule = get_rule(5); - cl_assert_equal_s("*.pat5", rule->match.pattern); - cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_HASWILD) != 0); - - rule = get_rule(7); - cl_assert_equal_s("pat7[a-e]??[xyz]", rule->match.pattern); - cl_assert(rule->assigns.length == 1); - cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_HASWILD) != 0); - assign = get_assign(rule,0); - cl_assert_equal_s("attr7", assign->name); - cl_assert(GIT_ATTR_TRUE(assign->value)); - - rule = get_rule(8); - cl_assert_equal_s("pat8 with spaces", rule->match.pattern); - cl_assert(rule->match.length == strlen("pat8 with spaces")); - - rule = get_rule(9); - cl_assert_equal_s("pat9", rule->match.pattern); - - git_attr_file__free(file); -} - -static void check_one_assign( - git_attr_file *file, - int rule_idx, - int assign_idx, - const char *pattern, - const char *name, - enum attr_expect_t expected, - const char *expected_str) -{ - git_attr_rule *rule = get_rule(rule_idx); - git_attr_assignment *assign = get_assign(rule, assign_idx); - - cl_assert_equal_s(pattern, rule->match.pattern); - cl_assert(rule->assigns.length == 1); - cl_assert_equal_s(name, assign->name); - cl_assert(assign->name_hash == git_attr_file__name_hash(assign->name)); - - attr_check_expected(expected, expected_str, assign->name, assign->value); -} - -void test_attr_file__assign_variants(void) -{ - git_attr_file *file; - git_attr_rule *rule; - git_attr_assignment *assign; - - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr2"))); - - cl_assert_equal_s(cl_fixture("attr/attr2"), file->key + 2); - cl_assert(file->rules.length == 11); - - check_one_assign(file, 0, 0, "pat0", "simple", EXPECT_TRUE, NULL); - check_one_assign(file, 1, 0, "pat1", "neg", EXPECT_FALSE, NULL); - check_one_assign(file, 2, 0, "*", "notundef", EXPECT_TRUE, NULL); - check_one_assign(file, 3, 0, "pat2", "notundef", EXPECT_UNDEFINED, NULL); - check_one_assign(file, 4, 0, "pat3", "assigned", EXPECT_STRING, "test-value"); - check_one_assign(file, 5, 0, "pat4", "rule-with-more-chars", EXPECT_STRING, "value-with-more-chars"); - check_one_assign(file, 6, 0, "pat5", "empty", EXPECT_TRUE, NULL); - check_one_assign(file, 7, 0, "pat6", "negempty", EXPECT_FALSE, NULL); - - rule = get_rule(8); - cl_assert_equal_s("pat7", rule->match.pattern); - cl_assert(rule->assigns.length == 5); - /* assignments will be sorted by hash value, so we have to do - * lookups by search instead of by position - */ - assign = git_attr_rule__lookup_assignment(rule, "multiple"); - cl_assert(assign); - cl_assert_equal_s("multiple", assign->name); - cl_assert(GIT_ATTR_TRUE(assign->value)); - assign = git_attr_rule__lookup_assignment(rule, "single"); - cl_assert(assign); - cl_assert_equal_s("single", assign->name); - cl_assert(GIT_ATTR_FALSE(assign->value)); - assign = git_attr_rule__lookup_assignment(rule, "values"); - cl_assert(assign); - cl_assert_equal_s("values", assign->name); - cl_assert_equal_s("1", assign->value); - assign = git_attr_rule__lookup_assignment(rule, "also"); - cl_assert(assign); - cl_assert_equal_s("also", assign->name); - cl_assert_equal_s("a-really-long-value/*", assign->value); - assign = git_attr_rule__lookup_assignment(rule, "happy"); - cl_assert(assign); - cl_assert_equal_s("happy", assign->name); - cl_assert_equal_s("yes!", assign->value); - assign = git_attr_rule__lookup_assignment(rule, "other"); - cl_assert(!assign); - - rule = get_rule(9); - cl_assert_equal_s("pat8", rule->match.pattern); - cl_assert(rule->assigns.length == 2); - assign = git_attr_rule__lookup_assignment(rule, "again"); - cl_assert(assign); - cl_assert_equal_s("again", assign->name); - cl_assert(GIT_ATTR_TRUE(assign->value)); - assign = git_attr_rule__lookup_assignment(rule, "another"); - cl_assert(assign); - cl_assert_equal_s("another", assign->name); - cl_assert_equal_s("12321", assign->value); - - check_one_assign(file, 10, 0, "pat9", "at-eof", EXPECT_FALSE, NULL); - - git_attr_file__free(file); -} - -void test_attr_file__check_attr_examples(void) -{ - git_attr_file *file; - git_attr_rule *rule; - git_attr_assignment *assign; - - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr3"))); - cl_assert_equal_s(cl_fixture("attr/attr3"), file->key + 2); - cl_assert(file->rules.length == 3); - - rule = get_rule(0); - cl_assert_equal_s("*.java", rule->match.pattern); - cl_assert(rule->assigns.length == 3); - assign = git_attr_rule__lookup_assignment(rule, "diff"); - cl_assert_equal_s("diff", assign->name); - cl_assert_equal_s("java", assign->value); - assign = git_attr_rule__lookup_assignment(rule, "crlf"); - cl_assert_equal_s("crlf", assign->name); - cl_assert(GIT_ATTR_FALSE(assign->value)); - assign = git_attr_rule__lookup_assignment(rule, "myAttr"); - cl_assert_equal_s("myAttr", assign->name); - cl_assert(GIT_ATTR_TRUE(assign->value)); - assign = git_attr_rule__lookup_assignment(rule, "missing"); - cl_assert(assign == NULL); - - rule = get_rule(1); - cl_assert_equal_s("NoMyAttr.java", rule->match.pattern); - cl_assert(rule->assigns.length == 1); - assign = get_assign(rule, 0); - cl_assert_equal_s("myAttr", assign->name); - cl_assert(GIT_ATTR_UNSPECIFIED(assign->value)); - - rule = get_rule(2); - cl_assert_equal_s("README", rule->match.pattern); - cl_assert(rule->assigns.length == 1); - assign = get_assign(rule, 0); - cl_assert_equal_s("caveat", assign->name); - cl_assert_equal_s("unspecified", assign->value); - - git_attr_file__free(file); -} diff --git a/tests-clar/attr/flags.c b/tests-clar/attr/flags.c deleted file mode 100644 index 80c6e1171..000000000 --- a/tests-clar/attr/flags.c +++ /dev/null @@ -1,108 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/attr.h" - -void test_attr_flags__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_attr_flags__bare(void) -{ - git_repository *repo = cl_git_sandbox_init("testrepo.git"); - const char *value; - - cl_assert(git_repository_is_bare(repo)); - - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM, "README.md", "diff")); - cl_assert(GIT_ATTR_UNSPECIFIED(value)); -} - -void test_attr_flags__index_vs_workdir(void) -{ - git_repository *repo = cl_git_sandbox_init("attr_index"); - const char *value; - - cl_assert(!git_repository_is_bare(repo)); - - /* wd then index */ - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, - "README.md", "bar")); - cl_assert(GIT_ATTR_FALSE(value)); - - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, - "README.md", "blargh")); - cl_assert_equal_s(value, "goop"); - - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, - "README.txt", "foo")); - cl_assert(GIT_ATTR_FALSE(value)); - - /* index then wd */ - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, - "README.md", "bar")); - cl_assert(GIT_ATTR_TRUE(value)); - - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, - "README.md", "blargh")); - cl_assert_equal_s(value, "garble"); - - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, - "README.txt", "foo")); - cl_assert(GIT_ATTR_TRUE(value)); -} - -void test_attr_flags__subdir(void) -{ - git_repository *repo = cl_git_sandbox_init("attr_index"); - const char *value; - - /* wd then index */ - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, - "sub/sub/README.md", "bar")); - cl_assert_equal_s(value, "1234"); - - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, - "sub/sub/README.txt", "another")); - cl_assert_equal_s(value, "one"); - - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, - "sub/sub/README.txt", "again")); - cl_assert(GIT_ATTR_TRUE(value)); - - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, - "sub/sub/README.txt", "beep")); - cl_assert_equal_s(value, "10"); - - /* index then wd */ - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, - "sub/sub/README.md", "bar")); - cl_assert_equal_s(value, "1337"); - - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, - "sub/sub/README.txt", "another")); - cl_assert_equal_s(value, "one"); - - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, - "sub/sub/README.txt", "again")); - cl_assert(GIT_ATTR_TRUE(value)); - - cl_git_pass(git_attr_get( - &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, - "sub/sub/README.txt", "beep")); - cl_assert_equal_s(value, "5"); -} - diff --git a/tests-clar/attr/ignore.c b/tests-clar/attr/ignore.c deleted file mode 100644 index 0f945ebf6..000000000 --- a/tests-clar/attr/ignore.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" -#include "path.h" -#include "fileops.h" - -static git_repository *g_repo = NULL; - -void test_attr_ignore__initialize(void) -{ - g_repo = cl_git_sandbox_init("attr"); -} - -void test_attr_ignore__cleanup(void) -{ - cl_git_sandbox_cleanup(); - g_repo = NULL; -} - -void assert_is_ignored(bool expected, const char *filepath) -{ - int is_ignored; - - cl_git_pass(git_ignore_path_is_ignored(&is_ignored, g_repo, filepath)); - cl_assert_equal_b(expected, is_ignored); -} - -void test_attr_ignore__honor_temporary_rules(void) -{ - cl_git_rewritefile("attr/.gitignore", "/NewFolder\n/NewFolder/NewFolder"); - - assert_is_ignored(false, "File.txt"); - assert_is_ignored(true, "NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); -} - -void test_attr_ignore__allow_root(void) -{ - cl_git_rewritefile("attr/.gitignore", "/"); - - assert_is_ignored(false, "File.txt"); - assert_is_ignored(false, "NewFolder"); - assert_is_ignored(false, "NewFolder/NewFolder"); - assert_is_ignored(false, "NewFolder/NewFolder/File.txt"); -} - -void test_attr_ignore__ignore_root(void) -{ - cl_git_rewritefile("attr/.gitignore", "/\n\n/NewFolder\n/NewFolder/NewFolder"); - - assert_is_ignored(false, "File.txt"); - assert_is_ignored(true, "NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); -} - - -void test_attr_ignore__skip_gitignore_directory(void) -{ - cl_git_rewritefile("attr/.git/info/exclude", "/NewFolder\n/NewFolder/NewFolder"); - p_unlink("attr/.gitignore"); - cl_assert(!git_path_exists("attr/.gitignore")); - p_mkdir("attr/.gitignore", 0777); - cl_git_mkfile("attr/.gitignore/garbage.txt", "new_file\n"); - - assert_is_ignored(false, "File.txt"); - assert_is_ignored(true, "NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder"); - assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); -} - -void test_attr_ignore__expand_tilde_to_homedir(void) -{ - git_buf path = GIT_BUF_INIT; - git_config *cfg; - - assert_is_ignored(false, "example.global_with_tilde"); - - /* construct fake home with fake global excludes */ - - cl_must_pass(p_mkdir("home", 0777)); - cl_git_pass(git_path_prettify(&path, "home", NULL)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); - - cl_git_mkfile("home/globalexcludes", "# found me\n*.global_with_tilde\n"); - - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_set_string(cfg, "core.excludesfile", "~/globalexcludes")); - git_config_free(cfg); - - git_attr_cache_flush(g_repo); /* must reset to pick up change */ - - assert_is_ignored(true, "example.global_with_tilde"); - - cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES)); - - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, NULL)); - - git_buf_free(&path); -} diff --git a/tests-clar/attr/lookup.c b/tests-clar/attr/lookup.c deleted file mode 100644 index 200bdd2c7..000000000 --- a/tests-clar/attr/lookup.c +++ /dev/null @@ -1,262 +0,0 @@ -#include "clar_libgit2.h" -#include "attr_file.h" - -#include "attr_expect.h" - -void test_attr_lookup__simple(void) -{ - git_attr_file *file; - git_attr_path path; - const char *value = NULL; - - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr0"))); - cl_assert_equal_s(cl_fixture("attr/attr0"), file->key + 2); - cl_assert(file->rules.length == 1); - - cl_git_pass(git_attr_path__init(&path, "test", NULL)); - cl_assert_equal_s("test", path.path); - cl_assert_equal_s("test", path.basename); - cl_assert(!path.is_dir); - - cl_git_pass(git_attr_file__lookup_one(file,&path,"binary",&value)); - cl_assert(GIT_ATTR_TRUE(value)); - - cl_git_pass(git_attr_file__lookup_one(file,&path,"missing",&value)); - cl_assert(!value); - - git_attr_path__free(&path); - git_attr_file__free(file); -} - -static void run_test_cases(git_attr_file *file, struct attr_expected *cases, int force_dir) -{ - git_attr_path path; - const char *value = NULL; - struct attr_expected *c; - int error; - - for (c = cases; c->path != NULL; c++) { - cl_git_pass(git_attr_path__init(&path, c->path, NULL)); - - if (force_dir) - path.is_dir = 1; - - error = git_attr_file__lookup_one(file,&path,c->attr,&value); - cl_git_pass(error); - - attr_check_expected(c->expected, c->expected_str, c->attr, value); - - git_attr_path__free(&path); - } -} - -void test_attr_lookup__match_variants(void) -{ - git_attr_file *file; - git_attr_path path; - - struct attr_expected dir_cases[] = { - { "pat2", "attr2", EXPECT_TRUE, NULL }, - { "/testing/for/pat2", "attr2", EXPECT_TRUE, NULL }, - { "/not/pat2/yousee", "attr2", EXPECT_UNDEFINED, NULL }, - { "/fun/fun/fun/pat4.dir", "attr4", EXPECT_TRUE, NULL }, - { "foo.pat5", "attr5", EXPECT_TRUE, NULL }, - { NULL, NULL, 0, NULL } - }; - - struct attr_expected cases[] = { - /* pat0 -> simple match */ - { "pat0", "attr0", EXPECT_TRUE, NULL }, - { "/testing/for/pat0", "attr0", EXPECT_TRUE, NULL }, - { "relative/to/pat0", "attr0", EXPECT_TRUE, NULL }, - { "this-contains-pat0-inside", "attr0", EXPECT_UNDEFINED, NULL }, - { "this-aint-right", "attr0", EXPECT_UNDEFINED, NULL }, - { "/this/pat0/dont/match", "attr0", EXPECT_UNDEFINED, NULL }, - /* negative match */ - { "pat0", "attr1", EXPECT_TRUE, NULL }, - { "pat1", "attr1", EXPECT_UNDEFINED, NULL }, - { "/testing/for/pat1", "attr1", EXPECT_UNDEFINED, NULL }, - { "/testing/for/pat0", "attr1", EXPECT_TRUE, NULL }, - { "/testing/for/pat1/inside", "attr1", EXPECT_TRUE, NULL }, - { "misc", "attr1", EXPECT_TRUE, NULL }, - /* dir match */ - { "pat2", "attr2", EXPECT_UNDEFINED, NULL }, - { "/testing/for/pat2", "attr2", EXPECT_UNDEFINED, NULL }, - { "/not/pat2/yousee", "attr2", EXPECT_UNDEFINED, NULL }, - /* path match */ - { "pat3file", "attr3", EXPECT_UNDEFINED, NULL }, - { "/pat3dir/pat3file", "attr3", EXPECT_TRUE, NULL }, - { "pat3dir/pat3file", "attr3", EXPECT_TRUE, NULL }, - /* pattern* match */ - { "pat4.txt", "attr4", EXPECT_TRUE, NULL }, - { "/fun/fun/fun/pat4.c", "attr4", EXPECT_TRUE, NULL }, - { "pat4.", "attr4", EXPECT_TRUE, NULL }, - { "pat4", "attr4", EXPECT_UNDEFINED, NULL }, - /* *pattern match */ - { "foo.pat5", "attr5", EXPECT_TRUE, NULL }, - { "/this/is/ok.pat5", "attr5", EXPECT_TRUE, NULL }, - { "/this/is/bad.pat5/yousee.txt", "attr5", EXPECT_UNDEFINED, NULL }, - { "foo.pat5", "attr100", EXPECT_UNDEFINED, NULL }, - /* glob match with slashes */ - { "foo.pat6", "attr6", EXPECT_UNDEFINED, NULL }, - { "pat6/pat6/foobar.pat6", "attr6", EXPECT_TRUE, NULL }, - { "pat6/pat6/.pat6", "attr6", EXPECT_TRUE, NULL }, - { "pat6/pat6/extra/foobar.pat6", "attr6", EXPECT_UNDEFINED, NULL }, - { "/prefix/pat6/pat6/foobar.pat6", "attr6", EXPECT_UNDEFINED, NULL }, - { "/pat6/pat6/foobar.pat6", "attr6", EXPECT_TRUE, NULL }, - /* complex pattern */ - { "pat7a12z", "attr7", EXPECT_TRUE, NULL }, - { "pat7e__x", "attr7", EXPECT_TRUE, NULL }, - { "pat7b/1y", "attr7", EXPECT_UNDEFINED, NULL }, /* ? does not match / */ - { "pat7e_x", "attr7", EXPECT_UNDEFINED, NULL }, - { "pat7aaaa", "attr7", EXPECT_UNDEFINED, NULL }, - { "pat7zzzz", "attr7", EXPECT_UNDEFINED, NULL }, - { "/this/can/be/anything/pat7a12z", "attr7", EXPECT_TRUE, NULL }, - { "but/it/still/must/match/pat7aaaa", "attr7", EXPECT_UNDEFINED, NULL }, - { "pat7aaay.fail", "attr7", EXPECT_UNDEFINED, NULL }, - /* pattern with spaces */ - { "pat8 with spaces", "attr8", EXPECT_TRUE, NULL }, - { "/gotta love/pat8 with spaces", "attr8", EXPECT_TRUE, NULL }, - { "failing pat8 with spaces", "attr8", EXPECT_UNDEFINED, NULL }, - { "spaces", "attr8", EXPECT_UNDEFINED, NULL }, - /* pattern at eof */ - { "pat9", "attr9", EXPECT_TRUE, NULL }, - { "/eof/pat9", "attr9", EXPECT_TRUE, NULL }, - { "pat", "attr9", EXPECT_UNDEFINED, NULL }, - { "at9", "attr9", EXPECT_UNDEFINED, NULL }, - { "pat9.fail", "attr9", EXPECT_UNDEFINED, NULL }, - /* sentinel at end */ - { NULL, NULL, 0, NULL } - }; - - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr1"))); - cl_assert_equal_s(cl_fixture("attr/attr1"), file->key + 2); - cl_assert(file->rules.length == 10); - - cl_git_pass(git_attr_path__init(&path, "/testing/for/pat0", NULL)); - cl_assert_equal_s("pat0", path.basename); - - run_test_cases(file, cases, 0); - run_test_cases(file, dir_cases, 1); - - git_attr_file__free(file); - git_attr_path__free(&path); -} - -void test_attr_lookup__assign_variants(void) -{ - git_attr_file *file; - - struct attr_expected cases[] = { - /* pat0 -> simple assign */ - { "pat0", "simple", EXPECT_TRUE, NULL }, - { "/testing/pat0", "simple", EXPECT_TRUE, NULL }, - { "pat0", "fail", EXPECT_UNDEFINED, NULL }, - { "/testing/pat0", "fail", EXPECT_UNDEFINED, NULL }, - /* negative assign */ - { "pat1", "neg", EXPECT_FALSE, NULL }, - { "/testing/pat1", "neg", EXPECT_FALSE, NULL }, - { "pat1", "fail", EXPECT_UNDEFINED, NULL }, - { "/testing/pat1", "fail", EXPECT_UNDEFINED, NULL }, - /* forced undef */ - { "pat1", "notundef", EXPECT_TRUE, NULL }, - { "pat2", "notundef", EXPECT_UNDEFINED, NULL }, - { "/lead/in/pat1", "notundef", EXPECT_TRUE, NULL }, - { "/lead/in/pat2", "notundef", EXPECT_UNDEFINED, NULL }, - /* assign value */ - { "pat3", "assigned", EXPECT_STRING, "test-value" }, - { "pat3", "notassigned", EXPECT_UNDEFINED, NULL }, - /* assign value */ - { "pat4", "rule-with-more-chars", EXPECT_STRING, "value-with-more-chars" }, - { "pat4", "notassigned-rule-with-more-chars", EXPECT_UNDEFINED, NULL }, - /* empty assignments */ - { "pat5", "empty", EXPECT_TRUE, NULL }, - { "pat6", "negempty", EXPECT_FALSE, NULL }, - /* multiple assignment */ - { "pat7", "multiple", EXPECT_TRUE, NULL }, - { "pat7", "single", EXPECT_FALSE, NULL }, - { "pat7", "values", EXPECT_STRING, "1" }, - { "pat7", "also", EXPECT_STRING, "a-really-long-value/*" }, - { "pat7", "happy", EXPECT_STRING, "yes!" }, - { "pat8", "again", EXPECT_TRUE, NULL }, - { "pat8", "another", EXPECT_STRING, "12321" }, - /* bad assignment */ - { "patbad0", "simple", EXPECT_UNDEFINED, NULL }, - { "patbad0", "notundef", EXPECT_TRUE, NULL }, - { "patbad1", "simple", EXPECT_UNDEFINED, NULL }, - /* eof assignment */ - { "pat9", "at-eof", EXPECT_FALSE, NULL }, - /* sentinel at end */ - { NULL, NULL, 0, NULL } - }; - - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr2"))); - cl_assert(file->rules.length == 11); - - run_test_cases(file, cases, 0); - - git_attr_file__free(file); -} - -void test_attr_lookup__check_attr_examples(void) -{ - git_attr_file *file; - - struct attr_expected cases[] = { - { "foo.java", "diff", EXPECT_STRING, "java" }, - { "foo.java", "crlf", EXPECT_FALSE, NULL }, - { "foo.java", "myAttr", EXPECT_TRUE, NULL }, - { "foo.java", "other", EXPECT_UNDEFINED, NULL }, - { "/prefix/dir/foo.java", "diff", EXPECT_STRING, "java" }, - { "/prefix/dir/foo.java", "crlf", EXPECT_FALSE, NULL }, - { "/prefix/dir/foo.java", "myAttr", EXPECT_TRUE, NULL }, - { "/prefix/dir/foo.java", "other", EXPECT_UNDEFINED, NULL }, - { "NoMyAttr.java", "crlf", EXPECT_FALSE, NULL }, - { "NoMyAttr.java", "myAttr", EXPECT_UNDEFINED, NULL }, - { "NoMyAttr.java", "other", EXPECT_UNDEFINED, NULL }, - { "/prefix/dir/NoMyAttr.java", "crlf", EXPECT_FALSE, NULL }, - { "/prefix/dir/NoMyAttr.java", "myAttr", EXPECT_UNDEFINED, NULL }, - { "/prefix/dir/NoMyAttr.java", "other", EXPECT_UNDEFINED, NULL }, - { "README", "caveat", EXPECT_STRING, "unspecified" }, - { "/specific/path/README", "caveat", EXPECT_STRING, "unspecified" }, - { "README", "missing", EXPECT_UNDEFINED, NULL }, - { "/specific/path/README", "missing", EXPECT_UNDEFINED, NULL }, - /* sentinel at end */ - { NULL, NULL, 0, NULL } - }; - - cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr3"))); - cl_assert(file->rules.length == 3); - - run_test_cases(file, cases, 0); - - git_attr_file__free(file); -} - -void test_attr_lookup__from_buffer(void) -{ - git_attr_file *file; - - struct attr_expected cases[] = { - { "abc", "foo", EXPECT_TRUE, NULL }, - { "abc", "bar", EXPECT_TRUE, NULL }, - { "abc", "baz", EXPECT_TRUE, NULL }, - { "aaa", "foo", EXPECT_TRUE, NULL }, - { "aaa", "bar", EXPECT_UNDEFINED, NULL }, - { "aaa", "baz", EXPECT_TRUE, NULL }, - { "qqq", "foo", EXPECT_UNDEFINED, NULL }, - { "qqq", "bar", EXPECT_UNDEFINED, NULL }, - { "qqq", "baz", EXPECT_TRUE, NULL }, - { NULL, NULL, 0, NULL } - }; - - cl_git_pass(git_attr_file__new(&file, 0, NULL, NULL)); - - cl_git_pass(git_attr_file__parse_buffer(NULL, NULL, "a* foo\nabc bar\n* baz", file)); - - cl_assert(file->rules.length == 3); - - run_test_cases(file, cases, 0); - - git_attr_file__free(file); -} diff --git a/tests-clar/attr/repo.c b/tests-clar/attr/repo.c deleted file mode 100644 index ef2ad5ce9..000000000 --- a/tests-clar/attr/repo.c +++ /dev/null @@ -1,310 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "git2/attr.h" -#include "attr.h" - -#include "attr_expect.h" - -static git_repository *g_repo = NULL; - -void test_attr_repo__initialize(void) -{ - /* Before each test, instantiate the attr repo from the fixtures and - * rename the .gitted to .git so it is a repo with a working dir. - * Also rename gitattributes to .gitattributes, because it contains - * macro definitions which are only allowed in the root. - */ - g_repo = cl_git_sandbox_init("attr"); -} - -void test_attr_repo__cleanup(void) -{ - cl_git_sandbox_cleanup(); - g_repo = NULL; -} - -void test_attr_repo__get_one(void) -{ - struct attr_expected test_cases[] = { - { "root_test1", "repoattr", EXPECT_TRUE, NULL }, - { "root_test1", "rootattr", EXPECT_TRUE, NULL }, - { "root_test1", "missingattr", EXPECT_UNDEFINED, NULL }, - { "root_test1", "subattr", EXPECT_UNDEFINED, NULL }, - { "root_test1", "negattr", EXPECT_UNDEFINED, NULL }, - { "root_test2", "repoattr", EXPECT_TRUE, NULL }, - { "root_test2", "rootattr", EXPECT_FALSE, NULL }, - { "root_test2", "missingattr", EXPECT_UNDEFINED, NULL }, - { "root_test2", "multiattr", EXPECT_FALSE, NULL }, - { "root_test3", "repoattr", EXPECT_TRUE, NULL }, - { "root_test3", "rootattr", EXPECT_UNDEFINED, NULL }, - { "root_test3", "multiattr", EXPECT_STRING, "3" }, - { "root_test3", "multi2", EXPECT_UNDEFINED, NULL }, - { "sub/subdir_test1", "repoattr", EXPECT_TRUE, NULL }, - { "sub/subdir_test1", "rootattr", EXPECT_TRUE, NULL }, - { "sub/subdir_test1", "missingattr", EXPECT_UNDEFINED, NULL }, - { "sub/subdir_test1", "subattr", EXPECT_STRING, "yes" }, - { "sub/subdir_test1", "negattr", EXPECT_FALSE, NULL }, - { "sub/subdir_test1", "another", EXPECT_UNDEFINED, NULL }, - { "sub/subdir_test2.txt", "repoattr", EXPECT_TRUE, NULL }, - { "sub/subdir_test2.txt", "rootattr", EXPECT_TRUE, NULL }, - { "sub/subdir_test2.txt", "missingattr", EXPECT_UNDEFINED, NULL }, - { "sub/subdir_test2.txt", "subattr", EXPECT_STRING, "yes" }, - { "sub/subdir_test2.txt", "negattr", EXPECT_FALSE, NULL }, - { "sub/subdir_test2.txt", "another", EXPECT_STRING, "zero" }, - { "sub/subdir_test2.txt", "reposub", EXPECT_TRUE, NULL }, - { "sub/sub/subdir.txt", "another", EXPECT_STRING, "one" }, - { "sub/sub/subdir.txt", "reposubsub", EXPECT_TRUE, NULL }, - { "sub/sub/subdir.txt", "reposub", EXPECT_UNDEFINED, NULL }, - { "does-not-exist", "foo", EXPECT_STRING, "yes" }, - { "sub/deep/file", "deepdeep", EXPECT_TRUE, NULL }, - { "sub/sub/d/no", "test", EXPECT_STRING, "a/b/d/*" }, - { "sub/sub/d/yes", "test", EXPECT_UNDEFINED, NULL }, - { NULL, NULL, 0, NULL } - }, *scan; - - for (scan = test_cases; scan->path != NULL; scan++) { - const char *value; - cl_git_pass(git_attr_get(&value, g_repo, 0, scan->path, scan->attr)); - attr_check_expected(scan->expected, scan->expected_str, scan->attr, value); - } - - cl_assert(git_attr_cache__is_cached(g_repo, 0, ".git/info/attributes")); - cl_assert(git_attr_cache__is_cached(g_repo, 0, ".gitattributes")); - cl_assert(git_attr_cache__is_cached(g_repo, 0, "sub/.gitattributes")); -} - -void test_attr_repo__get_many(void) -{ - const char *names[4] = { "repoattr", "rootattr", "missingattr", "subattr" }; - const char *values[4]; - - cl_git_pass(git_attr_get_many(values, g_repo, 0, "root_test1", 4, names)); - - cl_assert(GIT_ATTR_TRUE(values[0])); - cl_assert(GIT_ATTR_TRUE(values[1])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[2])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); - - cl_git_pass(git_attr_get_many(values, g_repo, 0, "root_test2", 4, names)); - - cl_assert(GIT_ATTR_TRUE(values[0])); - cl_assert(GIT_ATTR_FALSE(values[1])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[2])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); - - cl_git_pass(git_attr_get_many(values, g_repo, 0, "sub/subdir_test1", 4, names)); - - cl_assert(GIT_ATTR_TRUE(values[0])); - cl_assert(GIT_ATTR_TRUE(values[1])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[2])); - cl_assert_equal_s("yes", values[3]); -} - -void test_attr_repo__get_many_in_place(void) -{ - const char *vals[4] = { "repoattr", "rootattr", "missingattr", "subattr" }; - - /* it should be legal to look up values into the same array that has - * the attribute names, overwriting each name as the value is found. - */ - - cl_git_pass(git_attr_get_many(vals, g_repo, 0, "sub/subdir_test1", 4, vals)); - - cl_assert(GIT_ATTR_TRUE(vals[0])); - cl_assert(GIT_ATTR_TRUE(vals[1])); - cl_assert(GIT_ATTR_UNSPECIFIED(vals[2])); - cl_assert_equal_s("yes", vals[3]); -} - -static int count_attrs( - const char *name, - const char *value, - void *payload) -{ - GIT_UNUSED(name); - GIT_UNUSED(value); - - *((int *)payload) += 1; - - return 0; -} - -static int cancel_iteration( - const char *name, - const char *value, - void *payload) -{ - GIT_UNUSED(name); - GIT_UNUSED(value); - - *((int *)payload) -= 1; - - if (*((int *)payload) < 0) - return -1; - - return 0; -} - -void test_attr_repo__foreach(void) -{ - int count; - - count = 0; - cl_git_pass(git_attr_foreach( - g_repo, 0, "root_test1", &count_attrs, &count)); - cl_assert(count == 2); - - count = 0; - cl_git_pass(git_attr_foreach(g_repo, 0, "sub/subdir_test1", - &count_attrs, &count)); - cl_assert(count == 4); /* repoattr, rootattr, subattr, negattr */ - - count = 0; - cl_git_pass(git_attr_foreach(g_repo, 0, "sub/subdir_test2.txt", - &count_attrs, &count)); - cl_assert(count == 6); /* repoattr, rootattr, subattr, reposub, negattr, another */ - - count = 2; - cl_assert_equal_i( - GIT_EUSER, git_attr_foreach( - g_repo, 0, "sub/subdir_test1", &cancel_iteration, &count) - ); -} - -void test_attr_repo__manpage_example(void) -{ - const char *value; - - cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "foo")); - cl_assert(GIT_ATTR_TRUE(value)); - - cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "bar")); - cl_assert(GIT_ATTR_UNSPECIFIED(value)); - - cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "baz")); - cl_assert(GIT_ATTR_FALSE(value)); - - cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "merge")); - cl_assert_equal_s("filfre", value); - - cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "frotz")); - cl_assert(GIT_ATTR_UNSPECIFIED(value)); -} - -void test_attr_repo__macros(void) -{ - const char *names[5] = { "rootattr", "binary", "diff", "crlf", "frotz" }; - const char *names2[5] = { "mymacro", "positive", "negative", "rootattr", "another" }; - const char *names3[3] = { "macro2", "multi2", "multi3" }; - const char *values[5]; - - cl_git_pass(git_attr_get_many(values, g_repo, 0, "binfile", 5, names)); - - cl_assert(GIT_ATTR_TRUE(values[0])); - cl_assert(GIT_ATTR_TRUE(values[1])); - cl_assert(GIT_ATTR_FALSE(values[2])); - cl_assert(GIT_ATTR_FALSE(values[3])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[4])); - - cl_git_pass(git_attr_get_many(values, g_repo, 0, "macro_test", 5, names2)); - - cl_assert(GIT_ATTR_TRUE(values[0])); - cl_assert(GIT_ATTR_TRUE(values[1])); - cl_assert(GIT_ATTR_FALSE(values[2])); - cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); - cl_assert_equal_s("77", values[4]); - - cl_git_pass(git_attr_get_many(values, g_repo, 0, "macro_test", 3, names3)); - - cl_assert(GIT_ATTR_TRUE(values[0])); - cl_assert(GIT_ATTR_FALSE(values[1])); - cl_assert_equal_s("answer", values[2]); -} - -void test_attr_repo__bad_macros(void) -{ - const char *names[6] = { "rootattr", "positive", "negative", - "firstmacro", "secondmacro", "thirdmacro" }; - const char *values[6]; - - cl_git_pass(git_attr_get_many(values, g_repo, 0, "macro_bad", 6, names)); - - /* these three just confirm that the "mymacro" rule ran */ - cl_assert(GIT_ATTR_UNSPECIFIED(values[0])); - cl_assert(GIT_ATTR_TRUE(values[1])); - cl_assert(GIT_ATTR_FALSE(values[2])); - - /* file contains: - * # let's try some malicious macro defs - * [attr]firstmacro -thirdmacro -secondmacro - * [attr]secondmacro firstmacro -firstmacro - * [attr]thirdmacro secondmacro=hahaha -firstmacro - * macro_bad firstmacro secondmacro thirdmacro - * - * firstmacro assignment list ends up with: - * -thirdmacro -secondmacro - * secondmacro assignment list expands "firstmacro" and ends up with: - * -thirdmacro -secondmacro -firstmacro - * thirdmacro assignment don't expand so list ends up with: - * secondmacro="hahaha" - * - * macro_bad assignment list ends up with: - * -thirdmacro -secondmacro firstmacro && - * -thirdmacro -secondmacro -firstmacro secondmacro && - * secondmacro="hahaha" thirdmacro - * - * so summary results should be: - * -firstmacro secondmacro="hahaha" thirdmacro - */ - cl_assert(GIT_ATTR_FALSE(values[3])); - cl_assert_equal_s("hahaha", values[4]); - cl_assert(GIT_ATTR_TRUE(values[5])); -} - -#define CONTENT "I'm going to be dynamically processed\r\n" \ - "And my line endings...\r\n" \ - "...are going to be\n" \ - "normalized!\r\n" - -#define GITATTR "* text=auto\n" \ - "*.txt text\n" \ - "*.data binary\n" - -static void add_to_workdir(const char *filename, const char *content) -{ - git_buf buf = GIT_BUF_INIT; - - cl_git_pass(git_buf_joinpath(&buf, "attr", filename)); - cl_git_rewritefile(git_buf_cstr(&buf), content); - - git_buf_free(&buf); -} - -static void assert_proper_normalization(git_index *index, const char *filename, const char *expected_sha) -{ - size_t index_pos; - const git_index_entry *entry; - - add_to_workdir(filename, CONTENT); - cl_git_pass(git_index_add_bypath(index, filename)); - - cl_assert(!git_index_find(&index_pos, index, filename)); - - entry = git_index_get_byindex(index, index_pos); - cl_assert_equal_i(0, git_oid_streq(&entry->oid, expected_sha)); -} - -void test_attr_repo__staging_properly_normalizes_line_endings_according_to_gitattributes_directives(void) -{ - git_index* index; - - cl_git_pass(git_repository_index(&index, g_repo)); - - add_to_workdir(".gitattributes", GITATTR); - - assert_proper_normalization(index, "text.txt", "22c74203bace3c2e950278c7ab08da0fca9f4e9b"); - assert_proper_normalization(index, "huh.dunno", "22c74203bace3c2e950278c7ab08da0fca9f4e9b"); - assert_proper_normalization(index, "binary.data", "66eeff1fcbacf589e6d70aa70edd3fce5be2b37c"); - - git_index_free(index); -} diff --git a/tests-clar/blame/blame_helpers.c b/tests-clar/blame/blame_helpers.c deleted file mode 100644 index d64bb5c4c..000000000 --- a/tests-clar/blame/blame_helpers.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "blame_helpers.h" - -void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...) -{ - va_list arglist; - - printf("Hunk %zd (line %d +%d): ", idx, - hunk->final_start_line_number, hunk->lines_in_hunk-1); - - va_start(arglist, fmt); - vprintf(fmt, arglist); - va_end(arglist); - - printf("\n"); -} - -void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx, - int start_line, int len, char boundary, const char *commit_id, const char *orig_path) -{ - char expected[41] = {0}, actual[41] = {0}; - const git_blame_hunk *hunk = git_blame_get_hunk_byindex(blame, idx); - cl_assert(hunk); - - if (!strncmp(commit_id, "0000", 4)) { - strcpy(expected, "0000000000000000000000000000000000000000"); - } else { - git_object *obj; - cl_git_pass(git_revparse_single(&obj, repo, commit_id)); - git_oid_fmt(expected, git_object_id(obj)); - git_object_free(obj); - } - - if (hunk->final_start_line_number != start_line) { - hunk_message(idx, hunk, "mismatched start line number: expected %d, got %d", - start_line, hunk->final_start_line_number); - } - cl_assert_equal_i(hunk->final_start_line_number, start_line); - - if (hunk->lines_in_hunk != len) { - hunk_message(idx, hunk, "mismatched line count: expected %d, got %d", - len, hunk->lines_in_hunk); - } - cl_assert_equal_i(hunk->lines_in_hunk, len); - - git_oid_fmt(actual, &hunk->final_commit_id); - if (strcmp(expected, actual)) { - hunk_message(idx, hunk, "has mismatched original id (got %s, expected %s)\n", - actual, expected); - } - cl_assert_equal_s(actual, expected); - if (strcmp(hunk->orig_path, orig_path)) { - hunk_message(idx, hunk, "has mismatched original path (got '%s', expected '%s')\n", - hunk->orig_path, orig_path); - } - cl_assert_equal_s(hunk->orig_path, orig_path); - - if (hunk->boundary != boundary) { - hunk_message(idx, hunk, "doesn't match boundary flag (got %d, expected %d)\n", - hunk->boundary, boundary); - } - cl_assert_equal_i(boundary, hunk->boundary); -} - - diff --git a/tests-clar/blame/blame_helpers.h b/tests-clar/blame/blame_helpers.h deleted file mode 100644 index 94321a5b5..000000000 --- a/tests-clar/blame/blame_helpers.h +++ /dev/null @@ -1,16 +0,0 @@ -#include "clar_libgit2.h" -#include "blame.h" - -void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...); - -void check_blame_hunk_index( - git_repository *repo, - git_blame *blame, - int idx, - int start_line, - int len, - char boundary, - const char *commit_id, - const char *orig_path); - - diff --git a/tests-clar/blame/buffer.c b/tests-clar/blame/buffer.c deleted file mode 100644 index 912ee9846..000000000 --- a/tests-clar/blame/buffer.c +++ /dev/null @@ -1,166 +0,0 @@ -#include "blame_helpers.h" - -git_repository *g_repo; -git_blame *g_fileblame, *g_bufferblame; - -void test_blame_buffer__initialize(void) -{ - cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); - cl_git_pass(git_blame_file(&g_fileblame, g_repo, "b.txt", NULL)); - g_bufferblame = NULL; -} - -void test_blame_buffer__cleanup(void) -{ - git_blame_free(g_fileblame); - git_blame_free(g_bufferblame); - git_repository_free(g_repo); -} - -void test_blame_buffer__added_line(void) -{ - const git_blame_hunk *hunk; - - const char *buffer = "\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -\n\ -abcdefg\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; - - cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); - cl_assert_equal_i(5, git_blame_get_hunk_count(g_bufferblame)); - check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "000000", "b.txt"); - - hunk = git_blame_get_hunk_byline(g_bufferblame, 16); - cl_assert(hunk); - cl_assert_equal_s("Ben Straub", hunk->final_signature->name); -} - -void test_blame_buffer__deleted_line(void) -{ - const char *buffer = "\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; - - cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); - check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 3, 0, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 3, 9, 1, 0, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 4, 10, 5, 0, "aa06ecca", "b.txt"); -} - -void test_blame_buffer__add_splits_hunk(void) -{ - const char *buffer = "\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -abc\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; - - cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); - check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 2, 0, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 3, 8, 1, 0, "00000000", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 4, 9, 3, 0, "63d671eb", "b.txt"); -} - -void test_blame_buffer__delete_crosses_hunk_boundary(void) -{ - const char *buffer = "\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; - - cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); - check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 2, 0, "aa06ecca", "b.txt"); -} - -void test_blame_buffer__replace_line(void) -{ - const char *buffer = "\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -abc\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; - - cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); - check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 1, 0, "00000000", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 4, 8, 3, 0, "63d671eb", "b.txt"); -} - -void test_blame_buffer__add_lines_at_end(void) -{ - const char *buffer = "\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ -\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ -\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ -\n\ -abc\n\ -def\n"; - cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); - - cl_assert_equal_i(5, git_blame_get_hunk_count(g_bufferblame)); - check_blame_hunk_index(g_repo, g_bufferblame, 0, 1, 4, 0, "da237394", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 5, 0, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 3, 11, 5, 0, "aa06ecca", "b.txt"); - check_blame_hunk_index(g_repo, g_bufferblame, 4, 16, 2, 0, "00000000", "b.txt"); -} diff --git a/tests-clar/blame/getters.c b/tests-clar/blame/getters.c deleted file mode 100644 index 66eaeecf9..000000000 --- a/tests-clar/blame/getters.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "clar_libgit2.h" - -#include "blame.h" - -git_blame *g_blame; - -void test_blame_getters__initialize(void) -{ - size_t i; - git_blame_options opts = GIT_BLAME_OPTIONS_INIT; - - git_blame_hunk hunks[] = { - { 3, {{0}}, 1, NULL, {{0}}, "a", 0}, - { 3, {{0}}, 4, NULL, {{0}}, "b", 0}, - { 3, {{0}}, 7, NULL, {{0}}, "c", 0}, - { 3, {{0}}, 10, NULL, {{0}}, "d", 0}, - { 3, {{0}}, 13, NULL, {{0}}, "e", 0}, - }; - - g_blame = git_blame__alloc(NULL, opts, ""); - - for (i=0; i<5; i++) { - git_blame_hunk *h = git__calloc(1, sizeof(git_blame_hunk)); - h->final_start_line_number = hunks[i].final_start_line_number; - h->orig_path = git__strdup(hunks[i].orig_path); - h->lines_in_hunk = hunks[i].lines_in_hunk; - - git_vector_insert(&g_blame->hunks, h); - } -} - -void test_blame_getters__cleanup(void) -{ - git_blame_free(g_blame); -} - - -void test_blame_getters__byindex(void) -{ - const git_blame_hunk *h = git_blame_get_hunk_byindex(g_blame, 2); - cl_assert(h); - cl_assert_equal_s(h->orig_path, "c"); - - h = git_blame_get_hunk_byindex(g_blame, 95); - cl_assert_equal_p(h, NULL); -} - -void test_blame_getters__byline(void) -{ - const git_blame_hunk *h = git_blame_get_hunk_byline(g_blame, 5); - cl_assert(h); - cl_assert_equal_s(h->orig_path, "b"); - - h = git_blame_get_hunk_byline(g_blame, 95); - cl_assert_equal_p(h, NULL); -} diff --git a/tests-clar/blame/harder.c b/tests-clar/blame/harder.c deleted file mode 100644 index 7c4dd4f74..000000000 --- a/tests-clar/blame/harder.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "clar_libgit2.h" - -#include "blame.h" - - -/** - * The test repo has a history that looks like this: - * - * * (A) bc7c5ac - * |\ - * | * (B) aa06ecc - * * | (C) 63d671e - * |/ - * * (D) da23739 - * * (E) b99f7ac - * - */ - -static git_repository *g_repo = NULL; - -void test_blame_harder__initialize(void) -{ - cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); -} - -void test_blame_harder__cleanup(void) -{ - git_repository_free(g_repo); - g_repo = NULL; -} - - - -void test_blame_harder__m(void) -{ - /* TODO */ - git_blame_options opts = GIT_BLAME_OPTIONS_INIT; - - opts.flags = GIT_BLAME_TRACK_COPIES_SAME_FILE; -} - - -void test_blame_harder__c(void) -{ - git_blame_options opts = GIT_BLAME_OPTIONS_INIT; - - /* Attribute the first hunk in b.txt to (E), since it was cut/pasted from - * a.txt in (D). - */ - opts.flags = GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; -} - -void test_blame_harder__cc(void) -{ - git_blame_options opts = GIT_BLAME_OPTIONS_INIT; - - /* Attribute the second hunk in b.txt to (E), since it was copy/pasted from - * a.txt in (C). - */ - opts.flags = GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; -} - -void test_blame_harder__ccc(void) -{ - git_blame_options opts = GIT_BLAME_OPTIONS_INIT; - - /* Attribute the third hunk in b.txt to (E). This hunk was deleted from - * a.txt in (D), but reintroduced in (B). - */ - opts.flags = GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES; -} diff --git a/tests-clar/blame/simple.c b/tests-clar/blame/simple.c deleted file mode 100644 index 79bd56b83..000000000 --- a/tests-clar/blame/simple.c +++ /dev/null @@ -1,305 +0,0 @@ -#include "blame_helpers.h" - -static git_repository *g_repo; -static git_blame *g_blame; - -void test_blame_simple__initialize(void) -{ - g_repo = NULL; - g_blame = NULL; -} - -void test_blame_simple__cleanup(void) -{ - git_blame_free(g_blame); - git_repository_free(g_repo); -} - -/* - * $ git blame -s branch_file.txt - * orig line no final line no - * commit V author timestamp V - * c47800c7 1 (Scott Chacon 2010-05-25 11:58:14 -0700 1 - * a65fedf3 2 (Scott Chacon 2011-08-09 19:33:46 -0700 2 - */ -void test_blame_simple__trivial_testrepo(void) -{ - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo/.gitted"))); - cl_git_pass(git_blame_file(&g_blame, g_repo, "branch_file.txt", NULL)); - - cl_assert_equal_i(2, git_blame_get_hunk_count(g_blame)); - check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, 0, "c47800c7", "branch_file.txt"); - check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, 0, "a65fedf3", "branch_file.txt"); -} - -/* - * $ git blame -n b.txt - * orig line no final line no - * commit V author timestamp V - * da237394 1 (Ben Straub 2013-02-12 15:11:30 -0800 1 - * da237394 2 (Ben Straub 2013-02-12 15:11:30 -0800 2 - * da237394 3 (Ben Straub 2013-02-12 15:11:30 -0800 3 - * da237394 4 (Ben Straub 2013-02-12 15:11:30 -0800 4 - * ^b99f7ac 1 (Ben Straub 2013-02-12 15:10:12 -0800 5 - * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 - * 63d671eb 7 (Ben Straub 2013-02-12 15:13:04 -0800 7 - * 63d671eb 8 (Ben Straub 2013-02-12 15:13:04 -0800 8 - * 63d671eb 9 (Ben Straub 2013-02-12 15:13:04 -0800 9 - * 63d671eb 10 (Ben Straub 2013-02-12 15:13:04 -0800 10 - * aa06ecca 6 (Ben Straub 2013-02-12 15:14:46 -0800 11 - * aa06ecca 7 (Ben Straub 2013-02-12 15:14:46 -0800 12 - * aa06ecca 8 (Ben Straub 2013-02-12 15:14:46 -0800 13 - * aa06ecca 9 (Ben Straub 2013-02-12 15:14:46 -0800 14 - * aa06ecca 10 (Ben Straub 2013-02-12 15:14:46 -0800 15 - */ -void test_blame_simple__trivial_blamerepo(void) -{ - cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); - cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", NULL)); - - cl_assert_equal_i(4, git_blame_get_hunk_count(g_blame)); - check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, 0, "da237394", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 2, 6, 5, 0, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 3, 11, 5, 0, "aa06ecca", "b.txt"); -} - - -/* - * $ git blame -n 359fc2d -- include/git2.h - * orig line no final line no - * commit orig path V author timestamp V - * d12299fe src/git.h 1 (Vicent Martí 2010-12-03 22:22:10 +0200 1 - * 359fc2d2 include/git2.h 2 (Edward Thomson 2013-01-08 17:07:25 -0600 2 - * d12299fe src/git.h 5 (Vicent Martí 2010-12-03 22:22:10 +0200 3 - * bb742ede include/git2.h 4 (Vicent Martí 2011-09-19 01:54:32 +0300 4 - * bb742ede include/git2.h 5 (Vicent Martí 2011-09-19 01:54:32 +0300 5 - * d12299fe src/git.h 24 (Vicent Martí 2010-12-03 22:22:10 +0200 6 - * d12299fe src/git.h 25 (Vicent Martí 2010-12-03 22:22:10 +0200 7 - * d12299fe src/git.h 26 (Vicent Martí 2010-12-03 22:22:10 +0200 8 - * d12299fe src/git.h 27 (Vicent Martí 2010-12-03 22:22:10 +0200 9 - * d12299fe src/git.h 28 (Vicent Martí 2010-12-03 22:22:10 +0200 10 - * 96fab093 include/git2.h 11 (Sven Strickroth 2011-10-09 18:37:41 +0200 11 - * 9d1dcca2 src/git2.h 33 (Vicent Martí 2011-02-07 10:35:58 +0200 12 - * 44908fe7 src/git2.h 29 (Vicent Martí 2010-12-06 23:03:16 +0200 13 - * a15c550d include/git2.h 14 (Vicent Martí 2011-11-16 14:09:44 +0100 14 - * 44908fe7 src/git2.h 30 (Vicent Martí 2010-12-06 23:03:16 +0200 15 - * d12299fe src/git.h 32 (Vicent Martí 2010-12-03 22:22:10 +0200 16 - * 44908fe7 src/git2.h 33 (Vicent Martí 2010-12-06 23:03:16 +0200 17 - * d12299fe src/git.h 34 (Vicent Martí 2010-12-03 22:22:10 +0200 18 - * 44908fe7 src/git2.h 35 (Vicent Martí 2010-12-06 23:03:16 +0200 19 - * 638c2ca4 src/git2.h 36 (Vicent Martí 2010-12-18 02:10:25 +0200 20 - * 44908fe7 src/git2.h 36 (Vicent Martí 2010-12-06 23:03:16 +0200 21 - * d12299fe src/git.h 37 (Vicent Martí 2010-12-03 22:22:10 +0200 22 - * 44908fe7 src/git2.h 38 (Vicent Martí 2010-12-06 23:03:16 +0200 23 - * 44908fe7 src/git2.h 39 (Vicent Martí 2010-12-06 23:03:16 +0200 24 - * bf787bd8 include/git2.h 25 (Carlos Martín Nieto 2012-04-08 18:56:50 +0200 25 - * 0984c876 include/git2.h 26 (Scott J. Goldman 2012-11-28 18:27:43 -0800 26 - * 2f8a8ab2 src/git2.h 41 (Vicent Martí 2011-01-29 01:56:25 +0200 27 - * 27df4275 include/git2.h 47 (Michael Schubert 2011-06-28 14:13:12 +0200 28 - * a346992f include/git2.h 28 (Ben Straub 2012-05-10 09:47:14 -0700 29 - * d12299fe src/git.h 40 (Vicent Martí 2010-12-03 22:22:10 +0200 30 - * 44908fe7 src/git2.h 41 (Vicent Martí 2010-12-06 23:03:16 +0200 31 - * 44908fe7 src/git2.h 42 (Vicent Martí 2010-12-06 23:03:16 +0200 32 - * 44908fe7 src/git2.h 43 (Vicent Martí 2010-12-06 23:03:16 +0200 33 - * 44908fe7 src/git2.h 44 (Vicent Martí 2010-12-06 23:03:16 +0200 34 - * 44908fe7 src/git2.h 45 (Vicent Martí 2010-12-06 23:03:16 +0200 35 - * 65b09b1d include/git2.h 33 (Russell Belfer 2012-02-02 18:03:43 -0800 36 - * d12299fe src/git.h 46 (Vicent Martí 2010-12-03 22:22:10 +0200 37 - * 44908fe7 src/git2.h 47 (Vicent Martí 2010-12-06 23:03:16 +0200 38 - * 5d4cd003 include/git2.h 55 (Carlos Martín Nieto 2011-03-28 17:02:45 +0200 39 - * 41fb1ca0 include/git2.h 39 (Philip Kelley 2012-10-29 13:41:14 -0400 40 - * 2dc31040 include/git2.h 56 (Carlos Martín Nieto 2011-06-20 18:58:57 +0200 41 - * 764df57e include/git2.h 40 (Ben Straub 2012-06-15 13:14:43 -0700 42 - * 5280f4e6 include/git2.h 41 (Ben Straub 2012-07-31 19:39:06 -0700 43 - * 613d5eb9 include/git2.h 43 (Philip Kelley 2012-11-28 11:42:37 -0500 44 - * d12299fe src/git.h 48 (Vicent Martí 2010-12-03 22:22:10 +0200 45 - * 111ee3fe include/git2.h 41 (Vicent Martí 2012-07-11 14:37:26 +0200 46 - * f004c4a8 include/git2.h 44 (Russell Belfer 2012-08-21 17:26:39 -0700 47 - * 111ee3fe include/git2.h 42 (Vicent Martí 2012-07-11 14:37:26 +0200 48 - * 9c82357b include/git2.h 58 (Carlos Martín Nieto 2011-06-17 18:13:14 +0200 49 - * d6258deb include/git2.h 61 (Carlos Martín Nieto 2011-06-25 15:10:09 +0200 50 - * b311e313 include/git2.h 63 (Julien Miotte 2011-07-27 18:31:13 +0200 51 - * 3412391d include/git2.h 63 (Carlos Martín Nieto 2011-07-07 11:47:31 +0200 52 - * bfc9ca59 include/git2.h 43 (Russell Belfer 2012-03-28 16:45:36 -0700 53 - * bf477ed4 include/git2.h 44 (Michael Schubert 2012-02-15 00:33:38 +0100 54 - * edebceff include/git2.h 46 (nulltoken 2012-05-01 13:57:45 +0200 55 - * 743a4b3b include/git2.h 48 (nulltoken 2012-06-15 22:24:59 +0200 56 - * 0a32dca5 include/git2.h 54 (Michael Schubert 2012-08-19 22:26:32 +0200 57 - * 590fb68b include/git2.h 55 (nulltoken 2012-10-04 13:47:45 +0200 58 - * bf477ed4 include/git2.h 45 (Michael Schubert 2012-02-15 00:33:38 +0100 59 - * d12299fe src/git.h 49 (Vicent Martí 2010-12-03 22:22:10 +0200 60 - */ -void test_blame_simple__trivial_libgit2(void) -{ - git_blame_options opts = GIT_BLAME_OPTIONS_INIT; - git_object *obj; - - cl_git_pass(git_repository_open(&g_repo, cl_fixture("../.."))); - - /* This test can't work on a shallow clone */ - if (git_repository_is_shallow(g_repo)) - return; - - cl_git_pass(git_revparse_single(&obj, g_repo, "359fc2d")); - git_oid_cpy(&opts.newest_commit, git_object_id(obj)); - git_object_free(obj); - - cl_git_pass(git_blame_file(&g_blame, g_repo, "include/git2.h", &opts)); - - check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, 0, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, 0, "359fc2d2", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 2, 3, 1, 0, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 3, 4, 2, 0, "bb742ede", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 4, 6, 5, 0, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 5, 11, 1, 0, "96fab093", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 6, 12, 1, 0, "9d1dcca2", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 7, 13, 1, 0, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 8, 14, 1, 0, "a15c550d", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 9, 15, 1, 0, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 10, 16, 1, 0, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 11, 17, 1, 0, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 12, 18, 1, 0, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 13, 19, 1, 0, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 14, 20, 1, 0, "638c2ca4", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 15, 21, 1, 0, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 16, 22, 1, 0, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 17, 23, 2, 0, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 18, 25, 1, 0, "bf787bd8", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 19, 26, 1, 0, "0984c876", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 20, 27, 1, 0, "2f8a8ab2", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 21, 28, 1, 0, "27df4275", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 22, 29, 1, 0, "a346992f", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 23, 30, 1, 0, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 24, 31, 5, 0, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 25, 36, 1, 0, "65b09b1d", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 26, 37, 1, 0, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 27, 38, 1, 0, "44908fe7", "src/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 28, 39, 1, 0, "5d4cd003", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 29, 40, 1, 0, "41fb1ca0", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 30, 41, 1, 0, "2dc31040", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 31, 42, 1, 0, "764df57e", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 32, 43, 1, 0, "5280f4e6", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 33, 44, 1, 0, "613d5eb9", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 34, 45, 1, 0, "d12299fe", "src/git.h"); - check_blame_hunk_index(g_repo, g_blame, 35, 46, 1, 0, "111ee3fe", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 36, 47, 1, 0, "f004c4a8", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 37, 48, 1, 0, "111ee3fe", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 38, 49, 1, 0, "9c82357b", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 39, 50, 1, 0, "d6258deb", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 40, 51, 1, 0, "b311e313", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 41, 52, 1, 0, "3412391d", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 42, 53, 1, 0, "bfc9ca59", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 43, 54, 1, 0, "bf477ed4", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 44, 55, 1, 0, "edebceff", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 45, 56, 1, 0, "743a4b3b", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 46, 57, 1, 0, "0a32dca5", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 47, 58, 1, 0, "590fb68b", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 48, 59, 1, 0, "bf477ed4", "include/git2.h"); - check_blame_hunk_index(g_repo, g_blame, 49, 60, 1, 0, "d12299fe", "src/git.h"); -} - - -/* - * $ git blame -n b.txt -L 8 - * orig line no final line no - * commit V author timestamp V - * 63d671eb 8 (Ben Straub 2013-02-12 15:13:04 -0800 8 - * 63d671eb 9 (Ben Straub 2013-02-12 15:13:04 -0800 9 - * 63d671eb 10 (Ben Straub 2013-02-12 15:13:04 -0800 10 - * aa06ecca 6 (Ben Straub 2013-02-12 15:14:46 -0800 11 - * aa06ecca 7 (Ben Straub 2013-02-12 15:14:46 -0800 12 - * aa06ecca 8 (Ben Straub 2013-02-12 15:14:46 -0800 13 - * aa06ecca 9 (Ben Straub 2013-02-12 15:14:46 -0800 14 - * aa06ecca 10 (Ben Straub 2013-02-12 15:14:46 -0800 15 - */ -void test_blame_simple__can_restrict_lines_min(void) -{ - git_blame_options opts = GIT_BLAME_OPTIONS_INIT; - - cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); - - opts.min_line = 8; - cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); - cl_assert_equal_i(2, git_blame_get_hunk_count(g_blame)); - check_blame_hunk_index(g_repo, g_blame, 0, 8, 3, 0, "63d671eb", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 1, 11, 5, 0, "aa06ecca", "b.txt"); -} - -/* - * $ git blame -n b.txt -L ,6 - * orig line no final line no - * commit V author timestamp V - * da237394 1 (Ben Straub 2013-02-12 15:11:30 -0800 1 - * da237394 2 (Ben Straub 2013-02-12 15:11:30 -0800 2 - * da237394 3 (Ben Straub 2013-02-12 15:11:30 -0800 3 - * da237394 4 (Ben Straub 2013-02-12 15:11:30 -0800 4 - * ^b99f7ac 1 (Ben Straub 2013-02-12 15:10:12 -0800 5 - * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 - */ -void test_blame_simple__can_restrict_lines_max(void) -{ - git_blame_options opts = GIT_BLAME_OPTIONS_INIT; - - cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); - - opts.max_line = 6; - cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); - cl_assert_equal_i(3, git_blame_get_hunk_count(g_blame)); - check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, 0, "da237394", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 2, 6, 1, 0, "63d671eb", "b.txt"); -} - -/* - * $ git blame -n b.txt -L 2,7 - * orig line no final line no - * commit V author timestamp V - * da237394 2 (Ben Straub 2013-02-12 15:11:30 -0800 2 - * da237394 3 (Ben Straub 2013-02-12 15:11:30 -0800 3 - * da237394 4 (Ben Straub 2013-02-12 15:11:30 -0800 4 - * ^b99f7ac 1 (Ben Straub 2013-02-12 15:10:12 -0800 5 - * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 - * 63d671eb 7 (Ben Straub 2013-02-12 15:13:04 -0800 7 - */ -void test_blame_simple__can_restrict_lines_both(void) -{ - git_blame_options opts = GIT_BLAME_OPTIONS_INIT; - - cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); - - opts.min_line = 2; - opts.max_line = 7; - cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); - cl_assert_equal_i(3, git_blame_get_hunk_count(g_blame)); - check_blame_hunk_index(g_repo, g_blame, 0, 2, 3, 0, "da237394", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 2, 6, 2, 0, "63d671eb", "b.txt"); -} - -/* - * $ git blame -n branch_file.txt be3563a..HEAD - * orig line no final line no - * commit V author timestamp V - * ^be3563a 1 (Scott Chacon 2010-05-25 11:58:27 -0700 1) hi - * a65fedf3 2 (Scott Chacon 2011-08-09 19:33:46 -0700 2) bye! - */ -void test_blame_simple__can_restrict_to_newish_commits(void) -{ - git_blame_options opts = GIT_BLAME_OPTIONS_INIT; - - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); - - { - git_object *obj; - cl_git_pass(git_revparse_single(&obj, g_repo, "be3563a")); - git_oid_cpy(&opts.oldest_commit, git_object_id(obj)); - git_object_free(obj); - } - - cl_git_pass(git_blame_file(&g_blame, g_repo, "branch_file.txt", &opts)); - - cl_assert_equal_i(2, git_blame_get_hunk_count(g_blame)); - check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, 1, "be3563a", "branch_file.txt"); - check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, 0, "a65fedf", "branch_file.txt"); -} diff --git a/tests-clar/buf/basic.c b/tests-clar/buf/basic.c deleted file mode 100644 index d558757a9..000000000 --- a/tests-clar/buf/basic.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" - -static const char *test_string = "Have you seen that? Have you seeeen that??"; - -void test_buf_basic__resize(void) -{ - git_buf buf1 = GIT_BUF_INIT; - git_buf_puts(&buf1, test_string); - cl_assert(git_buf_oom(&buf1) == 0); - cl_assert_equal_s(git_buf_cstr(&buf1), test_string); - - git_buf_puts(&buf1, test_string); - cl_assert(strlen(git_buf_cstr(&buf1)) == strlen(test_string) * 2); - git_buf_free(&buf1); -} - -void test_buf_basic__printf(void) -{ - git_buf buf2 = GIT_BUF_INIT; - git_buf_printf(&buf2, "%s %s %d ", "shoop", "da", 23); - cl_assert(git_buf_oom(&buf2) == 0); - cl_assert_equal_s(git_buf_cstr(&buf2), "shoop da 23 "); - - git_buf_printf(&buf2, "%s %d", "woop", 42); - cl_assert(git_buf_oom(&buf2) == 0); - cl_assert_equal_s(git_buf_cstr(&buf2), "shoop da 23 woop 42"); - git_buf_free(&buf2); -} diff --git a/tests-clar/buf/splice.c b/tests-clar/buf/splice.c deleted file mode 100644 index e80c93105..000000000 --- a/tests-clar/buf/splice.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" - -static git_buf _buf; - -void test_buf_splice__initialize(void) { - git_buf_init(&_buf, 16); -} - -void test_buf_splice__cleanup(void) { - git_buf_free(&_buf); -} - -void test_buf_splice__preprend(void) -{ - git_buf_sets(&_buf, "world!"); - - cl_git_pass(git_buf_splice(&_buf, 0, 0, "Hello Dolly", strlen("Hello "))); - - cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); -} - -void test_buf_splice__append(void) -{ - git_buf_sets(&_buf, "Hello"); - - cl_git_pass(git_buf_splice(&_buf, git_buf_len(&_buf), 0, " world!", strlen(" world!"))); - - cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); -} - -void test_buf_splice__insert_at(void) -{ - git_buf_sets(&_buf, "Hell world!"); - - cl_git_pass(git_buf_splice(&_buf, strlen("Hell"), 0, "o", strlen("o"))); - - cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); -} - -void test_buf_splice__remove_at(void) -{ - git_buf_sets(&_buf, "Hello world of warcraft!"); - - cl_git_pass(git_buf_splice(&_buf, strlen("Hello world"), strlen(" of warcraft"), "", 0)); - - cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); -} - -void test_buf_splice__replace(void) -{ - git_buf_sets(&_buf, "Hell0 w0rld!"); - - cl_git_pass(git_buf_splice(&_buf, strlen("Hell"), strlen("0 w0"), "o wo", strlen("o wo"))); - - cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); -} - -void test_buf_splice__replace_with_longer(void) -{ - git_buf_sets(&_buf, "Hello you!"); - - cl_git_pass(git_buf_splice(&_buf, strlen("Hello "), strlen("you"), "world", strlen("world"))); - - cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); -} - -void test_buf_splice__replace_with_shorter(void) -{ - git_buf_sets(&_buf, "Brave new world!"); - - cl_git_pass(git_buf_splice(&_buf, 0, strlen("Brave new"), "Hello", strlen("Hello"))); - - cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); -} - -void test_buf_splice__truncate(void) -{ - git_buf_sets(&_buf, "Hello world!!"); - - cl_git_pass(git_buf_splice(&_buf, strlen("Hello world!"), strlen("!"), "", 0)); - - cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); -} - -void test_buf_splice__dont_do_anything(void) -{ - git_buf_sets(&_buf, "Hello world!"); - - cl_git_pass(git_buf_splice(&_buf, 3, 0, "Hello", 0)); - - cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); -} diff --git a/tests-clar/checkout/binaryunicode.c b/tests-clar/checkout/binaryunicode.c deleted file mode 100644 index 14ab9fdfa..000000000 --- a/tests-clar/checkout/binaryunicode.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" -#include "repo/repo_helpers.h" -#include "path.h" -#include "fileops.h" - -static git_repository *g_repo; - -void test_checkout_binaryunicode__initialize(void) -{ - g_repo = cl_git_sandbox_init("binaryunicode"); -} - -void test_checkout_binaryunicode__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -static void execute_test(void) -{ - git_oid oid, check; - git_commit *commit; - git_tree *tree; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/branch1")); - cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); - cl_git_pass(git_commit_tree(&tree, commit)); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE; - - cl_git_pass(git_checkout_tree(g_repo, (git_object *)tree, &opts)); - - git_tree_free(tree); - git_commit_free(commit); - - /* Verify that the lenna.jpg file was checked out correctly */ - cl_git_pass(git_oid_fromstr(&check, "8ab005d890fe53f65eda14b23672f60d9f4ec5a1")); - cl_git_pass(git_odb_hashfile(&oid, "binaryunicode/lenna.jpg", GIT_OBJ_BLOB)); - cl_assert(git_oid_equal(&oid, &check)); - - /* Verify that the text file was checked out correctly */ - cl_git_pass(git_oid_fromstr(&check, "965b223880dd4249e2c66a0cc0b4cffe1dc40f5a")); - cl_git_pass(git_odb_hashfile(&oid, "binaryunicode/utf16_withbom_noeol_crlf.txt", GIT_OBJ_BLOB)); - cl_assert(git_oid_equal(&oid, &check)); -} - -void test_checkout_binaryunicode__noautocrlf(void) -{ - cl_repo_set_bool(g_repo, "core.autocrlf", false); - execute_test(); -} - -void test_checkout_binaryunicode__autocrlf(void) -{ - cl_repo_set_bool(g_repo, "core.autocrlf", true); - execute_test(); -} diff --git a/tests-clar/checkout/checkout_helpers.c b/tests-clar/checkout/checkout_helpers.c deleted file mode 100644 index 06b4e0682..000000000 --- a/tests-clar/checkout/checkout_helpers.c +++ /dev/null @@ -1,130 +0,0 @@ -#include "clar_libgit2.h" -#include "checkout_helpers.h" -#include "refs.h" -#include "fileops.h" - -void assert_on_branch(git_repository *repo, const char *branch) -{ - git_reference *head; - git_buf bname = GIT_BUF_INIT; - - cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE)); - cl_assert_(git_reference_type(head) == GIT_REF_SYMBOLIC, branch); - - cl_git_pass(git_buf_joinpath(&bname, "refs/heads", branch)); - cl_assert_equal_s(bname.ptr, git_reference_symbolic_target(head)); - - git_reference_free(head); - git_buf_free(&bname); -} - -void reset_index_to_treeish(git_object *treeish) -{ - git_object *tree; - git_index *index; - git_repository *repo = git_object_owner(treeish); - - cl_git_pass(git_object_peel(&tree, treeish, GIT_OBJ_TREE)); - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_read_tree(index, (git_tree *)tree)); - cl_git_pass(git_index_write(index)); - - git_object_free(tree); - git_index_free(index); -} - -int checkout_count_callback( - git_checkout_notify_t why, - const char *path, - const git_diff_file *baseline, - const git_diff_file *target, - const git_diff_file *workdir, - void *payload) -{ - checkout_counts *ct = payload; - - GIT_UNUSED(baseline); GIT_UNUSED(target); GIT_UNUSED(workdir); - - if (why & GIT_CHECKOUT_NOTIFY_CONFLICT) { - ct->n_conflicts++; - - if (ct->debug) { - if (workdir) { - if (baseline) { - if (target) - fprintf(stderr, "M %s (conflicts with M %s)\n", - workdir->path, target->path); - else - fprintf(stderr, "M %s (conflicts with D %s)\n", - workdir->path, baseline->path); - } else { - if (target) - fprintf(stderr, "Existing %s (conflicts with A %s)\n", - workdir->path, target->path); - else - fprintf(stderr, "How can an untracked file be a conflict (%s)\n", workdir->path); - } - } else { - if (baseline) { - if (target) - fprintf(stderr, "D %s (conflicts with M %s)\n", - target->path, baseline->path); - else - fprintf(stderr, "D %s (conflicts with D %s)\n", - baseline->path, baseline->path); - } else { - if (target) - fprintf(stderr, "How can an added file with no workdir be a conflict (%s)\n", target->path); - else - fprintf(stderr, "How can a nonexistent file be a conflict (%s)\n", path); - } - } - } - } - - if (why & GIT_CHECKOUT_NOTIFY_DIRTY) { - ct->n_dirty++; - - if (ct->debug) { - if (workdir) - fprintf(stderr, "M %s\n", workdir->path); - else - fprintf(stderr, "D %s\n", baseline->path); - } - } - - if (why & GIT_CHECKOUT_NOTIFY_UPDATED) { - ct->n_updates++; - - if (ct->debug) { - if (baseline) { - if (target) - fprintf(stderr, "update: M %s\n", path); - else - fprintf(stderr, "update: D %s\n", path); - } else { - if (target) - fprintf(stderr, "update: A %s\n", path); - else - fprintf(stderr, "update: this makes no sense %s\n", path); - } - } - } - - if (why & GIT_CHECKOUT_NOTIFY_UNTRACKED) { - ct->n_untracked++; - - if (ct->debug) - fprintf(stderr, "? %s\n", path); - } - - if (why & GIT_CHECKOUT_NOTIFY_IGNORED) { - ct->n_ignored++; - - if (ct->debug) - fprintf(stderr, "I %s\n", path); - } - - return 0; -} diff --git a/tests-clar/checkout/checkout_helpers.h b/tests-clar/checkout/checkout_helpers.h deleted file mode 100644 index 705ee903d..000000000 --- a/tests-clar/checkout/checkout_helpers.h +++ /dev/null @@ -1,29 +0,0 @@ -#include "buffer.h" -#include "git2/object.h" -#include "git2/repository.h" - -extern void assert_on_branch(git_repository *repo, const char *branch); -extern void reset_index_to_treeish(git_object *treeish); - -#define check_file_contents(PATH,EXP) \ - cl_assert_equal_file(EXP,0,PATH) - -#define check_file_contents_nocr(PATH,EXP) \ - cl_assert_equal_file_ignore_cr(EXP,0,PATH) - -typedef struct { - int n_conflicts; - int n_dirty; - int n_updates; - int n_untracked; - int n_ignored; - int debug; -} checkout_counts; - -extern int checkout_count_callback( - git_checkout_notify_t why, - const char *path, - const git_diff_file *baseline, - const git_diff_file *target, - const git_diff_file *workdir, - void *payload); diff --git a/tests-clar/checkout/conflict.c b/tests-clar/checkout/conflict.c deleted file mode 100644 index 66965a89b..000000000 --- a/tests-clar/checkout/conflict.c +++ /dev/null @@ -1,1127 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/repository.h" -#include "git2/sys/index.h" -#include "fileops.h" - -static git_repository *g_repo; -static git_index *g_index; - -#define TEST_REPO_PATH "merge-resolve" - -#define CONFLICTING_ANCESTOR_OID "d427e0b2e138501a3d15cc376077a3631e15bd46" -#define CONFLICTING_OURS_OID "4e886e602529caa9ab11d71f86634bd1b6e0de10" -#define CONFLICTING_THEIRS_OID "2bd0a343aeef7a2cf0d158478966a6e587ff3863" - -#define AUTOMERGEABLE_ANCESTOR_OID "6212c31dab5e482247d7977e4f0dd3601decf13b" -#define AUTOMERGEABLE_OURS_OID "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf" -#define AUTOMERGEABLE_THEIRS_OID "058541fc37114bfc1dddf6bd6bffc7fae5c2e6fe" - -#define LINK_ANCESTOR_OID "1a010b1c0f081b2e8901d55307a15c29ff30af0e" -#define LINK_OURS_OID "72ea499e108df5ff0a4a913e7655bbeeb1fb69f2" -#define LINK_THEIRS_OID "8bfb012a6d809e499bd8d3e194a3929bc8995b93" - -#define LINK_ANCESTOR_TARGET "file" -#define LINK_OURS_TARGET "other-file" -#define LINK_THEIRS_TARGET "still-another-file" - -#define CONFLICTING_OURS_FILE \ - "this file is changed in master and branch\n" -#define CONFLICTING_THEIRS_FILE \ - "this file is changed in branch and master\n" -#define CONFLICTING_DIFF3_FILE \ - "<<<<<<< ours\n" \ - "this file is changed in master and branch\n" \ - "=======\n" \ - "this file is changed in branch and master\n" \ - ">>>>>>> theirs\n" - -#define AUTOMERGEABLE_MERGED_FILE \ - "this file is changed in master\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is changed in branch\n" - -struct checkout_index_entry { - uint16_t mode; - char oid_str[41]; - int stage; - char path[128]; -}; - -struct checkout_name_entry { - char ancestor[64]; - char ours[64]; - char theirs[64]; -}; - -void test_checkout_conflict__initialize(void) -{ - g_repo = cl_git_sandbox_init(TEST_REPO_PATH); - git_repository_index(&g_index, g_repo); - - cl_git_rewritefile( - TEST_REPO_PATH "/.gitattributes", - "* text eol=lf\n"); -} - -void test_checkout_conflict__cleanup(void) -{ - git_index_free(g_index); - cl_git_sandbox_cleanup(); -} - -static void create_index(struct checkout_index_entry *entries, size_t entries_len) -{ - git_buf path = GIT_BUF_INIT; - size_t i; - - for (i = 0; i < entries_len; i++) { - git_buf_joinpath(&path, TEST_REPO_PATH, entries[i].path); - - if (entries[i].stage == 3 && (i == 0 || strcmp(entries[i-1].path, entries[i].path) != 0 || entries[i-1].stage != 2)) - p_unlink(git_buf_cstr(&path)); - - git_index_remove_bypath(g_index, entries[i].path); - } - - for (i = 0; i < entries_len; i++) { - git_index_entry entry; - - memset(&entry, 0x0, sizeof(git_index_entry)); - - entry.mode = entries[i].mode; - entry.flags = entries[i].stage << GIT_IDXENTRY_STAGESHIFT; - git_oid_fromstr(&entry.oid, entries[i].oid_str); - entry.path = entries[i].path; - - cl_git_pass(git_index_add(g_index, &entry)); - } - - git_buf_free(&path); -} - -static void create_index_names(struct checkout_name_entry *entries, size_t entries_len) -{ - size_t i; - - for (i = 0; i < entries_len; i++) { - cl_git_pass(git_index_name_add(g_index, - strlen(entries[i].ancestor) == 0 ? NULL : entries[i].ancestor, - strlen(entries[i].ours) == 0 ? NULL : entries[i].ours, - strlen(entries[i].theirs) == 0 ? NULL : entries[i].theirs)); - } -} - -static void create_conflicting_index(void) -{ - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting.txt" }, - { 0100644, CONFLICTING_OURS_OID, 2, "conflicting.txt" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting.txt" }, - }; - - create_index(checkout_index_entries, 3); - git_index_write(g_index); -} - -static void ensure_workdir_contents(const char *path, const char *contents) -{ - git_buf fullpath = GIT_BUF_INIT, data_buf = GIT_BUF_INIT; - - cl_git_pass( - git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); - - cl_git_pass(git_futils_readbuffer(&data_buf, git_buf_cstr(&fullpath))); - cl_assert(strcmp(git_buf_cstr(&data_buf), contents) == 0); - - git_buf_free(&fullpath); - git_buf_free(&data_buf); -} - -static void ensure_workdir_oid(const char *path, const char *oid_str) -{ - git_oid expected, actual; - - cl_git_pass(git_oid_fromstr(&expected, oid_str)); - cl_git_pass(git_repository_hashfile(&actual, g_repo, path, GIT_OBJ_BLOB, NULL)); - cl_assert(git_oid_cmp(&expected, &actual) == 0); -} - -static void ensure_workdir_mode(const char *path, int mode) -{ -#ifndef GIT_WIN32 - git_buf fullpath = GIT_BUF_INIT; - struct stat st; - - cl_git_pass( - git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); - - cl_git_pass(p_stat(git_buf_cstr(&fullpath), &st)); - cl_assert_equal_i(mode, st.st_mode); - - git_buf_free(&fullpath); -#endif -} - -static void ensure_workdir(const char *path, int mode, const char *oid_str) -{ - ensure_workdir_mode(path, mode); - ensure_workdir_oid(path, oid_str); -} - -static void ensure_workdir_link(const char *path, const char *target) -{ -#ifdef GIT_WIN32 - ensure_workdir_contents(path, target); -#else - git_buf fullpath = GIT_BUF_INIT; - char actual[1024]; - struct stat st; - int len; - - cl_git_pass( - git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); - - cl_git_pass(p_lstat(git_buf_cstr(&fullpath), &st)); - cl_assert(S_ISLNK(st.st_mode)); - - cl_assert((len = p_readlink(git_buf_cstr(&fullpath), actual, 1024)) > 0); - actual[len] = '\0'; - cl_assert(strcmp(actual, target) == 0); - - git_buf_free(&fullpath); -#endif -} - -void test_checkout_conflict__ignored(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - opts.checkout_strategy |= GIT_CHECKOUT_SKIP_UNMERGED; - - create_conflicting_index(); - cl_git_pass(p_unlink(TEST_REPO_PATH "/conflicting.txt")); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - cl_assert(!git_path_exists(TEST_REPO_PATH "/conflicting.txt")); -} - -void test_checkout_conflict__ours(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - opts.checkout_strategy |= GIT_CHECKOUT_USE_OURS; - - create_conflicting_index(); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - ensure_workdir_contents("conflicting.txt", CONFLICTING_OURS_FILE); -} - -void test_checkout_conflict__theirs(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - opts.checkout_strategy |= GIT_CHECKOUT_USE_THEIRS; - - create_conflicting_index(); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - ensure_workdir_contents("conflicting.txt", CONFLICTING_THEIRS_FILE); - -} - -void test_checkout_conflict__diff3(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - create_conflicting_index(); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - ensure_workdir_contents("conflicting.txt", CONFLICTING_DIFF3_FILE); -} - -void test_checkout_conflict__automerge(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "automergeable.txt" }, - { 0100644, AUTOMERGEABLE_OURS_OID, 2, "automergeable.txt" }, - { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "automergeable.txt" }, - }; - - create_index(checkout_index_entries, 3); - git_index_write(g_index); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - ensure_workdir_contents("automergeable.txt", AUTOMERGEABLE_MERGED_FILE); -} - -void test_checkout_conflict__directory_file(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-1" }, - { 0100644, CONFLICTING_OURS_OID, 2, "df-1" }, - { 0100644, CONFLICTING_THEIRS_OID, 0, "df-1/file" }, - - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-2" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "df-2" }, - { 0100644, CONFLICTING_OURS_OID, 0, "df-2/file" }, - - { 0100644, CONFLICTING_THEIRS_OID, 3, "df-3" }, - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-3/file" }, - { 0100644, CONFLICTING_OURS_OID, 2, "df-3/file" }, - - { 0100644, CONFLICTING_OURS_OID, 2, "df-4" }, - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-4/file" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "df-4/file" }, - }; - - opts.checkout_strategy |= GIT_CHECKOUT_SAFE; - - create_index(checkout_index_entries, 12); - git_index_write(g_index); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - ensure_workdir_oid("df-1/file", CONFLICTING_THEIRS_OID); - ensure_workdir_oid("df-1~ours", CONFLICTING_OURS_OID); - ensure_workdir_oid("df-2/file", CONFLICTING_OURS_OID); - ensure_workdir_oid("df-2~theirs", CONFLICTING_THEIRS_OID); - ensure_workdir_oid("df-3/file", CONFLICTING_OURS_OID); - ensure_workdir_oid("df-3~theirs", CONFLICTING_THEIRS_OID); - ensure_workdir_oid("df-4~ours", CONFLICTING_OURS_OID); - ensure_workdir_oid("df-4/file", CONFLICTING_THEIRS_OID); -} - -void test_checkout_conflict__directory_file_with_custom_labels(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-1" }, - { 0100644, CONFLICTING_OURS_OID, 2, "df-1" }, - { 0100644, CONFLICTING_THEIRS_OID, 0, "df-1/file" }, - - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-2" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "df-2" }, - { 0100644, CONFLICTING_OURS_OID, 0, "df-2/file" }, - - { 0100644, CONFLICTING_THEIRS_OID, 3, "df-3" }, - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-3/file" }, - { 0100644, CONFLICTING_OURS_OID, 2, "df-3/file" }, - - { 0100644, CONFLICTING_OURS_OID, 2, "df-4" }, - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-4/file" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "df-4/file" }, - }; - - opts.checkout_strategy |= GIT_CHECKOUT_SAFE; - opts.our_label = "HEAD"; - opts.their_label = "branch"; - - create_index(checkout_index_entries, 12); - git_index_write(g_index); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - ensure_workdir_oid("df-1/file", CONFLICTING_THEIRS_OID); - ensure_workdir_oid("df-1~HEAD", CONFLICTING_OURS_OID); - ensure_workdir_oid("df-2/file", CONFLICTING_OURS_OID); - ensure_workdir_oid("df-2~branch", CONFLICTING_THEIRS_OID); - ensure_workdir_oid("df-3/file", CONFLICTING_OURS_OID); - ensure_workdir_oid("df-3~branch", CONFLICTING_THEIRS_OID); - ensure_workdir_oid("df-4~HEAD", CONFLICTING_OURS_OID); - ensure_workdir_oid("df-4/file", CONFLICTING_THEIRS_OID); -} - -void test_checkout_conflict__link_file(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "link-1" }, - { 0100644, CONFLICTING_OURS_OID, 2, "link-1" }, - { 0120000, LINK_THEIRS_OID, 3, "link-1" }, - - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "link-2" }, - { 0120000, LINK_OURS_OID, 2, "link-2" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "link-2" }, - - { 0120000, LINK_ANCESTOR_OID, 1, "link-3" }, - { 0100644, CONFLICTING_OURS_OID, 2, "link-3" }, - { 0120000, LINK_THEIRS_OID, 3, "link-3" }, - - { 0120000, LINK_ANCESTOR_OID, 1, "link-4" }, - { 0120000, LINK_OURS_OID, 2, "link-4" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "link-4" }, - }; - - opts.checkout_strategy |= GIT_CHECKOUT_SAFE; - - create_index(checkout_index_entries, 12); - git_index_write(g_index); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - /* Typechange conflicts always keep the file in the workdir */ - ensure_workdir_oid("link-1", CONFLICTING_OURS_OID); - ensure_workdir_oid("link-2", CONFLICTING_THEIRS_OID); - ensure_workdir_oid("link-3", CONFLICTING_OURS_OID); - ensure_workdir_oid("link-4", CONFLICTING_THEIRS_OID); -} - -void test_checkout_conflict__links(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - struct checkout_index_entry checkout_index_entries[] = { - { 0120000, LINK_ANCESTOR_OID, 1, "link-1" }, - { 0120000, LINK_OURS_OID, 2, "link-1" }, - { 0120000, LINK_THEIRS_OID, 3, "link-1" }, - - { 0120000, LINK_OURS_OID, 2, "link-2" }, - { 0120000, LINK_THEIRS_OID, 3, "link-2" }, - }; - - opts.checkout_strategy |= GIT_CHECKOUT_SAFE; - - create_index(checkout_index_entries, 5); - git_index_write(g_index); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - /* Conflicts with links always keep the ours side (even with -Xtheirs) */ - ensure_workdir_link("link-1", LINK_OURS_TARGET); - ensure_workdir_link("link-2", LINK_OURS_TARGET); -} - -void test_checkout_conflict__add_add(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, CONFLICTING_OURS_OID, 2, "conflicting.txt" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting.txt" }, - }; - - opts.checkout_strategy |= GIT_CHECKOUT_SAFE; - - create_index(checkout_index_entries, 2); - git_index_write(g_index); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - /* Add/add writes diff3 files */ - ensure_workdir_contents("conflicting.txt", CONFLICTING_DIFF3_FILE); -} - -void test_checkout_conflict__mode_change(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "executable-1" }, - { 0100755, CONFLICTING_ANCESTOR_OID, 2, "executable-1" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "executable-1" }, - - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "executable-2" }, - { 0100644, CONFLICTING_OURS_OID, 2, "executable-2" }, - { 0100755, CONFLICTING_ANCESTOR_OID, 3, "executable-2" }, - - { 0100755, CONFLICTING_ANCESTOR_OID, 1, "executable-3" }, - { 0100644, CONFLICTING_ANCESTOR_OID, 2, "executable-3" }, - { 0100755, CONFLICTING_THEIRS_OID, 3, "executable-3" }, - - { 0100755, CONFLICTING_ANCESTOR_OID, 1, "executable-4" }, - { 0100755, CONFLICTING_OURS_OID, 2, "executable-4" }, - { 0100644, CONFLICTING_ANCESTOR_OID, 3, "executable-4" }, - - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "executable-5" }, - { 0100755, CONFLICTING_OURS_OID, 2, "executable-5" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "executable-5" }, - - { 0100755, CONFLICTING_ANCESTOR_OID, 1, "executable-6" }, - { 0100644, CONFLICTING_OURS_OID, 2, "executable-6" }, - { 0100755, CONFLICTING_THEIRS_OID, 3, "executable-6" }, - }; - - opts.checkout_strategy |= GIT_CHECKOUT_SAFE; - - create_index(checkout_index_entries, 18); - git_index_write(g_index); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - /* Keep the modified mode */ - ensure_workdir_oid("executable-1", CONFLICTING_THEIRS_OID); - ensure_workdir_mode("executable-1", 0100755); - - ensure_workdir_oid("executable-2", CONFLICTING_OURS_OID); - ensure_workdir_mode("executable-2", 0100755); - - ensure_workdir_oid("executable-3", CONFLICTING_THEIRS_OID); - ensure_workdir_mode("executable-3", 0100644); - - ensure_workdir_oid("executable-4", CONFLICTING_OURS_OID); - ensure_workdir_mode("executable-4", 0100644); - - ensure_workdir_contents("executable-5", CONFLICTING_DIFF3_FILE); - ensure_workdir_mode("executable-5", 0100755); - - ensure_workdir_contents("executable-6", CONFLICTING_DIFF3_FILE); - ensure_workdir_mode("executable-6", 0100644); -} - -void test_checkout_conflict__renames(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, - { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, - { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 1, "0b-rewritten-in-ours.txt" }, - { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 2, "0b-rewritten-in-ours.txt" }, - { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 3, "0b-rewritten-in-ours.txt" }, - { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, - { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 1, "0c-rewritten-in-theirs.txt" }, - { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 2, "0c-rewritten-in-theirs.txt" }, - { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 3, "0c-rewritten-in-theirs.txt" }, - { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, - { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, - { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, - { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, - { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, - { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 2, "3a-newname-in-ours-deleted-in-theirs.txt" }, - { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 1, "3a-renamed-in-ours-deleted-in-theirs.txt" }, - { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 3, "3b-newname-in-theirs-deleted-in-ours.txt" }, - { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 1, "3b-renamed-in-theirs-deleted-in-ours.txt" }, - { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 2, "4a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 3, "4a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 1, "4a-renamed-in-ours-added-in-theirs.txt" }, - { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 2, "4b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 3, "4b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 1, "4b-renamed-in-theirs-added-in-ours.txt" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 2, "5a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 3, "5a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 1, "5a-renamed-in-ours-added-in-theirs.txt" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 3, "5a-renamed-in-ours-added-in-theirs.txt" }, - { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 2, "5b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 3, "5b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 1, "5b-renamed-in-theirs-added-in-ours.txt" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 2, "5b-renamed-in-theirs-added-in-ours.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 2, "6-both-renamed-1-to-2-ours.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 3, "6-both-renamed-1-to-2-theirs.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 1, "6-both-renamed-1-to-2.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "7-both-renamed-side-1.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "7-both-renamed-side-1.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "7-both-renamed-side-2.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "7-both-renamed-side-2.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" } - }; - - struct checkout_name_entry checkout_name_entries[] = { - { - "3a-renamed-in-ours-deleted-in-theirs.txt", - "3a-newname-in-ours-deleted-in-theirs.txt", - "" - }, - - { - "3b-renamed-in-theirs-deleted-in-ours.txt", - "", - "3b-newname-in-theirs-deleted-in-ours.txt" - }, - - { - "4a-renamed-in-ours-added-in-theirs.txt", - "4a-newname-in-ours-added-in-theirs.txt", - "" - }, - - { - "4b-renamed-in-theirs-added-in-ours.txt", - "", - "4b-newname-in-theirs-added-in-ours.txt" - }, - - { - "5a-renamed-in-ours-added-in-theirs.txt", - "5a-newname-in-ours-added-in-theirs.txt", - "5a-renamed-in-ours-added-in-theirs.txt" - }, - - { - "5b-renamed-in-theirs-added-in-ours.txt", - "5b-renamed-in-theirs-added-in-ours.txt", - "5b-newname-in-theirs-added-in-ours.txt" - }, - - { - "6-both-renamed-1-to-2.txt", - "6-both-renamed-1-to-2-ours.txt", - "6-both-renamed-1-to-2-theirs.txt" - }, - - { - "7-both-renamed-side-1.txt", - "7-both-renamed.txt", - "7-both-renamed-side-1.txt" - }, - - { - "7-both-renamed-side-2.txt", - "7-both-renamed-side-2.txt", - "7-both-renamed.txt" - } - }; - - opts.checkout_strategy |= GIT_CHECKOUT_SAFE; - - create_index(checkout_index_entries, 41); - create_index_names(checkout_name_entries, 9); - git_index_write(g_index); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - ensure_workdir("0a-no-change.txt", - 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"); - - ensure_workdir("0b-duplicated-in-ours.txt", - 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6"); - - ensure_workdir("0b-rewritten-in-ours.txt", - 0100644, "4c7e515d6d52d820496858f2f059ece69e99e2e3"); - - ensure_workdir("0c-duplicated-in-theirs.txt", - 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31"); - - ensure_workdir("0c-rewritten-in-theirs.txt", - 0100644, "4648d658682d1155c2a3db5b0c53305e26884ea5"); - - ensure_workdir("1a-newname-in-ours-edited-in-theirs.txt", - 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638"); - - ensure_workdir("1a-newname-in-ours.txt", - 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"); - - ensure_workdir("1b-newname-in-theirs-edited-in-ours.txt", - 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a"); - - ensure_workdir("1b-newname-in-theirs.txt", - 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"); - - ensure_workdir("2-newname-in-both.txt", - 0100644, "178940b450f238a56c0d75b7955cb57b38191982"); - - ensure_workdir("3a-newname-in-ours-deleted-in-theirs.txt", - 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"); - - ensure_workdir("3b-newname-in-theirs-deleted-in-ours.txt", - 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495"); - - ensure_workdir("4a-newname-in-ours-added-in-theirs.txt~ours", - 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c"); - - ensure_workdir("4a-newname-in-ours-added-in-theirs.txt~theirs", - 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a"); - - ensure_workdir("4b-newname-in-theirs-added-in-ours.txt~ours", - 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9"); - - ensure_workdir("4b-newname-in-theirs-added-in-ours.txt~theirs", - 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db"); - - ensure_workdir("5a-newname-in-ours-added-in-theirs.txt~ours", - 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436"); - - ensure_workdir("5a-newname-in-ours-added-in-theirs.txt~theirs", - 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714"); - - ensure_workdir("5b-newname-in-theirs-added-in-ours.txt~ours", - 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced"); - - ensure_workdir("5b-newname-in-theirs-added-in-ours.txt~theirs", - 0100644, "63247125386de9ec90a27ad36169307bf8a11a38"); - - ensure_workdir("6-both-renamed-1-to-2-ours.txt", - 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450"); - - ensure_workdir("6-both-renamed-1-to-2-theirs.txt", - 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450"); - - ensure_workdir("7-both-renamed.txt~ours", - 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); - - ensure_workdir("7-both-renamed.txt~theirs", - 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); -} - -void test_checkout_conflict__rename_keep_ours(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, - { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, - { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 1, "0b-rewritten-in-ours.txt" }, - { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 2, "0b-rewritten-in-ours.txt" }, - { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 3, "0b-rewritten-in-ours.txt" }, - { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, - { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 1, "0c-rewritten-in-theirs.txt" }, - { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 2, "0c-rewritten-in-theirs.txt" }, - { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 3, "0c-rewritten-in-theirs.txt" }, - { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, - { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, - { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, - { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, - { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, - { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 2, "3a-newname-in-ours-deleted-in-theirs.txt" }, - { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 1, "3a-renamed-in-ours-deleted-in-theirs.txt" }, - { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 3, "3b-newname-in-theirs-deleted-in-ours.txt" }, - { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 1, "3b-renamed-in-theirs-deleted-in-ours.txt" }, - { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 2, "4a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 3, "4a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 1, "4a-renamed-in-ours-added-in-theirs.txt" }, - { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 2, "4b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 3, "4b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 1, "4b-renamed-in-theirs-added-in-ours.txt" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 2, "5a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 3, "5a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 1, "5a-renamed-in-ours-added-in-theirs.txt" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 3, "5a-renamed-in-ours-added-in-theirs.txt" }, - { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 2, "5b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 3, "5b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 1, "5b-renamed-in-theirs-added-in-ours.txt" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 2, "5b-renamed-in-theirs-added-in-ours.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 2, "6-both-renamed-1-to-2-ours.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 3, "6-both-renamed-1-to-2-theirs.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 1, "6-both-renamed-1-to-2.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "7-both-renamed-side-1.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "7-both-renamed-side-1.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "7-both-renamed-side-2.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "7-both-renamed-side-2.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" } - }; - - struct checkout_name_entry checkout_name_entries[] = { - { - "3a-renamed-in-ours-deleted-in-theirs.txt", - "3a-newname-in-ours-deleted-in-theirs.txt", - "" - }, - - { - "3b-renamed-in-theirs-deleted-in-ours.txt", - "", - "3b-newname-in-theirs-deleted-in-ours.txt" - }, - - { - "4a-renamed-in-ours-added-in-theirs.txt", - "4a-newname-in-ours-added-in-theirs.txt", - "" - }, - - { - "4b-renamed-in-theirs-added-in-ours.txt", - "", - "4b-newname-in-theirs-added-in-ours.txt" - }, - - { - "5a-renamed-in-ours-added-in-theirs.txt", - "5a-newname-in-ours-added-in-theirs.txt", - "5a-renamed-in-ours-added-in-theirs.txt" - }, - - { - "5b-renamed-in-theirs-added-in-ours.txt", - "5b-renamed-in-theirs-added-in-ours.txt", - "5b-newname-in-theirs-added-in-ours.txt" - }, - - { - "6-both-renamed-1-to-2.txt", - "6-both-renamed-1-to-2-ours.txt", - "6-both-renamed-1-to-2-theirs.txt" - }, - - { - "7-both-renamed-side-1.txt", - "7-both-renamed.txt", - "7-both-renamed-side-1.txt" - }, - - { - "7-both-renamed-side-2.txt", - "7-both-renamed-side-2.txt", - "7-both-renamed.txt" - } - }; - - opts.checkout_strategy |= GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS; - - create_index(checkout_index_entries, 41); - create_index_names(checkout_name_entries, 9); - git_index_write(g_index); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - ensure_workdir("0a-no-change.txt", - 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"); - - ensure_workdir("0b-duplicated-in-ours.txt", - 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6"); - - ensure_workdir("0b-rewritten-in-ours.txt", - 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e"); - - ensure_workdir("0c-duplicated-in-theirs.txt", - 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31"); - - ensure_workdir("0c-rewritten-in-theirs.txt", - 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09"); - - ensure_workdir("1a-newname-in-ours-edited-in-theirs.txt", - 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638"); - - ensure_workdir("1a-newname-in-ours.txt", - 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"); - - ensure_workdir("1b-newname-in-theirs-edited-in-ours.txt", - 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a"); - - ensure_workdir("1b-newname-in-theirs.txt", - 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"); - - ensure_workdir("2-newname-in-both.txt", - 0100644, "178940b450f238a56c0d75b7955cb57b38191982"); - - ensure_workdir("3a-newname-in-ours-deleted-in-theirs.txt", - 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"); - - ensure_workdir("3b-newname-in-theirs-deleted-in-ours.txt", - 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495"); - - ensure_workdir("4a-newname-in-ours-added-in-theirs.txt", - 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c"); - - ensure_workdir("4b-newname-in-theirs-added-in-ours.txt", - 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9"); - - ensure_workdir("5a-newname-in-ours-added-in-theirs.txt", - 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436"); - - ensure_workdir("5b-newname-in-theirs-added-in-ours.txt", - 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced"); - - ensure_workdir("6-both-renamed-1-to-2-ours.txt", - 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450"); - - ensure_workdir("7-both-renamed.txt", - 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); -} - -void test_checkout_conflict__name_mangled_file_exists_in_workdir(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "test-one-side-one.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "test-one-side-one.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "test-one-side-two.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "test-one-side-two.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "test-one.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "test-one.txt" }, - - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "test-two-side-one.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "test-two-side-one.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "test-two-side-two.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "test-two-side-two.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "test-two.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "test-two.txt" }, - - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "test-three-side-one.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "test-three-side-one.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "test-three-side-two.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "test-three-side-two.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "test-three.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "test-three.txt" }, - - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-one" }, - { 0100644, CONFLICTING_OURS_OID, 2, "directory_file-one" }, - { 0100644, CONFLICTING_THEIRS_OID, 0, "directory_file-one/file" }, - - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-two" }, - { 0100644, CONFLICTING_OURS_OID, 0, "directory_file-two/file" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "directory_file-two" }, - }; - - struct checkout_name_entry checkout_name_entries[] = { - { - "test-one-side-one.txt", - "test-one.txt", - "test-one-side-one.txt" - }, - { - "test-one-side-two.txt", - "test-one-side-two.txt", - "test-one.txt" - }, - - { - "test-two-side-one.txt", - "test-two.txt", - "test-two-side-one.txt" - }, - { - "test-two-side-two.txt", - "test-two-side-two.txt", - "test-two.txt" - }, - - { - "test-three-side-one.txt", - "test-three.txt", - "test-three-side-one.txt" - }, - { - "test-three-side-two.txt", - "test-three-side-two.txt", - "test-three.txt" - } - }; - - opts.checkout_strategy |= GIT_CHECKOUT_SAFE; - - create_index(checkout_index_entries, 24); - create_index_names(checkout_name_entries, 6); - git_index_write(g_index); - - /* Add some files on disk that conflict with the names that would be chosen - * for the files written for each side. */ - - cl_git_rewritefile("merge-resolve/test-one.txt~ours", - "Expect index contents to be written to ~ours_0"); - cl_git_rewritefile("merge-resolve/test-one.txt~theirs", - "Expect index contents to be written to ~theirs_0"); - - cl_git_rewritefile("merge-resolve/test-two.txt~ours", - "Expect index contents to be written to ~ours_3"); - cl_git_rewritefile("merge-resolve/test-two.txt~theirs", - "Expect index contents to be written to ~theirs_3"); - cl_git_rewritefile("merge-resolve/test-two.txt~ours_0", - "Expect index contents to be written to ~ours_3"); - cl_git_rewritefile("merge-resolve/test-two.txt~theirs_0", - "Expect index contents to be written to ~theirs_3"); - cl_git_rewritefile("merge-resolve/test-two.txt~ours_1", - "Expect index contents to be written to ~ours_3"); - cl_git_rewritefile("merge-resolve/test-two.txt~theirs_1", - "Expect index contents to be written to ~theirs_3"); - cl_git_rewritefile("merge-resolve/test-two.txt~ours_2", - "Expect index contents to be written to ~ours_3"); - cl_git_rewritefile("merge-resolve/test-two.txt~theirs_2", - "Expect index contents to be written to ~theirs_3"); - - cl_git_rewritefile("merge-resolve/test-three.txt~Ours", - "Expect case insensitive filesystems to create ~ours_0"); - cl_git_rewritefile("merge-resolve/test-three.txt~THEIRS", - "Expect case insensitive filesystems to create ~theirs_0"); - - cl_git_rewritefile("merge-resolve/directory_file-one~ours", - "Index contents written to ~ours_0 in this D/F conflict"); - cl_git_rewritefile("merge-resolve/directory_file-two~theirs", - "Index contents written to ~theirs_0 in this D/F conflict"); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - ensure_workdir("test-one.txt~ours_0", - 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); - ensure_workdir("test-one.txt~theirs_0", - 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); - - ensure_workdir("test-two.txt~ours_3", - 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); - ensure_workdir("test-two.txt~theirs_3", - 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); - - /* Name is mangled on case insensitive only */ -#if defined(GIT_WIN32) || defined(__APPLE__) - ensure_workdir("test-three.txt~ours_0", - 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); - ensure_workdir("test-three.txt~theirs_0", - 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); -#else - ensure_workdir("test-three.txt~ours", - 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); - ensure_workdir("test-three.txt~theirs", - 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); -#endif - - ensure_workdir("directory_file-one~ours_0", 0100644, CONFLICTING_OURS_OID); - ensure_workdir("directory_file-two~theirs_0", 0100644, CONFLICTING_THEIRS_OID); -} - -void test_checkout_conflict__update_only(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "automergeable.txt" }, - { 0100644, AUTOMERGEABLE_OURS_OID, 2, "automergeable.txt" }, - { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "automergeable.txt" }, - - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "modify-delete" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "modify-delete" }, - - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-one" }, - { 0100644, CONFLICTING_OURS_OID, 2, "directory_file-one" }, - { 0100644, CONFLICTING_THEIRS_OID, 0, "directory_file-one/file" }, - - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-two" }, - { 0100644, CONFLICTING_OURS_OID, 0, "directory_file-two/file" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "directory_file-two" }, - }; - - opts.checkout_strategy |= GIT_CHECKOUT_UPDATE_ONLY; - - create_index(checkout_index_entries, 3); - git_index_write(g_index); - - cl_git_pass(p_mkdir("merge-resolve/directory_file-two", 0777)); - cl_git_rewritefile("merge-resolve/directory_file-two/file", CONFLICTING_OURS_FILE); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - ensure_workdir_contents("automergeable.txt", AUTOMERGEABLE_MERGED_FILE); - ensure_workdir("directory_file-two/file", 0100644, CONFLICTING_OURS_OID); - - cl_assert(!git_path_exists("merge-resolve/modify-delete")); - cl_assert(!git_path_exists("merge-resolve/test-one.txt")); - cl_assert(!git_path_exists("merge-resolve/test-one-side-one.txt")); - cl_assert(!git_path_exists("merge-resolve/test-one-side-two.txt")); - cl_assert(!git_path_exists("merge-resolve/test-one.txt~ours")); - cl_assert(!git_path_exists("merge-resolve/test-one.txt~theirs")); - cl_assert(!git_path_exists("merge-resolve/directory_file-one/file")); - cl_assert(!git_path_exists("merge-resolve/directory_file-one~ours")); - cl_assert(!git_path_exists("merge-resolve/directory_file-two~theirs")); -} - -void test_checkout_conflict__path_filters(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - char *paths[] = { "conflicting-1.txt", "conflicting-3.txt" }; - git_strarray patharray = {0}; - - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-1.txt" }, - { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-1.txt" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-1.txt" }, - - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-2.txt" }, - { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-2.txt" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-2.txt" }, - - { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-3.txt" }, - { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-3.txt" }, - { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-3.txt" }, - - { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-4.txt" }, - { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-4.txt" }, - { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-4.txt" }, - }; - - patharray.count = 2; - patharray.strings = paths; - - opts.paths = patharray; - - create_index(checkout_index_entries, 12); - git_index_write(g_index); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - ensure_workdir_contents("conflicting-1.txt", CONFLICTING_DIFF3_FILE); - cl_assert(!git_path_exists("merge-resolve/conflicting-2.txt")); - ensure_workdir_contents("conflicting-3.txt", AUTOMERGEABLE_MERGED_FILE); - cl_assert(!git_path_exists("merge-resolve/conflicting-4.txt")); -} - -static void collect_progress( - const char *path, - size_t completed_steps, - size_t total_steps, - void *payload) -{ - git_vector *paths = payload; - - (void)completed_steps; - (void)total_steps; - - if (path == NULL) - return; - - git_vector_insert(paths, strdup(path)); -} - -void test_checkout_conflict__report_progress(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_vector paths = GIT_VECTOR_INIT; - char *path; - size_t i; - - struct checkout_index_entry checkout_index_entries[] = { - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-1.txt" }, - { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-1.txt" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-1.txt" }, - - { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-2.txt" }, - { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-2.txt" }, - { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-2.txt" }, - - { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-3.txt" }, - { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-3.txt" }, - { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-3.txt" }, - - { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-4.txt" }, - { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-4.txt" }, - { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-4.txt" }, - }; - - opts.progress_cb = collect_progress; - opts.progress_payload = &paths; - - - create_index(checkout_index_entries, 12); - git_index_write(g_index); - - cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - - cl_assert_equal_i(4, git_vector_length(&paths)); - cl_assert_equal_s("conflicting-1.txt", git_vector_get(&paths, 0)); - cl_assert_equal_s("conflicting-2.txt", git_vector_get(&paths, 1)); - cl_assert_equal_s("conflicting-3.txt", git_vector_get(&paths, 2)); - cl_assert_equal_s("conflicting-4.txt", git_vector_get(&paths, 3)); - - git_vector_foreach(&paths, i, path) - git__free(path); - - git_vector_free(&paths); -} diff --git a/tests-clar/checkout/crlf.c b/tests-clar/checkout/crlf.c deleted file mode 100644 index 9a4cbd313..000000000 --- a/tests-clar/checkout/crlf.c +++ /dev/null @@ -1,231 +0,0 @@ -#include "clar_libgit2.h" -#include "checkout_helpers.h" -#include "../filter/crlf.h" - -#include "git2/checkout.h" -#include "repository.h" -#include "posix.h" - -static git_repository *g_repo; - -void test_checkout_crlf__initialize(void) -{ - g_repo = cl_git_sandbox_init("crlf"); -} - -void test_checkout_crlf__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_checkout_crlf__detect_crlf_autocrlf_false(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_repo_set_bool(g_repo, "core.autocrlf", false); - - git_checkout_head(g_repo, &opts); - - check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW); - check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW); -} - -void test_checkout_crlf__autocrlf_false_index_size_is_unfiltered_size(void) -{ - git_index *index; - const git_index_entry *entry; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_repo_set_bool(g_repo, "core.autocrlf", false); - - git_checkout_head(g_repo, &opts); - - git_repository_index(&index, g_repo); - - cl_assert((entry = git_index_get_bypath(index, "all-lf", 0)) != NULL); - cl_assert(entry->file_size == strlen(ALL_LF_TEXT_RAW)); - - cl_assert((entry = git_index_get_bypath(index, "all-crlf", 0)) != NULL); - cl_assert(entry->file_size == strlen(ALL_CRLF_TEXT_RAW)); - - git_index_free(index); -} - -void test_checkout_crlf__detect_crlf_autocrlf_true(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - git_checkout_head(g_repo, &opts); - - if (GIT_EOL_NATIVE == GIT_EOL_LF) - check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW); - else - check_file_contents("./crlf/all-lf", ALL_LF_TEXT_AS_CRLF); - - check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW); -} - -void test_checkout_crlf__more_lf_autocrlf_true(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - git_checkout_head(g_repo, &opts); - - if (GIT_EOL_NATIVE == GIT_EOL_LF) - check_file_contents("./crlf/more-lf", MORE_LF_TEXT_RAW); - else - check_file_contents("./crlf/more-lf", MORE_LF_TEXT_AS_CRLF); -} - -void test_checkout_crlf__more_crlf_autocrlf_true(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - git_checkout_head(g_repo, &opts); - - if (GIT_EOL_NATIVE == GIT_EOL_LF) - check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_RAW); - else - check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_AS_CRLF); -} - -void test_checkout_crlf__all_crlf_autocrlf_true(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - git_checkout_head(g_repo, &opts); - - check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW); -} - -void test_checkout_crlf__autocrlf_true_index_size_is_filtered_size(void) -{ - git_index *index; - const git_index_entry *entry; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - git_checkout_head(g_repo, &opts); - - git_repository_index(&index, g_repo); - - cl_assert((entry = git_index_get_bypath(index, "all-lf", 0)) != NULL); - - if (GIT_EOL_NATIVE == GIT_EOL_LF) - cl_assert_equal_sz(strlen(ALL_LF_TEXT_RAW), entry->file_size); - else - cl_assert_equal_sz(strlen(ALL_LF_TEXT_AS_CRLF), entry->file_size); - - cl_assert((entry = git_index_get_bypath(index, "all-crlf", 0)) != NULL); - cl_assert_equal_sz(strlen(ALL_CRLF_TEXT_RAW), entry->file_size); - - git_index_free(index); -} - -void test_checkout_crlf__with_ident(void) -{ - git_index *index; - git_blob *blob; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_git_mkfile("crlf/.gitattributes", - "*.txt text\n*.bin binary\n" - "*.crlf text eol=crlf\n" - "*.lf text eol=lf\n" - "*.ident text ident\n" - "*.identcrlf ident text eol=crlf\n" - "*.identlf ident text eol=lf\n"); - - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - /* add files with $Id$ */ - - cl_git_mkfile("crlf/lf.ident", ALL_LF_TEXT_RAW "\n$Id: initial content$\n"); - cl_git_mkfile("crlf/crlf.ident", ALL_CRLF_TEXT_RAW "\r\n$Id$\r\n\r\n"); - cl_git_mkfile("crlf/more1.identlf", "$Id$\n" MORE_LF_TEXT_RAW); - cl_git_mkfile("crlf/more2.identcrlf", "\r\n$Id: $\r\n" MORE_CRLF_TEXT_RAW); - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_index_add_bypath(index, "lf.ident")); - cl_git_pass(git_index_add_bypath(index, "crlf.ident")); - cl_git_pass(git_index_add_bypath(index, "more1.identlf")); - cl_git_pass(git_index_add_bypath(index, "more2.identcrlf")); - cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "Some ident files\n"); - - git_checkout_head(g_repo, &opts); - - /* check that blobs have $Id$ */ - - cl_git_pass(git_blob_lookup(&blob, g_repo, - & git_index_get_bypath(index, "lf.ident", 0)->oid)); - cl_assert_equal_s( - ALL_LF_TEXT_RAW "\n$Id$\n", git_blob_rawcontent(blob)); - git_blob_free(blob); - - cl_git_pass(git_blob_lookup(&blob, g_repo, - & git_index_get_bypath(index, "more2.identcrlf", 0)->oid)); - cl_assert_equal_s( - "\n$Id$\n" MORE_CRLF_TEXT_AS_LF, git_blob_rawcontent(blob)); - git_blob_free(blob); - - /* check that filesystem is initially untouched - matching core Git */ - - cl_assert_equal_file( - ALL_LF_TEXT_RAW "\n$Id: initial content$\n", 0, "crlf/lf.ident"); - - /* check that forced checkout rewrites correctly */ - - p_unlink("crlf/lf.ident"); - p_unlink("crlf/crlf.ident"); - p_unlink("crlf/more1.identlf"); - p_unlink("crlf/more2.identcrlf"); - - git_checkout_head(g_repo, &opts); - - if (GIT_EOL_NATIVE == GIT_EOL_LF) { - cl_assert_equal_file( - ALL_LF_TEXT_RAW - "\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467$\n", - 0, "crlf/lf.ident"); - cl_assert_equal_file( - ALL_CRLF_TEXT_AS_LF - "\n$Id: f2c66ad9b2b5a734d9bf00d5000cc10a62b8a857$\n\n", - 0, "crlf/crlf.ident"); - } else { - cl_assert_equal_file( - ALL_LF_TEXT_AS_CRLF - "\r\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467$\r\n", - 0, "crlf/lf.ident"); - cl_assert_equal_file( - ALL_CRLF_TEXT_RAW - "\r\n$Id: f2c66ad9b2b5a734d9bf00d5000cc10a62b8a857$\r\n\r\n", - 0, "crlf/crlf.ident"); - } - - cl_assert_equal_file( - "$Id: f7830382dac1f1583422be5530fdfbd26289431b$\n" - MORE_LF_TEXT_AS_LF, 0, "crlf/more1.identlf"); - - cl_assert_equal_file( - "\r\n$Id: 74677a68413012ce8d7e7cfc3f12603df3a3eac4$\r\n" - MORE_CRLF_TEXT_AS_CRLF, 0, "crlf/more2.identcrlf"); - - git_index_free(index); -} diff --git a/tests-clar/checkout/head.c b/tests-clar/checkout/head.c deleted file mode 100644 index a7a7e9071..000000000 --- a/tests-clar/checkout/head.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" -#include "repo/repo_helpers.h" -#include "path.h" -#include "fileops.h" - -static git_repository *g_repo; - -void test_checkout_head__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_checkout_head__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_checkout_head__unborn_head_returns_GIT_EUNBORNBRANCH(void) -{ - make_head_unborn(g_repo, NON_EXISTING_HEAD); - - cl_assert_equal_i(GIT_EUNBORNBRANCH, git_checkout_head(g_repo, NULL)); -} - -void test_checkout_head__with_index_only_tree(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_index *index; - - /* let's start by getting things into a known state */ - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - cl_git_pass(git_checkout_head(g_repo, &opts)); - - /* now let's stage some new stuff including a new directory */ - - cl_git_pass(git_repository_index(&index, g_repo)); - - p_mkdir("testrepo/newdir", 0777); - cl_git_mkfile("testrepo/newdir/newfile.txt", "new file\n"); - - cl_git_pass(git_index_add_bypath(index, "newdir/newfile.txt")); - cl_git_pass(git_index_write(index)); - - cl_assert(git_path_isfile("testrepo/newdir/newfile.txt")); - cl_assert(git_index_get_bypath(index, "newdir/newfile.txt", 0) != NULL); - - git_index_free(index); - - /* okay, so now we have staged this new file; let's see if we can remove */ - - opts.checkout_strategy = GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED; - cl_git_pass(git_checkout_head(g_repo, &opts)); - - cl_git_pass(git_repository_index(&index, g_repo)); - - cl_assert(!git_path_isfile("testrepo/newdir/newfile.txt")); - cl_assert(git_index_get_bypath(index, "newdir/newfile.txt", 0) == NULL); - - git_index_free(index); -} diff --git a/tests-clar/checkout/index.c b/tests-clar/checkout/index.c deleted file mode 100644 index 48d6d79f9..000000000 --- a/tests-clar/checkout/index.c +++ /dev/null @@ -1,620 +0,0 @@ -#include "clar_libgit2.h" -#include "checkout_helpers.h" - -#include "git2/checkout.h" -#include "fileops.h" -#include "repository.h" - -static git_repository *g_repo; - -void test_checkout_index__initialize(void) -{ - git_tree *tree; - - g_repo = cl_git_sandbox_init("testrepo"); - - cl_git_pass(git_repository_head_tree(&tree, g_repo)); - - reset_index_to_treeish((git_object *)tree); - git_tree_free(tree); - - cl_git_rewritefile( - "./testrepo/.gitattributes", - "* text eol=lf\n"); -} - -void test_checkout_index__cleanup(void) -{ - cl_git_sandbox_cleanup(); - - /* try to remove alternative dir */ - if (git_path_isdir("alternative")) - git_futils_rmdir_r("alternative", NULL, GIT_RMDIR_REMOVE_FILES); -} - -void test_checkout_index__cannot_checkout_a_bare_repository(void) -{ - test_checkout_index__cleanup(); - - g_repo = cl_git_sandbox_init("testrepo.git"); - - cl_git_fail(git_checkout_index(g_repo, NULL, NULL)); -} - -void test_checkout_index__can_create_missing_files(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - cl_assert_equal_i(false, git_path_isfile("./testrepo/README")); - cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt")); - cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt")); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - check_file_contents("./testrepo/README", "hey there\n"); - check_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n"); - check_file_contents("./testrepo/new.txt", "my new file\n"); -} - -void test_checkout_index__can_remove_untracked_files(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - git_futils_mkdir("./testrepo/dir/subdir/subsubdir", NULL, 0755, GIT_MKDIR_PATH); - cl_git_mkfile("./testrepo/dir/one", "one\n"); - cl_git_mkfile("./testrepo/dir/subdir/two", "two\n"); - - cl_assert_equal_i(true, git_path_isdir("./testrepo/dir/subdir/subsubdir")); - - opts.checkout_strategy = - GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_REMOVE_UNTRACKED; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - cl_assert_equal_i(false, git_path_isdir("./testrepo/dir")); -} - -void test_checkout_index__honor_the_specified_pathspecs(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - char *entries[] = { "*.txt" }; - - opts.paths.strings = entries; - opts.paths.count = 1; - - cl_assert_equal_i(false, git_path_isfile("./testrepo/README")); - cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt")); - cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt")); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - cl_assert_equal_i(false, git_path_isfile("./testrepo/README")); - check_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n"); - check_file_contents("./testrepo/new.txt", "my new file\n"); -} - -void test_checkout_index__honor_the_gitattributes_directives(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - const char *attributes = - "branch_file.txt text eol=crlf\n" - "new.txt text eol=lf\n"; - - cl_git_mkfile("./testrepo/.gitattributes", attributes); - cl_repo_set_bool(g_repo, "core.autocrlf", false); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - check_file_contents("./testrepo/README", "hey there\n"); - check_file_contents("./testrepo/new.txt", "my new file\n"); - check_file_contents("./testrepo/branch_file.txt", "hi\r\nbye!\r\n"); -} - -void test_checkout_index__honor_coreautocrlf_setting_set_to_true(void) -{ -#ifdef GIT_WIN32 - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - const char *expected_readme_text = "hey there\r\n"; - - cl_git_pass(p_unlink("./testrepo/.gitattributes")); - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - check_file_contents("./testrepo/README", expected_readme_text); -#endif -} - -void test_checkout_index__honor_coresymlinks_setting_set_to_true(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - cl_repo_set_bool(g_repo, "core.symlinks", true); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - -#ifdef GIT_WIN32 - check_file_contents("./testrepo/link_to_new.txt", "new.txt"); -#else - { - char link_data[1024]; - size_t link_size = 1024; - - link_size = p_readlink("./testrepo/link_to_new.txt", link_data, link_size); - link_data[link_size] = '\0'; - cl_assert_equal_i(link_size, strlen("new.txt")); - cl_assert_equal_s(link_data, "new.txt"); - check_file_contents("./testrepo/link_to_new.txt", "my new file\n"); - } -#endif -} - -void test_checkout_index__honor_coresymlinks_setting_set_to_false(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - cl_repo_set_bool(g_repo, "core.symlinks", false); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - check_file_contents("./testrepo/link_to_new.txt", "new.txt"); -} - -void test_checkout_index__donot_overwrite_modified_file_by_default(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!"); - - /* set this up to not return an error code on conflicts, but it - * still will not have permission to overwrite anything... - */ - opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - check_file_contents("./testrepo/new.txt", "This isn't what's stored!"); -} - -void test_checkout_index__can_overwrite_modified_file(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!"); - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - check_file_contents("./testrepo/new.txt", "my new file\n"); -} - -void test_checkout_index__options_disable_filters(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - cl_git_mkfile("./testrepo/.gitattributes", "*.txt text eol=crlf\n"); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - opts.disable_filters = false; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - check_file_contents("./testrepo/new.txt", "my new file\r\n"); - - p_unlink("./testrepo/new.txt"); - - opts.disable_filters = true; - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - check_file_contents("./testrepo/new.txt", "my new file\n"); -} - -void test_checkout_index__options_dir_modes(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - struct stat st; - git_oid oid; - git_commit *commit; - mode_t um; - - if (!cl_is_chmod_supported()) - return; - - cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); - cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); - - reset_index_to_treeish((git_object *)commit); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - opts.dir_mode = 0701; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - /* umask will influence actual directory creation mode */ - (void)p_umask(um = p_umask(022)); - - cl_git_pass(p_stat("./testrepo/a", &st)); - cl_assert_equal_i_fmt(st.st_mode, (GIT_FILEMODE_TREE | 0701) & ~um, "%07o"); - - /* File-mode test, since we're on the 'dir' branch */ - cl_git_pass(p_stat("./testrepo/a/b.txt", &st)); - cl_assert_equal_i_fmt(st.st_mode, GIT_FILEMODE_BLOB_EXECUTABLE, "%07o"); - - git_commit_free(commit); -} - -void test_checkout_index__options_override_file_modes(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - struct stat st; - - if (!cl_is_chmod_supported()) - return; - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - opts.file_mode = 0700; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - cl_git_pass(p_stat("./testrepo/new.txt", &st)); - cl_assert_equal_i_fmt(st.st_mode & GIT_MODE_PERMS_MASK, 0700, "%07o"); -} - -void test_checkout_index__options_open_flags(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - cl_git_mkfile("./testrepo/new.txt", "hi\n"); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - opts.file_open_flags = O_CREAT | O_RDWR | O_APPEND; - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - check_file_contents("./testrepo/new.txt", "hi\nmy new file\n"); -} - -struct notify_data { - const char *file; - const char *sha; -}; - -static int test_checkout_notify_cb( - git_checkout_notify_t why, - const char *path, - const git_diff_file *baseline, - const git_diff_file *target, - const git_diff_file *workdir, - void *payload) -{ - struct notify_data *expectations = (struct notify_data *)payload; - - GIT_UNUSED(workdir); - - cl_assert_equal_i(GIT_CHECKOUT_NOTIFY_CONFLICT, why); - cl_assert_equal_s(expectations->file, path); - cl_assert_equal_i(0, git_oid_streq(&baseline->oid, expectations->sha)); - cl_assert_equal_i(0, git_oid_streq(&target->oid, expectations->sha)); - - return 0; -} - -void test_checkout_index__can_notify_of_skipped_files(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - struct notify_data data; - - cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!"); - - /* - * $ git ls-tree HEAD - * 100644 blob a8233120f6ad708f843d861ce2b7228ec4e3dec6 README - * 100644 blob 3697d64be941a53d4ae8f6a271e4e3fa56b022cc branch_file.txt - * 100644 blob a71586c1dfe8a71c6cbf6c129f404c5642ff31bd new.txt - */ - data.file = "new.txt"; - data.sha = "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd"; - - opts.checkout_strategy = - GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS; - opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT; - opts.notify_cb = test_checkout_notify_cb; - opts.notify_payload = &data; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); -} - -static int dont_notify_cb( - git_checkout_notify_t why, - const char *path, - const git_diff_file *baseline, - const git_diff_file *target, - const git_diff_file *workdir, - void *payload) -{ - GIT_UNUSED(why); - GIT_UNUSED(path); - GIT_UNUSED(baseline); - GIT_UNUSED(target); - GIT_UNUSED(workdir); - GIT_UNUSED(payload); - - cl_assert(false); - - return 0; -} - -void test_checkout_index__wont_notify_of_expected_line_ending_changes(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - cl_git_pass(p_unlink("./testrepo/.gitattributes")); - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - cl_git_mkfile("./testrepo/new.txt", "my new file\r\n"); - - opts.checkout_strategy = - GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS; - opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT; - opts.notify_cb = dont_notify_cb; - opts.notify_payload = NULL; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); -} - -static void checkout_progress_counter( - const char *path, size_t cur, size_t tot, void *payload) -{ - GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot); - (*(int *)payload)++; -} - -void test_checkout_index__calls_progress_callback(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - int calls = 0; - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - opts.progress_cb = checkout_progress_counter; - opts.progress_payload = &calls; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - cl_assert(calls > 0); -} - -void test_checkout_index__can_overcome_name_clashes(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_index *index; - - cl_git_pass(git_repository_index(&index, g_repo)); - git_index_clear(index); - - cl_git_mkfile("./testrepo/path0", "content\r\n"); - cl_git_pass(p_mkdir("./testrepo/path1", 0777)); - cl_git_mkfile("./testrepo/path1/file1", "content\r\n"); - - cl_git_pass(git_index_add_bypath(index, "path0")); - cl_git_pass(git_index_add_bypath(index, "path1/file1")); - - cl_git_pass(p_unlink("./testrepo/path0")); - cl_git_pass(git_futils_rmdir_r( - "./testrepo/path1", NULL, GIT_RMDIR_REMOVE_FILES)); - - cl_git_mkfile("./testrepo/path1", "content\r\n"); - cl_git_pass(p_mkdir("./testrepo/path0", 0777)); - cl_git_mkfile("./testrepo/path0/file0", "content\r\n"); - - cl_assert(git_path_isfile("./testrepo/path1")); - cl_assert(git_path_isfile("./testrepo/path0/file0")); - - opts.checkout_strategy = - GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS; - cl_git_pass(git_checkout_index(g_repo, index, &opts)); - - cl_assert(git_path_isfile("./testrepo/path1")); - cl_assert(git_path_isfile("./testrepo/path0/file0")); - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - cl_git_pass(git_checkout_index(g_repo, index, &opts)); - - cl_assert(git_path_isfile("./testrepo/path0")); - cl_assert(git_path_isfile("./testrepo/path1/file1")); - - git_index_free(index); -} - -void test_checkout_index__validates_struct_version(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - const git_error *err; - - opts.version = 1024; - cl_git_fail(git_checkout_index(g_repo, NULL, &opts)); - - err = giterr_last(); - cl_assert_equal_i(err->klass, GITERR_INVALID); - - opts.version = 0; - giterr_clear(); - cl_git_fail(git_checkout_index(g_repo, NULL, &opts)); - - err = giterr_last(); - cl_assert_equal_i(err->klass, GITERR_INVALID); -} - -void test_checkout_index__can_update_prefixed_files(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - cl_assert_equal_i(false, git_path_isfile("./testrepo/README")); - cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt")); - cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt")); - - cl_git_mkfile("./testrepo/READ", "content\n"); - cl_git_mkfile("./testrepo/README.after", "content\n"); - cl_git_pass(p_mkdir("./testrepo/branch_file", 0777)); - cl_git_pass(p_mkdir("./testrepo/branch_file/contained_dir", 0777)); - cl_git_mkfile("./testrepo/branch_file/contained_file", "content\n"); - cl_git_pass(p_mkdir("./testrepo/branch_file.txt.after", 0777)); - - opts.checkout_strategy = - GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_REMOVE_UNTRACKED; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - /* remove untracked will remove the .gitattributes file before the blobs - * were created, so they will have had crlf filtering applied on Windows - */ - check_file_contents_nocr("./testrepo/README", "hey there\n"); - check_file_contents_nocr("./testrepo/branch_file.txt", "hi\nbye!\n"); - check_file_contents_nocr("./testrepo/new.txt", "my new file\n"); - - cl_assert(!git_path_exists("testrepo/READ")); - cl_assert(!git_path_exists("testrepo/README.after")); - cl_assert(!git_path_exists("testrepo/branch_file")); - cl_assert(!git_path_exists("testrepo/branch_file.txt.after")); -} - -void test_checkout_index__can_checkout_a_newly_initialized_repository(void) -{ - test_checkout_index__cleanup(); - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - cl_git_remove_placeholders(git_repository_path(g_repo), "dummy-marker.txt"); - - cl_git_pass(git_checkout_index(g_repo, NULL, NULL)); -} - -void test_checkout_index__issue_1397(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - test_checkout_index__cleanup(); - - g_repo = cl_git_sandbox_init("issue_1397"); - - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - check_file_contents("./issue_1397/crlf_file.txt", "first line\r\nsecond line\r\nboth with crlf"); -} - -void test_checkout_index__target_directory(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - checkout_counts cts; - memset(&cts, 0, sizeof(cts)); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - opts.target_directory = "alternative"; - cl_assert(!git_path_isdir("alternative")); - - opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL; - opts.notify_cb = checkout_count_callback; - opts.notify_payload = &cts; - - /* create some files that *would* conflict if we were using the wd */ - cl_git_mkfile("testrepo/README", "I'm in the way!\n"); - cl_git_mkfile("testrepo/new.txt", "my new file\n"); - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - cl_assert_equal_i(0, cts.n_untracked); - cl_assert_equal_i(0, cts.n_ignored); - cl_assert_equal_i(4, cts.n_updates); - - check_file_contents("./alternative/README", "hey there\n"); - check_file_contents("./alternative/branch_file.txt", "hi\nbye!\n"); - check_file_contents("./alternative/new.txt", "my new file\n"); - - cl_git_pass(git_futils_rmdir_r( - "alternative", NULL, GIT_RMDIR_REMOVE_FILES)); -} - -void test_checkout_index__target_directory_from_bare(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_index *index; - git_object *head = NULL; - checkout_counts cts; - memset(&cts, 0, sizeof(cts)); - - test_checkout_index__cleanup(); - - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_assert(git_repository_is_bare(g_repo)); - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_revparse_single(&head, g_repo, "HEAD^{tree}")); - cl_git_pass(git_index_read_tree(index, (const git_tree *)head)); - cl_git_pass(git_index_write(index)); - git_index_free(index); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL; - opts.notify_cb = checkout_count_callback; - opts.notify_payload = &cts; - - /* fail to checkout a bare repo */ - cl_git_fail(git_checkout_index(g_repo, NULL, &opts)); - - opts.target_directory = "alternative"; - cl_assert(!git_path_isdir("alternative")); - - cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); - - cl_assert_equal_i(0, cts.n_untracked); - cl_assert_equal_i(0, cts.n_ignored); - cl_assert_equal_i(3, cts.n_updates); - - /* files will have been filtered if needed, so strip CR */ - check_file_contents_nocr("./alternative/README", "hey there\n"); - check_file_contents_nocr("./alternative/branch_file.txt", "hi\nbye!\n"); - check_file_contents_nocr("./alternative/new.txt", "my new file\n"); - - cl_git_pass(git_futils_rmdir_r( - "alternative", NULL, GIT_RMDIR_REMOVE_FILES)); - - git_object_free(head); -} - -void test_checkout_index__can_get_repo_from_index(void) -{ - git_index *index; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - cl_assert_equal_i(false, git_path_isfile("./testrepo/README")); - cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt")); - cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt")); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_git_pass(git_repository_index(&index, g_repo)); - - cl_git_pass(git_checkout_index(NULL, index, &opts)); - - check_file_contents("./testrepo/README", "hey there\n"); - check_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n"); - check_file_contents("./testrepo/new.txt", "my new file\n"); - - git_index_free(index); -} diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c deleted file mode 100644 index 66b01bc7f..000000000 --- a/tests-clar/checkout/tree.c +++ /dev/null @@ -1,742 +0,0 @@ -#include "clar_libgit2.h" -#include "checkout_helpers.h" - -#include "git2/checkout.h" -#include "repository.h" -#include "buffer.h" -#include "fileops.h" - -static git_repository *g_repo; -static git_checkout_opts g_opts; -static git_object *g_object; - -void test_checkout_tree__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); - - GIT_INIT_STRUCTURE(&g_opts, GIT_CHECKOUT_OPTS_VERSION); - g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; -} - -void test_checkout_tree__cleanup(void) -{ - git_object_free(g_object); - g_object = NULL; - - cl_git_sandbox_cleanup(); - - if (git_path_isdir("alternative")) - git_futils_rmdir_r("alternative", NULL, GIT_RMDIR_REMOVE_FILES); -} - -void test_checkout_tree__cannot_checkout_a_non_treeish(void) -{ - /* blob */ - cl_git_pass(git_revparse_single(&g_object, g_repo, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd")); - cl_git_fail(git_checkout_tree(g_repo, g_object, NULL)); -} - -void test_checkout_tree__can_checkout_a_subdirectory_from_a_commit(void) -{ - char *entries[] = { "ab/de/" }; - - g_opts.paths.strings = entries; - g_opts.paths.count = 1; - - cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees")); - - cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/")); - - cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); - - cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/2.txt")); - cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/fgh/1.txt")); -} - -void test_checkout_tree__can_checkout_and_remove_directory(void) -{ - cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/")); - - /* Checkout brach "subtrees" and update HEAD, so that HEAD matches the - * current working tree - */ - cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees")); - cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); - - cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees")); - - cl_assert_equal_i(true, git_path_isdir("./testrepo/ab/")); - cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/2.txt")); - cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/fgh/1.txt")); - - git_object_free(g_object); - g_object = NULL; - - /* Checkout brach "master" and update HEAD, so that HEAD matches the - * current working tree - */ - cl_git_pass(git_revparse_single(&g_object, g_repo, "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")); - - /* This directory should no longer exist */ - cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/")); -} - -void test_checkout_tree__can_checkout_a_subdirectory_from_a_subtree(void) -{ - char *entries[] = { "de/" }; - - g_opts.paths.strings = entries; - g_opts.paths.count = 1; - - cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees:ab")); - - cl_assert_equal_i(false, git_path_isdir("./testrepo/de/")); - - cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); - - cl_assert_equal_i(true, git_path_isfile("./testrepo/de/2.txt")); - cl_assert_equal_i(true, git_path_isfile("./testrepo/de/fgh/1.txt")); -} - -static void progress(const char *path, size_t cur, size_t tot, void *payload) -{ - bool *was_called = (bool*)payload; - GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot); - *was_called = true; -} - -void test_checkout_tree__calls_progress_callback(void) -{ - bool was_called = 0; - - g_opts.progress_cb = progress; - g_opts.progress_payload = &was_called; - - cl_git_pass(git_revparse_single(&g_object, g_repo, "master")); - - cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); - - cl_assert_equal_i(was_called, true); -} - -void test_checkout_tree__doesnt_write_unrequested_files_to_worktree(void) -{ - git_oid master_oid; - git_oid chomped_oid; - git_commit* p_master_commit; - git_commit* p_chomped_commit; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - git_oid_fromstr(&master_oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - git_oid_fromstr(&chomped_oid, "e90810b8df3e80c413d903f631643c716887138d"); - cl_git_pass(git_commit_lookup(&p_master_commit, g_repo, &master_oid)); - cl_git_pass(git_commit_lookup(&p_chomped_commit, g_repo, &chomped_oid)); - - /* GIT_CHECKOUT_NONE should not add any file to the working tree from the - * index as it is supposed to be a dry run. - */ - opts.checkout_strategy = GIT_CHECKOUT_NONE; - git_checkout_tree(g_repo, (git_object*)p_chomped_commit, &opts); - cl_assert_equal_i(false, git_path_isfile("testrepo/readme.txt")); - - git_commit_free(p_master_commit); - git_commit_free(p_chomped_commit); -} - -void test_checkout_tree__can_switch_branches(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_oid oid; - git_object *obj = NULL; - - assert_on_branch(g_repo, "master"); - - /* do first checkout with FORCE because we don't know if testrepo - * base data is clean for a checkout or not - */ - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - - cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); - cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir")); - - cl_assert(git_path_isfile("testrepo/README")); - cl_assert(git_path_isfile("testrepo/branch_file.txt")); - cl_assert(git_path_isfile("testrepo/new.txt")); - cl_assert(git_path_isfile("testrepo/a/b.txt")); - - cl_assert(!git_path_isdir("testrepo/ab")); - - assert_on_branch(g_repo, "dir"); - - git_object_free(obj); - - /* do second checkout safe because we should be clean after first */ - opts.checkout_strategy = GIT_CHECKOUT_SAFE; - - cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/subtrees")); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - - cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); - cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees")); - - cl_assert(git_path_isfile("testrepo/README")); - cl_assert(git_path_isfile("testrepo/branch_file.txt")); - cl_assert(git_path_isfile("testrepo/new.txt")); - cl_assert(git_path_isfile("testrepo/ab/4.txt")); - cl_assert(git_path_isfile("testrepo/ab/c/3.txt")); - cl_assert(git_path_isfile("testrepo/ab/de/2.txt")); - cl_assert(git_path_isfile("testrepo/ab/de/fgh/1.txt")); - - cl_assert(!git_path_isdir("testrepo/a")); - - assert_on_branch(g_repo, "subtrees"); - - git_object_free(obj); -} - -void test_checkout_tree__can_remove_untracked(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_REMOVE_UNTRACKED; - - cl_git_mkfile("testrepo/untracked_file", "as you wish"); - cl_assert(git_path_isfile("testrepo/untracked_file")); - - cl_git_pass(git_checkout_head(g_repo, &opts)); - - cl_assert(!git_path_isfile("testrepo/untracked_file")); -} - -void test_checkout_tree__can_remove_ignored(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - int ignored = 0; - - opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_REMOVE_IGNORED; - - cl_git_mkfile("testrepo/ignored_file", "as you wish"); - - cl_git_pass(git_ignore_add_rule(g_repo, "ignored_file\n")); - - cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "ignored_file")); - cl_assert_equal_i(1, ignored); - - cl_assert(git_path_isfile("testrepo/ignored_file")); - - cl_git_pass(git_checkout_head(g_repo, &opts)); - - cl_assert(!git_path_isfile("testrepo/ignored_file")); -} - -void test_checkout_tree__can_update_only(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_oid oid; - git_object *obj = NULL; - - /* first let's get things into a known state - by checkout out the HEAD */ - - assert_on_branch(g_repo, "master"); - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - cl_git_pass(git_checkout_head(g_repo, &opts)); - - cl_assert(!git_path_isdir("testrepo/a")); - - check_file_contents_nocr("testrepo/branch_file.txt", "hi\nbye!\n"); - - /* now checkout branch but with update only */ - - opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; - - cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - - cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); - cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir")); - - assert_on_branch(g_repo, "dir"); - - /* this normally would have been created (which was tested separately in - * the test_checkout_tree__can_switch_branches test), but with - * UPDATE_ONLY it will not have been created. - */ - cl_assert(!git_path_isdir("testrepo/a")); - - /* but this file still should have been updated */ - check_file_contents_nocr("testrepo/branch_file.txt", "hi\n"); - - git_object_free(obj); -} - -void test_checkout_tree__can_checkout_with_pattern(void) -{ - char *entries[] = { "[l-z]*.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, "8496071c1b46c854b31185ea97743be6a8774479")); - - cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); - cl_git_pass( - git_repository_set_head_detached(g_repo, git_object_id(g_object))); - - git_object_free(g_object); - g_object = NULL; - - 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")); - - /* now to a narrow patterned checkout */ - - g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - g_opts.paths.strings = entries; - g_opts.paths.count = 1; - - 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_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")); -} - -void test_checkout_tree__can_disable_pattern_match(void) -{ - char *entries[] = { "b*.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, "8496071c1b46c854b31185ea97743be6a8774479")); - - cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); - cl_git_pass( - git_repository_set_head_detached(g_repo, git_object_id(g_object))); - - git_object_free(g_object); - g_object = NULL; - - cl_assert(!git_path_isfile("testrepo/branch_file.txt")); - - /* now to a narrow patterned checkout, but disable pattern */ - - g_opts.checkout_strategy = - GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH; - g_opts.paths.strings = entries; - g_opts.paths.count = 1; - - 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_assert(!git_path_isfile("testrepo/branch_file.txt")); - - /* let's try that again, but allow the pattern match */ - - g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); - - cl_assert(git_path_isfile("testrepo/branch_file.txt")); -} - -void assert_conflict( - const char *entry_path, - const char *new_content, - const char *parent_sha, - const char *commit_sha) -{ - git_index *index; - git_object *hack_tree; - git_reference *branch, *head; - git_buf file_path = GIT_BUF_INIT; - - cl_git_pass(git_repository_index(&index, g_repo)); - - /* Create a branch pointing at the parent */ - cl_git_pass(git_revparse_single(&g_object, g_repo, parent_sha)); - cl_git_pass(git_branch_create(&branch, g_repo, - "potential_conflict", (git_commit *)g_object, 0)); - - /* Make HEAD point to this branch */ - cl_git_pass(git_reference_symbolic_create( - &head, g_repo, "HEAD", git_reference_name(branch), 1)); - git_reference_free(head); - git_reference_free(branch); - - /* Checkout the parent */ - g_opts.checkout_strategy = GIT_CHECKOUT_FORCE; - cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); - - /* Hack-ishy workaound to ensure *all* the index entries - * match the content of the tree - */ - cl_git_pass(git_object_peel(&hack_tree, g_object, GIT_OBJ_TREE)); - cl_git_pass(git_index_read_tree(index, (git_tree *)hack_tree)); - git_object_free(hack_tree); - git_object_free(g_object); - g_object = NULL; - - /* Create a conflicting file */ - cl_git_pass(git_buf_joinpath(&file_path, "./testrepo", entry_path)); - cl_git_mkfile(git_buf_cstr(&file_path), new_content); - git_buf_free(&file_path); - - /* Trying to checkout the original commit */ - cl_git_pass(git_revparse_single(&g_object, g_repo, commit_sha)); - - g_opts.checkout_strategy = GIT_CHECKOUT_SAFE; - cl_assert_equal_i( - GIT_EMERGECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts)); - - /* Stage the conflicting change */ - cl_git_pass(git_index_add_bypath(index, entry_path)); - cl_git_pass(git_index_write(index)); - git_index_free(index); - - cl_assert_equal_i( - GIT_EMERGECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts)); -} - -void test_checkout_tree__checking_out_a_conflicting_type_change_returns_EMERGECONFLICT(void) -{ - /* - * 099faba adds a symlink named 'link_to_new.txt' - * a65fedf is the parent of 099faba - */ - - assert_conflict("link_to_new.txt", "old.txt", "a65fedf", "099faba"); -} - -void test_checkout_tree__checking_out_a_conflicting_type_change_returns_EMERGECONFLICT_2(void) -{ - /* - * cf80f8d adds a directory named 'a/' - * a4a7dce is the parent of cf80f8d - */ - - assert_conflict("a", "hello\n", "a4a7dce", "cf80f8d"); -} - -void test_checkout_tree__checking_out_a_conflicting_content_change_returns_EMERGECONFLICT(void) -{ - /* - * c47800c adds a symlink named 'branch_file.txt' - * 5b5b025 is the parent of 763d71a - */ - - assert_conflict("branch_file.txt", "hello\n", "5b5b025", "c47800c"); -} - -void test_checkout_tree__donot_update_deleted_file_by_default(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_oid old_id, new_id; - git_commit *old_commit = NULL, *new_commit = NULL; - git_index *index = NULL; - checkout_counts ct; - - opts.checkout_strategy = GIT_CHECKOUT_SAFE; - - memset(&ct, 0, sizeof(ct)); - opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL; - opts.notify_cb = checkout_count_callback; - opts.notify_payload = &ct; - - cl_git_pass(git_repository_index(&index, g_repo)); - - cl_git_pass(git_oid_fromstr(&old_id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); - cl_git_pass(git_commit_lookup(&old_commit, g_repo, &old_id)); - cl_git_pass(git_reset(g_repo, (git_object *)old_commit, GIT_RESET_HARD)); - - cl_git_pass(p_unlink("testrepo/branch_file.txt")); - cl_git_pass(git_index_remove_bypath(index ,"branch_file.txt")); - cl_git_pass(git_index_write(index)); - - cl_assert(!git_path_exists("testrepo/branch_file.txt")); - - cl_git_pass(git_oid_fromstr(&new_id, "099fabac3a9ea935598528c27f866e34089c2eff")); - cl_git_pass(git_commit_lookup(&new_commit, g_repo, &new_id)); - - - cl_git_fail(git_checkout_tree(g_repo, (git_object *)new_commit, &opts)); - - cl_assert_equal_i(1, ct.n_conflicts); - cl_assert_equal_i(1, ct.n_updates); - - git_commit_free(old_commit); - git_commit_free(new_commit); - git_index_free(index); -} - -void test_checkout_tree__can_checkout_with_last_workdir_item_missing(void) -{ - git_index *index = NULL; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_oid tree_id, commit_id; - git_tree *tree = NULL; - git_commit *commit = NULL; - - git_repository_index(&index, g_repo); - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - cl_git_pass(git_reference_name_to_id(&commit_id, g_repo, "refs/heads/master")); - cl_git_pass(git_commit_lookup(&commit, g_repo, &commit_id)); - - cl_git_pass(git_checkout_tree(g_repo, (git_object *)commit, &opts)); - cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master")); - - cl_git_pass(p_mkdir("./testrepo/this-is-dir", 0777)); - cl_git_mkfile("./testrepo/this-is-dir/contained_file", "content\n"); - - cl_git_pass(git_index_add_bypath(index, "this-is-dir/contained_file")); - git_index_write_tree(&tree_id, index); - cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); - - cl_git_pass(p_unlink("./testrepo/this-is-dir/contained_file")); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE; - - opts.checkout_strategy = 1; - git_checkout_tree(g_repo, (git_object *)tree, &opts); - - git_tree_free(tree); - git_commit_free(commit); - git_index_free(index); -} - -void test_checkout_tree__issue_1397(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - const char *partial_oid = "8a7ef04"; - git_object *tree = NULL; - - test_checkout_tree__cleanup(); /* cleanup default checkout */ - - g_repo = cl_git_sandbox_init("issue_1397"); - - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - cl_git_pass(git_revparse_single(&tree, g_repo, partial_oid)); - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - cl_git_pass(git_checkout_tree(g_repo, tree, &opts)); - - check_file_contents("./issue_1397/crlf_file.txt", "first line\r\nsecond line\r\nboth with crlf"); - - git_object_free(tree); -} - -void test_checkout_tree__can_write_to_empty_dirs(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_oid oid; - git_object *obj = NULL; - - assert_on_branch(g_repo, "master"); - - cl_git_pass(p_mkdir("testrepo/a", 0777)); - - /* do first checkout with FORCE because we don't know if testrepo - * base data is clean for a checkout or not - */ - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - - cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); - - cl_assert(git_path_isfile("testrepo/a/b.txt")); - - git_object_free(obj); -} - -void test_checkout_tree__fails_when_dir_in_use(void) -{ -#ifdef GIT_WIN32 - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_oid oid; - git_object *obj = NULL; - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - - cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); - - cl_assert(git_path_isfile("testrepo/a/b.txt")); - - git_object_free(obj); - - cl_git_pass(p_chdir("testrepo/a")); - - cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/master")); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - - cl_git_fail(git_checkout_tree(g_repo, obj, &opts)); - - cl_git_pass(p_chdir("../..")); - - cl_assert(git_path_is_empty_dir("testrepo/a")); - - git_object_free(obj); -#endif -} - -void test_checkout_tree__can_continue_when_dir_in_use(void) -{ -#ifdef GIT_WIN32 - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_oid oid; - git_object *obj = NULL; - - opts.checkout_strategy = GIT_CHECKOUT_FORCE | - GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES; - - cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - - cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); - - cl_assert(git_path_isfile("testrepo/a/b.txt")); - - git_object_free(obj); - - cl_git_pass(p_chdir("testrepo/a")); - - cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/master")); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - - cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); - - cl_git_pass(p_chdir("../..")); - - cl_assert(git_path_is_empty_dir("testrepo/a")); - - git_object_free(obj); -#endif -} - -void test_checkout_tree__target_directory_from_bare(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_oid oid; - checkout_counts cts; - memset(&cts, 0, sizeof(cts)); - - test_checkout_tree__cleanup(); /* cleanup default checkout */ - - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_assert(git_repository_is_bare(g_repo)); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - - opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL; - opts.notify_cb = checkout_count_callback; - opts.notify_payload = &cts; - - cl_git_pass(git_reference_name_to_id(&oid, g_repo, "HEAD")); - cl_git_pass(git_object_lookup(&g_object, g_repo, &oid, GIT_OBJ_ANY)); - - cl_git_fail(git_checkout_tree(g_repo, g_object, &opts)); - - opts.target_directory = "alternative"; - cl_assert(!git_path_isdir("alternative")); - - cl_git_pass(git_checkout_tree(g_repo, g_object, &opts)); - - cl_assert_equal_i(0, cts.n_untracked); - cl_assert_equal_i(0, cts.n_ignored); - cl_assert_equal_i(3, cts.n_updates); - - check_file_contents_nocr("./alternative/README", "hey there\n"); - check_file_contents_nocr("./alternative/branch_file.txt", "hi\nbye!\n"); - check_file_contents_nocr("./alternative/new.txt", "my new file\n"); - - cl_git_pass(git_futils_rmdir_r( - "alternative", NULL, GIT_RMDIR_REMOVE_FILES)); -} - -void test_checkout_tree__extremely_long_file_name(void) -{ - // A utf-8 string with 83 characters, but 249 bytes. - const char *longname = "\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97"; - char path[1024]; - - g_opts.checkout_strategy = GIT_CHECKOUT_FORCE; - cl_git_pass(git_revparse_single(&g_object, g_repo, "long-file-name")); - cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); - - sprintf(path, "testrepo/%s.txt", longname); - cl_assert(git_path_exists(path)); - - git_object_free(g_object); - cl_git_pass(git_revparse_single(&g_object, g_repo, "master")); - cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); - cl_assert(!git_path_exists(path)); -} - -static void create_conflict(void) -{ - git_index *index; - git_index_entry entry; - - cl_git_pass(git_repository_index(&index, g_repo)); - - memset(&entry, 0x0, sizeof(git_index_entry)); - entry.mode = 0100644; - entry.flags = 1 << GIT_IDXENTRY_STAGESHIFT; - git_oid_fromstr(&entry.oid, "d427e0b2e138501a3d15cc376077a3631e15bd46"); - entry.path = "conflicts.txt"; - cl_git_pass(git_index_add(index, &entry)); - - entry.flags = 2 << GIT_IDXENTRY_STAGESHIFT; - git_oid_fromstr(&entry.oid, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf"); - cl_git_pass(git_index_add(index, &entry)); - - entry.flags = 3 << GIT_IDXENTRY_STAGESHIFT; - git_oid_fromstr(&entry.oid, "2bd0a343aeef7a2cf0d158478966a6e587ff3863"); - cl_git_pass(git_index_add(index, &entry)); - - git_index_write(index); - git_index_free(index); -} - -void test_checkout_tree__fails_when_conflicts_exist_in_index(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_oid oid; - git_object *obj = NULL; - - opts.checkout_strategy = GIT_CHECKOUT_SAFE; - - cl_git_pass(git_reference_name_to_id(&oid, g_repo, "HEAD")); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - - create_conflict(); - - cl_git_fail(git_checkout_tree(g_repo, obj, &opts)); - - git_object_free(obj); -} diff --git a/tests-clar/checkout/typechange.c b/tests-clar/checkout/typechange.c deleted file mode 100644 index 6cf99ac15..000000000 --- a/tests-clar/checkout/typechange.c +++ /dev/null @@ -1,240 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/checkout.h" -#include "path.h" -#include "posix.h" -#include "fileops.h" - -static git_repository *g_repo = NULL; - -static const char *g_typechange_oids[] = { - "79b9f23e85f55ea36a472a902e875bc1121a94cb", - "9bdb75b73836a99e3dbeea640a81de81031fdc29", - "0e7ed140b514b8cae23254cb8656fe1674403aff", - "9d0235c7a7edc0889a18f97a42ee6db9fe688447", - "9b19edf33a03a0c59cdfc113bfa5c06179bf9b1a", - "1b63caae4a5ca96f78e8dfefc376c6a39a142475", - "6eae26c90e8ccc4d16208972119c40635489c6f0", - NULL -}; - -static bool g_typechange_empty[] = { - true, false, false, false, false, false, true, true -}; - -void test_checkout_typechange__initialize(void) -{ - g_repo = cl_git_sandbox_init("typechanges"); - - cl_fixture_sandbox("submod2_target"); - p_rename("submod2_target/.gitted", "submod2_target/.git"); -} - -void test_checkout_typechange__cleanup(void) -{ - cl_git_sandbox_cleanup(); - cl_fixture_cleanup("submod2_target"); -} - -static void assert_file_exists(const char *path) -{ - cl_assert_(git_path_isfile(path), path); -} - -static void assert_dir_exists(const char *path) -{ - cl_assert_(git_path_isdir(path), path); -} - -static void assert_workdir_matches_tree( - git_repository *repo, const git_oid *id, const char *root, bool recurse) -{ - git_object *obj; - git_tree *tree; - size_t i, max_i; - git_buf path = GIT_BUF_INIT; - - if (!root) - root = git_repository_workdir(repo); - cl_assert(root); - - cl_git_pass(git_object_lookup(&obj, repo, id, GIT_OBJ_ANY)); - cl_git_pass(git_object_peel((git_object **)&tree, obj, GIT_OBJ_TREE)); - git_object_free(obj); - - max_i = git_tree_entrycount(tree); - - for (i = 0; i < max_i; ++i) { - const git_tree_entry *te = git_tree_entry_byindex(tree, i); - cl_assert(te); - - cl_git_pass(git_buf_joinpath(&path, root, git_tree_entry_name(te))); - - switch (git_tree_entry_type(te)) { - case GIT_OBJ_COMMIT: - assert_dir_exists(path.ptr); - break; - case GIT_OBJ_TREE: - assert_dir_exists(path.ptr); - if (recurse) - assert_workdir_matches_tree( - repo, git_tree_entry_id(te), path.ptr, true); - break; - case GIT_OBJ_BLOB: - switch (git_tree_entry_filemode(te)) { - case GIT_FILEMODE_BLOB: - case GIT_FILEMODE_BLOB_EXECUTABLE: - assert_file_exists(path.ptr); - /* because of cross-platform, don't confirm exec bit yet */ - break; - case GIT_FILEMODE_LINK: - cl_assert_(git_path_exists(path.ptr), path.ptr); - /* because of cross-platform, don't confirm link yet */ - break; - default: - cl_assert(false); /* really?! */ - } - break; - default: - cl_assert(false); /* really?!! */ - } - } - - git_tree_free(tree); - git_buf_free(&path); -} - -void test_checkout_typechange__checkout_typechanges_safe(void) -{ - int i; - git_object *obj; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - for (i = 0; g_typechange_oids[i] != NULL; ++i) { - cl_git_pass(git_revparse_single(&obj, g_repo, g_typechange_oids[i])); - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - /* There are bugs in some submodule->tree changes that prevent - * SAFE from passing here, even though the following should work: - */ - /* !i ? GIT_CHECKOUT_FORCE : GIT_CHECKOUT_SAFE; */ - - cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); - - cl_git_pass( - git_repository_set_head_detached(g_repo, git_object_id(obj))); - - assert_workdir_matches_tree(g_repo, git_object_id(obj), NULL, true); - - git_object_free(obj); - - if (!g_typechange_empty[i]) { - cl_assert(git_path_isdir("typechanges")); - cl_assert(git_path_exists("typechanges/a")); - cl_assert(git_path_exists("typechanges/b")); - cl_assert(git_path_exists("typechanges/c")); - cl_assert(git_path_exists("typechanges/d")); - cl_assert(git_path_exists("typechanges/e")); - } else { - cl_assert(git_path_isdir("typechanges")); - cl_assert(!git_path_exists("typechanges/a")); - cl_assert(!git_path_exists("typechanges/b")); - cl_assert(!git_path_exists("typechanges/c")); - cl_assert(!git_path_exists("typechanges/d")); - cl_assert(!git_path_exists("typechanges/e")); - } - } -} - -typedef struct { - int conflicts; - int dirty; - int updates; - int untracked; - int ignored; -} notify_counts; - -static int notify_counter( - git_checkout_notify_t why, - const char *path, - const git_diff_file *baseline, - const git_diff_file *target, - const git_diff_file *workdir, - void *payload) -{ - notify_counts *cts = payload; - - GIT_UNUSED(path); - GIT_UNUSED(baseline); - GIT_UNUSED(target); - GIT_UNUSED(workdir); - - switch (why) { - case GIT_CHECKOUT_NOTIFY_CONFLICT: cts->conflicts++; break; - case GIT_CHECKOUT_NOTIFY_DIRTY: cts->dirty++; break; - case GIT_CHECKOUT_NOTIFY_UPDATED: cts->updates++; break; - case GIT_CHECKOUT_NOTIFY_UNTRACKED: cts->untracked++; break; - case GIT_CHECKOUT_NOTIFY_IGNORED: cts->ignored++; break; - default: break; - } - - return 0; -} - -static void force_create_file(const char *file) -{ - int error = git_futils_rmdir_r(file, NULL, - GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS); - cl_assert(!error || error == GIT_ENOTFOUND); - cl_git_pass(git_futils_mkpath2file(file, 0777)); - cl_git_rewritefile(file, "yowza!!"); -} - -void test_checkout_typechange__checkout_with_conflicts(void) -{ - int i; - git_object *obj; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - notify_counts cts = {0}; - - opts.notify_flags = - GIT_CHECKOUT_NOTIFY_CONFLICT | GIT_CHECKOUT_NOTIFY_UNTRACKED; - opts.notify_cb = notify_counter; - opts.notify_payload = &cts; - - for (i = 0; g_typechange_oids[i] != NULL; ++i) { - cl_git_pass(git_revparse_single(&obj, g_repo, g_typechange_oids[i])); - - force_create_file("typechanges/a/blocker"); - force_create_file("typechanges/b"); - force_create_file("typechanges/c/sub/sub/file"); - git_futils_rmdir_r("typechanges/d", NULL, GIT_RMDIR_REMOVE_FILES); - p_mkdir("typechanges/d", 0777); /* intentionally empty dir */ - force_create_file("typechanges/untracked"); - - opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - memset(&cts, 0, sizeof(cts)); - - cl_git_fail(git_checkout_tree(g_repo, obj, &opts)); - cl_assert(cts.conflicts > 0); - cl_assert(cts.untracked > 0); - - opts.checkout_strategy = - GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED; - memset(&cts, 0, sizeof(cts)); - - cl_assert(git_path_exists("typechanges/untracked")); - - cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); - cl_assert_equal_i(0, cts.conflicts); - - cl_assert(!git_path_exists("typechanges/untracked")); - - cl_git_pass( - git_repository_set_head_detached(g_repo, git_object_id(obj))); - - assert_workdir_matches_tree(g_repo, git_object_id(obj), NULL, true); - - git_object_free(obj); - } -} diff --git a/tests-clar/clar.c b/tests-clar/clar.c deleted file mode 100644 index 6c7399a54..000000000 --- a/tests-clar/clar.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - * Copyright (c) Vicent Marti. All rights reserved. - * - * This file is part of clar, distributed under the ISC license. - * For full terms see the included COPYING file. - */ -#include -#include -#include -#include -#include -#include -#include - -/* required for sandboxing */ -#include -#include - -#ifdef _WIN32 -# include -# include -# include -# include - -# define _MAIN_CC __cdecl - -# ifndef stat -# define stat(path, st) _stat(path, st) -# endif -# ifndef mkdir -# define mkdir(path, mode) _mkdir(path) -# endif -# ifndef chdir -# define chdir(path) _chdir(path) -# endif -# ifndef access -# define access(path, mode) _access(path, mode) -# endif -# ifndef strdup -# define strdup(str) _strdup(str) -# endif -# ifndef strcasecmp -# define strcasecmp(a,b) _stricmp(a,b) -# endif - -# ifndef __MINGW32__ -# pragma comment(lib, "shell32") -# ifndef strncpy -# define strncpy(to, from, to_size) strncpy_s(to, to_size, from, _TRUNCATE) -# endif -# ifndef W_OK -# define W_OK 02 -# endif -# ifndef S_ISDIR -# define S_ISDIR(x) ((x & _S_IFDIR) != 0) -# endif -# define p_snprintf(buf,sz,fmt,...) _snprintf_s(buf,sz,_TRUNCATE,fmt,__VA_ARGS__) -# else -# define p_snprintf snprintf -# endif - -# ifndef PRIuZ -# define PRIuZ "Iu" -# endif -# ifndef PRIxZ -# define PRIxZ "Ix" -# endif - typedef struct _stat STAT_T; -#else -# include /* waitpid(2) */ -# include -# define _MAIN_CC -# define p_snprintf snprintf -# ifndef PRIuZ -# define PRIuZ "zu" -# endif -# ifndef PRIxZ -# define PRIxZ "zx" -# endif - typedef struct stat STAT_T; -#endif - -#include "clar.h" - -static void fs_rm(const char *_source); -static void fs_copy(const char *_source, const char *dest); - -static const char * -fixture_path(const char *base, const char *fixture_name); - -struct clar_error { - const char *test; - int test_number; - const char *suite; - const char *file; - int line_number; - const char *error_msg; - char *description; - - struct clar_error *next; -}; - -static struct { - const char *active_test; - const char *active_suite; - - int suite_errors; - int total_errors; - - int tests_ran; - int suites_ran; - - int report_errors_only; - int exit_on_error; - int report_suite_names; - - struct clar_error *errors; - struct clar_error *last_error; - - void (*local_cleanup)(void *); - void *local_cleanup_payload; - - jmp_buf trampoline; - int trampoline_enabled; -} _clar; - -struct clar_func { - const char *name; - void (*ptr)(void); -}; - -struct clar_suite { - const char *name; - struct clar_func initialize; - struct clar_func cleanup; - const struct clar_func *tests; - size_t test_count; - int enabled; -}; - -/* From clar_print_*.c */ -static void clar_print_init(int test_count, int suite_count, const char *suite_names); -static void clar_print_shutdown(int test_count, int suite_count, int error_count); -static void clar_print_error(int num, const struct clar_error *error); -static void clar_print_ontest(const char *test_name, int test_number, int failed); -static void clar_print_onsuite(const char *suite_name, int suite_index); -static void clar_print_onabort(const char *msg, ...); - -/* From clar_sandbox.c */ -static void clar_unsandbox(void); -static int clar_sandbox(void); - -/* Load the declarations for the test suite */ -#include "clar.suite" - -/* Core test functions */ -static void -clar_report_errors(void) -{ - int i = 1; - struct clar_error *error, *next; - - error = _clar.errors; - while (error != NULL) { - next = error->next; - clar_print_error(i++, error); - free(error->description); - free(error); - error = next; - } - - _clar.errors = _clar.last_error = NULL; -} - -static void -clar_run_test( - const struct clar_func *test, - const struct clar_func *initialize, - const struct clar_func *cleanup) -{ - int error_st = _clar.suite_errors; - - _clar.trampoline_enabled = 1; - - if (setjmp(_clar.trampoline) == 0) { - if (initialize->ptr != NULL) - initialize->ptr(); - - test->ptr(); - } - - _clar.trampoline_enabled = 0; - - if (_clar.local_cleanup != NULL) - _clar.local_cleanup(_clar.local_cleanup_payload); - - if (cleanup->ptr != NULL) - cleanup->ptr(); - - _clar.tests_ran++; - - /* remove any local-set cleanup methods */ - _clar.local_cleanup = NULL; - _clar.local_cleanup_payload = NULL; - - if (_clar.report_errors_only) - clar_report_errors(); - else - clar_print_ontest( - test->name, - _clar.tests_ran, - (_clar.suite_errors > error_st) - ); -} - -static void -clar_run_suite(const struct clar_suite *suite, const char *filter) -{ - const struct clar_func *test = suite->tests; - size_t i, matchlen; - - if (!suite->enabled) - return; - - if (_clar.exit_on_error && _clar.total_errors) - return; - - if (!_clar.report_errors_only) - clar_print_onsuite(suite->name, ++_clar.suites_ran); - - _clar.active_suite = suite->name; - _clar.suite_errors = 0; - - if (filter) { - size_t suitelen = strlen(suite->name); - matchlen = strlen(filter); - if (matchlen <= suitelen) { - filter = NULL; - } else { - filter += suitelen; - while (*filter == ':') - ++filter; - matchlen = strlen(filter); - } - } - - for (i = 0; i < suite->test_count; ++i) { - if (filter && strncmp(test[i].name, filter, matchlen)) - continue; - - _clar.active_test = test[i].name; - clar_run_test(&test[i], &suite->initialize, &suite->cleanup); - - if (_clar.exit_on_error && _clar.total_errors) - return; - } -} - -static void -clar_usage(const char *arg) -{ - printf("Usage: %s [options]\n\n", arg); - printf("Options:\n"); - printf(" -sname\tRun only the suite with `name` (can go to individual test name)\n"); - printf(" -iname\tInclude the suite with `name`\n"); - printf(" -xname\tExclude the suite with `name`\n"); - printf(" -q \tOnly report tests that had an error\n"); - printf(" -Q \tQuit as soon as a test fails\n"); - printf(" -l \tPrint suite names\n"); - exit(-1); -} - -static void -clar_parse_args(int argc, char **argv) -{ - int i; - - for (i = 1; i < argc; ++i) { - char *argument = argv[i]; - - if (argument[0] != '-') - clar_usage(argv[0]); - - switch (argument[1]) { - case 's': - case 'i': - case 'x': { /* given suite name */ - int offset = (argument[2] == '=') ? 3 : 2, found = 0; - char action = argument[1]; - size_t j, arglen, suitelen, cmplen; - - argument += offset; - arglen = strlen(argument); - - if (arglen == 0) - clar_usage(argv[0]); - - for (j = 0; j < _clar_suite_count; ++j) { - suitelen = strlen(_clar_suites[j].name); - cmplen = (arglen < suitelen) ? arglen : suitelen; - - if (strncmp(argument, _clar_suites[j].name, cmplen) == 0) { - int exact = (arglen >= suitelen); - - ++found; - - if (!exact) - _clar.report_suite_names = 1; - - switch (action) { - case 's': clar_run_suite(&_clar_suites[j], argument); break; - case 'i': _clar_suites[j].enabled = 1; break; - case 'x': _clar_suites[j].enabled = 0; break; - } - - if (exact) - break; - } - } - - if (!found) { - clar_print_onabort("No suite matching '%s' found.\n", argument); - exit(-1); - } - break; - } - - case 'q': - _clar.report_errors_only = 1; - break; - - case 'Q': - _clar.exit_on_error = 1; - break; - - case 'l': { - size_t j; - printf("Test suites (use -s to run just one):\n"); - for (j = 0; j < _clar_suite_count; ++j) - printf(" %3d: %s\n", (int)j, _clar_suites[j].name); - - exit(0); - } - - default: - clar_usage(argv[0]); - } - } -} - -int -clar_test(int argc, char **argv) -{ - clar_print_init( - (int)_clar_callback_count, - (int)_clar_suite_count, - "" - ); - - if (clar_sandbox() < 0) { - clar_print_onabort("Failed to sandbox the test runner.\n"); - exit(-1); - } - - if (argc > 1) - clar_parse_args(argc, argv); - - if (!_clar.suites_ran) { - size_t i; - for (i = 0; i < _clar_suite_count; ++i) - clar_run_suite(&_clar_suites[i], NULL); - } - - clar_print_shutdown( - _clar.tests_ran, - (int)_clar_suite_count, - _clar.total_errors - ); - - clar_unsandbox(); - return _clar.total_errors; -} - -void clar__fail( - const char *file, - int line, - const char *error_msg, - const char *description, - int should_abort) -{ - struct clar_error *error = calloc(1, sizeof(struct clar_error)); - - if (_clar.errors == NULL) - _clar.errors = error; - - if (_clar.last_error != NULL) - _clar.last_error->next = error; - - _clar.last_error = error; - - error->test = _clar.active_test; - error->test_number = _clar.tests_ran; - error->suite = _clar.active_suite; - error->file = file; - error->line_number = line; - error->error_msg = error_msg; - - if (description != NULL) - error->description = strdup(description); - - _clar.suite_errors++; - _clar.total_errors++; - - if (should_abort) { - if (!_clar.trampoline_enabled) { - clar_print_onabort( - "Fatal error: a cleanup method raised an exception."); - clar_report_errors(); - exit(-1); - } - - longjmp(_clar.trampoline, -1); - } -} - -void clar__assert( - int condition, - const char *file, - int line, - const char *error_msg, - const char *description, - int should_abort) -{ - if (condition) - return; - - clar__fail(file, line, error_msg, description, should_abort); -} - -void clar__assert_equal( - const char *file, - int line, - const char *err, - int should_abort, - const char *fmt, - ...) -{ - va_list args; - char buf[4096]; - int is_equal = 1; - - va_start(args, fmt); - - if (!strcmp("%s", fmt)) { - const char *s1 = va_arg(args, const char *); - const char *s2 = va_arg(args, const char *); - is_equal = (!s1 || !s2) ? (s1 == s2) : !strcmp(s1, s2); - - if (!is_equal) { - if (s1 && s2) { - int pos; - for (pos = 0; s1[pos] == s2[pos] && s1[pos] && s2[pos]; ++pos) - /* find differing byte offset */; - p_snprintf(buf, sizeof(buf), "'%s' != '%s' (at byte %d)", - s1, s2, pos); - } else { - p_snprintf(buf, sizeof(buf), "'%s' != '%s'", s1, s2); - } - } - } - else if (!strcmp("%"PRIuZ, fmt) || !strcmp("%"PRIxZ, fmt)) { - size_t sz1 = va_arg(args, size_t), sz2 = va_arg(args, size_t); - is_equal = (sz1 == sz2); - if (!is_equal) { - int offset = p_snprintf(buf, sizeof(buf), fmt, sz1); - strncat(buf, " != ", sizeof(buf) - offset); - p_snprintf(buf + offset + 4, sizeof(buf) - offset - 4, fmt, sz2); - } - } - else if (!strcmp("%p", fmt)) { - void *p1 = va_arg(args, void *), *p2 = va_arg(args, void *); - is_equal = (p1 == p2); - if (!is_equal) - p_snprintf(buf, sizeof(buf), "%p != %p", p1, p2); - } - else { - int i1 = va_arg(args, int), i2 = va_arg(args, int); - is_equal = (i1 == i2); - if (!is_equal) { - int offset = p_snprintf(buf, sizeof(buf), fmt, i1); - strncat(buf, " != ", sizeof(buf) - offset); - p_snprintf(buf + offset + 4, sizeof(buf) - offset - 4, fmt, i2); - } - } - - va_end(args); - - if (!is_equal) - clar__fail(file, line, err, buf, should_abort); -} - -void cl_set_cleanup(void (*cleanup)(void *), void *opaque) -{ - _clar.local_cleanup = cleanup; - _clar.local_cleanup_payload = opaque; -} - -#include "clar/sandbox.h" -#include "clar/fixtures.h" -#include "clar/fs.h" -#include "clar/print.h" diff --git a/tests-clar/clar.h b/tests-clar/clar.h deleted file mode 100644 index e1f244eba..000000000 --- a/tests-clar/clar.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) Vicent Marti. All rights reserved. - * - * This file is part of clar, distributed under the ISC license. - * For full terms see the included COPYING file. - */ -#ifndef __CLAR_TEST_H__ -#define __CLAR_TEST_H__ - -#include - -int clar_test(int argc, char *argv[]); - -void cl_set_cleanup(void (*cleanup)(void *), void *opaque); -void cl_fs_cleanup(void); - -#ifdef CLAR_FIXTURE_PATH -const char *cl_fixture(const char *fixture_name); -void cl_fixture_sandbox(const char *fixture_name); -void cl_fixture_cleanup(const char *fixture_name); -#endif - -/** - * Assertion macros with explicit error message - */ -#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __LINE__, "Function call failed: " #expr, desc, 1) -#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __LINE__, "Expected function call to fail: " #expr, desc, 1) -#define cl_assert_(expr, desc) clar__assert((expr) != 0, __FILE__, __LINE__, "Expression is not true: " #expr, desc, 1) - -/** - * Check macros with explicit error message - */ -#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __LINE__, "Function call failed: " #expr, desc, 0) -#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __LINE__, "Expected function call to fail: " #expr, desc, 0) -#define cl_check_(expr, desc) clar__assert((expr) != 0, __FILE__, __LINE__, "Expression is not true: " #expr, desc, 0) - -/** - * Assertion macros with no error message - */ -#define cl_must_pass(expr) cl_must_pass_(expr, NULL) -#define cl_must_fail(expr) cl_must_fail_(expr, NULL) -#define cl_assert(expr) cl_assert_(expr, NULL) - -/** - * Check macros with no error message - */ -#define cl_check_pass(expr) cl_check_pass_(expr, NULL) -#define cl_check_fail(expr) cl_check_fail_(expr, NULL) -#define cl_check(expr) cl_check_(expr, NULL) - -/** - * Forced failure/warning - */ -#define cl_fail(desc) clar__fail(__FILE__, __LINE__, "Test failed.", desc, 1) -#define cl_warning(desc) clar__fail(__FILE__, __LINE__, "Warning during test execution:", desc, 0) - -/** - * Typed assertion macros - */ -#define cl_assert_equal_s(s1,s2) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2)) -#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2)) - -#define cl_assert_equal_i(i1,i2) clar__assert_equal(__FILE__,__LINE__,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2)) -#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(__FILE__,__LINE__,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2)) -#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(__FILE__,__LINE__,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2)) - -#define cl_assert_equal_b(b1,b2) clar__assert_equal(__FILE__,__LINE__,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0)) - -#define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2)) - - -void clar__fail( - const char *file, - int line, - const char *error, - const char *description, - int should_abort); - -void clar__assert( - int condition, - const char *file, - int line, - const char *error, - const char *description, - int should_abort); - -void clar__assert_equal( - const char *file, - int line, - const char *err, - int should_abort, - const char *fmt, - ...); - -#endif diff --git a/tests-clar/clar/fixtures.h b/tests-clar/clar/fixtures.h deleted file mode 100644 index 264cd7f4f..000000000 --- a/tests-clar/clar/fixtures.h +++ /dev/null @@ -1,38 +0,0 @@ -static const char * -fixture_path(const char *base, const char *fixture_name) -{ - static char _path[4096]; - size_t root_len; - - root_len = strlen(base); - strncpy(_path, base, sizeof(_path)); - - if (_path[root_len - 1] != '/') - _path[root_len++] = '/'; - - if (fixture_name[0] == '/') - fixture_name++; - - strncpy(_path + root_len, - fixture_name, - sizeof(_path) - root_len); - - return _path; -} - -#ifdef CLAR_FIXTURE_PATH -const char *cl_fixture(const char *fixture_name) -{ - return fixture_path(CLAR_FIXTURE_PATH, fixture_name); -} - -void cl_fixture_sandbox(const char *fixture_name) -{ - fs_copy(cl_fixture(fixture_name), _clar_path); -} - -void cl_fixture_cleanup(const char *fixture_name) -{ - fs_rm(fixture_path(_clar_path, fixture_name)); -} -#endif diff --git a/tests-clar/clar/fs.h b/tests-clar/clar/fs.h deleted file mode 100644 index b7a1ff9d2..000000000 --- a/tests-clar/clar/fs.h +++ /dev/null @@ -1,325 +0,0 @@ -#ifdef _WIN32 - -#define RM_RETRY_COUNT 5 -#define RM_RETRY_DELAY 10 - -#ifdef __MINGW32__ - -/* These security-enhanced functions are not available - * in MinGW, so just use the vanilla ones */ -#define wcscpy_s(a, b, c) wcscpy((a), (c)) -#define wcscat_s(a, b, c) wcscat((a), (c)) - -#endif /* __MINGW32__ */ - -static int -fs__dotordotdot(WCHAR *_tocheck) -{ - return _tocheck[0] == '.' && - (_tocheck[1] == '\0' || - (_tocheck[1] == '.' && _tocheck[2] == '\0')); -} - -static int -fs_rmdir_rmdir(WCHAR *_wpath) -{ - unsigned retries = 1; - - while (!RemoveDirectoryW(_wpath)) { - /* Only retry when we have retries remaining, and the - * error was ERROR_DIR_NOT_EMPTY. */ - if (retries++ > RM_RETRY_COUNT || - ERROR_DIR_NOT_EMPTY != GetLastError()) - return -1; - - /* Give whatever has a handle to a child item some time - * to release it before trying again */ - Sleep(RM_RETRY_DELAY * retries * retries); - } - - return 0; -} - -static void -fs_rmdir_helper(WCHAR *_wsource) -{ - WCHAR buffer[MAX_PATH]; - HANDLE find_handle; - WIN32_FIND_DATAW find_data; - size_t buffer_prefix_len; - - /* Set up the buffer and capture the length */ - wcscpy_s(buffer, MAX_PATH, _wsource); - wcscat_s(buffer, MAX_PATH, L"\\"); - buffer_prefix_len = wcslen(buffer); - - /* FindFirstFile needs a wildcard to match multiple items */ - wcscat_s(buffer, MAX_PATH, L"*"); - find_handle = FindFirstFileW(buffer, &find_data); - cl_assert(INVALID_HANDLE_VALUE != find_handle); - - do { - /* FindFirstFile/FindNextFile gives back . and .. - * entries at the beginning */ - if (fs__dotordotdot(find_data.cFileName)) - continue; - - wcscpy_s(buffer + buffer_prefix_len, MAX_PATH - buffer_prefix_len, find_data.cFileName); - - if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes) - fs_rmdir_helper(buffer); - else { - /* If set, the +R bit must be cleared before deleting */ - if (FILE_ATTRIBUTE_READONLY & find_data.dwFileAttributes) - cl_assert(SetFileAttributesW(buffer, find_data.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)); - - cl_assert(DeleteFileW(buffer)); - } - } - while (FindNextFileW(find_handle, &find_data)); - - /* Ensure that we successfully completed the enumeration */ - cl_assert(ERROR_NO_MORE_FILES == GetLastError()); - - /* Close the find handle */ - FindClose(find_handle); - - /* Now that the directory is empty, remove it */ - cl_assert(0 == fs_rmdir_rmdir(_wsource)); -} - -static int -fs_rm_wait(WCHAR *_wpath) -{ - unsigned retries = 1; - DWORD last_error; - - do { - if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(_wpath)) - last_error = GetLastError(); - else - last_error = ERROR_SUCCESS; - - /* Is the item gone? */ - if (ERROR_FILE_NOT_FOUND == last_error || - ERROR_PATH_NOT_FOUND == last_error) - return 0; - - Sleep(RM_RETRY_DELAY * retries * retries); - } - while (retries++ <= RM_RETRY_COUNT); - - return -1; -} - -static void -fs_rm(const char *_source) -{ - WCHAR wsource[MAX_PATH]; - DWORD attrs; - - /* The input path is UTF-8. Convert it to wide characters - * for use with the Windows API */ - cl_assert(MultiByteToWideChar(CP_UTF8, - MB_ERR_INVALID_CHARS, - _source, - -1, /* Indicates NULL termination */ - wsource, - MAX_PATH)); - - /* Does the item exist? If not, we have no work to do */ - attrs = GetFileAttributesW(wsource); - - if (INVALID_FILE_ATTRIBUTES == attrs) - return; - - if (FILE_ATTRIBUTE_DIRECTORY & attrs) - fs_rmdir_helper(wsource); - else { - /* The item is a file. Strip the +R bit */ - if (FILE_ATTRIBUTE_READONLY & attrs) - cl_assert(SetFileAttributesW(wsource, attrs & ~FILE_ATTRIBUTE_READONLY)); - - cl_assert(DeleteFileW(wsource)); - } - - /* Wait for the DeleteFile or RemoveDirectory call to complete */ - cl_assert(0 == fs_rm_wait(wsource)); -} - -static void -fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest) -{ - WCHAR buf_source[MAX_PATH], buf_dest[MAX_PATH]; - HANDLE find_handle; - WIN32_FIND_DATAW find_data; - size_t buf_source_prefix_len, buf_dest_prefix_len; - - wcscpy_s(buf_source, MAX_PATH, _wsource); - wcscat_s(buf_source, MAX_PATH, L"\\"); - buf_source_prefix_len = wcslen(buf_source); - - wcscpy_s(buf_dest, MAX_PATH, _wdest); - wcscat_s(buf_dest, MAX_PATH, L"\\"); - buf_dest_prefix_len = wcslen(buf_dest); - - /* Get an enumerator for the items in the source. */ - wcscat_s(buf_source, MAX_PATH, L"*"); - find_handle = FindFirstFileW(buf_source, &find_data); - cl_assert(INVALID_HANDLE_VALUE != find_handle); - - /* Create the target directory. */ - cl_assert(CreateDirectoryW(_wdest, NULL)); - - do { - /* FindFirstFile/FindNextFile gives back . and .. - * entries at the beginning */ - if (fs__dotordotdot(find_data.cFileName)) - continue; - - wcscpy_s(buf_source + buf_source_prefix_len, MAX_PATH - buf_source_prefix_len, find_data.cFileName); - wcscpy_s(buf_dest + buf_dest_prefix_len, MAX_PATH - buf_dest_prefix_len, find_data.cFileName); - - if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes) - fs_copydir_helper(buf_source, buf_dest); - else - cl_assert(CopyFileW(buf_source, buf_dest, TRUE)); - } - while (FindNextFileW(find_handle, &find_data)); - - /* Ensure that we successfully completed the enumeration */ - cl_assert(ERROR_NO_MORE_FILES == GetLastError()); - - /* Close the find handle */ - FindClose(find_handle); -} - -static void -fs_copy(const char *_source, const char *_dest) -{ - WCHAR wsource[MAX_PATH], wdest[MAX_PATH]; - DWORD source_attrs, dest_attrs; - HANDLE find_handle; - WIN32_FIND_DATAW find_data; - - /* The input paths are UTF-8. Convert them to wide characters - * for use with the Windows API. */ - cl_assert(MultiByteToWideChar(CP_UTF8, - MB_ERR_INVALID_CHARS, - _source, - -1, - wsource, - MAX_PATH)); - - cl_assert(MultiByteToWideChar(CP_UTF8, - MB_ERR_INVALID_CHARS, - _dest, - -1, - wdest, - MAX_PATH)); - - /* Check the source for existence */ - source_attrs = GetFileAttributesW(wsource); - cl_assert(INVALID_FILE_ATTRIBUTES != source_attrs); - - /* Check the target for existence */ - dest_attrs = GetFileAttributesW(wdest); - - if (INVALID_FILE_ATTRIBUTES != dest_attrs) { - /* Target exists; append last path part of source to target. - * Use FindFirstFile to parse the path */ - find_handle = FindFirstFileW(wsource, &find_data); - cl_assert(INVALID_HANDLE_VALUE != find_handle); - wcscat_s(wdest, MAX_PATH, L"\\"); - wcscat_s(wdest, MAX_PATH, find_data.cFileName); - FindClose(find_handle); - - /* Check the new target for existence */ - cl_assert(INVALID_FILE_ATTRIBUTES == GetFileAttributesW(wdest)); - } - - if (FILE_ATTRIBUTE_DIRECTORY & source_attrs) - fs_copydir_helper(wsource, wdest); - else - cl_assert(CopyFileW(wsource, wdest, TRUE)); -} - -void -cl_fs_cleanup(void) -{ - fs_rm(fixture_path(_clar_path, "*")); -} - -#else -static int -shell_out(char * const argv[]) -{ - int status; - pid_t pid; - - pid = fork(); - - if (pid < 0) { - fprintf(stderr, - "System error: `fork()` call failed.\n"); - exit(-1); - } - - if (pid == 0) { - execv(argv[0], argv); - } - - waitpid(pid, &status, 0); - return WEXITSTATUS(status); -} - -static void -fs_copy(const char *_source, const char *dest) -{ - char *argv[5]; - char *source; - size_t source_len; - - source = strdup(_source); - source_len = strlen(source); - - if (source[source_len - 1] == '/') - source[source_len - 1] = 0; - - argv[0] = "/bin/cp"; - argv[1] = "-R"; - argv[2] = source; - argv[3] = (char *)dest; - argv[4] = NULL; - - cl_must_pass_( - shell_out(argv), - "Failed to copy test fixtures to sandbox" - ); - - free(source); -} - -static void -fs_rm(const char *source) -{ - char *argv[4]; - - argv[0] = "/bin/rm"; - argv[1] = "-Rf"; - argv[2] = (char *)source; - argv[3] = NULL; - - cl_must_pass_( - shell_out(argv), - "Failed to cleanup the sandbox" - ); -} - -void -cl_fs_cleanup(void) -{ - clar_unsandbox(); - clar_sandbox(); -} -#endif diff --git a/tests-clar/clar/print.h b/tests-clar/clar/print.h deleted file mode 100644 index 368016f2f..000000000 --- a/tests-clar/clar/print.h +++ /dev/null @@ -1,60 +0,0 @@ - -static void clar_print_init(int test_count, int suite_count, const char *suite_names) -{ - (void)test_count; - printf("Loaded %d suites: %s\n", (int)suite_count, suite_names); - printf("Started\n"); -} - -static void clar_print_shutdown(int test_count, int suite_count, int error_count) -{ - (void)test_count; - (void)suite_count; - (void)error_count; - - printf("\n\n"); - clar_report_errors(); -} - -static void clar_print_error(int num, const struct clar_error *error) -{ - printf(" %d) Failure:\n", num); - - printf("%s::%s [%s:%d]\n", - error->suite, - error->test, - error->file, - error->line_number); - - printf(" %s\n", error->error_msg); - - if (error->description != NULL) - printf(" %s\n", error->description); - - printf("\n"); - fflush(stdout); -} - -static void clar_print_ontest(const char *test_name, int test_number, int failed) -{ - (void)test_name; - (void)test_number; - printf("%c", failed ? 'F' : '.'); - fflush(stdout); -} - -static void clar_print_onsuite(const char *suite_name, int suite_index) -{ - if (_clar.report_suite_names) - printf("\n%s", suite_name); - - (void)suite_index; -} - -static void clar_print_onabort(const char *msg, ...) -{ - va_list argp; - va_start(argp, msg); - vfprintf(stderr, msg, argp); - va_end(argp); -} diff --git a/tests-clar/clar/sandbox.h b/tests-clar/clar/sandbox.h deleted file mode 100644 index ee7564148..000000000 --- a/tests-clar/clar/sandbox.h +++ /dev/null @@ -1,129 +0,0 @@ -static char _clar_path[4096]; - -static int -is_valid_tmp_path(const char *path) -{ - STAT_T st; - - if (stat(path, &st) != 0) - return 0; - - if (!S_ISDIR(st.st_mode)) - return 0; - - return (access(path, W_OK) == 0); -} - -static int -find_tmp_path(char *buffer, size_t length) -{ -#ifndef _WIN32 - static const size_t var_count = 5; - static const char *env_vars[] = { - "CLAR_TMP", "TMPDIR", "TMP", "TEMP", "USERPROFILE" - }; - - size_t i; - - for (i = 0; i < var_count; ++i) { - const char *env = getenv(env_vars[i]); - if (!env) - continue; - - if (is_valid_tmp_path(env)) { - strncpy(buffer, env, length); - return 0; - } - } - - /* If the environment doesn't say anything, try to use /tmp */ - if (is_valid_tmp_path("/tmp")) { - strncpy(buffer, "/tmp", length); - return 0; - } - -#else - DWORD env_len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length); - if (env_len > 0 && env_len < (DWORD)length) - return 0; - - if (GetTempPath((DWORD)length, buffer)) - return 0; -#endif - - /* This system doesn't like us, try to use the current directory */ - if (is_valid_tmp_path(".")) { - strncpy(buffer, ".", length); - return 0; - } - - return -1; -} - -static void clar_unsandbox(void) -{ - if (_clar_path[0] == '\0') - return; - - chdir(".."); - - fs_rm(_clar_path); -} - -static int build_sandbox_path(void) -{ - const char path_tail[] = "clar_tmp_XXXXXX"; - size_t len; - - if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0) - return -1; - - len = strlen(_clar_path); - -#ifdef _WIN32 - { /* normalize path to POSIX forward slashes */ - size_t i; - for (i = 0; i < len; ++i) { - if (_clar_path[i] == '\\') - _clar_path[i] = '/'; - } - } -#endif - - if (_clar_path[len - 1] != '/') { - _clar_path[len++] = '/'; - } - - strncpy(_clar_path + len, path_tail, sizeof(_clar_path) - len); - -#if defined(__MINGW32__) - if (_mktemp(_clar_path) == NULL) - return -1; - - if (mkdir(_clar_path, 0700) != 0) - return -1; -#elif defined(_WIN32) - if (_mktemp_s(_clar_path, sizeof(_clar_path)) != 0) - return -1; - - if (mkdir(_clar_path, 0700) != 0) - return -1; -#else - if (mkdtemp(_clar_path) == NULL) - return -1; -#endif - - return 0; -} - -static int clar_sandbox(void) -{ - if (_clar_path[0] == '\0' && build_sandbox_path() < 0) - return -1; - - if (chdir(_clar_path) != 0) - return -1; - - return 0; -} - diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c deleted file mode 100644 index 50762cdb8..000000000 --- a/tests-clar/clar_libgit2.c +++ /dev/null @@ -1,483 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" -#include "path.h" -#include "git2/sys/repository.h" - -void cl_git_report_failure( - int error, 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 : ""); - clar__assert(0, file, line, fncall, msg, 1); -} - -void cl_git_mkfile(const char *filename, const char *content) -{ - int fd; - - fd = p_creat(filename, 0666); - cl_assert(fd != 0); - - if (content) { - cl_must_pass(p_write(fd, content, strlen(content))); - } else { - cl_must_pass(p_write(fd, filename, strlen(filename))); - cl_must_pass(p_write(fd, "\n", 1)); - } - - cl_must_pass(p_close(fd)); -} - -void cl_git_write2file( - const char *path, const char *content, size_t content_len, - int flags, unsigned int mode) -{ - int fd; - cl_assert(path && content); - cl_assert((fd = p_open(path, flags, mode)) >= 0); - if (!content_len) - content_len = strlen(content); - cl_must_pass(p_write(fd, content, content_len)); - cl_must_pass(p_close(fd)); -} - -void cl_git_append2file(const char *path, const char *content) -{ - cl_git_write2file(path, content, 0, O_WRONLY | O_CREAT | O_APPEND, 0644); -} - -void cl_git_rewritefile(const char *path, const char *content) -{ - cl_git_write2file(path, content, 0, O_WRONLY | O_CREAT | O_TRUNC, 0644); -} - -#ifdef GIT_WIN32 - -#include "win32/utf-conv.h" - -char *cl_getenv(const char *name) -{ - git_win32_path name_utf16; - DWORD alloc_len; - wchar_t *value_utf16; - char *value_utf8; - - git_win32_path_from_c(name_utf16, name); - alloc_len = GetEnvironmentVariableW(name_utf16, NULL, 0); - if (alloc_len <= 0) - return NULL; - - cl_assert(value_utf16 = git__calloc(alloc_len, sizeof(wchar_t))); - - GetEnvironmentVariableW(name_utf16, value_utf16, alloc_len); - - alloc_len = alloc_len * 4 + 1; /* worst case UTF16->UTF8 growth */ - cl_assert(value_utf8 = git__calloc(alloc_len, 1)); - - git__utf16_to_8(value_utf8, alloc_len, value_utf16); - - git__free(value_utf16); - - return value_utf8; -} - -int cl_setenv(const char *name, const char *value) -{ - git_win32_path name_utf16; - git_win32_path value_utf16; - - git_win32_path_from_c(name_utf16, name); - - if (value) { - git_win32_path_from_c(value_utf16, value); - cl_assert(SetEnvironmentVariableW(name_utf16, value_utf16)); - } else { - /* Windows XP returns 0 (failed) when passing NULL for lpValue when - * lpName does not exist in the environment block. This behavior - * seems to have changed in later versions. Don't check return value - * of SetEnvironmentVariable when passing NULL for lpValue. - */ - SetEnvironmentVariableW(name_utf16, NULL); - } - - return 0; -} - -/* This function performs retries on calls to MoveFile in order - * to provide enhanced reliability in the face of antivirus - * agents that may be scanning the source (or in the case that - * the source is a directory, a child of the source). */ -int cl_rename(const char *source, const char *dest) -{ - git_win32_path source_utf16; - git_win32_path dest_utf16; - unsigned retries = 1; - - git_win32_path_from_c(source_utf16, source); - git_win32_path_from_c(dest_utf16, dest); - - while (!MoveFileW(source_utf16, dest_utf16)) { - /* Only retry if the error is ERROR_ACCESS_DENIED; - * this may indicate that an antivirus agent is - * preventing the rename from source to target */ - if (retries > 5 || - ERROR_ACCESS_DENIED != GetLastError()) - return -1; - - /* With 5 retries and a coefficient of 10ms, the maximum - * delay here is 550 ms */ - Sleep(10 * retries * retries); - retries++; - } - - return 0; -} - -#else - -#include -char *cl_getenv(const char *name) -{ - return getenv(name); -} - -int cl_setenv(const char *name, const char *value) -{ - return (value == NULL) ? unsetenv(name) : setenv(name, value, 1); -} - -int cl_rename(const char *source, const char *dest) -{ - return p_rename(source, dest); -} - -#endif - -static const char *_cl_sandbox = NULL; -static git_repository *_cl_repo = NULL; - -git_repository *cl_git_sandbox_init(const char *sandbox) -{ - /* Copy the whole sandbox folder from our fixtures to our test sandbox - * area. After this it can be accessed with `./sandbox` - */ - cl_fixture_sandbox(sandbox); - _cl_sandbox = sandbox; - - cl_git_pass(p_chdir(sandbox)); - - /* If this is not a bare repo, then rename `sandbox/.gitted` to - * `sandbox/.git` which must be done since we cannot store a folder - * named `.git` inside the fixtures folder of our libgit2 repo. - */ - if (p_access(".gitted", F_OK) == 0) - cl_git_pass(cl_rename(".gitted", ".git")); - - /* If we have `gitattributes`, rename to `.gitattributes`. This may - * be necessary if we don't want the attributes to be applied in the - * libgit2 repo, but just during testing. - */ - if (p_access("gitattributes", F_OK) == 0) - cl_git_pass(cl_rename("gitattributes", ".gitattributes")); - - /* As with `gitattributes`, we may need `gitignore` just for testing. */ - if (p_access("gitignore", F_OK) == 0) - cl_git_pass(cl_rename("gitignore", ".gitignore")); - - cl_git_pass(p_chdir("..")); - - /* Now open the sandbox repository and make it available for tests */ - cl_git_pass(git_repository_open(&_cl_repo, sandbox)); - - /* Adjust configs after copying to new filesystem */ - cl_git_pass(git_repository_reinit_filesystem(_cl_repo, 0)); - - return _cl_repo; -} - -git_repository *cl_git_sandbox_reopen(void) -{ - if (_cl_repo) { - git_repository_free(_cl_repo); - _cl_repo = NULL; - - cl_git_pass(git_repository_open(&_cl_repo, _cl_sandbox)); - } - - return _cl_repo; -} - -void cl_git_sandbox_cleanup(void) -{ - if (_cl_repo) { - git_repository_free(_cl_repo); - _cl_repo = NULL; - } - if (_cl_sandbox) { - cl_fixture_cleanup(_cl_sandbox); - _cl_sandbox = NULL; - } -} - -bool cl_toggle_filemode(const char *filename) -{ - struct stat st1, st2; - - cl_must_pass(p_stat(filename, &st1)); - cl_must_pass(p_chmod(filename, st1.st_mode ^ 0100)); - cl_must_pass(p_stat(filename, &st2)); - - return (st1.st_mode != st2.st_mode); -} - -bool cl_is_chmod_supported(void) -{ - static int _is_supported = -1; - - if (_is_supported < 0) { - cl_git_mkfile("filemode.t", "Test if filemode can be modified"); - _is_supported = cl_toggle_filemode("filemode.t"); - cl_must_pass(p_unlink("filemode.t")); - } - - return _is_supported; -} - -const char* cl_git_fixture_url(const char *fixturename) -{ - return cl_git_path_url(cl_fixture(fixturename)); -} - -const char* cl_git_path_url(const char *path) -{ - static char url[4096]; - - const char *in_buf; - git_buf path_buf = GIT_BUF_INIT; - git_buf url_buf = GIT_BUF_INIT; - - cl_git_pass(git_path_prettify_dir(&path_buf, path, NULL)); - cl_git_pass(git_buf_puts(&url_buf, "file://")); - -#ifdef GIT_WIN32 - /* - * A FILE uri matches the following format: file://[host]/path - * where "host" can be empty and "path" is an absolute path to the resource. - * - * In this test, no hostname is used, but we have to ensure the leading triple slashes: - * - * *nix: file:///usr/home/... - * Windows: file:///C:/Users/... - */ - cl_git_pass(git_buf_putc(&url_buf, '/')); -#endif - - in_buf = git_buf_cstr(&path_buf); - - /* - * A very hacky Url encoding that only takes care of escaping the spaces - */ - while (*in_buf) { - if (*in_buf == ' ') - cl_git_pass(git_buf_puts(&url_buf, "%20")); - else - cl_git_pass(git_buf_putc(&url_buf, *in_buf)); - - in_buf++; - } - - strncpy(url, git_buf_cstr(&url_buf), 4096); - git_buf_free(&url_buf); - git_buf_free(&path_buf); - return url; -} - -typedef struct { - const char *filename; - size_t filename_len; -} remove_data; - -static int remove_placeholders_recurs(void *_data, git_buf *path) -{ - remove_data *data = (remove_data *)_data; - size_t pathlen; - - if (git_path_isdir(path->ptr) == true) - return git_path_direach(path, 0, remove_placeholders_recurs, data); - - pathlen = path->size; - - if (pathlen < data->filename_len) - return 0; - - /* if path ends in '/'+filename (or equals filename) */ - if (!strcmp(data->filename, path->ptr + pathlen - data->filename_len) && - (pathlen == data->filename_len || - path->ptr[pathlen - data->filename_len - 1] == '/')) - return p_unlink(path->ptr); - - return 0; -} - -int cl_git_remove_placeholders(const char *directory_path, const char *filename) -{ - int error; - remove_data data; - git_buf buffer = GIT_BUF_INIT; - - if (git_path_isdir(directory_path) == false) - return -1; - - if (git_buf_sets(&buffer, directory_path) < 0) - return -1; - - data.filename = filename; - data.filename_len = strlen(filename); - - error = remove_placeholders_recurs(&data, &buffer); - - git_buf_free(&buffer); - - return error; -} - -#define CL_COMMIT_NAME "Libgit2 Tester" -#define CL_COMMIT_EMAIL "libgit2-test@github.com" -#define CL_COMMIT_MSG "Test commit of tree " - -void cl_repo_commit_from_index( - git_oid *out, - git_repository *repo, - git_signature *sig, - git_time_t time, - const char *msg) -{ - git_index *index; - git_oid commit_id, tree_id; - git_object *parent = NULL; - git_reference *ref = NULL; - git_tree *tree = NULL; - char buf[128]; - int free_sig = (sig == NULL); - - /* it is fine if looking up HEAD fails - we make this the first commit */ - git_revparse_ext(&parent, &ref, repo, "HEAD"); - - /* write the index content as a tree */ - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_write_tree(&tree_id, index)); - cl_git_pass(git_index_write(index)); - git_index_free(index); - - cl_git_pass(git_tree_lookup(&tree, repo, &tree_id)); - - if (sig) - cl_assert(sig->name && sig->email); - else if (!time) - cl_git_pass(git_signature_now(&sig, CL_COMMIT_NAME, CL_COMMIT_EMAIL)); - else - cl_git_pass(git_signature_new( - &sig, CL_COMMIT_NAME, CL_COMMIT_EMAIL, time, 0)); - - if (!msg) { - strcpy(buf, CL_COMMIT_MSG); - git_oid_tostr(buf + strlen(CL_COMMIT_MSG), - sizeof(buf) - strlen(CL_COMMIT_MSG), &tree_id); - msg = buf; - } - - cl_git_pass(git_commit_create_v( - &commit_id, repo, ref ? git_reference_name(ref) : "HEAD", - sig, sig, NULL, msg, tree, parent ? 1 : 0, parent)); - - if (out) - git_oid_cpy(out, &commit_id); - - git_object_free(parent); - git_reference_free(ref); - if (free_sig) - git_signature_free(sig); - git_tree_free(tree); -} - -void cl_repo_set_bool(git_repository *repo, const char *cfg, int value) -{ - git_config *config; - cl_git_pass(git_repository_config(&config, repo)); - cl_git_pass(git_config_set_bool(config, cfg, value != 0)); - git_config_free(config); -} - -int cl_repo_get_bool(git_repository *repo, const char *cfg) -{ - int val = 0; - git_config *config; - cl_git_pass(git_repository_config(&config, repo)); - cl_git_pass(git_config_get_bool(&val, config, cfg));; - git_config_free(config); - return val; -} - -/* this is essentially the code from git__unescape modified slightly */ -static size_t strip_cr_from_buf(char *start, size_t len) -{ - char *scan, *trail, *end = start + len; - - for (scan = trail = start; scan < end; trail++, scan++) { - while (*scan == '\r') - scan++; /* skip '\r' */ - - if (trail != scan) - *trail = *scan; - } - - *trail = '\0'; - - return (trail - start); -} - -void clar__assert_equal_file( - const char *expected_data, - size_t expected_bytes, - int ignore_cr, - const char *path, - const char *file, - int line) -{ - char buf[4000]; - ssize_t bytes, total_bytes = 0; - int fd = p_open(path, O_RDONLY | O_BINARY); - cl_assert(fd >= 0); - - if (expected_data && !expected_bytes) - expected_bytes = strlen(expected_data); - - while ((bytes = p_read(fd, buf, sizeof(buf))) != 0) { - clar__assert( - bytes > 0, file, line, "error reading from file", path, 1); - - if (ignore_cr) - bytes = strip_cr_from_buf(buf, bytes); - - if (memcmp(expected_data, buf, bytes) != 0) { - int pos; - for (pos = 0; pos < bytes && expected_data[pos] == buf[pos]; ++pos) - /* find differing byte offset */; - p_snprintf( - buf, sizeof(buf), "file content mismatch at byte %d", - (int)(total_bytes + pos)); - clar__fail(file, line, buf, path, 1); - } - - expected_data += bytes; - total_bytes += bytes; - } - - p_close(fd); - - clar__assert(!bytes, file, line, "error reading from file", path, 1); - clar__assert_equal(file, line, "mismatched file length", 1, "%"PRIuZ, - (size_t)expected_bytes, (size_t)total_bytes); -} diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h deleted file mode 100644 index b9ef5627e..000000000 --- a/tests-clar/clar_libgit2.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef __CLAR_LIBGIT2__ -#define __CLAR_LIBGIT2__ - -#include "clar.h" -#include -#include "common.h" - -/** - * Replace for `clar_must_pass` that passes the last library error as the - * test failure message. - * - * Use this wrapper around all `git_` library calls that return error codes! - */ -#define cl_git_pass(expr) do { \ - int _lg2_error; \ - giterr_clear(); \ - if ((_lg2_error = (expr)) != 0) \ - cl_git_report_failure(_lg2_error, __FILE__, __LINE__, "Function call failed: " #expr); \ - } while (0) - -/** - * Wrapper for `clar_must_fail` -- this one is - * 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) - -void cl_git_report_failure(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) - -GIT_INLINE(void) clar__assert_in_range( - int lo, int val, int hi, - const char *file, int line, const char *err, int should_abort) -{ - if (lo > val || hi < val) { - char buf[128]; - snprintf(buf, sizeof(buf), "%d not in [%d,%d]", val, lo, hi); - clar__fail(file, line, err, buf, should_abort); - } -} - -#define cl_assert_equal_sz(sz1,sz2) do { \ - size_t __sz1 = (size_t)(sz1), __sz2 = (size_t)(sz2); \ - clar__assert_equal(__FILE__,__LINE__,#sz1 " != " #sz2, 1, "%"PRIuZ, __sz1, __sz2); \ -} while (0) - -#define cl_assert_in_range(L,V,H) \ - clar__assert_in_range((L),(V),(H),__FILE__,__LINE__,"Range check: " #V " in [" #L "," #H "]", 1) - -#define cl_assert_equal_file(DATA,SIZE,PATH) \ - clar__assert_equal_file(DATA,SIZE,0,PATH,__FILE__,(int)__LINE__) - -#define cl_assert_equal_file_ignore_cr(DATA,SIZE,PATH) \ - clar__assert_equal_file(DATA,SIZE,1,PATH,__FILE__,(int)__LINE__) - -void clar__assert_equal_file( - const char *expected_data, - size_t expected_size, - int ignore_cr, - const char *path, - const char *file, - int line); - -/* - * Some utility macros for building long strings - */ -#define REP4(STR) STR STR STR STR -#define REP15(STR) REP4(STR) REP4(STR) REP4(STR) STR STR STR -#define REP16(STR) REP4(REP4(STR)) -#define REP256(STR) REP16(REP16(STR)) -#define REP1024(STR) REP4(REP256(STR)) - -/* Write the contents of a buffer to disk */ -void cl_git_mkfile(const char *filename, const char *content); -void cl_git_append2file(const char *filename, const char *new_content); -void cl_git_rewritefile(const char *filename, const char *new_content); -void cl_git_write2file(const char *path, const char *data, - size_t datalen, int flags, unsigned int mode); - -bool cl_toggle_filemode(const char *filename); -bool cl_is_chmod_supported(void); - -/* Environment wrappers */ -char *cl_getenv(const char *name); -int cl_setenv(const char *name, const char *value); - -/* Reliable rename */ -int cl_rename(const char *source, const char *dest); - -/* Git sandbox setup helpers */ - -git_repository *cl_git_sandbox_init(const char *sandbox); -void cl_git_sandbox_cleanup(void); -git_repository *cl_git_sandbox_reopen(void); - -/* Local-repo url helpers */ -const char* cl_git_fixture_url(const char *fixturename); -const char* cl_git_path_url(const char *path); - -/* Test repository cleaner */ -int cl_git_remove_placeholders(const char *directory_path, const char *filename); - -/* commit creation helpers */ -void cl_repo_commit_from_index( - git_oid *out, - git_repository *repo, - git_signature *sig, - git_time_t time, - const char *msg); - -/* config setting helpers */ -void cl_repo_set_bool(git_repository *repo, const char *cfg, int value); -int cl_repo_get_bool(git_repository *repo, const char *cfg); - -#endif diff --git a/tests-clar/clone/empty.c b/tests-clar/clone/empty.c deleted file mode 100644 index 6d19244cc..000000000 --- a/tests-clar/clone/empty.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "clar_libgit2.h" - -#include "git2/clone.h" -#include "repository.h" - -static git_clone_options g_options; -static git_repository *g_repo; -static git_repository *g_repo_cloned; - -void test_clone_empty__initialize(void) -{ - git_repository *sandbox = cl_git_sandbox_init("empty_bare.git"); - git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; - cl_git_remove_placeholders(git_repository_path(sandbox), "dummy-marker.txt"); - - g_repo = NULL; - - memset(&g_options, 0, sizeof(git_clone_options)); - g_options.version = GIT_CLONE_OPTIONS_VERSION; - g_options.remote_callbacks = dummy_callbacks; -} - -void test_clone_empty__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -static void cleanup_repository(void *path) -{ - cl_fixture_cleanup((const char *)path); - - git_repository_free(g_repo_cloned); - g_repo_cloned = NULL; -} - -void test_clone_empty__can_clone_an_empty_local_repo_barely(void) -{ - char *local_name = "refs/heads/master"; - const char *expected_tracked_branch_name = "refs/remotes/origin/master"; - const char *expected_remote_name = "origin"; - char buffer[1024]; - git_reference *ref; - - cl_set_cleanup(&cleanup_repository, "./empty"); - - g_options.bare = true; - cl_git_pass(git_clone(&g_repo_cloned, "./empty_bare.git", "./empty", &g_options)); - - /* Although the HEAD is unborn... */ - cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo_cloned, local_name)); - - /* ...one can still retrieve the name of the remote tracking reference */ - cl_assert_equal_i((int)strlen(expected_tracked_branch_name) + 1, - git_branch_upstream_name(buffer, 1024, g_repo_cloned, local_name)); - - cl_assert_equal_s(expected_tracked_branch_name, buffer); - - /* ...and the name of the remote... */ - cl_assert_equal_i((int)strlen(expected_remote_name) + 1, - git_branch_remote_name(buffer, 1024, g_repo_cloned, expected_tracked_branch_name)); - - cl_assert_equal_s(expected_remote_name, buffer); - - /* ...even when the remote HEAD is unborn as well */ - cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo_cloned, - expected_tracked_branch_name)); -} - -void test_clone_empty__can_clone_an_empty_local_repo(void) -{ - cl_set_cleanup(&cleanup_repository, "./empty"); - - cl_git_pass(git_clone(&g_repo_cloned, "./empty_bare.git", "./empty", &g_options)); -} - -void test_clone_empty__can_clone_an_empty_standard_repo(void) -{ - cl_git_sandbox_cleanup(); - g_repo = cl_git_sandbox_init("empty_standard_repo"); - cl_git_remove_placeholders(git_repository_path(g_repo), "dummy-marker.txt"); - - cl_set_cleanup(&cleanup_repository, "./empty"); - - cl_git_pass(git_clone(&g_repo_cloned, "./empty_standard_repo", "./empty", &g_options)); -} diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c deleted file mode 100644 index a286e2a8f..000000000 --- a/tests-clar/clone/nonetwork.c +++ /dev/null @@ -1,179 +0,0 @@ -#include "clar_libgit2.h" - -#include "git2/clone.h" -#include "remote.h" -#include "fileops.h" -#include "repository.h" - -#define LIVE_REPO_URL "git://github.com/libgit2/TestGitRepository" - -static git_clone_options g_options; -static git_repository *g_repo; -static git_reference* g_ref; -static git_remote* g_remote; - -void test_clone_nonetwork__initialize(void) -{ - git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT; - git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; - - g_repo = NULL; - - memset(&g_options, 0, sizeof(git_clone_options)); - g_options.version = GIT_CLONE_OPTIONS_VERSION; - g_options.checkout_opts = dummy_opts; - g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; - g_options.remote_callbacks = dummy_callbacks; -} - -void test_clone_nonetwork__cleanup(void) -{ - if (g_repo) { - git_repository_free(g_repo); - g_repo = NULL; - } - - if (g_ref) { - git_reference_free(g_ref); - g_ref = NULL; - } - - if (g_remote) { - git_remote_free(g_remote); - g_remote = NULL; - } - - cl_fixture_cleanup("./foo"); -} - -void test_clone_nonetwork__bad_urls(void) -{ - /* Clone should clean up the mess if the URL isn't a git repository */ - cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); - cl_assert(!git_path_exists("./foo")); - g_options.bare = true; - cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); - cl_assert(!git_path_exists("./foo")); - - cl_git_fail(git_clone(&g_repo, "git://example.com:asdf", "./foo", &g_options)); - cl_git_fail(git_clone(&g_repo, "https://example.com:asdf/foo", "./foo", &g_options)); - cl_git_fail(git_clone(&g_repo, "git://github.com/git://github.com/foo/bar.git.git", - "./foo", &g_options)); - cl_git_fail(git_clone(&g_repo, "arrbee:my/bad:password@github.com:1111/strange:words.git", - "./foo", &g_options)); -} - -void test_clone_nonetwork__do_not_clean_existing_directory(void) -{ - /* Clone should not remove the directory if it already exists, but - * Should clean up entries it creates. */ - p_mkdir("./foo", GIT_DIR_MODE); - cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); - cl_assert(git_path_is_empty_dir("./foo")); - - /* Try again with a bare repository. */ - g_options.bare = true; - cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); - cl_assert(git_path_is_empty_dir("./foo")); -} - -void test_clone_nonetwork__local(void) -{ - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); -} - -void test_clone_nonetwork__local_absolute_path(void) -{ - const char *local_src; - local_src = cl_fixture("testrepo.git"); - cl_git_pass(git_clone(&g_repo, local_src, "./foo", &g_options)); -} - -void test_clone_nonetwork__local_bare(void) -{ - g_options.bare = true; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); -} - -void test_clone_nonetwork__fail_when_the_target_is_a_file(void) -{ - cl_git_mkfile("./foo", "Bar!"); - cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); -} - -void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(void) -{ - p_mkdir("./foo", GIT_DIR_MODE); - cl_git_mkfile("./foo/bar", "Baz!"); - cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); -} - -void test_clone_nonetwork__custom_origin_name(void) -{ - g_options.remote_name = "my_origin"; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin")); -} - -void test_clone_nonetwork__defaults(void) -{ - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", NULL)); - cl_assert(g_repo); - cl_git_pass(git_remote_load(&g_remote, g_repo, "origin")); -} - -void test_clone_nonetwork__cope_with_already_existing_directory(void) -{ - p_mkdir("./foo", GIT_DIR_MODE); - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); -} - -void test_clone_nonetwork__can_prevent_the_checkout_of_a_standard_repo(void) -{ - git_buf path = GIT_BUF_INIT; - - g_options.checkout_opts.checkout_strategy = 0; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); - cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&path))); - - git_buf_free(&path); -} - -void test_clone_nonetwork__can_checkout_given_branch(void) -{ - g_options.checkout_branch = "test"; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_assert_equal_i(0, git_repository_head_unborn(g_repo)); - - cl_git_pass(git_repository_head(&g_ref, g_repo)); - cl_assert_equal_s(git_reference_name(g_ref), "refs/heads/test"); -} - -void test_clone_nonetwork__can_detached_head(void) -{ - git_object *obj; - git_repository *cloned; - git_reference *cloned_head; - - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - - cl_git_pass(git_revparse_single(&obj, g_repo, "master~1")); - cl_git_pass(git_repository_set_head_detached(g_repo, git_object_id(obj))); - - cl_git_pass(git_clone(&cloned, "./foo", "./foo1", &g_options)); - - cl_assert(git_repository_head_detached(cloned)); - - cl_git_pass(git_repository_head(&cloned_head, cloned)); - cl_assert(!git_oid_cmp(git_object_id(obj), git_reference_target(cloned_head))); - - git_object_free(obj); - git_reference_free(cloned_head); - git_repository_free(cloned); - - cl_fixture_cleanup("./foo1"); -} diff --git a/tests-clar/commit/commit.c b/tests-clar/commit/commit.c deleted file mode 100644 index 8f071ff94..000000000 --- a/tests-clar/commit/commit.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "clar_libgit2.h" - -static git_repository *_repo; - -void test_commit_commit__initialize(void) -{ - cl_fixture_sandbox("testrepo.git"); - cl_git_pass(git_repository_open(&_repo, "testrepo.git")); -} - -void test_commit_commit__cleanup(void) -{ - git_repository_free(_repo); - _repo = NULL; - - cl_fixture_cleanup("testrepo.git"); -} - -void test_commit_commit__create_unexisting_update_ref(void) -{ - git_oid oid; - git_tree *tree; - git_commit *commit; - git_signature *s; - git_reference *ref; - - git_oid_fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - cl_git_pass(git_commit_lookup(&commit, _repo, &oid)); - - git_oid_fromstr(&oid, "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"); - cl_git_pass(git_tree_lookup(&tree, _repo, &oid)); - - cl_git_pass(git_signature_now(&s, "alice", "alice@example.com")); - - cl_git_fail(git_reference_lookup(&ref, _repo, "refs/heads/foo/bar")); - cl_git_pass(git_commit_create(&oid, _repo, "refs/heads/foo/bar", s, s, - NULL, "some msg", tree, 1, (const git_commit **) &commit)); - - cl_git_pass(git_reference_lookup(&ref, _repo, "refs/heads/foo/bar")); - cl_assert(!git_oid_cmp(&oid, git_reference_target(ref))); - - git_tree_free(tree); - git_commit_free(commit); - git_signature_free(s); - git_reference_free(ref); -} diff --git a/tests-clar/commit/parent.c b/tests-clar/commit/parent.c deleted file mode 100644 index 18ce0bba6..000000000 --- a/tests-clar/commit/parent.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "clar_libgit2.h" - -static git_repository *_repo; -static git_commit *commit; - -void test_commit_parent__initialize(void) -{ - git_oid oid; - - cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); - - git_oid_fromstr(&oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - cl_git_pass(git_commit_lookup(&commit, _repo, &oid)); -} - -void test_commit_parent__cleanup(void) -{ - git_commit_free(commit); - commit = NULL; - - git_repository_free(_repo); - _repo = NULL; -} - -static void assert_nth_gen_parent(unsigned int gen, const char *expected_oid) -{ - git_commit *parent = NULL; - int error; - - error = git_commit_nth_gen_ancestor(&parent, commit, gen); - - if (expected_oid != NULL) { - cl_assert_equal_i(0, error); - cl_assert_equal_i(0, git_oid_streq(git_commit_id(parent), expected_oid)); - } else - cl_assert_equal_i(GIT_ENOTFOUND, error); - - git_commit_free(parent); -} - -/* - * $ git show be35~0 - * commit be3563ae3f795b2b4353bcce3a527ad0a4f7f644 - * - * $ git show be35~1 - * commit 9fd738e8f7967c078dceed8190330fc8648ee56a - * - * $ git show be35~3 - * commit 5b5b025afb0b4c913b4c338a42934a3863bf3644 - * - * $ git show be35~42 - * fatal: ambiguous argument 'be35~42': unknown revision or path not in the working tree. - */ -void test_commit_parent__can_retrieve_nth_generation_parent(void) -{ - assert_nth_gen_parent(0, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - assert_nth_gen_parent(1, "9fd738e8f7967c078dceed8190330fc8648ee56a"); - assert_nth_gen_parent(3, "5b5b025afb0b4c913b4c338a42934a3863bf3644"); - assert_nth_gen_parent(42, NULL); -} diff --git a/tests-clar/commit/parse.c b/tests-clar/commit/parse.c deleted file mode 100644 index 41e162440..000000000 --- a/tests-clar/commit/parse.c +++ /dev/null @@ -1,413 +0,0 @@ -#include "clar_libgit2.h" -#include -#include "commit.h" -#include "signature.h" - -// Fixture setup -static git_repository *g_repo; -void test_commit_parse__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} -void test_commit_parse__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - - -// Header parsing -typedef struct { - const char *line; - const char *header; -} parse_test_case; - -static parse_test_case passing_header_cases[] = { - { "parent 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "parent " }, - { "tree 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree " }, - { "random_heading 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "random_heading " }, - { "stuck_heading05452d6349abcd67aa396dfb28660d765d8b2a36\n", "stuck_heading" }, - { "tree 5F4BEFFC0759261D015AA63A3A85613FF2F235DE\n", "tree " }, - { "tree 1A669B8AB81B5EB7D9DB69562D34952A38A9B504\n", "tree " }, - { "tree 5B20DCC6110FCC75D31C6CEDEBD7F43ECA65B503\n", "tree " }, - { "tree 173E7BF00EA5C33447E99E6C1255954A13026BE4\n", "tree " }, - { NULL, NULL } -}; - -static parse_test_case failing_header_cases[] = { - { "parent 05452d6349abcd67aa396dfb28660d765d8b2a36", "parent " }, - { "05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree " }, - { "parent05452d6349abcd67aa396dfb28660d765d8b2a6a\n", "parent " }, - { "parent 05452d6349abcd67aa396dfb280d765d8b2a6\n", "parent " }, - { "tree 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree " }, - { "parent 0545xd6349abcd67aa396dfb28660d765d8b2a36\n", "parent " }, - { "parent 0545xd6349abcd67aa396dfb28660d765d8b2a36FF\n", "parent " }, - { "", "tree " }, - { "", "" }, - { NULL, NULL } -}; - -void test_commit_parse__header(void) -{ - git_oid oid; - - parse_test_case *testcase; - for (testcase = passing_header_cases; testcase->line != NULL; testcase++) - { - const char *line = testcase->line; - const char *line_end = line + strlen(line); - - cl_git_pass(git_oid__parse(&oid, &line, line_end, testcase->header)); - cl_assert(line == line_end); - } - - for (testcase = failing_header_cases; testcase->line != NULL; testcase++) - { - const char *line = testcase->line; - const char *line_end = line + strlen(line); - - cl_git_fail(git_oid__parse(&oid, &line, line_end, testcase->header)); - } -} - - -// Signature parsing -typedef struct { - const char *string; - const char *header; - const char *name; - const char *email; - git_time_t time; - int offset; -} passing_signature_test_case; - -passing_signature_test_case passing_signature_cases[] = { - {"author Vicent Marti 12345 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 12345, 0}, - {"author Vicent Marti <> 12345 \n", "author ", "Vicent Marti", "", 12345, 0}, - {"author Vicent Marti 231301 +1020\n", "author ", "Vicent Marti", "tanoku@gmail.com", 231301, 620}, - {"author Vicent Marti with an outrageously long name which will probably overflow the buffer 12345 \n", "author ", "Vicent Marti with an outrageously long name which will probably overflow the buffer", "tanoku@gmail.com", 12345, 0}, - {"author Vicent Marti 12345 \n", "author ", "Vicent Marti", "tanokuwithaveryveryverylongemailwhichwillprobablyvoverflowtheemailbuffer@gmail.com", 12345, 0}, - {"committer Vicent Marti 123456 +0000 \n", "committer ", "Vicent Marti", "tanoku@gmail.com", 123456, 0}, - {"committer Vicent Marti 123456 +0100 \n", "committer ", "Vicent Marti", "tanoku@gmail.com", 123456, 60}, - {"committer Vicent Marti 123456 -0100 \n", "committer ", "Vicent Marti", "tanoku@gmail.com", 123456, -60}, - // Parse a signature without an author field - {"committer 123456 -0100 \n", "committer ", "", "tanoku@gmail.com", 123456, -60}, - // Parse a signature without an author field - {"committer 123456 -0100 \n", "committer ", "", "tanoku@gmail.com", 123456, -60}, - // Parse a signature with an empty author field - {"committer 123456 -0100 \n", "committer ", "", "tanoku@gmail.com", 123456, -60}, - // Parse a signature with an empty email field - {"committer Vicent Marti <> 123456 -0100 \n", "committer ", "Vicent Marti", "", 123456, -60}, - // Parse a signature with an empty email field - {"committer Vicent Marti < > 123456 -0100 \n", "committer ", "Vicent Marti", "", 123456, -60}, - // Parse a signature with empty name and email - {"committer <> 123456 -0100 \n", "committer ", "", "", 123456, -60}, - // Parse a signature with empty name and email - {"committer <> 123456 -0100 \n", "committer ", "", "", 123456, -60}, - // Parse a signature with empty name and email - {"committer < > 123456 -0100 \n", "committer ", "", "", 123456, -60}, - // Parse an obviously invalid signature - {"committer foo<@bar> 123456 -0100 \n", "committer ", "foo", "@bar", 123456, -60}, - // Parse an obviously invalid signature - {"committer foo<@bar> 123456 -0100 \n", "committer ", "foo", "@bar", 123456, -60}, - // Parse an obviously invalid signature - {"committer <>\n", "committer ", "", "", 0, 0}, - {"committer Vicent Marti 123456 -1500 \n", "committer ", "Vicent Marti", "tanoku@gmail.com", 123456, 0}, - {"committer Vicent Marti 123456 +0163 \n", "committer ", "Vicent Marti", "tanoku@gmail.com", 123456, 0}, - {"author Vicent Marti \n", "author ", "Vicent Marti", "tanoku@gmail.com", 0, 0}, - /* a variety of dates */ - {"author Vicent Marti 0 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 0, 0}, - {"author Vicent Marti 1234567890 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 1234567890, 0}, - {"author Vicent Marti 2147483647 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 0x7fffffff, 0}, - {"author Vicent Marti 4294967295 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 0xffffffff, 0}, - {"author Vicent Marti 4294967296 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 4294967296, 0}, - {"author Vicent Marti 8589934592 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 8589934592, 0}, - - {NULL,NULL,NULL,NULL,0,0} -}; - -typedef struct { - const char *string; - const char *header; -} failing_signature_test_case; - -failing_signature_test_case failing_signature_cases[] = { - {"committer Vicent Marti tanoku@gmail.com> 123456 -0100 \n", "committer "}, - {"author Vicent Marti 12345 \n", "author "}, - {"author Vicent Marti 12345 \n", "committer "}, - {"author Vicent Marti 12345 \n", "author "}, - {"author Vicent Marti <\n", "committer "}, - {"author ", "author "}, - {NULL, NULL,} -}; - -void test_commit_parse__signature(void) -{ - passing_signature_test_case *passcase; - failing_signature_test_case *failcase; - - for (passcase = passing_signature_cases; passcase->string != NULL; passcase++) - { - const char *str = passcase->string; - size_t len = strlen(passcase->string); - struct git_signature person = {0}; - - cl_git_pass(git_signature__parse(&person, &str, str + len, passcase->header, '\n')); - cl_assert_equal_s(passcase->name, person.name); - cl_assert_equal_s(passcase->email, person.email); - cl_assert_equal_i((int)passcase->time, (int)person.when.time); - cl_assert_equal_i(passcase->offset, person.when.offset); - git__free(person.name); git__free(person.email); - } - - for (failcase = failing_signature_cases; failcase->string != NULL; failcase++) - { - const char *str = failcase->string; - size_t len = strlen(failcase->string); - git_signature person = {0}; - cl_git_fail(git_signature__parse(&person, &str, str + len, failcase->header, '\n')); - git__free(person.name); git__free(person.email); - } -} - - - -static char *failing_commit_cases[] = { -// empty commit -"", -// random garbage -"asd97sa9du902e9a0jdsuusad09as9du098709aweu8987sd\n", -// broken endlines 1 -"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\r\n\ -parent 05452d6349abcd67aa396dfb28660d765d8b2a36\r\n\ -author Vicent Marti 1273848544 +0200\r\n\ -committer Vicent Marti 1273848544 +0200\r\n\ -\r\n\ -a test commit with broken endlines\r\n", -// broken endlines 2 -"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\ -parent 05452d6349abcd67aa396dfb28660d765d8b2a36\ -author Vicent Marti 1273848544 +0200\ -committer Vicent Marti 1273848544 +0200\ -\ -another test commit with broken endlines", -// starting endlines -"\ntree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\ -parent 05452d6349abcd67aa396dfb28660d765d8b2a36\n\ -author Vicent Marti 1273848544 +0200\n\ -committer Vicent Marti 1273848544 +0200\n\ -\n\ -a test commit with a starting endline\n", -// corrupted commit 1 -"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\ -parent 05452d6349abcd67aa396df", -// corrupted commit 2 -"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\ -parent ", -// corrupted commit 3 -"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\ -parent ", -// corrupted commit 4 -"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\ -par", -}; - - -static char *passing_commit_cases[] = { -// simple commit with no message -"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ -author Vicent Marti 1273848544 +0200\n\ -committer Vicent Marti 1273848544 +0200\n\ -\n", -// simple commit, no parent -"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ -author Vicent Marti 1273848544 +0200\n\ -committer Vicent Marti 1273848544 +0200\n\ -\n\ -a simple commit which works\n", -// simple commit, no parent, no newline in message -"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ -author Vicent Marti 1273848544 +0200\n\ -committer Vicent Marti 1273848544 +0200\n\ -\n\ -a simple commit which works", -// simple commit, 1 parent -"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ -parent e90810b8df3e80c413d903f631643c716887138d\n\ -author Vicent Marti 1273848544 +0200\n\ -committer Vicent Marti 1273848544 +0200\n\ -\n\ -a simple commit which works\n", -/* simple commit with GPG signature */ -"tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\ -parent 34734e478d6cf50c27c9d69026d93974d052c454\n\ -author Ben Burkert 1358451456 -0800\n\ -committer Ben Burkert 1358451456 -0800\n\ -gpgsig -----BEGIN PGP SIGNATURE-----\n\ - Version: GnuPG v1.4.12 (Darwin)\n\ - \n\ - iQIcBAABAgAGBQJQ+FMIAAoJEH+LfPdZDSs1e3EQAJMjhqjWF+WkGLHju7pTw2al\n\ - o6IoMAhv0Z/LHlWhzBd9e7JeCnanRt12bAU7yvYp9+Z+z+dbwqLwDoFp8LVuigl8\n\ - JGLcnwiUW3rSvhjdCp9irdb4+bhKUnKUzSdsR2CK4/hC0N2i/HOvMYX+BRsvqweq\n\ - AsAkA6dAWh+gAfedrBUkCTGhlNYoetjdakWqlGL1TiKAefEZrtA1TpPkGn92vbLq\n\ - SphFRUY9hVn1ZBWrT3hEpvAIcZag3rTOiRVT1X1flj8B2vGCEr3RrcwOIZikpdaW\n\ - who/X3xh/DGbI2RbuxmmJpxxP/8dsVchRJJzBwG+yhwU/iN3MlV2c5D69tls/Dok\n\ - 6VbyU4lm/ae0y3yR83D9dUlkycOnmmlBAHKIZ9qUts9X7mWJf0+yy2QxJVpjaTGG\n\ - cmnQKKPeNIhGJk2ENnnnzjEve7L7YJQF6itbx5VCOcsGh3Ocb3YR7DMdWjt7f8pu\n\ - c6j+q1rP7EpE2afUN/geSlp5i3x8aXZPDj67jImbVCE/Q1X9voCtyzGJH7MXR0N9\n\ - ZpRF8yzveRfMH8bwAJjSOGAFF5XkcR/RNY95o+J+QcgBLdX48h+ZdNmUf6jqlu3J\n\ - 7KmTXXQcOVpN6dD3CmRFsbjq+x6RHwa8u1iGn+oIkX908r97ckfB/kHKH7ZdXIJc\n\ - cpxtDQQMGYFpXK/71stq\n\ - =ozeK\n\ - -----END PGP SIGNATURE-----\n\ -\n\ -a simple commit which works\n", -}; - -static int parse_commit(git_commit **out, const char *buffer) -{ - git_commit *commit; - git_odb_object fake_odb_object; - int error; - - commit = (git_commit*)git__malloc(sizeof(git_commit)); - memset(commit, 0x0, sizeof(git_commit)); - commit->object.repo = g_repo; - - memset(&fake_odb_object, 0x0, sizeof(git_odb_object)); - fake_odb_object.buffer = (char *)buffer; - fake_odb_object.cached.size = strlen(fake_odb_object.buffer); - - error = git_commit__parse(commit, &fake_odb_object); - - *out = commit; - return error; -} - -void test_commit_parse__entire_commit(void) -{ - const int failing_commit_count = ARRAY_SIZE(failing_commit_cases); - const int passing_commit_count = ARRAY_SIZE(passing_commit_cases); - int i; - git_commit *commit; - - for (i = 0; i < failing_commit_count; ++i) { - cl_git_fail(parse_commit(&commit, failing_commit_cases[i])); - git_commit__free(commit); - } - - for (i = 0; i < passing_commit_count; ++i) { - cl_git_pass(parse_commit(&commit, passing_commit_cases[i])); - - if (!i) - cl_assert_equal_s("", git_commit_message(commit)); - else - cl_assert(git__prefixcmp( - git_commit_message(commit), "a simple commit which works") == 0); - - git_commit__free(commit); - } -} - - -// query the details on a parsed commit -void test_commit_parse__details0(void) { - static const char *commit_ids[] = { - "a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */ - "9fd738e8f7967c078dceed8190330fc8648ee56a", /* 1 */ - "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", /* 2 */ - "c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */ - "8496071c1b46c854b31185ea97743be6a8774479", /* 4 */ - "5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */ - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", /* 6 */ - }; - const size_t commit_count = sizeof(commit_ids) / sizeof(const char *); - unsigned int i; - - for (i = 0; i < commit_count; ++i) { - git_oid id; - git_commit *commit; - - const git_signature *author, *committer; - const char *message; - git_time_t commit_time; - unsigned int parents, p; - git_commit *parent = NULL, *old_parent = NULL; - - git_oid_fromstr(&id, commit_ids[i]); - - cl_git_pass(git_commit_lookup(&commit, g_repo, &id)); - - message = git_commit_message(commit); - author = git_commit_author(commit); - committer = git_commit_committer(commit); - commit_time = git_commit_time(commit); - parents = git_commit_parentcount(commit); - - cl_assert_equal_s("Scott Chacon", author->name); - cl_assert_equal_s("schacon@gmail.com", author->email); - cl_assert_equal_s("Scott Chacon", committer->name); - cl_assert_equal_s("schacon@gmail.com", committer->email); - cl_assert(message != NULL); - cl_assert(commit_time > 0); - cl_assert(parents <= 2); - for (p = 0;p < parents;p++) { - if (old_parent != NULL) - git_commit_free(old_parent); - - old_parent = parent; - cl_git_pass(git_commit_parent(&parent, commit, p)); - cl_assert(parent != NULL); - cl_assert(git_commit_author(parent) != NULL); // is it really a commit? - } - git_commit_free(old_parent); - git_commit_free(parent); - - cl_git_fail(git_commit_parent(&parent, commit, parents)); - git_commit_free(commit); - } -} - -void test_commit_parse__leading_lf(void) -{ - git_commit *commit; - const char *buffer = -"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ -parent e90810b8df3e80c413d903f631643c716887138d\n\ -author Vicent Marti 1273848544 +0200\n\ -committer Vicent Marti 1273848544 +0200\n\ -\n\ -\n\ -\n\ -This commit has a few LF at the start of the commit message"; - const char *message = -"This commit has a few LF at the start of the commit message"; - const char *raw_message = -"\n\ -\n\ -This commit has a few LF at the start of the commit message"; - cl_git_pass(parse_commit(&commit, buffer)); - cl_assert_equal_s(message, git_commit_message(commit)); - cl_assert_equal_s(raw_message, git_commit_message_raw(commit)); - git_commit__free(commit); -} - -void test_commit_parse__only_lf(void) -{ - git_commit *commit; - const char *buffer = -"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ -parent e90810b8df3e80c413d903f631643c716887138d\n\ -author Vicent Marti 1273848544 +0200\n\ -committer Vicent Marti 1273848544 +0200\n\ -\n\ -\n\ -\n"; - const char *message = ""; - const char *raw_message = "\n\n"; - - cl_git_pass(parse_commit(&commit, buffer)); - cl_assert_equal_s(message, git_commit_message(commit)); - cl_assert_equal_s(raw_message, git_commit_message_raw(commit)); - git_commit__free(commit); -} diff --git a/tests-clar/commit/signature.c b/tests-clar/commit/signature.c deleted file mode 100644 index e9dcfab41..000000000 --- a/tests-clar/commit/signature.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "clar_libgit2.h" - -static int try_build_signature(const char *name, const char *email, git_time_t time, int offset) -{ - git_signature *sign; - int error = 0; - - if ((error = git_signature_new(&sign, name, email, time, offset)) < 0) - return error; - - git_signature_free((git_signature *)sign); - - return error; -} - -static void assert_name_and_email( - const char *expected_name, - const char *expected_email, - const char *name, - const char *email) -{ - git_signature *sign; - - cl_git_pass(git_signature_new(&sign, name, email, 1234567890, 60)); - cl_assert_equal_s(expected_name, sign->name); - cl_assert_equal_s(expected_email, sign->email); - - git_signature_free(sign); -} - -void test_commit_signature__leading_and_trailing_spaces_are_trimmed(void) -{ - assert_name_and_email("nulltoken", "emeric.fermas@gmail.com", " nulltoken ", " emeric.fermas@gmail.com "); - assert_name_and_email("nulltoken", "emeric.fermas@gmail.com", " nulltoken ", " emeric.fermas@gmail.com \n"); - assert_name_and_email("nulltoken", "emeric.fermas@gmail.com", " \t nulltoken \n", " \n emeric.fermas@gmail.com \n"); -} - -void test_commit_signature__angle_brackets_in_names_are_not_supported(void) -{ - cl_git_fail(try_build_signature("Haack", "phil@haack", 1234567890, 60)); - cl_git_fail(try_build_signature("", "phil@haack", 1234567890, 60)); -} - -void test_commit_signature__angle_brackets_in_email_are_not_supported(void) -{ - cl_git_fail(try_build_signature("Phil Haack", ">phil@haack", 1234567890, 60)); - cl_git_fail(try_build_signature("Phil Haack", "phil@>haack", 1234567890, 60)); - cl_git_fail(try_build_signature("Phil Haack", "", 1234567890, 60)); -} - -void test_commit_signature__create_empties(void) -{ - // can not create a signature with empty name or email - cl_git_pass(try_build_signature("nulltoken", "emeric.fermas@gmail.com", 1234567890, 60)); - - cl_git_fail(try_build_signature("", "emeric.fermas@gmail.com", 1234567890, 60)); - cl_git_fail(try_build_signature(" ", "emeric.fermas@gmail.com", 1234567890, 60)); - cl_git_pass(try_build_signature("nulltoken", "", 1234567890, 60)); - cl_git_pass(try_build_signature("nulltoken", " ", 1234567890, 60)); -} - -void test_commit_signature__create_one_char(void) -{ - // creating a one character signature - assert_name_and_email("x", "foo@bar.baz", "x", "foo@bar.baz"); -} - -void test_commit_signature__create_two_char(void) -{ - // creating a two character signature - assert_name_and_email("xx", "foo@bar.baz", "xx", "foo@bar.baz"); -} - -void test_commit_signature__create_zero_char(void) -{ - // creating a zero character signature - git_signature *sign; - cl_git_fail(git_signature_new(&sign, "", "x@y.z", 1234567890, 60)); - cl_assert(sign == NULL); -} diff --git a/tests-clar/commit/write.c b/tests-clar/commit/write.c deleted file mode 100644 index 73436b74b..000000000 --- a/tests-clar/commit/write.c +++ /dev/null @@ -1,147 +0,0 @@ -#include "clar_libgit2.h" - -static const char *committer_name = "Vicent Marti"; -static const char *committer_email = "vicent@github.com"; -static const char *commit_message = "This commit has been created in memory\n\ - This is a commit created in memory and it will be written back to disk\n"; -static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd"; -static const char *root_commit_message = "This is a root commit\n\ - This is a root commit and should be the only one in this branch\n"; -static char *head_old; -static git_reference *head, *branch; -static git_commit *commit; - -// Fixture setup -static git_repository *g_repo; -void test_commit_write__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_commit_write__cleanup(void) -{ - git_reference_free(head); - head = NULL; - - git_reference_free(branch); - branch = NULL; - - git_commit_free(commit); - commit = NULL; - - git__free(head_old); - head_old = NULL; - - cl_git_sandbox_cleanup(); -} - - -// write a new commit object from memory to disk -void test_commit_write__from_memory(void) -{ - git_oid tree_id, parent_id, commit_id; - git_signature *author, *committer; - const git_signature *author1, *committer1; - git_commit *parent; - git_tree *tree; - const char *commit_id_str = "8496071c1b46c854b31185ea97743be6a8774479"; - - git_oid_fromstr(&tree_id, tree_oid); - cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); - - git_oid_fromstr(&parent_id, commit_id_str); - cl_git_pass(git_commit_lookup(&parent, g_repo, &parent_id)); - - /* create signatures */ - cl_git_pass(git_signature_new(&committer, committer_name, committer_email, 123456789, 60)); - cl_git_pass(git_signature_new(&author, committer_name, committer_email, 987654321, 90)); - - cl_git_pass(git_commit_create_v( - &commit_id, /* out id */ - g_repo, - NULL, /* do not update the HEAD */ - author, - committer, - NULL, - commit_message, - tree, - 1, parent)); - - git_object_free((git_object *)parent); - git_object_free((git_object *)tree); - - git_signature_free(committer); - git_signature_free(author); - - cl_git_pass(git_commit_lookup(&commit, g_repo, &commit_id)); - - /* Check attributes were set correctly */ - author1 = git_commit_author(commit); - cl_assert(author1 != NULL); - cl_assert_equal_s(committer_name, author1->name); - cl_assert_equal_s(committer_email, author1->email); - cl_assert(author1->when.time == 987654321); - cl_assert(author1->when.offset == 90); - - committer1 = git_commit_committer(commit); - cl_assert(committer1 != NULL); - cl_assert_equal_s(committer_name, committer1->name); - cl_assert_equal_s(committer_email, committer1->email); - cl_assert(committer1->when.time == 123456789); - cl_assert(committer1->when.offset == 60); - - cl_assert_equal_s(commit_message, git_commit_message(commit)); -} - -// create a root commit -void test_commit_write__root(void) -{ - git_oid tree_id, commit_id; - const git_oid *branch_oid; - git_signature *author, *committer; - const char *branch_name = "refs/heads/root-commit-branch"; - git_tree *tree; - - git_oid_fromstr(&tree_id, tree_oid); - cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); - - /* create signatures */ - cl_git_pass(git_signature_new(&committer, committer_name, committer_email, 123456789, 60)); - cl_git_pass(git_signature_new(&author, committer_name, committer_email, 987654321, 90)); - - /* First we need to update HEAD so it points to our non-existant branch */ - cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); - cl_assert(git_reference_type(head) == GIT_REF_SYMBOLIC); - head_old = git__strdup(git_reference_symbolic_target(head)); - cl_assert(head_old != NULL); - git_reference_free(head); - - cl_git_pass(git_reference_symbolic_create(&head, g_repo, "HEAD", branch_name, 1)); - - cl_git_pass(git_commit_create_v( - &commit_id, /* out id */ - g_repo, - "HEAD", - author, - committer, - NULL, - root_commit_message, - tree, - 0)); - - git_object_free((git_object *)tree); - git_signature_free(committer); - git_signature_free(author); - - /* - * The fact that creating a commit works has already been - * tested. Here we just make sure it's our commit and that it was - * written as a root commit. - */ - cl_git_pass(git_commit_lookup(&commit, g_repo, &commit_id)); - cl_assert(git_commit_parentcount(commit) == 0); - cl_git_pass(git_reference_lookup(&branch, g_repo, branch_name)); - branch_oid = git_reference_target(branch); - cl_git_pass(git_oid_cmp(branch_oid, &commit_id)); - cl_assert_equal_s(root_commit_message, git_commit_message(commit)); -} diff --git a/tests-clar/config/add.c b/tests-clar/config/add.c deleted file mode 100644 index 405f1e2c9..000000000 --- a/tests-clar/config/add.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "clar_libgit2.h" - -void test_config_add__initialize(void) -{ - cl_fixture_sandbox("config/config10"); -} - -void test_config_add__cleanup(void) -{ - cl_fixture_cleanup("config10"); -} - -void test_config_add__to_existing_section(void) -{ - git_config *cfg; - int32_t i; - - cl_git_pass(git_config_open_ondisk(&cfg, "config10")); - cl_git_pass(git_config_set_int32(cfg, "empty.tmp", 5)); - cl_git_pass(git_config_get_int32(&i, cfg, "empty.tmp")); - cl_assert(i == 5); - cl_git_pass(git_config_delete_entry(cfg, "empty.tmp")); - git_config_free(cfg); -} - -void test_config_add__to_new_section(void) -{ - git_config *cfg; - int32_t i; - - cl_git_pass(git_config_open_ondisk(&cfg, "config10")); - cl_git_pass(git_config_set_int32(cfg, "section.tmp", 5)); - cl_git_pass(git_config_get_int32(&i, cfg, "section.tmp")); - cl_assert(i == 5); - cl_git_pass(git_config_delete_entry(cfg, "section.tmp")); - git_config_free(cfg); -} diff --git a/tests-clar/config/backend.c b/tests-clar/config/backend.c deleted file mode 100644 index 3fd6eb114..000000000 --- a/tests-clar/config/backend.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/sys/config.h" - -void test_config_backend__checks_version(void) -{ - git_config *cfg; - git_config_backend backend = GIT_CONFIG_BACKEND_INIT; - const git_error *err; - - backend.version = 1024; - - cl_git_pass(git_config_new(&cfg)); - cl_git_fail(git_config_add_backend(cfg, &backend, 0, false)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); - - giterr_clear(); - backend.version = 1024; - cl_git_fail(git_config_add_backend(cfg, &backend, 0, false)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); - - git_config_free(cfg); -} diff --git a/tests-clar/config/config_helpers.c b/tests-clar/config/config_helpers.c deleted file mode 100644 index 53bd945a0..000000000 --- a/tests-clar/config/config_helpers.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "clar_libgit2.h" -#include "config_helpers.h" -#include "repository.h" - -void assert_config_entry_existence( - git_repository *repo, - const char *name, - bool is_supposed_to_exist) -{ - git_config *config; - const char *out; - int result; - - cl_git_pass(git_repository_config__weakptr(&config, repo)); - - result = git_config_get_string(&out, config, name); - - if (is_supposed_to_exist) - cl_git_pass(result); - else - cl_assert_equal_i(GIT_ENOTFOUND, result); -} - -void assert_config_entry_value( - git_repository *repo, - const char *name, - const char *expected_value) -{ - git_config *config; - const char *out; - - cl_git_pass(git_repository_config__weakptr(&config, repo)); - - cl_git_pass(git_config_get_string(&out, config, name)); - - cl_assert_equal_s(expected_value, out); -} diff --git a/tests-clar/config/config_helpers.h b/tests-clar/config/config_helpers.h deleted file mode 100644 index b887b3d38..000000000 --- a/tests-clar/config/config_helpers.h +++ /dev/null @@ -1,9 +0,0 @@ -extern void assert_config_entry_existence( - git_repository *repo, - const char *name, - bool is_supposed_to_exist); - -extern void assert_config_entry_value( - git_repository *repo, - const char *name, - const char *expected_value); diff --git a/tests-clar/config/configlevel.c b/tests-clar/config/configlevel.c deleted file mode 100644 index 1c22e8d9f..000000000 --- a/tests-clar/config/configlevel.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "clar_libgit2.h" - -void test_config_configlevel__adding_the_same_level_twice_returns_EEXISTS(void) -{ - int error; - git_config *cfg; - - cl_git_pass(git_config_new(&cfg)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), - GIT_CONFIG_LEVEL_LOCAL, 0)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), - GIT_CONFIG_LEVEL_GLOBAL, 0)); - error = git_config_add_file_ondisk(cfg, cl_fixture("config/config16"), - GIT_CONFIG_LEVEL_GLOBAL, 0); - - cl_git_fail(error); - cl_assert_equal_i(GIT_EEXISTS, error); - - git_config_free(cfg); -} - -void test_config_configlevel__can_replace_a_config_file_at_an_existing_level(void) -{ - git_config *cfg; - const char *s; - - cl_git_pass(git_config_new(&cfg)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"), - GIT_CONFIG_LEVEL_LOCAL, 1)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"), - GIT_CONFIG_LEVEL_LOCAL, 1)); - - cl_git_pass(git_config_get_string(&s, cfg, "core.stringglobal")); - cl_assert_equal_s("don't find me!", s); - - git_config_free(cfg); -} - -void test_config_configlevel__can_read_from_a_single_level_focused_file_after_parent_config_has_been_freed(void) -{ - git_config *cfg; - git_config *single_level_cfg; - const char *s; - - cl_git_pass(git_config_new(&cfg)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"), - GIT_CONFIG_LEVEL_GLOBAL, 0)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"), - GIT_CONFIG_LEVEL_LOCAL, 0)); - - cl_git_pass(git_config_open_level(&single_level_cfg, cfg, GIT_CONFIG_LEVEL_LOCAL)); - - git_config_free(cfg); - - cl_git_pass(git_config_get_string(&s, single_level_cfg, "core.stringglobal")); - cl_assert_equal_s("don't find me!", s); - - git_config_free(single_level_cfg); -} - -void test_config_configlevel__fetching_a_level_from_an_empty_compound_config_returns_ENOTFOUND(void) -{ - git_config *cfg; - git_config *local_cfg; - - cl_git_pass(git_config_new(&cfg)); - - cl_assert_equal_i(GIT_ENOTFOUND, git_config_open_level(&local_cfg, cfg, GIT_CONFIG_LEVEL_LOCAL)); - - git_config_free(cfg); -} diff --git a/tests-clar/config/global.c b/tests-clar/config/global.c deleted file mode 100644 index d5f95f504..000000000 --- a/tests-clar/config/global.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "fileops.h" - -void test_config_global__initialize(void) -{ - git_buf path = GIT_BUF_INIT; - - cl_assert_equal_i(0, p_mkdir("home", 0777)); - cl_git_pass(git_path_prettify(&path, "home", NULL)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); - - cl_assert_equal_i(0, p_mkdir("xdg", 0777)); - cl_assert_equal_i(0, p_mkdir("xdg/git", 0777)); - cl_git_pass(git_path_prettify(&path, "xdg/git", NULL)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); - - cl_assert_equal_i(0, p_mkdir("etc", 0777)); - cl_git_pass(git_path_prettify(&path, "etc", NULL)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); - - git_buf_free(&path); -} - -void test_config_global__cleanup(void) -{ - cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES)); - cl_git_pass(git_futils_rmdir_r("xdg", NULL, GIT_RMDIR_REMOVE_FILES)); - cl_git_pass(git_futils_rmdir_r("etc", NULL, GIT_RMDIR_REMOVE_FILES)); - - git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, NULL); - git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, NULL); - git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, NULL); -} - -void test_config_global__open_global(void) -{ - git_config *cfg, *global, *selected, *dummy; - - cl_git_pass(git_config_open_default(&cfg)); - cl_git_pass(git_config_open_level(&global, cfg, GIT_CONFIG_LEVEL_GLOBAL)); - cl_git_fail(git_config_open_level(&dummy, cfg, GIT_CONFIG_LEVEL_XDG)); - cl_git_pass(git_config_open_global(&selected, cfg)); - - git_config_free(selected); - git_config_free(global); - git_config_free(cfg); -} - -void test_config_global__open_xdg(void) -{ - git_config *cfg, *xdg, *selected; - const char *val, *str = "teststring"; - const char *key = "this.variable"; - - cl_git_mkfile("xdg/git/config", "# XDG config\n[core]\n test = 1\n"); - - cl_git_pass(git_config_open_default(&cfg)); - cl_git_pass(git_config_open_level(&xdg, cfg, GIT_CONFIG_LEVEL_XDG)); - cl_git_pass(git_config_open_global(&selected, cfg)); - - cl_git_pass(git_config_set_string(xdg, key, str)); - cl_git_pass(git_config_get_string(&val, selected, key)); - cl_assert_equal_s(str, val); - - git_config_free(selected); - git_config_free(xdg); - git_config_free(cfg); -} diff --git a/tests-clar/config/include.c b/tests-clar/config/include.c deleted file mode 100644 index 535573808..000000000 --- a/tests-clar/config/include.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "fileops.h" - -void test_config_include__relative(void) -{ - git_config *cfg; - const char *str; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config-include"))); - - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); - cl_assert_equal_s(str, "huzzah"); - - git_config_free(cfg); -} - -void test_config_include__absolute(void) -{ - git_config *cfg; - const char *str; - git_buf buf = GIT_BUF_INIT; - - cl_git_pass(git_buf_printf(&buf, "[include]\npath = %s/config-included", cl_fixture("config"))); - - cl_git_mkfile("config-include-absolute", git_buf_cstr(&buf)); - git_buf_free(&buf); - cl_git_pass(git_config_open_ondisk(&cfg, "config-include-absolute")); - - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); - cl_assert_equal_s(str, "huzzah"); - - git_config_free(cfg); -} - -void test_config_include__homedir(void) -{ - git_config *cfg; - const char *str; - - cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, cl_fixture("config"))); - cl_git_mkfile("config-include-homedir", "[include]\npath = ~/config-included"); - - cl_git_pass(git_config_open_ondisk(&cfg, "config-include-homedir")); - - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); - cl_assert_equal_s(str, "huzzah"); - - git_config_free(cfg); -} - -void test_config_include__refresh(void) -{ - git_config *cfg; - const char *str; - - cl_fixture_sandbox("config"); - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config-include")); - - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); - cl_assert_equal_s(str, "huzzah"); - - /* Change the included file and see if we refresh */ - cl_git_mkfile("config/config-included", "[foo \"bar\"]\nbaz = hurrah"); - cl_git_pass(git_config_refresh(cfg)); - - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); - cl_assert_equal_s(str, "hurrah"); - - git_config_free(cfg); - cl_fixture_cleanup("config"); -} - -/* We need to pretend that the variables were defined where the file was included */ -void test_config_include__ordering(void) -{ - git_config *cfg; - const char *str; - - cl_git_mkfile("included", "[foo \"bar\"]\nbaz = hurrah\nfrotz = hiya"); - cl_git_mkfile("including", - "[foo \"bar\"]\nfrotz = hello\n" - "[include]\npath = included\n" - "[foo \"bar\"]\nbaz = huzzah\n"); - - cl_git_pass(git_config_open_ondisk(&cfg, "including")); - - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.frotz")); - cl_assert_equal_s(str, "hiya"); - cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); - cl_assert_equal_s(str, "huzzah"); - - git_config_free(cfg); -} - -/* We need to pretend that the variables were defined where the file was included */ -void test_config_include__depth(void) -{ - git_config *cfg; - - cl_git_mkfile("a", "[include]\npath = b"); - cl_git_mkfile("b", "[include]\npath = a"); - - cl_git_fail(git_config_open_ondisk(&cfg, "a")); - - unlink("a"); - unlink("b"); -} diff --git a/tests-clar/config/multivar.c b/tests-clar/config/multivar.c deleted file mode 100644 index afdb1e5f4..000000000 --- a/tests-clar/config/multivar.c +++ /dev/null @@ -1,288 +0,0 @@ -#include "clar_libgit2.h" - -static const char *_name = "remote.ab.url"; - -void test_config_multivar__initialize(void) -{ - cl_fixture_sandbox("config"); -} - -void test_config_multivar__cleanup(void) -{ - cl_fixture_cleanup("config"); -} - -static int mv_read_cb(const git_config_entry *entry, void *data) -{ - int *n = (int *) data; - - if (!strcmp(entry->name, _name)) - (*n)++; - - return 0; -} - -void test_config_multivar__foreach(void) -{ - git_config *cfg; - int n = 0; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config11"))); - - cl_git_pass(git_config_foreach(cfg, mv_read_cb, &n)); - cl_assert(n == 2); - - git_config_free(cfg); -} - -static int cb(const git_config_entry *entry, void *data) -{ - int *n = (int *) data; - - GIT_UNUSED(entry); - - (*n)++; - - return 0; -} - -static void check_get_multivar_foreach( - git_config *cfg, int expected, int expected_patterned) -{ - int n = 0; - - if (expected > 0) { - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - cl_assert_equal_i(expected, n); - } else { - cl_assert_equal_i(GIT_ENOTFOUND, - git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - } - - n = 0; - - if (expected_patterned > 0) { - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "example", cb, &n)); - cl_assert_equal_i(expected_patterned, n); - } else { - cl_assert_equal_i(GIT_ENOTFOUND, - git_config_get_multivar_foreach(cfg, _name, "example", cb, &n)); - } -} - -static void check_get_multivar(git_config *cfg, int expected) -{ - git_config_iterator *iter; - git_config_entry *entry; - int n = 0; - - cl_git_pass(git_config_multivar_iterator_new(&iter, cfg, _name, NULL)); - - while (git_config_next(&entry, iter) == 0) - n++; - - cl_assert_equal_i(expected, n); - git_config_iterator_free(iter); - -} - -void test_config_multivar__get(void) -{ - git_config *cfg; - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - check_get_multivar_foreach(cfg, 2, 1); - - /* add another that has the _name entry */ - cl_git_pass(git_config_add_file_ondisk(cfg, "config/config9", GIT_CONFIG_LEVEL_SYSTEM, 1)); - check_get_multivar_foreach(cfg, 3, 2); - - /* add another that does not have the _name entry */ - cl_git_pass(git_config_add_file_ondisk(cfg, "config/config0", GIT_CONFIG_LEVEL_GLOBAL, 1)); - check_get_multivar_foreach(cfg, 3, 2); - - /* add another that does not have the _name entry at the end */ - cl_git_pass(git_config_add_file_ondisk(cfg, "config/config1", GIT_CONFIG_LEVEL_APP, 1)); - check_get_multivar_foreach(cfg, 3, 2); - - /* drop original file */ - cl_git_pass(git_config_add_file_ondisk(cfg, "config/config2", GIT_CONFIG_LEVEL_LOCAL, 1)); - check_get_multivar_foreach(cfg, 1, 1); - - /* drop other file with match */ - cl_git_pass(git_config_add_file_ondisk(cfg, "config/config3", GIT_CONFIG_LEVEL_SYSTEM, 1)); - check_get_multivar_foreach(cfg, 0, 0); - - /* reload original file (add different place in order) */ - cl_git_pass(git_config_add_file_ondisk(cfg, "config/config11", GIT_CONFIG_LEVEL_SYSTEM, 1)); - check_get_multivar_foreach(cfg, 2, 1); - - check_get_multivar(cfg, 2); - - git_config_free(cfg); -} - -void test_config_multivar__add(void) -{ - git_config *cfg; - int n; - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - cl_git_pass(git_config_set_multivar(cfg, _name, "nonexistant", "git://git.otherplace.org/libgit2")); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - cl_assert_equal_i(n, 3); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); - cl_assert_equal_i(n, 1); - - git_config_free(cfg); - - /* We know it works in memory, let's see if the file is written correctly */ - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - cl_assert_equal_i(n, 3); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); - cl_assert_equal_i(n, 1); - - git_config_free(cfg); -} - -void test_config_multivar__add_new(void) -{ - const char *var = "a.brand.new"; - git_config *cfg; - int n; - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - - cl_git_pass(git_config_set_multivar(cfg, var, "", "variable")); - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, var, NULL, cb, &n)); - cl_assert_equal_i(n, 1); - - git_config_free(cfg); -} - -void test_config_multivar__replace(void) -{ - git_config *cfg; - int n; - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - cl_assert(n == 2); - - cl_git_pass(git_config_set_multivar(cfg, _name, "github", "git://git.otherplace.org/libgit2")); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - cl_assert(n == 2); - - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - cl_assert(n == 2); - - git_config_free(cfg); -} - -void test_config_multivar__replace_multiple(void) -{ - git_config *cfg; - int n; - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - cl_git_pass(git_config_set_multivar(cfg, _name, "git://", "git://git.otherplace.org/libgit2")); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); - cl_assert_equal_i(n, 2); - - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); - cl_assert_equal_i(n, 2); - - git_config_free(cfg); -} - -void test_config_multivar__delete(void) -{ - git_config *cfg; - int n; - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - cl_assert(n == 2); - - cl_git_pass(git_config_delete_multivar(cfg, _name, "github")); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - cl_assert(n == 1); - - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - cl_assert(n == 1); - - git_config_free(cfg); -} - -void test_config_multivar__delete_multiple(void) -{ - git_config *cfg; - int n; - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - - n = 0; - cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); - cl_assert(n == 2); - - cl_git_pass(git_config_delete_multivar(cfg, _name, "git")); - - n = 0; - cl_git_fail_with(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n), GIT_ENOTFOUND); - - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - - n = 0; - cl_git_fail_with(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n), GIT_ENOTFOUND); - - git_config_free(cfg); -} - -void test_config_multivar__delete_notfound(void) -{ - git_config *cfg; - - cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); - - cl_git_fail_with(git_config_delete_multivar(cfg, "remote.ab.noturl", "git"), GIT_ENOTFOUND); - - git_config_free(cfg); -} diff --git a/tests-clar/config/new.c b/tests-clar/config/new.c deleted file mode 100644 index dd6dbca9e..000000000 --- a/tests-clar/config/new.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "clar_libgit2.h" - -#include "filebuf.h" -#include "fileops.h" -#include "posix.h" - -#define TEST_CONFIG "git-new-config" - -void test_config_new__write_new_config(void) -{ - const char *out; - git_config *config; - - cl_git_mkfile(TEST_CONFIG, ""); - cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); - - cl_git_pass(git_config_set_string(config, "color.ui", "auto")); - cl_git_pass(git_config_set_string(config, "core.editor", "ed")); - - git_config_free(config); - - cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); - - cl_git_pass(git_config_get_string(&out, config, "color.ui")); - cl_assert_equal_s(out, "auto"); - cl_git_pass(git_config_get_string(&out, config, "core.editor")); - cl_assert_equal_s(out, "ed"); - - git_config_free(config); - - p_unlink(TEST_CONFIG); -} diff --git a/tests-clar/config/read.c b/tests-clar/config/read.c deleted file mode 100644 index abc088d59..000000000 --- a/tests-clar/config/read.c +++ /dev/null @@ -1,569 +0,0 @@ -#include "clar_libgit2.h" - -void test_config_read__simple_read(void) -{ - git_config *cfg; - int32_t i; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config0"))); - - cl_git_pass(git_config_get_int32(&i, cfg, "core.repositoryformatversion")); - cl_assert(i == 0); - cl_git_pass(git_config_get_bool(&i, cfg, "core.filemode")); - cl_assert(i == 1); - cl_git_pass(git_config_get_bool(&i, cfg, "core.bare")); - cl_assert(i == 0); - cl_git_pass(git_config_get_bool(&i, cfg, "core.logallrefupdates")); - cl_assert(i == 1); - - git_config_free(cfg); -} - -void test_config_read__case_sensitive(void) -{ - git_config *cfg; - int i; - const char *str; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config1"))); - - cl_git_pass(git_config_get_string(&str, cfg, "this.that.other")); - cl_assert_equal_s(str, "true"); - cl_git_pass(git_config_get_string(&str, cfg, "this.That.other")); - cl_assert_equal_s(str, "yes"); - - cl_git_pass(git_config_get_bool(&i, cfg, "this.that.other")); - cl_assert(i == 1); - cl_git_pass(git_config_get_bool(&i, cfg, "this.That.other")); - cl_assert(i == 1); - - /* This one doesn't exist */ - cl_must_fail(git_config_get_bool(&i, cfg, "this.thaT.other")); - - git_config_free(cfg); -} - -/* - * If \ is the last non-space character on the line, we read the next - * one, separating each line with SP. - */ -void test_config_read__multiline_value(void) -{ - git_config *cfg; - const char *str; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config2"))); - - cl_git_pass(git_config_get_string(&str, cfg, "this.That.and")); - cl_assert_equal_s(str, "one one one two two three three"); - - git_config_free(cfg); -} - -/* - * This kind of subsection declaration is case-insensitive - */ -void test_config_read__subsection_header(void) -{ - git_config *cfg; - const char *str; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config3"))); - - cl_git_pass(git_config_get_string(&str, cfg, "section.subsection.var")); - cl_assert_equal_s(str, "hello"); - - /* The subsection is transformed to lower-case */ - cl_must_fail(git_config_get_string(&str, cfg, "section.subSectIon.var")); - - git_config_free(cfg); -} - -void test_config_read__lone_variable(void) -{ - git_config *cfg; - const char *str; - int i; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config4"))); - - cl_git_fail(git_config_get_int32(&i, cfg, "some.section.variable")); - - cl_git_pass(git_config_get_string(&str, cfg, "some.section.variable")); - cl_assert_equal_s(str, ""); - - cl_git_pass(git_config_get_bool(&i, cfg, "some.section.variable")); - cl_assert(i == 1); - - cl_git_pass(git_config_get_string(&str, cfg, "some.section.variableeq")); - cl_assert_equal_s(str, ""); - - cl_git_pass(git_config_get_bool(&i, cfg, "some.section.variableeq")); - cl_assert(i == 0); - - git_config_free(cfg); -} - -void test_config_read__number_suffixes(void) -{ - git_config *cfg; - int64_t i; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config5"))); - - cl_git_pass(git_config_get_int64(&i, cfg, "number.simple")); - cl_assert(i == 1); - - cl_git_pass(git_config_get_int64(&i, cfg, "number.k")); - cl_assert(i == 1 * 1024); - - cl_git_pass(git_config_get_int64(&i, cfg, "number.kk")); - cl_assert(i == 1 * 1024); - - cl_git_pass(git_config_get_int64(&i, cfg, "number.m")); - cl_assert(i == 1 * 1024 * 1024); - - cl_git_pass(git_config_get_int64(&i, cfg, "number.mm")); - cl_assert(i == 1 * 1024 * 1024); - - cl_git_pass(git_config_get_int64(&i, cfg, "number.g")); - cl_assert(i == 1 * 1024 * 1024 * 1024); - - cl_git_pass(git_config_get_int64(&i, cfg, "number.gg")); - cl_assert(i == 1 * 1024 * 1024 * 1024); - - git_config_free(cfg); -} - -void test_config_read__blank_lines(void) -{ - git_config *cfg; - int i; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config6"))); - - cl_git_pass(git_config_get_bool(&i, cfg, "valid.subsection.something")); - cl_assert(i == 1); - - cl_git_pass(git_config_get_bool(&i, cfg, "something.else.something")); - cl_assert(i == 0); - - git_config_free(cfg); -} - -void test_config_read__invalid_ext_headers(void) -{ - git_config *cfg; - cl_must_fail(git_config_open_ondisk(&cfg, cl_fixture("config/config7"))); -} - -void test_config_read__empty_files(void) -{ - git_config *cfg; - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config8"))); - git_config_free(cfg); -} - -void test_config_read__symbol_headers(void) -{ - git_config *cfg; - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config20"))); - git_config_free(cfg); -} - -void test_config_read__header_in_last_line(void) -{ - git_config *cfg; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config10"))); - git_config_free(cfg); -} - -void test_config_read__prefixes(void) -{ - git_config *cfg; - const char *str; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9"))); - cl_git_pass(git_config_get_string(&str, cfg, "remote.ab.url")); - cl_assert_equal_s(str, "http://example.com/git/ab"); - - cl_git_pass(git_config_get_string(&str, cfg, "remote.abba.url")); - cl_assert_equal_s(str, "http://example.com/git/abba"); - - git_config_free(cfg); -} - -void test_config_read__escaping_quotes(void) -{ - git_config *cfg; - const char *str; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config13"))); - cl_git_pass(git_config_get_string(&str, cfg, "core.editor")); - cl_assert_equal_s("\"C:/Program Files/Nonsense/bah.exe\" \"--some option\"", str); - - git_config_free(cfg); -} - -static int count_cfg_entries_and_compare_levels( - const git_config_entry *entry, void *payload) -{ - int *count = payload; - - if (!strcmp(entry->value, "7") || !strcmp(entry->value, "17")) - cl_assert(entry->level == GIT_CONFIG_LEVEL_GLOBAL); - else - cl_assert(entry->level == GIT_CONFIG_LEVEL_SYSTEM); - - (*count)++; - return 0; -} - -static int cfg_callback_countdown(const git_config_entry *entry, void *payload) -{ - int *count = payload; - GIT_UNUSED(entry); - (*count)--; - if (*count == 0) - return -100; - return 0; -} - -void test_config_read__foreach(void) -{ - git_config *cfg; - int count, ret; - - cl_git_pass(git_config_new(&cfg)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), - GIT_CONFIG_LEVEL_SYSTEM, 0)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), - GIT_CONFIG_LEVEL_GLOBAL, 0)); - - count = 0; - cl_git_pass(git_config_foreach(cfg, count_cfg_entries_and_compare_levels, &count)); - cl_assert_equal_i(7, count); - - count = 3; - cl_git_fail(ret = git_config_foreach(cfg, cfg_callback_countdown, &count)); - cl_assert_equal_i(GIT_EUSER, ret); - - git_config_free(cfg); -} - -void test_config_read__iterator(void) -{ - git_config *cfg; - git_config_iterator *iter; - git_config_entry *entry; - int count, ret; - - cl_git_pass(git_config_new(&cfg)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), - GIT_CONFIG_LEVEL_SYSTEM, 0)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), - GIT_CONFIG_LEVEL_GLOBAL, 0)); - - count = 0; - cl_git_pass(git_config_iterator_new(&iter, cfg)); - - while ((ret = git_config_next(&entry, iter)) == 0) { - count++; - } - - git_config_iterator_free(iter); - cl_assert_equal_i(GIT_ITEROVER, ret); - cl_assert_equal_i(7, count); - - count = 3; - cl_git_pass(git_config_iterator_new(&iter, cfg)); - - git_config_iterator_free(iter); - git_config_free(cfg); -} - -static int count_cfg_entries(const git_config_entry *entry, void *payload) -{ - int *count = payload; - GIT_UNUSED(entry); - (*count)++; - return 0; -} - -void test_config_read__foreach_match(void) -{ - git_config *cfg; - int count; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9"))); - - count = 0; - cl_git_pass( - git_config_foreach_match(cfg, "core.*", count_cfg_entries, &count)); - cl_assert_equal_i(3, count); - - count = 0; - cl_git_pass( - git_config_foreach_match(cfg, "remote\\.ab.*", count_cfg_entries, &count)); - cl_assert_equal_i(2, count); - - count = 0; - cl_git_pass( - git_config_foreach_match(cfg, ".*url$", count_cfg_entries, &count)); - cl_assert_equal_i(2, count); - - count = 0; - cl_git_pass( - git_config_foreach_match(cfg, ".*dummy.*", count_cfg_entries, &count)); - cl_assert_equal_i(2, count); - - count = 0; - cl_git_pass( - git_config_foreach_match(cfg, ".*nomatch.*", count_cfg_entries, &count)); - cl_assert_equal_i(0, count); - - git_config_free(cfg); -} - -static void check_glob_iter(git_config *cfg, const char *regexp, int expected) -{ - git_config_iterator *iter; - git_config_entry *entry; - int count, error; - - cl_git_pass(git_config_iterator_glob_new(&iter, cfg, regexp)); - - count = 0; - while ((error = git_config_next(&entry, iter)) == 0) - count++; - - cl_assert_equal_i(GIT_ITEROVER, error); - cl_assert_equal_i(expected, count); - git_config_iterator_free(iter); -} - -void test_config_read__iterator_glob(void) -{ - git_config *cfg; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9"))); - - check_glob_iter(cfg, "core.*", 3); - check_glob_iter(cfg, "remote\\.ab.*", 2); - check_glob_iter(cfg, ".*url$", 2); - check_glob_iter(cfg, ".*dummy.*", 2); - check_glob_iter(cfg, ".*nomatch.*", 0); - - git_config_free(cfg); -} - -void test_config_read__whitespace_not_required_around_assignment(void) -{ - git_config *cfg; - const char *str; - - cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config14"))); - - cl_git_pass(git_config_get_string(&str, cfg, "a.b")); - cl_assert_equal_s(str, "c"); - - cl_git_pass(git_config_get_string(&str, cfg, "d.e")); - cl_assert_equal_s(str, "f"); - - git_config_free(cfg); -} - -void test_config_read__read_git_config_entry(void) -{ - git_config *cfg; - const git_config_entry *entry; - - cl_git_pass(git_config_new(&cfg)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), - GIT_CONFIG_LEVEL_SYSTEM, 0)); - - cl_git_pass(git_config_get_entry(&entry, cfg, "core.dummy2")); - cl_assert_equal_s("core.dummy2", entry->name); - cl_assert_equal_s("42", entry->value); - cl_assert_equal_i(GIT_CONFIG_LEVEL_SYSTEM, entry->level); - - git_config_free(cfg); -} - -/* - * At the beginning of the test: - * - config9 has: core.dummy2=42 - * - config15 has: core.dummy2=7 - * - config16 has: core.dummy2=28 - */ -void test_config_read__local_config_overrides_global_config_overrides_system_config(void) -{ - git_config *cfg; - int32_t i; - - cl_git_pass(git_config_new(&cfg)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), - GIT_CONFIG_LEVEL_SYSTEM, 0)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), - GIT_CONFIG_LEVEL_GLOBAL, 0)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config16"), - GIT_CONFIG_LEVEL_LOCAL, 0)); - - cl_git_pass(git_config_get_int32(&i, cfg, "core.dummy2")); - cl_assert_equal_i(28, i); - - git_config_free(cfg); - - cl_git_pass(git_config_new(&cfg)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), - GIT_CONFIG_LEVEL_SYSTEM, 0)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), - GIT_CONFIG_LEVEL_GLOBAL, 0)); - - cl_git_pass(git_config_get_int32(&i, cfg, "core.dummy2")); - cl_assert_equal_i(7, i); - - git_config_free(cfg); -} - -/* - * At the beginning of the test: - * - config9 has: core.global does not exist - * - config15 has: core.global=17 - * - config16 has: core.global=29 - * - * And also: - * - config9 has: core.system does not exist - * - config15 has: core.system does not exist - * - config16 has: core.system=11 - */ -void test_config_read__fallback_from_local_to_global_and_from_global_to_system(void) -{ - git_config *cfg; - int32_t i; - - cl_git_pass(git_config_new(&cfg)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), - GIT_CONFIG_LEVEL_SYSTEM, 0)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), - GIT_CONFIG_LEVEL_GLOBAL, 0)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config16"), - GIT_CONFIG_LEVEL_LOCAL, 0)); - - cl_git_pass(git_config_get_int32(&i, cfg, "core.global")); - cl_assert_equal_i(17, i); - cl_git_pass(git_config_get_int32(&i, cfg, "core.system")); - cl_assert_equal_i(11, i); - - git_config_free(cfg); -} - -/* - * At the beginning of the test, config18 has: - * int32global = 28 - * int64global = 9223372036854775803 - * boolglobal = true - * stringglobal = I'm a global config value! - * - * And config19 has: - * int32global = -1 - * int64global = -2 - * boolglobal = false - * stringglobal = don't find me! - * - */ -void test_config_read__simple_read_from_specific_level(void) -{ - git_config *cfg, *cfg_specific; - int i; - int64_t l, expected = +9223372036854775803; - const char *s; - - cl_git_pass(git_config_new(&cfg)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"), - GIT_CONFIG_LEVEL_GLOBAL, 0)); - cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"), - GIT_CONFIG_LEVEL_SYSTEM, 0)); - - cl_git_pass(git_config_open_level(&cfg_specific, cfg, GIT_CONFIG_LEVEL_GLOBAL)); - - cl_git_pass(git_config_get_int32(&i, cfg_specific, "core.int32global")); - cl_assert_equal_i(28, i); - cl_git_pass(git_config_get_int64(&l, cfg_specific, "core.int64global")); - cl_assert(l == expected); - cl_git_pass(git_config_get_bool(&i, cfg_specific, "core.boolglobal")); - cl_assert_equal_b(true, i); - cl_git_pass(git_config_get_string(&s, cfg_specific, "core.stringglobal")); - cl_assert_equal_s("I'm a global config value!", s); - - git_config_free(cfg_specific); - git_config_free(cfg); -} - -static void clean_test_config(void *unused) -{ - GIT_UNUSED(unused); - cl_fixture_cleanup("./testconfig"); -} - -void test_config_read__can_load_and_parse_an_empty_config_file(void) -{ - git_config *cfg; - int i; - - cl_set_cleanup(&clean_test_config, NULL); - cl_git_mkfile("./testconfig", ""); - cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig")); - cl_assert_equal_i(GIT_ENOTFOUND, git_config_get_int32(&i, cfg, "nope.neither")); - - git_config_free(cfg); -} - -void test_config_read__corrupt_header(void) -{ - git_config *cfg; - - cl_set_cleanup(&clean_test_config, NULL); - cl_git_mkfile("./testconfig", "[sneaky ] \"quoted closing quote mark\\\""); - cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); - - git_config_free(cfg); -} - -void test_config_read__corrupt_header2(void) -{ - git_config *cfg; - - cl_set_cleanup(&clean_test_config, NULL); - cl_git_mkfile("./testconfig", "[unclosed \"bracket\"\n lib = git2\n"); - cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); - - git_config_free(cfg); -} - -void test_config_read__corrupt_header3(void) -{ - git_config *cfg; - - cl_set_cleanup(&clean_test_config, NULL); - cl_git_mkfile("./testconfig", "[unclosed \"slash\\\"]\n lib = git2\n"); - cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); - - git_config_free(cfg); -} - -void test_config_read__override_variable(void) -{ - git_config *cfg; - const char *str; - - cl_set_cleanup(&clean_test_config, NULL); - cl_git_mkfile("./testconfig", "[some] var = one\nvar = two"); - cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig")); - - cl_git_pass(git_config_get_string(&str, cfg, "some.var")); - cl_assert_equal_s(str, "two"); - - git_config_free(cfg); -} diff --git a/tests-clar/config/refresh.c b/tests-clar/config/refresh.c deleted file mode 100644 index 99d677f0e..000000000 --- a/tests-clar/config/refresh.c +++ /dev/null @@ -1,67 +0,0 @@ -#include "clar_libgit2.h" - -#define TEST_FILE "config.refresh" - -void test_config_refresh__initialize(void) -{ -} - -void test_config_refresh__cleanup(void) -{ - cl_fixture_cleanup(TEST_FILE); -} - -void test_config_refresh__update_value(void) -{ - git_config *cfg; - int32_t v; - - cl_git_mkfile(TEST_FILE, "[section]\n\tvalue = 1\n\n"); - - /* By freeing the config, we make sure we flush the values */ - cl_git_pass(git_config_open_ondisk(&cfg, TEST_FILE)); - - cl_git_pass(git_config_get_int32(&v, cfg, "section.value")); - cl_assert_equal_i(1, v); - - cl_git_rewritefile(TEST_FILE, "[section]\n\tvalue = 10\n\n"); - - cl_git_pass(git_config_get_int32(&v, cfg, "section.value")); - cl_assert_equal_i(1, v); - - cl_git_pass(git_config_refresh(cfg)); - - cl_git_pass(git_config_get_int32(&v, cfg, "section.value")); - cl_assert_equal_i(10, v); - - git_config_free(cfg); -} - -void test_config_refresh__delete_value(void) -{ - git_config *cfg; - int32_t v; - - cl_git_mkfile(TEST_FILE, "[section]\n\tvalue = 1\n\n"); - - /* By freeing the config, we make sure we flush the values */ - cl_git_pass(git_config_open_ondisk(&cfg, TEST_FILE)); - - cl_git_pass(git_config_get_int32(&v, cfg, "section.value")); - cl_assert_equal_i(1, v); - cl_git_fail(git_config_get_int32(&v, cfg, "section.newval")); - - cl_git_rewritefile(TEST_FILE, "[section]\n\tnewval = 10\n\n"); - - cl_git_pass(git_config_get_int32(&v, cfg, "section.value")); - cl_assert_equal_i(1, v); - cl_git_fail(git_config_get_int32(&v, cfg, "section.newval")); - - cl_git_pass(git_config_refresh(cfg)); - - cl_git_fail(git_config_get_int32(&v, cfg, "section.value")); - cl_git_pass(git_config_get_int32(&v, cfg, "section.newval")); - cl_assert_equal_i(10, v); - - git_config_free(cfg); -} diff --git a/tests-clar/config/stress.c b/tests-clar/config/stress.c deleted file mode 100644 index eeca54ff4..000000000 --- a/tests-clar/config/stress.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "clar_libgit2.h" - -#include "filebuf.h" -#include "fileops.h" -#include "posix.h" - -#define TEST_CONFIG "git-test-config" - -void test_config_stress__initialize(void) -{ - git_filebuf file = GIT_FILEBUF_INIT; - - cl_git_pass(git_filebuf_open(&file, TEST_CONFIG, 0, 0666)); - - git_filebuf_printf(&file, "[color]\n\tui = auto\n"); - git_filebuf_printf(&file, "[core]\n\teditor = \n"); - - cl_git_pass(git_filebuf_commit(&file)); -} - -void test_config_stress__cleanup(void) -{ - p_unlink(TEST_CONFIG); -} - -void test_config_stress__dont_break_on_invalid_input(void) -{ - const char *editor, *color; - git_config *config; - - cl_assert(git_path_exists(TEST_CONFIG)); - cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); - - cl_git_pass(git_config_get_string(&color, config, "color.ui")); - cl_git_pass(git_config_get_string(&editor, config, "core.editor")); - - git_config_free(config); -} - -void test_config_stress__comments(void) -{ - git_config *config; - const char *str; - - cl_git_pass(git_config_open_ondisk(&config, cl_fixture("config/config12"))); - - cl_git_pass(git_config_get_string(&str, config, "some.section.other")); - cl_assert_equal_s("hello! \" ; ; ; ", str); - - cl_git_pass(git_config_get_string(&str, config, "some.section.multi")); - cl_assert_equal_s("hi, this is a ; multiline comment # with ;\n special chars and other stuff !@#", str); - - cl_git_pass(git_config_get_string(&str, config, "some.section.back")); - cl_assert_equal_s("this is \ba phrase", str); - - git_config_free(config); -} - -void test_config_stress__escape_subsection_names(void) -{ - git_config *config; - const char *str; - - cl_assert(git_path_exists("git-test-config")); - cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); - - cl_git_pass(git_config_set_string(config, "some.sec\\tion.other", "foo")); - git_config_free(config); - - cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); - - cl_git_pass(git_config_get_string(&str, config, "some.sec\\tion.other")); - cl_assert_equal_s("foo", str); - git_config_free(config); -} - -void test_config_stress__trailing_backslash(void) -{ - git_config *config; - const char *str; - const char *path = "C:\\iam\\some\\windows\\path\\"; - - cl_assert(git_path_exists("git-test-config")); - cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); - cl_git_pass(git_config_set_string(config, "windows.path", path)); - git_config_free(config); - - cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); - cl_git_pass(git_config_get_string(&str, config, "windows.path")); - cl_assert_equal_s(path, str); - git_config_free(config); -} diff --git a/tests-clar/config/validkeyname.c b/tests-clar/config/validkeyname.c deleted file mode 100644 index 33699737b..000000000 --- a/tests-clar/config/validkeyname.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "clar_libgit2.h" - -#include "config.h" - -static git_config *cfg; -static const char *value; - -void test_config_validkeyname__initialize(void) -{ - cl_fixture_sandbox("config/config10"); - - cl_git_pass(git_config_open_ondisk(&cfg, "config10")); -} - -void test_config_validkeyname__cleanup(void) -{ - git_config_free(cfg); - cfg = NULL; - - cl_fixture_cleanup("config10"); -} - -static void assert_invalid_config_key_name(const char *name) -{ - cl_git_fail_with(git_config_get_string(&value, cfg, name), - GIT_EINVALIDSPEC); - cl_git_fail_with(git_config_set_string(cfg, name, "42"), - GIT_EINVALIDSPEC); - cl_git_fail_with(git_config_delete_entry(cfg, name), - GIT_EINVALIDSPEC); - cl_git_fail_with(git_config_get_multivar_foreach(cfg, name, "*", NULL, NULL), - GIT_EINVALIDSPEC); - cl_git_fail_with(git_config_set_multivar(cfg, name, "*", "42"), - GIT_EINVALIDSPEC); -} - -void test_config_validkeyname__accessing_requires_a_valid_name(void) -{ - assert_invalid_config_key_name(""); - assert_invalid_config_key_name("."); - assert_invalid_config_key_name(".."); - assert_invalid_config_key_name("core."); - assert_invalid_config_key_name("d#ff.dirstat.lines"); - assert_invalid_config_key_name("diff.dirstat.lines#"); - assert_invalid_config_key_name("dif\nf.dirstat.lines"); - assert_invalid_config_key_name("dif.dir\nstat.lines"); - assert_invalid_config_key_name("dif.dirstat.li\nes"); -} - -static void assert_invalid_config_section_name(git_repository *repo, const char *name) -{ - cl_git_fail_with(git_config_rename_section(repo, "branch.remoteless", name), GIT_EINVALIDSPEC); -} - -void test_config_validkeyname__renaming_a_section_requires_a_valid_name(void) -{ - git_repository *repo; - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - - assert_invalid_config_section_name(repo, ""); - assert_invalid_config_section_name(repo, "bra\nch"); - assert_invalid_config_section_name(repo, "branc#"); - assert_invalid_config_section_name(repo, "bra\nch.duh"); - assert_invalid_config_section_name(repo, "branc#.duh"); - - git_repository_free(repo); -} diff --git a/tests-clar/config/write.c b/tests-clar/config/write.c deleted file mode 100644 index 15f750dc0..000000000 --- a/tests-clar/config/write.c +++ /dev/null @@ -1,305 +0,0 @@ -#include "clar_libgit2.h" - -void test_config_write__initialize(void) -{ - cl_fixture_sandbox("config/config9"); - cl_fixture_sandbox("config/config15"); - cl_fixture_sandbox("config/config17"); -} - -void test_config_write__cleanup(void) -{ - cl_fixture_cleanup("config9"); - cl_fixture_cleanup("config15"); - cl_fixture_cleanup("config17"); -} - -void test_config_write__replace_value(void) -{ - git_config *cfg; - int i; - int64_t l, expected = +9223372036854775803; - - /* By freeing the config, we make sure we flush the values */ - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_set_int32(cfg, "core.dummy", 5)); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_get_int32(&i, cfg, "core.dummy")); - cl_assert(i == 5); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_set_int32(cfg, "core.dummy", 1)); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_set_int64(cfg, "core.verylong", expected)); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_get_int64(&l, cfg, "core.verylong")); - cl_assert(l == expected); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_must_fail(git_config_get_int32(&i, cfg, "core.verylong")); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_set_int64(cfg, "core.verylong", 1)); - git_config_free(cfg); -} - -void test_config_write__delete_value(void) -{ - git_config *cfg; - int32_t i; - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_set_int32(cfg, "core.dummy", 5)); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_delete_entry(cfg, "core.dummy")); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_assert(git_config_get_int32(&i, cfg, "core.dummy") == GIT_ENOTFOUND); - cl_git_pass(git_config_set_int32(cfg, "core.dummy", 1)); - git_config_free(cfg); -} - -/* - * At the beginning of the test: - * - config9 has: core.dummy2=42 - * - config15 has: core.dummy2=7 - */ -void test_config_write__delete_value_at_specific_level(void) -{ - git_config *cfg, *cfg_specific; - int32_t i; - - cl_git_pass(git_config_open_ondisk(&cfg, "config15")); - cl_git_pass(git_config_get_int32(&i, cfg, "core.dummy2")); - cl_assert(i == 7); - git_config_free(cfg); - - cl_git_pass(git_config_new(&cfg)); - cl_git_pass(git_config_add_file_ondisk(cfg, "config9", - GIT_CONFIG_LEVEL_LOCAL, 0)); - cl_git_pass(git_config_add_file_ondisk(cfg, "config15", - GIT_CONFIG_LEVEL_GLOBAL, 0)); - - cl_git_pass(git_config_open_level(&cfg_specific, cfg, GIT_CONFIG_LEVEL_GLOBAL)); - - cl_git_pass(git_config_delete_entry(cfg_specific, "core.dummy2")); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config15")); - cl_assert(git_config_get_int32(&i, cfg, "core.dummy2") == GIT_ENOTFOUND); - cl_git_pass(git_config_set_int32(cfg, "core.dummy2", 7)); - - git_config_free(cfg_specific); - git_config_free(cfg); -} - -void test_config_write__write_subsection(void) -{ - git_config *cfg; - const char *str; - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_set_string(cfg, "my.own.var", "works")); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_get_string(&str, cfg, "my.own.var")); - cl_assert_equal_s("works", str); - git_config_free(cfg); -} - -void test_config_write__delete_inexistent(void) -{ - git_config *cfg; - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_assert(git_config_delete_entry(cfg, "core.imaginary") == GIT_ENOTFOUND); - git_config_free(cfg); -} - -void test_config_write__value_containing_quotes(void) -{ - git_config *cfg; - const char* str; - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_set_string(cfg, "core.somevar", "this \"has\" quotes")); - cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); - cl_assert_equal_s(str, "this \"has\" quotes"); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); - cl_assert_equal_s(str, "this \"has\" quotes"); - git_config_free(cfg); - - /* The code path for values that already exist is different, check that one as well */ - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_set_string(cfg, "core.somevar", "this also \"has\" quotes")); - cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); - cl_assert_equal_s(str, "this also \"has\" quotes"); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); - cl_assert_equal_s(str, "this also \"has\" quotes"); - git_config_free(cfg); -} - -void test_config_write__escape_value(void) -{ - git_config *cfg; - const char* str; - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_set_string(cfg, "core.somevar", "this \"has\" quotes and \t")); - cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); - cl_assert_equal_s(str, "this \"has\" quotes and \t"); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); - cl_assert_equal_s(str, "this \"has\" quotes and \t"); - git_config_free(cfg); -} - -void test_config_write__add_value_at_specific_level(void) -{ - git_config *cfg, *cfg_specific; - int i; - int64_t l, expected = +9223372036854775803; - const char *s; - - // open config15 as global level config file - cl_git_pass(git_config_new(&cfg)); - cl_git_pass(git_config_add_file_ondisk(cfg, "config9", - GIT_CONFIG_LEVEL_LOCAL, 0)); - cl_git_pass(git_config_add_file_ondisk(cfg, "config15", - GIT_CONFIG_LEVEL_GLOBAL, 0)); - - cl_git_pass(git_config_open_level(&cfg_specific, cfg, GIT_CONFIG_LEVEL_GLOBAL)); - - cl_git_pass(git_config_set_int32(cfg_specific, "core.int32global", 28)); - cl_git_pass(git_config_set_int64(cfg_specific, "core.int64global", expected)); - cl_git_pass(git_config_set_bool(cfg_specific, "core.boolglobal", true)); - cl_git_pass(git_config_set_string(cfg_specific, "core.stringglobal", "I'm a global config value!")); - git_config_free(cfg_specific); - git_config_free(cfg); - - // open config15 as local level config file - cl_git_pass(git_config_open_ondisk(&cfg, "config15")); - - cl_git_pass(git_config_get_int32(&i, cfg, "core.int32global")); - cl_assert_equal_i(28, i); - cl_git_pass(git_config_get_int64(&l, cfg, "core.int64global")); - cl_assert(l == expected); - cl_git_pass(git_config_get_bool(&i, cfg, "core.boolglobal")); - cl_assert_equal_b(true, i); - cl_git_pass(git_config_get_string(&s, cfg, "core.stringglobal")); - cl_assert_equal_s("I'm a global config value!", s); - - git_config_free(cfg); -} - -void test_config_write__add_value_at_file_with_no_clrf_at_the_end(void) -{ - git_config *cfg; - int i; - - cl_git_pass(git_config_open_ondisk(&cfg, "config17")); - cl_git_pass(git_config_set_int32(cfg, "core.newline", 7)); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config17")); - cl_git_pass(git_config_get_int32(&i, cfg, "core.newline")); - cl_assert_equal_i(7, i); - - git_config_free(cfg); -} - -void test_config_write__add_value_which_needs_quotes(void) -{ - git_config *cfg; - const char* str1; - const char* str2; - const char* str3; - const char* str4; - const char* str5; - - cl_git_pass(git_config_open_ondisk(&cfg, "config17")); - cl_git_pass(git_config_set_string(cfg, "core.startwithspace", " Something")); - cl_git_pass(git_config_set_string(cfg, "core.endwithspace", "Something ")); - cl_git_pass(git_config_set_string(cfg, "core.containscommentchar1", "some#thing")); - cl_git_pass(git_config_set_string(cfg, "core.containscommentchar2", "some;thing")); - cl_git_pass(git_config_set_string(cfg, "core.startwhithsapceandcontainsdoublequote", " some\"thing")); - git_config_free(cfg); - - cl_git_pass(git_config_open_ondisk(&cfg, "config17")); - cl_git_pass(git_config_get_string(&str1, cfg, "core.startwithspace")); - cl_assert_equal_s(" Something", str1); - cl_git_pass(git_config_get_string(&str2, cfg, "core.endwithspace")); - cl_assert_equal_s("Something ", str2); - cl_git_pass(git_config_get_string(&str3, cfg, "core.containscommentchar1")); - cl_assert_equal_s("some#thing", str3); - cl_git_pass(git_config_get_string(&str4, cfg, "core.containscommentchar2")); - cl_assert_equal_s("some;thing", str4); - cl_git_pass(git_config_get_string(&str5, cfg, "core.startwhithsapceandcontainsdoublequote")); - cl_assert_equal_s(" some\"thing", str5); - git_config_free(cfg); -} - -void test_config_write__can_set_a_value_to_NULL(void) -{ - git_repository *repository; - git_config *config; - - repository = cl_git_sandbox_init("testrepo.git"); - - cl_git_pass(git_repository_config(&config, repository)); - cl_git_fail(git_config_set_string(config, "a.b.c", NULL)); - git_config_free(config); - - cl_git_sandbox_cleanup(); -} - -void test_config_write__can_set_an_empty_value(void) -{ - git_repository *repository; - git_config *config; - const char * str; - - repository = cl_git_sandbox_init("testrepo.git"); - cl_git_pass(git_repository_config(&config, repository)); - - cl_git_pass(git_config_set_string(config, "core.somevar", "")); - cl_git_pass(git_config_get_string(&str, config, "core.somevar")); - cl_assert_equal_s(str, ""); - - git_config_free(config); - cl_git_sandbox_cleanup(); -} - -void test_config_write__updating_a_locked_config_file_returns_ELOCKED(void) -{ - git_config *cfg; - - cl_git_pass(git_config_open_ondisk(&cfg, "config9")); - - cl_git_mkfile("config9.lock", "[core]\n"); - - cl_git_fail_with(git_config_set_string(cfg, "core.dump", "boom"), GIT_ELOCKED); - - git_config_free(cfg); -} diff --git a/tests-clar/core/bitvec.c b/tests-clar/core/bitvec.c deleted file mode 100644 index 48d7b99f0..000000000 --- a/tests-clar/core/bitvec.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "clar_libgit2.h" -#include "bitvec.h" - -#if 0 -static void print_bitvec(git_bitvec *bv) -{ - int b; - - if (!bv->length) { - for (b = 63; b >= 0; --b) - fprintf(stderr, "%d", (bv->u.bits & (1ul << b)) ? 1 : 0); - } else { - for (b = bv->length * 8; b >= 0; --b) - fprintf(stderr, "%d", (bv->u.ptr[b >> 3] & (b & 0x0ff)) ? 1 : 0); - } - fprintf(stderr, "\n"); -} -#endif - -static void set_some_bits(git_bitvec *bv, size_t length) -{ - size_t i; - - for (i = 0; i < length; ++i) { - if (i % 3 == 0 || i % 7 == 0) - git_bitvec_set(bv, i, true); - } -} - -static void check_some_bits(git_bitvec *bv, size_t length) -{ - size_t i; - - for (i = 0; i < length; ++i) - cl_assert_equal_b(i % 3 == 0 || i % 7 == 0, git_bitvec_get(bv, i)); -} - -void test_core_bitvec__0(void) -{ - git_bitvec bv; - - cl_git_pass(git_bitvec_init(&bv, 32)); - set_some_bits(&bv, 16); - check_some_bits(&bv, 16); - git_bitvec_clear(&bv); - set_some_bits(&bv, 32); - check_some_bits(&bv, 32); - git_bitvec_clear(&bv); - set_some_bits(&bv, 64); - check_some_bits(&bv, 64); - git_bitvec_free(&bv); - - cl_git_pass(git_bitvec_init(&bv, 128)); - set_some_bits(&bv, 32); - check_some_bits(&bv, 32); - set_some_bits(&bv, 128); - check_some_bits(&bv, 128); - git_bitvec_free(&bv); - - cl_git_pass(git_bitvec_init(&bv, 4000)); - set_some_bits(&bv, 4000); - check_some_bits(&bv, 4000); - git_bitvec_free(&bv); -} diff --git a/tests-clar/core/buffer.c b/tests-clar/core/buffer.c deleted file mode 100644 index 11d173d49..000000000 --- a/tests-clar/core/buffer.c +++ /dev/null @@ -1,1039 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "buf_text.h" -#include "hashsig.h" -#include "fileops.h" - -#define TESTSTR "Have you seen that? Have you seeeen that??" -const char *test_string = TESTSTR; -const char *test_string_x2 = TESTSTR TESTSTR; - -#define TESTSTR_4096 REP1024("1234") -#define TESTSTR_8192 REP1024("12341234") -const char *test_4096 = TESTSTR_4096; -const char *test_8192 = TESTSTR_8192; - -/* test basic data concatenation */ -void test_core_buffer__0(void) -{ - git_buf buf = GIT_BUF_INIT; - - cl_assert(buf.size == 0); - - git_buf_puts(&buf, test_string); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(test_string, git_buf_cstr(&buf)); - - git_buf_puts(&buf, test_string); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(test_string_x2, git_buf_cstr(&buf)); - - git_buf_free(&buf); -} - -/* test git_buf_printf */ -void test_core_buffer__1(void) -{ - git_buf buf = GIT_BUF_INIT; - - git_buf_printf(&buf, "%s %s %d ", "shoop", "da", 23); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s("shoop da 23 ", git_buf_cstr(&buf)); - - git_buf_printf(&buf, "%s %d", "woop", 42); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s("shoop da 23 woop 42", git_buf_cstr(&buf)); - - git_buf_free(&buf); -} - -/* more thorough test of concatenation options */ -void test_core_buffer__2(void) -{ - git_buf buf = GIT_BUF_INIT; - int i; - char data[128]; - - cl_assert(buf.size == 0); - - /* this must be safe to do */ - git_buf_free(&buf); - cl_assert(buf.size == 0); - cl_assert(buf.asize == 0); - - /* empty buffer should be empty string */ - cl_assert_equal_s("", git_buf_cstr(&buf)); - cl_assert(buf.size == 0); - /* cl_assert(buf.asize == 0); -- should not assume what git_buf does */ - - /* free should set us back to the beginning */ - git_buf_free(&buf); - cl_assert(buf.size == 0); - cl_assert(buf.asize == 0); - - /* add letter */ - git_buf_putc(&buf, '+'); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s("+", git_buf_cstr(&buf)); - - /* add letter again */ - git_buf_putc(&buf, '+'); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s("++", git_buf_cstr(&buf)); - - /* let's try that a few times */ - for (i = 0; i < 16; ++i) { - git_buf_putc(&buf, '+'); - cl_assert(git_buf_oom(&buf) == 0); - } - cl_assert_equal_s("++++++++++++++++++", git_buf_cstr(&buf)); - - git_buf_free(&buf); - - /* add data */ - git_buf_put(&buf, "xo", 2); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s("xo", git_buf_cstr(&buf)); - - /* add letter again */ - git_buf_put(&buf, "xo", 2); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s("xoxo", git_buf_cstr(&buf)); - - /* let's try that a few times */ - for (i = 0; i < 16; ++i) { - git_buf_put(&buf, "xo", 2); - cl_assert(git_buf_oom(&buf) == 0); - } - cl_assert_equal_s("xoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxo", - git_buf_cstr(&buf)); - - git_buf_free(&buf); - - /* set to string */ - git_buf_sets(&buf, test_string); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(test_string, git_buf_cstr(&buf)); - - /* append string */ - git_buf_puts(&buf, test_string); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(test_string_x2, git_buf_cstr(&buf)); - - /* set to string again (should overwrite - not append) */ - git_buf_sets(&buf, test_string); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(test_string, git_buf_cstr(&buf)); - - /* test clear */ - git_buf_clear(&buf); - cl_assert_equal_s("", git_buf_cstr(&buf)); - - git_buf_free(&buf); - - /* test extracting data into buffer */ - git_buf_puts(&buf, REP4("0123456789")); - cl_assert(git_buf_oom(&buf) == 0); - - git_buf_copy_cstr(data, sizeof(data), &buf); - cl_assert_equal_s(REP4("0123456789"), data); - git_buf_copy_cstr(data, 11, &buf); - cl_assert_equal_s("0123456789", data); - git_buf_copy_cstr(data, 3, &buf); - cl_assert_equal_s("01", data); - git_buf_copy_cstr(data, 1, &buf); - cl_assert_equal_s("", data); - - git_buf_copy_cstr(data, sizeof(data), &buf); - cl_assert_equal_s(REP4("0123456789"), data); - - git_buf_sets(&buf, REP256("x")); - git_buf_copy_cstr(data, sizeof(data), &buf); - /* since sizeof(data) == 128, only 127 bytes should be copied */ - cl_assert_equal_s(REP4(REP16("x")) REP16("x") REP16("x") - REP16("x") "xxxxxxxxxxxxxxx", data); - - git_buf_free(&buf); - - git_buf_copy_cstr(data, sizeof(data), &buf); - cl_assert_equal_s("", data); -} - -/* let's do some tests with larger buffers to push our limits */ -void test_core_buffer__3(void) -{ - git_buf buf = GIT_BUF_INIT; - - /* set to string */ - git_buf_set(&buf, test_4096, 4096); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(test_4096, git_buf_cstr(&buf)); - - /* append string */ - git_buf_puts(&buf, test_4096); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(test_8192, git_buf_cstr(&buf)); - - /* set to string again (should overwrite - not append) */ - git_buf_set(&buf, test_4096, 4096); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(test_4096, git_buf_cstr(&buf)); - - git_buf_free(&buf); -} - -/* let's try some producer/consumer tests */ -void test_core_buffer__4(void) -{ - git_buf buf = GIT_BUF_INIT; - int i; - - for (i = 0; i < 10; ++i) { - git_buf_puts(&buf, "1234"); /* add 4 */ - cl_assert(git_buf_oom(&buf) == 0); - git_buf_consume(&buf, buf.ptr + 2); /* eat the first two */ - cl_assert(strlen(git_buf_cstr(&buf)) == (size_t)((i + 1) * 2)); - } - /* we have appended 1234 10x and removed the first 20 letters */ - cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf)); - - git_buf_consume(&buf, NULL); - cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf)); - - git_buf_consume(&buf, "invalid pointer"); - cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf)); - - git_buf_consume(&buf, buf.ptr); - cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf)); - - git_buf_consume(&buf, buf.ptr + 1); - cl_assert_equal_s("2341234123412341234", git_buf_cstr(&buf)); - - git_buf_consume(&buf, buf.ptr + buf.size); - cl_assert_equal_s("", git_buf_cstr(&buf)); - - git_buf_free(&buf); -} - - -static void -check_buf_append( - const char* data_a, - const char* data_b, - const char* expected_data, - size_t expected_size, - size_t expected_asize) -{ - git_buf tgt = GIT_BUF_INIT; - - git_buf_sets(&tgt, data_a); - cl_assert(git_buf_oom(&tgt) == 0); - git_buf_puts(&tgt, data_b); - cl_assert(git_buf_oom(&tgt) == 0); - cl_assert_equal_s(expected_data, git_buf_cstr(&tgt)); - cl_assert(tgt.size == expected_size); - if (expected_asize > 0) - cl_assert(tgt.asize == expected_asize); - - git_buf_free(&tgt); -} - -static void -check_buf_append_abc( - const char* buf_a, - const char* buf_b, - const char* buf_c, - const char* expected_ab, - const char* expected_abc, - const char* expected_abca, - const char* expected_abcab, - const char* expected_abcabc) -{ - git_buf buf = GIT_BUF_INIT; - - git_buf_sets(&buf, buf_a); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(buf_a, git_buf_cstr(&buf)); - - git_buf_puts(&buf, buf_b); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(expected_ab, git_buf_cstr(&buf)); - - git_buf_puts(&buf, buf_c); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(expected_abc, git_buf_cstr(&buf)); - - git_buf_puts(&buf, buf_a); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(expected_abca, git_buf_cstr(&buf)); - - git_buf_puts(&buf, buf_b); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(expected_abcab, git_buf_cstr(&buf)); - - git_buf_puts(&buf, buf_c); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(expected_abcabc, git_buf_cstr(&buf)); - - git_buf_free(&buf); -} - -/* more variations on append tests */ -void test_core_buffer__5(void) -{ - check_buf_append("", "", "", 0, 8); - check_buf_append("a", "", "a", 1, 8); - check_buf_append("", "a", "a", 1, 8); - check_buf_append("", "a", "a", 1, 8); - check_buf_append("a", "", "a", 1, 8); - check_buf_append("a", "b", "ab", 2, 8); - check_buf_append("", "abcdefgh", "abcdefgh", 8, 16); - check_buf_append("abcdefgh", "", "abcdefgh", 8, 16); - - /* buffer with starting asize will grow to: - * 1 -> 2, 2 -> 3, 3 -> 5, 4 -> 6, 5 -> 8, 6 -> 9, - * 7 -> 11, 8 -> 12, 9 -> 14, 10 -> 15, 11 -> 17, 12 -> 18, - * 13 -> 20, 14 -> 21, 15 -> 23, 16 -> 24, 17 -> 26, 18 -> 27, - * 19 -> 29, 20 -> 30, 21 -> 32, 22 -> 33, 23 -> 35, 24 -> 36, - * ... - * follow sequence until value > target size, - * then round up to nearest multiple of 8. - */ - - check_buf_append("abcdefgh", "/", "abcdefgh/", 9, 16); - check_buf_append("abcdefgh", "ijklmno", "abcdefghijklmno", 15, 16); - check_buf_append("abcdefgh", "ijklmnop", "abcdefghijklmnop", 16, 24); - check_buf_append("0123456789", "0123456789", - "01234567890123456789", 20, 24); - check_buf_append(REP16("x"), REP16("o"), - REP16("x") REP16("o"), 32, 40); - - check_buf_append(test_4096, "", test_4096, 4096, 4104); - check_buf_append(test_4096, test_4096, test_8192, 8192, 9240); - - /* check sequences of appends */ - check_buf_append_abc("a", "b", "c", - "ab", "abc", "abca", "abcab", "abcabc"); - check_buf_append_abc("a1", "b2", "c3", - "a1b2", "a1b2c3", "a1b2c3a1", - "a1b2c3a1b2", "a1b2c3a1b2c3"); - check_buf_append_abc("a1/", "b2/", "c3/", - "a1/b2/", "a1/b2/c3/", "a1/b2/c3/a1/", - "a1/b2/c3/a1/b2/", "a1/b2/c3/a1/b2/c3/"); -} - -/* test swap */ -void test_core_buffer__6(void) -{ - git_buf a = GIT_BUF_INIT; - git_buf b = GIT_BUF_INIT; - - git_buf_sets(&a, "foo"); - cl_assert(git_buf_oom(&a) == 0); - git_buf_sets(&b, "bar"); - cl_assert(git_buf_oom(&b) == 0); - - cl_assert_equal_s("foo", git_buf_cstr(&a)); - cl_assert_equal_s("bar", git_buf_cstr(&b)); - - git_buf_swap(&a, &b); - - cl_assert_equal_s("bar", git_buf_cstr(&a)); - cl_assert_equal_s("foo", git_buf_cstr(&b)); - - git_buf_free(&a); - git_buf_free(&b); -} - - -/* test detach/attach data */ -void test_core_buffer__7(void) -{ - const char *fun = "This is fun"; - git_buf a = GIT_BUF_INIT; - char *b = NULL; - - git_buf_sets(&a, "foo"); - cl_assert(git_buf_oom(&a) == 0); - cl_assert_equal_s("foo", git_buf_cstr(&a)); - - b = git_buf_detach(&a); - - cl_assert_equal_s("foo", b); - cl_assert_equal_s("", a.ptr); - git__free(b); - - b = git_buf_detach(&a); - - cl_assert_equal_s(NULL, b); - cl_assert_equal_s("", a.ptr); - - git_buf_free(&a); - - b = git__strdup(fun); - git_buf_attach(&a, b, 0); - - cl_assert_equal_s(fun, a.ptr); - cl_assert(a.size == strlen(fun)); - cl_assert(a.asize == strlen(fun) + 1); - - git_buf_free(&a); - - b = git__strdup(fun); - git_buf_attach(&a, b, strlen(fun) + 1); - - cl_assert_equal_s(fun, a.ptr); - cl_assert(a.size == strlen(fun)); - cl_assert(a.asize == strlen(fun) + 1); - - git_buf_free(&a); -} - - -static void -check_joinbuf_2( - const char *a, - const char *b, - const char *expected) -{ - char sep = '/'; - git_buf buf = GIT_BUF_INIT; - - git_buf_join(&buf, sep, a, b); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(expected, git_buf_cstr(&buf)); - git_buf_free(&buf); -} - -static void -check_joinbuf_n_2( - const char *a, - const char *b, - const char *expected) -{ - char sep = '/'; - git_buf buf = GIT_BUF_INIT; - - git_buf_sets(&buf, a); - cl_assert(git_buf_oom(&buf) == 0); - - git_buf_join_n(&buf, sep, 1, b); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(expected, git_buf_cstr(&buf)); - - git_buf_free(&buf); -} - -static void -check_joinbuf_n_4( - const char *a, - const char *b, - const char *c, - const char *d, - const char *expected) -{ - char sep = ';'; - git_buf buf = GIT_BUF_INIT; - git_buf_join_n(&buf, sep, 4, a, b, c, d); - cl_assert(git_buf_oom(&buf) == 0); - cl_assert_equal_s(expected, git_buf_cstr(&buf)); - git_buf_free(&buf); -} - -/* test join */ -void test_core_buffer__8(void) -{ - git_buf a = GIT_BUF_INIT; - - git_buf_join_n(&a, '/', 1, "foo"); - cl_assert(git_buf_oom(&a) == 0); - cl_assert_equal_s("foo", git_buf_cstr(&a)); - - git_buf_join_n(&a, '/', 1, "bar"); - cl_assert(git_buf_oom(&a) == 0); - cl_assert_equal_s("foo/bar", git_buf_cstr(&a)); - - git_buf_join_n(&a, '/', 1, "baz"); - cl_assert(git_buf_oom(&a) == 0); - cl_assert_equal_s("foo/bar/baz", git_buf_cstr(&a)); - - git_buf_free(&a); - - check_joinbuf_2(NULL, "", ""); - check_joinbuf_2(NULL, "a", "a"); - check_joinbuf_2(NULL, "/a", "/a"); - check_joinbuf_2("", "", ""); - check_joinbuf_2("", "a", "a"); - check_joinbuf_2("", "/a", "/a"); - check_joinbuf_2("a", "", "a/"); - check_joinbuf_2("a", "/", "a/"); - check_joinbuf_2("a", "b", "a/b"); - check_joinbuf_2("/", "a", "/a"); - check_joinbuf_2("/", "", "/"); - check_joinbuf_2("/a", "/b", "/a/b"); - check_joinbuf_2("/a", "/b/", "/a/b/"); - check_joinbuf_2("/a/", "b/", "/a/b/"); - check_joinbuf_2("/a/", "/b/", "/a/b/"); - check_joinbuf_2("/a/", "//b/", "/a/b/"); - check_joinbuf_2("/abcd", "/defg", "/abcd/defg"); - check_joinbuf_2("/abcd", "/defg/", "/abcd/defg/"); - check_joinbuf_2("/abcd/", "defg/", "/abcd/defg/"); - check_joinbuf_2("/abcd/", "/defg/", "/abcd/defg/"); - - check_joinbuf_n_2("", "", ""); - check_joinbuf_n_2("", "a", "a"); - check_joinbuf_n_2("", "/a", "/a"); - check_joinbuf_n_2("a", "", "a/"); - check_joinbuf_n_2("a", "/", "a/"); - check_joinbuf_n_2("a", "b", "a/b"); - check_joinbuf_n_2("/", "a", "/a"); - check_joinbuf_n_2("/", "", "/"); - check_joinbuf_n_2("/a", "/b", "/a/b"); - check_joinbuf_n_2("/a", "/b/", "/a/b/"); - check_joinbuf_n_2("/a/", "b/", "/a/b/"); - check_joinbuf_n_2("/a/", "/b/", "/a/b/"); - check_joinbuf_n_2("/abcd", "/defg", "/abcd/defg"); - check_joinbuf_n_2("/abcd", "/defg/", "/abcd/defg/"); - check_joinbuf_n_2("/abcd/", "defg/", "/abcd/defg/"); - check_joinbuf_n_2("/abcd/", "/defg/", "/abcd/defg/"); - - check_joinbuf_n_4("", "", "", "", ""); - check_joinbuf_n_4("", "a", "", "", "a;"); - check_joinbuf_n_4("a", "", "", "", "a;"); - check_joinbuf_n_4("", "", "", "a", "a"); - check_joinbuf_n_4("a", "b", "", ";c;d;", "a;b;c;d;"); - check_joinbuf_n_4("a", "b", "", ";c;d", "a;b;c;d"); - check_joinbuf_n_4("abcd", "efgh", "ijkl", "mnop", "abcd;efgh;ijkl;mnop"); - check_joinbuf_n_4("abcd;", "efgh;", "ijkl;", "mnop;", "abcd;efgh;ijkl;mnop;"); - check_joinbuf_n_4(";abcd;", ";efgh;", ";ijkl;", ";mnop;", ";abcd;efgh;ijkl;mnop;"); -} - -void test_core_buffer__9(void) -{ - git_buf buf = GIT_BUF_INIT; - - /* just some exhaustive tests of various separator placement */ - char *a[] = { "", "-", "a-", "-a", "-a-" }; - char *b[] = { "", "-", "b-", "-b", "-b-" }; - char sep[] = { 0, '-', '/' }; - char *expect_null[] = { "", "-", "a-", "-a", "-a-", - "-", "--", "a--", "-a-", "-a--", - "b-", "-b-", "a-b-", "-ab-", "-a-b-", - "-b", "--b", "a--b", "-a-b", "-a--b", - "-b-", "--b-", "a--b-", "-a-b-", "-a--b-" }; - char *expect_dash[] = { "", "-", "a-", "-a-", "-a-", - "-", "-", "a-", "-a-", "-a-", - "b-", "-b-", "a-b-", "-a-b-", "-a-b-", - "-b", "-b", "a-b", "-a-b", "-a-b", - "-b-", "-b-", "a-b-", "-a-b-", "-a-b-" }; - char *expect_slas[] = { "", "-/", "a-/", "-a/", "-a-/", - "-", "-/-", "a-/-", "-a/-", "-a-/-", - "b-", "-/b-", "a-/b-", "-a/b-", "-a-/b-", - "-b", "-/-b", "a-/-b", "-a/-b", "-a-/-b", - "-b-", "-/-b-", "a-/-b-", "-a/-b-", "-a-/-b-" }; - char **expect_values[] = { expect_null, expect_dash, expect_slas }; - char separator, **expect; - unsigned int s, i, j; - - for (s = 0; s < sizeof(sep) / sizeof(char); ++s) { - separator = sep[s]; - expect = expect_values[s]; - - for (j = 0; j < sizeof(b) / sizeof(char*); ++j) { - for (i = 0; i < sizeof(a) / sizeof(char*); ++i) { - git_buf_join(&buf, separator, a[i], b[j]); - cl_assert_equal_s(*expect, buf.ptr); - expect++; - } - } - } - - git_buf_free(&buf); -} - -void test_core_buffer__10(void) -{ - git_buf a = GIT_BUF_INIT; - - cl_git_pass(git_buf_join_n(&a, '/', 1, "test")); - cl_assert_equal_s(a.ptr, "test"); - cl_git_pass(git_buf_join_n(&a, '/', 1, "string")); - cl_assert_equal_s(a.ptr, "test/string"); - git_buf_clear(&a); - cl_git_pass(git_buf_join_n(&a, '/', 3, "test", "string", "join")); - cl_assert_equal_s(a.ptr, "test/string/join"); - cl_git_pass(git_buf_join_n(&a, '/', 2, a.ptr, "more")); - cl_assert_equal_s(a.ptr, "test/string/join/test/string/join/more"); - - git_buf_free(&a); -} - -void test_core_buffer__11(void) -{ - git_buf a = GIT_BUF_INIT; - git_strarray t; - char *t1[] = { "nothing", "in", "common" }; - char *t2[] = { "something", "something else", "some other" }; - char *t3[] = { "something", "some fun", "no fun" }; - char *t4[] = { "happy", "happier", "happiest" }; - char *t5[] = { "happiest", "happier", "happy" }; - char *t6[] = { "no", "nope", "" }; - char *t7[] = { "", "doesn't matter" }; - - t.strings = t1; - t.count = 3; - cl_git_pass(git_buf_text_common_prefix(&a, &t)); - cl_assert_equal_s(a.ptr, ""); - - t.strings = t2; - t.count = 3; - cl_git_pass(git_buf_text_common_prefix(&a, &t)); - cl_assert_equal_s(a.ptr, "some"); - - t.strings = t3; - t.count = 3; - cl_git_pass(git_buf_text_common_prefix(&a, &t)); - cl_assert_equal_s(a.ptr, ""); - - t.strings = t4; - t.count = 3; - cl_git_pass(git_buf_text_common_prefix(&a, &t)); - cl_assert_equal_s(a.ptr, "happ"); - - t.strings = t5; - t.count = 3; - cl_git_pass(git_buf_text_common_prefix(&a, &t)); - cl_assert_equal_s(a.ptr, "happ"); - - t.strings = t6; - t.count = 3; - cl_git_pass(git_buf_text_common_prefix(&a, &t)); - cl_assert_equal_s(a.ptr, ""); - - t.strings = t7; - t.count = 3; - cl_git_pass(git_buf_text_common_prefix(&a, &t)); - cl_assert_equal_s(a.ptr, ""); - - git_buf_free(&a); -} - -void test_core_buffer__rfind_variants(void) -{ - git_buf a = GIT_BUF_INIT; - ssize_t len; - - cl_git_pass(git_buf_sets(&a, "/this/is/it/")); - - len = (ssize_t)git_buf_len(&a); - - cl_assert(git_buf_rfind(&a, '/') == len - 1); - cl_assert(git_buf_rfind_next(&a, '/') == len - 4); - - cl_assert(git_buf_rfind(&a, 'i') == len - 3); - cl_assert(git_buf_rfind_next(&a, 'i') == len - 3); - - cl_assert(git_buf_rfind(&a, 'h') == 2); - cl_assert(git_buf_rfind_next(&a, 'h') == 2); - - cl_assert(git_buf_rfind(&a, 'q') == -1); - cl_assert(git_buf_rfind_next(&a, 'q') == -1); - - git_buf_free(&a); -} - -void test_core_buffer__puts_escaped(void) -{ - git_buf a = GIT_BUF_INIT; - - git_buf_clear(&a); - cl_git_pass(git_buf_text_puts_escaped(&a, "this is a test", "", "")); - cl_assert_equal_s("this is a test", a.ptr); - - git_buf_clear(&a); - cl_git_pass(git_buf_text_puts_escaped(&a, "this is a test", "t", "\\")); - cl_assert_equal_s("\\this is a \\tes\\t", a.ptr); - - git_buf_clear(&a); - cl_git_pass(git_buf_text_puts_escaped(&a, "this is a test", "i ", "__")); - cl_assert_equal_s("th__is__ __is__ a__ test", a.ptr); - - git_buf_clear(&a); - cl_git_pass(git_buf_text_puts_escape_regex(&a, "^match\\s*[A-Z]+.*")); - cl_assert_equal_s("\\^match\\\\s\\*\\[A-Z\\]\\+\\.\\*", a.ptr); - - git_buf_free(&a); -} - -static void assert_unescape(char *expected, char *to_unescape) { - git_buf buf = GIT_BUF_INIT; - - cl_git_pass(git_buf_sets(&buf, to_unescape)); - git_buf_text_unescape(&buf); - cl_assert_equal_s(expected, buf.ptr); - cl_assert_equal_sz(strlen(expected), buf.size); - - git_buf_free(&buf); -} - -void test_core_buffer__unescape(void) -{ - assert_unescape("Escaped\\", "Es\\ca\\ped\\"); - assert_unescape("Es\\caped\\", "Es\\\\ca\\ped\\\\"); - assert_unescape("\\", "\\"); - assert_unescape("\\", "\\\\"); - assert_unescape("", ""); -} - -void test_core_buffer__base64(void) -{ - git_buf buf = GIT_BUF_INIT; - - /* t h i s - * 0x 74 68 69 73 - * 0b 01110100 01101000 01101001 01110011 - * 0b 011101 000110 100001 101001 011100 110000 - * 0x 1d 06 21 29 1c 30 - * d G h p c w - */ - cl_git_pass(git_buf_put_base64(&buf, "this", 4)); - cl_assert_equal_s("dGhpcw==", buf.ptr); - - git_buf_clear(&buf); - cl_git_pass(git_buf_put_base64(&buf, "this!", 5)); - cl_assert_equal_s("dGhpcyE=", buf.ptr); - - git_buf_clear(&buf); - cl_git_pass(git_buf_put_base64(&buf, "this!\n", 6)); - cl_assert_equal_s("dGhpcyEK", buf.ptr); - - git_buf_free(&buf); -} - -void test_core_buffer__classify_with_utf8(void) -{ - char *data0 = "Simple text\n"; - size_t data0len = 12; - char *data1 = "Is that UTF-8 data I see…\nYep!\n"; - size_t data1len = 31; - char *data2 = "Internal NUL!!!\000\n\nI see you!\n"; - size_t data2len = 29; - char *data3 = "\xef\xbb\xbfThis is UTF-8 with a BOM.\n"; - size_t data3len = 20; - git_buf b; - - b.ptr = data0; b.size = b.asize = data0len; - cl_assert(!git_buf_text_is_binary(&b)); - cl_assert(!git_buf_text_contains_nul(&b)); - - b.ptr = data1; b.size = b.asize = data1len; - cl_assert(git_buf_text_is_binary(&b)); - cl_assert(!git_buf_text_contains_nul(&b)); - - b.ptr = data2; b.size = b.asize = data2len; - cl_assert(git_buf_text_is_binary(&b)); - cl_assert(git_buf_text_contains_nul(&b)); - - b.ptr = data3; b.size = b.asize = data3len; - cl_assert(!git_buf_text_is_binary(&b)); - cl_assert(!git_buf_text_contains_nul(&b)); -} - -#define SIMILARITY_TEST_DATA_1 \ - "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \ - "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \ - "020\n021\n022\n023\n024\n025\n026\n027\n028\n029\n" \ - "030\n031\n032\n033\n034\n035\n036\n037\n038\n039\n" \ - "040\n041\n042\n043\n044\n045\n046\n047\n048\n049\n" - -void test_core_buffer__similarity_metric(void) -{ - git_hashsig *a, *b; - git_buf buf = GIT_BUF_INIT; - int sim; - - /* in the first case, we compare data to itself and expect 100% match */ - - cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); - cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); - cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); - - cl_assert_equal_i(100, git_hashsig_compare(a, b)); - - git_hashsig_free(a); - git_hashsig_free(b); - - /* if we change just a single byte, how much does that change magnify? */ - - cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); - cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); - cl_git_pass(git_buf_sets(&buf, - "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \ - "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \ - "x020x\n021\n022\n023\n024\n025\n026\n027\n028\n029\n" \ - "030\n031\n032\n033\n034\n035\n036\n037\n038\n039\n" \ - "040\n041\n042\n043\n044\n045\n046\n047\n048\n049\n" - )); - cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); - - sim = git_hashsig_compare(a, b); - - cl_assert_in_range(95, sim, 100); /* expect >95% similarity */ - - git_hashsig_free(a); - git_hashsig_free(b); - - /* let's try comparing data to a superset of itself */ - - cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); - cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); - cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1 - "050\n051\n052\n053\n054\n055\n056\n057\n058\n059\n")); - cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); - - sim = git_hashsig_compare(a, b); - /* 20% lines added ~= 10% lines changed */ - - cl_assert_in_range(85, sim, 95); /* expect similarity around 90% */ - - git_hashsig_free(a); - git_hashsig_free(b); - - /* what if we keep about half the original data and add half new */ - - cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); - cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); - cl_git_pass(git_buf_sets(&buf, - "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \ - "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \ - "020x\n021\n022\n023\n024\n" \ - "x25\nx26\nx27\nx28\nx29\n" \ - "x30\nx31\nx32\nx33\nx34\nx35\nx36\nx37\nx38\nx39\n" \ - "x40\nx41\nx42\nx43\nx44\nx45\nx46\nx47\nx48\nx49\n" - )); - cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); - - sim = git_hashsig_compare(a, b); - /* 50% lines changed */ - - cl_assert_in_range(40, sim, 60); /* expect in the 40-60% similarity range */ - - git_hashsig_free(a); - git_hashsig_free(b); - - /* lastly, let's check that we can hash file content as well */ - - cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); - cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); - - cl_git_pass(git_futils_mkdir("scratch", NULL, 0755, GIT_MKDIR_PATH)); - cl_git_mkfile("scratch/testdata", SIMILARITY_TEST_DATA_1); - cl_git_pass(git_hashsig_create_fromfile( - &b, "scratch/testdata", GIT_HASHSIG_NORMAL)); - - cl_assert_equal_i(100, git_hashsig_compare(a, b)); - - git_hashsig_free(a); - git_hashsig_free(b); - - git_buf_free(&buf); - git_futils_rmdir_r("scratch", NULL, GIT_RMDIR_REMOVE_FILES); -} - - -void test_core_buffer__similarity_metric_whitespace(void) -{ - git_hashsig *a, *b; - git_buf buf = GIT_BUF_INIT; - int sim, i, j; - git_hashsig_option_t opt; - const char *tabbed = - " for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {\n" - " separator = sep[s];\n" - " expect = expect_values[s];\n" - "\n" - " for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {\n" - " for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {\n" - " git_buf_join(&buf, separator, a[i], b[j]);\n" - " cl_assert_equal_s(*expect, buf.ptr);\n" - " expect++;\n" - " }\n" - " }\n" - " }\n"; - const char *spaced = - " for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {\n" - " separator = sep[s];\n" - " expect = expect_values[s];\n" - "\n" - " for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {\n" - " for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {\n" - " git_buf_join(&buf, separator, a[i], b[j]);\n" - " cl_assert_equal_s(*expect, buf.ptr);\n" - " expect++;\n" - " }\n" - " }\n" - " }\n"; - const char *crlf_spaced2 = - " for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {\r\n" - " separator = sep[s];\r\n" - " expect = expect_values[s];\r\n" - "\r\n" - " for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {\r\n" - " for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {\r\n" - " git_buf_join(&buf, separator, a[i], b[j]);\r\n" - " cl_assert_equal_s(*expect, buf.ptr);\r\n" - " expect++;\r\n" - " }\r\n" - " }\r\n" - " }\r\n"; - const char *text[3] = { tabbed, spaced, crlf_spaced2 }; - - /* let's try variations of our own code with whitespace changes */ - - for (opt = GIT_HASHSIG_NORMAL; opt <= GIT_HASHSIG_SMART_WHITESPACE; ++opt) { - for (i = 0; i < 3; ++i) { - for (j = 0; j < 3; ++j) { - cl_git_pass(git_buf_sets(&buf, text[i])); - cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, opt)); - - cl_git_pass(git_buf_sets(&buf, text[j])); - cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, opt)); - - sim = git_hashsig_compare(a, b); - - if (opt == GIT_HASHSIG_NORMAL) { - if (i == j) - cl_assert_equal_i(100, sim); - else - cl_assert_in_range(0, sim, 30); /* pretty different */ - } else { - cl_assert_equal_i(100, sim); - } - - git_hashsig_free(a); - git_hashsig_free(b); - } - } - } - - git_buf_free(&buf); -} - -#include "../filter/crlf.h" - -#define check_buf(expected,buf) do { \ - cl_assert_equal_s(expected, buf.ptr); \ - cl_assert_equal_sz(strlen(expected), buf.size); } while (0) - -void test_core_buffer__lf_and_crlf_conversions(void) -{ - git_buf src = GIT_BUF_INIT, tgt = GIT_BUF_INIT; - - /* LF source */ - - git_buf_sets(&src, "lf\nlf\nlf\nlf\n"); - - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf("lf\r\nlf\r\nlf\r\nlf\r\n", tgt); - - cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); - check_buf(src.ptr, tgt); - - git_buf_sets(&src, "\nlf\nlf\nlf\nlf\nlf"); - - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf("\r\nlf\r\nlf\r\nlf\r\nlf\r\nlf", tgt); - - cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); - check_buf(src.ptr, tgt); - - /* CRLF source */ - - git_buf_sets(&src, "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n"); - - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf("crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n", tgt); - check_buf(src.ptr, tgt); - - cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); - check_buf("crlf\ncrlf\ncrlf\ncrlf\n", tgt); - - git_buf_sets(&src, "\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf"); - - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf("\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf", tgt); - check_buf(src.ptr, tgt); - - cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); - check_buf("\ncrlf\ncrlf\ncrlf\ncrlf\ncrlf", tgt); - - /* CRLF in LF text */ - - git_buf_sets(&src, "\nlf\nlf\ncrlf\r\nlf\nlf\ncrlf\r\n"); - - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf("\r\nlf\r\nlf\r\ncrlf\r\nlf\r\nlf\r\ncrlf\r\n", tgt); - cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); - check_buf("\nlf\nlf\ncrlf\nlf\nlf\ncrlf\n", tgt); - - /* LF in CRLF text */ - - git_buf_sets(&src, "\ncrlf\r\ncrlf\r\nlf\ncrlf\r\ncrlf"); - - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf("\r\ncrlf\r\ncrlf\r\nlf\r\ncrlf\r\ncrlf", tgt); - cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); - check_buf("\ncrlf\ncrlf\nlf\ncrlf\ncrlf", tgt); - - /* bare CR test */ - - git_buf_sets(&src, "\rcrlf\r\nlf\nlf\ncr\rcrlf\r\nlf\ncr\r"); - - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf("\rcrlf\r\nlf\r\nlf\r\ncr\rcrlf\r\nlf\r\ncr\r", tgt); - cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); - check_buf("\rcrlf\nlf\nlf\ncr\rcrlf\nlf\ncr\r", tgt); - - git_buf_sets(&src, "\rcr\r"); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf(src.ptr, tgt); - cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); - check_buf("\rcr\r", tgt); - - git_buf_free(&src); - git_buf_free(&tgt); - - /* blob correspondence tests */ - - git_buf_sets(&src, ALL_CRLF_TEXT_RAW); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf(ALL_CRLF_TEXT_AS_CRLF, tgt); - cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); - check_buf(ALL_CRLF_TEXT_AS_LF, tgt); - git_buf_free(&src); - git_buf_free(&tgt); - - git_buf_sets(&src, ALL_LF_TEXT_RAW); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf(ALL_LF_TEXT_AS_CRLF, tgt); - cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); - check_buf(ALL_LF_TEXT_AS_LF, tgt); - git_buf_free(&src); - git_buf_free(&tgt); - - git_buf_sets(&src, MORE_CRLF_TEXT_RAW); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf(MORE_CRLF_TEXT_AS_CRLF, tgt); - cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); - check_buf(MORE_CRLF_TEXT_AS_LF, tgt); - git_buf_free(&src); - git_buf_free(&tgt); - - git_buf_sets(&src, MORE_LF_TEXT_RAW); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf(MORE_LF_TEXT_AS_CRLF, tgt); - cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); - check_buf(MORE_LF_TEXT_AS_LF, tgt); - git_buf_free(&src); - git_buf_free(&tgt); -} diff --git a/tests-clar/core/caps.c b/tests-clar/core/caps.c deleted file mode 100644 index 68a518ed7..000000000 --- a/tests-clar/core/caps.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "clar_libgit2.h" - -void test_core_caps__0(void) -{ - int major, minor, rev, caps; - - git_libgit2_version(&major, &minor, &rev); - cl_assert_equal_i(LIBGIT2_VER_MAJOR, major); - cl_assert_equal_i(LIBGIT2_VER_MINOR, minor); - cl_assert_equal_i(LIBGIT2_VER_REVISION, rev); - - caps = git_libgit2_capabilities(); - -#ifdef GIT_THREADS - cl_assert((caps & GIT_CAP_THREADS) != 0); -#else - cl_assert((caps & GIT_CAP_THREADS) == 0); -#endif - -#if defined(GIT_SSL) || defined(GIT_WINHTTP) - cl_assert((caps & GIT_CAP_HTTPS) != 0); -#else - cl_assert((caps & GIT_CAP_HTTPS) == 0); -#endif - -#if defined(GIT_SSH) - cl_assert((caps & GIT_CAP_SSH) != 0); -#else - cl_assert((caps & GIT_CAP_SSH) == 0); -#endif -} diff --git a/tests-clar/core/copy.c b/tests-clar/core/copy.c deleted file mode 100644 index c0c59c056..000000000 --- a/tests-clar/core/copy.c +++ /dev/null @@ -1,126 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "path.h" -#include "posix.h" - -void test_core_copy__file(void) -{ - struct stat st; - const char *content = "This is some stuff to copy\n"; - - cl_git_mkfile("copy_me", content); - - cl_git_pass(git_futils_cp("copy_me", "copy_me_two", 0664)); - - cl_git_pass(git_path_lstat("copy_me_two", &st)); - cl_assert(S_ISREG(st.st_mode)); - cl_assert(strlen(content) == (size_t)st.st_size); - - cl_git_pass(p_unlink("copy_me_two")); - cl_git_pass(p_unlink("copy_me")); -} - -void test_core_copy__file_in_dir(void) -{ - struct stat st; - const char *content = "This is some other stuff to copy\n"; - - cl_git_pass(git_futils_mkdir("an_dir/in_a_dir", NULL, 0775, GIT_MKDIR_PATH)); - cl_git_mkfile("an_dir/in_a_dir/copy_me", content); - cl_assert(git_path_isdir("an_dir")); - - cl_git_pass(git_futils_mkpath2file - ("an_dir/second_dir/and_more/copy_me_two", 0775)); - - cl_git_pass(git_futils_cp - ("an_dir/in_a_dir/copy_me", - "an_dir/second_dir/and_more/copy_me_two", - 0664)); - - cl_git_pass(git_path_lstat("an_dir/second_dir/and_more/copy_me_two", &st)); - cl_assert(S_ISREG(st.st_mode)); - cl_assert(strlen(content) == (size_t)st.st_size); - - cl_git_pass(git_futils_rmdir_r("an_dir", NULL, GIT_RMDIR_REMOVE_FILES)); - cl_assert(!git_path_isdir("an_dir")); -} - -void test_core_copy__tree(void) -{ - struct stat st; - const char *content = "File content\n"; - - cl_git_pass(git_futils_mkdir("src/b", NULL, 0775, GIT_MKDIR_PATH)); - cl_git_pass(git_futils_mkdir("src/c/d", NULL, 0775, GIT_MKDIR_PATH)); - cl_git_pass(git_futils_mkdir("src/c/e", NULL, 0775, GIT_MKDIR_PATH)); - - cl_git_mkfile("src/f1", content); - cl_git_mkfile("src/b/f2", content); - cl_git_mkfile("src/c/f3", content); - cl_git_mkfile("src/c/d/f4", content); - cl_git_mkfile("src/c/d/.f5", content); - -#ifndef GIT_WIN32 - cl_assert(p_symlink("../../b/f2", "src/c/d/l1") == 0); -#endif - - cl_assert(git_path_isdir("src")); - cl_assert(git_path_isdir("src/b")); - cl_assert(git_path_isdir("src/c/d")); - cl_assert(git_path_isfile("src/c/d/f4")); - - /* copy with no empty dirs, yes links, no dotfiles, no overwrite */ - - cl_git_pass( - git_futils_cp_r("src", "t1", GIT_CPDIR_COPY_SYMLINKS, 0) ); - - cl_assert(git_path_isdir("t1")); - cl_assert(git_path_isdir("t1/b")); - cl_assert(git_path_isdir("t1/c")); - cl_assert(git_path_isdir("t1/c/d")); - cl_assert(!git_path_isdir("t1/c/e")); - - cl_assert(git_path_isfile("t1/f1")); - cl_assert(git_path_isfile("t1/b/f2")); - cl_assert(git_path_isfile("t1/c/f3")); - cl_assert(git_path_isfile("t1/c/d/f4")); - cl_assert(!git_path_isfile("t1/c/d/.f5")); - - cl_git_pass(git_path_lstat("t1/c/f3", &st)); - cl_assert(S_ISREG(st.st_mode)); - cl_assert(strlen(content) == (size_t)st.st_size); - -#ifndef GIT_WIN32 - cl_git_pass(git_path_lstat("t1/c/d/l1", &st)); - cl_assert(S_ISLNK(st.st_mode)); -#endif - - cl_git_pass(git_futils_rmdir_r("t1", NULL, GIT_RMDIR_REMOVE_FILES)); - cl_assert(!git_path_isdir("t1")); - - /* copy with empty dirs, no links, yes dotfiles, no overwrite */ - - cl_git_pass( - git_futils_cp_r("src", "t2", GIT_CPDIR_CREATE_EMPTY_DIRS | GIT_CPDIR_COPY_DOTFILES, 0) ); - - cl_assert(git_path_isdir("t2")); - cl_assert(git_path_isdir("t2/b")); - cl_assert(git_path_isdir("t2/c")); - cl_assert(git_path_isdir("t2/c/d")); - cl_assert(git_path_isdir("t2/c/e")); - - cl_assert(git_path_isfile("t2/f1")); - cl_assert(git_path_isfile("t2/b/f2")); - cl_assert(git_path_isfile("t2/c/f3")); - cl_assert(git_path_isfile("t2/c/d/f4")); - cl_assert(git_path_isfile("t2/c/d/.f5")); - -#ifndef GIT_WIN32 - cl_git_fail(git_path_lstat("t2/c/d/l1", &st)); -#endif - - cl_git_pass(git_futils_rmdir_r("t2", NULL, GIT_RMDIR_REMOVE_FILES)); - cl_assert(!git_path_isdir("t2")); - - cl_git_pass(git_futils_rmdir_r("src", NULL, GIT_RMDIR_REMOVE_FILES)); -} diff --git a/tests-clar/core/dirent.c b/tests-clar/core/dirent.c deleted file mode 100644 index f17260362..000000000 --- a/tests-clar/core/dirent.c +++ /dev/null @@ -1,236 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" - -typedef struct name_data { - int count; /* return count */ - char *name; /* filename */ -} name_data; - -typedef struct walk_data { - char *sub; /* sub-directory name */ - name_data *names; /* name state data */ - git_buf path; -} walk_data; - - -static char *top_dir = "dir-walk"; -static walk_data *state_loc; - -static void setup(walk_data *d) -{ - name_data *n; - - cl_must_pass(p_mkdir(top_dir, 0777)); - - cl_must_pass(p_chdir(top_dir)); - - if (strcmp(d->sub, ".") != 0) - cl_must_pass(p_mkdir(d->sub, 0777)); - - cl_git_pass(git_buf_sets(&d->path, d->sub)); - - state_loc = d; - - for (n = d->names; n->name; n++) { - git_file fd = p_creat(n->name, 0666); - cl_assert(fd >= 0); - p_close(fd); - n->count = 0; - } -} - -static void dirent_cleanup__cb(void *_d) -{ - walk_data *d = _d; - name_data *n; - - for (n = d->names; n->name; n++) { - cl_must_pass(p_unlink(n->name)); - } - - if (strcmp(d->sub, ".") != 0) - cl_must_pass(p_rmdir(d->sub)); - - cl_must_pass(p_chdir("..")); - - cl_must_pass(p_rmdir(top_dir)); - - git_buf_free(&d->path); -} - -static void check_counts(walk_data *d) -{ - name_data *n; - - for (n = d->names; n->name; n++) { - cl_assert(n->count == 1); - } -} - -static int one_entry(void *state, git_buf *path) -{ - walk_data *d = (walk_data *) state; - name_data *n; - - if (state != state_loc) - return GIT_ERROR; - - if (path != &d->path) - return GIT_ERROR; - - for (n = d->names; n->name; n++) { - if (!strcmp(n->name, path->ptr)) { - n->count++; - return 0; - } - } - - return GIT_ERROR; -} - - -static name_data dot_names[] = { - { 0, "./a" }, - { 0, "./asdf" }, - { 0, "./pack-foo.pack" }, - { 0, NULL } -}; -static walk_data dot = { - ".", - dot_names, - GIT_BUF_INIT -}; - -/* make sure that the '.' folder is not traversed */ -void test_core_dirent__dont_traverse_dot(void) -{ - cl_set_cleanup(&dirent_cleanup__cb, &dot); - setup(&dot); - - cl_git_pass(git_path_direach(&dot.path, 0, one_entry, &dot)); - - check_counts(&dot); -} - - -static name_data sub_names[] = { - { 0, "sub/a" }, - { 0, "sub/asdf" }, - { 0, "sub/pack-foo.pack" }, - { 0, NULL } -}; -static walk_data sub = { - "sub", - sub_names, - GIT_BUF_INIT -}; - -/* traverse a subfolder */ -void test_core_dirent__traverse_subfolder(void) -{ - cl_set_cleanup(&dirent_cleanup__cb, &sub); - setup(&sub); - - cl_git_pass(git_path_direach(&sub.path, 0, one_entry, &sub)); - - check_counts(&sub); -} - - -static walk_data sub_slash = { - "sub/", - sub_names, - GIT_BUF_INIT -}; - -/* traverse a slash-terminated subfolder */ -void test_core_dirent__traverse_slash_terminated_folder(void) -{ - cl_set_cleanup(&dirent_cleanup__cb, &sub_slash); - setup(&sub_slash); - - cl_git_pass(git_path_direach(&sub_slash.path, 0, one_entry, &sub_slash)); - - check_counts(&sub_slash); -} - - -static name_data empty_names[] = { - { 0, NULL } -}; -static walk_data empty = { - "empty", - empty_names, - GIT_BUF_INIT -}; - -/* make sure that empty folders are not traversed */ -void test_core_dirent__dont_traverse_empty_folders(void) -{ - cl_set_cleanup(&dirent_cleanup__cb, &empty); - setup(&empty); - - cl_git_pass(git_path_direach(&empty.path, 0, one_entry, &empty)); - - check_counts(&empty); - - /* make sure callback not called */ - cl_assert(git_path_is_empty_dir(empty.path.ptr)); -} - -static name_data odd_names[] = { - { 0, "odd/.a" }, - { 0, "odd/..c" }, - /* the following don't work on cygwin/win32 */ - /* { 0, "odd/.b." }, */ - /* { 0, "odd/..d.." }, */ - { 0, NULL } -}; -static walk_data odd = { - "odd", - odd_names, - GIT_BUF_INIT -}; - -/* make sure that strange looking filenames ('..c') are traversed */ -void test_core_dirent__traverse_weird_filenames(void) -{ - cl_set_cleanup(&dirent_cleanup__cb, &odd); - setup(&odd); - - cl_git_pass(git_path_direach(&odd.path, 0, one_entry, &odd)); - - check_counts(&odd); -} - -/* test filename length limits */ -void test_core_dirent__length_limits(void) -{ - char *big_filename = (char *)git__malloc(FILENAME_MAX + 1); - memset(big_filename, 'a', FILENAME_MAX + 1); - big_filename[FILENAME_MAX] = 0; - - cl_must_fail(p_creat(big_filename, 0666)); - - git__free(big_filename); -} - -void test_core_dirent__empty_dir(void) -{ - cl_must_pass(p_mkdir("empty_dir", 0777)); - cl_assert(git_path_is_empty_dir("empty_dir")); - - cl_git_mkfile("empty_dir/content", "whatever\n"); - cl_assert(!git_path_is_empty_dir("empty_dir")); - cl_assert(!git_path_is_empty_dir("empty_dir/content")); - - cl_must_pass(p_unlink("empty_dir/content")); - - cl_must_pass(p_mkdir("empty_dir/content", 0777)); - cl_assert(!git_path_is_empty_dir("empty_dir")); - cl_assert(git_path_is_empty_dir("empty_dir/content")); - - cl_must_pass(p_rmdir("empty_dir/content")); - - cl_must_pass(p_rmdir("empty_dir")); -} diff --git a/tests-clar/core/env.c b/tests-clar/core/env.c deleted file mode 100644 index 0fa6472d7..000000000 --- a/tests-clar/core/env.c +++ /dev/null @@ -1,303 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "path.h" - -#ifdef GIT_WIN32 -#define NUM_VARS 5 -static const char *env_vars[NUM_VARS] = { - "HOME", "HOMEDRIVE", "HOMEPATH", "USERPROFILE", "PROGRAMFILES" -}; -#else -#define NUM_VARS 1 -static const char *env_vars[NUM_VARS] = { "HOME" }; -#endif - -static char *env_save[NUM_VARS]; - -static char *home_values[] = { - "fake_home", - "f\xc3\xa1ke_h\xc3\xb5me", /* all in latin-1 supplement */ - "f\xc4\x80ke_\xc4\xa4ome", /* latin extended */ - "f\xce\xb1\xce\xba\xce\xb5_h\xce\xbfm\xce\xad", /* having fun with greek */ - "fa\xe0" "\xb8" "\x87" "e_\xe0" "\xb8" "\x99" "ome", /* thai characters */ - "f\xe1\x9cx80ke_\xe1\x9c\x91ome", /* tagalog characters */ - "\xe1\xb8\x9f\xe1\xba\xa2" "ke_ho" "\xe1" "\xb9" "\x81" "e", /* latin extended additional */ - "\xf0\x9f\x98\x98\xf0\x9f\x98\x82", /* emoticons */ - NULL -}; - -void test_core_env__initialize(void) -{ - int i; - for (i = 0; i < NUM_VARS; ++i) { - const char *original = cl_getenv(env_vars[i]); -#ifdef GIT_WIN32 - env_save[i] = (char *)original; -#else - env_save[i] = original ? git__strdup(original) : NULL; -#endif - } -} - -static void reset_global_search_path(void) -{ - cl_git_pass(git_futils_dirs_set(GIT_FUTILS_DIR_GLOBAL, NULL)); -} - -static void reset_system_search_path(void) -{ - cl_git_pass(git_futils_dirs_set(GIT_FUTILS_DIR_SYSTEM, NULL)); -} - -void test_core_env__cleanup(void) -{ - int i; - char **val; - - for (i = 0; i < NUM_VARS; ++i) { - cl_setenv(env_vars[i], env_save[i]); - git__free(env_save[i]); - env_save[i] = NULL; - } - - /* these will probably have already been cleaned up, but if a test - * fails, then it's probably good to try and clear out these dirs - */ - for (val = home_values; *val != NULL; val++) { - if (**val != '\0') - (void)p_rmdir(*val); - } - - /* reset search paths to default */ - reset_global_search_path(); - reset_system_search_path(); -} - -static void setenv_and_check(const char *name, const char *value) -{ - char *check; - - cl_git_pass(cl_setenv(name, value)); - - check = cl_getenv(name); - cl_assert_equal_s(value, check); -#ifdef GIT_WIN32 - git__free(check); -#endif -} - -void test_core_env__0(void) -{ - git_buf path = GIT_BUF_INIT, found = GIT_BUF_INIT; - char testfile[16], tidx = '0'; - char **val; - const char *testname = "testfile"; - size_t testlen = strlen(testname); - - strncpy(testfile, testname, sizeof(testfile)); - cl_assert_equal_s(testname, testfile); - - for (val = home_values; *val != NULL; val++) { - - /* if we can't make the directory, let's just assume - * we are on a filesystem that doesn't support the - * characters in question and skip this test... - */ - if (p_mkdir(*val, 0777) != 0) { - *val = ""; /* mark as not created */ - continue; - } - - cl_git_pass(git_path_prettify(&path, *val, NULL)); - - /* vary testfile name in each directory so accidentally leaving - * an environment variable set from a previous iteration won't - * accidentally make this test pass... - */ - testfile[testlen] = tidx++; - cl_git_pass(git_buf_joinpath(&path, path.ptr, testfile)); - cl_git_mkfile(path.ptr, "find me"); - git_buf_rtruncate_at_char(&path, '/'); - - cl_assert_equal_i( - GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile)); - - setenv_and_check("HOME", path.ptr); - reset_global_search_path(); - - cl_git_pass(git_futils_find_global_file(&found, testfile)); - - cl_setenv("HOME", env_save[0]); - reset_global_search_path(); - - cl_assert_equal_i( - GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile)); - -#ifdef GIT_WIN32 - setenv_and_check("HOMEDRIVE", NULL); - setenv_and_check("HOMEPATH", NULL); - setenv_and_check("USERPROFILE", path.ptr); - reset_global_search_path(); - - cl_git_pass(git_futils_find_global_file(&found, testfile)); - - { - int root = git_path_root(path.ptr); - char old; - - if (root >= 0) { - setenv_and_check("USERPROFILE", NULL); - reset_global_search_path(); - - cl_assert_equal_i( - GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile)); - - old = path.ptr[root]; - path.ptr[root] = '\0'; - setenv_and_check("HOMEDRIVE", path.ptr); - path.ptr[root] = old; - setenv_and_check("HOMEPATH", &path.ptr[root]); - reset_global_search_path(); - - cl_git_pass(git_futils_find_global_file(&found, testfile)); - } - } -#endif - - (void)p_rmdir(*val); - } - - git_buf_free(&path); - git_buf_free(&found); -} - - -void test_core_env__1(void) -{ - git_buf path = GIT_BUF_INIT; - - cl_assert_equal_i( - GIT_ENOTFOUND, git_futils_find_global_file(&path, "nonexistentfile")); - - cl_git_pass(cl_setenv("HOME", "doesnotexist")); -#ifdef GIT_WIN32 - cl_git_pass(cl_setenv("HOMEPATH", "doesnotexist")); - cl_git_pass(cl_setenv("USERPROFILE", "doesnotexist")); -#endif - reset_global_search_path(); - - cl_assert_equal_i( - GIT_ENOTFOUND, git_futils_find_global_file(&path, "nonexistentfile")); - - cl_git_pass(cl_setenv("HOME", NULL)); -#ifdef GIT_WIN32 - cl_git_pass(cl_setenv("HOMEPATH", NULL)); - cl_git_pass(cl_setenv("USERPROFILE", NULL)); -#endif - reset_global_search_path(); - reset_system_search_path(); - - cl_assert_equal_i( - GIT_ENOTFOUND, git_futils_find_global_file(&path, "nonexistentfile")); - - cl_assert_equal_i( - GIT_ENOTFOUND, git_futils_find_system_file(&path, "nonexistentfile")); - -#ifdef GIT_WIN32 - cl_git_pass(cl_setenv("PROGRAMFILES", NULL)); - reset_system_search_path(); - - cl_assert_equal_i( - GIT_ENOTFOUND, git_futils_find_system_file(&path, "nonexistentfile")); -#endif - - git_buf_free(&path); -} - -static void check_global_searchpath( - const char *path, int position, const char *file, git_buf *temp) -{ - char out[GIT_PATH_MAX]; - - /* build and set new path */ - if (position < 0) - cl_git_pass(git_buf_join(temp, GIT_PATH_LIST_SEPARATOR, path, "$PATH")); - else if (position > 0) - cl_git_pass(git_buf_join(temp, GIT_PATH_LIST_SEPARATOR, "$PATH", path)); - else - cl_git_pass(git_buf_sets(temp, path)); - - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, temp->ptr)); - - /* get path and make sure $PATH expansion worked */ - cl_git_pass(git_libgit2_opts( - GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, out, sizeof(out))); - - if (position < 0) - cl_assert(git__prefixcmp(out, path) == 0); - else if (position > 0) - cl_assert(git__suffixcmp(out, path) == 0); - else - cl_assert_equal_s(out, path); - - /* find file using new path */ - cl_git_pass(git_futils_find_global_file(temp, file)); - - /* reset path and confirm file not found */ - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, NULL)); - cl_assert_equal_i( - GIT_ENOTFOUND, git_futils_find_global_file(temp, file)); -} - -void test_core_env__2(void) -{ - git_buf path = GIT_BUF_INIT, found = GIT_BUF_INIT; - char testfile[16], tidx = '0'; - char **val; - const char *testname = "alternate"; - size_t testlen = strlen(testname); - - strncpy(testfile, testname, sizeof(testfile)); - cl_assert_equal_s(testname, testfile); - - for (val = home_values; *val != NULL; val++) { - - /* if we can't make the directory, let's just assume - * we are on a filesystem that doesn't support the - * characters in question and skip this test... - */ - if (p_mkdir(*val, 0777) != 0 && errno != EEXIST) { - *val = ""; /* mark as not created */ - continue; - } - - cl_git_pass(git_path_prettify(&path, *val, NULL)); - - /* vary testfile name so any sloppiness is resetting variables or - * deleting files won't accidentally make a test pass. - */ - testfile[testlen] = tidx++; - cl_git_pass(git_buf_joinpath(&path, path.ptr, testfile)); - cl_git_mkfile(path.ptr, "find me"); - git_buf_rtruncate_at_char(&path, '/'); - - /* default should be NOTFOUND */ - cl_assert_equal_i( - GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile)); - - /* try plain, append $PATH, and prepend $PATH */ - check_global_searchpath(path.ptr, 0, testfile, &found); - check_global_searchpath(path.ptr, -1, testfile, &found); - check_global_searchpath(path.ptr, 1, testfile, &found); - - /* cleanup */ - cl_git_pass(git_buf_joinpath(&path, path.ptr, testfile)); - (void)p_unlink(path.ptr); - (void)p_rmdir(*val); - } - - git_buf_free(&path); - git_buf_free(&found); -} diff --git a/tests-clar/core/errors.c b/tests-clar/core/errors.c deleted file mode 100644 index 512a4134d..000000000 --- a/tests-clar/core/errors.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "clar_libgit2.h" - -void test_core_errors__public_api(void) -{ - char *str_in_error; - - giterr_clear(); - cl_assert(giterr_last() == NULL); - - giterr_set_oom(); - - cl_assert(giterr_last() != NULL); - cl_assert(giterr_last()->klass == GITERR_NOMEMORY); - str_in_error = strstr(giterr_last()->message, "memory"); - cl_assert(str_in_error != NULL); - - giterr_clear(); - - giterr_set_str(GITERR_REPOSITORY, "This is a test"); - - cl_assert(giterr_last() != NULL); - str_in_error = strstr(giterr_last()->message, "This is a test"); - cl_assert(str_in_error != NULL); - - giterr_clear(); - cl_assert(giterr_last() == NULL); -} - -#include "common.h" -#include "util.h" -#include "posix.h" - -void test_core_errors__new_school(void) -{ - char *str_in_error; - - giterr_clear(); - cl_assert(giterr_last() == NULL); - - giterr_set_oom(); /* internal fn */ - - cl_assert(giterr_last() != NULL); - cl_assert(giterr_last()->klass == GITERR_NOMEMORY); - str_in_error = strstr(giterr_last()->message, "memory"); - cl_assert(str_in_error != NULL); - - giterr_clear(); - - giterr_set(GITERR_REPOSITORY, "This is a test"); /* internal fn */ - - cl_assert(giterr_last() != NULL); - str_in_error = strstr(giterr_last()->message, "This is a test"); - cl_assert(str_in_error != NULL); - - giterr_clear(); - cl_assert(giterr_last() == NULL); - - do { - struct stat st; - memset(&st, 0, sizeof(st)); - cl_assert(p_lstat("this_file_does_not_exist", &st) < 0); - GIT_UNUSED(st); - } while (false); - giterr_set(GITERR_OS, "stat failed"); /* internal fn */ - - cl_assert(giterr_last() != NULL); - str_in_error = strstr(giterr_last()->message, "stat failed"); - cl_assert(str_in_error != NULL); - cl_assert(git__prefixcmp(str_in_error, "stat failed: ") == 0); - cl_assert(strlen(str_in_error) > strlen("stat failed: ")); - -#ifdef GIT_WIN32 - giterr_clear(); - - /* The MSDN docs use this to generate a sample error */ - cl_assert(GetProcessId(NULL) == 0); - giterr_set(GITERR_OS, "GetProcessId failed"); /* internal fn */ - - cl_assert(giterr_last() != NULL); - str_in_error = strstr(giterr_last()->message, "GetProcessId failed"); - cl_assert(str_in_error != NULL); - cl_assert(git__prefixcmp(str_in_error, "GetProcessId failed: ") == 0); - cl_assert(strlen(str_in_error) > strlen("GetProcessId failed: ")); -#endif - - giterr_clear(); -} diff --git a/tests-clar/core/filebuf.c b/tests-clar/core/filebuf.c deleted file mode 100644 index 5a3e7510f..000000000 --- a/tests-clar/core/filebuf.c +++ /dev/null @@ -1,126 +0,0 @@ -#include "clar_libgit2.h" -#include "filebuf.h" - -/* make sure git_filebuf_open doesn't delete an existing lock */ -void test_core_filebuf__0(void) -{ - git_filebuf file = GIT_FILEBUF_INIT; - int fd; - char test[] = "test", testlock[] = "test.lock"; - - fd = p_creat(testlock, 0744); //-V536 - - cl_must_pass(fd); - cl_must_pass(p_close(fd)); - - cl_git_fail(git_filebuf_open(&file, test, 0, 0666)); - cl_assert(git_path_exists(testlock)); - - cl_must_pass(p_unlink(testlock)); -} - - -/* make sure GIT_FILEBUF_APPEND works as expected */ -void test_core_filebuf__1(void) -{ - git_filebuf file = GIT_FILEBUF_INIT; - char test[] = "test"; - - cl_git_mkfile(test, "libgit2 rocks\n"); - - cl_git_pass(git_filebuf_open(&file, test, GIT_FILEBUF_APPEND, 0666)); - cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks")); - cl_git_pass(git_filebuf_commit(&file)); - - cl_assert_equal_file("libgit2 rocks\nlibgit2 rocks\n", 0, test); - - cl_must_pass(p_unlink(test)); -} - - -/* make sure git_filebuf_write writes large buffer correctly */ -void test_core_filebuf__2(void) -{ - git_filebuf file = GIT_FILEBUF_INIT; - char test[] = "test"; - unsigned char buf[4096 * 4]; /* 2 * WRITE_BUFFER_SIZE */ - - memset(buf, 0xfe, sizeof(buf)); - - cl_git_pass(git_filebuf_open(&file, test, 0, 0666)); - cl_git_pass(git_filebuf_write(&file, buf, sizeof(buf))); - cl_git_pass(git_filebuf_commit(&file)); - - cl_assert_equal_file((char *)buf, sizeof(buf), test); - - cl_must_pass(p_unlink(test)); -} - -/* make sure git_filebuf_cleanup clears the buffer */ -void test_core_filebuf__4(void) -{ - git_filebuf file = GIT_FILEBUF_INIT; - char test[] = "test"; - - cl_assert(file.buffer == NULL); - - cl_git_pass(git_filebuf_open(&file, test, 0, 0666)); - cl_assert(file.buffer != NULL); - - git_filebuf_cleanup(&file); - cl_assert(file.buffer == NULL); -} - - -/* make sure git_filebuf_commit clears the buffer */ -void test_core_filebuf__5(void) -{ - git_filebuf file = GIT_FILEBUF_INIT; - char test[] = "test"; - - cl_assert(file.buffer == NULL); - - cl_git_pass(git_filebuf_open(&file, test, 0, 0666)); - cl_assert(file.buffer != NULL); - cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks")); - cl_assert(file.buffer != NULL); - - cl_git_pass(git_filebuf_commit(&file)); - cl_assert(file.buffer == NULL); - - cl_must_pass(p_unlink(test)); -} - - -/* make sure git_filebuf_commit takes umask into account */ -void test_core_filebuf__umask(void) -{ - git_filebuf file = GIT_FILEBUF_INIT; - char test[] = "test"; - struct stat statbuf; - mode_t mask, os_mask; - -#ifdef GIT_WIN32 - os_mask = 0600; -#else - os_mask = 0777; -#endif - - p_umask(mask = p_umask(0)); - - cl_assert(file.buffer == NULL); - - cl_git_pass(git_filebuf_open(&file, test, 0, 0666)); - cl_assert(file.buffer != NULL); - cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks")); - cl_assert(file.buffer != NULL); - - cl_git_pass(git_filebuf_commit(&file)); - cl_assert(file.buffer == NULL); - - cl_must_pass(p_stat("test", &statbuf)); - cl_assert_equal_i(statbuf.st_mode & os_mask, (0666 & ~mask) & os_mask); - - cl_must_pass(p_unlink(test)); -} - diff --git a/tests-clar/core/hex.c b/tests-clar/core/hex.c deleted file mode 100644 index 930af1670..000000000 --- a/tests-clar/core/hex.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "clar_libgit2.h" -#include "util.h" - -void test_core_hex__fromhex(void) -{ - /* Passing cases */ - cl_assert(git__fromhex('0') == 0x0); - cl_assert(git__fromhex('1') == 0x1); - cl_assert(git__fromhex('3') == 0x3); - cl_assert(git__fromhex('9') == 0x9); - cl_assert(git__fromhex('A') == 0xa); - cl_assert(git__fromhex('C') == 0xc); - cl_assert(git__fromhex('F') == 0xf); - cl_assert(git__fromhex('a') == 0xa); - cl_assert(git__fromhex('c') == 0xc); - cl_assert(git__fromhex('f') == 0xf); - - /* Failing cases */ - cl_assert(git__fromhex('g') == -1); - cl_assert(git__fromhex('z') == -1); - cl_assert(git__fromhex('X') == -1); -} diff --git a/tests-clar/core/iconv.c b/tests-clar/core/iconv.c deleted file mode 100644 index 8aedab206..000000000 --- a/tests-clar/core/iconv.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "clar_libgit2.h" -#include "path.h" - -#ifdef GIT_USE_ICONV -static git_path_iconv_t ic; -static char *nfc = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D"; -static char *nfd = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D"; -#endif - -void test_core_iconv__initialize(void) -{ -#ifdef GIT_USE_ICONV - cl_git_pass(git_path_iconv_init_precompose(&ic)); -#endif -} - -void test_core_iconv__cleanup(void) -{ -#ifdef GIT_USE_ICONV - git_path_iconv_clear(&ic); -#endif -} - -void test_core_iconv__unchanged(void) -{ -#ifdef GIT_USE_ICONV - char *data = "Ascii data", *original = data; - size_t datalen = strlen(data); - - cl_git_pass(git_path_iconv(&ic, &data, &datalen)); - GIT_UNUSED(datalen); - - /* There are no high bits set, so this should leave data untouched */ - cl_assert(data == original); -#endif -} - -void test_core_iconv__decomposed_to_precomposed(void) -{ -#ifdef GIT_USE_ICONV - char *data = nfd; - size_t datalen = strlen(nfd); - - cl_git_pass(git_path_iconv(&ic, &data, &datalen)); - GIT_UNUSED(datalen); - - /* The decomposed nfd string should be transformed to the nfc form - * (on platforms where iconv is enabled, of course). - */ - cl_assert_equal_s(nfc, data); -#endif -} - -void test_core_iconv__precomposed_is_unmodified(void) -{ -#ifdef GIT_USE_ICONV - char *data = nfc; - size_t datalen = strlen(nfc); - - cl_git_pass(git_path_iconv(&ic, &data, &datalen)); - GIT_UNUSED(datalen); - - /* data is already in precomposed form, so even though some bytes have - * the high-bit set, the iconv transform should result in no change. - */ - cl_assert_equal_s(nfc, data); -#endif -} diff --git a/tests-clar/core/mkdir.c b/tests-clar/core/mkdir.c deleted file mode 100644 index a8c5b10ae..000000000 --- a/tests-clar/core/mkdir.c +++ /dev/null @@ -1,188 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "path.h" -#include "posix.h" - -static void cleanup_basic_dirs(void *ref) -{ - GIT_UNUSED(ref); - git_futils_rmdir_r("d0", NULL, GIT_RMDIR_EMPTY_HIERARCHY); - git_futils_rmdir_r("d1", NULL, GIT_RMDIR_EMPTY_HIERARCHY); - git_futils_rmdir_r("d2", NULL, GIT_RMDIR_EMPTY_HIERARCHY); - git_futils_rmdir_r("d3", NULL, GIT_RMDIR_EMPTY_HIERARCHY); - git_futils_rmdir_r("d4", NULL, GIT_RMDIR_EMPTY_HIERARCHY); -} - -void test_core_mkdir__basic(void) -{ - cl_set_cleanup(cleanup_basic_dirs, NULL); - - /* make a directory */ - cl_assert(!git_path_isdir("d0")); - cl_git_pass(git_futils_mkdir("d0", NULL, 0755, 0)); - cl_assert(git_path_isdir("d0")); - - /* make a path */ - cl_assert(!git_path_isdir("d1")); - cl_git_pass(git_futils_mkdir("d1/d1.1/d1.2", NULL, 0755, GIT_MKDIR_PATH)); - cl_assert(git_path_isdir("d1")); - cl_assert(git_path_isdir("d1/d1.1")); - cl_assert(git_path_isdir("d1/d1.1/d1.2")); - - /* make a dir exclusively */ - cl_assert(!git_path_isdir("d2")); - cl_git_pass(git_futils_mkdir("d2", NULL, 0755, GIT_MKDIR_EXCL)); - cl_assert(git_path_isdir("d2")); - - /* make exclusive failure */ - cl_git_fail(git_futils_mkdir("d2", NULL, 0755, GIT_MKDIR_EXCL)); - - /* make a path exclusively */ - cl_assert(!git_path_isdir("d3")); - cl_git_pass(git_futils_mkdir("d3/d3.1/d3.2", NULL, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL)); - cl_assert(git_path_isdir("d3")); - cl_assert(git_path_isdir("d3/d3.1/d3.2")); - - /* make exclusive path failure */ - cl_git_fail(git_futils_mkdir("d3/d3.1/d3.2", NULL, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL)); - /* ??? Should EXCL only apply to the last item in the path? */ - - /* path with trailing slash? */ - cl_assert(!git_path_isdir("d4")); - cl_git_pass(git_futils_mkdir("d4/d4.1/", NULL, 0755, GIT_MKDIR_PATH)); - cl_assert(git_path_isdir("d4/d4.1")); -} - -static void cleanup_basedir(void *ref) -{ - GIT_UNUSED(ref); - git_futils_rmdir_r("base", NULL, GIT_RMDIR_EMPTY_HIERARCHY); -} - -void test_core_mkdir__with_base(void) -{ -#define BASEDIR "base/dir/here" - - cl_set_cleanup(cleanup_basedir, NULL); - - cl_git_pass(git_futils_mkdir(BASEDIR, NULL, 0755, GIT_MKDIR_PATH)); - - cl_git_pass(git_futils_mkdir("a", BASEDIR, 0755, 0)); - cl_assert(git_path_isdir(BASEDIR "/a")); - - cl_git_pass(git_futils_mkdir("b/b1/b2", BASEDIR, 0755, GIT_MKDIR_PATH)); - cl_assert(git_path_isdir(BASEDIR "/b/b1/b2")); - - /* exclusive with existing base */ - cl_git_pass(git_futils_mkdir("c/c1/c2", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL)); - - /* fail: exclusive with duplicated suffix */ - cl_git_fail(git_futils_mkdir("c/c1/c3", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL)); - - /* fail: exclusive with any duplicated component */ - cl_git_fail(git_futils_mkdir("c/cz/cz", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL)); - - /* success: exclusive without path */ - cl_git_pass(git_futils_mkdir("c/c1/c3", BASEDIR, 0755, GIT_MKDIR_EXCL)); - - /* path with shorter base and existing dirs */ - cl_git_pass(git_futils_mkdir("dir/here/d/", "base", 0755, GIT_MKDIR_PATH)); - cl_assert(git_path_isdir("base/dir/here/d")); - - /* fail: path with shorter base and existing dirs */ - cl_git_fail(git_futils_mkdir("dir/here/e/", "base", 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL)); - - /* fail: base with missing components */ - cl_git_fail(git_futils_mkdir("f/", "base/missing", 0755, GIT_MKDIR_PATH)); - - /* success: shift missing component to path */ - cl_git_pass(git_futils_mkdir("missing/f/", "base/", 0755, GIT_MKDIR_PATH)); -} - -static void cleanup_chmod_root(void *ref) -{ - mode_t *mode = ref; - - if (*mode != 0) { - (void)p_umask(*mode); - git__free(mode); - } - - git_futils_rmdir_r("r", NULL, GIT_RMDIR_EMPTY_HIERARCHY); -} - -#define check_mode(X,A) check_mode_at_line((X), (A), __FILE__, __LINE__) - -static void check_mode_at_line( - mode_t expected, mode_t actual, const char *file, int line) -{ - /* FAT filesystems don't support exec bit, nor group/world bits */ - if (!cl_is_chmod_supported()) { - expected &= 0600; - actual &= 0600; - } - - clar__assert_equal( - file, line, "expected_mode != actual_mode", 1, - "%07o", (int)expected, (int)(actual & 0777)); -} - -void test_core_mkdir__chmods(void) -{ - struct stat st; - mode_t *old = git__malloc(sizeof(mode_t)); - *old = p_umask(022); - - cl_set_cleanup(cleanup_chmod_root, old); - - cl_git_pass(git_futils_mkdir("r", NULL, 0777, 0)); - - cl_git_pass(git_futils_mkdir("mode/is/important", "r", 0777, GIT_MKDIR_PATH)); - - cl_git_pass(git_path_lstat("r/mode", &st)); - check_mode(0755, st.st_mode); - cl_git_pass(git_path_lstat("r/mode/is", &st)); - check_mode(0755, st.st_mode); - cl_git_pass(git_path_lstat("r/mode/is/important", &st)); - check_mode(0755, st.st_mode); - - cl_git_pass(git_futils_mkdir("mode2/is2/important2", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD)); - - cl_git_pass(git_path_lstat("r/mode2", &st)); - check_mode(0755, st.st_mode); - cl_git_pass(git_path_lstat("r/mode2/is2", &st)); - check_mode(0755, st.st_mode); - cl_git_pass(git_path_lstat("r/mode2/is2/important2", &st)); - check_mode(0777, st.st_mode); - - cl_git_pass(git_futils_mkdir("mode3/is3/important3", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD_PATH)); - - cl_git_pass(git_path_lstat("r/mode3", &st)); - check_mode(0777, st.st_mode); - cl_git_pass(git_path_lstat("r/mode3/is3", &st)); - check_mode(0777, st.st_mode); - cl_git_pass(git_path_lstat("r/mode3/is3/important3", &st)); - check_mode(0777, st.st_mode); - - /* test that we chmod existing dir */ - - cl_git_pass(git_futils_mkdir("mode/is/important", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD)); - - cl_git_pass(git_path_lstat("r/mode", &st)); - check_mode(0755, st.st_mode); - cl_git_pass(git_path_lstat("r/mode/is", &st)); - check_mode(0755, st.st_mode); - cl_git_pass(git_path_lstat("r/mode/is/important", &st)); - check_mode(0777, st.st_mode); - - /* test that we chmod even existing dirs if CHMOD_PATH is set */ - - cl_git_pass(git_futils_mkdir("mode2/is2/important2.1", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD_PATH)); - - cl_git_pass(git_path_lstat("r/mode2", &st)); - check_mode(0777, st.st_mode); - cl_git_pass(git_path_lstat("r/mode2/is2", &st)); - check_mode(0777, st.st_mode); - cl_git_pass(git_path_lstat("r/mode2/is2/important2.1", &st)); - check_mode(0777, st.st_mode); -} diff --git a/tests-clar/core/oid.c b/tests-clar/core/oid.c deleted file mode 100644 index 7ee6fb67d..000000000 --- a/tests-clar/core/oid.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "clar_libgit2.h" - -static git_oid id; -static git_oid idp; -static git_oid idm; -const char *str_oid = "ae90f12eea699729ed24555e40b9fd669da12a12"; -const char *str_oid_p = "ae90f12eea699729ed"; -const char *str_oid_m = "ae90f12eea699729ed24555e40b9fd669da12a12THIS IS EXTRA TEXT THAT SHOULD GET IGNORED"; - -void test_core_oid__initialize(void) -{ - cl_git_pass(git_oid_fromstr(&id, str_oid)); - cl_git_pass(git_oid_fromstrp(&idp, str_oid_p)); - cl_git_fail(git_oid_fromstrp(&idm, str_oid_m)); -} - -void test_core_oid__streq(void) -{ - cl_assert_equal_i(0, git_oid_streq(&id, str_oid)); - cl_assert_equal_i(-1, git_oid_streq(&id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")); - - cl_assert_equal_i(-1, git_oid_streq(&id, "deadbeef")); - cl_assert_equal_i(-1, git_oid_streq(&id, "I'm not an oid.... :)")); - - cl_assert_equal_i(0, git_oid_streq(&idp, "ae90f12eea699729ed0000000000000000000000")); - cl_assert_equal_i(0, git_oid_streq(&idp, "ae90f12eea699729ed")); - cl_assert_equal_i(-1, git_oid_streq(&idp, "ae90f12eea699729ed1")); - cl_assert_equal_i(-1, git_oid_streq(&idp, "ae90f12eea699729ec")); - cl_assert_equal_i(-1, git_oid_streq(&idp, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")); - - cl_assert_equal_i(-1, git_oid_streq(&idp, "deadbeef")); - cl_assert_equal_i(-1, git_oid_streq(&idp, "I'm not an oid.... :)")); -} - -void test_core_oid__strcmp(void) -{ - cl_assert_equal_i(0, git_oid_strcmp(&id, str_oid)); - cl_assert(git_oid_strcmp(&id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef") < 0); - - cl_assert(git_oid_strcmp(&id, "deadbeef") < 0); - cl_assert_equal_i(-1, git_oid_strcmp(&id, "I'm not an oid.... :)")); - - cl_assert_equal_i(0, git_oid_strcmp(&idp, "ae90f12eea699729ed0000000000000000000000")); - cl_assert_equal_i(0, git_oid_strcmp(&idp, "ae90f12eea699729ed")); - cl_assert(git_oid_strcmp(&idp, "ae90f12eea699729ed1") < 0); - cl_assert(git_oid_strcmp(&idp, "ae90f12eea699729ec") > 0); - cl_assert(git_oid_strcmp(&idp, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef") < 0); - - cl_assert(git_oid_strcmp(&idp, "deadbeef") < 0); - cl_assert_equal_i(-1, git_oid_strcmp(&idp, "I'm not an oid.... :)")); -} - -void test_core_oid__ncmp(void) -{ - cl_assert(!git_oid_ncmp(&id, &idp, 0)); - cl_assert(!git_oid_ncmp(&id, &idp, 1)); - cl_assert(!git_oid_ncmp(&id, &idp, 2)); - cl_assert(!git_oid_ncmp(&id, &idp, 17)); - cl_assert(!git_oid_ncmp(&id, &idp, 18)); - cl_assert(git_oid_ncmp(&id, &idp, 19)); - cl_assert(git_oid_ncmp(&id, &idp, 40)); - cl_assert(git_oid_ncmp(&id, &idp, 41)); - cl_assert(git_oid_ncmp(&id, &idp, 42)); - - cl_assert(!git_oid_ncmp(&id, &id, 0)); - cl_assert(!git_oid_ncmp(&id, &id, 1)); - cl_assert(!git_oid_ncmp(&id, &id, 39)); - cl_assert(!git_oid_ncmp(&id, &id, 40)); - cl_assert(!git_oid_ncmp(&id, &id, 41)); -} diff --git a/tests-clar/core/oidmap.c b/tests-clar/core/oidmap.c deleted file mode 100644 index ec4b5e775..000000000 --- a/tests-clar/core/oidmap.c +++ /dev/null @@ -1,110 +0,0 @@ -#include "clar_libgit2.h" -#include "oidmap.h" - -GIT__USE_OIDMAP; - -typedef struct { - git_oid oid; - size_t extra; -} oidmap_item; - -#define NITEMS 0x0fff - -void test_core_oidmap__basic(void) -{ - git_oidmap *map; - oidmap_item items[NITEMS]; - uint32_t i, j; - - for (i = 0; i < NITEMS; ++i) { - items[i].extra = i; - for (j = 0; j < GIT_OID_RAWSZ / 4; ++j) { - items[i].oid.id[j * 4 ] = (unsigned char)i; - items[i].oid.id[j * 4 + 1] = (unsigned char)(i >> 8); - items[i].oid.id[j * 4 + 2] = (unsigned char)(i >> 16); - items[i].oid.id[j * 4 + 3] = (unsigned char)(i >> 24); - } - } - - map = git_oidmap_alloc(); - cl_assert(map != NULL); - - for (i = 0; i < NITEMS; ++i) { - khiter_t pos; - int ret; - - pos = kh_get(oid, map, &items[i].oid); - cl_assert(pos == kh_end(map)); - - pos = kh_put(oid, map, &items[i].oid, &ret); - cl_assert(ret != 0); - - kh_val(map, pos) = &items[i]; - } - - - for (i = 0; i < NITEMS; ++i) { - khiter_t pos; - - pos = kh_get(oid, map, &items[i].oid); - cl_assert(pos != kh_end(map)); - - cl_assert_equal_p(kh_val(map, pos), &items[i]); - } - - git_oidmap_free(map); -} - -void test_core_oidmap__hash_collision(void) -{ - git_oidmap *map; - oidmap_item items[NITEMS]; - uint32_t i, j; - - for (i = 0; i < NITEMS; ++i) { - uint32_t segment = i / 8; - int modi = i - (segment * 8); - - items[i].extra = i; - - for (j = 0; j < GIT_OID_RAWSZ / 4; ++j) { - items[i].oid.id[j * 4 ] = (unsigned char)modi; - items[i].oid.id[j * 4 + 1] = (unsigned char)(modi >> 8); - items[i].oid.id[j * 4 + 2] = (unsigned char)(modi >> 16); - items[i].oid.id[j * 4 + 3] = (unsigned char)(modi >> 24); - } - - items[i].oid.id[ 8] = (unsigned char)i; - items[i].oid.id[ 9] = (unsigned char)(i >> 8); - items[i].oid.id[10] = (unsigned char)(i >> 16); - items[i].oid.id[11] = (unsigned char)(i >> 24); - } - - map = git_oidmap_alloc(); - cl_assert(map != NULL); - - for (i = 0; i < NITEMS; ++i) { - khiter_t pos; - int ret; - - pos = kh_get(oid, map, &items[i].oid); - cl_assert(pos == kh_end(map)); - - pos = kh_put(oid, map, &items[i].oid, &ret); - cl_assert(ret != 0); - - kh_val(map, pos) = &items[i]; - } - - - for (i = 0; i < NITEMS; ++i) { - khiter_t pos; - - pos = kh_get(oid, map, &items[i].oid); - cl_assert(pos != kh_end(map)); - - cl_assert_equal_p(kh_val(map, pos), &items[i]); - } - - git_oidmap_free(map); -} diff --git a/tests-clar/core/opts.c b/tests-clar/core/opts.c deleted file mode 100644 index 3173c648b..000000000 --- a/tests-clar/core/opts.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "clar_libgit2.h" -#include "cache.h" - -void test_core_opts__readwrite(void) -{ - size_t old_val = 0; - size_t new_val = 0; - - git_libgit2_opts(GIT_OPT_GET_MWINDOW_SIZE, &old_val); - git_libgit2_opts(GIT_OPT_SET_MWINDOW_SIZE, (size_t)1234); - git_libgit2_opts(GIT_OPT_GET_MWINDOW_SIZE, &new_val); - - cl_assert(new_val == 1234); - - git_libgit2_opts(GIT_OPT_SET_MWINDOW_SIZE, old_val); - git_libgit2_opts(GIT_OPT_GET_MWINDOW_SIZE, &new_val); - - cl_assert(new_val == old_val); -} diff --git a/tests-clar/core/path.c b/tests-clar/core/path.c deleted file mode 100644 index cf2d5e944..000000000 --- a/tests-clar/core/path.c +++ /dev/null @@ -1,583 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" - -static void -check_dirname(const char *A, const char *B) -{ - git_buf dir = GIT_BUF_INIT; - char *dir2; - - cl_assert(git_path_dirname_r(&dir, A) >= 0); - cl_assert_equal_s(B, dir.ptr); - git_buf_free(&dir); - - cl_assert((dir2 = git_path_dirname(A)) != NULL); - cl_assert_equal_s(B, dir2); - git__free(dir2); -} - -static void -check_basename(const char *A, const char *B) -{ - git_buf base = GIT_BUF_INIT; - char *base2; - - cl_assert(git_path_basename_r(&base, A) >= 0); - cl_assert_equal_s(B, base.ptr); - git_buf_free(&base); - - cl_assert((base2 = git_path_basename(A)) != NULL); - cl_assert_equal_s(B, base2); - git__free(base2); -} - -static void -check_topdir(const char *A, const char *B) -{ - const char *dir; - - cl_assert((dir = git_path_topdir(A)) != NULL); - cl_assert_equal_s(B, dir); -} - -static void -check_joinpath(const char *path_a, const char *path_b, const char *expected_path) -{ - git_buf joined_path = GIT_BUF_INIT; - - cl_git_pass(git_buf_joinpath(&joined_path, path_a, path_b)); - cl_assert_equal_s(expected_path, joined_path.ptr); - - git_buf_free(&joined_path); -} - -static void -check_joinpath_n( - const char *path_a, - const char *path_b, - const char *path_c, - const char *path_d, - const char *expected_path) -{ - git_buf joined_path = GIT_BUF_INIT; - - cl_git_pass(git_buf_join_n(&joined_path, '/', 4, - path_a, path_b, path_c, path_d)); - cl_assert_equal_s(expected_path, joined_path.ptr); - - git_buf_free(&joined_path); -} - - -/* get the dirname of a path */ -void test_core_path__00_dirname(void) -{ - check_dirname(NULL, "."); - check_dirname("", "."); - check_dirname("a", "."); - check_dirname("/", "/"); - check_dirname("/usr", "/"); - check_dirname("/usr/", "/"); - check_dirname("/usr/lib", "/usr"); - check_dirname("/usr/lib/", "/usr"); - check_dirname("/usr/lib//", "/usr"); - check_dirname("usr/lib", "usr"); - check_dirname("usr/lib/", "usr"); - check_dirname("usr/lib//", "usr"); - check_dirname(".git/", "."); - - check_dirname(REP16("/abc"), REP15("/abc")); - -#ifdef GIT_WIN32 - check_dirname("C:/path/", "C:/"); - check_dirname("C:/path", "C:/"); - check_dirname("//computername/path/", "//computername/"); - check_dirname("//computername/path", "//computername/"); - check_dirname("//computername/sub/path/", "//computername/sub"); - check_dirname("//computername/sub/path", "//computername/sub"); -#endif -} - -/* get the base name of a path */ -void test_core_path__01_basename(void) -{ - check_basename(NULL, "."); - check_basename("", "."); - check_basename("a", "a"); - check_basename("/", "/"); - check_basename("/usr", "usr"); - check_basename("/usr/", "usr"); - check_basename("/usr/lib", "lib"); - check_basename("/usr/lib//", "lib"); - check_basename("usr/lib", "lib"); - - check_basename(REP16("/abc"), "abc"); - check_basename(REP1024("/abc"), "abc"); -} - -/* get the latest component in a path */ -void test_core_path__02_topdir(void) -{ - check_topdir(".git/", ".git/"); - check_topdir("/.git/", ".git/"); - check_topdir("usr/local/.git/", ".git/"); - check_topdir("./.git/", ".git/"); - check_topdir("/usr/.git/", ".git/"); - check_topdir("/", "/"); - check_topdir("a/", "a/"); - - cl_assert(git_path_topdir("/usr/.git") == NULL); - cl_assert(git_path_topdir(".") == NULL); - cl_assert(git_path_topdir("") == NULL); - cl_assert(git_path_topdir("a") == NULL); -} - -/* properly join path components */ -void test_core_path__05_joins(void) -{ - check_joinpath("", "", ""); - check_joinpath("", "a", "a"); - check_joinpath("", "/a", "/a"); - check_joinpath("a", "", "a/"); - check_joinpath("a", "/", "a/"); - check_joinpath("a", "b", "a/b"); - check_joinpath("/", "a", "/a"); - check_joinpath("/", "", "/"); - check_joinpath("/a", "/b", "/a/b"); - check_joinpath("/a", "/b/", "/a/b/"); - check_joinpath("/a/", "b/", "/a/b/"); - check_joinpath("/a/", "/b/", "/a/b/"); - - check_joinpath("/abcd", "/defg", "/abcd/defg"); - check_joinpath("/abcd", "/defg/", "/abcd/defg/"); - check_joinpath("/abcd/", "defg/", "/abcd/defg/"); - check_joinpath("/abcd/", "/defg/", "/abcd/defg/"); - - check_joinpath("/abcdefgh", "/12345678", "/abcdefgh/12345678"); - check_joinpath("/abcdefgh", "/12345678/", "/abcdefgh/12345678/"); - check_joinpath("/abcdefgh/", "12345678/", "/abcdefgh/12345678/"); - - check_joinpath(REP1024("aaaa"), "", REP1024("aaaa") "/"); - check_joinpath(REP1024("aaaa/"), "", REP1024("aaaa/")); - check_joinpath(REP1024("/aaaa"), "", REP1024("/aaaa") "/"); - - check_joinpath(REP1024("aaaa"), REP1024("bbbb"), - REP1024("aaaa") "/" REP1024("bbbb")); - check_joinpath(REP1024("/aaaa"), REP1024("/bbbb"), - REP1024("/aaaa") REP1024("/bbbb")); -} - -/* properly join path components for more than one path */ -void test_core_path__06_long_joins(void) -{ - check_joinpath_n("", "", "", "", ""); - check_joinpath_n("", "a", "", "", "a/"); - check_joinpath_n("a", "", "", "", "a/"); - check_joinpath_n("", "", "", "a", "a"); - check_joinpath_n("a", "b", "", "/c/d/", "a/b/c/d/"); - check_joinpath_n("a", "b", "", "/c/d", "a/b/c/d"); - check_joinpath_n("abcd", "efgh", "ijkl", "mnop", "abcd/efgh/ijkl/mnop"); - check_joinpath_n("abcd/", "efgh/", "ijkl/", "mnop/", "abcd/efgh/ijkl/mnop/"); - check_joinpath_n("/abcd/", "/efgh/", "/ijkl/", "/mnop/", "/abcd/efgh/ijkl/mnop/"); - - check_joinpath_n(REP1024("a"), REP1024("b"), REP1024("c"), REP1024("d"), - REP1024("a") "/" REP1024("b") "/" - REP1024("c") "/" REP1024("d")); - check_joinpath_n(REP1024("/a"), REP1024("/b"), REP1024("/c"), REP1024("/d"), - REP1024("/a") REP1024("/b") - REP1024("/c") REP1024("/d")); -} - - -static void -check_path_to_dir( - const char* path, - const char* expected) -{ - git_buf tgt = GIT_BUF_INIT; - - git_buf_sets(&tgt, path); - cl_git_pass(git_path_to_dir(&tgt)); - cl_assert_equal_s(expected, tgt.ptr); - - git_buf_free(&tgt); -} - -static void -check_string_to_dir( - const char* path, - size_t maxlen, - const char* expected) -{ - size_t len = strlen(path); - char *buf = git__malloc(len + 2); - cl_assert(buf); - - strncpy(buf, path, len + 2); - - git_path_string_to_dir(buf, maxlen); - - cl_assert_equal_s(expected, buf); - - git__free(buf); -} - -/* convert paths to dirs */ -void test_core_path__07_path_to_dir(void) -{ - check_path_to_dir("", ""); - check_path_to_dir(".", "./"); - check_path_to_dir("./", "./"); - check_path_to_dir("a/", "a/"); - check_path_to_dir("ab", "ab/"); - /* make sure we try just under and just over an expansion that will - * require a realloc - */ - check_path_to_dir("abcdef", "abcdef/"); - check_path_to_dir("abcdefg", "abcdefg/"); - check_path_to_dir("abcdefgh", "abcdefgh/"); - check_path_to_dir("abcdefghi", "abcdefghi/"); - check_path_to_dir(REP1024("abcd") "/", REP1024("abcd") "/"); - check_path_to_dir(REP1024("abcd"), REP1024("abcd") "/"); - - check_string_to_dir("", 1, ""); - check_string_to_dir(".", 1, "."); - check_string_to_dir(".", 2, "./"); - check_string_to_dir(".", 3, "./"); - check_string_to_dir("abcd", 3, "abcd"); - check_string_to_dir("abcd", 4, "abcd"); - check_string_to_dir("abcd", 5, "abcd/"); - check_string_to_dir("abcd", 6, "abcd/"); -} - -/* join path to itself */ -void test_core_path__08_self_join(void) -{ - git_buf path = GIT_BUF_INIT; - size_t asize = 0; - - asize = path.asize; - cl_git_pass(git_buf_sets(&path, "/foo")); - cl_assert_equal_s(path.ptr, "/foo"); - cl_assert(asize < path.asize); - - asize = path.asize; - cl_git_pass(git_buf_joinpath(&path, path.ptr, "this is a new string")); - cl_assert_equal_s(path.ptr, "/foo/this is a new string"); - cl_assert(asize < path.asize); - - asize = path.asize; - cl_git_pass(git_buf_joinpath(&path, path.ptr, "/grow the buffer, grow the buffer, grow the buffer")); - cl_assert_equal_s(path.ptr, "/foo/this is a new string/grow the buffer, grow the buffer, grow the buffer"); - cl_assert(asize < path.asize); - - git_buf_free(&path); - cl_git_pass(git_buf_sets(&path, "/foo/bar")); - - cl_git_pass(git_buf_joinpath(&path, path.ptr + 4, "baz")); - cl_assert_equal_s(path.ptr, "/bar/baz"); - - asize = path.asize; - cl_git_pass(git_buf_joinpath(&path, path.ptr + 4, "somethinglongenoughtorealloc")); - cl_assert_equal_s(path.ptr, "/baz/somethinglongenoughtorealloc"); - cl_assert(asize < path.asize); - - git_buf_free(&path); -} - -static void check_percent_decoding(const char *expected_result, const char *input) -{ - git_buf buf = GIT_BUF_INIT; - - cl_git_pass(git__percent_decode(&buf, input)); - cl_assert_equal_s(expected_result, git_buf_cstr(&buf)); - - git_buf_free(&buf); -} - -void test_core_path__09_percent_decode(void) -{ - check_percent_decoding("abcd", "abcd"); - check_percent_decoding("a2%", "a2%"); - check_percent_decoding("a2%3", "a2%3"); - check_percent_decoding("a2%%3", "a2%%3"); - check_percent_decoding("a2%3z", "a2%3z"); - check_percent_decoding("a,", "a%2c"); - check_percent_decoding("a21", "a2%31"); - check_percent_decoding("a2%1", "a2%%31"); - check_percent_decoding("a bc ", "a%20bc%20"); - check_percent_decoding("Vicent Mart" "\355", "Vicent%20Mart%ED"); -} - -static void check_fromurl(const char *expected_result, const char *input, int should_fail) -{ - git_buf buf = GIT_BUF_INIT; - - assert(should_fail || expected_result); - - if (!should_fail) { - cl_git_pass(git_path_fromurl(&buf, input)); - cl_assert_equal_s(expected_result, git_buf_cstr(&buf)); - } else - cl_git_fail(git_path_fromurl(&buf, input)); - - git_buf_free(&buf); -} - -#ifdef GIT_WIN32 -#define ABS_PATH_MARKER "" -#else -#define ABS_PATH_MARKER "/" -#endif - -void test_core_path__10_fromurl(void) -{ - /* Failing cases */ - check_fromurl(NULL, "a", 1); - check_fromurl(NULL, "http:///c:/Temp%20folder/note.txt", 1); - check_fromurl(NULL, "file://c:/Temp%20folder/note.txt", 1); - check_fromurl(NULL, "file:////c:/Temp%20folder/note.txt", 1); - check_fromurl(NULL, "file:///", 1); - check_fromurl(NULL, "file:////", 1); - check_fromurl(NULL, "file://servername/c:/Temp%20folder/note.txt", 1); - - /* Passing cases */ - check_fromurl(ABS_PATH_MARKER "c:/Temp folder/note.txt", "file:///c:/Temp%20folder/note.txt", 0); - check_fromurl(ABS_PATH_MARKER "c:/Temp folder/note.txt", "file://localhost/c:/Temp%20folder/note.txt", 0); - check_fromurl(ABS_PATH_MARKER "c:/Temp+folder/note.txt", "file:///c:/Temp+folder/note.txt", 0); - check_fromurl(ABS_PATH_MARKER "a", "file:///a", 0); -} - -typedef struct { - int expect_idx; - char **expect; -} check_walkup_info; - -static int check_one_walkup_step(void *ref, git_buf *path) -{ - check_walkup_info *info = (check_walkup_info *)ref; - cl_assert(info->expect[info->expect_idx] != NULL); - cl_assert_equal_s(info->expect[info->expect_idx], path->ptr); - info->expect_idx++; - return 0; -} - -void test_core_path__11_walkup(void) -{ - git_buf p = GIT_BUF_INIT; - char *expect[] = { - "/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL, - "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL, - "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL, - "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL, - "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL, - "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL, - "this is a path", NULL, - "///a///b///c///d///e///", "///a///b///c///d///", "///a///b///c///", "///a///b///", "///a///", "///", NULL, - NULL - }; - char *root[] = { NULL, NULL, "/", "", "/a/b", "/a/b/", NULL, NULL, NULL }; - int i, j; - check_walkup_info info; - - info.expect = expect; - - for (i = 0, j = 0; expect[i] != NULL; i++, j++) { - - git_buf_sets(&p, expect[i]); - - info.expect_idx = i; - cl_git_pass( - git_path_walk_up(&p, root[j], check_one_walkup_step, &info) - ); - - cl_assert_equal_s(p.ptr, expect[i]); - - /* skip to next run of expectations */ - while (expect[i] != NULL) i++; - } - - git_buf_free(&p); -} - -void test_core_path__12_offset_to_path_root(void) -{ - cl_assert(git_path_root("non/rooted/path") == -1); - cl_assert(git_path_root("/rooted/path") == 0); - -#ifdef GIT_WIN32 - /* Windows specific tests */ - cl_assert(git_path_root("C:non/rooted/path") == -1); - cl_assert(git_path_root("C:/rooted/path") == 2); - cl_assert(git_path_root("//computername/sharefolder/resource") == 14); - cl_assert(git_path_root("//computername/sharefolder") == 14); - cl_assert(git_path_root("//computername") == -1); -#endif -} - -#define NON_EXISTING_FILEPATH "i_hope_i_do_not_exist" - -void test_core_path__13_cannot_prettify_a_non_existing_file(void) -{ - git_buf p = GIT_BUF_INIT; - - cl_must_pass(git_path_exists(NON_EXISTING_FILEPATH) == false); - cl_assert_equal_i(GIT_ENOTFOUND, git_path_prettify(&p, NON_EXISTING_FILEPATH, NULL)); - cl_assert_equal_i(GIT_ENOTFOUND, git_path_prettify(&p, NON_EXISTING_FILEPATH "/so-do-i", NULL)); - - git_buf_free(&p); -} - -void test_core_path__14_apply_relative(void) -{ - git_buf p = GIT_BUF_INIT; - - cl_git_pass(git_buf_sets(&p, "/this/is/a/base")); - - cl_git_pass(git_path_apply_relative(&p, "../test")); - cl_assert_equal_s("/this/is/a/test", p.ptr); - - cl_git_pass(git_path_apply_relative(&p, "../../the/./end")); - cl_assert_equal_s("/this/is/the/end", p.ptr); - - cl_git_pass(git_path_apply_relative(&p, "./of/this/../the/string")); - cl_assert_equal_s("/this/is/the/end/of/the/string", p.ptr); - - cl_git_pass(git_path_apply_relative(&p, "../../../../../..")); - cl_assert_equal_s("/this/", p.ptr); - - cl_git_pass(git_path_apply_relative(&p, "../")); - cl_assert_equal_s("/", p.ptr); - - cl_git_fail(git_path_apply_relative(&p, "../../..")); - - - cl_git_pass(git_buf_sets(&p, "d:/another/test")); - - cl_git_pass(git_path_apply_relative(&p, "../..")); - cl_assert_equal_s("d:/", p.ptr); - - cl_git_pass(git_path_apply_relative(&p, "from/here/to/../and/./back/.")); - cl_assert_equal_s("d:/from/here/and/back/", p.ptr); - - - cl_git_pass(git_buf_sets(&p, "https://my.url.com/test.git")); - - cl_git_pass(git_path_apply_relative(&p, "../another.git")); - cl_assert_equal_s("https://my.url.com/another.git", p.ptr); - - cl_git_pass(git_path_apply_relative(&p, "../full/path/url.patch")); - cl_assert_equal_s("https://my.url.com/full/path/url.patch", p.ptr); - - cl_git_pass(git_path_apply_relative(&p, "..")); - cl_assert_equal_s("https://my.url.com/full/path/", p.ptr); - - cl_git_pass(git_path_apply_relative(&p, "../../../")); - cl_assert_equal_s("https://", p.ptr); - - - cl_git_pass(git_buf_sets(&p, "../../this/is/relative")); - - cl_git_pass(git_path_apply_relative(&p, "../../preserves/the/prefix")); - cl_assert_equal_s("../../this/preserves/the/prefix", p.ptr); - - cl_git_pass(git_path_apply_relative(&p, "../../../../that")); - cl_assert_equal_s("../../that", p.ptr); - - cl_git_pass(git_path_apply_relative(&p, "../there")); - cl_assert_equal_s("../../there", p.ptr); - git_buf_free(&p); -} - -static void assert_resolve_relative( - git_buf *buf, const char *expected, const char *path) -{ - cl_git_pass(git_buf_sets(buf, path)); - cl_git_pass(git_path_resolve_relative(buf, 0)); - cl_assert_equal_s(expected, buf->ptr); -} - -void test_core_path__15_resolve_relative(void) -{ - git_buf buf = GIT_BUF_INIT; - - assert_resolve_relative(&buf, "", ""); - assert_resolve_relative(&buf, "", "."); - assert_resolve_relative(&buf, "", "./"); - assert_resolve_relative(&buf, "..", ".."); - assert_resolve_relative(&buf, "../", "../"); - assert_resolve_relative(&buf, "..", "./.."); - assert_resolve_relative(&buf, "../", "./../"); - assert_resolve_relative(&buf, "../", "../."); - assert_resolve_relative(&buf, "../", ".././"); - assert_resolve_relative(&buf, "../..", "../.."); - assert_resolve_relative(&buf, "../../", "../../"); - - assert_resolve_relative(&buf, "/", "/"); - assert_resolve_relative(&buf, "/", "/."); - - assert_resolve_relative(&buf, "", "a/.."); - assert_resolve_relative(&buf, "", "a/../"); - assert_resolve_relative(&buf, "", "a/../."); - - assert_resolve_relative(&buf, "/a", "/a"); - assert_resolve_relative(&buf, "/a/", "/a/."); - assert_resolve_relative(&buf, "/", "/a/../"); - assert_resolve_relative(&buf, "/", "/a/../."); - assert_resolve_relative(&buf, "/", "/a/.././"); - - assert_resolve_relative(&buf, "a", "a"); - assert_resolve_relative(&buf, "a/", "a/"); - assert_resolve_relative(&buf, "a/", "a/."); - assert_resolve_relative(&buf, "a/", "a/./"); - - assert_resolve_relative(&buf, "a/b", "a//b"); - assert_resolve_relative(&buf, "a/b/c", "a/b/c"); - assert_resolve_relative(&buf, "b/c", "./b/c"); - assert_resolve_relative(&buf, "a/c", "a/./c"); - assert_resolve_relative(&buf, "a/b/", "a/b/."); - - assert_resolve_relative(&buf, "/a/b/c", "///a/b/c"); - assert_resolve_relative(&buf, "/", "////"); - assert_resolve_relative(&buf, "/a", "///a"); - assert_resolve_relative(&buf, "/", "///."); - assert_resolve_relative(&buf, "/", "///a/.."); - - assert_resolve_relative(&buf, "../../path", "../../test//../././path"); - assert_resolve_relative(&buf, "../d", "a/b/../../../c/../d"); - - cl_git_pass(git_buf_sets(&buf, "/..")); - cl_git_fail(git_path_resolve_relative(&buf, 0)); - - cl_git_pass(git_buf_sets(&buf, "/./..")); - cl_git_fail(git_path_resolve_relative(&buf, 0)); - - cl_git_pass(git_buf_sets(&buf, "/.//..")); - cl_git_fail(git_path_resolve_relative(&buf, 0)); - - cl_git_pass(git_buf_sets(&buf, "/../.")); - cl_git_fail(git_path_resolve_relative(&buf, 0)); - - cl_git_pass(git_buf_sets(&buf, "/../.././../a")); - cl_git_fail(git_path_resolve_relative(&buf, 0)); - - cl_git_pass(git_buf_sets(&buf, "////..")); - cl_git_fail(git_path_resolve_relative(&buf, 0)); - - /* things that start with Windows network paths */ -#ifdef GIT_WIN32 - assert_resolve_relative(&buf, "//a/b/c", "//a/b/c"); - assert_resolve_relative(&buf, "//a/", "//a/b/.."); - assert_resolve_relative(&buf, "//a/b/c", "//a/Q/../b/x/y/../../c"); - - cl_git_pass(git_buf_sets(&buf, "//a/b/../..")); - cl_git_fail(git_path_resolve_relative(&buf, 0)); -#else - assert_resolve_relative(&buf, "/a/b/c", "//a/b/c"); - assert_resolve_relative(&buf, "/a/", "//a/b/.."); - assert_resolve_relative(&buf, "/a/b/c", "//a/Q/../b/x/y/../../c"); - assert_resolve_relative(&buf, "/", "//a/b/../.."); -#endif - - git_buf_free(&buf); -} diff --git a/tests-clar/core/pool.c b/tests-clar/core/pool.c deleted file mode 100644 index 3073c4a45..000000000 --- a/tests-clar/core/pool.c +++ /dev/null @@ -1,145 +0,0 @@ -#include "clar_libgit2.h" -#include "pool.h" -#include "git2/oid.h" - -void test_core_pool__0(void) -{ - int i; - git_pool p; - void *ptr; - - cl_git_pass(git_pool_init(&p, 1, 4000)); - - for (i = 1; i < 10000; i *= 2) { - ptr = git_pool_malloc(&p, i); - cl_assert(ptr != NULL); - cl_assert(git_pool__ptr_in_pool(&p, ptr)); - cl_assert(!git_pool__ptr_in_pool(&p, &i)); - } - - /* 1+2+4+8+16+32+64+128+256+512+1024 -> original block */ - /* 2048 -> 1 block */ - /* 4096 -> 1 block */ - /* 8192 -> 1 block */ - - cl_assert(git_pool__open_pages(&p) + git_pool__full_pages(&p) == 4); - - git_pool_clear(&p); -} - -void test_core_pool__1(void) -{ - int i; - git_pool p; - - cl_git_pass(git_pool_init(&p, 1, 4000)); - - for (i = 2010; i > 0; i--) - cl_assert(git_pool_malloc(&p, i) != NULL); - - /* with fixed page size, allocation must end up with these values */ - cl_assert(git_pool__open_pages(&p) == 1); - cl_assert(git_pool__full_pages(&p) == 505); - - git_pool_clear(&p); - - cl_git_pass(git_pool_init(&p, 1, 4100)); - - for (i = 2010; i > 0; i--) - cl_assert(git_pool_malloc(&p, i) != NULL); - - /* with fixed page size, allocation must end up with these values */ - cl_assert(git_pool__open_pages(&p) == 1); - cl_assert(git_pool__full_pages(&p) == 492); - - git_pool_clear(&p); -} - -static char to_hex[] = "0123456789abcdef"; - -void test_core_pool__2(void) -{ - git_pool p; - char oid_hex[GIT_OID_HEXSZ]; - git_oid *oid; - int i, j; - - memset(oid_hex, '0', sizeof(oid_hex)); - - cl_git_pass(git_pool_init(&p, sizeof(git_oid), 100)); - - for (i = 1000; i < 10000; i++) { - oid = git_pool_malloc(&p, 1); - cl_assert(oid != NULL); - - for (j = 0; j < 8; j++) - oid_hex[j] = to_hex[(i >> (4 * j)) & 0x0f]; - cl_git_pass(git_oid_fromstr(oid, oid_hex)); - } - - /* with fixed page size, allocation must end up with these values */ - cl_assert(git_pool__open_pages(&p) == 0); - cl_assert(git_pool__full_pages(&p) == 90); - - git_pool_clear(&p); -} - -void test_core_pool__free_list(void) -{ - int i; - git_pool p; - void *ptr, *ptrs[50]; - - cl_git_pass(git_pool_init(&p, 100, 100)); - - for (i = 0; i < 10; ++i) { - ptr = git_pool_malloc(&p, 1); - cl_assert(ptr != NULL); - } - cl_assert_equal_i(10, (int)p.items); - - for (i = 0; i < 50; ++i) { - ptrs[i] = git_pool_malloc(&p, 1); - cl_assert(ptrs[i] != NULL); - } - cl_assert_equal_i(60, (int)p.items); - - git_pool_free(&p, ptr); - cl_assert_equal_i(60, (int)p.items); - - git_pool_free_array(&p, 50, ptrs); - cl_assert_equal_i(60, (int)p.items); - - for (i = 0; i < 50; ++i) { - ptrs[i] = git_pool_malloc(&p, 1); - cl_assert(ptrs[i] != NULL); - } - cl_assert_equal_i(60, (int)p.items); - - for (i = 0; i < 111; ++i) { - ptr = git_pool_malloc(&p, 1); - cl_assert(ptr != NULL); - } - cl_assert_equal_i(170, (int)p.items); - - git_pool_free_array(&p, 50, ptrs); - cl_assert_equal_i(170, (int)p.items); - - for (i = 0; i < 50; ++i) { - ptrs[i] = git_pool_malloc(&p, 1); - cl_assert(ptrs[i] != NULL); - } - cl_assert_equal_i(170, (int)p.items); - - git_pool_clear(&p); -} - -void test_core_pool__strndup_limit(void) -{ - git_pool p; - - cl_git_pass(git_pool_init(&p, 1, 100)); - cl_assert(git_pool_strndup(&p, "foo", -1) == NULL); - git_pool_clear(&p); -} - diff --git a/tests-clar/core/posix.c b/tests-clar/core/posix.c deleted file mode 100644 index 1cef937cd..000000000 --- a/tests-clar/core/posix.c +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef _WIN32 -# include -# include -# include -#else -# include -# ifdef _MSC_VER -# pragma comment(lib, "ws2_32") -# endif -#endif - -#include "clar_libgit2.h" -#include "posix.h" - -void test_core_posix__initialize(void) -{ -#ifdef GIT_WIN32 - /* on win32, the WSA context needs to be initialized - * before any socket calls can be performed */ - WSADATA wsd; - - cl_git_pass(WSAStartup(MAKEWORD(2,2), &wsd)); - cl_assert(LOBYTE(wsd.wVersion) == 2 && HIBYTE(wsd.wVersion) == 2); -#endif -} - -static bool supports_ipv6(void) -{ -#ifdef GIT_WIN32 - /* IPv6 is supported on Vista and newer */ - return git_has_win32_version(6, 0, 0); -#else - return 1; -#endif -} - -void test_core_posix__inet_pton(void) -{ - struct in_addr addr; - struct in6_addr addr6; - size_t i; - - struct in_addr_data { - const char *p; - const uint8_t n[4]; - }; - - struct in6_addr_data { - const char *p; - const uint8_t n[16]; - }; - - static struct in_addr_data in_addr_data[] = { - { "0.0.0.0", { 0, 0, 0, 0 } }, - { "10.42.101.8", { 10, 42, 101, 8 } }, - { "127.0.0.1", { 127, 0, 0, 1 } }, - { "140.177.10.12", { 140, 177, 10, 12 } }, - { "204.232.175.90", { 204, 232, 175, 90 } }, - { "255.255.255.255", { 255, 255, 255, 255 } }, - }; - - static struct in6_addr_data in6_addr_data[] = { - { "::", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, - { "::1", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, - { "0:0:0:0:0:0:0:1", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, - { "2001:db8:8714:3a90::12", { 0x20, 0x01, 0x0d, 0xb8, 0x87, 0x14, 0x3a, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12 } }, - { "fe80::f8ba:c2d6:86be:3645", { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xba, 0xc2, 0xd6, 0x86, 0xbe, 0x36, 0x45 } }, - { "::ffff:204.152.189.116", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0x98, 0xbd, 0x74 } }, - }; - - /* Test some ipv4 addresses */ - for (i = 0; i < 6; i++) { - cl_assert(p_inet_pton(AF_INET, in_addr_data[i].p, &addr) == 1); - cl_assert(memcmp(&addr, in_addr_data[i].n, sizeof(struct in_addr)) == 0); - } - - /* Test some ipv6 addresses */ - if (supports_ipv6()) - { - for (i = 0; i < 6; i++) { - cl_assert(p_inet_pton(AF_INET6, in6_addr_data[i].p, &addr6) == 1); - cl_assert(memcmp(&addr6, in6_addr_data[i].n, sizeof(struct in6_addr)) == 0); - } - } - - /* Test some invalid strings */ - cl_assert(p_inet_pton(AF_INET, "", &addr) == 0); - cl_assert(p_inet_pton(AF_INET, "foo", &addr) == 0); - cl_assert(p_inet_pton(AF_INET, " 127.0.0.1", &addr) == 0); - cl_assert(p_inet_pton(AF_INET, "bar", &addr) == 0); - 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_assert_equal_i(EAFNOSUPPORT, errno); - - cl_git_fail(p_inet_pton(5, "315.124", NULL)); /* AF_CHAOS */ - cl_assert_equal_i(EAFNOSUPPORT, errno); -} diff --git a/tests-clar/core/rmdir.c b/tests-clar/core/rmdir.c deleted file mode 100644 index f0b0bfa42..000000000 --- a/tests-clar/core/rmdir.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" - -static const char *empty_tmp_dir = "test_gitfo_rmdir_recurs_test"; - -void test_core_rmdir__initialize(void) -{ - git_buf path = GIT_BUF_INIT; - - cl_must_pass(p_mkdir(empty_tmp_dir, 0777)); - - cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one")); - cl_must_pass(p_mkdir(path.ptr, 0777)); - - cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one/two_one")); - cl_must_pass(p_mkdir(path.ptr, 0777)); - - cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one/two_two")); - cl_must_pass(p_mkdir(path.ptr, 0777)); - - cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one/two_two/three")); - cl_must_pass(p_mkdir(path.ptr, 0777)); - - cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/two")); - cl_must_pass(p_mkdir(path.ptr, 0777)); - - git_buf_free(&path); -} - -/* make sure empty dir can be deleted recusively */ -void test_core_rmdir__delete_recursive(void) -{ - cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_EMPTY_HIERARCHY)); -} - -/* make sure non-empty dir cannot be deleted recusively */ -void test_core_rmdir__fail_to_delete_non_empty_dir(void) -{ - git_buf file = GIT_BUF_INIT; - - cl_git_pass(git_buf_joinpath(&file, empty_tmp_dir, "/two/file.txt")); - - cl_git_mkfile(git_buf_cstr(&file), "dummy"); - - cl_git_fail(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_EMPTY_HIERARCHY)); - - cl_must_pass(p_unlink(file.ptr)); - cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_EMPTY_HIERARCHY)); - - git_buf_free(&file); -} - -void test_core_rmdir__can_skip_non_empty_dir(void) -{ - git_buf file = GIT_BUF_INIT; - - cl_git_pass(git_buf_joinpath(&file, empty_tmp_dir, "/two/file.txt")); - - cl_git_mkfile(git_buf_cstr(&file), "dummy"); - - cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_SKIP_NONEMPTY)); - cl_assert(git_path_exists(git_buf_cstr(&file)) == true); - - cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_REMOVE_FILES)); - cl_assert(git_path_exists(empty_tmp_dir) == false); - - git_buf_free(&file); -} - -void test_core_rmdir__can_remove_empty_parents(void) -{ - git_buf file = GIT_BUF_INIT; - - cl_git_pass( - git_buf_joinpath(&file, empty_tmp_dir, "/one/two_two/three/file.txt")); - cl_git_mkfile(git_buf_cstr(&file), "dummy"); - cl_assert(git_path_isfile(git_buf_cstr(&file))); - - cl_git_pass(git_futils_rmdir_r("one/two_two/three/file.txt", empty_tmp_dir, - GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_EMPTY_PARENTS)); - - cl_assert(!git_path_exists(git_buf_cstr(&file))); - - git_buf_rtruncate_at_char(&file, '/'); /* three (only contained file.txt) */ - cl_assert(!git_path_exists(git_buf_cstr(&file))); - - git_buf_rtruncate_at_char(&file, '/'); /* two_two (only contained three) */ - cl_assert(!git_path_exists(git_buf_cstr(&file))); - - git_buf_rtruncate_at_char(&file, '/'); /* one (contained two_one also) */ - cl_assert(git_path_exists(git_buf_cstr(&file))); - - cl_assert(git_path_exists(empty_tmp_dir) == true); - - git_buf_free(&file); - - cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_EMPTY_HIERARCHY)); -} diff --git a/tests-clar/core/sortedcache.c b/tests-clar/core/sortedcache.c deleted file mode 100644 index c1869bee0..000000000 --- a/tests-clar/core/sortedcache.c +++ /dev/null @@ -1,363 +0,0 @@ -#include "clar_libgit2.h" -#include "sortedcache.h" - -static int name_only_cmp(const void *a, const void *b) -{ - return strcmp(a, b); -} - -void test_core_sortedcache__name_only(void) -{ - git_sortedcache *sc; - void *item; - size_t pos; - - cl_git_pass(git_sortedcache_new( - &sc, 0, NULL, NULL, name_only_cmp, NULL)); - - cl_git_pass(git_sortedcache_wlock(sc)); - cl_git_pass(git_sortedcache_upsert(&item, sc, "aaa")); - cl_git_pass(git_sortedcache_upsert(&item, sc, "bbb")); - cl_git_pass(git_sortedcache_upsert(&item, sc, "zzz")); - cl_git_pass(git_sortedcache_upsert(&item, sc, "mmm")); - cl_git_pass(git_sortedcache_upsert(&item, sc, "iii")); - git_sortedcache_wunlock(sc); - - cl_assert_equal_sz(5, git_sortedcache_entrycount(sc)); - - cl_assert((item = git_sortedcache_lookup(sc, "aaa")) != NULL); - cl_assert_equal_s("aaa", item); - cl_assert((item = git_sortedcache_lookup(sc, "mmm")) != NULL); - cl_assert_equal_s("mmm", item); - cl_assert((item = git_sortedcache_lookup(sc, "zzz")) != NULL); - cl_assert_equal_s("zzz", item); - cl_assert(git_sortedcache_lookup(sc, "qqq") == NULL); - - cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); - cl_assert_equal_s("aaa", item); - cl_assert((item = git_sortedcache_entry(sc, 1)) != NULL); - cl_assert_equal_s("bbb", item); - cl_assert((item = git_sortedcache_entry(sc, 2)) != NULL); - cl_assert_equal_s("iii", item); - cl_assert((item = git_sortedcache_entry(sc, 3)) != NULL); - cl_assert_equal_s("mmm", item); - cl_assert((item = git_sortedcache_entry(sc, 4)) != NULL); - cl_assert_equal_s("zzz", item); - cl_assert(git_sortedcache_entry(sc, 5) == NULL); - - cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "aaa")); - cl_assert_equal_sz(0, pos); - cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "iii")); - cl_assert_equal_sz(2, pos); - cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "zzz")); - cl_assert_equal_sz(4, pos); - cl_assert_equal_i( - GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "abc")); - - git_sortedcache_clear(sc, true); - - cl_assert_equal_sz(0, git_sortedcache_entrycount(sc)); - cl_assert(git_sortedcache_entry(sc, 0) == NULL); - cl_assert(git_sortedcache_lookup(sc, "aaa") == NULL); - cl_assert(git_sortedcache_entry(sc, 0) == NULL); - - git_sortedcache_free(sc); -} - -typedef struct { - int value; - char smaller_value; - char path[GIT_FLEX_ARRAY]; -} sortedcache_test_struct; - -static int sortedcache_test_struct_cmp(const void *a_, const void *b_) -{ - const sortedcache_test_struct *a = a_, *b = b_; - return strcmp(a->path, b->path); -} - -static void sortedcache_test_struct_free(void *payload, void *item_) -{ - sortedcache_test_struct *item = item_; - int *count = payload; - (*count)++; - item->smaller_value = 0; -} - -void test_core_sortedcache__in_memory(void) -{ - git_sortedcache *sc; - sortedcache_test_struct *item; - int free_count = 0; - - cl_git_pass(git_sortedcache_new( - &sc, offsetof(sortedcache_test_struct, path), - sortedcache_test_struct_free, &free_count, - sortedcache_test_struct_cmp, NULL)); - - cl_git_pass(git_sortedcache_wlock(sc)); - cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "aaa")); - item->value = 10; - item->smaller_value = 1; - cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "bbb")); - item->value = 20; - item->smaller_value = 2; - cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "zzz")); - item->value = 30; - item->smaller_value = 26; - cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "mmm")); - item->value = 40; - item->smaller_value = 14; - cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "iii")); - item->value = 50; - item->smaller_value = 9; - git_sortedcache_wunlock(sc); - - cl_assert_equal_sz(5, git_sortedcache_entrycount(sc)); - - cl_git_pass(git_sortedcache_rlock(sc)); - - cl_assert((item = git_sortedcache_lookup(sc, "aaa")) != NULL); - cl_assert_equal_s("aaa", item->path); - cl_assert_equal_i(10, item->value); - cl_assert((item = git_sortedcache_lookup(sc, "mmm")) != NULL); - cl_assert_equal_s("mmm", item->path); - cl_assert_equal_i(40, item->value); - cl_assert((item = git_sortedcache_lookup(sc, "zzz")) != NULL); - cl_assert_equal_s("zzz", item->path); - cl_assert_equal_i(30, item->value); - cl_assert(git_sortedcache_lookup(sc, "abc") == NULL); - - /* not on Windows: - * cl_git_pass(git_sortedcache_rlock(sc)); -- grab more than one - */ - - cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); - cl_assert_equal_s("aaa", item->path); - cl_assert_equal_i(10, item->value); - cl_assert((item = git_sortedcache_entry(sc, 1)) != NULL); - cl_assert_equal_s("bbb", item->path); - cl_assert_equal_i(20, item->value); - cl_assert((item = git_sortedcache_entry(sc, 2)) != NULL); - cl_assert_equal_s("iii", item->path); - cl_assert_equal_i(50, item->value); - cl_assert((item = git_sortedcache_entry(sc, 3)) != NULL); - cl_assert_equal_s("mmm", item->path); - cl_assert_equal_i(40, item->value); - cl_assert((item = git_sortedcache_entry(sc, 4)) != NULL); - cl_assert_equal_s("zzz", item->path); - cl_assert_equal_i(30, item->value); - cl_assert(git_sortedcache_entry(sc, 5) == NULL); - - git_sortedcache_runlock(sc); - /* git_sortedcache_runlock(sc); */ - - cl_assert_equal_i(0, free_count); - - git_sortedcache_clear(sc, true); - - cl_assert_equal_i(5, free_count); - - cl_assert_equal_sz(0, git_sortedcache_entrycount(sc)); - cl_assert(git_sortedcache_entry(sc, 0) == NULL); - cl_assert(git_sortedcache_lookup(sc, "aaa") == NULL); - cl_assert(git_sortedcache_entry(sc, 0) == NULL); - - free_count = 0; - - cl_git_pass(git_sortedcache_wlock(sc)); - cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "testing")); - item->value = 10; - item->smaller_value = 3; - cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "again")); - item->value = 20; - item->smaller_value = 1; - cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "final")); - item->value = 30; - item->smaller_value = 2; - git_sortedcache_wunlock(sc); - - cl_assert_equal_sz(3, git_sortedcache_entrycount(sc)); - - cl_assert((item = git_sortedcache_lookup(sc, "testing")) != NULL); - cl_assert_equal_s("testing", item->path); - cl_assert_equal_i(10, item->value); - cl_assert((item = git_sortedcache_lookup(sc, "again")) != NULL); - cl_assert_equal_s("again", item->path); - cl_assert_equal_i(20, item->value); - cl_assert((item = git_sortedcache_lookup(sc, "final")) != NULL); - cl_assert_equal_s("final", item->path); - cl_assert_equal_i(30, item->value); - cl_assert(git_sortedcache_lookup(sc, "zzz") == NULL); - - cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); - cl_assert_equal_s("again", item->path); - cl_assert_equal_i(20, item->value); - cl_assert((item = git_sortedcache_entry(sc, 1)) != NULL); - cl_assert_equal_s("final", item->path); - cl_assert_equal_i(30, item->value); - cl_assert((item = git_sortedcache_entry(sc, 2)) != NULL); - cl_assert_equal_s("testing", item->path); - cl_assert_equal_i(10, item->value); - cl_assert(git_sortedcache_entry(sc, 3) == NULL); - - { - size_t pos; - - cl_git_pass(git_sortedcache_wlock(sc)); - - cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "again")); - cl_assert_equal_sz(0, pos); - cl_git_pass(git_sortedcache_remove(sc, pos)); - cl_assert_equal_i( - GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "again")); - - cl_assert_equal_sz(2, git_sortedcache_entrycount(sc)); - - cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "testing")); - cl_assert_equal_sz(1, pos); - cl_git_pass(git_sortedcache_remove(sc, pos)); - cl_assert_equal_i( - GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "testing")); - - cl_assert_equal_sz(1, git_sortedcache_entrycount(sc)); - - cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "final")); - cl_assert_equal_sz(0, pos); - cl_git_pass(git_sortedcache_remove(sc, pos)); - cl_assert_equal_i( - GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "final")); - - cl_assert_equal_sz(0, git_sortedcache_entrycount(sc)); - - git_sortedcache_wunlock(sc); - } - - git_sortedcache_free(sc); - - cl_assert_equal_i(3, free_count); -} - -static void sortedcache_test_reload(git_sortedcache *sc) -{ - int count = 0; - git_buf buf = GIT_BUF_INIT; - char *scan, *after; - sortedcache_test_struct *item; - - cl_assert(git_sortedcache_lockandload(sc, &buf) > 0); - - git_sortedcache_clear(sc, false); /* clear once we already have lock */ - - for (scan = buf.ptr; *scan; scan = after + 1) { - int val = strtol(scan, &after, 0); - cl_assert(after > scan); - scan = after; - - for (scan = after; git__isspace(*scan); ++scan) /* find start */; - for (after = scan; *after && *after != '\n'; ++after) /* find eol */; - *after = '\0'; - - cl_git_pass(git_sortedcache_upsert((void **)&item, sc, scan)); - - item->value = val; - item->smaller_value = (char)(count++); - } - - git_sortedcache_wunlock(sc); - - git_buf_free(&buf); -} - -void test_core_sortedcache__on_disk(void) -{ - git_sortedcache *sc; - sortedcache_test_struct *item; - int free_count = 0; - size_t pos; - - cl_git_mkfile("cacheitems.txt", "10 abc\n20 bcd\n30 cde\n"); - - cl_git_pass(git_sortedcache_new( - &sc, offsetof(sortedcache_test_struct, path), - sortedcache_test_struct_free, &free_count, - sortedcache_test_struct_cmp, "cacheitems.txt")); - - /* should need to reload the first time */ - - sortedcache_test_reload(sc); - - /* test what we loaded */ - - cl_assert_equal_sz(3, git_sortedcache_entrycount(sc)); - - cl_assert((item = git_sortedcache_lookup(sc, "abc")) != NULL); - cl_assert_equal_s("abc", item->path); - cl_assert_equal_i(10, item->value); - cl_assert((item = git_sortedcache_lookup(sc, "cde")) != NULL); - cl_assert_equal_s("cde", item->path); - cl_assert_equal_i(30, item->value); - cl_assert(git_sortedcache_lookup(sc, "aaa") == NULL); - - cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); - cl_assert_equal_s("abc", item->path); - cl_assert_equal_i(10, item->value); - cl_assert((item = git_sortedcache_entry(sc, 1)) != NULL); - cl_assert_equal_s("bcd", item->path); - cl_assert_equal_i(20, item->value); - cl_assert(git_sortedcache_entry(sc, 3) == NULL); - - /* should not need to reload this time */ - - cl_assert_equal_i(0, git_sortedcache_lockandload(sc, NULL)); - - /* rewrite ondisk file and reload */ - - cl_assert_equal_i(0, free_count); - - cl_git_rewritefile( - "cacheitems.txt", "100 abc\n200 zzz\n500 aaa\n10 final\n"); - sortedcache_test_reload(sc); - - cl_assert_equal_i(3, free_count); - - /* test what we loaded */ - - cl_assert_equal_sz(4, git_sortedcache_entrycount(sc)); - - cl_assert((item = git_sortedcache_lookup(sc, "abc")) != NULL); - cl_assert_equal_s("abc", item->path); - cl_assert_equal_i(100, item->value); - cl_assert((item = git_sortedcache_lookup(sc, "final")) != NULL); - cl_assert_equal_s("final", item->path); - cl_assert_equal_i(10, item->value); - cl_assert(git_sortedcache_lookup(sc, "cde") == NULL); - - cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); - cl_assert_equal_s("aaa", item->path); - cl_assert_equal_i(500, item->value); - cl_assert((item = git_sortedcache_entry(sc, 2)) != NULL); - cl_assert_equal_s("final", item->path); - cl_assert_equal_i(10, item->value); - cl_assert((item = git_sortedcache_entry(sc, 3)) != NULL); - cl_assert_equal_s("zzz", item->path); - cl_assert_equal_i(200, item->value); - - cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "aaa")); - cl_assert_equal_sz(0, pos); - cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "abc")); - cl_assert_equal_sz(1, pos); - cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "final")); - cl_assert_equal_sz(2, pos); - cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "zzz")); - cl_assert_equal_sz(3, pos); - cl_assert_equal_i( - GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "missing")); - cl_assert_equal_i( - GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "cde")); - - git_sortedcache_free(sc); - - cl_assert_equal_i(7, free_count); -} - diff --git a/tests-clar/core/stat.c b/tests-clar/core/stat.c deleted file mode 100644 index 2e4abfb79..000000000 --- a/tests-clar/core/stat.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "path.h" -#include "posix.h" - -void test_core_stat__initialize(void) -{ - cl_git_pass(git_futils_mkdir("root/d1/d2", NULL, 0755, GIT_MKDIR_PATH)); - cl_git_mkfile("root/file", "whatever\n"); - cl_git_mkfile("root/d1/file", "whatever\n"); -} - -void test_core_stat__cleanup(void) -{ - git_futils_rmdir_r("root", NULL, GIT_RMDIR_REMOVE_FILES); -} - -#define cl_assert_error(val) \ - do { err = errno; cl_assert_equal_i((val), err); } while (0) - -void test_core_stat__0(void) -{ - struct stat st; - int err; - - cl_assert_equal_i(0, p_lstat("root", &st)); - cl_assert(S_ISDIR(st.st_mode)); - cl_assert_error(0); - - cl_assert_equal_i(0, p_lstat("root/", &st)); - cl_assert(S_ISDIR(st.st_mode)); - cl_assert_error(0); - - cl_assert_equal_i(0, p_lstat("root/file", &st)); - cl_assert(S_ISREG(st.st_mode)); - cl_assert_error(0); - - cl_assert_equal_i(0, p_lstat("root/d1", &st)); - cl_assert(S_ISDIR(st.st_mode)); - cl_assert_error(0); - - cl_assert_equal_i(0, p_lstat("root/d1/", &st)); - cl_assert(S_ISDIR(st.st_mode)); - cl_assert_error(0); - - cl_assert_equal_i(0, p_lstat("root/d1/file", &st)); - cl_assert(S_ISREG(st.st_mode)); - cl_assert_error(0); - - cl_assert(p_lstat("root/missing", &st) < 0); - cl_assert_error(ENOENT); - - cl_assert(p_lstat("root/missing/but/could/be/created", &st) < 0); - cl_assert_error(ENOENT); - - cl_assert(p_lstat_posixly("root/missing/but/could/be/created", &st) < 0); - cl_assert_error(ENOENT); - - cl_assert(p_lstat("root/d1/missing", &st) < 0); - cl_assert_error(ENOENT); - - cl_assert(p_lstat("root/d1/missing/deeper/path", &st) < 0); - cl_assert_error(ENOENT); - - cl_assert(p_lstat_posixly("root/d1/missing/deeper/path", &st) < 0); - cl_assert_error(ENOENT); - - cl_assert(p_lstat_posixly("root/d1/file/deeper/path", &st) < 0); - cl_assert_error(ENOTDIR); - - cl_assert(p_lstat("root/file/invalid", &st) < 0); -#ifdef GIT_WIN32 - cl_assert_error(ENOENT); -#else - cl_assert_error(ENOTDIR); -#endif - - cl_assert(p_lstat_posixly("root/file/invalid", &st) < 0); - cl_assert_error(ENOTDIR); - - cl_assert(p_lstat("root/file/invalid/deeper_path", &st) < 0); -#ifdef GIT_WIN32 - cl_assert_error(ENOENT); -#else - cl_assert_error(ENOTDIR); -#endif - - cl_assert(p_lstat_posixly("root/file/invalid/deeper_path", &st) < 0); - cl_assert_error(ENOTDIR); - - cl_assert(p_lstat_posixly("root/d1/file/extra", &st) < 0); - cl_assert_error(ENOTDIR); - - cl_assert(p_lstat_posixly("root/d1/file/further/invalid/items", &st) < 0); - cl_assert_error(ENOTDIR); -} - diff --git a/tests-clar/core/string.c b/tests-clar/core/string.c deleted file mode 100644 index ec9575685..000000000 --- a/tests-clar/core/string.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "clar_libgit2.h" - -/* compare prefixes */ -void test_core_string__0(void) -{ - cl_assert(git__prefixcmp("", "") == 0); - cl_assert(git__prefixcmp("a", "") == 0); - cl_assert(git__prefixcmp("", "a") < 0); - cl_assert(git__prefixcmp("a", "b") < 0); - cl_assert(git__prefixcmp("b", "a") > 0); - cl_assert(git__prefixcmp("ab", "a") == 0); - cl_assert(git__prefixcmp("ab", "ac") < 0); - cl_assert(git__prefixcmp("ab", "aa") > 0); -} - -/* compare suffixes */ -void test_core_string__1(void) -{ - cl_assert(git__suffixcmp("", "") == 0); - cl_assert(git__suffixcmp("a", "") == 0); - cl_assert(git__suffixcmp("", "a") < 0); - cl_assert(git__suffixcmp("a", "b") < 0); - cl_assert(git__suffixcmp("b", "a") > 0); - cl_assert(git__suffixcmp("ba", "a") == 0); - cl_assert(git__suffixcmp("zaa", "ac") < 0); - cl_assert(git__suffixcmp("zaz", "ac") > 0); -} - -/* compare icase sorting with case equality */ -void test_core_string__2(void) -{ - cl_assert(git__strcasesort_cmp("", "") == 0); - cl_assert(git__strcasesort_cmp("foo", "foo") == 0); - cl_assert(git__strcasesort_cmp("foo", "bar") > 0); - cl_assert(git__strcasesort_cmp("bar", "foo") < 0); - cl_assert(git__strcasesort_cmp("foo", "FOO") > 0); - cl_assert(git__strcasesort_cmp("FOO", "foo") < 0); - cl_assert(git__strcasesort_cmp("foo", "BAR") > 0); - cl_assert(git__strcasesort_cmp("BAR", "foo") < 0); - cl_assert(git__strcasesort_cmp("fooBar", "foobar") < 0); -} diff --git a/tests-clar/core/strmap.c b/tests-clar/core/strmap.c deleted file mode 100644 index f34a4f89f..000000000 --- a/tests-clar/core/strmap.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "clar_libgit2.h" -#include "strmap.h" - -GIT__USE_STRMAP; - -void test_core_strmap__0(void) -{ - git_strmap *table = git_strmap_alloc(); - cl_assert(table != NULL); - cl_assert(git_strmap_num_entries(table) == 0); - git_strmap_free(table); -} - -static void insert_strings(git_strmap *table, int count) -{ - int i, j, over, err; - char *str; - - for (i = 0; i < count; ++i) { - str = malloc(10); - for (j = 0; j < 10; ++j) - str[j] = 'a' + (i % 26); - str[9] = '\0'; - - /* if > 26, then encode larger value in first letters */ - for (j = 0, over = i / 26; over > 0; j++, over = over / 26) - str[j] = 'A' + (over % 26); - - git_strmap_insert(table, str, str, err); - cl_assert(err >= 0); - } - - cl_assert((int)git_strmap_num_entries(table) == count); -} - -void test_core_strmap__1(void) -{ - int i; - char *str; - git_strmap *table = git_strmap_alloc(); - cl_assert(table != NULL); - - insert_strings(table, 20); - - cl_assert(git_strmap_exists(table, "aaaaaaaaa")); - cl_assert(git_strmap_exists(table, "ggggggggg")); - cl_assert(!git_strmap_exists(table, "aaaaaaaab")); - cl_assert(!git_strmap_exists(table, "abcdefghi")); - - i = 0; - git_strmap_foreach_value(table, str, { i++; free(str); }); - cl_assert(i == 20); - - git_strmap_free(table); -} - -void test_core_strmap__2(void) -{ - khiter_t pos; - int i; - char *str; - git_strmap *table = git_strmap_alloc(); - cl_assert(table != NULL); - - insert_strings(table, 20); - - cl_assert(git_strmap_exists(table, "aaaaaaaaa")); - cl_assert(git_strmap_exists(table, "ggggggggg")); - cl_assert(!git_strmap_exists(table, "aaaaaaaab")); - cl_assert(!git_strmap_exists(table, "abcdefghi")); - - cl_assert(git_strmap_exists(table, "bbbbbbbbb")); - pos = git_strmap_lookup_index(table, "bbbbbbbbb"); - cl_assert(git_strmap_valid_index(table, pos)); - cl_assert_equal_s(git_strmap_value_at(table, pos), "bbbbbbbbb"); - free(git_strmap_value_at(table, pos)); - git_strmap_delete_at(table, pos); - - cl_assert(!git_strmap_exists(table, "bbbbbbbbb")); - - i = 0; - git_strmap_foreach_value(table, str, { i++; free(str); }); - cl_assert(i == 19); - - git_strmap_free(table); -} - -void test_core_strmap__3(void) -{ - int i; - char *str; - git_strmap *table = git_strmap_alloc(); - cl_assert(table != NULL); - - insert_strings(table, 10000); - - i = 0; - git_strmap_foreach_value(table, str, { i++; free(str); }); - cl_assert(i == 10000); - - git_strmap_free(table); -} diff --git a/tests-clar/core/strtol.c b/tests-clar/core/strtol.c deleted file mode 100644 index 8765e042b..000000000 --- a/tests-clar/core/strtol.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "clar_libgit2.h" - -void test_core_strtol__int32(void) -{ - int32_t i; - - cl_git_pass(git__strtol32(&i, "123", NULL, 10)); - cl_assert(i == 123); - cl_git_pass(git__strtol32(&i, " +123 ", NULL, 10)); - cl_assert(i == 123); - cl_git_pass(git__strtol32(&i, " +2147483647 ", NULL, 10)); - cl_assert(i == 2147483647); - cl_git_pass(git__strtol32(&i, " -2147483648 ", NULL, 10)); - cl_assert(i == -2147483648LL); - - cl_git_fail(git__strtol32(&i, " 2147483657 ", NULL, 10)); - cl_git_fail(git__strtol32(&i, " -2147483657 ", NULL, 10)); -} - -void test_core_strtol__int64(void) -{ - int64_t i; - - cl_git_pass(git__strtol64(&i, "123", NULL, 10)); - cl_assert(i == 123); - cl_git_pass(git__strtol64(&i, " +123 ", NULL, 10)); - cl_assert(i == 123); - cl_git_pass(git__strtol64(&i, " +2147483647 ", NULL, 10)); - cl_assert(i == 2147483647); - cl_git_pass(git__strtol64(&i, " -2147483648 ", NULL, 10)); - cl_assert(i == -2147483648LL); - cl_git_pass(git__strtol64(&i, " 2147483657 ", NULL, 10)); - cl_assert(i == 2147483657LL); - cl_git_pass(git__strtol64(&i, " -2147483657 ", NULL, 10)); - cl_assert(i == -2147483657LL); -} - diff --git a/tests-clar/core/vector.c b/tests-clar/core/vector.c deleted file mode 100644 index db52c004f..000000000 --- a/tests-clar/core/vector.c +++ /dev/null @@ -1,275 +0,0 @@ -#include "clar_libgit2.h" -#include "vector.h" - -/* initial size of 1 would cause writing past array bounds */ -void test_core_vector__0(void) -{ - git_vector x; - int i; - git_vector_init(&x, 1, NULL); - for (i = 0; i < 10; ++i) { - git_vector_insert(&x, (void*) 0xabc); - } - git_vector_free(&x); -} - - -/* don't read past array bounds on remove() */ -void test_core_vector__1(void) -{ - git_vector x; - // make initial capacity exact for our insertions. - git_vector_init(&x, 3, NULL); - git_vector_insert(&x, (void*) 0xabc); - git_vector_insert(&x, (void*) 0xdef); - git_vector_insert(&x, (void*) 0x123); - - git_vector_remove(&x, 0); // used to read past array bounds. - git_vector_free(&x); -} - - -static int test_cmp(const void *a, const void *b) -{ - return *(const int *)a - *(const int *)b; -} - -/* remove duplicates */ -void test_core_vector__2(void) -{ - git_vector x; - int *ptrs[2]; - - ptrs[0] = git__malloc(sizeof(int)); - ptrs[1] = git__malloc(sizeof(int)); - - *ptrs[0] = 2; - *ptrs[1] = 1; - - cl_git_pass(git_vector_init(&x, 5, test_cmp)); - cl_git_pass(git_vector_insert(&x, ptrs[0])); - cl_git_pass(git_vector_insert(&x, ptrs[1])); - cl_git_pass(git_vector_insert(&x, ptrs[1])); - cl_git_pass(git_vector_insert(&x, ptrs[0])); - cl_git_pass(git_vector_insert(&x, ptrs[1])); - cl_assert(x.length == 5); - - git_vector_uniq(&x, NULL); - cl_assert(x.length == 2); - - git_vector_free(&x); - - git__free(ptrs[0]); - git__free(ptrs[1]); -} - - -static int compare_them(const void *a, const void *b) -{ - return (int)((long)a - (long)b); -} - -/* insert_sorted */ -void test_core_vector__3(void) -{ - git_vector x; - long i; - git_vector_init(&x, 1, &compare_them); - - for (i = 0; i < 10; i += 2) { - git_vector_insert_sorted(&x, (void*)(i + 1), NULL); - } - - for (i = 9; i > 0; i -= 2) { - git_vector_insert_sorted(&x, (void*)(i + 1), NULL); - } - - cl_assert(x.length == 10); - for (i = 0; i < 10; ++i) { - cl_assert(git_vector_get(&x, i) == (void*)(i + 1)); - } - - git_vector_free(&x); -} - -/* insert_sorted with duplicates */ -void test_core_vector__4(void) -{ - git_vector x; - long i; - git_vector_init(&x, 1, &compare_them); - - for (i = 0; i < 10; i += 2) { - git_vector_insert_sorted(&x, (void*)(i + 1), NULL); - } - - for (i = 9; i > 0; i -= 2) { - git_vector_insert_sorted(&x, (void*)(i + 1), NULL); - } - - for (i = 0; i < 10; i += 2) { - git_vector_insert_sorted(&x, (void*)(i + 1), NULL); - } - - for (i = 9; i > 0; i -= 2) { - git_vector_insert_sorted(&x, (void*)(i + 1), NULL); - } - - cl_assert(x.length == 20); - for (i = 0; i < 20; ++i) { - cl_assert(git_vector_get(&x, i) == (void*)(i / 2 + 1)); - } - - git_vector_free(&x); -} - -typedef struct { - int content; - int count; -} my_struct; - -static int _struct_count = 0; - -static int compare_structs(const void *a, const void *b) -{ - return ((const my_struct *)a)->content - - ((const my_struct *)b)->content; -} - -static int merge_structs(void **old_raw, void *new) -{ - my_struct *old = *(my_struct **)old_raw; - cl_assert(((my_struct *)old)->content == ((my_struct *)new)->content); - ((my_struct *)old)->count += 1; - git__free(new); - _struct_count--; - return GIT_EEXISTS; -} - -static my_struct *alloc_struct(int value) -{ - my_struct *st = git__malloc(sizeof(my_struct)); - st->content = value; - st->count = 0; - _struct_count++; - return st; -} - -/* insert_sorted with duplicates and special handling */ -void test_core_vector__5(void) -{ - git_vector x; - int i; - - git_vector_init(&x, 1, &compare_structs); - - for (i = 0; i < 10; i += 2) - git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs); - - for (i = 9; i > 0; i -= 2) - git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs); - - cl_assert(x.length == 10); - cl_assert(_struct_count == 10); - - for (i = 0; i < 10; i += 2) - git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs); - - for (i = 9; i > 0; i -= 2) - git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs); - - cl_assert(x.length == 10); - cl_assert(_struct_count == 10); - - for (i = 0; i < 10; ++i) { - cl_assert(((my_struct *)git_vector_get(&x, i))->content == i); - git__free(git_vector_get(&x, i)); - _struct_count--; - } - - git_vector_free(&x); -} - -static int remove_ones(const git_vector *v, size_t idx) -{ - return (git_vector_get(v, idx) == (void *)0x001); -} - -/* Test removal based on callback */ -void test_core_vector__remove_matching(void) -{ - git_vector x; - size_t i; - void *compare; - - git_vector_init(&x, 1, NULL); - git_vector_insert(&x, (void*) 0x001); - - cl_assert(x.length == 1); - git_vector_remove_matching(&x, remove_ones); - cl_assert(x.length == 0); - - git_vector_insert(&x, (void*) 0x001); - git_vector_insert(&x, (void*) 0x001); - git_vector_insert(&x, (void*) 0x001); - - cl_assert(x.length == 3); - git_vector_remove_matching(&x, remove_ones); - cl_assert(x.length == 0); - - git_vector_insert(&x, (void*) 0x002); - git_vector_insert(&x, (void*) 0x001); - git_vector_insert(&x, (void*) 0x002); - git_vector_insert(&x, (void*) 0x001); - - cl_assert(x.length == 4); - git_vector_remove_matching(&x, remove_ones); - cl_assert(x.length == 2); - - git_vector_foreach(&x, i, compare) { - cl_assert(compare != (void *)0x001); - } - - git_vector_clear(&x); - - git_vector_insert(&x, (void*) 0x001); - git_vector_insert(&x, (void*) 0x002); - git_vector_insert(&x, (void*) 0x002); - git_vector_insert(&x, (void*) 0x001); - - cl_assert(x.length == 4); - git_vector_remove_matching(&x, remove_ones); - cl_assert(x.length == 2); - - git_vector_foreach(&x, i, compare) { - cl_assert(compare != (void *)0x001); - } - - git_vector_clear(&x); - - git_vector_insert(&x, (void*) 0x002); - git_vector_insert(&x, (void*) 0x001); - git_vector_insert(&x, (void*) 0x002); - git_vector_insert(&x, (void*) 0x001); - - cl_assert(x.length == 4); - git_vector_remove_matching(&x, remove_ones); - cl_assert(x.length == 2); - - git_vector_foreach(&x, i, compare) { - cl_assert(compare != (void *)0x001); - } - - git_vector_clear(&x); - - git_vector_insert(&x, (void*) 0x002); - git_vector_insert(&x, (void*) 0x003); - git_vector_insert(&x, (void*) 0x002); - git_vector_insert(&x, (void*) 0x003); - - cl_assert(x.length == 4); - git_vector_remove_matching(&x, remove_ones); - cl_assert(x.length == 4); - - git_vector_free(&x); -} diff --git a/tests-clar/date/date.c b/tests-clar/date/date.c deleted file mode 100644 index 88881d1e1..000000000 --- a/tests-clar/date/date.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "clar_libgit2.h" - -#include "util.h" - -void test_date_date__overflow(void) -{ -#ifdef __LP64__ - git_time_t d2038, d2039; - - /* This is expected to fail on a 32-bit machine. */ - cl_git_pass(git__date_parse(&d2038, "2038-1-1")); - cl_git_pass(git__date_parse(&d2039, "2039-1-1")); - cl_assert(d2038 < d2039); -#endif -} diff --git a/tests-clar/diff/blob.c b/tests-clar/diff/blob.c deleted file mode 100644 index 93f20711c..000000000 --- a/tests-clar/diff/blob.c +++ /dev/null @@ -1,1067 +0,0 @@ -#include "clar_libgit2.h" -#include "diff_helpers.h" - -static git_repository *g_repo = NULL; -static diff_expects expected; -static git_diff_options opts; -static git_blob *d, *alien; - -static void quick_diff_blob_to_str( - const git_blob *blob, const char *blob_path, - const char *str, size_t len, const char *str_path) -{ - memset(&expected, 0, sizeof(expected)); - - if (str && !len) - len = strlen(str); - - cl_git_pass(git_diff_blob_to_buffer( - blob, blob_path, str, len, str_path, - &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); -} - -void test_diff_blob__initialize(void) -{ - git_oid oid; - - g_repo = cl_git_sandbox_init("attr"); - - cl_git_pass(git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION)); - opts.context_lines = 1; - - memset(&expected, 0, sizeof(expected)); - - /* tests/resources/attr/root_test4.txt */ - cl_git_pass(git_oid_fromstrn(&oid, "a0f7217a", 8)); - cl_git_pass(git_blob_lookup_prefix(&d, g_repo, &oid, 4)); - - /* alien.png */ - cl_git_pass(git_oid_fromstrn(&oid, "edf3dcee", 8)); - cl_git_pass(git_blob_lookup_prefix(&alien, g_repo, &oid, 4)); -} - -void test_diff_blob__cleanup(void) -{ - git_blob_free(d); - d = NULL; - - git_blob_free(alien); - alien = NULL; - - cl_git_sandbox_cleanup(); -} - -void test_diff_blob__can_compare_text_blobs(void) -{ - git_blob *a, *b, *c; - git_oid a_oid, b_oid, c_oid; - - /* tests/resources/attr/root_test1 */ - cl_git_pass(git_oid_fromstrn(&a_oid, "45141a79", 8)); - cl_git_pass(git_blob_lookup_prefix(&a, g_repo, &a_oid, 4)); - - /* tests/resources/attr/root_test2 */ - cl_git_pass(git_oid_fromstrn(&b_oid, "4d713dc4", 8)); - cl_git_pass(git_blob_lookup_prefix(&b, g_repo, &b_oid, 4)); - - /* tests/resources/attr/root_test3 */ - cl_git_pass(git_oid_fromstrn(&c_oid, "c96bbb2c2557a832", 16)); - cl_git_pass(git_blob_lookup_prefix(&c, g_repo, &c_oid, 8)); - - /* Doing the equivalent of a `git diff -U1` on these files */ - - /* diff on tests/resources/attr/root_test1 */ - cl_git_pass(git_diff_blobs( - a, NULL, b, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expected.files_binary); - - cl_assert_equal_i(1, expected.hunks); - cl_assert_equal_i(6, expected.lines); - cl_assert_equal_i(1, expected.line_ctxt); - cl_assert_equal_i(5, expected.line_adds); - cl_assert_equal_i(0, expected.line_dels); - - /* diff on tests/resources/attr/root_test2 */ - memset(&expected, 0, sizeof(expected)); - cl_git_pass(git_diff_blobs( - b, NULL, c, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expected.files_binary); - - cl_assert_equal_i(1, expected.hunks); - cl_assert_equal_i(15, expected.lines); - cl_assert_equal_i(3, expected.line_ctxt); - cl_assert_equal_i(9, expected.line_adds); - cl_assert_equal_i(3, expected.line_dels); - - /* diff on tests/resources/attr/root_test3 */ - memset(&expected, 0, sizeof(expected)); - cl_git_pass(git_diff_blobs( - a, NULL, c, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expected.files_binary); - - cl_assert_equal_i(1, expected.hunks); - cl_assert_equal_i(13, expected.lines); - cl_assert_equal_i(0, expected.line_ctxt); - cl_assert_equal_i(12, expected.line_adds); - cl_assert_equal_i(1, expected.line_dels); - - memset(&expected, 0, sizeof(expected)); - cl_git_pass(git_diff_blobs( - c, NULL, d, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expected.files_binary); - - cl_assert_equal_i(2, expected.hunks); - cl_assert_equal_i(14, expected.lines); - cl_assert_equal_i(4, expected.line_ctxt); - cl_assert_equal_i(6, expected.line_adds); - cl_assert_equal_i(4, expected.line_dels); - - git_blob_free(a); - git_blob_free(b); - git_blob_free(c); -} - -void test_diff_blob__can_compare_text_blobs_with_patch(void) -{ - git_blob *a, *b, *c; - git_oid a_oid, b_oid, c_oid; - git_patch *p; - const git_diff_delta *delta; - size_t tc, ta, td; - - /* tests/resources/attr/root_test1 */ - cl_git_pass(git_oid_fromstrn(&a_oid, "45141a79", 8)); - cl_git_pass(git_blob_lookup_prefix(&a, g_repo, &a_oid, 4)); - - /* tests/resources/attr/root_test2 */ - cl_git_pass(git_oid_fromstrn(&b_oid, "4d713dc4", 8)); - cl_git_pass(git_blob_lookup_prefix(&b, g_repo, &b_oid, 4)); - - /* tests/resources/attr/root_test3 */ - cl_git_pass(git_oid_fromstrn(&c_oid, "c96bbb2c2557a832", 16)); - cl_git_pass(git_blob_lookup_prefix(&c, g_repo, &c_oid, 8)); - - /* Doing the equivalent of a `git diff -U1` on these files */ - - /* diff on tests/resources/attr/root_test1 */ - cl_git_pass(git_patch_from_blobs(&p, a, NULL, b, NULL, &opts)); - - cl_assert(p != NULL); - - delta = git_patch_get_delta(p); - cl_assert(delta != NULL); - cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); - cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.oid)); - cl_assert_equal_sz(git_blob_rawsize(a), delta->old_file.size); - cl_assert(git_oid_equal(git_blob_id(b), &delta->new_file.oid)); - cl_assert_equal_sz(git_blob_rawsize(b), delta->new_file.size); - - cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); - cl_assert_equal_i(6, git_patch_num_lines_in_hunk(p, 0)); - - cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); - cl_assert_equal_i(1, (int)tc); - cl_assert_equal_i(5, (int)ta); - cl_assert_equal_i(0, (int)td); - - git_patch_free(p); - - /* diff on tests/resources/attr/root_test2 */ - cl_git_pass(git_patch_from_blobs(&p, b, NULL, c, NULL, &opts)); - - cl_assert(p != NULL); - - delta = git_patch_get_delta(p); - cl_assert(delta != NULL); - cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); - cl_assert(git_oid_equal(git_blob_id(b), &delta->old_file.oid)); - cl_assert_equal_sz(git_blob_rawsize(b), delta->old_file.size); - cl_assert(git_oid_equal(git_blob_id(c), &delta->new_file.oid)); - cl_assert_equal_sz(git_blob_rawsize(c), delta->new_file.size); - - cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); - cl_assert_equal_i(15, git_patch_num_lines_in_hunk(p, 0)); - - cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); - cl_assert_equal_i(3, (int)tc); - cl_assert_equal_i(9, (int)ta); - cl_assert_equal_i(3, (int)td); - - git_patch_free(p); - - /* diff on tests/resources/attr/root_test3 */ - cl_git_pass(git_patch_from_blobs(&p, a, NULL, c, NULL, &opts)); - - cl_assert(p != NULL); - - delta = git_patch_get_delta(p); - cl_assert(delta != NULL); - cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); - cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.oid)); - cl_assert_equal_sz(git_blob_rawsize(a), delta->old_file.size); - cl_assert(git_oid_equal(git_blob_id(c), &delta->new_file.oid)); - cl_assert_equal_sz(git_blob_rawsize(c), delta->new_file.size); - - cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); - cl_assert_equal_i(0, (int)tc); - cl_assert_equal_i(12, (int)ta); - cl_assert_equal_i(1, (int)td); - - git_patch_free(p); - - /* one more */ - cl_git_pass(git_patch_from_blobs(&p, c, NULL, d, NULL, &opts)); - - cl_assert(p != NULL); - - delta = git_patch_get_delta(p); - cl_assert(delta != NULL); - cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); - cl_assert(git_oid_equal(git_blob_id(c), &delta->old_file.oid)); - cl_assert_equal_sz(git_blob_rawsize(c), delta->old_file.size); - cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.oid)); - cl_assert_equal_sz(git_blob_rawsize(d), delta->new_file.size); - - cl_assert_equal_i(2, (int)git_patch_num_hunks(p)); - cl_assert_equal_i(5, git_patch_num_lines_in_hunk(p, 0)); - cl_assert_equal_i(9, git_patch_num_lines_in_hunk(p, 1)); - - cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); - cl_assert_equal_i(4, (int)tc); - cl_assert_equal_i(6, (int)ta); - cl_assert_equal_i(4, (int)td); - - git_patch_free(p); - - git_blob_free(a); - git_blob_free(b); - git_blob_free(c); -} - -void test_diff_blob__can_compare_against_null_blobs(void) -{ - git_blob *e = NULL; - - cl_git_pass(git_diff_blobs( - d, NULL, e, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(0, expected.files_binary); - - cl_assert_equal_i(1, expected.hunks); - cl_assert_equal_i(14, expected.hunk_old_lines); - cl_assert_equal_i(14, expected.lines); - cl_assert_equal_i(14, expected.line_dels); - - opts.flags |= GIT_DIFF_REVERSE; - memset(&expected, 0, sizeof(expected)); - - cl_git_pass(git_diff_blobs( - d, NULL, e, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, expected.files_binary); - - cl_assert_equal_i(1, expected.hunks); - cl_assert_equal_i(14, expected.hunk_new_lines); - cl_assert_equal_i(14, expected.lines); - cl_assert_equal_i(14, expected.line_adds); - - opts.flags ^= GIT_DIFF_REVERSE; - memset(&expected, 0, sizeof(expected)); - - cl_git_pass(git_diff_blobs( - alien, NULL, NULL, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.files_binary); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(0, expected.hunks); - cl_assert_equal_i(0, expected.lines); - - memset(&expected, 0, sizeof(expected)); - - cl_git_pass(git_diff_blobs( - NULL, NULL, alien, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.files_binary); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, expected.hunks); - cl_assert_equal_i(0, expected.lines); -} - -void test_diff_blob__can_compare_against_null_blobs_with_patch(void) -{ - git_blob *e = NULL; - git_patch *p; - const git_diff_delta *delta; - const git_diff_line *line; - int l, max_l; - - cl_git_pass(git_patch_from_blobs(&p, d, NULL, e, NULL, &opts)); - - cl_assert(p != NULL); - - delta = git_patch_get_delta(p); - cl_assert(delta != NULL); - cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); - cl_assert(git_oid_equal(git_blob_id(d), &delta->old_file.oid)); - cl_assert_equal_sz(git_blob_rawsize(d), delta->old_file.size); - cl_assert(git_oid_iszero(&delta->new_file.oid)); - cl_assert_equal_sz(0, delta->new_file.size); - - cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); - cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p, 0)); - - max_l = git_patch_num_lines_in_hunk(p, 0); - for (l = 0; l < max_l; ++l) { - cl_git_pass(git_patch_get_line_in_hunk(&line, p, 0, l)); - cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); - } - - git_patch_free(p); - - opts.flags |= GIT_DIFF_REVERSE; - - cl_git_pass(git_patch_from_blobs(&p, d, NULL, e, NULL, &opts)); - - cl_assert(p != NULL); - - delta = git_patch_get_delta(p); - cl_assert(delta != NULL); - cl_assert_equal_i(GIT_DELTA_ADDED, delta->status); - cl_assert(git_oid_iszero(&delta->old_file.oid)); - cl_assert_equal_sz(0, delta->old_file.size); - cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.oid)); - cl_assert_equal_sz(git_blob_rawsize(d), delta->new_file.size); - - cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); - cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p, 0)); - - max_l = git_patch_num_lines_in_hunk(p, 0); - for (l = 0; l < max_l; ++l) { - cl_git_pass(git_patch_get_line_in_hunk(&line, p, 0, l)); - cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); - } - - git_patch_free(p); - - opts.flags ^= GIT_DIFF_REVERSE; - - cl_git_pass(git_patch_from_blobs(&p, alien, NULL, NULL, NULL, &opts)); - - cl_assert(p != NULL); - - delta = git_patch_get_delta(p); - cl_assert(delta != NULL); - cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); - cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); - - cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); - - git_patch_free(p); - - cl_git_pass(git_patch_from_blobs(&p, NULL, NULL, alien, NULL, &opts)); - - cl_assert(p != NULL); - - delta = git_patch_get_delta(p); - cl_assert(delta != NULL); - cl_assert_equal_i(GIT_DELTA_ADDED, delta->status); - cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); - - cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); - - git_patch_free(p); -} - -static void assert_identical_blobs_comparison(diff_expects *expected) -{ - cl_assert_equal_i(1, expected->files); - cl_assert_equal_i(1, expected->file_status[GIT_DELTA_UNMODIFIED]); - cl_assert_equal_i(0, expected->hunks); - cl_assert_equal_i(0, expected->lines); -} - -void test_diff_blob__can_compare_identical_blobs(void) -{ - opts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; - - cl_git_pass(git_diff_blobs( - d, NULL, d, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - assert_identical_blobs_comparison(&expected); - cl_assert_equal_i(0, expected.files_binary); - - memset(&expected, 0, sizeof(expected)); - cl_git_pass(git_diff_blobs( - NULL, NULL, NULL, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - assert_identical_blobs_comparison(&expected); - cl_assert_equal_i(0, expected.files_binary); - - memset(&expected, 0, sizeof(expected)); - cl_git_pass(git_diff_blobs( - alien, NULL, alien, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - assert_identical_blobs_comparison(&expected); - cl_assert(expected.files_binary > 0); -} - -void test_diff_blob__can_compare_identical_blobs_with_patch(void) -{ - git_patch *p; - const git_diff_delta *delta; - - cl_git_pass(git_patch_from_blobs(&p, d, NULL, d, NULL, &opts)); - cl_assert(p != NULL); - - delta = git_patch_get_delta(p); - cl_assert(delta != NULL); - cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status); - cl_assert_equal_sz(delta->old_file.size, git_blob_rawsize(d)); - cl_assert(git_oid_equal(git_blob_id(d), &delta->old_file.oid)); - cl_assert_equal_sz(delta->new_file.size, git_blob_rawsize(d)); - cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.oid)); - - cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); - git_patch_free(p); - - cl_git_pass(git_patch_from_blobs(&p, NULL, NULL, NULL, NULL, &opts)); - cl_assert(p != NULL); - - delta = git_patch_get_delta(p); - cl_assert(delta != NULL); - cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status); - cl_assert_equal_sz(0, delta->old_file.size); - cl_assert(git_oid_iszero(&delta->old_file.oid)); - cl_assert_equal_sz(0, delta->new_file.size); - cl_assert(git_oid_iszero(&delta->new_file.oid)); - - cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); - git_patch_free(p); - - cl_git_pass(git_patch_from_blobs(&p, alien, NULL, alien, NULL, &opts)); - cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_patch_get_delta(p)->status); - cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); - git_patch_free(p); -} - -static void assert_binary_blobs_comparison(diff_expects *expected) -{ - cl_assert(expected->files_binary > 0); - - cl_assert_equal_i(1, expected->files); - cl_assert_equal_i(1, expected->file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expected->hunks); - cl_assert_equal_i(0, expected->lines); -} - -void test_diff_blob__can_compare_two_binary_blobs(void) -{ - git_blob *heart; - git_oid h_oid; - - /* heart.png */ - cl_git_pass(git_oid_fromstrn(&h_oid, "de863bff", 8)); - cl_git_pass(git_blob_lookup_prefix(&heart, g_repo, &h_oid, 4)); - - cl_git_pass(git_diff_blobs( - alien, NULL, heart, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - assert_binary_blobs_comparison(&expected); - - memset(&expected, 0, sizeof(expected)); - - cl_git_pass(git_diff_blobs( - heart, NULL, alien, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - assert_binary_blobs_comparison(&expected); - - git_blob_free(heart); -} - -void test_diff_blob__can_compare_a_binary_blob_and_a_text_blob(void) -{ - cl_git_pass(git_diff_blobs( - alien, NULL, d, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - assert_binary_blobs_comparison(&expected); - - memset(&expected, 0, sizeof(expected)); - - cl_git_pass(git_diff_blobs( - d, NULL, alien, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - assert_binary_blobs_comparison(&expected); -} - -/* - * $ git diff fe773770 a0f7217 - * diff --git a/fe773770 b/a0f7217 - * index fe77377..a0f7217 100644 - * --- a/fe773770 - * +++ b/a0f7217 - * @@ -1,6 +1,6 @@ - * Here is some stuff at the start - * - * -This should go in one hunk - * +This should go in one hunk (first) - * - * Some additional lines - * - * @@ -8,7 +8,7 @@ Down here below the other lines - * - * With even more at the end - * - * -Followed by a second hunk of stuff - * +Followed by a second hunk of stuff (second) - * - * That happens down here - */ -void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void) -{ - git_blob *old_d; - git_oid old_d_oid; - - opts.context_lines = 3; - - /* tests/resources/attr/root_test1 from commit f5b0af1 */ - cl_git_pass(git_oid_fromstrn(&old_d_oid, "fe773770", 8)); - cl_git_pass(git_blob_lookup_prefix(&old_d, g_repo, &old_d_oid, 4)); - - /* Test with default inter-hunk-context (not set) => default is 0 */ - cl_git_pass(git_diff_blobs( - old_d, NULL, d, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - cl_assert_equal_i(2, expected.hunks); - - /* Test with inter-hunk-context explicitly set to 0 */ - opts.interhunk_lines = 0; - memset(&expected, 0, sizeof(expected)); - cl_git_pass(git_diff_blobs( - old_d, NULL, d, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - cl_assert_equal_i(2, expected.hunks); - - /* Test with inter-hunk-context explicitly set to 1 */ - opts.interhunk_lines = 1; - memset(&expected, 0, sizeof(expected)); - cl_git_pass(git_diff_blobs( - old_d, NULL, d, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - - cl_assert_equal_i(1, expected.hunks); - - git_blob_free(old_d); -} - -void test_diff_blob__checks_options_version_too_low(void) -{ - const git_error *err; - - opts.version = 0; - cl_git_fail(git_diff_blobs( - d, NULL, alien, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); -} - -void test_diff_blob__checks_options_version_too_high(void) -{ - const git_error *err; - - opts.version = 1024; - cl_git_fail(git_diff_blobs( - d, NULL, alien, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); -} - -void test_diff_blob__can_correctly_detect_a_binary_blob_as_binary(void) -{ - /* alien.png */ - cl_assert_equal_i(true, git_blob_is_binary(alien)); -} - -void test_diff_blob__can_correctly_detect_a_textual_blob_as_non_binary(void) -{ - /* tests/resources/attr/root_test4.txt */ - cl_assert_equal_i(false, git_blob_is_binary(d)); -} - -/* - * git_diff_blob_to_buffer tests - */ - -static void assert_changed_single_one_line_file( - diff_expects *expected, git_delta_t mod) -{ - cl_assert_equal_i(1, expected->files); - cl_assert_equal_i(1, expected->file_status[mod]); - cl_assert_equal_i(1, expected->hunks); - cl_assert_equal_i(1, expected->lines); - - if (mod == GIT_DELTA_ADDED) - cl_assert_equal_i(1, expected->line_adds); - else if (mod == GIT_DELTA_DELETED) - cl_assert_equal_i(1, expected->line_dels); -} - -void test_diff_blob__can_compare_blob_to_buffer(void) -{ - git_blob *a; - git_oid a_oid; - const char *a_content = "Hello from the root\n"; - const char *b_content = "Hello from the root\n\nSome additional lines\n\nDown here below\n\n"; - - /* tests/resources/attr/root_test1 */ - cl_git_pass(git_oid_fromstrn(&a_oid, "45141a79", 8)); - cl_git_pass(git_blob_lookup_prefix(&a, g_repo, &a_oid, 4)); - - /* diff from blob a to content of b */ - quick_diff_blob_to_str(a, NULL, b_content, 0, NULL); - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expected.files_binary); - cl_assert_equal_i(1, expected.hunks); - cl_assert_equal_i(6, expected.lines); - cl_assert_equal_i(1, expected.line_ctxt); - cl_assert_equal_i(5, expected.line_adds); - cl_assert_equal_i(0, expected.line_dels); - - /* diff from blob a to content of a */ - opts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; - quick_diff_blob_to_str(a, NULL, a_content, 0, NULL); - assert_identical_blobs_comparison(&expected); - - /* diff from NULL blob to content of a */ - memset(&expected, 0, sizeof(expected)); - quick_diff_blob_to_str(NULL, NULL, a_content, 0, NULL); - assert_changed_single_one_line_file(&expected, GIT_DELTA_ADDED); - - /* diff from blob a to NULL buffer */ - memset(&expected, 0, sizeof(expected)); - quick_diff_blob_to_str(a, NULL, NULL, 0, NULL); - assert_changed_single_one_line_file(&expected, GIT_DELTA_DELETED); - - /* diff with reverse */ - opts.flags ^= GIT_DIFF_REVERSE; - - memset(&expected, 0, sizeof(expected)); - quick_diff_blob_to_str(a, NULL, NULL, 0, NULL); - assert_changed_single_one_line_file(&expected, GIT_DELTA_ADDED); - - git_blob_free(a); -} - -void test_diff_blob__can_compare_blob_to_buffer_with_patch(void) -{ - git_patch *p; - git_blob *a; - git_oid a_oid; - const char *a_content = "Hello from the root\n"; - const char *b_content = "Hello from the root\n\nSome additional lines\n\nDown here below\n\n"; - size_t tc, ta, td; - - /* tests/resources/attr/root_test1 */ - cl_git_pass(git_oid_fromstrn(&a_oid, "45141a79", 8)); - cl_git_pass(git_blob_lookup_prefix(&a, g_repo, &a_oid, 4)); - - /* diff from blob a to content of b */ - cl_git_pass(git_patch_from_blob_and_buffer( - &p, a, NULL, b_content, strlen(b_content), NULL, &opts)); - - cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_MODIFIED, git_patch_get_delta(p)->status); - cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); - cl_assert_equal_i(6, git_patch_num_lines_in_hunk(p, 0)); - - cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); - cl_assert_equal_i(1, (int)tc); - cl_assert_equal_i(5, (int)ta); - cl_assert_equal_i(0, (int)td); - - git_patch_free(p); - - /* diff from blob a to content of a */ - opts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; - cl_git_pass(git_patch_from_blob_and_buffer( - &p, a, NULL, a_content, strlen(a_content), NULL, &opts)); - cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_patch_get_delta(p)->status); - cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); - git_patch_free(p); - - /* diff from NULL blob to content of a */ - cl_git_pass(git_patch_from_blob_and_buffer( - &p, NULL, NULL, a_content, strlen(a_content), NULL, &opts)); - cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_ADDED, git_patch_get_delta(p)->status); - cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); - cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); - git_patch_free(p); - - /* diff from blob a to NULL buffer */ - cl_git_pass(git_patch_from_blob_and_buffer( - &p, a, NULL, NULL, 0, NULL, &opts)); - cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_DELETED, git_patch_get_delta(p)->status); - cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); - cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); - git_patch_free(p); - - /* diff with reverse */ - opts.flags ^= GIT_DIFF_REVERSE; - - cl_git_pass(git_patch_from_blob_and_buffer( - &p, a, NULL, NULL, 0, NULL, &opts)); - cl_assert(p != NULL); - cl_assert_equal_i(GIT_DELTA_ADDED, git_patch_get_delta(p)->status); - cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); - cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); - git_patch_free(p); - - git_blob_free(a); -} - -static void assert_one_modified_with_lines(diff_expects *expected, int lines) -{ - cl_assert_equal_i(1, expected->files); - cl_assert_equal_i(1, expected->file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expected->files_binary); - cl_assert_equal_i(lines, expected->lines); -} - -void test_diff_blob__binary_data_comparisons(void) -{ - git_blob *bin, *nonbin; - git_oid oid; - const char *nonbin_content = "Hello from the root\n"; - size_t nonbin_len = 20; - const char *bin_content = "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n"; - size_t bin_len = 33; - - opts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; - - cl_git_pass(git_oid_fromstrn(&oid, "45141a79", 8)); - cl_git_pass(git_blob_lookup_prefix(&nonbin, g_repo, &oid, 4)); - - cl_git_pass(git_oid_fromstrn(&oid, "b435cd56", 8)); - cl_git_pass(git_blob_lookup_prefix(&bin, g_repo, &oid, 4)); - - /* non-binary to reference content */ - - quick_diff_blob_to_str(nonbin, NULL, nonbin_content, nonbin_len, NULL); - assert_identical_blobs_comparison(&expected); - cl_assert_equal_i(0, expected.files_binary); - - /* binary to reference content */ - - quick_diff_blob_to_str(bin, NULL, bin_content, bin_len, NULL); - assert_identical_blobs_comparison(&expected); - - cl_assert_equal_i(1, expected.files_binary); - - /* non-binary to binary content */ - - quick_diff_blob_to_str(nonbin, NULL, bin_content, bin_len, NULL); - assert_binary_blobs_comparison(&expected); - - /* binary to non-binary content */ - - quick_diff_blob_to_str(bin, NULL, nonbin_content, nonbin_len, NULL); - assert_binary_blobs_comparison(&expected); - - /* non-binary to binary blob */ - - memset(&expected, 0, sizeof(expected)); - cl_git_pass(git_diff_blobs( - bin, NULL, nonbin, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - assert_binary_blobs_comparison(&expected); - - /* - * repeat with FORCE_TEXT - */ - - opts.flags |= GIT_DIFF_FORCE_TEXT; - - quick_diff_blob_to_str(bin, NULL, bin_content, bin_len, NULL); - assert_identical_blobs_comparison(&expected); - - quick_diff_blob_to_str(nonbin, NULL, bin_content, bin_len, NULL); - assert_one_modified_with_lines(&expected, 4); - - quick_diff_blob_to_str(bin, NULL, nonbin_content, nonbin_len, NULL); - assert_one_modified_with_lines(&expected, 4); - - memset(&expected, 0, sizeof(expected)); - cl_git_pass(git_diff_blobs( - bin, NULL, nonbin, NULL, &opts, - diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); - assert_one_modified_with_lines(&expected, 4); - - /* cleanup */ - git_blob_free(bin); - git_blob_free(nonbin); -} - -void test_diff_blob__using_path_and_attributes(void) -{ - git_config *cfg; - git_blob *bin, *nonbin; - git_oid oid; - const char *nonbin_content = "Hello from the root\n"; - const char *bin_content = - "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n"; - size_t bin_len = 33; - const char *changed; - git_patch *p; - char *pout; - - /* set up custom diff drivers and 'diff' attribute mappings for them */ - - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_set_bool(cfg, "diff.iam_binary.binary", 1)); - cl_git_pass(git_config_set_bool(cfg, "diff.iam_text.binary", 0)); - cl_git_pass(git_config_set_string( - cfg, "diff.iam_alphactx.xfuncname", "^[A-Za-z]")); - cl_git_pass(git_config_set_bool(cfg, "diff.iam_textalpha.binary", 0)); - cl_git_pass(git_config_set_string( - cfg, "diff.iam_textalpha.xfuncname", "^[A-Za-z]")); - cl_git_pass(git_config_set_string( - cfg, "diff.iam_numctx.funcname", "^[0-9]")); - cl_git_pass(git_config_set_bool(cfg, "diff.iam_textnum.binary", 0)); - cl_git_pass(git_config_set_string( - cfg, "diff.iam_textnum.funcname", "^[0-9]")); - git_config_free(cfg); - - cl_git_append2file( - "attr/.gitattributes", - "\n\n# test_diff_blob__using_path_and_attributes extra\n\n" - "*.binary diff=iam_binary\n" - "*.textary diff=iam_text\n" - "*.alphary diff=iam_alphactx\n" - "*.textalphary diff=iam_textalpha\n" - "*.textnumary diff=iam_textnum\n" - "*.numary diff=iam_numctx\n\n"); - - opts.context_lines = 0; - opts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; - - cl_git_pass(git_oid_fromstrn(&oid, "45141a79", 8)); - cl_git_pass(git_blob_lookup_prefix(&nonbin, g_repo, &oid, 4)); - /* 20b: "Hello from the root\n" */ - - cl_git_pass(git_oid_fromstrn(&oid, "b435cd56", 8)); - cl_git_pass(git_blob_lookup_prefix(&bin, g_repo, &oid, 4)); - /* 33b: "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\n0123456789\n" */ - - /* non-binary to reference content */ - - quick_diff_blob_to_str(nonbin, NULL, nonbin_content, 0, NULL); - assert_identical_blobs_comparison(&expected); - cl_assert_equal_i(0, expected.files_binary); - - /* binary to reference content */ - - quick_diff_blob_to_str(bin, NULL, bin_content, bin_len, NULL); - assert_identical_blobs_comparison(&expected); - cl_assert_equal_i(1, expected.files_binary); - - /* add some text */ - - changed = "Hello from the root\nMore lines\nAnd more\nGo here\n"; - - quick_diff_blob_to_str(nonbin, NULL, changed, 0, NULL); - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expected.files_binary); - cl_assert_equal_i(1, expected.hunks); - cl_assert_equal_i(3, expected.lines); - cl_assert_equal_i(0, expected.line_ctxt); - cl_assert_equal_i(3, expected.line_adds); - cl_assert_equal_i(0, expected.line_dels); - - quick_diff_blob_to_str(nonbin, "foo/bar.binary", changed, 0, NULL); - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, expected.files_binary); - cl_assert_equal_i(0, expected.hunks); - cl_assert_equal_i(0, expected.lines); - cl_assert_equal_i(0, expected.line_ctxt); - cl_assert_equal_i(0, expected.line_adds); - cl_assert_equal_i(0, expected.line_dels); - - quick_diff_blob_to_str(nonbin, "foo/bar.textary", changed, 0, NULL); - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expected.files_binary); - cl_assert_equal_i(1, expected.hunks); - cl_assert_equal_i(3, expected.lines); - cl_assert_equal_i(0, expected.line_ctxt); - cl_assert_equal_i(3, expected.line_adds); - cl_assert_equal_i(0, expected.line_dels); - - quick_diff_blob_to_str(nonbin, "foo/bar.alphary", changed, 0, NULL); - cl_assert_equal_i(1, expected.files); - cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expected.files_binary); - cl_assert_equal_i(1, expected.hunks); - cl_assert_equal_i(3, expected.lines); - cl_assert_equal_i(0, expected.line_ctxt); - cl_assert_equal_i(3, expected.line_adds); - cl_assert_equal_i(0, expected.line_dels); - - cl_git_pass(git_patch_from_blob_and_buffer( - &p, nonbin, "zzz.normal", changed, strlen(changed), NULL, &opts)); - cl_git_pass(git_patch_to_str(&pout, p)); - cl_assert_equal_s( - "diff --git a/zzz.normal b/zzz.normal\n" - "index 45141a7..75b0dbb 100644\n" - "--- a/zzz.normal\n" - "+++ b/zzz.normal\n" - "@@ -1,0 +2,3 @@ Hello from the root\n" - "+More lines\n" - "+And more\n" - "+Go here\n", pout); - git__free(pout); - git_patch_free(p); - - cl_git_pass(git_patch_from_blob_and_buffer( - &p, nonbin, "zzz.binary", changed, strlen(changed), NULL, &opts)); - cl_git_pass(git_patch_to_str(&pout, p)); - cl_assert_equal_s( - "diff --git a/zzz.binary b/zzz.binary\n" - "index 45141a7..75b0dbb 100644\n" - "Binary files a/zzz.binary and b/zzz.binary differ\n", pout); - git__free(pout); - git_patch_free(p); - - cl_git_pass(git_patch_from_blob_and_buffer( - &p, nonbin, "zzz.alphary", changed, strlen(changed), NULL, &opts)); - cl_git_pass(git_patch_to_str(&pout, p)); - cl_assert_equal_s( - "diff --git a/zzz.alphary b/zzz.alphary\n" - "index 45141a7..75b0dbb 100644\n" - "--- a/zzz.alphary\n" - "+++ b/zzz.alphary\n" - "@@ -1,0 +2,3 @@ Hello from the root\n" - "+More lines\n" - "+And more\n" - "+Go here\n", pout); - git__free(pout); - git_patch_free(p); - - cl_git_pass(git_patch_from_blob_and_buffer( - &p, nonbin, "zzz.numary", changed, strlen(changed), NULL, &opts)); - cl_git_pass(git_patch_to_str(&pout, p)); - cl_assert_equal_s( - "diff --git a/zzz.numary b/zzz.numary\n" - "index 45141a7..75b0dbb 100644\n" - "--- a/zzz.numary\n" - "+++ b/zzz.numary\n" - "@@ -1,0 +2,3 @@\n" - "+More lines\n" - "+And more\n" - "+Go here\n", pout); - git__free(pout); - git_patch_free(p); - - /* "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n" - * 33 bytes - */ - - changed = "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\nreplace a line\n"; - - cl_git_pass(git_patch_from_blob_and_buffer( - &p, bin, "zzz.normal", changed, 37, NULL, &opts)); - cl_git_pass(git_patch_to_str(&pout, p)); - cl_assert_equal_s( - "diff --git a/zzz.normal b/zzz.normal\n" - "index b435cd5..1604519 100644\n" - "Binary files a/zzz.normal and b/zzz.normal differ\n", pout); - git__free(pout); - git_patch_free(p); - - cl_git_pass(git_patch_from_blob_and_buffer( - &p, bin, "zzz.textary", changed, 37, NULL, &opts)); - cl_git_pass(git_patch_to_str(&pout, p)); - cl_assert_equal_s( - "diff --git a/zzz.textary b/zzz.textary\n" - "index b435cd5..1604519 100644\n" - "--- a/zzz.textary\n" - "+++ b/zzz.textary\n" - "@@ -3 +3 @@\n" - "-0123456789\n" - "+replace a line\n", pout); - git__free(pout); - git_patch_free(p); - - cl_git_pass(git_patch_from_blob_and_buffer( - &p, bin, "zzz.textalphary", changed, 37, NULL, &opts)); - cl_git_pass(git_patch_to_str(&pout, p)); - cl_assert_equal_s( - "diff --git a/zzz.textalphary b/zzz.textalphary\n" - "index b435cd5..1604519 100644\n" - "--- a/zzz.textalphary\n" - "+++ b/zzz.textalphary\n" - "@@ -3 +3 @@\n" - "-0123456789\n" - "+replace a line\n", pout); - git__free(pout); - git_patch_free(p); - - cl_git_pass(git_patch_from_blob_and_buffer( - &p, bin, "zzz.textnumary", changed, 37, NULL, &opts)); - cl_git_pass(git_patch_to_str(&pout, p)); - cl_assert_equal_s( - "diff --git a/zzz.textnumary b/zzz.textnumary\n" - "index b435cd5..1604519 100644\n" - "--- a/zzz.textnumary\n" - "+++ b/zzz.textnumary\n" - "@@ -3 +3 @@ 0123456789\n" - "-0123456789\n" - "+replace a line\n", pout); - git__free(pout); - git_patch_free(p); - - git_blob_free(nonbin); - git_blob_free(bin); -} diff --git a/tests-clar/diff/diff_helpers.c b/tests-clar/diff/diff_helpers.c deleted file mode 100644 index 33bb561f6..000000000 --- a/tests-clar/diff/diff_helpers.c +++ /dev/null @@ -1,246 +0,0 @@ -#include "clar_libgit2.h" -#include "diff_helpers.h" - -git_tree *resolve_commit_oid_to_tree( - git_repository *repo, - const char *partial_oid) -{ - size_t len = strlen(partial_oid); - git_oid oid; - git_object *obj = NULL; - git_tree *tree = NULL; - - if (git_oid_fromstrn(&oid, partial_oid, len) == 0) - git_object_lookup_prefix(&obj, repo, &oid, len, GIT_OBJ_ANY); - cl_assert(obj); - if (git_object_type(obj) == GIT_OBJ_TREE) - return (git_tree *)obj; - cl_assert(git_object_type(obj) == GIT_OBJ_COMMIT); - cl_git_pass(git_commit_tree(&tree, (git_commit *)obj)); - git_object_free(obj); - return tree; -} - -static char diff_pick_suffix(int mode) -{ - if (S_ISDIR(mode)) - return '/'; - else if (GIT_PERMS_IS_EXEC(mode)) - return '*'; - else - return ' '; -} - -static void fprintf_delta(FILE *fp, const git_diff_delta *delta, float progress) -{ - char code = git_diff_status_char(delta->status); - char old_suffix = diff_pick_suffix(delta->old_file.mode); - char new_suffix = diff_pick_suffix(delta->new_file.mode); - - fprintf(fp, "%c\t%s", code, delta->old_file.path); - - if ((delta->old_file.path != delta->new_file.path && - strcmp(delta->old_file.path, delta->new_file.path) != 0) || - (delta->old_file.mode != delta->new_file.mode && - delta->old_file.mode != 0 && delta->new_file.mode != 0)) - fprintf(fp, "%c %s%c", old_suffix, delta->new_file.path, new_suffix); - else if (old_suffix != ' ') - fprintf(fp, "%c", old_suffix); - - fprintf(fp, "\t[%.2f]\n", progress); -} - -int diff_file_cb( - const git_diff_delta *delta, - float progress, - void *payload) -{ - diff_expects *e = payload; - - if (e->debug) - fprintf_delta(stderr, delta, progress); - - if (e->names) - cl_assert_equal_s(e->names[e->files], delta->old_file.path); - if (e->statuses) - cl_assert_equal_i(e->statuses[e->files], (int)delta->status); - - e->files++; - - if ((delta->flags & GIT_DIFF_FLAG_BINARY) != 0) - e->files_binary++; - - cl_assert(delta->status <= GIT_DELTA_TYPECHANGE); - - e->file_status[delta->status] += 1; - - return 0; -} - -int diff_print_file_cb( - const git_diff_delta *delta, - float progress, - void *payload) -{ - if (!payload) { - fprintf_delta(stderr, delta, progress); - return 0; - } - - if (!((diff_expects *)payload)->debug) - fprintf_delta(stderr, delta, progress); - - return diff_file_cb(delta, progress, payload); -} - -int diff_hunk_cb( - const git_diff_delta *delta, - const git_diff_hunk *hunk, - void *payload) -{ - diff_expects *e = payload; - const char *scan = hunk->header, *scan_end = scan + hunk->header_len; - - GIT_UNUSED(delta); - - /* confirm no NUL bytes in header text */ - while (scan < scan_end) - cl_assert('\0' != *scan++); - - e->hunks++; - e->hunk_old_lines += hunk->old_lines; - e->hunk_new_lines += hunk->new_lines; - return 0; -} - -int diff_line_cb( - const git_diff_delta *delta, - const git_diff_hunk *hunk, - const git_diff_line *line, - void *payload) -{ - diff_expects *e = payload; - - GIT_UNUSED(delta); - GIT_UNUSED(hunk); - - e->lines++; - switch (line->origin) { - case GIT_DIFF_LINE_CONTEXT: - case GIT_DIFF_LINE_CONTEXT_EOFNL: /* techically not a line */ - e->line_ctxt++; - break; - case GIT_DIFF_LINE_ADDITION: - case GIT_DIFF_LINE_ADD_EOFNL: /* technically not a line add */ - e->line_adds++; - break; - case GIT_DIFF_LINE_DELETION: - case GIT_DIFF_LINE_DEL_EOFNL: /* technically not a line delete */ - e->line_dels++; - break; - default: - break; - } - return 0; -} - -int diff_foreach_via_iterator( - git_diff *diff, - git_diff_file_cb file_cb, - git_diff_hunk_cb hunk_cb, - git_diff_line_cb line_cb, - void *data) -{ - size_t d, num_d = git_diff_num_deltas(diff); - - for (d = 0; d < num_d; ++d) { - git_patch *patch; - const git_diff_delta *delta; - size_t h, num_h; - - cl_git_pass(git_patch_from_diff(&patch, diff, d)); - cl_assert((delta = git_patch_get_delta(patch)) != NULL); - - /* call file_cb for this file */ - if (file_cb != NULL && file_cb(delta, (float)d / num_d, data) != 0) { - git_patch_free(patch); - goto abort; - } - - /* if there are no changes, then the patch will be NULL */ - if (!patch) { - cl_assert(delta->status == GIT_DELTA_UNMODIFIED || - (delta->flags & GIT_DIFF_FLAG_BINARY) != 0); - continue; - } - - if (!hunk_cb && !line_cb) { - git_patch_free(patch); - continue; - } - - num_h = git_patch_num_hunks(patch); - - for (h = 0; h < num_h; h++) { - const git_diff_hunk *hunk; - size_t l, num_l; - - cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h)); - - if (hunk_cb && hunk_cb(delta, hunk, data) != 0) { - git_patch_free(patch); - goto abort; - } - - for (l = 0; l < num_l; ++l) { - const git_diff_line *line; - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l)); - - if (line_cb && - line_cb(delta, hunk, line, data) != 0) { - git_patch_free(patch); - goto abort; - } - } - } - - git_patch_free(patch); - } - - return 0; - -abort: - giterr_clear(); - return GIT_EUSER; -} - -static int diff_print_cb( - const git_diff_delta *delta, - const git_diff_hunk *hunk, - const git_diff_line *line, - void *payload) -{ - FILE *fp = payload; - - GIT_UNUSED(delta); GIT_UNUSED(hunk); - - if (line->origin == GIT_DIFF_LINE_CONTEXT || - line->origin == GIT_DIFF_LINE_ADDITION || - line->origin == GIT_DIFF_LINE_DELETION) - fputc(line->origin, fp); - fwrite(line->content, 1, line->content_len, fp); - return 0; -} - -void diff_print(FILE *fp, git_diff *diff) -{ - cl_git_pass(git_diff_print( - diff, GIT_DIFF_FORMAT_PATCH, diff_print_cb, fp ? fp : stderr)); -} - -void diff_print_raw(FILE *fp, git_diff *diff) -{ - cl_git_pass(git_diff_print( - diff, GIT_DIFF_FORMAT_RAW, diff_print_cb, fp ? fp : stderr)); -} diff --git a/tests-clar/diff/diff_helpers.h b/tests-clar/diff/diff_helpers.h deleted file mode 100644 index bf21f4b1f..000000000 --- a/tests-clar/diff/diff_helpers.h +++ /dev/null @@ -1,64 +0,0 @@ -#include "fileops.h" -#include "git2/diff.h" - -extern git_tree *resolve_commit_oid_to_tree( - git_repository *repo, const char *partial_oid); - -typedef struct { - int files; - int files_binary; - - int file_status[10]; /* indexed by git_delta_t value */ - - int hunks; - int hunk_new_lines; - int hunk_old_lines; - - int lines; - int line_ctxt; - int line_adds; - int line_dels; - - /* optional arrays of expected specific values */ - const char **names; - int *statuses; - - int debug; - -} diff_expects; - -typedef struct { - const char *path; - const char *matched_pathspec; -} notify_expected; - -extern int diff_file_cb( - const git_diff_delta *delta, - float progress, - void *cb_data); - -extern int diff_print_file_cb( - const git_diff_delta *delta, - float progress, - void *cb_data); - -extern int diff_hunk_cb( - const git_diff_delta *delta, - const git_diff_hunk *hunk, - void *cb_data); - -extern int diff_line_cb( - const git_diff_delta *delta, - const git_diff_hunk *hunk, - const git_diff_line *line, - void *cb_data); - -extern int diff_foreach_via_iterator( - git_diff *diff, - git_diff_file_cb file_cb, - git_diff_hunk_cb hunk_cb, - git_diff_line_cb line_cb, - void *data); - -extern void diff_print(FILE *fp, git_diff *diff); -extern void diff_print_raw(FILE *fp, git_diff *diff); diff --git a/tests-clar/diff/diffiter.c b/tests-clar/diff/diffiter.c deleted file mode 100644 index f886e1baa..000000000 --- a/tests-clar/diff/diffiter.c +++ /dev/null @@ -1,453 +0,0 @@ -#include "clar_libgit2.h" -#include "diff_helpers.h" - -void test_diff_diffiter__initialize(void) -{ -} - -void test_diff_diffiter__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_diff_diffiter__create(void) -{ - git_repository *repo = cl_git_sandbox_init("attr"); - git_diff *diff; - size_t d, num_d; - - cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); - - num_d = git_diff_num_deltas(diff); - for (d = 0; d < num_d; ++d) { - const git_diff_delta *delta = git_diff_get_delta(diff, d); - cl_assert(delta != NULL); - } - - cl_assert(!git_diff_get_delta(diff, num_d)); - - git_diff_free(diff); -} - -void test_diff_diffiter__iterate_files_1(void) -{ - git_repository *repo = cl_git_sandbox_init("attr"); - git_diff *diff; - size_t d, num_d; - diff_expects exp = { 0 }; - - cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); - - num_d = git_diff_num_deltas(diff); - - for (d = 0; d < num_d; ++d) { - const git_diff_delta *delta = git_diff_get_delta(diff, d); - cl_assert(delta != NULL); - - diff_file_cb(delta, (float)d / (float)num_d, &exp); - } - cl_assert_equal_sz(6, exp.files); - - git_diff_free(diff); -} - -void test_diff_diffiter__iterate_files_2(void) -{ - git_repository *repo = cl_git_sandbox_init("status"); - git_diff *diff; - size_t d, num_d; - int count = 0; - - cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); - - num_d = git_diff_num_deltas(diff); - cl_assert_equal_i(8, (int)num_d); - - for (d = 0; d < num_d; ++d) { - const git_diff_delta *delta = git_diff_get_delta(diff, d); - cl_assert(delta != NULL); - count++; - } - cl_assert_equal_i(8, count); - - git_diff_free(diff); -} - -void test_diff_diffiter__iterate_files_and_hunks(void) -{ - git_repository *repo = cl_git_sandbox_init("status"); - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - size_t d, num_d; - int file_count = 0, hunk_count = 0; - - opts.context_lines = 3; - opts.interhunk_lines = 1; - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - - cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); - - num_d = git_diff_num_deltas(diff); - - for (d = 0; d < num_d; ++d) { - git_patch *patch; - size_t h, num_h; - - cl_git_pass(git_patch_from_diff(&patch, diff, d)); - cl_assert(patch); - - file_count++; - - num_h = git_patch_num_hunks(patch); - - for (h = 0; h < num_h; h++) { - const git_diff_hunk *hunk; - - cl_git_pass(git_patch_get_hunk(&hunk, NULL, patch, h)); - cl_assert(hunk); - - hunk_count++; - } - - git_patch_free(patch); - } - - cl_assert_equal_i(13, file_count); - cl_assert_equal_i(8, hunk_count); - - git_diff_free(diff); -} - -void test_diff_diffiter__max_size_threshold(void) -{ - git_repository *repo = cl_git_sandbox_init("status"); - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - int file_count = 0, binary_count = 0, hunk_count = 0; - size_t d, num_d; - - opts.context_lines = 3; - opts.interhunk_lines = 1; - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - - cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); - num_d = git_diff_num_deltas(diff); - - for (d = 0; d < num_d; ++d) { - git_patch *patch; - const git_diff_delta *delta; - - cl_git_pass(git_patch_from_diff(&patch, diff, d)); - cl_assert(patch); - delta = git_patch_get_delta(patch); - cl_assert(delta); - - file_count++; - hunk_count += (int)git_patch_num_hunks(patch); - - assert((delta->flags & (GIT_DIFF_FLAG_BINARY|GIT_DIFF_FLAG_NOT_BINARY)) != 0); - binary_count += ((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); - - git_patch_free(patch); - } - - cl_assert_equal_i(13, file_count); - cl_assert_equal_i(0, binary_count); - cl_assert_equal_i(8, hunk_count); - - git_diff_free(diff); - - /* try again with low file size threshold */ - - file_count = binary_count = hunk_count = 0; - - opts.context_lines = 3; - opts.interhunk_lines = 1; - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - opts.max_size = 50; /* treat anything over 50 bytes as binary! */ - - cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); - num_d = git_diff_num_deltas(diff); - - for (d = 0; d < num_d; ++d) { - git_patch *patch; - const git_diff_delta *delta; - - cl_git_pass(git_patch_from_diff(&patch, diff, d)); - delta = git_patch_get_delta(patch); - - file_count++; - hunk_count += (int)git_patch_num_hunks(patch); - - assert((delta->flags & (GIT_DIFF_FLAG_BINARY|GIT_DIFF_FLAG_NOT_BINARY)) != 0); - binary_count += ((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); - - git_patch_free(patch); - } - - cl_assert_equal_i(13, file_count); - /* Three files are over the 50 byte threshold: - * - staged_changes_file_deleted - * - staged_changes_modified_file - * - staged_new_file_modified_file - */ - cl_assert_equal_i(3, binary_count); - cl_assert_equal_i(5, hunk_count); - - git_diff_free(diff); -} - - -void test_diff_diffiter__iterate_all(void) -{ - git_repository *repo = cl_git_sandbox_init("status"); - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - diff_expects exp = {0}; - size_t d, num_d; - - opts.context_lines = 3; - opts.interhunk_lines = 1; - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - - cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); - - num_d = git_diff_num_deltas(diff); - for (d = 0; d < num_d; ++d) { - git_patch *patch; - size_t h, num_h; - - cl_git_pass(git_patch_from_diff(&patch, diff, d)); - cl_assert(patch); - exp.files++; - - num_h = git_patch_num_hunks(patch); - for (h = 0; h < num_h; h++) { - const git_diff_hunk *range; - size_t l, num_l; - - cl_git_pass(git_patch_get_hunk(&range, &num_l, patch, h)); - cl_assert(range); - exp.hunks++; - - for (l = 0; l < num_l; ++l) { - const git_diff_line *line; - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l)); - cl_assert(line && line->content); - exp.lines++; - } - } - - git_patch_free(patch); - } - - cl_assert_equal_i(13, exp.files); - cl_assert_equal_i(8, exp.hunks); - cl_assert_equal_i(14, exp.lines); - - git_diff_free(diff); -} - -static void iterate_over_patch(git_patch *patch, diff_expects *exp) -{ - size_t h, num_h = git_patch_num_hunks(patch), num_l; - - exp->files++; - exp->hunks += (int)num_h; - - /* let's iterate in reverse, just because we can! */ - for (h = 1, num_l = 0; h <= num_h; ++h) - num_l += git_patch_num_lines_in_hunk(patch, num_h - h); - - exp->lines += (int)num_l; -} - -#define PATCH_CACHE 5 - -void test_diff_diffiter__iterate_randomly_while_saving_state(void) -{ - git_repository *repo = cl_git_sandbox_init("status"); - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - diff_expects exp = {0}; - git_patch *patches[PATCH_CACHE]; - size_t p, d, num_d; - - memset(patches, 0, sizeof(patches)); - - opts.context_lines = 3; - opts.interhunk_lines = 1; - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - - cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); - - num_d = git_diff_num_deltas(diff); - - /* To make sure that references counts work for diff and patch objects, - * this generates patches and randomly caches them. Only when the patch - * is removed from the cache are hunks and lines counted. At the end, - * there are still patches in the cache, so free the diff and try to - * process remaining patches after the diff is freed. - */ - - srand(121212); - p = rand() % PATCH_CACHE; - - for (d = 0; d < num_d; ++d) { - /* take old patch */ - git_patch *patch = patches[p]; - patches[p] = NULL; - - /* cache new patch */ - cl_git_pass(git_patch_from_diff(&patches[p], diff, d)); - cl_assert(patches[p] != NULL); - - /* process old patch if non-NULL */ - if (patch != NULL) { - iterate_over_patch(patch, &exp); - git_patch_free(patch); - } - - p = rand() % PATCH_CACHE; - } - - /* free diff list now - refcounts should keep things safe */ - git_diff_free(diff); - - /* process remaining unprocessed patches */ - for (p = 0; p < PATCH_CACHE; p++) { - git_patch *patch = patches[p]; - - if (patch != NULL) { - iterate_over_patch(patch, &exp); - git_patch_free(patch); - } - } - - /* hopefully it all still added up right */ - cl_assert_equal_i(13, exp.files); - cl_assert_equal_i(8, exp.hunks); - cl_assert_equal_i(14, exp.lines); -} - -/* This output is taken directly from `git diff` on the status test data */ -static const char *expected_patch_text[8] = { - /* 0 */ - "diff --git a/file_deleted b/file_deleted\n" - "deleted file mode 100644\n" - "index 5452d32..0000000\n" - "--- a/file_deleted\n" - "+++ /dev/null\n" - "@@ -1 +0,0 @@\n" - "-file_deleted\n", - /* 1 */ - "diff --git a/modified_file b/modified_file\n" - "index 452e424..0a53963 100644\n" - "--- a/modified_file\n" - "+++ b/modified_file\n" - "@@ -1 +1,2 @@\n" - " modified_file\n" - "+modified_file\n", - /* 2 */ - "diff --git a/staged_changes_file_deleted b/staged_changes_file_deleted\n" - "deleted file mode 100644\n" - "index a6be623..0000000\n" - "--- a/staged_changes_file_deleted\n" - "+++ /dev/null\n" - "@@ -1,2 +0,0 @@\n" - "-staged_changes_file_deleted\n" - "-staged_changes_file_deleted\n", - /* 3 */ - "diff --git a/staged_changes_modified_file b/staged_changes_modified_file\n" - "index 906ee77..011c344 100644\n" - "--- a/staged_changes_modified_file\n" - "+++ b/staged_changes_modified_file\n" - "@@ -1,2 +1,3 @@\n" - " staged_changes_modified_file\n" - " staged_changes_modified_file\n" - "+staged_changes_modified_file\n", - /* 4 */ - "diff --git a/staged_new_file_deleted_file b/staged_new_file_deleted_file\n" - "deleted file mode 100644\n" - "index 90b8c29..0000000\n" - "--- a/staged_new_file_deleted_file\n" - "+++ /dev/null\n" - "@@ -1 +0,0 @@\n" - "-staged_new_file_deleted_file\n", - /* 5 */ - "diff --git a/staged_new_file_modified_file b/staged_new_file_modified_file\n" - "index ed06290..8b090c0 100644\n" - "--- a/staged_new_file_modified_file\n" - "+++ b/staged_new_file_modified_file\n" - "@@ -1 +1,2 @@\n" - " staged_new_file_modified_file\n" - "+staged_new_file_modified_file\n", - /* 6 */ - "diff --git a/subdir/deleted_file b/subdir/deleted_file\n" - "deleted file mode 100644\n" - "index 1888c80..0000000\n" - "--- a/subdir/deleted_file\n" - "+++ /dev/null\n" - "@@ -1 +0,0 @@\n" - "-subdir/deleted_file\n", - /* 7 */ - "diff --git a/subdir/modified_file b/subdir/modified_file\n" - "index a619198..57274b7 100644\n" - "--- a/subdir/modified_file\n" - "+++ b/subdir/modified_file\n" - "@@ -1 +1,2 @@\n" - " subdir/modified_file\n" - "+subdir/modified_file\n" -}; - -void test_diff_diffiter__iterate_and_generate_patch_text(void) -{ - git_repository *repo = cl_git_sandbox_init("status"); - git_diff *diff; - size_t d, num_d; - - cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); - - num_d = git_diff_num_deltas(diff); - cl_assert_equal_i(8, (int)num_d); - - for (d = 0; d < num_d; ++d) { - git_patch *patch; - char *text; - - cl_git_pass(git_patch_from_diff(&patch, diff, d)); - cl_assert(patch != NULL); - - cl_git_pass(git_patch_to_str(&text, patch)); - - cl_assert_equal_s(expected_patch_text[d], text); - - git__free(text); - git_patch_free(patch); - } - - git_diff_free(diff); -} - -void test_diff_diffiter__checks_options_version(void) -{ - git_repository *repo = cl_git_sandbox_init("status"); - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - const git_error *err; - - opts.version = 0; - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - - cl_git_fail(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); - - giterr_clear(); - opts.version = 1024; - cl_git_fail(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); -} - diff --git a/tests-clar/diff/drivers.c b/tests-clar/diff/drivers.c deleted file mode 100644 index fbd1dff81..000000000 --- a/tests-clar/diff/drivers.c +++ /dev/null @@ -1,163 +0,0 @@ -#include "clar_libgit2.h" -#include "diff_helpers.h" -#include "repository.h" -#include "diff_driver.h" - -static git_repository *g_repo = NULL; - -void test_diff_drivers__initialize(void) -{ -} - -void test_diff_drivers__cleanup(void) -{ - cl_git_sandbox_cleanup(); - g_repo = NULL; -} - -void test_diff_drivers__patterns(void) -{ - git_config *cfg; - const char *one_sha = "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13"; - git_tree *one; - git_diff *diff; - git_patch *patch; - char *text; - const char *expected0 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Comes through the blood of the vanguards who\n dreamed--too soon--it had sounded.\r\n \r\n -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n"; - const char *expected1 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\nBinary files a/untimely.txt and b/untimely.txt differ\n"; - const char *expected2 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Heaven delivers on earth the Hour that cannot be\n dreamed--too soon--it had sounded.\r\n \r\n -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n"; - - g_repo = cl_git_sandbox_init("renames"); - - one = resolve_commit_oid_to_tree(g_repo, one_sha); - - /* no diff */ - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); - cl_assert_equal_i(0, (int)git_diff_num_deltas(diff)); - git_diff_free(diff); - - /* default diff */ - - cl_git_append2file("renames/untimely.txt", "\r\nSome new stuff\r\n"); - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_git_pass(git_patch_to_str(&text, patch)); - cl_assert_equal_s(expected0, text); - - git__free(text); - git_patch_free(patch); - git_diff_free(diff); - - /* attribute diff set to false */ - - cl_git_rewritefile("renames/.gitattributes", "untimely.txt -diff\n"); - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_git_pass(git_patch_to_str(&text, patch)); - cl_assert_equal_s(expected1, text); - - git__free(text); - git_patch_free(patch); - git_diff_free(diff); - - /* attribute diff set to unconfigured value (should use default) */ - - cl_git_rewritefile("renames/.gitattributes", "untimely.txt diff=kipling0\n"); - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_git_pass(git_patch_to_str(&text, patch)); - cl_assert_equal_s(expected0, text); - - git__free(text); - git_patch_free(patch); - git_diff_free(diff); - - /* let's define that driver */ - - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_set_bool(cfg, "diff.kipling0.binary", 1)); - git_config_free(cfg); - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_git_pass(git_patch_to_str(&text, patch)); - cl_assert_equal_s(expected1, text); - - git__free(text); - git_patch_free(patch); - git_diff_free(diff); - - /* let's use a real driver with some regular expressions */ - - git_diff_driver_registry_free(g_repo->diff_drivers); - g_repo->diff_drivers = NULL; - - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_set_bool(cfg, "diff.kipling0.binary", 0)); - cl_git_pass(git_config_set_string(cfg, "diff.kipling0.xfuncname", "^H")); - git_config_free(cfg); - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_git_pass(git_patch_to_str(&text, patch)); - cl_assert_equal_s(expected2, text); - - git__free(text); - git_patch_free(patch); - git_diff_free(diff); - - git_tree_free(one); -} - -void test_diff_drivers__long_lines(void) -{ - const char *base = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non nisi ligula. Ut viverra enim sed lobortis suscipit.\nPhasellus eget erat odio. Praesent at est iaculis, ultricies augue vel, dignissim risus. Suspendisse at nisi quis turpis fringilla rutrum id sit amet nulla.\nNam eget dolor fermentum, aliquet nisl at, convallis tellus. Pellentesque rhoncus erat enim, id porttitor elit euismod quis.\nMauris sollicitudin magna odio, non egestas libero vehicula ut. Etiam et quam velit. Fusce eget libero rhoncus, ultricies felis sit amet, egestas purus.\nAliquam in semper tellus. Pellentesque adipiscing rutrum velit, quis malesuada lacus consequat eget.\n"; - git_index *idx; - git_diff *diff; - git_patch *patch; - char *actual; - const char *expected = "diff --git a/longlines.txt b/longlines.txt\nindex c1ce6ef..0134431 100644\n--- a/longlines.txt\n+++ b/longlines.txt\n@@ -3,3 +3,5 @@ Phasellus eget erat odio. Praesent at est iaculis, ultricies augue vel, dignissi\n Nam eget dolor fermentum, aliquet nisl at, convallis tellus. Pellentesque rhoncus erat enim, id porttitor elit euismod quis.\n Mauris sollicitudin magna odio, non egestas libero vehicula ut. Etiam et quam velit. Fusce eget libero rhoncus, ultricies felis sit amet, egestas purus.\n Aliquam in semper tellus. Pellentesque adipiscing rutrum velit, quis malesuada lacus consequat eget.\n+newline\n+newline\n"; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_mkfile("empty_standard_repo/longlines.txt", base); - cl_git_pass(git_repository_index(&idx, g_repo)); - cl_git_pass(git_index_add_bypath(idx, "longlines.txt")); - cl_git_pass(git_index_write(idx)); - git_index_free(idx); - - cl_git_append2file("empty_standard_repo/longlines.txt", "newline\nnewline\n"); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); - cl_assert_equal_sz(1, git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_git_pass(git_patch_to_str(&actual, patch)); - - /* if chmod not supported, overwrite mode bits since anything is possible */ - if (!cl_is_chmod_supported()) { - size_t actual_len = strlen(actual); - if (actual_len > 72 && memcmp(&actual[66], "100644", 6) != 0) - memcpy(&actual[66], "100644", 6); - } - - cl_assert_equal_s(expected, actual); - - free(actual); - git_patch_free(patch); - git_diff_free(diff); -} - diff --git a/tests-clar/diff/index.c b/tests-clar/diff/index.c deleted file mode 100644 index 8f4567137..000000000 --- a/tests-clar/diff/index.c +++ /dev/null @@ -1,167 +0,0 @@ -#include "clar_libgit2.h" -#include "diff_helpers.h" - -static git_repository *g_repo = NULL; - -void test_diff_index__initialize(void) -{ - g_repo = cl_git_sandbox_init("status"); -} - -void test_diff_index__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_diff_index__0(void) -{ - /* grabbed a couple of commit oids from the history of the attr repo */ - const char *a_commit = "26a125ee1bf"; /* the current HEAD */ - const char *b_commit = "0017bd4ab1ec3"; /* the start */ - git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); - git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit); - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - diff_expects exp; - - cl_assert(a); - cl_assert(b); - - opts.context_lines = 1; - opts.interhunk_lines = 1; - - memset(&exp, 0, sizeof(exp)); - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - /* to generate these values: - * - cd to tests/resources/status, - * - mv .gitted .git - * - git diff --name-status --cached 26a125ee1bf - * - git diff -U1 --cached 26a125ee1bf - * - mv .git .gitted - */ - cl_assert_equal_i(8, exp.files); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); - - cl_assert_equal_i(8, exp.hunks); - - cl_assert_equal_i(11, exp.lines); - cl_assert_equal_i(3, exp.line_ctxt); - cl_assert_equal_i(6, exp.line_adds); - cl_assert_equal_i(2, exp.line_dels); - - git_diff_free(diff); - diff = NULL; - memset(&exp, 0, sizeof(exp)); - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - /* to generate these values: - * - cd to tests/resources/status, - * - mv .gitted .git - * - git diff --name-status --cached 0017bd4ab1ec3 - * - git diff -U1 --cached 0017bd4ab1ec3 - * - mv .git .gitted - */ - cl_assert_equal_i(12, exp.files); - cl_assert_equal_i(7, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); - - cl_assert_equal_i(12, exp.hunks); - - cl_assert_equal_i(16, exp.lines); - cl_assert_equal_i(3, exp.line_ctxt); - cl_assert_equal_i(11, exp.line_adds); - cl_assert_equal_i(2, exp.line_dels); - - git_diff_free(diff); - diff = NULL; - - git_tree_free(a); - git_tree_free(b); -} - -static int diff_stop_after_2_files( - const git_diff_delta *delta, - float progress, - void *payload) -{ - diff_expects *e = payload; - - GIT_UNUSED(progress); - GIT_UNUSED(delta); - - e->files++; - - return (e->files == 2); -} - -void test_diff_index__1(void) -{ - /* grabbed a couple of commit oids from the history of the attr repo */ - const char *a_commit = "26a125ee1bf"; /* the current HEAD */ - const char *b_commit = "0017bd4ab1ec3"; /* the start */ - git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); - git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit); - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - diff_expects exp; - - cl_assert(a); - cl_assert(b); - - opts.context_lines = 1; - opts.interhunk_lines = 1; - - memset(&exp, 0, sizeof(exp)); - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); - - cl_assert_equal_i( - GIT_EUSER, - git_diff_foreach(diff, diff_stop_after_2_files, NULL, NULL, &exp) - ); - - cl_assert_equal_i(2, exp.files); - - git_diff_free(diff); - diff = NULL; - - git_tree_free(a); - git_tree_free(b); -} - -void test_diff_index__checks_options_version(void) -{ - const char *a_commit = "26a125ee1bf"; - git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - const git_error *err; - - opts.version = 0; - cl_git_fail(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); - cl_assert_equal_p(diff, NULL); - - giterr_clear(); - opts.version = 1024; - cl_git_fail(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); - cl_assert_equal_p(diff, NULL); - - git_tree_free(a); -} - diff --git a/tests-clar/diff/iterator.c b/tests-clar/diff/iterator.c deleted file mode 100644 index bbdae8ad1..000000000 --- a/tests-clar/diff/iterator.c +++ /dev/null @@ -1,937 +0,0 @@ -#include "clar_libgit2.h" -#include "diff_helpers.h" -#include "iterator.h" -#include "tree.h" - -void test_diff_iterator__initialize(void) -{ - /* since we are doing tests with different sandboxes, defer setup - * to the actual tests. cleanup will still be done in the global - * cleanup function so that assertion failures don't result in a - * missed cleanup. - */ -} - -void test_diff_iterator__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - - -/* -- TREE ITERATOR TESTS -- */ - -static void tree_iterator_test( - const char *sandbox, - const char *treeish, - const char *start, - const char *end, - int expected_count, - const char **expected_values) -{ - git_tree *t; - git_iterator *i; - const git_index_entry *entry; - int error, count = 0, count_post_reset = 0; - git_repository *repo = cl_git_sandbox_init(sandbox); - - cl_assert(t = resolve_commit_oid_to_tree(repo, treeish)); - cl_git_pass(git_iterator_for_tree( - &i, t, GIT_ITERATOR_DONT_IGNORE_CASE, start, end)); - - /* test loop */ - while (!(error = git_iterator_advance(&entry, i))) { - cl_assert(entry); - if (expected_values != NULL) - cl_assert_equal_s(expected_values[count], entry->path); - count++; - } - cl_assert_equal_i(GIT_ITEROVER, error); - cl_assert(!entry); - cl_assert_equal_i(expected_count, count); - - /* test reset */ - cl_git_pass(git_iterator_reset(i, NULL, NULL)); - - while (!(error = git_iterator_advance(&entry, i))) { - cl_assert(entry); - if (expected_values != NULL) - cl_assert_equal_s(expected_values[count_post_reset], entry->path); - count_post_reset++; - } - cl_assert_equal_i(GIT_ITEROVER, error); - cl_assert(!entry); - cl_assert_equal_i(count, count_post_reset); - - git_iterator_free(i); - git_tree_free(t); -} - -/* results of: git ls-tree -r --name-only 605812a */ -const char *expected_tree_0[] = { - ".gitattributes", - "attr0", - "attr1", - "attr2", - "attr3", - "binfile", - "macro_test", - "root_test1", - "root_test2", - "root_test3", - "root_test4.txt", - "subdir/.gitattributes", - "subdir/abc", - "subdir/subdir_test1", - "subdir/subdir_test2.txt", - "subdir2/subdir2_test1", - NULL -}; - -void test_diff_iterator__tree_0(void) -{ - tree_iterator_test("attr", "605812a", NULL, NULL, 16, expected_tree_0); -} - -/* results of: git ls-tree -r --name-only 6bab5c79 */ -const char *expected_tree_1[] = { - ".gitattributes", - "attr0", - "attr1", - "attr2", - "attr3", - "root_test1", - "root_test2", - "root_test3", - "root_test4.txt", - "subdir/.gitattributes", - "subdir/subdir_test1", - "subdir/subdir_test2.txt", - "subdir2/subdir2_test1", - NULL -}; - -void test_diff_iterator__tree_1(void) -{ - tree_iterator_test("attr", "6bab5c79cd5", NULL, NULL, 13, expected_tree_1); -} - -/* results of: git ls-tree -r --name-only 26a125ee1 */ -const char *expected_tree_2[] = { - "current_file", - "file_deleted", - "modified_file", - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_file_deleted", - "staged_delete_modified_file", - "subdir.txt", - "subdir/current_file", - "subdir/deleted_file", - "subdir/modified_file", - NULL -}; - -void test_diff_iterator__tree_2(void) -{ - tree_iterator_test("status", "26a125ee1", NULL, NULL, 12, expected_tree_2); -} - -/* $ git ls-tree -r --name-only 0017bd4ab1e */ -const char *expected_tree_3[] = { - "current_file", - "file_deleted", - "modified_file", - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_file_deleted", - "staged_delete_modified_file" -}; - -void test_diff_iterator__tree_3(void) -{ - tree_iterator_test("status", "0017bd4ab1e", NULL, NULL, 8, expected_tree_3); -} - -/* $ git ls-tree -r --name-only 24fa9a9fc4e202313e24b648087495441dab432b */ -const char *expected_tree_4[] = { - "attr0", - "attr1", - "attr2", - "attr3", - "binfile", - "gitattributes", - "macro_bad", - "macro_test", - "root_test1", - "root_test2", - "root_test3", - "root_test4.txt", - "sub/abc", - "sub/file", - "sub/sub/file", - "sub/sub/subsub.txt", - "sub/subdir_test1", - "sub/subdir_test2.txt", - "subdir/.gitattributes", - "subdir/abc", - "subdir/subdir_test1", - "subdir/subdir_test2.txt", - "subdir2/subdir2_test1", - NULL -}; - -void test_diff_iterator__tree_4(void) -{ - tree_iterator_test( - "attr", "24fa9a9fc4e202313e24b648087495441dab432b", NULL, NULL, - 23, expected_tree_4); -} - -void test_diff_iterator__tree_4_ranged(void) -{ - tree_iterator_test( - "attr", "24fa9a9fc4e202313e24b648087495441dab432b", - "sub", "sub", - 11, &expected_tree_4[12]); -} - -const char *expected_tree_ranged_0[] = { - "gitattributes", - "macro_bad", - "macro_test", - "root_test1", - "root_test2", - "root_test3", - "root_test4.txt", - NULL -}; - -void test_diff_iterator__tree_ranged_0(void) -{ - tree_iterator_test( - "attr", "24fa9a9fc4e202313e24b648087495441dab432b", - "git", "root", - 7, expected_tree_ranged_0); -} - -const char *expected_tree_ranged_1[] = { - "sub/subdir_test2.txt", - NULL -}; - -void test_diff_iterator__tree_ranged_1(void) -{ - tree_iterator_test( - "attr", "24fa9a9fc4e202313e24b648087495441dab432b", - "sub/subdir_test2.txt", "sub/subdir_test2.txt", - 1, expected_tree_ranged_1); -} - -void test_diff_iterator__tree_range_empty_0(void) -{ - tree_iterator_test( - "attr", "24fa9a9fc4e202313e24b648087495441dab432b", - "empty", "empty", 0, NULL); -} - -void test_diff_iterator__tree_range_empty_1(void) -{ - tree_iterator_test( - "attr", "24fa9a9fc4e202313e24b648087495441dab432b", - "z_empty_after", NULL, 0, NULL); -} - -void test_diff_iterator__tree_range_empty_2(void) -{ - tree_iterator_test( - "attr", "24fa9a9fc4e202313e24b648087495441dab432b", - NULL, ".aaa_empty_before", 0, NULL); -} - -static void check_tree_entry( - git_iterator *i, - const char *oid, - const char *oid_p, - const char *oid_pp, - const char *oid_ppp) -{ - const git_index_entry *ie; - const git_tree_entry *te; - const git_tree *tree; - git_buf path = GIT_BUF_INIT; - - cl_git_pass(git_iterator_current_tree_entry(&te, i)); - cl_assert(te); - cl_assert(git_oid_streq(&te->oid, oid) == 0); - - cl_git_pass(git_iterator_current(&ie, i)); - cl_git_pass(git_buf_sets(&path, ie->path)); - - if (oid_p) { - git_buf_rtruncate_at_char(&path, '/'); - cl_git_pass(git_iterator_current_parent_tree(&tree, i, path.ptr)); - cl_assert(tree); - cl_assert(git_oid_streq(git_tree_id(tree), oid_p) == 0); - } - - if (oid_pp) { - git_buf_rtruncate_at_char(&path, '/'); - cl_git_pass(git_iterator_current_parent_tree(&tree, i, path.ptr)); - cl_assert(tree); - cl_assert(git_oid_streq(git_tree_id(tree), oid_pp) == 0); - } - - if (oid_ppp) { - git_buf_rtruncate_at_char(&path, '/'); - cl_git_pass(git_iterator_current_parent_tree(&tree, i, path.ptr)); - cl_assert(tree); - cl_assert(git_oid_streq(git_tree_id(tree), oid_ppp) == 0); - } - - git_buf_free(&path); -} - -void test_diff_iterator__tree_special_functions(void) -{ - git_tree *t; - git_iterator *i; - const git_index_entry *entry; - git_repository *repo = cl_git_sandbox_init("attr"); - int error, cases = 0; - const char *rootoid = "ce39a97a7fb1fa90bcf5e711249c1e507476ae0e"; - - t = resolve_commit_oid_to_tree( - repo, "24fa9a9fc4e202313e24b648087495441dab432b"); - cl_assert(t != NULL); - - cl_git_pass(git_iterator_for_tree( - &i, t, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)); - - while (!(error = git_iterator_advance(&entry, i))) { - cl_assert(entry); - - if (strcmp(entry->path, "sub/file") == 0) { - cases++; - check_tree_entry( - i, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057", - "ecb97df2a174987475ac816e3847fc8e9f6c596b", - rootoid, NULL); - } - else if (strcmp(entry->path, "sub/sub/subsub.txt") == 0) { - cases++; - check_tree_entry( - i, "9e5bdc47d6a80f2be0ea3049ad74231b94609242", - "4e49ba8c5b6c32ff28cd9dcb60be34df50fcc485", - "ecb97df2a174987475ac816e3847fc8e9f6c596b", rootoid); - } - else if (strcmp(entry->path, "subdir/.gitattributes") == 0) { - cases++; - check_tree_entry( - i, "99eae476896f4907224978b88e5ecaa6c5bb67a9", - "9fb40b6675dde60b5697afceae91b66d908c02d9", - rootoid, NULL); - } - else if (strcmp(entry->path, "subdir2/subdir2_test1") == 0) { - cases++; - check_tree_entry( - i, "dccada462d3df8ac6de596fb8c896aba9344f941", - "2929de282ce999e95183aedac6451d3384559c4b", - rootoid, NULL); - } - } - cl_assert_equal_i(GIT_ITEROVER, error); - cl_assert(!entry); - cl_assert_equal_i(4, cases); - - git_iterator_free(i); - git_tree_free(t); -} - -/* -- INDEX ITERATOR TESTS -- */ - -static void index_iterator_test( - const char *sandbox, - const char *start, - const char *end, - int expected_count, - const char **expected_names, - const char **expected_oids) -{ - git_index *index; - git_iterator *i; - const git_index_entry *entry; - int error, count = 0; - git_repository *repo = cl_git_sandbox_init(sandbox); - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_iterator_for_index(&i, index, 0, start, end)); - - while (!(error = git_iterator_advance(&entry, i))) { - cl_assert(entry); - - if (expected_names != NULL) - cl_assert_equal_s(expected_names[count], entry->path); - - if (expected_oids != NULL) { - git_oid oid; - cl_git_pass(git_oid_fromstr(&oid, expected_oids[count])); - cl_assert_equal_i(git_oid_cmp(&oid, &entry->oid), 0); - } - - count++; - } - - cl_assert_equal_i(GIT_ITEROVER, error); - cl_assert(!entry); - cl_assert_equal_i(expected_count, count); - - git_iterator_free(i); - git_index_free(index); -} - -static const char *expected_index_0[] = { - "attr0", - "attr1", - "attr2", - "attr3", - "binfile", - "gitattributes", - "macro_bad", - "macro_test", - "root_test1", - "root_test2", - "root_test3", - "root_test4.txt", - "sub/abc", - "sub/file", - "sub/sub/file", - "sub/sub/subsub.txt", - "sub/subdir_test1", - "sub/subdir_test2.txt", - "subdir/.gitattributes", - "subdir/abc", - "subdir/subdir_test1", - "subdir/subdir_test2.txt", - "subdir2/subdir2_test1", -}; - -static const char *expected_index_oids_0[] = { - "556f8c827b8e4a02ad5cab77dca2bcb3e226b0b3", - "3b74db7ab381105dc0d28f8295a77f6a82989292", - "2c66e14f77196ea763fb1e41612c1aa2bc2d8ed2", - "c485abe35abd4aa6fd83b076a78bbea9e2e7e06c", - "d800886d9c86731ae5c4a62b0b77c437015e00d2", - "2b40c5aca159b04ea8d20ffe36cdf8b09369b14a", - "5819a185d77b03325aaf87cafc771db36f6ddca7", - "ff69f8639ce2e6010b3f33a74160aad98b48da2b", - "45141a79a77842c59a63229403220a4e4be74e3d", - "4d713dc48e6b1bd75b0d61ad078ba9ca3a56745d", - "108bb4e7fd7b16490dc33ff7d972151e73d7166e", - "a0f7217ae99f5ac3e88534f5cea267febc5fa85b", - "3e42ffc54a663f9401cc25843d6c0e71a33e4249", - "45b983be36b73c0788dc9cbcb76cbb80fc7bb057", - "45b983be36b73c0788dc9cbcb76cbb80fc7bb057", - "9e5bdc47d6a80f2be0ea3049ad74231b94609242", - "e563cf4758f0d646f1b14b76016aa17fa9e549a4", - "fb5067b1aef3ac1ada4b379dbcb7d17255df7d78", - "99eae476896f4907224978b88e5ecaa6c5bb67a9", - "3e42ffc54a663f9401cc25843d6c0e71a33e4249", - "e563cf4758f0d646f1b14b76016aa17fa9e549a4", - "fb5067b1aef3ac1ada4b379dbcb7d17255df7d78", - "dccada462d3df8ac6de596fb8c896aba9344f941" -}; - -void test_diff_iterator__index_0(void) -{ - index_iterator_test( - "attr", NULL, NULL, 23, expected_index_0, expected_index_oids_0); -} - -static const char *expected_index_range[] = { - "root_test1", - "root_test2", - "root_test3", - "root_test4.txt", -}; - -static const char *expected_index_oids_range[] = { - "45141a79a77842c59a63229403220a4e4be74e3d", - "4d713dc48e6b1bd75b0d61ad078ba9ca3a56745d", - "108bb4e7fd7b16490dc33ff7d972151e73d7166e", - "a0f7217ae99f5ac3e88534f5cea267febc5fa85b", -}; - -void test_diff_iterator__index_range(void) -{ - index_iterator_test( - "attr", "root", "root", 4, expected_index_range, expected_index_oids_range); -} - -void test_diff_iterator__index_range_empty_0(void) -{ - index_iterator_test( - "attr", "empty", "empty", 0, NULL, NULL); -} - -void test_diff_iterator__index_range_empty_1(void) -{ - index_iterator_test( - "attr", "z_empty_after", NULL, 0, NULL, NULL); -} - -void test_diff_iterator__index_range_empty_2(void) -{ - index_iterator_test( - "attr", NULL, ".aaa_empty_before", 0, NULL, NULL); -} - -static const char *expected_index_1[] = { - "current_file", - "file_deleted", - "modified_file", - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_new_file", - "staged_new_file_deleted_file", - "staged_new_file_modified_file", - "subdir.txt", - "subdir/current_file", - "subdir/deleted_file", - "subdir/modified_file", -}; - -static const char* expected_index_oids_1[] = { - "a0de7e0ac200c489c41c59dfa910154a70264e6e", - "5452d32f1dd538eb0405e8a83cc185f79e25e80f", - "452e4244b5d083ddf0460acf1ecc74db9dcfa11a", - "55d316c9ba708999f1918e9677d01dfcae69c6b9", - "a6be623522ce87a1d862128ac42672604f7b468b", - "906ee7711f4f4928ddcb2a5f8fbc500deba0d2a8", - "529a16e8e762d4acb7b9636ff540a00831f9155a", - "90b8c29d8ba39434d1c63e1b093daaa26e5bd972", - "ed062903b8f6f3dccb2fa81117ba6590944ef9bd", - "e8ee89e15bbe9b20137715232387b3de5b28972e", - "53ace0d1cc1145a5f4fe4f78a186a60263190733", - "1888c805345ba265b0ee9449b8877b6064592058", - "a6191982709b746d5650e93c2acf34ef74e11504" -}; - -void test_diff_iterator__index_1(void) -{ - index_iterator_test( - "status", NULL, NULL, 13, expected_index_1, expected_index_oids_1); -} - - -/* -- WORKDIR ITERATOR TESTS -- */ - -static void workdir_iterator_test( - const char *sandbox, - const char *start, - const char *end, - int expected_count, - int expected_ignores, - const char **expected_names, - const char *an_ignored_name) -{ - git_iterator *i; - const git_index_entry *entry; - int error, count = 0, count_all = 0, count_all_post_reset = 0; - git_repository *repo = cl_git_sandbox_init(sandbox); - - cl_git_pass(git_iterator_for_workdir( - &i, repo, GIT_ITERATOR_DONT_AUTOEXPAND, start, end)); - - error = git_iterator_current(&entry, i); - cl_assert((error == 0 && entry != NULL) || - (error == GIT_ITEROVER && entry == NULL)); - - while (entry != NULL) { - int ignored = git_iterator_current_is_ignored(i); - - if (S_ISDIR(entry->mode)) { - cl_git_pass(git_iterator_advance_into(&entry, i)); - continue; - } - - if (expected_names != NULL) - cl_assert_equal_s(expected_names[count_all], entry->path); - - if (an_ignored_name && strcmp(an_ignored_name,entry->path)==0) - cl_assert(ignored); - - if (!ignored) - count++; - count_all++; - - error = git_iterator_advance(&entry, i); - - cl_assert((error == 0 && entry != NULL) || - (error == GIT_ITEROVER && entry == NULL)); - } - - cl_assert_equal_i(expected_count, count); - cl_assert_equal_i(expected_count + expected_ignores, count_all); - - cl_git_pass(git_iterator_reset(i, NULL, NULL)); - - error = git_iterator_current(&entry, i); - cl_assert((error == 0 && entry != NULL) || - (error == GIT_ITEROVER && entry == NULL)); - - while (entry != NULL) { - if (S_ISDIR(entry->mode)) { - cl_git_pass(git_iterator_advance_into(&entry, i)); - continue; - } - - if (expected_names != NULL) - cl_assert_equal_s( - expected_names[count_all_post_reset], entry->path); - count_all_post_reset++; - - error = git_iterator_advance(&entry, i); - cl_assert(error == 0 || error == GIT_ITEROVER); - } - - cl_assert_equal_i(count_all, count_all_post_reset); - - git_iterator_free(i); -} - -void test_diff_iterator__workdir_0(void) -{ - workdir_iterator_test("attr", NULL, NULL, 27, 1, NULL, "ign"); -} - -static const char *status_paths[] = { - "current_file", - "ignored_file", - "modified_file", - "new_file", - "staged_changes", - "staged_changes_modified_file", - "staged_delete_modified_file", - "staged_new_file", - "staged_new_file_modified_file", - "subdir.txt", - "subdir/current_file", - "subdir/modified_file", - "subdir/new_file", - "\xe8\xbf\x99", - NULL -}; - -void test_diff_iterator__workdir_1(void) -{ - workdir_iterator_test( - "status", NULL, NULL, 13, 1, status_paths, "ignored_file"); -} - -static const char *status_paths_range_0[] = { - "staged_changes", - "staged_changes_modified_file", - "staged_delete_modified_file", - "staged_new_file", - "staged_new_file_modified_file", - NULL -}; - -void test_diff_iterator__workdir_1_ranged_0(void) -{ - workdir_iterator_test( - "status", "staged", "staged", 5, 0, status_paths_range_0, NULL); -} - -static const char *status_paths_range_1[] = { - "modified_file", NULL -}; - -void test_diff_iterator__workdir_1_ranged_1(void) -{ - workdir_iterator_test( - "status", "modified_file", "modified_file", - 1, 0, status_paths_range_1, NULL); -} - -static const char *status_paths_range_3[] = { - "subdir.txt", - "subdir/current_file", - "subdir/modified_file", - NULL -}; - -void test_diff_iterator__workdir_1_ranged_3(void) -{ - workdir_iterator_test( - "status", "subdir", "subdir/modified_file", - 3, 0, status_paths_range_3, NULL); -} - -static const char *status_paths_range_4[] = { - "subdir/current_file", - "subdir/modified_file", - "subdir/new_file", - "\xe8\xbf\x99", - NULL -}; - -void test_diff_iterator__workdir_1_ranged_4(void) -{ - workdir_iterator_test( - "status", "subdir/", NULL, 4, 0, status_paths_range_4, NULL); -} - -static const char *status_paths_range_5[] = { - "subdir/modified_file", - NULL -}; - -void test_diff_iterator__workdir_1_ranged_5(void) -{ - workdir_iterator_test( - "status", "subdir/modified_file", "subdir/modified_file", - 1, 0, status_paths_range_5, NULL); -} - -void test_diff_iterator__workdir_1_ranged_empty_0(void) -{ - workdir_iterator_test( - "status", "\xff_does_not_exist", NULL, - 0, 0, NULL, NULL); -} - -void test_diff_iterator__workdir_1_ranged_empty_1(void) -{ - workdir_iterator_test( - "status", "empty", "empty", - 0, 0, NULL, NULL); -} - -void test_diff_iterator__workdir_1_ranged_empty_2(void) -{ - workdir_iterator_test( - "status", NULL, "aaaa_empty_before", - 0, 0, NULL, NULL); -} - -void test_diff_iterator__workdir_builtin_ignores(void) -{ - git_repository *repo = cl_git_sandbox_init("attr"); - git_iterator *i; - const git_index_entry *entry; - int idx; - static struct { - const char *path; - bool ignored; - } expected[] = { - { "dir/", true }, - { "file", false }, - { "ign", true }, - { "macro_bad", false }, - { "macro_test", false }, - { "root_test1", false }, - { "root_test2", false }, - { "root_test3", false }, - { "root_test4.txt", false }, - { "sub", false }, - { "sub/.gitattributes", false }, - { "sub/abc", false }, - { "sub/dir/", true }, - { "sub/file", false }, - { "sub/ign/", true }, - { "sub/sub", false }, - { "sub/sub/.gitattributes", false }, - { "sub/sub/dir", false }, /* file is not actually a dir */ - { "sub/sub/file", false }, - { NULL, false } - }; - - cl_git_pass(p_mkdir("attr/sub/sub/.git", 0777)); - cl_git_mkfile("attr/sub/.git", "whatever"); - - cl_git_pass(git_iterator_for_workdir( - &i, repo, GIT_ITERATOR_DONT_AUTOEXPAND, "dir", "sub/sub/file")); - cl_git_pass(git_iterator_current(&entry, i)); - - for (idx = 0; entry != NULL; ++idx) { - int ignored = git_iterator_current_is_ignored(i); - - cl_assert_equal_s(expected[idx].path, entry->path); - cl_assert_(ignored == expected[idx].ignored, expected[idx].path); - - if (!ignored && - (entry->mode == GIT_FILEMODE_TREE || - entry->mode == GIT_FILEMODE_COMMIT)) - { - /* it is possible to advance "into" a submodule */ - cl_git_pass(git_iterator_advance_into(&entry, i)); - } else { - int error = git_iterator_advance(&entry, i); - cl_assert(!error || error == GIT_ITEROVER); - } - } - - cl_assert(expected[idx].path == NULL); - - git_iterator_free(i); -} - -static void check_wd_first_through_third_range( - git_repository *repo, const char *start, const char *end) -{ - git_iterator *i; - const git_index_entry *entry; - int error, idx; - static const char *expected[] = { "FIRST", "second", "THIRD", NULL }; - - cl_git_pass(git_iterator_for_workdir( - &i, repo, GIT_ITERATOR_IGNORE_CASE, start, end)); - cl_git_pass(git_iterator_current(&entry, i)); - - for (idx = 0; entry != NULL; ++idx) { - cl_assert_equal_s(expected[idx], entry->path); - - error = git_iterator_advance(&entry, i); - cl_assert(!error || error == GIT_ITEROVER); - } - - cl_assert(expected[idx] == NULL); - - git_iterator_free(i); -} - -void test_diff_iterator__workdir_handles_icase_range(void) -{ - git_repository *repo; - - repo = cl_git_sandbox_init("empty_standard_repo"); - cl_git_remove_placeholders(git_repository_path(repo), "dummy-marker.txt"); - - cl_git_mkfile("empty_standard_repo/before", "whatever\n"); - cl_git_mkfile("empty_standard_repo/FIRST", "whatever\n"); - cl_git_mkfile("empty_standard_repo/second", "whatever\n"); - cl_git_mkfile("empty_standard_repo/THIRD", "whatever\n"); - cl_git_mkfile("empty_standard_repo/zafter", "whatever\n"); - cl_git_mkfile("empty_standard_repo/Zlast", "whatever\n"); - - check_wd_first_through_third_range(repo, "first", "third"); - check_wd_first_through_third_range(repo, "FIRST", "THIRD"); - check_wd_first_through_third_range(repo, "first", "THIRD"); - check_wd_first_through_third_range(repo, "FIRST", "third"); - check_wd_first_through_third_range(repo, "FirSt", "tHiRd"); -} - -static void check_tree_range( - git_repository *repo, - const char *start, - const char *end, - bool ignore_case, - int expected_count) -{ - git_tree *head; - git_iterator *i; - int error, count; - - cl_git_pass(git_repository_head_tree(&head, repo)); - - cl_git_pass(git_iterator_for_tree( - &i, head, - ignore_case ? GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE, - start, end)); - - for (count = 0; !(error = git_iterator_advance(NULL, i)); ++count) - /* count em up */; - - cl_assert_equal_i(GIT_ITEROVER, error); - cl_assert_equal_i(expected_count, count); - - git_iterator_free(i); - git_tree_free(head); -} - -void test_diff_iterator__tree_handles_icase_range(void) -{ - git_repository *repo; - - repo = cl_git_sandbox_init("testrepo"); - - check_tree_range(repo, "B", "C", false, 0); - check_tree_range(repo, "B", "C", true, 1); - check_tree_range(repo, "b", "c", false, 1); - check_tree_range(repo, "b", "c", true, 1); - - check_tree_range(repo, "a", "z", false, 3); - check_tree_range(repo, "a", "z", true, 4); - check_tree_range(repo, "A", "Z", false, 1); - check_tree_range(repo, "A", "Z", true, 4); - check_tree_range(repo, "a", "Z", false, 0); - check_tree_range(repo, "a", "Z", true, 4); - check_tree_range(repo, "A", "z", false, 4); - check_tree_range(repo, "A", "z", true, 4); - - check_tree_range(repo, "new.txt", "new.txt", true, 1); - check_tree_range(repo, "new.txt", "new.txt", false, 1); - check_tree_range(repo, "README", "README", true, 1); - check_tree_range(repo, "README", "README", false, 1); -} - -static void check_index_range( - git_repository *repo, - const char *start, - const char *end, - bool ignore_case, - int expected_count) -{ - git_index *index; - git_iterator *i; - int error, count, caps; - bool is_ignoring_case; - - cl_git_pass(git_repository_index(&index, repo)); - - caps = git_index_caps(index); - is_ignoring_case = ((caps & GIT_INDEXCAP_IGNORE_CASE) != 0); - - if (ignore_case != is_ignoring_case) - cl_git_pass(git_index_set_caps(index, caps ^ GIT_INDEXCAP_IGNORE_CASE)); - - cl_git_pass(git_iterator_for_index(&i, index, 0, start, end)); - - cl_assert(git_iterator_ignore_case(i) == ignore_case); - - for (count = 0; !(error = git_iterator_advance(NULL, i)); ++count) - /* count em up */; - - cl_assert_equal_i(GIT_ITEROVER, error); - cl_assert_equal_i(expected_count, count); - - git_iterator_free(i); - git_index_free(index); -} - -void test_diff_iterator__index_handles_icase_range(void) -{ - git_repository *repo; - git_index *index; - git_tree *head; - - repo = cl_git_sandbox_init("testrepo"); - - /* reset index to match HEAD */ - cl_git_pass(git_repository_head_tree(&head, repo)); - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_read_tree(index, head)); - cl_git_pass(git_index_write(index)); - git_tree_free(head); - git_index_free(index); - - /* do some ranged iterator checks toggling case sensitivity */ - check_index_range(repo, "B", "C", false, 0); - check_index_range(repo, "B", "C", true, 1); - check_index_range(repo, "a", "z", false, 3); - check_index_range(repo, "a", "z", true, 4); -} diff --git a/tests-clar/diff/notify.c b/tests-clar/diff/notify.c deleted file mode 100644 index cc33cb71c..000000000 --- a/tests-clar/diff/notify.c +++ /dev/null @@ -1,228 +0,0 @@ -#include "clar_libgit2.h" -#include "diff_helpers.h" - -static git_repository *g_repo = NULL; - -void test_diff_notify__initialize(void) -{ -} - -void test_diff_notify__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -static int assert_called_notifications( - const git_diff *diff_so_far, - const git_diff_delta *delta_to_add, - const char *matched_pathspec, - void *payload) -{ - bool found = false; - notify_expected *exp = (notify_expected*)payload; - notify_expected *e;; - - GIT_UNUSED(diff_so_far); - - for (e = exp; e->path != NULL; e++) { - if (strcmp(e->path, delta_to_add->new_file.path)) - continue; - - cl_assert_equal_s(e->matched_pathspec, matched_pathspec); - - found = true; - break; - } - - cl_assert(found); - return 0; -} - -static void test_notify( - char **searched_pathspecs, - int pathspecs_count, - notify_expected *expected_matched_pathspecs, - int expected_diffed_files_count) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - diff_expects exp; - - g_repo = cl_git_sandbox_init("status"); - - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - opts.notify_cb = assert_called_notifications; - opts.pathspec.strings = searched_pathspecs; - opts.pathspec.count = pathspecs_count; - - opts.notify_payload = expected_matched_pathspecs; - memset(&exp, 0, sizeof(exp)); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(expected_diffed_files_count, exp.files); - - git_diff_free(diff); -} - -void test_diff_notify__notify_single_pathspec(void) -{ - char *searched_pathspecs[] = { - "*_deleted", - }; - notify_expected expected_matched_pathspecs[] = { - { "file_deleted", "*_deleted" }, - { "staged_changes_file_deleted", "*_deleted" }, - { NULL, NULL } - }; - - test_notify(searched_pathspecs, 1, expected_matched_pathspecs, 2); -} - -void test_diff_notify__notify_multiple_pathspec(void) -{ - char *searched_pathspecs[] = { - "staged_changes_cant_find_me", - "subdir/modified_cant_find_me", - "subdir/*", - "staged*" - }; - notify_expected expected_matched_pathspecs[] = { - { "staged_changes_file_deleted", "staged*" }, - { "staged_changes_modified_file", "staged*" }, - { "staged_delete_modified_file", "staged*" }, - { "staged_new_file_deleted_file", "staged*" }, - { "staged_new_file_modified_file", "staged*" }, - { "subdir/deleted_file", "subdir/*" }, - { "subdir/modified_file", "subdir/*" }, - { "subdir/new_file", "subdir/*" }, - { NULL, NULL } - }; - - test_notify(searched_pathspecs, 4, expected_matched_pathspecs, 8); -} - -void test_diff_notify__notify_catchall_with_empty_pathspecs(void) -{ - char *searched_pathspecs[] = { - "", - "" - }; - notify_expected expected_matched_pathspecs[] = { - { "file_deleted", NULL }, - { "ignored_file", NULL }, - { "modified_file", NULL }, - { "new_file", NULL }, - { "\xe8\xbf\x99", NULL }, - { "staged_changes_file_deleted", NULL }, - { "staged_changes_modified_file", NULL }, - { "staged_delete_modified_file", NULL }, - { "staged_new_file_deleted_file", NULL }, - { "staged_new_file_modified_file", NULL }, - { "subdir/deleted_file", NULL }, - { "subdir/modified_file", NULL }, - { "subdir/new_file", NULL }, - { NULL, NULL } - }; - - test_notify(searched_pathspecs, 1, expected_matched_pathspecs, 13); -} - -void test_diff_notify__notify_catchall(void) -{ - char *searched_pathspecs[] = { - "*", - }; - notify_expected expected_matched_pathspecs[] = { - { "file_deleted", "*" }, - { "ignored_file", "*" }, - { "modified_file", "*" }, - { "new_file", "*" }, - { "\xe8\xbf\x99", "*" }, - { "staged_changes_file_deleted", "*" }, - { "staged_changes_modified_file", "*" }, - { "staged_delete_modified_file", "*" }, - { "staged_new_file_deleted_file", "*" }, - { "staged_new_file_modified_file", "*" }, - { "subdir/deleted_file", "*" }, - { "subdir/modified_file", "*" }, - { "subdir/new_file", "*" }, - { NULL, NULL } - }; - - test_notify(searched_pathspecs, 1, expected_matched_pathspecs, 13); -} - -static int abort_diff( - const git_diff *diff_so_far, - const git_diff_delta *delta_to_add, - const char *matched_pathspec, - void *payload) -{ - GIT_UNUSED(diff_so_far); - GIT_UNUSED(delta_to_add); - GIT_UNUSED(matched_pathspec); - GIT_UNUSED(payload); - - return -42; -} - -void test_diff_notify__notify_cb_can_abort_diff(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - char *pathspec = NULL; - - g_repo = cl_git_sandbox_init("status"); - - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - opts.notify_cb = abort_diff; - opts.pathspec.strings = &pathspec; - opts.pathspec.count = 1; - - pathspec = "file_deleted"; - cl_git_fail(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - pathspec = "staged_changes_modified_file"; - cl_git_fail(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); -} - -static int filter_all( - const git_diff *diff_so_far, - const git_diff_delta *delta_to_add, - const char *matched_pathspec, - void *payload) -{ - GIT_UNUSED(diff_so_far); - GIT_UNUSED(delta_to_add); - GIT_UNUSED(matched_pathspec); - GIT_UNUSED(payload); - - return 42; -} - -void test_diff_notify__notify_cb_can_be_used_as_filtering_function(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - char *pathspec = NULL; - diff_expects exp; - - g_repo = cl_git_sandbox_init("status"); - - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - opts.notify_cb = filter_all; - opts.pathspec.strings = &pathspec; - opts.pathspec.count = 1; - - pathspec = "*_deleted"; - memset(&exp, 0, sizeof(exp)); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(0, exp.files); - - git_diff_free(diff); -} diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c deleted file mode 100644 index 366e5da58..000000000 --- a/tests-clar/diff/patch.c +++ /dev/null @@ -1,571 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/sys/repository.h" - -#include "diff_helpers.h" -#include "repository.h" -#include "buf_text.h" - -static git_repository *g_repo = NULL; - -void test_diff_patch__initialize(void) -{ -} - -void test_diff_patch__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -#define EXPECTED_HEADER "diff --git a/subdir.txt b/subdir.txt\n" \ - "deleted file mode 100644\n" \ - "index e8ee89e..0000000\n" \ - "--- a/subdir.txt\n" \ - "+++ /dev/null\n" - -#define EXPECTED_HUNK "@@ -1,2 +0,0 @@\n" - -static int check_removal_cb( - const git_diff_delta *delta, - const git_diff_hunk *hunk, - const git_diff_line *line, - void *payload) -{ - GIT_UNUSED(payload); - - switch (line->origin) { - case GIT_DIFF_LINE_FILE_HDR: - cl_assert_equal_s(EXPECTED_HEADER, line->content); - cl_assert(hunk == NULL); - goto check_delta; - - case GIT_DIFF_LINE_HUNK_HDR: - cl_assert_equal_s(EXPECTED_HUNK, line->content); - /* Fall through */ - - case GIT_DIFF_LINE_CONTEXT: - case GIT_DIFF_LINE_DELETION: - goto check_hunk; - - default: - /* unexpected code path */ - return -1; - } - -check_hunk: - cl_assert(hunk != NULL); - cl_assert_equal_i(1, hunk->old_start); - cl_assert_equal_i(2, hunk->old_lines); - cl_assert_equal_i(0, hunk->new_start); - cl_assert_equal_i(0, hunk->new_lines); - -check_delta: - cl_assert_equal_s("subdir.txt", delta->old_file.path); - cl_assert_equal_s("subdir.txt", delta->new_file.path); - cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); - - return 0; -} - -void test_diff_patch__can_properly_display_the_removal_of_a_file(void) -{ - /* - * $ git diff 26a125e..735b6a2 - * diff --git a/subdir.txt b/subdir.txt - * deleted file mode 100644 - * index e8ee89e..0000000 - * --- a/subdir.txt - * +++ /dev/null - * @@ -1,2 +0,0 @@ - * -Is it a bird? - * -Is it a plane? - */ - - const char *one_sha = "26a125e"; - const char *another_sha = "735b6a2"; - git_tree *one, *another; - git_diff *diff; - - g_repo = cl_git_sandbox_init("status"); - - one = resolve_commit_oid_to_tree(g_repo, one_sha); - another = resolve_commit_oid_to_tree(g_repo, another_sha); - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, one, another, NULL)); - - cl_git_pass(git_diff_print( - diff, GIT_DIFF_FORMAT_PATCH, check_removal_cb, NULL)); - - git_diff_free(diff); - - git_tree_free(another); - git_tree_free(one); -} - -void test_diff_patch__to_string(void) -{ - const char *one_sha = "26a125e"; - const char *another_sha = "735b6a2"; - git_tree *one, *another; - git_diff *diff; - git_patch *patch; - char *text; - const char *expected = "diff --git a/subdir.txt b/subdir.txt\ndeleted file mode 100644\nindex e8ee89e..0000000\n--- a/subdir.txt\n+++ /dev/null\n@@ -1,2 +0,0 @@\n-Is it a bird?\n-Is it a plane?\n"; - - g_repo = cl_git_sandbox_init("status"); - - one = resolve_commit_oid_to_tree(g_repo, one_sha); - another = resolve_commit_oid_to_tree(g_repo, another_sha); - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, one, another, NULL)); - - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - - cl_git_pass(git_patch_to_str(&text, patch)); - - cl_assert_equal_s(expected, text); - - cl_assert_equal_sz(31, git_patch_size(patch, 0, 0, 0)); - cl_assert_equal_sz(31, git_patch_size(patch, 1, 0, 0)); - cl_assert_equal_sz(31 + 16, git_patch_size(patch, 1, 1, 0)); - cl_assert_equal_sz(strlen(expected), git_patch_size(patch, 1, 1, 1)); - - git__free(text); - git_patch_free(patch); - git_diff_free(diff); - git_tree_free(another); - git_tree_free(one); -} - -void test_diff_patch__config_options(void) -{ - const char *one_sha = "26a125e"; /* current HEAD */ - git_tree *one; - git_config *cfg; - git_diff *diff; - git_patch *patch; - char *text; - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - char *onefile = "staged_changes_modified_file"; - const char *expected1 = "diff --git c/staged_changes_modified_file i/staged_changes_modified_file\nindex 70bd944..906ee77 100644\n--- c/staged_changes_modified_file\n+++ i/staged_changes_modified_file\n@@ -1 +1,2 @@\n staged_changes_modified_file\n+staged_changes_modified_file\n"; - const char *expected2 = "diff --git i/staged_changes_modified_file w/staged_changes_modified_file\nindex 906ee77..011c344 100644\n--- i/staged_changes_modified_file\n+++ w/staged_changes_modified_file\n@@ -1,2 +1,3 @@\n staged_changes_modified_file\n staged_changes_modified_file\n+staged_changes_modified_file\n"; - const char *expected3 = "diff --git staged_changes_modified_file staged_changes_modified_file\nindex 906ee77..011c344 100644\n--- staged_changes_modified_file\n+++ staged_changes_modified_file\n@@ -1,2 +1,3 @@\n staged_changes_modified_file\n staged_changes_modified_file\n+staged_changes_modified_file\n"; - const char *expected4 = "diff --git staged_changes_modified_file staged_changes_modified_file\nindex 70bd9443ada0..906ee7711f4f 100644\n--- staged_changes_modified_file\n+++ staged_changes_modified_file\n@@ -1 +1,2 @@\n staged_changes_modified_file\n+staged_changes_modified_file\n"; - - g_repo = cl_git_sandbox_init("status"); - cl_git_pass(git_repository_config(&cfg, g_repo)); - one = resolve_commit_oid_to_tree(g_repo, one_sha); - opts.pathspec.count = 1; - opts.pathspec.strings = &onefile; - - - cl_git_pass(git_config_set_string(cfg, "diff.mnemonicprefix", "true")); - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, one, NULL, &opts)); - - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_git_pass(git_patch_to_str(&text, patch)); - cl_assert_equal_s(expected1, text); - - git__free(text); - git_patch_free(patch); - git_diff_free(diff); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_git_pass(git_patch_to_str(&text, patch)); - cl_assert_equal_s(expected2, text); - - git__free(text); - git_patch_free(patch); - git_diff_free(diff); - - - cl_git_pass(git_config_set_string(cfg, "diff.noprefix", "true")); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_git_pass(git_patch_to_str(&text, patch)); - cl_assert_equal_s(expected3, text); - - git__free(text); - git_patch_free(patch); - git_diff_free(diff); - - - cl_git_pass(git_config_set_int32(cfg, "core.abbrev", 12)); - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, one, NULL, &opts)); - - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_git_pass(git_patch_to_str(&text, patch)); - cl_assert_equal_s(expected4, text); - - git__free(text); - git_patch_free(patch); - git_diff_free(diff); - - git_tree_free(one); - git_config_free(cfg); -} - -void test_diff_patch__hunks_have_correct_line_numbers(void) -{ - git_config *cfg; - git_tree *head; - git_diff_options opt = GIT_DIFF_OPTIONS_INIT; - git_diff *diff; - git_patch *patch; - const git_diff_delta *delta; - const git_diff_hunk *hunk; - const git_diff_line *line; - size_t hunklen; - git_buf old_content = GIT_BUF_INIT, actual = GIT_BUF_INIT; - const char *new_content = "The Song of Seven Cities\n------------------------\n\nI WAS Lord of Cities very sumptuously builded.\nSeven roaring Cities paid me tribute from afar.\nIvory their outposts were--the guardrooms of them gilded,\nAnd garrisoned with Amazons invincible in war.\n\nThis is some new text;\nNot as good as the old text;\nBut here it is.\n\nSo they warred and trafficked only yesterday, my Cities.\nTo-day there is no mark or mound of where my Cities stood.\nFor the River rose at midnight and it washed away my Cities.\nThey are evened with Atlantis and the towns before the Flood.\n\nRain on rain-gorged channels raised the water-levels round them,\nFreshet backed on freshet swelled and swept their world from sight,\nTill the emboldened floods linked arms and, flashing forward, drowned them--\nDrowned my Seven Cities and their peoples in one night!\n\nLow among the alders lie their derelict foundations,\nThe beams wherein they trusted and the plinths whereon they built--\nMy rulers and their treasure and their unborn populations,\nDead, destroyed, aborted, and defiled with mud and silt!\n\nAnother replacement;\nBreaking up the poem;\nGenerating some hunks.\n\nTo the sound of trumpets shall their seed restore my Cities\nWealthy and well-weaponed, that once more may I behold\nAll the world go softly when it walks before my Cities,\nAnd the horses and the chariots fleeing from them as of old!\n\n -- Rudyard Kipling\n"; - - g_repo = cl_git_sandbox_init("renames"); - - cl_git_pass(git_config_new(&cfg)); - git_repository_set_config(g_repo, cfg); - git_config_free(cfg); - - git_repository_reinit_filesystem(g_repo, false); - - cl_git_pass( - git_futils_readbuffer(&old_content, "renames/songof7cities.txt")); - - cl_git_rewritefile("renames/songof7cities.txt", new_content); - - cl_git_pass(git_repository_head_tree(&head, g_repo)); - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, head, &opt)); - - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_assert((delta = git_patch_get_delta(patch)) != NULL); - - cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); - cl_assert_equal_i(2, (int)git_patch_num_hunks(patch)); - - /* check hunk 0 */ - - cl_git_pass( - git_patch_get_hunk(&hunk, &hunklen, patch, 0)); - - cl_assert_equal_i(18, (int)hunklen); - - cl_assert_equal_i(6, (int)hunk->old_start); - cl_assert_equal_i(15, (int)hunk->old_lines); - cl_assert_equal_i(6, (int)hunk->new_start); - cl_assert_equal_i(9, (int)hunk->new_lines); - - cl_assert_equal_i(18, (int)git_patch_num_lines_in_hunk(patch, 0)); - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 0)); - cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin); - cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); - cl_assert_equal_s("Ivory their outposts were--the guardrooms of them gilded,\n", actual.ptr); - cl_assert_equal_i(6, line->old_lineno); - cl_assert_equal_i(6, line->new_lineno); - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 3)); - cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); - cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); - cl_assert_equal_s("All the world went softly when it walked before my Cities--\n", actual.ptr); - cl_assert_equal_i(9, line->old_lineno); - cl_assert_equal_i(-1, line->new_lineno); - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 12)); - cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); - cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); - cl_assert_equal_s("This is some new text;\n", actual.ptr); - cl_assert_equal_i(-1, line->old_lineno); - cl_assert_equal_i(9, line->new_lineno); - - /* check hunk 1 */ - - cl_git_pass(git_patch_get_hunk(&hunk, &hunklen, patch, 1)); - - cl_assert_equal_i(18, (int)hunklen); - - cl_assert_equal_i(31, (int)hunk->old_start); - cl_assert_equal_i(15, (int)hunk->old_lines); - cl_assert_equal_i(25, (int)hunk->new_start); - cl_assert_equal_i(9, (int)hunk->new_lines); - - cl_assert_equal_i(18, (int)git_patch_num_lines_in_hunk(patch, 1)); - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 0)); - cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin); - cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); - cl_assert_equal_s("My rulers and their treasure and their unborn populations,\n", actual.ptr); - cl_assert_equal_i(31, line->old_lineno); - cl_assert_equal_i(25, line->new_lineno); - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 3)); - cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); - cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); - cl_assert_equal_s("The Daughters of the Palace whom they cherished in my Cities,\n", actual.ptr); - cl_assert_equal_i(34, line->old_lineno); - cl_assert_equal_i(-1, line->new_lineno); - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 12)); - cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); - cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); - cl_assert_equal_s("Another replacement;\n", actual.ptr); - cl_assert_equal_i(-1, line->old_lineno); - cl_assert_equal_i(28, line->new_lineno); - - git_patch_free(patch); - git_diff_free(diff); - - /* Let's check line numbers when there is no newline */ - - git_buf_rtrim(&old_content); - cl_git_rewritefile("renames/songof7cities.txt", old_content.ptr); - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, head, &opt)); - - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_assert((delta = git_patch_get_delta(patch)) != NULL); - - cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); - cl_assert_equal_i(1, (int)git_patch_num_hunks(patch)); - - /* check hunk 0 */ - - cl_git_pass(git_patch_get_hunk(&hunk, &hunklen, patch, 0)); - - cl_assert_equal_i(6, (int)hunklen); - - cl_assert_equal_i(46, (int)hunk->old_start); - cl_assert_equal_i(4, (int)hunk->old_lines); - cl_assert_equal_i(46, (int)hunk->new_start); - cl_assert_equal_i(4, (int)hunk->new_lines); - - cl_assert_equal_i(6, (int)git_patch_num_lines_in_hunk(patch, 0)); - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 1)); - cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin); - cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); - cl_assert_equal_s("And the horses and the chariots fleeing from them as of old!\n", actual.ptr); - cl_assert_equal_i(47, line->old_lineno); - cl_assert_equal_i(47, line->new_lineno); - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 2)); - cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin); - cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); - cl_assert_equal_s("\n", actual.ptr); - cl_assert_equal_i(48, line->old_lineno); - cl_assert_equal_i(48, line->new_lineno); - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 3)); - cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); - cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); - cl_assert_equal_s(" -- Rudyard Kipling\n", actual.ptr); - cl_assert_equal_i(49, line->old_lineno); - cl_assert_equal_i(-1, line->new_lineno); - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 4)); - cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); - cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); - cl_assert_equal_s(" -- Rudyard Kipling", actual.ptr); - cl_assert_equal_i(-1, line->old_lineno); - cl_assert_equal_i(49, line->new_lineno); - - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 5)); - cl_assert_equal_i(GIT_DIFF_LINE_DEL_EOFNL, (int)line->origin); - cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); - cl_assert_equal_s("\n\\ No newline at end of file\n", actual.ptr); - cl_assert_equal_i(-1, line->old_lineno); - cl_assert_equal_i(49, line->new_lineno); - - git_patch_free(patch); - git_diff_free(diff); - - git_buf_free(&actual); - git_buf_free(&old_content); - git_tree_free(head); -} - -static void check_single_patch_stats( - git_repository *repo, size_t hunks, - size_t adds, size_t dels, size_t ctxt, size_t *sizes, - const char *expected) -{ - git_diff *diff; - git_patch *patch; - const git_diff_delta *delta; - size_t actual_ctxt, actual_adds, actual_dels; - - cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); - - cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); - - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_assert((delta = git_patch_get_delta(patch)) != NULL); - cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); - - cl_assert_equal_i((int)hunks, (int)git_patch_num_hunks(patch)); - - cl_git_pass( git_patch_line_stats( - &actual_ctxt, &actual_adds, &actual_dels, patch) ); - - cl_assert_equal_sz(ctxt, actual_ctxt); - cl_assert_equal_sz(adds, actual_adds); - cl_assert_equal_sz(dels, actual_dels); - - if (expected != NULL) { - char *text; - cl_git_pass(git_patch_to_str(&text, patch)); - cl_assert_equal_s(expected, text); - git__free(text); - - cl_assert_equal_sz( - strlen(expected), git_patch_size(patch, 1, 1, 1)); - } - - if (sizes) { - if (sizes[0]) - cl_assert_equal_sz(sizes[0], git_patch_size(patch, 0, 0, 0)); - if (sizes[1]) - cl_assert_equal_sz(sizes[1], git_patch_size(patch, 1, 0, 0)); - if (sizes[2]) - cl_assert_equal_sz(sizes[2], git_patch_size(patch, 1, 1, 0)); - } - - /* walk lines in hunk with basic sanity checks */ - for (; hunks > 0; --hunks) { - size_t i, max_i; - const git_diff_line *line; - int last_new_lineno = -1, last_old_lineno = -1; - - max_i = git_patch_num_lines_in_hunk(patch, hunks - 1); - - for (i = 0; i < max_i; ++i) { - int expected = 1; - - cl_git_pass( - git_patch_get_line_in_hunk(&line, patch, hunks - 1, i)); - - if (line->origin == GIT_DIFF_LINE_ADD_EOFNL || - line->origin == GIT_DIFF_LINE_DEL_EOFNL || - line->origin == GIT_DIFF_LINE_CONTEXT_EOFNL) - expected = 0; - - if (line->old_lineno >= 0) { - if (last_old_lineno >= 0) - cl_assert_equal_i( - expected, line->old_lineno - last_old_lineno); - last_old_lineno = line->old_lineno; - } - - if (line->new_lineno >= 0) { - if (last_new_lineno >= 0) - cl_assert_equal_i( - expected, line->new_lineno - last_new_lineno); - last_new_lineno = line->new_lineno; - } - } - } - - git_patch_free(patch); - git_diff_free(diff); -} - -void test_diff_patch__line_counts_with_eofnl(void) -{ - git_config *cfg; - git_buf content = GIT_BUF_INIT; - const char *end; - git_index *index; - const char *expected = - /* below is pasted output of 'git diff' with fn context removed */ - "diff --git a/songof7cities.txt b/songof7cities.txt\n" - "index 378a7d9..3d0154e 100644\n" - "--- a/songof7cities.txt\n" - "+++ b/songof7cities.txt\n" - "@@ -42,7 +42,7 @@ With peoples undefeated of the dark, enduring blood.\n" - " \n" - " To the sound of trumpets shall their seed restore my Cities\n" - " Wealthy and well-weaponed, that once more may I behold\n" - "-All the world go softly when it walks before my Cities,\n" - "+#All the world go softly when it walks before my Cities,\n" - " And the horses and the chariots fleeing from them as of old!\n" - " \n" - " -- Rudyard Kipling\n" - "\\ No newline at end of file\n"; - size_t expected_sizes[3] = { 115, 119 + 115 + 114, 119 + 115 + 114 + 71 }; - - g_repo = cl_git_sandbox_init("renames"); - - cl_git_pass(git_config_new(&cfg)); - git_repository_set_config(g_repo, cfg); - git_config_free(cfg); - - git_repository_reinit_filesystem(g_repo, false); - - cl_git_pass(git_futils_readbuffer(&content, "renames/songof7cities.txt")); - - /* remove first line */ - - end = git_buf_cstr(&content) + git_buf_find(&content, '\n') + 1; - git_buf_consume(&content, end); - cl_git_rewritefile("renames/songof7cities.txt", content.ptr); - - check_single_patch_stats(g_repo, 1, 0, 1, 3, NULL, NULL); - - /* remove trailing whitespace */ - - git_buf_rtrim(&content); - cl_git_rewritefile("renames/songof7cities.txt", content.ptr); - - check_single_patch_stats(g_repo, 2, 1, 2, 6, NULL, NULL); - - /* add trailing whitespace */ - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); - cl_git_pass(git_index_write(index)); - git_index_free(index); - - cl_git_pass(git_buf_putc(&content, '\n')); - cl_git_rewritefile("renames/songof7cities.txt", content.ptr); - - check_single_patch_stats(g_repo, 1, 1, 1, 3, NULL, NULL); - - /* no trailing whitespace as context line */ - - { - /* walk back a couple lines, make space and insert char */ - char *scan = content.ptr + content.size; - int i; - - for (i = 0; i < 5; ++i) { - for (--scan; scan > content.ptr && *scan != '\n'; --scan) - /* seek to prev \n */; - } - cl_assert(scan > content.ptr); - - /* overwrite trailing \n with right-shifted content */ - memmove(scan + 1, scan, content.size - (scan - content.ptr) - 1); - /* insert '#' char into space we created */ - scan[1] = '#'; - } - cl_git_rewritefile("renames/songof7cities.txt", content.ptr); - - check_single_patch_stats( - g_repo, 1, 1, 1, 6, expected_sizes, expected); - - git_buf_free(&content); -} diff --git a/tests-clar/diff/pathspec.c b/tests-clar/diff/pathspec.c deleted file mode 100644 index 5761d2d2b..000000000 --- a/tests-clar/diff/pathspec.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "clar_libgit2.h" -#include "diff_helpers.h" - -static git_repository *g_repo = NULL; - -void test_diff_pathspec__initialize(void) -{ - g_repo = cl_git_sandbox_init("status"); -} - -void test_diff_pathspec__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_diff_pathspec__0(void) -{ - const char *a_commit = "26a125ee"; /* the current HEAD */ - const char *b_commit = "0017bd4a"; /* the start */ - git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); - git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit); - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - git_strarray paths = { NULL, 1 }; - char *path; - git_pathspec *ps; - git_pathspec_match_list *matches; - - cl_assert(a); - cl_assert(b); - - path = "*_file"; - paths.strings = &path; - cl_git_pass(git_pathspec_new(&ps, &paths)); - - cl_git_pass(git_pathspec_match_tree(&matches, a, GIT_PATHSPEC_DEFAULT, ps)); - cl_assert_equal_i(7, (int)git_pathspec_match_list_entrycount(matches)); - cl_assert_equal_s("current_file", git_pathspec_match_list_entry(matches,0)); - cl_assert(git_pathspec_match_list_diff_entry(matches,0) == NULL); - git_pathspec_match_list_free(matches); - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, NULL, a, &opts)); - - cl_git_pass(git_pathspec_match_diff( - &matches, diff, GIT_PATHSPEC_DEFAULT, ps)); - cl_assert_equal_i(7, (int)git_pathspec_match_list_entrycount(matches)); - cl_assert(git_pathspec_match_list_diff_entry(matches, 0) != NULL); - cl_assert(git_pathspec_match_list_entry(matches, 0) == NULL); - cl_assert_equal_s("current_file", - git_pathspec_match_list_diff_entry(matches,0)->new_file.path); - cl_assert_equal_i(GIT_DELTA_ADDED, - (int)git_pathspec_match_list_diff_entry(matches,0)->status); - git_pathspec_match_list_free(matches); - - git_diff_free(diff); - diff = NULL; - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); - - cl_git_pass(git_pathspec_match_diff( - &matches, diff, GIT_PATHSPEC_DEFAULT, ps)); - cl_assert_equal_i(3, (int)git_pathspec_match_list_entrycount(matches)); - cl_assert(git_pathspec_match_list_diff_entry(matches, 0) != NULL); - cl_assert(git_pathspec_match_list_entry(matches, 0) == NULL); - cl_assert_equal_s("subdir/current_file", - git_pathspec_match_list_diff_entry(matches,0)->new_file.path); - cl_assert_equal_i(GIT_DELTA_DELETED, - (int)git_pathspec_match_list_diff_entry(matches,0)->status); - git_pathspec_match_list_free(matches); - - git_diff_free(diff); - diff = NULL; - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); - - cl_git_pass(git_pathspec_match_diff( - &matches, diff, GIT_PATHSPEC_DEFAULT, ps)); - cl_assert_equal_i(4, (int)git_pathspec_match_list_entrycount(matches)); - cl_assert(git_pathspec_match_list_diff_entry(matches, 0) != NULL); - cl_assert(git_pathspec_match_list_entry(matches, 0) == NULL); - cl_assert_equal_s("modified_file", - git_pathspec_match_list_diff_entry(matches,0)->new_file.path); - cl_assert_equal_i(GIT_DELTA_MODIFIED, - (int)git_pathspec_match_list_diff_entry(matches,0)->status); - git_pathspec_match_list_free(matches); - - git_diff_free(diff); - diff = NULL; - - git_tree_free(a); - git_tree_free(b); - git_pathspec_free(ps); -} diff --git a/tests-clar/diff/rename.c b/tests-clar/diff/rename.c deleted file mode 100644 index 42bb65aa8..000000000 --- a/tests-clar/diff/rename.c +++ /dev/null @@ -1,1286 +0,0 @@ -#include "clar_libgit2.h" -#include "diff_helpers.h" -#include "buf_text.h" - -static git_repository *g_repo = NULL; - -void test_diff_rename__initialize(void) -{ - g_repo = cl_git_sandbox_init("renames"); - - cl_repo_set_bool(g_repo, "core.autocrlf", false); -} - -void test_diff_rename__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -/* - * Renames repo has: - * - * commit 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 - - * serving.txt (25 lines) - * sevencities.txt (50 lines) - * commit 2bc7f351d20b53f1c72c16c4b036e491c478c49a - - * serving.txt -> sixserving.txt (rename, no change, 100% match) - * sevencities.txt -> sevencities.txt (no change) - * sevencities.txt -> songofseven.txt (copy, no change, 100% match) - * commit 1c068dee5790ef1580cfc4cd670915b48d790084 - * songofseven.txt -> songofseven.txt (major rewrite, <20% match - split) - * sixserving.txt -> sixserving.txt (indentation change) - * sixserving.txt -> ikeepsix.txt (copy, add title, >80% match) - * sevencities.txt (no change) - * commit 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 - * songofseven.txt -> untimely.txt (rename, convert to crlf) - * ikeepsix.txt -> ikeepsix.txt (reorder sections in file) - * sixserving.txt -> sixserving.txt (whitespace change - not just indent) - * sevencities.txt -> songof7cities.txt (rename, small text changes) - */ - -void test_diff_rename__match_oid(void) -{ - const char *old_sha = "31e47d8c1fa36d7f8d537b96158e3f024de0a9f2"; - const char *new_sha = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; - git_tree *old_tree, *new_tree; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - diff_expects exp; - - old_tree = resolve_commit_oid_to_tree(g_repo, old_sha); - new_tree = resolve_commit_oid_to_tree(g_repo, new_sha); - - /* Must pass GIT_DIFF_INCLUDE_UNMODIFIED if you expect to emulate - * --find-copies-harder during rename transformion... - */ - diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; - - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, old_tree, new_tree, &diffopts)); - - /* git diff --no-renames \ - * 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 \ - * 2bc7f351d20b53f1c72c16c4b036e491c478c49a - */ - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - - /* git diff 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 \ - * 2bc7f351d20b53f1c72c16c4b036e491c478c49a - * don't use NULL opts to avoid config `diff.renames` contamination - */ - opts.flags = GIT_DIFF_FIND_RENAMES; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(3, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - - git_diff_free(diff); - - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, old_tree, new_tree, &diffopts)); - - /* git diff --find-copies-harder \ - * 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 \ - * 2bc7f351d20b53f1c72c16c4b036e491c478c49a - */ - opts.flags = GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(3, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - - git_diff_free(diff); - - git_tree_free(old_tree); - git_tree_free(new_tree); -} - -void test_diff_rename__checks_options_version(void) -{ - const char *old_sha = "31e47d8c1fa36d7f8d537b96158e3f024de0a9f2"; - const char *new_sha = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; - git_tree *old_tree, *new_tree; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - const git_error *err; - - old_tree = resolve_commit_oid_to_tree(g_repo, old_sha); - new_tree = resolve_commit_oid_to_tree(g_repo, new_sha); - diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, old_tree, new_tree, &diffopts)); - - opts.version = 0; - cl_git_fail(git_diff_find_similar(diff, &opts)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); - - giterr_clear(); - opts.version = 1024; - cl_git_fail(git_diff_find_similar(diff, &opts)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); - - git_diff_free(diff); - git_tree_free(old_tree); - git_tree_free(new_tree); -} - -void test_diff_rename__not_exact_match(void) -{ - const char *sha0 = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; - const char *sha1 = "1c068dee5790ef1580cfc4cd670915b48d790084"; - const char *sha2 = "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13"; - git_tree *old_tree, *new_tree; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - diff_expects exp; - - /* == Changes ===================================================== - * songofseven.txt -> songofseven.txt (major rewrite, <20% match - split) - * sixserving.txt -> sixserving.txt (indentation change) - * sixserving.txt -> ikeepsix.txt (copy, add title, >80% match) - * sevencities.txt (no change) - */ - - old_tree = resolve_commit_oid_to_tree(g_repo, sha0); - new_tree = resolve_commit_oid_to_tree(g_repo, sha1); - - /* Must pass GIT_DIFF_INCLUDE_UNMODIFIED if you expect to emulate - * --find-copies-harder during rename transformion... - */ - diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; - - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, old_tree, new_tree, &diffopts)); - - /* git diff --no-renames \ - * 2bc7f351d20b53f1c72c16c4b036e491c478c49a \ - * 1c068dee5790ef1580cfc4cd670915b48d790084 - */ - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); - - /* git diff -M 2bc7f351d20b53f1c72c16c4b036e491c478c49a \ - * 1c068dee5790ef1580cfc4cd670915b48d790084 - * - * must not pass NULL for opts because it will pick up environment - * values for "diff.renames" and test won't be consistent. - */ - opts.flags = GIT_DIFF_FIND_RENAMES; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); - - git_diff_free(diff); - - /* git diff -M -C \ - * 2bc7f351d20b53f1c72c16c4b036e491c478c49a \ - * 1c068dee5790ef1580cfc4cd670915b48d790084 - */ - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, old_tree, new_tree, &diffopts)); - - opts.flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]); - - git_diff_free(diff); - - /* git diff -M -C --find-copies-harder --break-rewrites \ - * 2bc7f351d20b53f1c72c16c4b036e491c478c49a \ - * 1c068dee5790ef1580cfc4cd670915b48d790084 - */ - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, old_tree, new_tree, &diffopts)); - - opts.flags = GIT_DIFF_FIND_ALL; - opts.break_rewrite_threshold = 70; - - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(5, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]); - - git_diff_free(diff); - - /* == Changes ===================================================== - * songofseven.txt -> untimely.txt (rename, convert to crlf) - * ikeepsix.txt -> ikeepsix.txt (reorder sections in file) - * sixserving.txt -> sixserving.txt (whitespace - not just indent) - * sevencities.txt -> songof7cities.txt (rename, small text changes) - */ - - git_tree_free(old_tree); - old_tree = new_tree; - new_tree = resolve_commit_oid_to_tree(g_repo, sha2); - - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, old_tree, new_tree, &diffopts)); - - /* git diff --no-renames \ - * 1c068dee5790ef1580cfc4cd670915b48d790084 \ - * 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 - */ - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(6, exp.files); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); - git_diff_free(diff); - - /* git diff -M -C \ - * 1c068dee5790ef1580cfc4cd670915b48d790084 \ - * 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 - */ - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, old_tree, new_tree, &diffopts)); - - opts.flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); - - git_diff_free(diff); - - /* git diff -M -C --find-copies-harder --break-rewrites \ - * 1c068dee5790ef1580cfc4cd670915b48d790084 \ - * 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 - * with libgit2 default similarity comparison... - */ - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, old_tree, new_tree, &diffopts)); - - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - /* the default match algorithm is going to find the internal - * whitespace differences in the lines of sixserving.txt to be - * significant enough that this will decide to split it into an ADD - * and a DELETE - */ - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(5, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); - - git_diff_free(diff); - - /* git diff -M -C --find-copies-harder --break-rewrites \ - * 1c068dee5790ef1580cfc4cd670915b48d790084 \ - * 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 - * with ignore_space whitespace comparision - */ - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, old_tree, new_tree, &diffopts)); - - opts.flags = GIT_DIFF_FIND_ALL | GIT_DIFF_FIND_IGNORE_WHITESPACE; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - /* Ignoring whitespace, this should no longer split sixserver.txt */ - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); - - git_diff_free(diff); - - git_tree_free(old_tree); - git_tree_free(new_tree); -} - -void test_diff_rename__handles_small_files(void) -{ - const char *tree_sha = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; - git_index *index; - git_tree *tree; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - - cl_git_pass(git_repository_index(&index, g_repo)); - - tree = resolve_commit_oid_to_tree(g_repo, tree_sha); - - cl_git_rewritefile("renames/songof7cities.txt", "single line\n"); - cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); - - cl_git_rewritefile("renames/untimely.txt", "untimely\n"); - cl_git_pass(git_index_add_bypath(index, "untimely.txt")); - - /* Tests that we can invoke find_similar on small files - * and that the GIT_EBUFS (too small) error code is not - * propagated to the caller. - */ - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - opts.flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES | - GIT_DIFF_FIND_AND_BREAK_REWRITES; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - git_diff_free(diff); - git_tree_free(tree); - git_index_free(index); -} - -void test_diff_rename__working_directory_changes(void) -{ - const char *sha0 = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; - const char *blobsha = "66311f5cfbe7836c27510a3ba2f43e282e2c8bba"; - git_oid id; - git_tree *tree; - git_blob *blob; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - diff_expects exp; - git_buf old_content = GIT_BUF_INIT, content = GIT_BUF_INIT;; - - tree = resolve_commit_oid_to_tree(g_repo, sha0); - diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED | GIT_DIFF_INCLUDE_UNTRACKED; - - /* - $ git cat-file -p 2bc7f351d20b53f1c72c16c4b036e491c478c49a^{tree} - - 100644 blob 66311f5cfbe7836c27510a3ba2f43e282e2c8bba sevencities.txt - 100644 blob ad0a8e55a104ac54a8a29ed4b84b49e76837a113 sixserving.txt - 100644 blob 66311f5cfbe7836c27510a3ba2f43e282e2c8bba songofseven.txt - - $ for f in *.txt; do - echo `git hash-object -t blob $f` $f - done - - eaf4a3e3bfe68585e90cada20736ace491cd100b ikeepsix.txt - f90d4fc20ecddf21eebe6a37e9225d244339d2b5 sixserving.txt - 4210ffd5c390b21dd5483375e75288dea9ede512 songof7cities.txt - 9a69d960ae94b060f56c2a8702545e2bb1abb935 untimely.txt - */ - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &diffopts)); - - /* git diff --no-renames 2bc7f351d20b53f1c72c16c4b036e491c478c49a */ - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(6, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); - - /* git diff -M 2bc7f351d20b53f1c72c16c4b036e491c478c49a */ - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(5, exp.files); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); - - /* rewrite files in the working directory with / without CRLF changes */ - - cl_git_pass( - git_futils_readbuffer(&old_content, "renames/songof7cities.txt")); - cl_git_pass( - git_buf_text_lf_to_crlf(&content, &old_content)); - cl_git_pass( - git_futils_writebuffer(&content, "renames/songof7cities.txt", 0, 0)); - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &diffopts)); - - /* git diff -M 2bc7f351d20b53f1c72c16c4b036e491c478c49a */ - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(5, exp.files); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); - - /* try a different whitespace option */ - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &diffopts)); - - opts.flags = GIT_DIFF_FIND_ALL | GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE; - opts.rename_threshold = 70; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(6, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); - - /* try a different matching option */ - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &diffopts)); - - opts.flags = GIT_DIFF_FIND_ALL | GIT_DIFF_FIND_EXACT_MATCH_ONLY; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(6, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); - - git_diff_free(diff); - - /* again with exact match blob */ - - cl_git_pass(git_oid_fromstr(&id, blobsha)); - cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); - cl_git_pass(git_buf_set( - &content, git_blob_rawcontent(blob), (size_t)git_blob_rawsize(blob))); - cl_git_rewritefile("renames/songof7cities.txt", content.ptr); - git_blob_free(blob); - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &diffopts)); - - opts.flags = GIT_DIFF_FIND_ALL | GIT_DIFF_FIND_EXACT_MATCH_ONLY; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - /* - fprintf(stderr, "\n\n"); - diff_print_raw(stderr, diff); - */ - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(5, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); - - git_tree_free(tree); - git_buf_free(&content); - git_buf_free(&old_content); -} - -void test_diff_rename__patch(void) -{ - const char *sha0 = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; - const char *sha1 = "1c068dee5790ef1580cfc4cd670915b48d790084"; - git_tree *old_tree, *new_tree; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - git_patch *patch; - const git_diff_delta *delta; - char *text; - const char *expected = "diff --git a/sixserving.txt b/ikeepsix.txt\nindex ad0a8e5..36020db 100644\n--- a/sixserving.txt\n+++ b/ikeepsix.txt\n@@ -1,3 +1,6 @@\n+I Keep Six Honest Serving-Men\n+=============================\n+\n I KEEP six honest serving-men\n (They taught me all I knew);\n Their names are What and Why and When\n@@ -21,4 +24,4 @@ She sends'em abroad on her own affairs,\n One million Hows, two million Wheres,\n And seven million Whys!\n \n- -- Rudyard Kipling\n+ -- Rudyard Kipling\n"; - - old_tree = resolve_commit_oid_to_tree(g_repo, sha0); - new_tree = resolve_commit_oid_to_tree(g_repo, sha1); - - diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, old_tree, new_tree, &diffopts)); - - opts.flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - /* == Changes ===================================================== - * sixserving.txt -> ikeepsix.txt (copy, add title, >80% match) - * sevencities.txt (no change) - * sixserving.txt -> sixserving.txt (indentation change) - * songofseven.txt -> songofseven.txt (major rewrite, <20% match - split) - */ - - cl_assert_equal_i(4, (int)git_diff_num_deltas(diff)); - - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_assert((delta = git_patch_get_delta(patch)) != NULL); - cl_assert_equal_i(GIT_DELTA_COPIED, (int)delta->status); - - cl_git_pass(git_patch_to_str(&text, patch)); - cl_assert_equal_s(expected, text); - git__free(text); - - git_patch_free(patch); - - cl_assert((delta = git_diff_get_delta(diff, 1)) != NULL); - cl_assert_equal_i(GIT_DELTA_UNMODIFIED, (int)delta->status); - - cl_assert((delta = git_diff_get_delta(diff, 2)) != NULL); - cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); - - cl_assert((delta = git_diff_get_delta(diff, 3)) != NULL); - cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); - - git_diff_free(diff); - git_tree_free(old_tree); - git_tree_free(new_tree); -} - -void test_diff_rename__file_exchange(void) -{ - git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT; - git_index *index; - git_tree *tree; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - diff_expects exp; - - cl_git_pass(git_futils_readbuffer(&c1, "renames/untimely.txt")); - cl_git_pass(git_futils_readbuffer(&c2, "renames/songof7cities.txt")); - cl_git_pass(git_futils_writebuffer(&c1, "renames/songof7cities.txt", 0, 0)); - cl_git_pass(git_futils_writebuffer(&c2, "renames/untimely.txt", 0, 0)); - - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_index_read_tree(index, tree)); - cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); - cl_git_pass(git_index_add_bypath(index, "untimely.txt")); - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(2, exp.files); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); - - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(2, exp.files); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); - - git_diff_free(diff); - git_tree_free(tree); - git_index_free(index); - - git_buf_free(&c1); - git_buf_free(&c2); -} - -void test_diff_rename__file_exchange_three(void) -{ - git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT, c3 = GIT_BUF_INIT; - git_index *index; - git_tree *tree; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - diff_expects exp; - - cl_git_pass(git_futils_readbuffer(&c1, "renames/untimely.txt")); - cl_git_pass(git_futils_readbuffer(&c2, "renames/songof7cities.txt")); - cl_git_pass(git_futils_readbuffer(&c3, "renames/ikeepsix.txt")); - - cl_git_pass(git_futils_writebuffer(&c1, "renames/ikeepsix.txt", 0, 0)); - cl_git_pass(git_futils_writebuffer(&c2, "renames/untimely.txt", 0, 0)); - cl_git_pass(git_futils_writebuffer(&c3, "renames/songof7cities.txt", 0, 0)); - - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_index_read_tree(index, tree)); - cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); - cl_git_pass(git_index_add_bypath(index, "untimely.txt")); - cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(3, exp.files); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); - - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(3, exp.files); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_RENAMED]); - - git_diff_free(diff); - git_tree_free(tree); - git_index_free(index); - - git_buf_free(&c1); - git_buf_free(&c2); - git_buf_free(&c3); -} - -void test_diff_rename__file_partial_exchange(void) -{ - git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT; - git_index *index; - git_tree *tree; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - diff_expects exp; - int i; - - cl_git_pass(git_futils_readbuffer(&c1, "renames/untimely.txt")); - cl_git_pass(git_futils_writebuffer(&c1, "renames/songof7cities.txt", 0, 0)); - for (i = 0; i < 100; ++i) - cl_git_pass(git_buf_puts(&c2, "this is not the content you are looking for\n")); - cl_git_pass(git_futils_writebuffer(&c2, "renames/untimely.txt", 0, 0)); - - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_index_read_tree(index, tree)); - cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); - cl_git_pass(git_index_add_bypath(index, "untimely.txt")); - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(2, exp.files); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); - - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(3, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - - git_diff_free(diff); - git_tree_free(tree); - git_index_free(index); - - git_buf_free(&c1); - git_buf_free(&c2); -} - -void test_diff_rename__rename_and_copy_from_same_source(void) -{ - git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT; - git_index *index; - git_tree *tree; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - diff_expects exp; - - /* put the first 2/3 of file into one new place - * and the second 2/3 of file into another new place - */ - cl_git_pass(git_futils_readbuffer(&c1, "renames/songof7cities.txt")); - cl_git_pass(git_buf_set(&c2, c1.ptr, c1.size)); - git_buf_truncate(&c1, c1.size * 2 / 3); - git_buf_consume(&c2, ((char *)c2.ptr) + (c2.size / 3)); - cl_git_pass(git_futils_writebuffer(&c1, "renames/song_a.txt", 0, 0)); - cl_git_pass(git_futils_writebuffer(&c2, "renames/song_b.txt", 0, 0)); - - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_index_read_tree(index, tree)); - cl_git_pass(git_index_add_bypath(index, "song_a.txt")); - cl_git_pass(git_index_add_bypath(index, "song_b.txt")); - - diffopts.flags = GIT_DIFF_INCLUDE_UNMODIFIED; - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(6, exp.files); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNMODIFIED]); - - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(6, exp.files); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_COPIED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNMODIFIED]); - - git_diff_free(diff); - git_tree_free(tree); - git_index_free(index); - - git_buf_free(&c1); - git_buf_free(&c2); -} - -void test_diff_rename__from_deleted_to_split(void) -{ - git_buf c1 = GIT_BUF_INIT; - git_index *index; - git_tree *tree; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - diff_expects exp; - - /* old file is missing, new file is actually old file renamed */ - - cl_git_pass(git_futils_readbuffer(&c1, "renames/songof7cities.txt")); - cl_git_pass(git_futils_writebuffer(&c1, "renames/untimely.txt", 0, 0)); - - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_index_read_tree(index, tree)); - cl_git_pass(git_index_remove_bypath(index, "songof7cities.txt")); - cl_git_pass(git_index_add_bypath(index, "untimely.txt")); - - diffopts.flags = GIT_DIFF_INCLUDE_UNMODIFIED; - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNMODIFIED]); - - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNMODIFIED]); - - git_diff_free(diff); - git_tree_free(tree); - git_index_free(index); - - git_buf_free(&c1); -} - -struct rename_expected -{ - size_t len; - - unsigned int *status; - const char **sources; - const char **targets; - - size_t idx; -}; - -int test_names_expected(const git_diff_delta *delta, float progress, void *p) -{ - struct rename_expected *expected = p; - - GIT_UNUSED(progress); - - cl_assert(expected->idx < expected->len); - - cl_assert_equal_i(delta->status, expected->status[expected->idx]); - - cl_assert(git__strcmp(expected->sources[expected->idx], - delta->old_file.path) == 0); - cl_assert(git__strcmp(expected->targets[expected->idx], - delta->new_file.path) == 0); - - expected->idx++; - - return 0; -} - -void test_diff_rename__rejected_match_can_match_others(void) -{ - git_reference *head, *selfsimilar; - git_index *index; - git_tree *tree; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; - git_buf one = GIT_BUF_INIT, two = GIT_BUF_INIT; - unsigned int status[] = { GIT_DELTA_RENAMED, GIT_DELTA_RENAMED }; - const char *sources[] = { "Class1.cs", "Class2.cs" }; - const char *targets[] = { "ClassA.cs", "ClassB.cs" }; - struct rename_expected expect = { 2, status, sources, targets }; - char *ptr; - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); - cl_git_pass(git_reference_symbolic_set_target( - &selfsimilar, head, "refs/heads/renames_similar")); - cl_git_pass(git_checkout_head(g_repo, &opts)); - cl_git_pass(git_repository_index(&index, g_repo)); - - cl_git_pass(git_futils_readbuffer(&one, "renames/Class1.cs")); - cl_git_pass(git_futils_readbuffer(&two, "renames/Class2.cs")); - - cl_git_pass(p_unlink("renames/Class1.cs")); - cl_git_pass(p_unlink("renames/Class2.cs")); - - cl_git_pass(git_index_remove_bypath(index, "Class1.cs")); - cl_git_pass(git_index_remove_bypath(index, "Class2.cs")); - - cl_assert(ptr = strstr(one.ptr, "Class1")); - ptr[5] = 'A'; - - cl_assert(ptr = strstr(two.ptr, "Class2")); - ptr[5] = 'B'; - - cl_git_pass( - git_futils_writebuffer(&one, "renames/ClassA.cs", O_RDWR|O_CREAT, 0777)); - cl_git_pass( - git_futils_writebuffer(&two, "renames/ClassB.cs", O_RDWR|O_CREAT, 0777)); - - cl_git_pass(git_index_add_bypath(index, "ClassA.cs")); - cl_git_pass(git_index_add_bypath(index, "ClassB.cs")); - - cl_git_pass(git_index_write(index)); - - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass( - git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - cl_git_pass(git_diff_find_similar(diff, &findopts)); - - cl_git_pass( - git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); - - git_diff_free(diff); - git_tree_free(tree); - git_index_free(index); - git_reference_free(head); - git_reference_free(selfsimilar); - git_buf_free(&one); - git_buf_free(&two); -} - -static void write_similarity_file_two(const char *filename, size_t b_lines) -{ - git_buf contents = GIT_BUF_INIT; - size_t i; - - for (i = 0; i < b_lines; i++) - git_buf_printf(&contents, "%02d - bbbbb\r\n", (int)(i+1)); - - for (i = b_lines; i < 50; i++) - git_buf_printf(&contents, "%02d - aaaaa%s", (int)(i+1), (i == 49 ? "" : "\r\n")); - - cl_git_pass( - git_futils_writebuffer(&contents, filename, O_RDWR|O_CREAT, 0777)); - - git_buf_free(&contents); -} - -void test_diff_rename__rejected_match_can_match_others_two(void) -{ - git_reference *head, *selfsimilar; - git_index *index; - git_tree *tree; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; - unsigned int status[] = { GIT_DELTA_RENAMED, GIT_DELTA_RENAMED }; - const char *sources[] = { "a.txt", "b.txt" }; - const char *targets[] = { "c.txt", "d.txt" }; - struct rename_expected expect = { 2, status, sources, targets }; - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); - cl_git_pass(git_reference_symbolic_set_target( - &selfsimilar, head, "refs/heads/renames_similar_two")); - cl_git_pass(git_checkout_head(g_repo, &opts)); - cl_git_pass(git_repository_index(&index, g_repo)); - - cl_git_pass(p_unlink("renames/a.txt")); - cl_git_pass(p_unlink("renames/b.txt")); - - cl_git_pass(git_index_remove_bypath(index, "a.txt")); - cl_git_pass(git_index_remove_bypath(index, "b.txt")); - - write_similarity_file_two("renames/c.txt", 7); - write_similarity_file_two("renames/d.txt", 8); - - cl_git_pass(git_index_add_bypath(index, "c.txt")); - cl_git_pass(git_index_add_bypath(index, "d.txt")); - - cl_git_pass(git_index_write(index)); - - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass( - git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - cl_git_pass(git_diff_find_similar(diff, &findopts)); - - cl_git_pass( - git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); - cl_assert(expect.idx > 0); - - git_diff_free(diff); - git_tree_free(tree); - git_index_free(index); - git_reference_free(head); - git_reference_free(selfsimilar); -} - -void test_diff_rename__rejected_match_can_match_others_three(void) -{ - git_reference *head, *selfsimilar; - git_index *index; - git_tree *tree; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; - - /* Both cannot be renames from a.txt */ - unsigned int status[] = { GIT_DELTA_ADDED, GIT_DELTA_RENAMED }; - const char *sources[] = { "0001.txt", "a.txt" }; - const char *targets[] = { "0001.txt", "0002.txt" }; - struct rename_expected expect = { 2, status, sources, targets }; - - opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); - cl_git_pass(git_reference_symbolic_set_target( - &selfsimilar, head, "refs/heads/renames_similar_two")); - cl_git_pass(git_checkout_head(g_repo, &opts)); - cl_git_pass(git_repository_index(&index, g_repo)); - - cl_git_pass(p_unlink("renames/a.txt")); - - cl_git_pass(git_index_remove_bypath(index, "a.txt")); - - write_similarity_file_two("renames/0001.txt", 7); - write_similarity_file_two("renames/0002.txt", 0); - - cl_git_pass(git_index_add_bypath(index, "0001.txt")); - cl_git_pass(git_index_add_bypath(index, "0002.txt")); - - cl_git_pass(git_index_write(index)); - - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass( - git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - cl_git_pass(git_diff_find_similar(diff, &findopts)); - - cl_git_pass( - git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); - - cl_assert(expect.idx == expect.len); - - git_diff_free(diff); - git_tree_free(tree); - git_index_free(index); - git_reference_free(head); - git_reference_free(selfsimilar); -} - -void test_diff_rename__can_rename_from_rewrite(void) -{ - git_index *index; - git_tree *tree; - git_diff *diff; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; - - unsigned int status[] = { GIT_DELTA_RENAMED, GIT_DELTA_RENAMED }; - const char *sources[] = { "ikeepsix.txt", "songof7cities.txt" }; - const char *targets[] = { "songof7cities.txt", "this-is-a-rename.txt" }; - struct rename_expected expect = { 2, status, sources, targets }; - - cl_git_pass(git_repository_index(&index, g_repo)); - - cl_git_pass(p_rename("renames/songof7cities.txt", "renames/this-is-a-rename.txt")); - cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/songof7cities.txt")); - - cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); - - cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); - cl_git_pass(git_index_add_bypath(index, "this-is-a-rename.txt")); - - cl_git_pass(git_index_write(index)); - - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass( - git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - findopts.flags |= GIT_DIFF_FIND_AND_BREAK_REWRITES | - GIT_DIFF_FIND_REWRITES | - GIT_DIFF_FIND_RENAMES_FROM_REWRITES; - - cl_git_pass(git_diff_find_similar(diff, &findopts)); - - cl_git_pass( - git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); - - cl_assert(expect.idx == expect.len); - - git_diff_free(diff); - git_tree_free(tree); - git_index_free(index); -} - -void test_diff_rename__case_changes_are_split(void) -{ - git_index *index; - git_tree *tree; - git_diff *diff = NULL; - diff_expects exp; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - - cl_git_pass(git_repository_index(&index, g_repo)); - - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/IKEEPSIX.txt")); - - cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_add_bypath(index, "IKEEPSIX.txt")); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, NULL)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(2, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); - - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(1, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - - git_diff_free(diff); - git_index_free(index); - git_tree_free(tree); -} - -void test_diff_rename__unmodified_can_be_renamed(void) -{ - git_index *index; - git_tree *tree; - git_diff *diff = NULL; - diff_expects exp; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/ikeepsix2.txt")); - - cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_add_bypath(index, "ikeepsix2.txt")); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(2, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); - - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(1, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(1, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - - git_diff_free(diff); - git_index_free(index); - git_tree_free(tree); -} - -void test_diff_rename__rewrite_on_single_file(void) -{ - git_index *index; - git_diff *diff = NULL; - diff_expects exp; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; - - diffopts.flags = GIT_DIFF_INCLUDE_UNTRACKED; - - findopts.flags = GIT_DIFF_FIND_FOR_UNTRACKED | - GIT_DIFF_FIND_AND_BREAK_REWRITES | - GIT_DIFF_FIND_RENAMES_FROM_REWRITES; - - cl_git_pass(git_repository_index(&index, g_repo)); - - cl_git_rewritefile("renames/ikeepsix.txt", - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n"); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &diffopts)); - cl_git_pass(git_diff_find_similar(diff, &findopts)); - - memset(&exp, 0, sizeof(exp)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(2, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); - git_index_free(index); -} diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c deleted file mode 100644 index 24545b2c7..000000000 --- a/tests-clar/diff/submodules.c +++ /dev/null @@ -1,423 +0,0 @@ -#include "clar_libgit2.h" -#include "repository.h" -#include "posix.h" -#include "../submodule/submodule_helpers.h" - -static git_repository *g_repo = NULL; - -void test_diff_submodules__initialize(void) -{ -} - -void test_diff_submodules__cleanup(void) -{ -} - -static void check_diff_patches_at_line( - git_diff *diff, const char **expected, const char *file, int line) -{ - const git_diff_delta *delta; - git_patch *patch = NULL; - size_t d, num_d = git_diff_num_deltas(diff); - char *patch_text; - - for (d = 0; d < num_d; ++d, git_patch_free(patch)) { - cl_git_pass(git_patch_from_diff(&patch, diff, d)); - cl_assert((delta = git_patch_get_delta(patch)) != NULL); - - if (delta->status == GIT_DELTA_UNMODIFIED) { - cl_assert_at_line(expected[d] == NULL, file, line); - continue; - } - - if (expected[d] && !strcmp(expected[d], "")) - continue; - if (expected[d] && !strcmp(expected[d], "")) { - cl_git_pass(git_patch_to_str(&patch_text, patch)); - cl_assert_at_line(!strcmp(expected[d], ""), file, line); - } - - cl_git_pass(git_patch_to_str(&patch_text, patch)); - - clar__assert_equal( - file, line, "expected diff did not match actual diff", 1, - "%s", expected[d], patch_text); - git__free(patch_text); - } - - cl_assert_at_line(expected[d] && !strcmp(expected[d], ""), file, line); -} - -#define check_diff_patches(diff, exp) \ - check_diff_patches_at_line(diff, exp, __FILE__, __LINE__) - -void test_diff_submodules__unmodified_submodule(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - static const char *expected[] = { - "", /* .gitmodules */ - NULL, /* added */ - NULL, /* ignored */ - "diff --git a/modified b/modified\nindex 092bfb9..452216e 100644\n--- a/modified\n+++ b/modified\n@@ -1 +1,2 @@\n-yo\n+changed\n+\n", /* modified */ - NULL, /* testrepo.git */ - NULL, /* unmodified */ - NULL, /* untracked */ - "" - }; - - g_repo = setup_fixture_submodules(); - - opts.flags = GIT_DIFF_INCLUDE_IGNORED | - GIT_DIFF_INCLUDE_UNTRACKED | - GIT_DIFF_INCLUDE_UNMODIFIED; - opts.old_prefix = "a"; opts.new_prefix = "b"; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected); - git_diff_free(diff); -} - -void test_diff_submodules__dirty_submodule(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - static const char *expected[] = { - "", /* .gitmodules */ - NULL, /* added */ - NULL, /* ignored */ - "diff --git a/modified b/modified\nindex 092bfb9..452216e 100644\n--- a/modified\n+++ b/modified\n@@ -1 +1,2 @@\n-yo\n+changed\n+\n", /* modified */ - "diff --git a/testrepo b/testrepo\nindex a65fedf..a65fedf 160000\n--- a/testrepo\n+++ b/testrepo\n@@ -1 +1 @@\n-Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750\n+Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750-dirty\n", /* testrepo.git */ - NULL, /* unmodified */ - NULL, /* untracked */ - "" - }; - - g_repo = setup_fixture_submodules(); - - cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); - cl_git_mkfile("submodules/testrepo/all_new.txt", "never seen before"); - - opts.flags = GIT_DIFF_INCLUDE_IGNORED | - GIT_DIFF_INCLUDE_UNTRACKED | - GIT_DIFF_INCLUDE_UNMODIFIED; - opts.old_prefix = "a"; opts.new_prefix = "b"; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected); - git_diff_free(diff); -} - -void test_diff_submodules__dirty_submodule_2(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL, *diff2 = NULL; - char *smpath = "testrepo"; - static const char *expected_none[] = { "" }; - static const char *expected_dirty[] = { - "diff --git a/testrepo b/testrepo\nindex a65fedf..a65fedf 160000\n--- a/testrepo\n+++ b/testrepo\n@@ -1 +1 @@\n-Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750\n+Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750-dirty\n", /* testrepo.git */ - "" - }; - - g_repo = setup_fixture_submodules(); - - cl_git_pass(git_submodule_reload_all(g_repo)); - - opts.flags = GIT_DIFF_INCLUDE_UNTRACKED | - GIT_DIFF_SHOW_UNTRACKED_CONTENT | - GIT_DIFF_RECURSE_UNTRACKED_DIRS | - GIT_DIFF_DISABLE_PATHSPEC_MATCH; - opts.old_prefix = "a"; opts.new_prefix = "b"; - opts.pathspec.count = 1; - opts.pathspec.strings = &smpath; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_none); - git_diff_free(diff); - - cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); - cl_git_mkfile("submodules/testrepo/all_new.txt", "never seen before"); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_dirty); - - { - git_tree *head; - - cl_git_pass(git_repository_head_tree(&head, g_repo)); - cl_git_pass(git_diff_tree_to_index(&diff2, g_repo, head, NULL, &opts)); - cl_git_pass(git_diff_merge(diff, diff2)); - git_diff_free(diff2); - git_tree_free(head); - - check_diff_patches(diff, expected_dirty); - } - - git_diff_free(diff); - - cl_git_pass(git_submodule_reload_all(g_repo)); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_dirty); - git_diff_free(diff); -} - -void test_diff_submodules__submod2_index_to_wd(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - static const char *expected[] = { - "", /* .gitmodules */ - "diff --git a/sm_changed_file b/sm_changed_file\nindex 4800958..4800958 160000\n--- a/sm_changed_file\n+++ b/sm_changed_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_file */ - "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ - "diff --git a/sm_changed_index b/sm_changed_index\nindex 4800958..4800958 160000\n--- a/sm_changed_index\n+++ b/sm_changed_index\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_index */ - "diff --git a/sm_changed_untracked_file b/sm_changed_untracked_file\nindex 4800958..4800958 160000\n--- a/sm_changed_untracked_file\n+++ b/sm_changed_untracked_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_untracked_file */ - "diff --git a/sm_missing_commits b/sm_missing_commits\nindex 4800958..5e49635 160000\n--- a/sm_missing_commits\n+++ b/sm_missing_commits\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 5e4963595a9774b90524d35a807169049de8ccad\n", /* sm_missing_commits */ - "" - }; - - g_repo = setup_fixture_submod2(); - - opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; - opts.old_prefix = "a"; opts.new_prefix = "b"; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected); - git_diff_free(diff); -} - -void test_diff_submodules__submod2_head_to_index(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_tree *head; - git_diff *diff = NULL; - static const char *expected[] = { - "", /* .gitmodules */ - "diff --git a/sm_added_and_uncommited b/sm_added_and_uncommited\nnew file mode 160000\nindex 0000000..4800958\n--- /dev/null\n+++ b/sm_added_and_uncommited\n@@ -0,0 +1 @@\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n", /* sm_added_and_uncommited */ - "" - }; - - g_repo = setup_fixture_submod2(); - - cl_git_pass(git_repository_head_tree(&head, g_repo)); - - opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; - opts.old_prefix = "a"; opts.new_prefix = "b"; - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, head, NULL, &opts)); - check_diff_patches(diff, expected); - git_diff_free(diff); - - git_tree_free(head); -} - -void test_diff_submodules__invalid_cache(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - git_submodule *sm; - char *smpath = "sm_changed_head"; - git_repository *smrepo; - git_index *smindex; - static const char *expected_baseline[] = { - "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ - "" - }; - static const char *expected_unchanged[] = { "" }; - static const char *expected_dirty[] = { - "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247-dirty\n", - "" - }; - static const char *expected_moved[] = { - "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..7002348 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 700234833f6ccc20d744b238612646be071acaae\n", - "" - }; - static const char *expected_moved_dirty[] = { - "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..7002348 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 700234833f6ccc20d744b238612646be071acaae-dirty\n", - "" - }; - - g_repo = setup_fixture_submod2(); - - opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; - opts.old_prefix = "a"; opts.new_prefix = "b"; - opts.pathspec.count = 1; - opts.pathspec.strings = &smpath; - - /* baseline */ - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_baseline); - git_diff_free(diff); - - /* update index with new HEAD */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath)); - cl_git_pass(git_submodule_add_to_index(sm, 1)); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_unchanged); - git_diff_free(diff); - - /* create untracked file in submodule working directory */ - cl_git_mkfile("submod2/sm_changed_head/new_around_here", "hello"); - git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_NONE); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_dirty); - git_diff_free(diff); - - git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_UNTRACKED); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_unchanged); - git_diff_free(diff); - - /* modify tracked file in submodule working directory */ - cl_git_append2file( - "submod2/sm_changed_head/file_to_modify", "\nmore stuff\n"); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_dirty); - git_diff_free(diff); - - cl_git_pass(git_submodule_reload_all(g_repo)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath)); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_dirty); - git_diff_free(diff); - - git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_unchanged); - git_diff_free(diff); - - /* add file to index in submodule */ - cl_git_pass(git_submodule_open(&smrepo, sm)); - cl_git_pass(git_repository_index(&smindex, smrepo)); - cl_git_pass(git_index_add_bypath(smindex, "file_to_modify")); - - git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_UNTRACKED); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_dirty); - git_diff_free(diff); - - git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_unchanged); - git_diff_free(diff); - - /* commit changed index of submodule */ - cl_repo_commit_from_index(NULL, smrepo, NULL, 1372350000, "Move it"); - - git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_moved); - git_diff_free(diff); - - git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_ALL); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_unchanged); - git_diff_free(diff); - - git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_NONE); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_moved_dirty); - git_diff_free(diff); - - p_unlink("submod2/sm_changed_head/new_around_here"); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_moved); - git_diff_free(diff); - - git_index_free(smindex); - git_repository_free(smrepo); -} - -void test_diff_submodules__diff_ignore_options(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - git_config *cfg; - static const char *expected_normal[] = { - "", /* .gitmodules */ - "diff --git a/sm_changed_file b/sm_changed_file\nindex 4800958..4800958 160000\n--- a/sm_changed_file\n+++ b/sm_changed_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_file */ - "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ - "diff --git a/sm_changed_index b/sm_changed_index\nindex 4800958..4800958 160000\n--- a/sm_changed_index\n+++ b/sm_changed_index\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_index */ - "diff --git a/sm_changed_untracked_file b/sm_changed_untracked_file\nindex 4800958..4800958 160000\n--- a/sm_changed_untracked_file\n+++ b/sm_changed_untracked_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_untracked_file */ - "diff --git a/sm_missing_commits b/sm_missing_commits\nindex 4800958..5e49635 160000\n--- a/sm_missing_commits\n+++ b/sm_missing_commits\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 5e4963595a9774b90524d35a807169049de8ccad\n", /* sm_missing_commits */ - "" - }; - static const char *expected_ignore_all[] = { - "", /* .gitmodules */ - "" - }; - static const char *expected_ignore_dirty[] = { - "", /* .gitmodules */ - "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ - "diff --git a/sm_missing_commits b/sm_missing_commits\nindex 4800958..5e49635 160000\n--- a/sm_missing_commits\n+++ b/sm_missing_commits\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 5e4963595a9774b90524d35a807169049de8ccad\n", /* sm_missing_commits */ - "" - }; - - g_repo = setup_fixture_submod2(); - - opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; - opts.old_prefix = "a"; opts.new_prefix = "b"; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_normal); - git_diff_free(diff); - - opts.flags |= GIT_DIFF_IGNORE_SUBMODULES; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_ignore_all); - git_diff_free(diff); - - opts.flags &= ~GIT_DIFF_IGNORE_SUBMODULES; - opts.ignore_submodules = GIT_SUBMODULE_IGNORE_ALL; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_ignore_all); - git_diff_free(diff); - - opts.ignore_submodules = GIT_SUBMODULE_IGNORE_DIRTY; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_ignore_dirty); - git_diff_free(diff); - - opts.ignore_submodules = 0; - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_set_bool(cfg, "diff.ignoreSubmodules", false)); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_normal); - git_diff_free(diff); - - cl_git_pass(git_config_set_bool(cfg, "diff.ignoreSubmodules", true)); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_ignore_all); - git_diff_free(diff); - - cl_git_pass(git_config_set_string(cfg, "diff.ignoreSubmodules", "none")); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_normal); - git_diff_free(diff); - - cl_git_pass(git_config_set_string(cfg, "diff.ignoreSubmodules", "dirty")); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - check_diff_patches(diff, expected_ignore_dirty); - git_diff_free(diff); - - git_config_free(cfg); -} diff --git a/tests-clar/diff/tree.c b/tests-clar/diff/tree.c deleted file mode 100644 index 582174b8b..000000000 --- a/tests-clar/diff/tree.c +++ /dev/null @@ -1,526 +0,0 @@ -#include "clar_libgit2.h" -#include "diff_helpers.h" - -static git_repository *g_repo = NULL; -static git_diff_options opts; -static git_diff *diff; -static git_tree *a, *b; -static diff_expects expect; - -void test_diff_tree__initialize(void) -{ - cl_git_pass(git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION)); - - memset(&expect, 0, sizeof(expect)); - - diff = NULL; - a = NULL; - b = NULL; -} - -void test_diff_tree__cleanup(void) -{ - git_diff_free(diff); - git_tree_free(a); - git_tree_free(b); - - cl_git_sandbox_cleanup(); - -} - -void test_diff_tree__0(void) -{ - /* grabbed a couple of commit oids from the history of the attr repo */ - const char *a_commit = "605812a"; - const char *b_commit = "370fe9ec22"; - const char *c_commit = "f5b0af1fb4f5c"; - git_tree *c; - - g_repo = cl_git_sandbox_init("attr"); - - cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); - cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); - cl_assert((c = resolve_commit_oid_to_tree(g_repo, c_commit)) != NULL); - - opts.context_lines = 1; - opts.interhunk_lines = 1; - - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); - - cl_assert_equal_i(5, expect.files); - cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, expect.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); - - cl_assert_equal_i(5, expect.hunks); - - cl_assert_equal_i(7 + 24 + 1 + 6 + 6, expect.lines); - cl_assert_equal_i(1, expect.line_ctxt); - cl_assert_equal_i(24 + 1 + 5 + 5, expect.line_adds); - cl_assert_equal_i(7 + 1, expect.line_dels); - - git_diff_free(diff); - diff = NULL; - - memset(&expect, 0, sizeof(expect)); - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, c, b, &opts)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); - - cl_assert_equal_i(2, expect.files); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); - - cl_assert_equal_i(2, expect.hunks); - - cl_assert_equal_i(8 + 15, expect.lines); - cl_assert_equal_i(1, expect.line_ctxt); - cl_assert_equal_i(1, expect.line_adds); - cl_assert_equal_i(7 + 14, expect.line_dels); - - git_tree_free(c); -} - -#define DIFF_OPTS(FLAGS, CTXT) \ - {GIT_DIFF_OPTIONS_VERSION, (FLAGS), GIT_SUBMODULE_IGNORE_DEFAULT, \ - {NULL,0}, NULL, NULL, (CTXT), 1} - -void test_diff_tree__options(void) -{ - /* grabbed a couple of commit oids from the history of the attr repo */ - const char *a_commit = "6bab5c79cd5140d0"; - const char *b_commit = "605812ab7fe421fdd"; - const char *c_commit = "f5b0af1fb4f5"; - const char *d_commit = "a97cc019851"; - git_tree *c, *d; - diff_expects actual; - int test_ab_or_cd[] = { 0, 0, 0, 0, 1, 1, 1, 1, 1 }; - git_diff_options test_options[] = { - /* a vs b tests */ - DIFF_OPTS(GIT_DIFF_NORMAL, 1), - DIFF_OPTS(GIT_DIFF_NORMAL, 3), - DIFF_OPTS(GIT_DIFF_REVERSE, 2), - DIFF_OPTS(GIT_DIFF_FORCE_TEXT, 2), - /* c vs d tests */ - DIFF_OPTS(GIT_DIFF_NORMAL, 3), - DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE, 3), - DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE_CHANGE, 3), - DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE_EOL, 3), - DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE | GIT_DIFF_REVERSE, 1), - }; - - /* to generate these values: - * - cd to tests/resources/attr, - * - mv .gitted .git - * - git diff [options] 6bab5c79cd5140d0 605812ab7fe421fdd - * - mv .git .gitted - */ -#define EXPECT_STATUS_ADM(ADDS,DELS,MODS) { 0, ADDS, DELS, MODS, 0, 0, 0, 0, 0 } - - diff_expects test_expects[] = { - /* a vs b tests */ - { 5, 0, EXPECT_STATUS_ADM(3, 0, 2), 4, 0, 0, 51, 2, 46, 3 }, - { 5, 0, EXPECT_STATUS_ADM(3, 0, 2), 4, 0, 0, 53, 4, 46, 3 }, - { 5, 0, EXPECT_STATUS_ADM(0, 3, 2), 4, 0, 0, 52, 3, 3, 46 }, - { 5, 0, EXPECT_STATUS_ADM(3, 0, 2), 5, 0, 0, 54, 3, 47, 4 }, - /* c vs d tests */ - { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 22, 9, 10, 3 }, - { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 19, 12, 7, 0 }, - { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 20, 11, 8, 1 }, - { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 20, 11, 8, 1 }, - { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 18, 11, 0, 7 }, - { 0 }, - }; - diff_expects *expected; - int i, j; - - g_repo = cl_git_sandbox_init("attr"); - - cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); - cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); - cl_assert((c = resolve_commit_oid_to_tree(g_repo, c_commit)) != NULL); - cl_assert((d = resolve_commit_oid_to_tree(g_repo, d_commit)) != NULL); - - for (i = 0; test_expects[i].files > 0; i++) { - memset(&actual, 0, sizeof(actual)); /* clear accumulator */ - opts = test_options[i]; - - if (test_ab_or_cd[i] == 0) - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); - else - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, c, d, &opts)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &actual)); - - expected = &test_expects[i]; - cl_assert_equal_i(actual.files, expected->files); - for (j = GIT_DELTA_UNMODIFIED; j <= GIT_DELTA_TYPECHANGE; ++j) - cl_assert_equal_i(expected->file_status[j], actual.file_status[j]); - cl_assert_equal_i(actual.hunks, expected->hunks); - cl_assert_equal_i(actual.lines, expected->lines); - cl_assert_equal_i(actual.line_ctxt, expected->line_ctxt); - cl_assert_equal_i(actual.line_adds, expected->line_adds); - cl_assert_equal_i(actual.line_dels, expected->line_dels); - - git_diff_free(diff); - diff = NULL; - } - - git_tree_free(c); - git_tree_free(d); -} - -void test_diff_tree__bare(void) -{ - const char *a_commit = "8496071c1b46c85"; - const char *b_commit = "be3563ae3f79"; - - g_repo = cl_git_sandbox_init("testrepo.git"); - - cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); - cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); - - opts.context_lines = 1; - opts.interhunk_lines = 1; - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); - - cl_assert_equal_i(3, expect.files); - cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, expect.file_status[GIT_DELTA_MODIFIED]); - - cl_assert_equal_i(3, expect.hunks); - - cl_assert_equal_i(4, expect.lines); - cl_assert_equal_i(0, expect.line_ctxt); - cl_assert_equal_i(3, expect.line_adds); - cl_assert_equal_i(1, expect.line_dels); -} - -void test_diff_tree__merge(void) -{ - /* grabbed a couple of commit oids from the history of the attr repo */ - const char *a_commit = "605812a"; - const char *b_commit = "370fe9ec22"; - const char *c_commit = "f5b0af1fb4f5c"; - git_tree *c; - git_diff *diff1 = NULL, *diff2 = NULL; - - g_repo = cl_git_sandbox_init("attr"); - - cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); - cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); - cl_assert((c = resolve_commit_oid_to_tree(g_repo, c_commit)) != NULL); - - cl_git_pass(git_diff_tree_to_tree(&diff1, g_repo, a, b, NULL)); - - cl_git_pass(git_diff_tree_to_tree(&diff2, g_repo, c, b, NULL)); - - git_tree_free(c); - - cl_git_pass(git_diff_merge(diff1, diff2)); - - git_diff_free(diff2); - - cl_git_pass(git_diff_foreach( - diff1, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); - - cl_assert_equal_i(6, expect.files); - cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, expect.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(3, expect.file_status[GIT_DELTA_MODIFIED]); - - cl_assert_equal_i(6, expect.hunks); - - cl_assert_equal_i(59, expect.lines); - cl_assert_equal_i(1, expect.line_ctxt); - cl_assert_equal_i(36, expect.line_adds); - cl_assert_equal_i(22, expect.line_dels); - - git_diff_free(diff1); -} - -void test_diff_tree__larger_hunks(void) -{ - const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69"; - const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10"; - size_t d, num_d, h, num_h, l, num_l; - git_patch *patch; - const git_diff_hunk *hunk; - const git_diff_line *line; - - g_repo = cl_git_sandbox_init("diff"); - - cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); - cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); - - opts.context_lines = 1; - opts.interhunk_lines = 0; - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); - - num_d = git_diff_num_deltas(diff); - for (d = 0; d < num_d; ++d) { - cl_git_pass(git_patch_from_diff(&patch, diff, d)); - cl_assert(patch); - - num_h = git_patch_num_hunks(patch); - for (h = 0; h < num_h; h++) { - cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h)); - - for (l = 0; l < num_l; ++l) { - cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l)); - cl_assert(line); - } - - cl_git_fail(git_patch_get_line_in_hunk(&line, patch, h, num_l)); - } - - cl_git_fail(git_patch_get_hunk(&hunk, &num_l, patch, num_h)); - - git_patch_free(patch); - } - - cl_git_fail(git_patch_from_diff(&patch, diff, num_d)); - - cl_assert_equal_i(2, (int)num_d); -} - -void test_diff_tree__checks_options_version(void) -{ - const char *a_commit = "8496071c1b46c85"; - const char *b_commit = "be3563ae3f79"; - const git_error *err; - - g_repo = cl_git_sandbox_init("testrepo.git"); - - cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); - cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); - - opts.version = 0; - cl_git_fail(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); - - giterr_clear(); - opts.version = 1024; - cl_git_fail(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); - err = giterr_last(); -} - -void process_tree_to_tree_diffing( - const char *old_commit, - const char *new_commit) -{ - g_repo = cl_git_sandbox_init("unsymlinked.git"); - - cl_assert((a = resolve_commit_oid_to_tree(g_repo, old_commit)) != NULL); - cl_assert((b = resolve_commit_oid_to_tree(g_repo, new_commit)) != NULL); - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &expect)); -} - -void test_diff_tree__symlink_blob_mode_changed_to_regular_file(void) -{ - /* - * $ git diff 7fccd7..806999 - * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h - * deleted file mode 120000 - * index 19bf568..0000000 - * --- a/include/Nu/Nu.h - * +++ /dev/null - * @@ -1 +0,0 @@ - * -../../objc/Nu.h - * \ No newline at end of file - * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h - * new file mode 100644 - * index 0000000..f9e6561 - * --- /dev/null - * +++ b/include/Nu/Nu.h - * @@ -0,0 +1 @@ - * +awesome content - * diff --git a/objc/Nu.h b/objc/Nu.h - * deleted file mode 100644 - * index f9e6561..0000000 - * --- a/objc/Nu.h - * +++ /dev/null - * @@ -1 +0,0 @@ - * -awesome content - */ - - process_tree_to_tree_diffing("7fccd7", "806999"); - - cl_assert_equal_i(3, expect.files); - cl_assert_equal_i(2, expect.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, expect.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_TYPECHANGE]); -} - -void test_diff_tree__symlink_blob_mode_changed_to_regular_file_as_typechange(void) -{ - /* - * $ git diff 7fccd7..a8595c - * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h - * deleted file mode 120000 - * index 19bf568..0000000 - * --- a/include/Nu/Nu.h - * +++ /dev/null - * @@ -1 +0,0 @@ - * -../../objc/Nu.h - * \ No newline at end of file - * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h - * new file mode 100755 - * index 0000000..f9e6561 - * --- /dev/null - * +++ b/include/Nu/Nu.h - * @@ -0,0 +1 @@ - * +awesome content - * diff --git a/objc/Nu.h b/objc/Nu.h - * deleted file mode 100644 - * index f9e6561..0000000 - * --- a/objc/Nu.h - * +++ /dev/null - * @@ -1 +0,0 @@ - * -awesome content - */ - - opts.flags = GIT_DIFF_INCLUDE_TYPECHANGE; - process_tree_to_tree_diffing("7fccd7", "a8595c"); - - cl_assert_equal_i(2, expect.files); - cl_assert_equal_i(1, expect.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, expect.file_status[GIT_DELTA_TYPECHANGE]); -} - -void test_diff_tree__regular_blob_mode_changed_to_executable_file(void) -{ - /* - * $ git diff 806999..a8595c - * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h - * old mode 100644 - * new mode 100755 - */ - - process_tree_to_tree_diffing("806999", "a8595c"); - - cl_assert_equal_i(1, expect.files); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, expect.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_TYPECHANGE]); -} - -void test_diff_tree__issue_1397(void) -{ - /* this test shows that it is not needed */ - - g_repo = cl_git_sandbox_init("issue_1397"); - - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - cl_assert((a = resolve_commit_oid_to_tree(g_repo, "8a7ef04")) != NULL); - cl_assert((b = resolve_commit_oid_to_tree(g_repo, "7f483a7")) != NULL); - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); - - cl_assert_equal_i(1, expect.files); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, expect.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, expect.file_status[GIT_DELTA_TYPECHANGE]); -} - -static void set_config_int(git_repository *repo, const char *name, int value) -{ - git_config *cfg; - - cl_git_pass(git_repository_config(&cfg, repo)); - cl_git_pass(git_config_set_int32(cfg, name, value)); - git_config_free(cfg); -} - -void test_diff_tree__diff_configs(void) -{ - const char *a_commit = "d70d245e"; - const char *b_commit = "7a9e0b02"; - - g_repo = cl_git_sandbox_init("diff"); - - cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); - cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); - - cl_assert_equal_i(2, expect.files); - cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(6, expect.hunks); - cl_assert_equal_i(55, expect.lines); - cl_assert_equal_i(33, expect.line_ctxt); - cl_assert_equal_i(7, expect.line_adds); - cl_assert_equal_i(15, expect.line_dels); - - git_diff_free(diff); - diff = NULL; - - set_config_int(g_repo, "diff.context", 1); - - memset(&expect, 0, sizeof(expect)); - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); - - cl_assert_equal_i(2, expect.files); - cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(7, expect.hunks); - cl_assert_equal_i(34, expect.lines); - cl_assert_equal_i(12, expect.line_ctxt); - cl_assert_equal_i(7, expect.line_adds); - cl_assert_equal_i(15, expect.line_dels); - - git_diff_free(diff); - diff = NULL; - - set_config_int(g_repo, "diff.context", 0); - set_config_int(g_repo, "diff.noprefix", 1); - - memset(&expect, 0, sizeof(expect)); - - cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); - - cl_assert_equal_i(2, expect.files); - cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(7, expect.hunks); - cl_assert_equal_i(22, expect.lines); - cl_assert_equal_i(0, expect.line_ctxt); - cl_assert_equal_i(7, expect.line_adds); - cl_assert_equal_i(15, expect.line_dels); -} diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c deleted file mode 100644 index 7cc032232..000000000 --- a/tests-clar/diff/workdir.c +++ /dev/null @@ -1,1490 +0,0 @@ -#include "clar_libgit2.h" -#include "diff_helpers.h" -#include "repository.h" - -static git_repository *g_repo = NULL; - -void test_diff_workdir__initialize(void) -{ -} - -void test_diff_workdir__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_diff_workdir__to_index(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - diff_expects exp; - int use_iterator; - - g_repo = cl_git_sandbox_init("status"); - - opts.context_lines = 3; - opts.interhunk_lines = 1; - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - else - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - /* to generate these values: - * - cd to tests/resources/status, - * - mv .gitted .git - * - git diff --name-status - * - git diff - * - mv .git .gitted - */ - cl_assert_equal_i(13, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]); - - cl_assert_equal_i(8, exp.hunks); - - cl_assert_equal_i(14, exp.lines); - cl_assert_equal_i(5, exp.line_ctxt); - cl_assert_equal_i(4, exp.line_adds); - cl_assert_equal_i(5, exp.line_dels); - } - - git_diff_free(diff); -} - -void test_diff_workdir__to_index_with_assume_unchanged(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - git_index *idx = NULL; - diff_expects exp; - const git_index_entry *iep; - git_index_entry ie; - - g_repo = cl_git_sandbox_init("status"); - - /* do initial diff */ - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(8, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); - git_diff_free(diff); - - /* mark a couple of entries with ASSUME_UNCHANGED */ - - cl_git_pass(git_repository_index(&idx, g_repo)); - - cl_assert((iep = git_index_get_bypath(idx, "modified_file", 0)) != NULL); - memcpy(&ie, iep, sizeof(ie)); - ie.flags |= GIT_IDXENTRY_VALID; - cl_git_pass(git_index_add(idx, &ie)); - - cl_assert((iep = git_index_get_bypath(idx, "file_deleted", 0)) != NULL); - memcpy(&ie, iep, sizeof(ie)); - ie.flags |= GIT_IDXENTRY_VALID; - cl_git_pass(git_index_add(idx, &ie)); - - cl_git_pass(git_index_write(idx)); - git_index_free(idx); - - /* redo diff and see that entries are skipped */ - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - cl_assert_equal_i(6, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); - git_diff_free(diff); - -} - -void test_diff_workdir__to_tree(void) -{ - /* grabbed a couple of commit oids from the history of the attr repo */ - const char *a_commit = "26a125ee1bf"; /* the current HEAD */ - const char *b_commit = "0017bd4ab1ec3"; /* the start */ - git_tree *a, *b; - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - git_diff *diff2 = NULL; - diff_expects exp; - int use_iterator; - - g_repo = cl_git_sandbox_init("status"); - - a = resolve_commit_oid_to_tree(g_repo, a_commit); - b = resolve_commit_oid_to_tree(g_repo, b_commit); - - opts.context_lines = 3; - opts.interhunk_lines = 1; - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - - /* You can't really generate the equivalent of git_diff_tree_to_workdir() - * using C git. It really wants to interpose the index into the diff. - * - * To validate the following results with command line git, I ran the - * following: - * - git ls-tree 26a125 - * - find . ! -path ./.git/\* -a -type f | git hash-object --stdin-paths - * The results are documented at the bottom of this file in the - * long comment entitled "PREPARATION OF TEST DATA". - */ - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - else - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(14, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(5, exp.file_status[GIT_DELTA_UNTRACKED]); - } - - /* Since there is no git diff equivalent, let's just assume that the - * text diffs produced by git_diff_foreach are accurate here. We will - * do more apples-to-apples test comparison below. - */ - - git_diff_free(diff); - diff = NULL; - memset(&exp, 0, sizeof(exp)); - - /* This is a compatible emulation of "git diff " which looks like - * a workdir to tree diff (even though it is not really). This is what - * you would get from "git diff --name-status 26a125ee1bf" - */ - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); - cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); - cl_git_pass(git_diff_merge(diff, diff2)); - git_diff_free(diff2); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - else - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(15, exp.files); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(5, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); - - cl_assert_equal_i(11, exp.hunks); - - cl_assert_equal_i(17, exp.lines); - cl_assert_equal_i(4, exp.line_ctxt); - cl_assert_equal_i(8, exp.line_adds); - cl_assert_equal_i(5, exp.line_dels); - } - - git_diff_free(diff); - diff = NULL; - memset(&exp, 0, sizeof(exp)); - - /* Again, emulating "git diff " for testing purposes using - * "git diff --name-status 0017bd4ab1ec3" instead. - */ - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts)); - cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); - cl_git_pass(git_diff_merge(diff, diff2)); - git_diff_free(diff2); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - else - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(16, exp.files); - cl_assert_equal_i(5, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); - - cl_assert_equal_i(12, exp.hunks); - - cl_assert_equal_i(19, exp.lines); - cl_assert_equal_i(3, exp.line_ctxt); - cl_assert_equal_i(12, exp.line_adds); - cl_assert_equal_i(4, exp.line_dels); - } - - git_diff_free(diff); - - /* Let's try that once more with a reversed diff */ - - opts.flags |= GIT_DIFF_REVERSE; - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts)); - cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); - cl_git_pass(git_diff_merge(diff, diff2)); - git_diff_free(diff2); - - memset(&exp, 0, sizeof(exp)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(16, exp.files); - cl_assert_equal_i(5, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); - - cl_assert_equal_i(12, exp.hunks); - - cl_assert_equal_i(19, exp.lines); - cl_assert_equal_i(3, exp.line_ctxt); - cl_assert_equal_i(12, exp.line_dels); - cl_assert_equal_i(4, exp.line_adds); - - git_diff_free(diff); - - /* all done now */ - - git_tree_free(a); - git_tree_free(b); -} - -void test_diff_workdir__to_index_with_pathspec(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - diff_expects exp; - char *pathspec = NULL; - int use_iterator; - - g_repo = cl_git_sandbox_init("status"); - - opts.context_lines = 3; - opts.interhunk_lines = 1; - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - opts.pathspec.strings = &pathspec; - opts.pathspec.count = 1; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, NULL, NULL, &exp)); - else - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(13, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]); - } - - git_diff_free(diff); - - pathspec = "modified_file"; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, NULL, NULL, &exp)); - else - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(1, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]); - } - - git_diff_free(diff); - - pathspec = "subdir"; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, NULL, NULL, &exp)); - else - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(3, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - } - - git_diff_free(diff); - - pathspec = "*_deleted"; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, NULL, NULL, &exp)); - else - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(2, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]); - } - - git_diff_free(diff); -} - -void test_diff_workdir__filemode_changes(void) -{ - git_diff *diff = NULL; - diff_expects exp; - int use_iterator; - - if (!cl_is_chmod_supported()) - return; - - g_repo = cl_git_sandbox_init("issue_592"); - - cl_repo_set_bool(g_repo, "core.filemode", true); - - /* test once with no mods */ - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - else - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(0, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.hunks); - } - - git_diff_free(diff); - - /* chmod file and test again */ - - cl_assert(cl_toggle_filemode("issue_592/a.txt")); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - else - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(1, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.hunks); - } - - git_diff_free(diff); - - cl_assert(cl_toggle_filemode("issue_592/a.txt")); -} - -void test_diff_workdir__filemode_changes_with_filemode_false(void) -{ - git_diff *diff = NULL; - diff_expects exp; - - if (!cl_is_chmod_supported()) - return; - - g_repo = cl_git_sandbox_init("issue_592"); - - cl_repo_set_bool(g_repo, "core.filemode", false); - - /* test once with no mods */ - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(0, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.hunks); - - git_diff_free(diff); - - /* chmod file and test again */ - - cl_assert(cl_toggle_filemode("issue_592/a.txt")); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(0, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.hunks); - - git_diff_free(diff); - - cl_assert(cl_toggle_filemode("issue_592/a.txt")); -} - -void test_diff_workdir__head_index_and_workdir_all_differ(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff_i2t = NULL, *diff_w2i = NULL; - diff_expects exp; - char *pathspec = "staged_changes_modified_file"; - git_tree *tree; - int use_iterator; - - /* For this file, - * - head->index diff has 1 line of context, 1 line of diff - * - index->workdir diff has 2 lines of context, 1 line of diff - * but - * - head->workdir diff has 1 line of context, 2 lines of diff - * Let's make sure the right one is returned from each fn. - */ - - g_repo = cl_git_sandbox_init("status"); - - tree = resolve_commit_oid_to_tree(g_repo, "26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f"); - - opts.pathspec.strings = &pathspec; - opts.pathspec.count = 1; - - cl_git_pass(git_diff_tree_to_index(&diff_i2t, g_repo, tree, NULL, &opts)); - cl_git_pass(git_diff_index_to_workdir(&diff_w2i, g_repo, NULL, &opts)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - else - cl_git_pass(git_diff_foreach( - diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(1, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.hunks); - cl_assert_equal_i(2, exp.lines); - cl_assert_equal_i(1, exp.line_ctxt); - cl_assert_equal_i(1, exp.line_adds); - cl_assert_equal_i(0, exp.line_dels); - } - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff_w2i, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - else - cl_git_pass(git_diff_foreach( - diff_w2i, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(1, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.hunks); - cl_assert_equal_i(3, exp.lines); - cl_assert_equal_i(2, exp.line_ctxt); - cl_assert_equal_i(1, exp.line_adds); - cl_assert_equal_i(0, exp.line_dels); - } - - cl_git_pass(git_diff_merge(diff_i2t, diff_w2i)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - else - cl_git_pass(git_diff_foreach( - diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(1, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.hunks); - cl_assert_equal_i(3, exp.lines); - cl_assert_equal_i(1, exp.line_ctxt); - cl_assert_equal_i(2, exp.line_adds); - cl_assert_equal_i(0, exp.line_dels); - } - - git_diff_free(diff_i2t); - git_diff_free(diff_w2i); - - git_tree_free(tree); -} - -void test_diff_workdir__eof_newline_changes(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - diff_expects exp; - char *pathspec = "current_file"; - int use_iterator; - - g_repo = cl_git_sandbox_init("status"); - - opts.pathspec.strings = &pathspec; - opts.pathspec.count = 1; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - else - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(0, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.hunks); - cl_assert_equal_i(0, exp.lines); - cl_assert_equal_i(0, exp.line_ctxt); - cl_assert_equal_i(0, exp.line_adds); - cl_assert_equal_i(0, exp.line_dels); - } - - git_diff_free(diff); - - cl_git_append2file("status/current_file", "\n"); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - else - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(1, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.hunks); - cl_assert_equal_i(2, exp.lines); - cl_assert_equal_i(1, exp.line_ctxt); - cl_assert_equal_i(1, exp.line_adds); - cl_assert_equal_i(0, exp.line_dels); - } - - git_diff_free(diff); - - cl_git_rewritefile("status/current_file", "current_file"); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - for (use_iterator = 0; use_iterator <= 1; use_iterator++) { - memset(&exp, 0, sizeof(exp)); - - if (use_iterator) - cl_git_pass(diff_foreach_via_iterator( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - else - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(1, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.hunks); - cl_assert_equal_i(3, exp.lines); - cl_assert_equal_i(0, exp.line_ctxt); - cl_assert_equal_i(1, exp.line_adds); - cl_assert_equal_i(2, exp.line_dels); - } - - git_diff_free(diff); -} - -/* PREPARATION OF TEST DATA - * - * Since there is no command line equivalent of git_diff_tree_to_workdir, - * it was a bit of a pain to confirm that I was getting the expected - * results in the first part of this tests. Here is what I ended up - * doing to set my expectation for the file counts and results: - * - * Running "git ls-tree 26a125" and "git ls-tree aa27a6" shows: - * - * A a0de7e0ac200c489c41c59dfa910154a70264e6e current_file - * B 5452d32f1dd538eb0405e8a83cc185f79e25e80f file_deleted - * C 452e4244b5d083ddf0460acf1ecc74db9dcfa11a modified_file - * D 32504b727382542f9f089e24fddac5e78533e96c staged_changes - * E 061d42a44cacde5726057b67558821d95db96f19 staged_changes_file_deleted - * F 70bd9443ada07063e7fbf0b3ff5c13f7494d89c2 staged_changes_modified_file - * G e9b9107f290627c04d097733a10055af941f6bca staged_delete_file_deleted - * H dabc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 staged_delete_modified_file - * I 53ace0d1cc1145a5f4fe4f78a186a60263190733 subdir/current_file - * J 1888c805345ba265b0ee9449b8877b6064592058 subdir/deleted_file - * K a6191982709b746d5650e93c2acf34ef74e11504 subdir/modified_file - * L e8ee89e15bbe9b20137715232387b3de5b28972e subdir.txt - * - * -------- - * - * find . ! -path ./.git/\* -a -type f | git hash-object --stdin-paths - * - * A a0de7e0ac200c489c41c59dfa910154a70264e6e current_file - * M 6a79f808a9c6bc9531ac726c184bbcd9351ccf11 ignored_file - * C 0a539630525aca2e7bc84975958f92f10a64c9b6 modified_file - * N d4fa8600b4f37d7516bef4816ae2c64dbf029e3a new_file - * D 55d316c9ba708999f1918e9677d01dfcae69c6b9 staged_changes - * F 011c3440d5c596e21d836aa6d7b10eb581f68c49 staged_changes_modified_file - * H dabc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 staged_delete_modified_file - * O 529a16e8e762d4acb7b9636ff540a00831f9155a staged_new_file - * P 8b090c06d14ffa09c4e880088ebad33893f921d1 staged_new_file_modified_file - * I 53ace0d1cc1145a5f4fe4f78a186a60263190733 subdir/current_file - * K 57274b75eeb5f36fd55527806d567b2240a20c57 subdir/modified_file - * Q 80a86a6931b91bc01c2dbf5ca55bdd24ad1ef466 subdir/new_file - * L e8ee89e15bbe9b20137715232387b3de5b28972e subdir.txt - * - * -------- - * - * A - current_file (UNMODIFIED) -> not in results - * B D file_deleted - * M I ignored_file (IGNORED) - * C M modified_file - * N U new_file (UNTRACKED) - * D M staged_changes - * E D staged_changes_file_deleted - * F M staged_changes_modified_file - * G D staged_delete_file_deleted - * H - staged_delete_modified_file (UNMODIFIED) -> not in results - * O U staged_new_file - * P U staged_new_file_modified_file - * I - subdir/current_file (UNMODIFIED) -> not in results - * J D subdir/deleted_file - * K M subdir/modified_file - * Q U subdir/new_file - * L - subdir.txt (UNMODIFIED) -> not in results - * - * Expect 13 files, 0 ADD, 4 DEL, 4 MOD, 1 IGN, 4 UNTR - */ - - -void test_diff_workdir__larger_hunks(void) -{ - const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69"; - const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10"; - git_tree *a, *b; - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - size_t i, d, num_d, h, num_h, l, num_l; - - g_repo = cl_git_sandbox_init("diff"); - - cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); - cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); - - opts.context_lines = 1; - opts.interhunk_lines = 0; - - for (i = 0; i <= 2; ++i) { - git_diff *diff = NULL; - git_patch *patch; - const git_diff_hunk *hunk; - const git_diff_line *line; - - /* okay, this is a bit silly, but oh well */ - switch (i) { - case 0: - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - break; - case 1: - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); - break; - case 2: - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, b, &opts)); - break; - } - - num_d = git_diff_num_deltas(diff); - cl_assert_equal_i(2, (int)num_d); - - for (d = 0; d < num_d; ++d) { - cl_git_pass(git_patch_from_diff(&patch, diff, d)); - cl_assert(patch); - - num_h = git_patch_num_hunks(patch); - for (h = 0; h < num_h; h++) { - cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h)); - - for (l = 0; l < num_l; ++l) { - cl_git_pass( - git_patch_get_line_in_hunk(&line, patch, h, l)); - cl_assert(line); - } - - /* confirm fail after the last item */ - cl_git_fail( - git_patch_get_line_in_hunk(&line, patch, h, num_l)); - } - - /* confirm fail after the last item */ - cl_git_fail(git_patch_get_hunk(&hunk, &num_l, patch, num_h)); - - git_patch_free(patch); - } - - git_diff_free(diff); - } - - git_tree_free(a); - git_tree_free(b); -} - -/* Set up a test that exercises this code. The easiest test using existing - * test data is probably to create a sandbox of submod2 and then run a - * git_diff_tree_to_workdir against tree - * 873585b94bdeabccea991ea5e3ec1a277895b698. As for what you should actually - * test, you can start by just checking that the number of lines of diff - * content matches the actual output of git diff. That will at least - * demonstrate that the submodule content is being used to generate somewhat - * comparable outputs. It is a test that would fail without this code and - * will succeed with it. - */ - -#include "../submodule/submodule_helpers.h" - -void test_diff_workdir__submodules(void) -{ - const char *a_commit = "873585b94bdeabccea991ea5e3ec1a277895b698"; - git_tree *a; - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - diff_expects exp; - - g_repo = setup_fixture_submod2(); - - a = resolve_commit_oid_to_tree(g_repo, a_commit); - - opts.flags = - GIT_DIFF_INCLUDE_UNTRACKED | - GIT_DIFF_INCLUDE_IGNORED | - GIT_DIFF_RECURSE_UNTRACKED_DIRS | - GIT_DIFF_SHOW_UNTRACKED_CONTENT; - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); - - /* diff_print(stderr, diff); */ - - /* essentially doing: git diff 873585b94bdeabccea991ea5e3ec1a277895b698 */ - - memset(&exp, 0, sizeof(exp)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - /* so "git diff 873585" returns: - * M .gitmodules - * A just_a_dir/contents - * A just_a_file - * A sm_added_and_uncommited - * A sm_changed_file - * A sm_changed_head - * A sm_changed_index - * A sm_changed_untracked_file - * M sm_missing_commits - * A sm_unchanged - * which is a little deceptive because of the difference between the - * "git diff " results from "git_diff_tree_to_workdir". The - * only significant difference is that those Added items will show up - * as Untracked items in the pure libgit2 diff. - * - * Then add in the two extra ignored items "not" and "not-submodule" - * to get the 12 files reported here. - */ - - cl_assert_equal_i(12, exp.files); - - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(8, exp.file_status[GIT_DELTA_UNTRACKED]); - - /* the following numbers match "git diff 873585" exactly */ - - cl_assert_equal_i(9, exp.hunks); - - cl_assert_equal_i(33, exp.lines); - cl_assert_equal_i(2, exp.line_ctxt); - cl_assert_equal_i(30, exp.line_adds); - cl_assert_equal_i(1, exp.line_dels); - - git_diff_free(diff); - git_tree_free(a); -} - -void test_diff_workdir__cannot_diff_against_a_bare_repository(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - git_tree *tree; - - g_repo = cl_git_sandbox_init("testrepo.git"); - - cl_assert_equal_i( - GIT_EBAREREPO, git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_git_pass(git_repository_head_tree(&tree, g_repo)); - - cl_assert_equal_i( - GIT_EBAREREPO, git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); - - git_tree_free(tree); -} - -void test_diff_workdir__to_null_tree(void) -{ - git_diff *diff; - diff_expects exp; - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - - opts.flags = GIT_DIFF_INCLUDE_UNTRACKED | - GIT_DIFF_RECURSE_UNTRACKED_DIRS; - - g_repo = cl_git_sandbox_init("status"); - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, NULL, &opts)); - - memset(&exp, 0, sizeof(exp)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(exp.files, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); -} - -void test_diff_workdir__checks_options_version(void) -{ - git_diff *diff; - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - const git_error *err; - - g_repo = cl_git_sandbox_init("status"); - - opts.version = 0; - cl_git_fail(git_diff_tree_to_workdir(&diff, g_repo, NULL, &opts)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); - - giterr_clear(); - opts.version = 1024; - cl_git_fail(git_diff_tree_to_workdir(&diff, g_repo, NULL, &opts)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); -} - -void test_diff_workdir__can_diff_empty_file(void) -{ - git_diff *diff; - git_tree *tree; - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - struct stat st; - git_patch *patch; - - g_repo = cl_git_sandbox_init("attr_index"); - - tree = resolve_commit_oid_to_tree(g_repo, "3812cfef3661"); /* HEAD */ - - /* baseline - make sure there are no outstanding diffs */ - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); - cl_assert_equal_i(2, (int)git_diff_num_deltas(diff)); - git_diff_free(diff); - - /* empty contents of file */ - - cl_git_rewritefile("attr_index/README.txt", ""); - cl_git_pass(git_path_lstat("attr_index/README.txt", &st)); - cl_assert_equal_i(0, (int)st.st_size); - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); - cl_assert_equal_i(3, (int)git_diff_num_deltas(diff)); - /* diffs are: .gitattributes, README.txt, sub/sub/.gitattributes */ - cl_git_pass(git_patch_from_diff(&patch, diff, 1)); - git_patch_free(patch); - git_diff_free(diff); - - /* remove a file altogether */ - - cl_git_pass(p_unlink("attr_index/README.txt")); - cl_assert(!git_path_exists("attr_index/README.txt")); - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); - cl_assert_equal_i(3, (int)git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, diff, 1)); - git_patch_free(patch); - git_diff_free(diff); - - git_tree_free(tree); -} - -void test_diff_workdir__to_index_issue_1397(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - diff_expects exp; - - g_repo = cl_git_sandbox_init("issue_1397"); - - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - opts.context_lines = 3; - opts.interhunk_lines = 1; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(0, exp.files); - cl_assert_equal_i(0, exp.hunks); - cl_assert_equal_i(0, exp.lines); - - git_diff_free(diff); - diff = NULL; - - cl_git_rewritefile("issue_1397/crlf_file.txt", - "first line\r\nsecond line modified\r\nboth with crlf"); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(1, exp.files); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - - cl_assert_equal_i(1, exp.hunks); - - cl_assert_equal_i(5, exp.lines); - cl_assert_equal_i(3, exp.line_ctxt); - cl_assert_equal_i(1, exp.line_adds); - cl_assert_equal_i(1, exp.line_dels); - - git_diff_free(diff); -} - -void test_diff_workdir__to_tree_issue_1397(void) -{ - const char *a_commit = "7f483a738"; /* the current HEAD */ - git_tree *a; - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - git_diff *diff2 = NULL; - diff_expects exp; - - g_repo = cl_git_sandbox_init("issue_1397"); - - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - a = resolve_commit_oid_to_tree(g_repo, a_commit); - - opts.context_lines = 3; - opts.interhunk_lines = 1; - - cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(0, exp.files); - cl_assert_equal_i(0, exp.hunks); - cl_assert_equal_i(0, exp.lines); - - git_diff_free(diff); - diff = NULL; - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); - cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); - cl_git_pass(git_diff_merge(diff, diff2)); - git_diff_free(diff2); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(0, exp.files); - cl_assert_equal_i(0, exp.hunks); - cl_assert_equal_i(0, exp.lines); - - git_diff_free(diff); - git_tree_free(a); -} - -void test_diff_workdir__untracked_directory_scenarios(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - diff_expects exp; - char *pathspec = NULL; - static const char *files0[] = { - "subdir/deleted_file", - "subdir/modified_file", - "subdir/new_file", - NULL - }; - static const char *files1[] = { - "subdir/deleted_file", - "subdir/directory/", - "subdir/modified_file", - "subdir/new_file", - NULL - }; - static const char *files2[] = { - "subdir/deleted_file", - "subdir/directory/more/notignored", - "subdir/modified_file", - "subdir/new_file", - NULL - }; - - g_repo = cl_git_sandbox_init("status"); - cl_git_mkfile("status/.gitignore", "ignored\n"); - - opts.context_lines = 3; - opts.interhunk_lines = 1; - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - opts.pathspec.strings = &pathspec; - opts.pathspec.count = 1; - pathspec = "subdir"; - - /* baseline for "subdir" pathspec */ - - memset(&exp, 0, sizeof(exp)); - exp.names = files0; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(3, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); - - /* empty directory */ - - cl_git_pass(p_mkdir("status/subdir/directory", 0777)); - - memset(&exp, 0, sizeof(exp)); - exp.names = files1; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); - - /* empty directory in empty directory */ - - cl_git_pass(p_mkdir("status/subdir/directory/empty", 0777)); - - memset(&exp, 0, sizeof(exp)); - exp.names = files1; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); - - /* directory with only ignored files */ - - cl_git_pass(p_mkdir("status/subdir/directory/deeper", 0777)); - cl_git_mkfile("status/subdir/directory/deeper/ignored", "ignore me\n"); - - cl_git_pass(p_mkdir("status/subdir/directory/another", 0777)); - cl_git_mkfile("status/subdir/directory/another/ignored", "ignore me\n"); - - memset(&exp, 0, sizeof(exp)); - exp.names = files1; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); - - /* directory with ignored directory (contents irrelevant) */ - - cl_git_pass(p_mkdir("status/subdir/directory/more", 0777)); - cl_git_pass(p_mkdir("status/subdir/directory/more/ignored", 0777)); - cl_git_mkfile("status/subdir/directory/more/ignored/notignored", - "inside ignored dir\n"); - - memset(&exp, 0, sizeof(exp)); - exp.names = files1; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); - - /* quick version avoids directory scan */ - - opts.flags = opts.flags | GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS; - - memset(&exp, 0, sizeof(exp)); - exp.names = files1; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); - - /* directory with nested non-ignored content */ - - opts.flags = opts.flags & ~GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS; - - cl_git_mkfile("status/subdir/directory/more/notignored", - "not ignored deep under untracked\n"); - - memset(&exp, 0, sizeof(exp)); - exp.names = files1; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); - - /* use RECURSE_UNTRACKED_DIRS to get actual untracked files (no ignores) */ - - opts.flags = opts.flags & ~GIT_DIFF_INCLUDE_IGNORED; - opts.flags = opts.flags | GIT_DIFF_RECURSE_UNTRACKED_DIRS; - - memset(&exp, 0, sizeof(exp)); - exp.names = files2; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); - - cl_assert_equal_i(4, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); - cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); - - git_diff_free(diff); -} - - -void test_diff_workdir__untracked_directory_comes_last(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - - g_repo = cl_git_sandbox_init("renames"); - - cl_git_mkfile("renames/.gitignore", "*.ign\n"); - cl_git_pass(p_mkdir("renames/zzz_untracked", 0777)); - cl_git_mkfile("renames/zzz_untracked/an.ign", "ignore me please"); - cl_git_mkfile("renames/zzz_untracked/skip.ign", "ignore me really"); - cl_git_mkfile("renames/zzz_untracked/test.ign", "ignore me now"); - - opts.context_lines = 3; - opts.interhunk_lines = 1; - opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_assert(diff != NULL); - - git_diff_free(diff); -} - -void test_diff_workdir__untracked_with_bom(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - const git_diff_delta *delta; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - cl_repo_set_bool(g_repo, "core.autocrlf", true); - - cl_git_write2file("empty_standard_repo/bom.txt", - "\xFF\xFE\x31\x00\x32\x00\x33\x00\x34\x00", 10, O_WRONLY|O_CREAT, 0664); - - opts.flags = - GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - cl_assert_equal_i(1, git_diff_num_deltas(diff)); - cl_assert((delta = git_diff_get_delta(diff, 0)) != NULL); - cl_assert_equal_i(GIT_DELTA_UNTRACKED, delta->status); - - /* not known at this point - * cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); - */ - - git_diff_free(diff); -} - -void test_diff_workdir__patience_diff(void) -{ - git_index *index; - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - git_patch *patch = NULL; - char *as_str = NULL; - const char *expected_normal = "diff --git a/test.txt b/test.txt\nindex 34a5acc..d52725f 100644\n--- a/test.txt\n+++ b/test.txt\n@@ -1,10 +1,7 @@\n When I wrote this\n I did not know\n-how to create\n-a patience diff\n I did not know\n how to create\n+a patience diff\n another problem\n-I did not know\n-how to create\n a minimal diff\n"; - const char *expected_patience = "diff --git a/test.txt b/test.txt\nindex 34a5acc..d52725f 100644\n--- a/test.txt\n+++ b/test.txt\n@@ -1,10 +1,7 @@\n When I wrote this\n I did not know\n+I did not know\n how to create\n a patience diff\n-I did not know\n-how to create\n another problem\n-I did not know\n-how to create\n a minimal diff\n"; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - cl_repo_set_bool(g_repo, "core.autocrlf", true); - cl_git_pass(git_repository_index(&index, g_repo)); - - cl_git_mkfile( - "empty_standard_repo/test.txt", - "When I wrote this\nI did not know\nhow to create\na patience diff\nI did not know\nhow to create\nanother problem\nI did not know\nhow to create\na minimal diff\n"); - cl_git_pass(git_index_add_bypath(index, "test.txt")); - cl_repo_commit_from_index(NULL, g_repo, NULL, 1372350000, "Base"); - git_index_free(index); - - cl_git_rewritefile( - "empty_standard_repo/test.txt", - "When I wrote this\nI did not know\nI did not know\nhow to create\na patience diff\nanother problem\na minimal diff\n"); - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_assert_equal_i(1, git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_git_pass(git_patch_to_str(&as_str, patch)); - - cl_assert_equal_s(expected_normal, as_str); - git__free(as_str); - git_patch_free(patch); - git_diff_free(diff); - - opts.flags |= GIT_DIFF_PATIENCE; - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - cl_assert_equal_i(1, git_diff_num_deltas(diff)); - cl_git_pass(git_patch_from_diff(&patch, diff, 0)); - cl_git_pass(git_patch_to_str(&as_str, patch)); - - cl_assert_equal_s(expected_patience, as_str); - git__free(as_str); - git_patch_free(patch); - git_diff_free(diff); -} - -void test_diff_workdir__with_stale_index(void) -{ - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff *diff = NULL; - git_index *idx = NULL; - diff_expects exp; - - g_repo = cl_git_sandbox_init("status"); - cl_git_pass(git_repository_index(&idx, g_repo)); - - /* make the in-memory index invalid */ - { - git_repository *r2; - git_index *idx2; - cl_git_pass(git_repository_open(&r2, "status")); - cl_git_pass(git_repository_index(&idx2, r2)); - cl_git_pass(git_index_add_bypath(idx2, "new_file")); - cl_git_pass(git_index_add_bypath(idx2, "subdir/new_file")); - cl_git_pass(git_index_remove_bypath(idx2, "staged_new_file")); - cl_git_pass(git_index_remove_bypath(idx2, "staged_changes_file_deleted")); - cl_git_pass(git_index_write(idx2)); - git_index_free(idx2); - git_repository_free(r2); - } - - opts.context_lines = 3; - opts.interhunk_lines = 1; - opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_INCLUDE_UNMODIFIED; - - /* first try with index pointer which should prevent reload */ - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, idx, &opts)); - - memset(&exp, 0, sizeof(exp)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - cl_assert_equal_i(17, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]); - cl_assert_equal_i(5, exp.file_status[GIT_DELTA_UNMODIFIED]); - - git_diff_free(diff); - - /* now let's try without the index pointer which should trigger reload */ - - /* two files that were UNTRACKED should have become UNMODIFIED */ - /* one file that was UNMODIFIED should now have become UNTRACKED */ - /* one file that was DELETED should now be gone completely */ - - cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); - - memset(&exp, 0, sizeof(exp)); - - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); - - git_diff_free(diff); - - cl_assert_equal_i(16, exp.files); - cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); - cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); - cl_assert_equal_i(6, exp.file_status[GIT_DELTA_UNMODIFIED]); - - git_index_free(idx); -} diff --git a/tests-clar/fetchhead/fetchhead_data.h b/tests-clar/fetchhead/fetchhead_data.h deleted file mode 100644 index 294c9fb01..000000000 --- a/tests-clar/fetchhead/fetchhead_data.h +++ /dev/null @@ -1,31 +0,0 @@ - -#define FETCH_HEAD_WILDCARD_DATA_LOCAL \ - "49322bb17d3acc9146f98c97d078513228bbf3c0\t\tbranch 'master' of git://github.com/libgit2/TestGitRepository\n" \ - "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" \ - "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of git://github.com/libgit2/TestGitRepository\n" \ - "d96c4e80345534eccee5ac7b07fc7603b56124cb\tnot-for-merge\ttag 'annotated_tag' of git://github.com/libgit2/TestGitRepository\n" \ - "55a1a760df4b86a02094a904dfa511deb5655905\tnot-for-merge\ttag 'blob' of git://github.com/libgit2/TestGitRepository\n" \ - "8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of git://github.com/libgit2/TestGitRepository\n" - -#define FETCH_HEAD_WILDCARD_DATA \ - "49322bb17d3acc9146f98c97d078513228bbf3c0\t\tbranch 'master' of git://github.com/libgit2/TestGitRepository\n" \ - "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" \ - "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of git://github.com/libgit2/TestGitRepository\n" \ - "d96c4e80345534eccee5ac7b07fc7603b56124cb\tnot-for-merge\ttag 'annotated_tag' of git://github.com/libgit2/TestGitRepository\n" \ - "55a1a760df4b86a02094a904dfa511deb5655905\tnot-for-merge\ttag 'blob' of git://github.com/libgit2/TestGitRepository\n" \ - "8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of git://github.com/libgit2/TestGitRepository\n" \ - "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e\tnot-for-merge\ttag 'nearly-dangling' of git://github.com/libgit2/TestGitRepository\n" - -#define FETCH_HEAD_NO_MERGE_DATA \ - "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" \ - "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\tbranch 'master' of git://github.com/libgit2/TestGitRepository\n" \ - "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of git://github.com/libgit2/TestGitRepository\n" \ - "d96c4e80345534eccee5ac7b07fc7603b56124cb\tnot-for-merge\ttag 'annotated_tag' of git://github.com/libgit2/TestGitRepository\n" \ - "55a1a760df4b86a02094a904dfa511deb5655905\tnot-for-merge\ttag 'blob' of git://github.com/libgit2/TestGitRepository\n" \ - "8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of git://github.com/libgit2/TestGitRepository\n" \ - "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e\tnot-for-merge\ttag 'nearly-dangling' of git://github.com/libgit2/TestGitRepository\n" - - -#define FETCH_HEAD_EXPLICIT_DATA \ - "0966a434eb1a025db6b71485ab63a3bfbea520b6\t\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" - diff --git a/tests-clar/fetchhead/nonetwork.c b/tests-clar/fetchhead/nonetwork.c deleted file mode 100644 index a68ebb0b7..000000000 --- a/tests-clar/fetchhead/nonetwork.c +++ /dev/null @@ -1,309 +0,0 @@ -#include "clar_libgit2.h" - -#include "fileops.h" -#include "fetchhead.h" - -#include "fetchhead_data.h" - -#define DO_LOCAL_TEST 0 - -static git_repository *g_repo; - -void test_fetchhead_nonetwork__initialize(void) -{ - g_repo = NULL; -} - -static void cleanup_repository(void *path) -{ - if (g_repo) { - git_repository_free(g_repo); - g_repo = NULL; - } - - cl_fixture_cleanup((const char *)path); -} - -static void populate_fetchhead(git_vector *out, git_repository *repo) -{ - git_fetchhead_ref *fetchhead_ref; - git_oid oid; - - cl_git_pass(git_oid_fromstr(&oid, - "49322bb17d3acc9146f98c97d078513228bbf3c0")); - cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 1, - "refs/heads/master", - "git://github.com/libgit2/TestGitRepository")); - cl_git_pass(git_vector_insert(out, fetchhead_ref)); - - cl_git_pass(git_oid_fromstr(&oid, - "0966a434eb1a025db6b71485ab63a3bfbea520b6")); - cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0, - "refs/heads/first-merge", - "git://github.com/libgit2/TestGitRepository")); - cl_git_pass(git_vector_insert(out, fetchhead_ref)); - - cl_git_pass(git_oid_fromstr(&oid, - "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1")); - cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0, - "refs/heads/no-parent", - "git://github.com/libgit2/TestGitRepository")); - cl_git_pass(git_vector_insert(out, fetchhead_ref)); - - cl_git_pass(git_oid_fromstr(&oid, - "d96c4e80345534eccee5ac7b07fc7603b56124cb")); - cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0, - "refs/tags/annotated_tag", - "git://github.com/libgit2/TestGitRepository")); - cl_git_pass(git_vector_insert(out, fetchhead_ref)); - - cl_git_pass(git_oid_fromstr(&oid, - "55a1a760df4b86a02094a904dfa511deb5655905")); - cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0, - "refs/tags/blob", - "git://github.com/libgit2/TestGitRepository")); - cl_git_pass(git_vector_insert(out, fetchhead_ref)); - - cl_git_pass(git_oid_fromstr(&oid, - "8f50ba15d49353813cc6e20298002c0d17b0a9ee")); - cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0, - "refs/tags/commit_tree", - "git://github.com/libgit2/TestGitRepository")); - cl_git_pass(git_vector_insert(out, fetchhead_ref)); - - cl_git_pass(git_fetchhead_write(repo, out)); -} - -void test_fetchhead_nonetwork__write(void) -{ - git_vector fetchhead_vector = GIT_VECTOR_INIT; - git_fetchhead_ref *fetchhead_ref; - git_buf fetchhead_buf = GIT_BUF_INIT; - int equals = 0; - size_t i; - - git_vector_init(&fetchhead_vector, 6, NULL); - - cl_set_cleanup(&cleanup_repository, "./test1"); - cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); - - populate_fetchhead(&fetchhead_vector, g_repo); - - cl_git_pass(git_futils_readbuffer(&fetchhead_buf, - "./test1/.git/FETCH_HEAD")); - - equals = (strcmp(fetchhead_buf.ptr, FETCH_HEAD_WILDCARD_DATA_LOCAL) == 0); - - git_buf_free(&fetchhead_buf); - - git_vector_foreach(&fetchhead_vector, i, fetchhead_ref) { - git_fetchhead_ref_free(fetchhead_ref); - } - - git_vector_free(&fetchhead_vector); - - cl_assert(equals); -} - -typedef struct { - git_vector *fetchhead_vector; - size_t idx; -} fetchhead_ref_cb_data; - -static int fetchhead_ref_cb(const char *name, const char *url, - const git_oid *oid, unsigned int is_merge, void *payload) -{ - fetchhead_ref_cb_data *cb_data = payload; - git_fetchhead_ref *expected; - - cl_assert(payload); - - expected = git_vector_get(cb_data->fetchhead_vector, cb_data->idx); - - cl_assert(git_oid_cmp(&expected->oid, oid) == 0); - cl_assert(expected->is_merge == is_merge); - - if (expected->ref_name) - cl_assert_equal_s(expected->ref_name, name); - else - cl_assert(name == NULL); - - if (expected->remote_url) - cl_assert_equal_s(expected->remote_url, url); - else - cl_assert(url == NULL); - - cb_data->idx++; - - return 0; -} - -void test_fetchhead_nonetwork__read(void) -{ - git_vector fetchhead_vector = GIT_VECTOR_INIT; - git_fetchhead_ref *fetchhead_ref; - fetchhead_ref_cb_data cb_data; - size_t i; - - memset(&cb_data, 0x0, sizeof(fetchhead_ref_cb_data)); - - cl_set_cleanup(&cleanup_repository, "./test1"); - cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); - - populate_fetchhead(&fetchhead_vector, g_repo); - - cb_data.fetchhead_vector = &fetchhead_vector; - - cl_git_pass(git_repository_fetchhead_foreach(g_repo, fetchhead_ref_cb, &cb_data)); - - git_vector_foreach(&fetchhead_vector, i, fetchhead_ref) { - git_fetchhead_ref_free(fetchhead_ref); - } - - git_vector_free(&fetchhead_vector); -} - -static int read_old_style_cb(const char *name, const char *url, - const git_oid *oid, unsigned int is_merge, void *payload) -{ - git_oid expected; - - GIT_UNUSED(payload); - - git_oid_fromstr(&expected, "49322bb17d3acc9146f98c97d078513228bbf3c0"); - - cl_assert(name == NULL); - cl_assert(url == NULL); - cl_assert(git_oid_cmp(&expected, oid) == 0); - cl_assert(is_merge == 1); - - return 0; -} - -void test_fetchhead_nonetwork__read_old_style(void) -{ - cl_set_cleanup(&cleanup_repository, "./test1"); - cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); - - cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\n"); - - cl_git_pass(git_repository_fetchhead_foreach(g_repo, read_old_style_cb, NULL)); -} - -static int read_type_missing(const char *ref_name, const char *remote_url, - const git_oid *oid, unsigned int is_merge, void *payload) -{ - git_oid expected; - - GIT_UNUSED(payload); - - git_oid_fromstr(&expected, "49322bb17d3acc9146f98c97d078513228bbf3c0"); - - cl_assert_equal_s("name", ref_name); - cl_assert_equal_s("remote_url", remote_url); - cl_assert(git_oid_cmp(&expected, oid) == 0); - cl_assert(is_merge == 0); - - return 0; -} - -void test_fetchhead_nonetwork__type_missing(void) -{ - cl_set_cleanup(&cleanup_repository, "./test1"); - cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); - - cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\t'name' of remote_url\n"); - - cl_git_pass(git_repository_fetchhead_foreach(g_repo, read_type_missing, NULL)); -} - -static int read_name_missing(const char *ref_name, const char *remote_url, - const git_oid *oid, unsigned int is_merge, void *payload) -{ - git_oid expected; - - GIT_UNUSED(payload); - - git_oid_fromstr(&expected, "49322bb17d3acc9146f98c97d078513228bbf3c0"); - - cl_assert(ref_name == NULL); - cl_assert_equal_s("remote_url", remote_url); - cl_assert(git_oid_cmp(&expected, oid) == 0); - cl_assert(is_merge == 0); - - return 0; -} - -void test_fetchhead_nonetwork__name_missing(void) -{ - cl_set_cleanup(&cleanup_repository, "./test1"); - cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); - - cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\tremote_url\n"); - - cl_git_pass(git_repository_fetchhead_foreach(g_repo, read_name_missing, NULL)); -} - -static int read_noop(const char *ref_name, const char *remote_url, - const git_oid *oid, unsigned int is_merge, void *payload) -{ - GIT_UNUSED(ref_name); - GIT_UNUSED(remote_url); - GIT_UNUSED(oid); - GIT_UNUSED(is_merge); - GIT_UNUSED(payload); - - return 0; -} - -void test_fetchhead_nonetwork__nonexistent(void) -{ - int error; - - cl_set_cleanup(&cleanup_repository, "./test1"); - cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); - - cl_git_fail((error = git_repository_fetchhead_foreach(g_repo, read_noop, NULL))); - cl_assert(error == GIT_ENOTFOUND); -} - -void test_fetchhead_nonetwork__invalid_unterminated_last_line(void) -{ - cl_set_cleanup(&cleanup_repository, "./test1"); - cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); - - cl_git_rewritefile("./test1/.git/FETCH_HEAD", "unterminated"); - cl_git_fail(git_repository_fetchhead_foreach(g_repo, read_noop, NULL)); -} - -void test_fetchhead_nonetwork__invalid_oid(void) -{ - cl_set_cleanup(&cleanup_repository, "./test1"); - cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); - - cl_git_rewritefile("./test1/.git/FETCH_HEAD", "shortoid\n"); - cl_git_fail(git_repository_fetchhead_foreach(g_repo, read_noop, NULL)); -} - -void test_fetchhead_nonetwork__invalid_for_merge(void) -{ - cl_set_cleanup(&cleanup_repository, "./test1"); - cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); - - 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); -} - -void test_fetchhead_nonetwork__invalid_description(void) -{ - cl_set_cleanup(&cleanup_repository, "./test1"); - cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); - - 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); -} - diff --git a/tests-clar/filter/blob.c b/tests-clar/filter/blob.c deleted file mode 100644 index 9600a9779..000000000 --- a/tests-clar/filter/blob.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "clar_libgit2.h" -#include "crlf.h" - -static git_repository *g_repo = NULL; - -void test_filter_blob__initialize(void) -{ - g_repo = cl_git_sandbox_init("crlf"); - cl_git_mkfile("crlf/.gitattributes", - "*.txt text\n*.bin binary\n" - "*.crlf text eol=crlf\n" - "*.lf text eol=lf\n" - "*.ident text ident\n" - "*.identcrlf ident text eol=crlf\n" - "*.identlf ident text eol=lf\n"); -} - -void test_filter_blob__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_filter_blob__all_crlf(void) -{ - git_blob *blob; - git_buf buf = { 0 }; - - cl_git_pass(git_revparse_single( - (git_object **)&blob, g_repo, "a9a2e891")); /* all-crlf */ - - cl_assert_equal_s(ALL_CRLF_TEXT_RAW, git_blob_rawcontent(blob)); - - cl_git_pass(git_blob_filtered_content(&buf, blob, "file.bin", 1)); - - cl_assert_equal_s(ALL_CRLF_TEXT_RAW, buf.ptr); - - cl_git_pass(git_blob_filtered_content(&buf, blob, "file.crlf", 1)); - - /* in this case, raw content has crlf in it already */ - cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr); - - cl_git_pass(git_blob_filtered_content(&buf, blob, "file.lf", 1)); - - cl_assert_equal_s(ALL_CRLF_TEXT_AS_LF, buf.ptr); - - git_buf_free(&buf); - git_blob_free(blob); -} - -void test_filter_blob__ident(void) -{ - git_oid id; - git_blob *blob; - git_buf buf = { 0 }; - - cl_git_mkfile("crlf/test.ident", "Some text\n$Id$\nGoes there\n"); - cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "test.ident")); - cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); - cl_assert_equal_s( - "Some text\n$Id$\nGoes there\n", git_blob_rawcontent(blob)); - git_blob_free(blob); - - cl_git_mkfile("crlf/test.ident", "Some text\n$Id: Any old just you want$\nGoes there\n"); - cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "test.ident")); - cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); - cl_assert_equal_s( - "Some text\n$Id$\nGoes there\n", git_blob_rawcontent(blob)); - - cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.bin", 1)); - cl_assert_equal_s( - "Some text\n$Id$\nGoes there\n", buf.ptr); - - cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.identcrlf", 1)); - cl_assert_equal_s( - "Some text\r\n$Id: 3164f585d548ac68027d22b104f2d8100b2b6845$\r\nGoes there\r\n", buf.ptr); - - cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.identlf", 1)); - cl_assert_equal_s( - "Some text\n$Id: 3164f585d548ac68027d22b104f2d8100b2b6845$\nGoes there\n", buf.ptr); - - git_buf_free(&buf); - git_blob_free(blob); - -} diff --git a/tests-clar/filter/crlf.c b/tests-clar/filter/crlf.c deleted file mode 100644 index c9fb9cd7f..000000000 --- a/tests-clar/filter/crlf.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/sys/filter.h" - -static git_repository *g_repo = NULL; - -void test_filter_crlf__initialize(void) -{ - g_repo = cl_git_sandbox_init("crlf"); - - cl_git_mkfile("crlf/.gitattributes", - "*.txt text\n*.bin binary\n*.crlf text eol=crlf\n*.lf text eol=lf\n"); - - cl_repo_set_bool(g_repo, "core.autocrlf", true); -} - -void test_filter_crlf__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_filter_crlf__to_worktree(void) -{ - git_filter_list *fl; - git_filter *crlf; - git_buf in = { 0 }, out = { 0 }; - - cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_WORKTREE)); - - crlf = git_filter_lookup(GIT_FILTER_CRLF); - cl_assert(crlf != NULL); - - cl_git_pass(git_filter_list_push(fl, crlf, NULL)); - - in.ptr = "Some text\nRight here\n"; - in.size = strlen(in.ptr); - - cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); - -#ifdef GIT_WIN32 - cl_assert_equal_s("Some text\r\nRight here\r\n", out.ptr); -#else - cl_assert_equal_s("Some text\nRight here\n", out.ptr); -#endif - - git_filter_list_free(fl); - git_buf_free(&out); -} - -void test_filter_crlf__to_odb(void) -{ - git_filter_list *fl; - git_filter *crlf; - git_buf in = { 0 }, out = { 0 }; - - cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_ODB)); - - crlf = git_filter_lookup(GIT_FILTER_CRLF); - cl_assert(crlf != NULL); - - cl_git_pass(git_filter_list_push(fl, crlf, NULL)); - - in.ptr = "Some text\r\nRight here\r\n"; - in.size = strlen(in.ptr); - - cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); - - cl_assert_equal_s("Some text\nRight here\n", out.ptr); - - git_filter_list_free(fl); - git_buf_free(&out); -} diff --git a/tests-clar/filter/crlf.h b/tests-clar/filter/crlf.h deleted file mode 100644 index 9cb98ad4c..000000000 --- a/tests-clar/filter/crlf.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef INCLUDE_filter_crlf_h__ -#define INCLUDE_filter_crlf_h__ - -/* - * file content for files in the resources/crlf repository - */ - -#define UTF8_BOM "\xEF\xBB\xBF" - -#define ALL_CRLF_TEXT_RAW "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n" -#define ALL_LF_TEXT_RAW "lf\nlf\nlf\nlf\nlf\n" -#define MORE_CRLF_TEXT_RAW "crlf\r\ncrlf\r\nlf\ncrlf\r\ncrlf\r\n" -#define MORE_LF_TEXT_RAW "lf\nlf\ncrlf\r\nlf\nlf\n" - -#define ALL_CRLF_TEXT_AS_CRLF ALL_CRLF_TEXT_RAW -#define ALL_LF_TEXT_AS_CRLF "lf\r\nlf\r\nlf\r\nlf\r\nlf\r\n" -#define MORE_CRLF_TEXT_AS_CRLF "crlf\r\ncrlf\r\nlf\r\ncrlf\r\ncrlf\r\n" -#define MORE_LF_TEXT_AS_CRLF "lf\r\nlf\r\ncrlf\r\nlf\r\nlf\r\n" - -#define ALL_CRLF_TEXT_AS_LF "crlf\ncrlf\ncrlf\ncrlf\n" -#define ALL_LF_TEXT_AS_LF ALL_LF_TEXT_RAW -#define MORE_CRLF_TEXT_AS_LF "crlf\ncrlf\nlf\ncrlf\ncrlf\n" -#define MORE_LF_TEXT_AS_LF "lf\nlf\ncrlf\nlf\nlf\n" - -#endif diff --git a/tests-clar/filter/custom.c b/tests-clar/filter/custom.c deleted file mode 100644 index a81885c28..000000000 --- a/tests-clar/filter/custom.c +++ /dev/null @@ -1,337 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" -#include "blob.h" -#include "filter.h" -#include "buf_text.h" -#include "git2/sys/filter.h" -#include "git2/sys/repository.h" - -/* going TO_WORKDIR, filters are executed low to high - * going TO_ODB, filters are executed high to low - */ -#define BITFLIP_FILTER_PRIORITY -1 -#define REVERSE_FILTER_PRIORITY -2 - -#define VERY_SECURE_ENCRYPTION(b) ((b) ^ 0xff) - -#ifdef GIT_WIN32 -# define NEWLINE "\r\n" -#else -# define NEWLINE "\n" -#endif - -static char workdir_data[] = - "some simple" NEWLINE - "data" NEWLINE - "that will be" NEWLINE - "trivially" NEWLINE - "scrambled." NEWLINE; - -/* Represents the data above scrambled (bits flipped) after \r\n -> \n - * conversion, then bytewise reversed - */ -static unsigned char bitflipped_and_reversed_data[] = - { 0xf5, 0xd1, 0x9b, 0x9a, 0x93, 0x9d, 0x92, 0x9e, 0x8d, 0x9c, 0x8c, - 0xf5, 0x86, 0x93, 0x93, 0x9e, 0x96, 0x89, 0x96, 0x8d, 0x8b, 0xf5, - 0x9a, 0x9d, 0xdf, 0x93, 0x93, 0x96, 0x88, 0xdf, 0x8b, 0x9e, 0x97, - 0x8b, 0xf5, 0x9e, 0x8b, 0x9e, 0x9b, 0xf5, 0x9a, 0x93, 0x8f, 0x92, - 0x96, 0x8c, 0xdf, 0x9a, 0x92, 0x90, 0x8c }; - -#define BITFLIPPED_AND_REVERSED_DATA_LEN 51 - -static git_repository *g_repo = NULL; - -static void register_custom_filters(void); - -void test_filter_custom__initialize(void) -{ - register_custom_filters(); - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_mkfile( - "empty_standard_repo/.gitattributes", - "hero* bitflip reverse\n" - "herofile text\n" - "heroflip -reverse binary\n" - "*.bin binary\n"); -} - -void test_filter_custom__cleanup(void) -{ - cl_git_sandbox_cleanup(); - g_repo = NULL; -} - -static int bitflip_filter_apply( - git_filter *self, - void **payload, - git_buf *to, - const git_buf *from, - const git_filter_source *source) -{ - const unsigned char *src = (const unsigned char *)from->ptr; - unsigned char *dst; - size_t i; - - GIT_UNUSED(self); GIT_UNUSED(payload); - - /* verify that attribute path match worked as expected */ - cl_assert_equal_i( - 0, git__strncmp("hero", git_filter_source_path(source), 4)); - - if (!from->size) - return 0; - - cl_git_pass(git_buf_grow(to, from->size)); - - dst = (unsigned char *)to->ptr; - - for (i = 0; i < from->size; i++) - dst[i] = VERY_SECURE_ENCRYPTION(src[i]); - - to->size = from->size; - - return 0; -} - -static void bitflip_filter_free(git_filter *f) -{ - git__free(f); -} - -static git_filter *create_bitflip_filter(void) -{ - git_filter *filter = git__calloc(1, sizeof(git_filter)); - cl_assert(filter); - - filter->version = GIT_FILTER_VERSION; - filter->attributes = "+bitflip"; - filter->shutdown = bitflip_filter_free; - filter->apply = bitflip_filter_apply; - - return filter; -} - - -static int reverse_filter_apply( - git_filter *self, - void **payload, - git_buf *to, - const git_buf *from, - const git_filter_source *source) -{ - const unsigned char *src = (const unsigned char *)from->ptr; - const unsigned char *end = src + from->size; - unsigned char *dst; - - GIT_UNUSED(self); GIT_UNUSED(payload); GIT_UNUSED(source); - - /* verify that attribute path match worked as expected */ - cl_assert_equal_i( - 0, git__strncmp("hero", git_filter_source_path(source), 4)); - - if (!from->size) - return 0; - - cl_git_pass(git_buf_grow(to, from->size)); - - dst = (unsigned char *)to->ptr + from->size - 1; - - while (src < end) - *dst-- = *src++; - - to->size = from->size; - - return 0; -} - -static void reverse_filter_free(git_filter *f) -{ - git__free(f); -} - -static git_filter *create_reverse_filter(const char *attrs) -{ - git_filter *filter = git__calloc(1, sizeof(git_filter)); - cl_assert(filter); - - filter->version = GIT_FILTER_VERSION; - filter->attributes = attrs; - filter->shutdown = reverse_filter_free; - filter->apply = reverse_filter_apply; - - return filter; -} - -static void register_custom_filters(void) -{ - static int filters_registered = 0; - - if (!filters_registered) { - cl_git_pass(git_filter_register( - "bitflip", create_bitflip_filter(), BITFLIP_FILTER_PRIORITY)); - - cl_git_pass(git_filter_register( - "reverse", create_reverse_filter("+reverse"), - REVERSE_FILTER_PRIORITY)); - - /* re-register reverse filter with standard filter=xyz priority */ - cl_git_pass(git_filter_register( - "pre-reverse", - create_reverse_filter("+prereverse"), - GIT_FILTER_DRIVER_PRIORITY)); - - filters_registered = 1; - } -} - - -void test_filter_custom__to_odb(void) -{ - git_filter_list *fl; - git_buf out = { 0 }; - git_buf in = GIT_BUF_INIT_CONST(workdir_data, strlen(workdir_data)); - - cl_git_pass(git_filter_list_load( - &fl, g_repo, NULL, "herofile", GIT_FILTER_TO_ODB)); - - cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); - - cl_assert_equal_i(BITFLIPPED_AND_REVERSED_DATA_LEN, out.size); - - cl_assert_equal_i( - 0, memcmp(bitflipped_and_reversed_data, out.ptr, out.size)); - - git_filter_list_free(fl); - git_buf_free(&out); -} - -void test_filter_custom__to_workdir(void) -{ - git_filter_list *fl; - git_buf out = { 0 }; - git_buf in = GIT_BUF_INIT_CONST( - bitflipped_and_reversed_data, BITFLIPPED_AND_REVERSED_DATA_LEN); - - cl_git_pass(git_filter_list_load( - &fl, g_repo, NULL, "herofile", GIT_FILTER_TO_WORKTREE)); - - cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); - - cl_assert_equal_i(strlen(workdir_data), out.size); - - cl_assert_equal_i( - 0, memcmp(workdir_data, out.ptr, out.size)); - - git_filter_list_free(fl); - git_buf_free(&out); -} - -void test_filter_custom__can_register_a_custom_filter_in_the_repository(void) -{ - git_filter_list *fl; - - cl_git_pass(git_filter_list_load( - &fl, g_repo, NULL, "herofile", GIT_FILTER_TO_WORKTREE)); - /* expect: bitflip, reverse, crlf */ - cl_assert_equal_sz(3, git_filter_list_length(fl)); - git_filter_list_free(fl); - - cl_git_pass(git_filter_list_load( - &fl, g_repo, NULL, "herocorp", GIT_FILTER_TO_WORKTREE)); - /* expect: bitflip, reverse - possibly crlf depending on global config */ - { - size_t flen = git_filter_list_length(fl); - cl_assert(flen == 2 || flen == 3); - } - git_filter_list_free(fl); - - cl_git_pass(git_filter_list_load( - &fl, g_repo, NULL, "hero.bin", GIT_FILTER_TO_WORKTREE)); - /* expect: bitflip, reverse */ - cl_assert_equal_sz(2, git_filter_list_length(fl)); - git_filter_list_free(fl); - - cl_git_pass(git_filter_list_load( - &fl, g_repo, NULL, "heroflip", GIT_FILTER_TO_WORKTREE)); - /* expect: bitflip (because of -reverse) */ - cl_assert_equal_sz(1, git_filter_list_length(fl)); - git_filter_list_free(fl); - - cl_git_pass(git_filter_list_load( - &fl, g_repo, NULL, "doesntapplytome.bin", GIT_FILTER_TO_WORKTREE)); - /* expect: none */ - cl_assert_equal_sz(0, git_filter_list_length(fl)); - git_filter_list_free(fl); -} - -void test_filter_custom__order_dependency(void) -{ - git_index *index; - git_blob *blob; - git_buf buf = { 0 }; - - /* so if ident and reverse are used together, an interesting thing - * happens - a reversed "$Id$" string is no longer going to trigger - * ident correctly. When checking out, the filters should be applied - * in order CLRF, then ident, then reverse, so ident expansion should - * work correctly. On check in, the content should be reversed, then - * ident, then CRLF filtered. Let's make sure that works... - */ - - cl_git_mkfile( - "empty_standard_repo/.gitattributes", - "hero.*.rev-ident text ident prereverse eol=lf\n"); - - cl_git_mkfile( - "empty_standard_repo/hero.1.rev-ident", - "This is a test\n$Id$\nHave fun!\n"); - - cl_git_mkfile( - "empty_standard_repo/hero.2.rev-ident", - "Another test\n$dI$\nCrazy!\n"); - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_index_add_bypath(index, "hero.1.rev-ident")); - cl_git_pass(git_index_add_bypath(index, "hero.2.rev-ident")); - cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "Filter chains\n"); - git_index_free(index); - - cl_git_pass(git_blob_lookup(&blob, g_repo, - & git_index_get_bypath(index, "hero.1.rev-ident", 0)->oid)); - cl_assert_equal_s( - "\n!nuf evaH\n$dI$\ntset a si sihT", git_blob_rawcontent(blob)); - cl_git_pass(git_blob_filtered_content(&buf, blob, "hero.1.rev-ident", 0)); - /* no expansion because id was reversed at checkin and now at ident - * time, reverse is not applied yet */ - cl_assert_equal_s( - "This is a test\n$Id$\nHave fun!\n", buf.ptr); - git_blob_free(blob); - - cl_git_pass(git_blob_lookup(&blob, g_repo, - & git_index_get_bypath(index, "hero.2.rev-ident", 0)->oid)); - cl_assert_equal_s( - "\n!yzarC\n$Id$\ntset rehtonA", git_blob_rawcontent(blob)); - cl_git_pass(git_blob_filtered_content(&buf, blob, "hero.2.rev-ident", 0)); - /* expansion because reverse was applied at checkin and at ident time, - * reverse is not applied yet */ - cl_assert_equal_s( - "Another test\n$59001fe193103b1016b27027c0c827d036fd0ac8 :dI$\nCrazy!\n", buf.ptr); - cl_assert_equal_i(0, git_oid_strcmp( - git_blob_id(blob), "8ca0df630d728c0c72072b6101b301391ef10095")); - git_blob_free(blob); - - git_buf_free(&buf); -} - -void test_filter_custom__filter_registry_failure_cases(void) -{ - git_filter fake = { GIT_FILTER_VERSION, 0 }; - - cl_assert_equal_i(GIT_EEXISTS, git_filter_register("bitflip", &fake, 0)); - - cl_git_fail(git_filter_unregister(GIT_FILTER_CRLF)); - cl_git_fail(git_filter_unregister(GIT_FILTER_IDENT)); - cl_assert_equal_i(GIT_ENOTFOUND, git_filter_unregister("not-a-filter")); -} diff --git a/tests-clar/filter/ident.c b/tests-clar/filter/ident.c deleted file mode 100644 index 2c8e6abea..000000000 --- a/tests-clar/filter/ident.c +++ /dev/null @@ -1,131 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/sys/filter.h" - -static git_repository *g_repo = NULL; - -void test_filter_ident__initialize(void) -{ - g_repo = cl_git_sandbox_init("crlf"); -} - -void test_filter_ident__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -static void add_blob_and_filter( - const char *data, - git_filter_list *fl, - const char *expected) -{ - git_oid id; - git_blob *blob; - git_buf out = { 0 }; - - cl_git_mkfile("crlf/identtest", data); - cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "identtest")); - cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); - - cl_git_pass(git_filter_list_apply_to_blob(&out, fl, blob)); - - cl_assert_equal_s(expected, out.ptr); - - git_blob_free(blob); - git_buf_free(&out); -} - -void test_filter_ident__to_worktree(void) -{ - git_filter_list *fl; - git_filter *ident; - - cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_WORKTREE)); - - ident = git_filter_lookup(GIT_FILTER_IDENT); - cl_assert(ident != NULL); - - cl_git_pass(git_filter_list_push(fl, ident, NULL)); - - add_blob_and_filter( - "Hello\n$Id$\nFun stuff\n", fl, - "Hello\n$Id: b69e2387aafcaf73c4de5b9ab59abe27fdadee30$\nFun stuff\n"); - add_blob_and_filter( - "Hello\n$Id: Junky$\nFun stuff\n", fl, - "Hello\n$Id: 45cd107a7102911cb2a7df08404674327fa050b9$\nFun stuff\n"); - add_blob_and_filter( - "$Id$\nAt the start\n", fl, - "$Id: b13415c767abc196fb95bd17070e8c1113e32160$\nAt the start\n"); - add_blob_and_filter( - "At the end\n$Id$", fl, - "At the end\n$Id: 1344925c6bc65b34c5a7b50f86bf688e48e9a272$"); - add_blob_and_filter( - "$Id$", fl, - "$Id: b3f5ebfb5843bc43ceecff6d4f26bb37c615beb1$"); - add_blob_and_filter( - "$Id: Some sort of junk goes here$", fl, - "$Id: ab2dd3853c7c9a4bff55aca2bea077a73c32ac06$"); - - add_blob_and_filter("$Id: ", fl, "$Id: "); - add_blob_and_filter("$Id", fl, "$Id"); - add_blob_and_filter("$I", fl, "$I"); - add_blob_and_filter("Id$", fl, "Id$"); - - git_filter_list_free(fl); -} - -void test_filter_ident__to_odb(void) -{ - git_filter_list *fl; - git_filter *ident; - - cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_ODB)); - - ident = git_filter_lookup(GIT_FILTER_IDENT); - cl_assert(ident != NULL); - - cl_git_pass(git_filter_list_push(fl, ident, NULL)); - - add_blob_and_filter( - "Hello\n$Id$\nFun stuff\n", - fl, "Hello\n$Id$\nFun stuff\n"); - add_blob_and_filter( - "Hello\n$Id: b69e2387aafcaf73c4de5b9ab59abe27fdadee30$\nFun stuff\n", - fl, "Hello\n$Id$\nFun stuff\n"); - add_blob_and_filter( - "Hello\n$Id: Any junk you may have left here$\nFun stuff\n", - fl, "Hello\n$Id$\nFun stuff\n"); - add_blob_and_filter( - "Hello\n$Id:$\nFun stuff\n", - fl, "Hello\n$Id$\nFun stuff\n"); - add_blob_and_filter( - "Hello\n$Id:x$\nFun stuff\n", - fl, "Hello\n$Id$\nFun stuff\n"); - - add_blob_and_filter( - "$Id$\nAt the start\n", fl, "$Id$\nAt the start\n"); - add_blob_and_filter( - "$Id: lots of random text that should be removed from here$\nAt the start\n", fl, "$Id$\nAt the start\n"); - add_blob_and_filter( - "$Id: lots of random text that should not be removed without a terminator\nAt the start\n", fl, "$Id: lots of random text that should not be removed without a terminator\nAt the start\n"); - - add_blob_and_filter( - "At the end\n$Id$", fl, "At the end\n$Id$"); - add_blob_and_filter( - "At the end\n$Id:$", fl, "At the end\n$Id$"); - add_blob_and_filter( - "At the end\n$Id:asdfasdf$", fl, "At the end\n$Id$"); - add_blob_and_filter( - "At the end\n$Id", fl, "At the end\n$Id"); - add_blob_and_filter( - "At the end\n$IddI", fl, "At the end\n$IddI"); - - add_blob_and_filter("$Id$", fl, "$Id$"); - add_blob_and_filter("$Id: any$", fl, "$Id$"); - add_blob_and_filter("$Id: any long stuff goes here you see$", fl, "$Id$"); - add_blob_and_filter("$Id: ", fl, "$Id: "); - add_blob_and_filter("$Id", fl, "$Id"); - add_blob_and_filter("$I", fl, "$I"); - add_blob_and_filter("Id$", fl, "Id$"); - - git_filter_list_free(fl); -} diff --git a/tests-clar/generate.py b/tests-clar/generate.py deleted file mode 100644 index d4fe8f2a3..000000000 --- a/tests-clar/generate.py +++ /dev/null @@ -1,244 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) Vicent Marti. All rights reserved. -# -# This file is part of clar, distributed under the ISC license. -# For full terms see the included COPYING file. -# - -from __future__ import with_statement -from string import Template -import re, fnmatch, os, codecs, pickle - -class Module(object): - class Template(object): - def __init__(self, module): - self.module = module - - def _render_callback(self, cb): - if not cb: - return ' { NULL, NULL }' - return ' { "%s", &%s }' % (cb['short_name'], cb['symbol']) - - class DeclarationTemplate(Template): - def render(self): - out = "\n".join("extern %s;" % cb['declaration'] for cb in self.module.callbacks) + "\n" - - if self.module.initialize: - out += "extern %s;\n" % self.module.initialize['declaration'] - - if self.module.cleanup: - out += "extern %s;\n" % self.module.cleanup['declaration'] - - return out - - class CallbacksTemplate(Template): - def render(self): - out = "static const struct clar_func _clar_cb_%s[] = {\n" % self.module.name - out += ",\n".join(self._render_callback(cb) for cb in self.module.callbacks) - out += "\n};\n" - return out - - class InfoTemplate(Template): - def render(self): - return Template( - r""" - { - "${clean_name}", - ${initialize}, - ${cleanup}, - ${cb_ptr}, ${cb_count}, ${enabled} - }""" - ).substitute( - clean_name = self.module.clean_name(), - initialize = self._render_callback(self.module.initialize), - cleanup = self._render_callback(self.module.cleanup), - cb_ptr = "_clar_cb_%s" % self.module.name, - cb_count = len(self.module.callbacks), - enabled = int(self.module.enabled) - ) - - def __init__(self, name): - self.name = name - - self.mtime = 0 - self.enabled = True - self.modified = False - - def clean_name(self): - return self.name.replace("_", "::") - - def _skip_comments(self, text): - SKIP_COMMENTS_REGEX = re.compile( - r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', - re.DOTALL | re.MULTILINE) - - def _replacer(match): - s = match.group(0) - return "" if s.startswith('/') else s - - return re.sub(SKIP_COMMENTS_REGEX, _replacer, text) - - def parse(self, contents): - TEST_FUNC_REGEX = r"^(void\s+(test_%s__(\w+))\(\s*void\s*\))\s*\{" - - contents = self._skip_comments(contents) - regex = re.compile(TEST_FUNC_REGEX % self.name, re.MULTILINE) - - self.callbacks = [] - self.initialize = None - self.cleanup = None - - for (declaration, symbol, short_name) in regex.findall(contents): - data = { - "short_name" : short_name, - "declaration" : declaration, - "symbol" : symbol - } - - if short_name == 'initialize': - self.initialize = data - elif short_name == 'cleanup': - self.cleanup = data - else: - self.callbacks.append(data) - - return self.callbacks != [] - - def refresh(self, path): - self.modified = False - - try: - st = os.stat(path) - - # Not modified - if st.st_mtime == self.mtime: - return True - - self.modified = True - self.mtime = st.st_mtime - - with open(path) as fp: - raw_content = fp.read() - - except IOError: - return False - - return self.parse(raw_content) - -class TestSuite(object): - - def __init__(self, path): - self.path = path - - def should_generate(self, path): - if not os.path.isfile(path): - return True - - if any(module.modified for module in self.modules.values()): - return True - - return False - - def find_modules(self): - modules = [] - for root, _, files in os.walk(self.path): - module_root = root[len(self.path):] - module_root = [c for c in module_root.split(os.sep) if c] - - tests_in_module = fnmatch.filter(files, "*.c") - - for test_file in tests_in_module: - full_path = os.path.join(root, test_file) - module_name = "_".join(module_root + [test_file[:-2]]) - - modules.append((full_path, module_name)) - - return modules - - def load_cache(self): - path = os.path.join(self.path, '.clarcache') - cache = {} - - try: - fp = open(path, 'rb') - cache = pickle.load(fp) - fp.close() - except (IOError, ValueError): - pass - - return cache - - def save_cache(self): - path = os.path.join(self.path, '.clarcache') - with open(path, 'wb') as cache: - pickle.dump(self.modules, cache) - - def load(self, force = False): - module_data = self.find_modules() - self.modules = {} if force else self.load_cache() - - for path, name in module_data: - if name not in self.modules: - self.modules[name] = Module(name) - - if not self.modules[name].refresh(path): - del self.modules[name] - - def disable(self, excluded): - for exclude in excluded: - for module in self.modules.values(): - name = module.clean_name() - if name.startswith(exclude): - module.enabled = False - module.modified = True - - def suite_count(self): - return len(self.modules) - - def callback_count(self): - return sum(len(module.callbacks) for module in self.modules.values()) - - def write(self): - output = os.path.join(self.path, 'clar.suite') - - if not self.should_generate(output): - return False - - with open(output, 'w') as data: - for module in self.modules.values(): - t = Module.DeclarationTemplate(module) - data.write(t.render()) - - for module in self.modules.values(): - t = Module.CallbacksTemplate(module) - data.write(t.render()) - - suites = "static struct clar_suite _clar_suites[] = {" + ','.join( - Module.InfoTemplate(module).render() for module in sorted(self.modules.values(), key=lambda module: module.name) - ) + "\n};\n" - - data.write(suites) - - data.write("static const size_t _clar_suite_count = %d;\n" % self.suite_count()) - data.write("static const size_t _clar_callback_count = %d;\n" % self.callback_count()) - - suite.save_cache() - return True - -if __name__ == '__main__': - from optparse import OptionParser - - parser = OptionParser() - parser.add_option('-f', '--force', dest='force', default=False) - parser.add_option('-x', '--exclude', dest='excluded', action='append', default=[]) - - options, args = parser.parse_args() - - for path in args or ['.']: - suite = TestSuite(path) - suite.load(options.force) - suite.disable(options.excluded) - if suite.write(): - print("Written `clar.suite` (%d tests in %d suites)" % (suite.callback_count(), suite.suite_count())) - diff --git a/tests-clar/index/addall.c b/tests-clar/index/addall.c deleted file mode 100644 index 44c51279d..000000000 --- a/tests-clar/index/addall.c +++ /dev/null @@ -1,258 +0,0 @@ -#include "clar_libgit2.h" -#include "../status/status_helpers.h" -#include "posix.h" -#include "fileops.h" - -git_repository *g_repo = NULL; - -void test_index_addall__initialize(void) -{ -} - -void test_index_addall__cleanup(void) -{ - git_repository_free(g_repo); - g_repo = NULL; -} - -#define STATUS_INDEX_FLAGS \ - (GIT_STATUS_INDEX_NEW | GIT_STATUS_INDEX_MODIFIED | \ - GIT_STATUS_INDEX_DELETED | GIT_STATUS_INDEX_RENAMED | \ - GIT_STATUS_INDEX_TYPECHANGE) - -#define STATUS_WT_FLAGS \ - (GIT_STATUS_WT_NEW | GIT_STATUS_WT_MODIFIED | \ - GIT_STATUS_WT_DELETED | GIT_STATUS_WT_TYPECHANGE | \ - GIT_STATUS_WT_RENAMED) - -typedef struct { - size_t index_adds; - size_t index_dels; - size_t index_mods; - size_t wt_adds; - size_t wt_dels; - size_t wt_mods; - size_t ignores; -} index_status_counts; - -static int index_status_cb( - const char *path, unsigned int status_flags, void *payload) -{ - index_status_counts *vals = payload; - - /* cb_status__print(path, status_flags, NULL); */ - - GIT_UNUSED(path); - - if (status_flags & GIT_STATUS_INDEX_NEW) - vals->index_adds++; - if (status_flags & GIT_STATUS_INDEX_MODIFIED) - vals->index_mods++; - if (status_flags & GIT_STATUS_INDEX_DELETED) - vals->index_dels++; - if (status_flags & GIT_STATUS_INDEX_TYPECHANGE) - vals->index_mods++; - - if (status_flags & GIT_STATUS_WT_NEW) - vals->wt_adds++; - if (status_flags & GIT_STATUS_WT_MODIFIED) - vals->wt_mods++; - if (status_flags & GIT_STATUS_WT_DELETED) - vals->wt_dels++; - if (status_flags & GIT_STATUS_WT_TYPECHANGE) - vals->wt_mods++; - - if (status_flags & GIT_STATUS_IGNORED) - vals->ignores++; - - return 0; -} - -static void check_status_at_line( - git_repository *repo, - size_t index_adds, size_t index_dels, size_t index_mods, - size_t wt_adds, size_t wt_dels, size_t wt_mods, size_t ignores, - const char *file, int line) -{ - index_status_counts vals; - - memset(&vals, 0, sizeof(vals)); - - cl_git_pass(git_status_foreach(repo, index_status_cb, &vals)); - - clar__assert_equal( - file,line,"wrong index adds", 1, "%"PRIuZ, index_adds, vals.index_adds); - clar__assert_equal( - file,line,"wrong index dels", 1, "%"PRIuZ, index_dels, vals.index_dels); - clar__assert_equal( - file,line,"wrong index mods", 1, "%"PRIuZ, index_mods, vals.index_mods); - clar__assert_equal( - file,line,"wrong workdir adds", 1, "%"PRIuZ, wt_adds, vals.wt_adds); - clar__assert_equal( - file,line,"wrong workdir dels", 1, "%"PRIuZ, wt_dels, vals.wt_dels); - clar__assert_equal( - file,line,"wrong workdir mods", 1, "%"PRIuZ, wt_mods, vals.wt_mods); - clar__assert_equal( - file,line,"wrong ignores", 1, "%"PRIuZ, ignores, vals.ignores); -} - -#define check_status(R,IA,ID,IM,WA,WD,WM,IG) \ - check_status_at_line(R,IA,ID,IM,WA,WD,WM,IG,__FILE__,__LINE__) - -static void check_stat_data(git_index *index, const char *path, bool match) -{ - const git_index_entry *entry; - struct stat st; - - cl_must_pass(p_lstat(path, &st)); - - /* skip repo base dir name */ - while (*path != '/') - ++path; - ++path; - - entry = git_index_get_bypath(index, path, 0); - cl_assert(entry); - - if (match) { - cl_assert(st.st_ctime == entry->ctime.seconds); - cl_assert(st.st_mtime == entry->mtime.seconds); - cl_assert(st.st_size == entry->file_size); - cl_assert(st.st_uid == entry->uid); - cl_assert(st.st_gid == entry->gid); - cl_assert_equal_i_fmt( - GIT_MODE_TYPE(st.st_mode), GIT_MODE_TYPE(entry->mode), "%07o"); - if (cl_is_chmod_supported()) - cl_assert_equal_b( - GIT_PERMS_IS_EXEC(st.st_mode), GIT_PERMS_IS_EXEC(entry->mode)); - } else { - /* most things will still match */ - cl_assert(st.st_size != entry->file_size); - /* would check mtime, but with second resolution it won't work :( */ - } -} - -void test_index_addall__repo_lifecycle(void) -{ - int error; - git_index *index; - git_strarray paths = { NULL, 0 }; - char *strs[1]; - - cl_git_pass(git_repository_init(&g_repo, "addall", false)); - check_status(g_repo, 0, 0, 0, 0, 0, 0, 0); - - cl_git_pass(git_repository_index(&index, g_repo)); - - cl_git_mkfile("addall/file.foo", "a file"); - check_status(g_repo, 0, 0, 0, 1, 0, 0, 0); - - cl_git_mkfile("addall/.gitignore", "*.foo\n"); - check_status(g_repo, 0, 0, 0, 1, 0, 0, 1); - - cl_git_mkfile("addall/file.bar", "another file"); - check_status(g_repo, 0, 0, 0, 2, 0, 0, 1); - - strs[0] = "file.*"; - paths.strings = strs; - paths.count = 1; - - cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL)); - check_stat_data(index, "addall/file.bar", true); - check_status(g_repo, 1, 0, 0, 1, 0, 0, 1); - - cl_git_rewritefile("addall/file.bar", "new content for file"); - check_stat_data(index, "addall/file.bar", false); - check_status(g_repo, 1, 0, 0, 1, 0, 1, 1); - - cl_git_mkfile("addall/file.zzz", "yet another one"); - cl_git_mkfile("addall/other.zzz", "yet another one"); - cl_git_mkfile("addall/more.zzz", "yet another one"); - check_status(g_repo, 1, 0, 0, 4, 0, 1, 1); - - cl_git_pass(git_index_update_all(index, NULL, NULL, NULL)); - check_stat_data(index, "addall/file.bar", true); - check_status(g_repo, 1, 0, 0, 4, 0, 0, 1); - - cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL)); - check_stat_data(index, "addall/file.zzz", true); - check_status(g_repo, 2, 0, 0, 3, 0, 0, 1); - - cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "first commit"); - check_status(g_repo, 0, 0, 0, 3, 0, 0, 1); - - /* attempt to add an ignored file - does nothing */ - strs[0] = "file.foo"; - cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL)); - check_status(g_repo, 0, 0, 0, 3, 0, 0, 1); - - /* add with check - should generate error */ - error = git_index_add_all( - index, &paths, GIT_INDEX_ADD_CHECK_PATHSPEC, NULL, NULL); - cl_assert_equal_i(GIT_EINVALIDSPEC, error); - check_status(g_repo, 0, 0, 0, 3, 0, 0, 1); - - /* add with force - should allow */ - cl_git_pass(git_index_add_all( - index, &paths, GIT_INDEX_ADD_FORCE, NULL, NULL)); - check_stat_data(index, "addall/file.foo", true); - check_status(g_repo, 1, 0, 0, 3, 0, 0, 0); - - /* now it's in the index, so regular add should work */ - cl_git_rewritefile("addall/file.foo", "new content for file"); - check_stat_data(index, "addall/file.foo", false); - check_status(g_repo, 1, 0, 0, 3, 0, 1, 0); - - cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL)); - check_stat_data(index, "addall/file.foo", true); - check_status(g_repo, 1, 0, 0, 3, 0, 0, 0); - - cl_git_pass(git_index_add_bypath(index, "more.zzz")); - check_stat_data(index, "addall/more.zzz", true); - check_status(g_repo, 2, 0, 0, 2, 0, 0, 0); - - cl_git_rewritefile("addall/file.zzz", "new content for file"); - check_status(g_repo, 2, 0, 0, 2, 0, 1, 0); - - cl_git_pass(git_index_add_bypath(index, "file.zzz")); - check_stat_data(index, "addall/file.zzz", true); - check_status(g_repo, 2, 0, 1, 2, 0, 0, 0); - - strs[0] = "*.zzz"; - cl_git_pass(git_index_remove_all(index, &paths, NULL, NULL)); - check_status(g_repo, 1, 1, 0, 4, 0, 0, 0); - - cl_git_pass(git_index_add_bypath(index, "file.zzz")); - check_status(g_repo, 1, 0, 1, 3, 0, 0, 0); - - cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "second commit"); - check_status(g_repo, 0, 0, 0, 3, 0, 0, 0); - - cl_must_pass(p_unlink("addall/file.zzz")); - check_status(g_repo, 0, 0, 0, 3, 1, 0, 0); - - /* update_all should be able to remove entries */ - cl_git_pass(git_index_update_all(index, NULL, NULL, NULL)); - check_status(g_repo, 0, 1, 0, 3, 0, 0, 0); - - strs[0] = "*"; - cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL)); - check_status(g_repo, 3, 1, 0, 0, 0, 0, 0); - - /* must be able to remove at any position while still updating other files */ - cl_must_pass(p_unlink("addall/.gitignore")); - cl_git_rewritefile("addall/file.zzz", "reconstructed file"); - cl_git_rewritefile("addall/more.zzz", "altered file reality"); - check_status(g_repo, 3, 1, 0, 1, 1, 1, 0); - - cl_git_pass(git_index_update_all(index, NULL, NULL, NULL)); - check_status(g_repo, 2, 1, 0, 1, 0, 0, 0); - /* this behavior actually matches 'git add -u' where "file.zzz" has - * been removed from the index, so when you go to update, even though - * it exists in the HEAD, it is not re-added to the index, leaving it - * as a DELETE when comparing HEAD to index and as an ADD comparing - * index to worktree - */ - - git_index_free(index); -} diff --git a/tests-clar/index/conflicts.c b/tests-clar/index/conflicts.c deleted file mode 100644 index 6311b3a75..000000000 --- a/tests-clar/index/conflicts.c +++ /dev/null @@ -1,287 +0,0 @@ -#include "clar_libgit2.h" -#include "index.h" -#include "git2/repository.h" - -static git_repository *repo; -static git_index *repo_index; - -#define TEST_REPO_PATH "mergedrepo" -#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" - -#define CONFLICTS_ONE_ANCESTOR_OID "1f85ca51b8e0aac893a621b61a9c2661d6aa6d81" -#define CONFLICTS_ONE_OUR_OID "6aea5f295304c36144ad6e9247a291b7f8112399" -#define CONFLICTS_ONE_THEIR_OID "516bd85f78061e09ccc714561d7b504672cb52da" - -#define CONFLICTS_TWO_ANCESTOR_OID "84af62840be1b1c47b778a8a249f3ff45155038c" -#define CONFLICTS_TWO_OUR_OID "8b3f43d2402825c200f835ca1762413e386fd0b2" -#define CONFLICTS_TWO_THEIR_OID "220bd62631c8cf7a83ef39c6b94595f00517211e" - -#define TEST_ANCESTOR_OID "f00ff00ff00ff00ff00ff00ff00ff00ff00ff00f" -#define TEST_OUR_OID "b44bb44bb44bb44bb44bb44bb44bb44bb44bb44b" -#define TEST_THEIR_OID "0123456789abcdef0123456789abcdef01234567" - -// Fixture setup and teardown -void test_index_conflicts__initialize(void) -{ - repo = cl_git_sandbox_init("mergedrepo"); - git_repository_index(&repo_index, repo); -} - -void test_index_conflicts__cleanup(void) -{ - git_index_free(repo_index); - repo_index = NULL; - - cl_git_sandbox_cleanup(); -} - -void test_index_conflicts__add(void) -{ - git_index_entry ancestor_entry, our_entry, their_entry; - - cl_assert(git_index_entrycount(repo_index) == 8); - - memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); - memset(&our_entry, 0x0, sizeof(git_index_entry)); - memset(&their_entry, 0x0, sizeof(git_index_entry)); - - ancestor_entry.path = "test-one.txt"; - ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); - git_oid_fromstr(&ancestor_entry.oid, TEST_ANCESTOR_OID); - - our_entry.path = "test-one.txt"; - ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT); - git_oid_fromstr(&our_entry.oid, TEST_OUR_OID); - - their_entry.path = "test-one.txt"; - ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT); - git_oid_fromstr(&their_entry.oid, TEST_THEIR_OID); - - cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry)); - - cl_assert(git_index_entrycount(repo_index) == 11); -} - -void test_index_conflicts__add_fixes_incorrect_stage(void) -{ - git_index_entry ancestor_entry, our_entry, their_entry; - const git_index_entry *conflict_entry[3]; - - cl_assert(git_index_entrycount(repo_index) == 8); - - memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); - memset(&our_entry, 0x0, sizeof(git_index_entry)); - memset(&their_entry, 0x0, sizeof(git_index_entry)); - - ancestor_entry.path = "test-one.txt"; - ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT); - git_oid_fromstr(&ancestor_entry.oid, TEST_ANCESTOR_OID); - - our_entry.path = "test-one.txt"; - ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); - git_oid_fromstr(&our_entry.oid, TEST_OUR_OID); - - their_entry.path = "test-one.txt"; - ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT); - git_oid_fromstr(&their_entry.oid, TEST_THEIR_OID); - - cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry)); - - cl_assert(git_index_entrycount(repo_index) == 11); - - cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], repo_index, "test-one.txt")); - - cl_assert(git_index_entry_stage(conflict_entry[0]) == 1); - cl_assert(git_index_entry_stage(conflict_entry[1]) == 2); - cl_assert(git_index_entry_stage(conflict_entry[2]) == 3); -} - -void test_index_conflicts__get(void) -{ - const git_index_entry *conflict_entry[3]; - git_oid oid; - - cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], - &conflict_entry[2], repo_index, "conflicts-one.txt")); - - cl_assert_equal_s("conflicts-one.txt", conflict_entry[0]->path); - - git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID); - cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0); - - git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID); - cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0); - - git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID); - cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0); - - cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], - &conflict_entry[2], repo_index, "conflicts-two.txt")); - - cl_assert_equal_s("conflicts-two.txt", conflict_entry[0]->path); - - git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0); - - git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID); - cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0); - - git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID); - cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0); -} - -void test_index_conflicts__iterate(void) -{ - git_index_conflict_iterator *iterator; - const git_index_entry *conflict_entry[3]; - git_oid oid; - - cl_git_pass(git_index_conflict_iterator_new(&iterator, repo_index)); - - cl_git_pass(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator)); - - git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID); - cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0); - cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0); - - git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID); - cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0); - cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0); - - git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID); - cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0); - cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0); - - cl_git_pass(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator)); - - git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0); - cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0); - - git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID); - cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0); - cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0); - - git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID); - cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0); - cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0); - - cl_assert(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator) == GIT_ITEROVER); - - cl_assert(conflict_entry[0] == NULL); - cl_assert(conflict_entry[2] == NULL); - cl_assert(conflict_entry[2] == NULL); - - git_index_conflict_iterator_free(iterator); -} - -void test_index_conflicts__remove(void) -{ - const git_index_entry *entry; - size_t i; - - cl_assert(git_index_entrycount(repo_index) == 8); - - cl_git_pass(git_index_conflict_remove(repo_index, "conflicts-one.txt")); - cl_assert(git_index_entrycount(repo_index) == 5); - - for (i = 0; i < git_index_entrycount(repo_index); i++) { - cl_assert(entry = git_index_get_byindex(repo_index, i)); - cl_assert(strcmp(entry->path, "conflicts-one.txt") != 0); - } - - cl_git_pass(git_index_conflict_remove(repo_index, "conflicts-two.txt")); - cl_assert(git_index_entrycount(repo_index) == 2); - - for (i = 0; i < git_index_entrycount(repo_index); i++) { - cl_assert(entry = git_index_get_byindex(repo_index, i)); - cl_assert(strcmp(entry->path, "conflicts-two.txt") != 0); - } -} - -void test_index_conflicts__moved_to_reuc_on_add(void) -{ - const git_index_entry *entry; - size_t i; - - cl_assert(git_index_entrycount(repo_index) == 8); - - cl_git_mkfile("./mergedrepo/conflicts-one.txt", "new-file\n"); - - cl_git_pass(git_index_add_bypath(repo_index, "conflicts-one.txt")); - - cl_assert(git_index_entrycount(repo_index) == 6); - - for (i = 0; i < git_index_entrycount(repo_index); i++) { - cl_assert(entry = git_index_get_byindex(repo_index, i)); - - if (strcmp(entry->path, "conflicts-one.txt") == 0) - cl_assert(git_index_entry_stage(entry) == 0); - } -} - -void test_index_conflicts__moved_to_reuc_on_remove(void) -{ - const git_index_entry *entry; - size_t i; - - cl_assert(git_index_entrycount(repo_index) == 8); - - cl_git_pass(p_unlink("./mergedrepo/conflicts-one.txt")); - - cl_git_pass(git_index_remove_bypath(repo_index, "conflicts-one.txt")); - - cl_assert(git_index_entrycount(repo_index) == 5); - - for (i = 0; i < git_index_entrycount(repo_index); i++) { - cl_assert(entry = git_index_get_byindex(repo_index, i)); - cl_assert(strcmp(entry->path, "conflicts-one.txt") != 0); - } -} - -void test_index_conflicts__remove_all_conflicts(void) -{ - size_t i; - const git_index_entry *entry; - - cl_assert(git_index_entrycount(repo_index) == 8); - - cl_assert_equal_i(true, git_index_has_conflicts(repo_index)); - - git_index_conflict_cleanup(repo_index); - - cl_assert_equal_i(false, git_index_has_conflicts(repo_index)); - - cl_assert(git_index_entrycount(repo_index) == 2); - - for (i = 0; i < git_index_entrycount(repo_index); i++) { - cl_assert(entry = git_index_get_byindex(repo_index, i)); - cl_assert(git_index_entry_stage(entry) == 0); - } -} - -void test_index_conflicts__partial(void) -{ - git_index_entry ancestor_entry, our_entry, their_entry; - const git_index_entry *conflict_entry[3]; - - cl_assert(git_index_entrycount(repo_index) == 8); - - memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); - memset(&our_entry, 0x0, sizeof(git_index_entry)); - memset(&their_entry, 0x0, sizeof(git_index_entry)); - - ancestor_entry.path = "test-one.txt"; - ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); - git_oid_fromstr(&ancestor_entry.oid, TEST_ANCESTOR_OID); - - cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, NULL, NULL)); - cl_assert(git_index_entrycount(repo_index) == 9); - - cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], - &conflict_entry[2], repo_index, "test-one.txt")); - - cl_assert(git_oid_cmp(&ancestor_entry.oid, &conflict_entry[0]->oid) == 0); - cl_assert(conflict_entry[1] == NULL); - cl_assert(conflict_entry[2] == NULL); -} diff --git a/tests-clar/index/filemodes.c b/tests-clar/index/filemodes.c deleted file mode 100644 index 013932696..000000000 --- a/tests-clar/index/filemodes.c +++ /dev/null @@ -1,154 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "posix.h" -#include "index.h" - -static git_repository *g_repo = NULL; - -void test_index_filemodes__initialize(void) -{ - g_repo = cl_git_sandbox_init("filemodes"); -} - -void test_index_filemodes__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_index_filemodes__read(void) -{ - git_index *index; - unsigned int i; - static bool expected[6] = { 0, 1, 0, 1, 0, 1 }; - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_assert_equal_i(6, (int)git_index_entrycount(index)); - - for (i = 0; i < 6; ++i) { - const git_index_entry *entry = git_index_get_byindex(index, i); - cl_assert(entry != NULL); - cl_assert(((entry->mode & 0100) ? 1 : 0) == expected[i]); - } - - git_index_free(index); -} - -static void replace_file_with_mode( - const char *filename, const char *backup, unsigned int create_mode) -{ - git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT; - - cl_git_pass(git_buf_joinpath(&path, "filemodes", filename)); - cl_git_pass(git_buf_printf(&content, "%s as %08u (%d)", - filename, create_mode, rand())); - - cl_git_pass(p_rename(path.ptr, backup)); - cl_git_write2file( - path.ptr, content.ptr, content.size, - O_WRONLY|O_CREAT|O_TRUNC, create_mode); - - git_buf_free(&path); - git_buf_free(&content); -} - -#define add_and_check_mode(I,F,X) add_and_check_mode_(I,F,X,__FILE__,__LINE__) - -static void add_and_check_mode_( - git_index *index, const char *filename, unsigned int expect_mode, - const char *file, int line) -{ - size_t pos; - const git_index_entry *entry; - - cl_git_pass(git_index_add_bypath(index, filename)); - - clar__assert(!git_index_find(&pos, index, filename), - file, line, "Cannot find index entry", NULL, 1); - - entry = git_index_get_byindex(index, pos); - - clar__assert_equal(file, line, "Expected mode does not match index", - 1, "%07o", (unsigned int)entry->mode, (unsigned int)expect_mode); -} - -void test_index_filemodes__untrusted(void) -{ - git_index *index; - - cl_repo_set_bool(g_repo, "core.filemode", false); - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_assert((git_index_caps(index) & GIT_INDEXCAP_NO_FILEMODE) != 0); - - /* 1 - add 0644 over existing 0644 -> expect 0644 */ - replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644); - add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB); - - /* 2 - add 0644 over existing 0755 -> expect 0755 */ - replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644); - add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); - - /* 3 - add 0755 over existing 0644 -> expect 0644 */ - replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755); - add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB); - - /* 4 - add 0755 over existing 0755 -> expect 0755 */ - replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755); - add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); - - /* 5 - add new 0644 -> expect 0644 */ - cl_git_write2file("filemodes/new_off", "blah", 0, - O_WRONLY | O_CREAT | O_TRUNC, 0644); - add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); - - /* 6 - add new 0755 -> expect 0644 if core.filemode == false */ - cl_git_write2file("filemodes/new_on", "blah", 0, - O_WRONLY | O_CREAT | O_TRUNC, 0755); - add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB); - - git_index_free(index); -} - -void test_index_filemodes__trusted(void) -{ - git_index *index; - - /* Only run these tests on platforms where I can actually - * chmod a file and get the stat results I expect! - */ - if (!cl_is_chmod_supported()) - return; - - cl_repo_set_bool(g_repo, "core.filemode", true); - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_assert((git_index_caps(index) & GIT_INDEXCAP_NO_FILEMODE) == 0); - - /* 1 - add 0644 over existing 0644 -> expect 0644 */ - replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644); - add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB); - - /* 2 - add 0644 over existing 0755 -> expect 0644 */ - replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644); - add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB); - - /* 3 - add 0755 over existing 0644 -> expect 0755 */ - replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755); - add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB_EXECUTABLE); - - /* 4 - add 0755 over existing 0755 -> expect 0755 */ - replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755); - add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); - - /* 5 - add new 0644 -> expect 0644 */ - cl_git_write2file("filemodes/new_off", "blah", 0, - O_WRONLY | O_CREAT | O_TRUNC, 0644); - add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); - - /* 6 - add 0755 -> expect 0755 */ - cl_git_write2file("filemodes/new_on", "blah", 0, - O_WRONLY | O_CREAT | O_TRUNC, 0755); - add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE); - - git_index_free(index); -} diff --git a/tests-clar/index/inmemory.c b/tests-clar/index/inmemory.c deleted file mode 100644 index 38e91e0fd..000000000 --- a/tests-clar/index/inmemory.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "clar_libgit2.h" - -void test_index_inmemory__can_create_an_inmemory_index(void) -{ - git_index *index; - - cl_git_pass(git_index_new(&index)); - cl_assert_equal_i(0, (int)git_index_entrycount(index)); - - git_index_free(index); -} - -void test_index_inmemory__cannot_add_bypath_to_an_inmemory_index(void) -{ - git_index *index; - - cl_git_pass(git_index_new(&index)); - - cl_assert_equal_i(GIT_ERROR, git_index_add_bypath(index, "test.txt")); - - git_index_free(index); -} diff --git a/tests-clar/index/names.c b/tests-clar/index/names.c deleted file mode 100644 index 9007b1b15..000000000 --- a/tests-clar/index/names.c +++ /dev/null @@ -1,148 +0,0 @@ -#include "clar_libgit2.h" -#include "index.h" -#include "git2/sys/index.h" -#include "git2/repository.h" -#include "../reset/reset_helpers.h" - -static git_repository *repo; -static git_index *repo_index; - -#define TEST_REPO_PATH "mergedrepo" -#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" - -// Fixture setup and teardown -void test_index_names__initialize(void) -{ - repo = cl_git_sandbox_init("mergedrepo"); - git_repository_index(&repo_index, repo); -} - -void test_index_names__cleanup(void) -{ - git_index_free(repo_index); - repo_index = NULL; - - cl_git_sandbox_cleanup(); -} - -void test_index_names__add(void) -{ - const git_index_name_entry *conflict_name; - - cl_git_pass(git_index_name_add(repo_index, "ancestor", "ours", "theirs")); - cl_git_pass(git_index_name_add(repo_index, "ancestor2", "ours2", NULL)); - cl_git_pass(git_index_name_add(repo_index, "ancestor3", NULL, "theirs3")); - - cl_assert(git_index_name_entrycount(repo_index) == 3); - - conflict_name = git_index_name_get_byindex(repo_index, 0); - cl_assert(strcmp(conflict_name->ancestor, "ancestor") == 0); - cl_assert(strcmp(conflict_name->ours, "ours") == 0); - cl_assert(strcmp(conflict_name->theirs, "theirs") == 0); - - conflict_name = git_index_name_get_byindex(repo_index, 1); - cl_assert(strcmp(conflict_name->ancestor, "ancestor2") == 0); - cl_assert(strcmp(conflict_name->ours, "ours2") == 0); - cl_assert(conflict_name->theirs == NULL); - - conflict_name = git_index_name_get_byindex(repo_index, 2); - cl_assert(strcmp(conflict_name->ancestor, "ancestor3") == 0); - cl_assert(conflict_name->ours == NULL); - cl_assert(strcmp(conflict_name->theirs, "theirs3") == 0); -} - -void test_index_names__roundtrip(void) -{ - const git_index_name_entry *conflict_name; - - cl_git_pass(git_index_name_add(repo_index, "ancestor", "ours", "theirs")); - cl_git_pass(git_index_name_add(repo_index, "ancestor2", "ours2", NULL)); - cl_git_pass(git_index_name_add(repo_index, "ancestor3", NULL, "theirs3")); - - cl_git_pass(git_index_write(repo_index)); - git_index_clear(repo_index); - cl_assert(git_index_name_entrycount(repo_index) == 0); - - cl_git_pass(git_index_read(repo_index, true)); - cl_assert(git_index_name_entrycount(repo_index) == 3); - - conflict_name = git_index_name_get_byindex(repo_index, 0); - cl_assert(strcmp(conflict_name->ancestor, "ancestor") == 0); - cl_assert(strcmp(conflict_name->ours, "ours") == 0); - cl_assert(strcmp(conflict_name->theirs, "theirs") == 0); - - conflict_name = git_index_name_get_byindex(repo_index, 1); - cl_assert(strcmp(conflict_name->ancestor, "ancestor2") == 0); - cl_assert(strcmp(conflict_name->ours, "ours2") == 0); - cl_assert(conflict_name->theirs == NULL); - - conflict_name = git_index_name_get_byindex(repo_index, 2); - cl_assert(strcmp(conflict_name->ancestor, "ancestor3") == 0); - cl_assert(conflict_name->ours == NULL); - cl_assert(strcmp(conflict_name->theirs, "theirs3") == 0); -} - -void test_index_names__cleaned_on_reset_hard(void) -{ - git_object *target; - - retrieve_target_from_oid(&target, repo, "3a34580a35add43a4cf361e8e9a30060a905c876"); - - test_index_names__add(); - cl_git_pass(git_reset(repo, target, GIT_RESET_HARD)); - cl_assert(git_index_name_entrycount(repo_index) == 0); - - git_object_free(target); -} - -void test_index_names__cleaned_on_reset_mixed(void) -{ - git_object *target; - - retrieve_target_from_oid(&target, repo, "3a34580a35add43a4cf361e8e9a30060a905c876"); - - test_index_names__add(); - cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED)); - cl_assert(git_index_name_entrycount(repo_index) == 0); - - git_object_free(target); -} - -void test_index_names__cleaned_on_checkout_tree(void) -{ - git_oid oid; - git_object *obj; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; - - test_index_names__add(); - git_reference_name_to_id(&oid, repo, "refs/heads/master"); - git_object_lookup(&obj, repo, &oid, GIT_OBJ_ANY); - git_checkout_tree(repo, obj, &opts); - cl_assert_equal_sz(0, git_index_name_entrycount(repo_index)); - - git_object_free(obj); -} - -void test_index_names__cleaned_on_checkout_head(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; - - test_index_names__add(); - git_checkout_head(repo, &opts); - cl_assert_equal_sz(0, git_index_name_entrycount(repo_index)); -} - -void test_index_names__retained_on_checkout_index(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; - - test_index_names__add(); - git_checkout_index(repo, repo_index, &opts); - cl_assert(git_index_name_entrycount(repo_index) > 0); -} diff --git a/tests-clar/index/read_tree.c b/tests-clar/index/read_tree.c deleted file mode 100644 index 6c6b40121..000000000 --- a/tests-clar/index/read_tree.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" - -/* Test that reading and writing a tree is a no-op */ -void test_index_read_tree__read_write_involution(void) -{ - git_repository *repo; - git_index *index; - git_oid tree_oid; - git_tree *tree; - git_oid expected; - - p_mkdir("read_tree", 0700); - - cl_git_pass(git_repository_init(&repo, "./read_tree", 0)); - cl_git_pass(git_repository_index(&index, repo)); - - cl_assert(git_index_entrycount(index) == 0); - - p_mkdir("./read_tree/abc", 0700); - - /* Sort order: '-' < '/' < '_' */ - cl_git_mkfile("./read_tree/abc-d", NULL); - cl_git_mkfile("./read_tree/abc/d", NULL); - cl_git_mkfile("./read_tree/abc_d", NULL); - - cl_git_pass(git_index_add_bypath(index, "abc-d")); - cl_git_pass(git_index_add_bypath(index, "abc_d")); - cl_git_pass(git_index_add_bypath(index, "abc/d")); - - /* write-tree */ - cl_git_pass(git_index_write_tree(&expected, index)); - - /* read-tree */ - git_tree_lookup(&tree, repo, &expected); - cl_git_pass(git_index_read_tree(index, tree)); - git_tree_free(tree); - - cl_git_pass(git_index_write_tree(&tree_oid, index)); - cl_assert(git_oid_cmp(&expected, &tree_oid) == 0); - - git_index_free(index); - git_repository_free(repo); - - cl_fixture_cleanup("read_tree"); -} diff --git a/tests-clar/index/rename.c b/tests-clar/index/rename.c deleted file mode 100644 index 4deef1332..000000000 --- a/tests-clar/index/rename.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" - -void test_index_rename__single_file(void) -{ - git_repository *repo; - git_index *index; - size_t position; - git_oid expected; - const git_index_entry *entry; - - p_mkdir("rename", 0700); - - cl_git_pass(git_repository_init(&repo, "./rename", 0)); - cl_git_pass(git_repository_index(&index, repo)); - - cl_assert(git_index_entrycount(index) == 0); - - cl_git_mkfile("./rename/lame.name.txt", "new_file\n"); - - /* This should add a new blob to the object database in 'd4/fa8600b4f37d7516bef4816ae2c64dbf029e3a' */ - cl_git_pass(git_index_add_bypath(index, "lame.name.txt")); - cl_assert(git_index_entrycount(index) == 1); - - cl_git_pass(git_oid_fromstr(&expected, "d4fa8600b4f37d7516bef4816ae2c64dbf029e3a")); - - cl_assert(!git_index_find(&position, index, "lame.name.txt")); - - entry = git_index_get_byindex(index, position); - cl_assert(git_oid_cmp(&expected, &entry->oid) == 0); - - /* This removes the entry from the index, but not from the object database */ - cl_git_pass(git_index_remove(index, "lame.name.txt", 0)); - cl_assert(git_index_entrycount(index) == 0); - - p_rename("./rename/lame.name.txt", "./rename/fancy.name.txt"); - - cl_git_pass(git_index_add_bypath(index, "fancy.name.txt")); - cl_assert(git_index_entrycount(index) == 1); - - cl_assert(!git_index_find(&position, index, "fancy.name.txt")); - - entry = git_index_get_byindex(index, position); - cl_assert(git_oid_cmp(&expected, &entry->oid) == 0); - - git_index_free(index); - git_repository_free(repo); - - cl_fixture_cleanup("rename"); -} diff --git a/tests-clar/index/reuc.c b/tests-clar/index/reuc.c deleted file mode 100644 index a18d5602e..000000000 --- a/tests-clar/index/reuc.c +++ /dev/null @@ -1,372 +0,0 @@ -#include "clar_libgit2.h" -#include "index.h" -#include "git2/sys/index.h" -#include "git2/repository.h" -#include "../reset/reset_helpers.h" - -static git_repository *repo; -static git_index *repo_index; - -#define TEST_REPO_PATH "mergedrepo" -#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" - -#define ONE_ANCESTOR_OID "478871385b9cd03908c5383acfd568bef023c6b3" -#define ONE_OUR_OID "4458b8bc9e72b6c8755ae456f60e9844d0538d8c" -#define ONE_THEIR_OID "8b72416545c7e761b64cecad4f1686eae4078aa8" - -#define TWO_ANCESTOR_OID "9d81f82fccc7dcd7de7a1ffead1815294c2e092c" -#define TWO_OUR_OID "8f3c06cff9a83757cec40c80bc9bf31a2582bde9" -#define TWO_THEIR_OID "887b153b165d32409c70163e0f734c090f12f673" - -// Fixture setup and teardown -void test_index_reuc__initialize(void) -{ - repo = cl_git_sandbox_init("mergedrepo"); - git_repository_index(&repo_index, repo); -} - -void test_index_reuc__cleanup(void) -{ - git_index_free(repo_index); - repo_index = NULL; - - cl_git_sandbox_cleanup(); -} - -void test_index_reuc__add(void) -{ - git_oid ancestor_oid, our_oid, their_oid; - const git_index_reuc_entry *reuc; - - git_oid_fromstr(&ancestor_oid, ONE_ANCESTOR_OID); - git_oid_fromstr(&our_oid, ONE_OUR_OID); - git_oid_fromstr(&their_oid, ONE_THEIR_OID); - - cl_git_pass(git_index_reuc_add(repo_index, "newfile.txt", - 0100644, &ancestor_oid, - 0100644, &our_oid, - 0100644, &their_oid)); - - cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "newfile.txt")); - - cl_assert_equal_s("newfile.txt", reuc->path); - cl_assert(reuc->mode[0] == 0100644); - cl_assert(reuc->mode[1] == 0100644); - cl_assert(reuc->mode[2] == 0100644); - cl_assert(git_oid_cmp(&reuc->oid[0], &ancestor_oid) == 0); - cl_assert(git_oid_cmp(&reuc->oid[1], &our_oid) == 0); - cl_assert(git_oid_cmp(&reuc->oid[2], &their_oid) == 0); -} - -void test_index_reuc__add_no_ancestor(void) -{ - git_oid ancestor_oid, our_oid, their_oid; - const git_index_reuc_entry *reuc; - - memset(&ancestor_oid, 0x0, sizeof(git_oid)); - git_oid_fromstr(&our_oid, ONE_OUR_OID); - git_oid_fromstr(&their_oid, ONE_THEIR_OID); - - cl_git_pass(git_index_reuc_add(repo_index, "newfile.txt", - 0, NULL, - 0100644, &our_oid, - 0100644, &their_oid)); - - cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "newfile.txt")); - - cl_assert_equal_s("newfile.txt", reuc->path); - cl_assert(reuc->mode[0] == 0); - cl_assert(reuc->mode[1] == 0100644); - cl_assert(reuc->mode[2] == 0100644); - cl_assert(git_oid_cmp(&reuc->oid[0], &ancestor_oid) == 0); - cl_assert(git_oid_cmp(&reuc->oid[1], &our_oid) == 0); - cl_assert(git_oid_cmp(&reuc->oid[2], &their_oid) == 0); -} - -void test_index_reuc__read_bypath(void) -{ - const git_index_reuc_entry *reuc; - git_oid oid; - - cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); - - cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "two.txt")); - - cl_assert_equal_s("two.txt", reuc->path); - cl_assert(reuc->mode[0] == 0100644); - cl_assert(reuc->mode[1] == 0100644); - cl_assert(reuc->mode[2] == 0100644); - git_oid_fromstr(&oid, TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); - git_oid_fromstr(&oid, TWO_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); - git_oid_fromstr(&oid, TWO_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); - - cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "one.txt")); - - cl_assert_equal_s("one.txt", reuc->path); - cl_assert(reuc->mode[0] == 0100644); - cl_assert(reuc->mode[1] == 0100644); - cl_assert(reuc->mode[2] == 0100644); - git_oid_fromstr(&oid, ONE_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); - git_oid_fromstr(&oid, ONE_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); - git_oid_fromstr(&oid, ONE_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); -} - -void test_index_reuc__ignore_case(void) -{ - const git_index_reuc_entry *reuc; - git_oid oid; - int index_caps; - - index_caps = git_index_caps(repo_index); - - index_caps &= ~GIT_INDEXCAP_IGNORE_CASE; - cl_git_pass(git_index_set_caps(repo_index, index_caps)); - - cl_assert(!git_index_reuc_get_bypath(repo_index, "TWO.txt")); - - index_caps |= GIT_INDEXCAP_IGNORE_CASE; - cl_git_pass(git_index_set_caps(repo_index, index_caps)); - - cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); - - cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "TWO.txt")); - - cl_assert_equal_s("two.txt", reuc->path); - cl_assert(reuc->mode[0] == 0100644); - cl_assert(reuc->mode[1] == 0100644); - cl_assert(reuc->mode[2] == 0100644); - git_oid_fromstr(&oid, TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); - git_oid_fromstr(&oid, TWO_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); - git_oid_fromstr(&oid, TWO_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); -} - -void test_index_reuc__read_byindex(void) -{ - const git_index_reuc_entry *reuc; - git_oid oid; - - cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); - - cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 0)); - - cl_assert_equal_s("one.txt", reuc->path); - cl_assert(reuc->mode[0] == 0100644); - cl_assert(reuc->mode[1] == 0100644); - cl_assert(reuc->mode[2] == 0100644); - git_oid_fromstr(&oid, ONE_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); - git_oid_fromstr(&oid, ONE_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); - git_oid_fromstr(&oid, ONE_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); - - cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 1)); - - cl_assert_equal_s("two.txt", reuc->path); - cl_assert(reuc->mode[0] == 0100644); - cl_assert(reuc->mode[1] == 0100644); - cl_assert(reuc->mode[2] == 0100644); - git_oid_fromstr(&oid, TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); - git_oid_fromstr(&oid, TWO_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); - git_oid_fromstr(&oid, TWO_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); -} - -void test_index_reuc__updates_existing(void) -{ - const git_index_reuc_entry *reuc; - git_oid ancestor_oid, our_oid, their_oid, oid; - int index_caps; - - git_index_clear(repo_index); - - index_caps = git_index_caps(repo_index); - - index_caps |= GIT_INDEXCAP_IGNORE_CASE; - cl_git_pass(git_index_set_caps(repo_index, index_caps)); - - git_oid_fromstr(&ancestor_oid, TWO_ANCESTOR_OID); - git_oid_fromstr(&our_oid, TWO_OUR_OID); - git_oid_fromstr(&their_oid, TWO_THEIR_OID); - - cl_git_pass(git_index_reuc_add(repo_index, "two.txt", - 0100644, &ancestor_oid, - 0100644, &our_oid, - 0100644, &their_oid)); - - cl_git_pass(git_index_reuc_add(repo_index, "TWO.txt", - 0100644, &our_oid, - 0100644, &their_oid, - 0100644, &ancestor_oid)); - - cl_assert_equal_i(1, git_index_reuc_entrycount(repo_index)); - - cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 0)); - - cl_assert_equal_s("TWO.txt", reuc->path); - git_oid_fromstr(&oid, TWO_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); - git_oid_fromstr(&oid, TWO_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); - git_oid_fromstr(&oid, TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); -} - -void test_index_reuc__remove(void) -{ - git_oid oid; - const git_index_reuc_entry *reuc; - - cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); - - cl_git_pass(git_index_reuc_remove(repo_index, 0)); - cl_git_fail(git_index_reuc_remove(repo_index, 1)); - - cl_assert_equal_i(1, git_index_reuc_entrycount(repo_index)); - - cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 0)); - - cl_assert_equal_s("two.txt", reuc->path); - cl_assert(reuc->mode[0] == 0100644); - cl_assert(reuc->mode[1] == 0100644); - cl_assert(reuc->mode[2] == 0100644); - git_oid_fromstr(&oid, TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); - git_oid_fromstr(&oid, TWO_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); - git_oid_fromstr(&oid, TWO_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); -} - -void test_index_reuc__write(void) -{ - git_oid ancestor_oid, our_oid, their_oid; - const git_index_reuc_entry *reuc; - - git_index_clear(repo_index); - - /* Write out of order to ensure sorting is correct */ - git_oid_fromstr(&ancestor_oid, TWO_ANCESTOR_OID); - git_oid_fromstr(&our_oid, TWO_OUR_OID); - git_oid_fromstr(&their_oid, TWO_THEIR_OID); - - cl_git_pass(git_index_reuc_add(repo_index, "two.txt", - 0100644, &ancestor_oid, - 0100644, &our_oid, - 0100644, &their_oid)); - - git_oid_fromstr(&ancestor_oid, ONE_ANCESTOR_OID); - git_oid_fromstr(&our_oid, ONE_OUR_OID); - git_oid_fromstr(&their_oid, ONE_THEIR_OID); - - cl_git_pass(git_index_reuc_add(repo_index, "one.txt", - 0100644, &ancestor_oid, - 0100644, &our_oid, - 0100644, &their_oid)); - - cl_git_pass(git_index_write(repo_index)); - cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); - - /* ensure sort order was round-tripped correct */ - cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 0)); - cl_assert_equal_s("one.txt", reuc->path); - - cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 1)); - cl_assert_equal_s("two.txt", reuc->path); -} - -static int reuc_entry_exists(void) -{ - return (git_index_reuc_get_bypath(repo_index, "newfile.txt") != NULL); -} - -void test_index_reuc__cleaned_on_reset_hard(void) -{ - git_object *target; - - retrieve_target_from_oid(&target, repo, "3a34580a35add43a4cf361e8e9a30060a905c876"); - - test_index_reuc__add(); - cl_git_pass(git_reset(repo, target, GIT_RESET_HARD)); - cl_assert(reuc_entry_exists() == false); - - git_object_free(target); -} - -void test_index_reuc__cleaned_on_reset_mixed(void) -{ - git_object *target; - - retrieve_target_from_oid(&target, repo, "3a34580a35add43a4cf361e8e9a30060a905c876"); - - test_index_reuc__add(); - cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED)); - cl_assert(reuc_entry_exists() == false); - - git_object_free(target); -} - -void test_index_reuc__retained_on_reset_soft(void) -{ - git_object *target; - - retrieve_target_from_oid(&target, repo, "3a34580a35add43a4cf361e8e9a30060a905c876"); - - git_reset(repo, target, GIT_RESET_HARD); - - test_index_reuc__add(); - cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT)); - cl_assert(reuc_entry_exists() == true); - - git_object_free(target); -} - -void test_index_reuc__cleaned_on_checkout_tree(void) -{ - git_oid oid; - git_object *obj; - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; - - test_index_reuc__add(); - git_reference_name_to_id(&oid, repo, "refs/heads/master"); - git_object_lookup(&obj, repo, &oid, GIT_OBJ_ANY); - git_checkout_tree(repo, obj, &opts); - cl_assert(reuc_entry_exists() == false); - - git_object_free(obj); -} - -void test_index_reuc__cleaned_on_checkout_head(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; - - test_index_reuc__add(); - git_checkout_head(repo, &opts); - cl_assert(reuc_entry_exists() == false); -} - -void test_index_reuc__retained_on_checkout_index(void) -{ - git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; - - opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; - - test_index_reuc__add(); - git_checkout_index(repo, repo_index, &opts); - cl_assert(reuc_entry_exists() == true); -} diff --git a/tests-clar/index/stage.c b/tests-clar/index/stage.c deleted file mode 100644 index 58dc1fb5e..000000000 --- a/tests-clar/index/stage.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "clar_libgit2.h" -#include "index.h" -#include "git2/repository.h" - -static git_repository *repo; -static git_index *repo_index; - -#define TEST_REPO_PATH "mergedrepo" -#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" - -// Fixture setup and teardown -void test_index_stage__initialize(void) -{ - repo = cl_git_sandbox_init("mergedrepo"); - git_repository_index(&repo_index, repo); -} - -void test_index_stage__cleanup(void) -{ - git_index_free(repo_index); - repo_index = NULL; - - cl_git_sandbox_cleanup(); -} - - -void test_index_stage__add_always_adds_stage_0(void) -{ - size_t entry_idx; - const git_index_entry *entry; - - cl_git_mkfile("./mergedrepo/new-file.txt", "new-file\n"); - - cl_git_pass(git_index_add_bypath(repo_index, "new-file.txt")); - - cl_assert(!git_index_find(&entry_idx, repo_index, "new-file.txt")); - cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); - cl_assert(git_index_entry_stage(entry) == 0); -} - -void test_index_stage__find_gets_first_stage(void) -{ - size_t entry_idx; - const git_index_entry *entry; - - cl_assert(!git_index_find(&entry_idx, repo_index, "one.txt")); - cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); - cl_assert(git_index_entry_stage(entry) == 0); - - cl_assert(!git_index_find(&entry_idx, repo_index, "two.txt")); - cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); - cl_assert(git_index_entry_stage(entry) == 0); - - cl_assert(!git_index_find(&entry_idx, repo_index, "conflicts-one.txt")); - cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); - cl_assert(git_index_entry_stage(entry) == 1); - - cl_assert(!git_index_find(&entry_idx, repo_index, "conflicts-two.txt")); - cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); - cl_assert(git_index_entry_stage(entry) == 1); -} - diff --git a/tests-clar/index/tests.c b/tests-clar/index/tests.c deleted file mode 100644 index e5202980c..000000000 --- a/tests-clar/index/tests.c +++ /dev/null @@ -1,537 +0,0 @@ -#include "clar_libgit2.h" -#include "index.h" - -static const size_t index_entry_count = 109; -static const size_t index_entry_count_2 = 1437; -#define TEST_INDEX_PATH cl_fixture("testrepo.git/index") -#define TEST_INDEX2_PATH cl_fixture("gitgit.index") -#define TEST_INDEXBIG_PATH cl_fixture("big.index") - - -/* Suite data */ -struct test_entry { - size_t index; - char path[128]; - git_off_t file_size; - git_time_t mtime; -}; - -static struct test_entry test_entries[] = { - {4, "Makefile", 5064, 0x4C3F7F33}, - {62, "tests/Makefile", 2631, 0x4C3F7F33}, - {36, "src/index.c", 10014, 0x4C43368D}, - {6, "git.git-authors", 2709, 0x4C3F7F33}, - {48, "src/revobject.h", 1448, 0x4C3F7FE2} -}; - -/* Helpers */ -static void copy_file(const char *src, const char *dst) -{ - git_buf source_buf = GIT_BUF_INIT; - git_file dst_fd; - - cl_git_pass(git_futils_readbuffer(&source_buf, src)); - - dst_fd = git_futils_creat_withpath(dst, 0777, 0666); /* -V536 */ - if (dst_fd < 0) - goto cleanup; - - cl_git_pass(p_write(dst_fd, source_buf.ptr, source_buf.size)); - -cleanup: - git_buf_free(&source_buf); - p_close(dst_fd); -} - -static void files_are_equal(const char *a, const char *b) -{ - git_buf buf_a = GIT_BUF_INIT; - git_buf buf_b = GIT_BUF_INIT; - int pass; - - if (git_futils_readbuffer(&buf_a, a) < 0) - cl_assert(0); - - if (git_futils_readbuffer(&buf_b, b) < 0) { - git_buf_free(&buf_a); - cl_assert(0); - } - - pass = (buf_a.size == buf_b.size && !memcmp(buf_a.ptr, buf_b.ptr, buf_a.size)); - - git_buf_free(&buf_a); - git_buf_free(&buf_b); - - cl_assert(pass); -} - - -/* Fixture setup and teardown */ -void test_index_tests__initialize(void) -{ -} - -void test_index_tests__empty_index(void) -{ - git_index *index; - - cl_git_pass(git_index_open(&index, "in-memory-index")); - cl_assert(index->on_disk == 0); - - cl_assert(git_index_entrycount(index) == 0); - cl_assert(index->entries.sorted); - - git_index_free(index); -} - -void test_index_tests__default_test_index(void) -{ - git_index *index; - unsigned int i; - git_index_entry **entries; - - cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); - cl_assert(index->on_disk); - - cl_assert(git_index_entrycount(index) == index_entry_count); - cl_assert(index->entries.sorted); - - entries = (git_index_entry **)index->entries.contents; - - for (i = 0; i < ARRAY_SIZE(test_entries); ++i) { - git_index_entry *e = entries[test_entries[i].index]; - - cl_assert_equal_s(e->path, test_entries[i].path); - cl_assert(e->mtime.seconds == test_entries[i].mtime); - cl_assert(e->file_size == test_entries[i].file_size); - } - - git_index_free(index); -} - -void test_index_tests__gitgit_index(void) -{ - git_index *index; - - cl_git_pass(git_index_open(&index, TEST_INDEX2_PATH)); - cl_assert(index->on_disk); - - cl_assert(git_index_entrycount(index) == index_entry_count_2); - cl_assert(index->entries.sorted); - cl_assert(index->tree != NULL); - - git_index_free(index); -} - -void test_index_tests__find_in_existing(void) -{ - git_index *index; - unsigned int i; - - cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); - - for (i = 0; i < ARRAY_SIZE(test_entries); ++i) { - size_t idx; - - cl_assert(!git_index_find(&idx, index, test_entries[i].path)); - cl_assert(idx == test_entries[i].index); - } - - git_index_free(index); -} - -void test_index_tests__find_in_empty(void) -{ - git_index *index; - unsigned int i; - - cl_git_pass(git_index_open(&index, "fake-index")); - - for (i = 0; i < ARRAY_SIZE(test_entries); ++i) { - cl_assert(GIT_ENOTFOUND == git_index_find(NULL, index, test_entries[i].path)); - } - - git_index_free(index); -} - -void test_index_tests__write(void) -{ - git_index *index; - - copy_file(TEST_INDEXBIG_PATH, "index_rewrite"); - - cl_git_pass(git_index_open(&index, "index_rewrite")); - cl_assert(index->on_disk); - - cl_git_pass(git_index_write(index)); - files_are_equal(TEST_INDEXBIG_PATH, "index_rewrite"); - - git_index_free(index); - - p_unlink("index_rewrite"); -} - -void test_index_tests__sort0(void) -{ - /* sort the entires in an index */ - - /* - * TODO: This no longer applies: - * index sorting in Git uses some specific changes to the way - * directories are sorted. - * - * We need to specificially check for this by creating a new - * index, adding entries in random order and then - * checking for consistency - */ -} - -void test_index_tests__sort1(void) -{ - /* sort the entires in an empty index */ - git_index *index; - - cl_git_pass(git_index_open(&index, "fake-index")); - - /* FIXME: this test is slightly dumb */ - cl_assert(index->entries.sorted); - - git_index_free(index); -} - -static void cleanup_myrepo(void *opaque) -{ - GIT_UNUSED(opaque); - cl_fixture_cleanup("myrepo"); -} - -void test_index_tests__add(void) -{ - git_index *index; - git_filebuf file = GIT_FILEBUF_INIT; - git_repository *repo; - const git_index_entry *entry; - git_oid id1; - - cl_set_cleanup(&cleanup_myrepo, NULL); - - /* Intialize a new repository */ - cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); - - /* Ensure we're the only guy in the room */ - cl_git_pass(git_repository_index(&index, repo)); - cl_assert(git_index_entrycount(index) == 0); - - /* Create a new file in the working directory */ - cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777)); - cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0, 0666)); - cl_git_pass(git_filebuf_write(&file, "hey there\n", 10)); - cl_git_pass(git_filebuf_commit(&file)); - - /* Store the expected hash of the file/blob - * This has been generated by executing the following - * $ echo "hey there" | git hash-object --stdin - */ - cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); - - /* Add the new file to the index */ - cl_git_pass(git_index_add_bypath(index, "test.txt")); - - /* Wow... it worked! */ - cl_assert(git_index_entrycount(index) == 1); - entry = git_index_get_byindex(index, 0); - - /* And the built-in hashing mechanism worked as expected */ - cl_assert(git_oid_cmp(&id1, &entry->oid) == 0); - - /* Test access by path instead of index */ - cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); - cl_assert(git_oid_cmp(&id1, &entry->oid) == 0); - - git_index_free(index); - git_repository_free(repo); -} - -static void cleanup_1397(void *opaque) -{ - GIT_UNUSED(opaque); - cl_git_sandbox_cleanup(); -} - -void test_index_tests__add_issue_1397(void) -{ - git_index *index; - git_repository *repo; - const git_index_entry *entry; - git_oid id1; - - cl_set_cleanup(&cleanup_1397, NULL); - - repo = cl_git_sandbox_init("issue_1397"); - - cl_repo_set_bool(repo, "core.autocrlf", true); - - /* Ensure we're the only guy in the room */ - cl_git_pass(git_repository_index(&index, repo)); - - /* Store the expected hash of the file/blob - * This has been generated by executing the following - * $ git hash-object crlf_file.txt - */ - cl_git_pass(git_oid_fromstr(&id1, "8312e0889a9cbab77c732b6bc39b51a683e3a318")); - - /* Make sure the initial SHA-1 is correct */ - cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL); - cl_assert_(git_oid_cmp(&id1, &entry->oid) == 0, "first oid check"); - - /* Update the index */ - cl_git_pass(git_index_add_bypath(index, "crlf_file.txt")); - - /* Check the new SHA-1 */ - cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL); - cl_assert_(git_oid_cmp(&id1, &entry->oid) == 0, "second oid check"); - - git_index_free(index); -} - -void test_index_tests__add_bypath_to_a_bare_repository_returns_EBAREPO(void) -{ - git_repository *bare_repo; - git_index *index; - - cl_git_pass(git_repository_open(&bare_repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_repository_index(&index, bare_repo)); - - cl_assert_equal_i(GIT_EBAREREPO, git_index_add_bypath(index, "test.txt")); - - git_index_free(index); - git_repository_free(bare_repo); -} - -/* Test that writing an invalid filename fails */ -void test_index_tests__write_invalid_filename(void) -{ - git_repository *repo; - git_index *index; - git_oid expected; - - p_mkdir("read_tree", 0700); - - cl_git_pass(git_repository_init(&repo, "./read_tree", 0)); - cl_git_pass(git_repository_index(&index, repo)); - - cl_assert(git_index_entrycount(index) == 0); - - cl_git_mkfile("./read_tree/.git/hello", NULL); - - cl_git_pass(git_index_add_bypath(index, ".git/hello")); - - /* write-tree */ - cl_git_fail(git_index_write_tree(&expected, index)); - - git_index_free(index); - git_repository_free(repo); - - cl_fixture_cleanup("read_tree"); -} - -void test_index_tests__remove_entry(void) -{ - git_repository *repo; - git_index *index; - - p_mkdir("index_test", 0770); - - cl_git_pass(git_repository_init(&repo, "index_test", 0)); - cl_git_pass(git_repository_index(&index, repo)); - cl_assert(git_index_entrycount(index) == 0); - - cl_git_mkfile("index_test/hello", NULL); - cl_git_pass(git_index_add_bypath(index, "hello")); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_index_read(index, true)); /* reload */ - cl_assert(git_index_entrycount(index) == 1); - cl_assert(git_index_get_bypath(index, "hello", 0) != NULL); - - cl_git_pass(git_index_remove(index, "hello", 0)); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_index_read(index, true)); /* reload */ - cl_assert(git_index_entrycount(index) == 0); - cl_assert(git_index_get_bypath(index, "hello", 0) == NULL); - - git_index_free(index); - git_repository_free(repo); - cl_fixture_cleanup("index_test"); -} - -void test_index_tests__remove_directory(void) -{ - git_repository *repo; - git_index *index; - - p_mkdir("index_test", 0770); - - cl_git_pass(git_repository_init(&repo, "index_test", 0)); - cl_git_pass(git_repository_index(&index, repo)); - cl_assert_equal_i(0, (int)git_index_entrycount(index)); - - p_mkdir("index_test/a", 0770); - cl_git_mkfile("index_test/a/1.txt", NULL); - cl_git_mkfile("index_test/a/2.txt", NULL); - cl_git_mkfile("index_test/a/3.txt", NULL); - cl_git_mkfile("index_test/b.txt", NULL); - - cl_git_pass(git_index_add_bypath(index, "a/1.txt")); - cl_git_pass(git_index_add_bypath(index, "a/2.txt")); - cl_git_pass(git_index_add_bypath(index, "a/3.txt")); - cl_git_pass(git_index_add_bypath(index, "b.txt")); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_index_read(index, true)); /* reload */ - cl_assert_equal_i(4, (int)git_index_entrycount(index)); - cl_assert(git_index_get_bypath(index, "a/1.txt", 0) != NULL); - cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL); - cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL); - - cl_git_pass(git_index_remove(index, "a/1.txt", 0)); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_index_read(index, true)); /* reload */ - cl_assert_equal_i(3, (int)git_index_entrycount(index)); - cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL); - cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL); - cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL); - - cl_git_pass(git_index_remove_directory(index, "a", 0)); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_index_read(index, true)); /* reload */ - cl_assert_equal_i(1, (int)git_index_entrycount(index)); - cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL); - cl_assert(git_index_get_bypath(index, "a/2.txt", 0) == NULL); - cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL); - - git_index_free(index); - git_repository_free(repo); - cl_fixture_cleanup("index_test"); -} - -void test_index_tests__preserves_case(void) -{ - git_repository *repo; - git_index *index; - const git_index_entry *entry; - int index_caps; - - cl_set_cleanup(&cleanup_myrepo, NULL); - - cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); - cl_git_pass(git_repository_index(&index, repo)); - - index_caps = git_index_caps(index); - - cl_git_rewritefile("myrepo/test.txt", "hey there\n"); - cl_git_pass(git_index_add_bypath(index, "test.txt")); - - cl_git_pass(p_rename("myrepo/test.txt", "myrepo/TEST.txt")); - cl_git_rewritefile("myrepo/TEST.txt", "hello again\n"); - cl_git_pass(git_index_add_bypath(index, "TEST.txt")); - - if (index_caps & GIT_INDEXCAP_IGNORE_CASE) - cl_assert_equal_i(1, (int)git_index_entrycount(index)); - else - cl_assert_equal_i(2, (int)git_index_entrycount(index)); - - /* Test access by path instead of index */ - cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); - /* The path should *not* have changed without an explicit remove */ - cl_assert(git__strcmp(entry->path, "test.txt") == 0); - - cl_assert((entry = git_index_get_bypath(index, "TEST.txt", 0)) != NULL); - if (index_caps & GIT_INDEXCAP_IGNORE_CASE) - /* The path should *not* have changed without an explicit remove */ - cl_assert(git__strcmp(entry->path, "test.txt") == 0); - else - cl_assert(git__strcmp(entry->path, "TEST.txt") == 0); - - git_index_free(index); - git_repository_free(repo); -} - -void test_index_tests__elocked(void) -{ - git_repository *repo; - git_index *index; - git_filebuf file = GIT_FILEBUF_INIT; - const git_error *err; - int error; - - cl_set_cleanup(&cleanup_myrepo, NULL); - - cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); - cl_git_pass(git_repository_index(&index, repo)); - - /* Lock the index file so we fail to lock it */ - cl_git_pass(git_filebuf_open(&file, index->index_file_path, 0, 0666)); - error = git_index_write(index); - cl_assert_equal_i(GIT_ELOCKED, error); - - err = giterr_last(); - cl_assert_equal_i(err->klass, GITERR_INDEX); - - git_filebuf_cleanup(&file); - git_index_free(index); - git_repository_free(repo); -} - -void test_index_tests__reload_from_disk(void) -{ - git_repository *repo; - git_index *read_index; - git_index *write_index; - - cl_set_cleanup(&cleanup_myrepo, NULL); - - cl_git_pass(git_futils_mkdir("./myrepo", NULL, 0777, GIT_MKDIR_PATH)); - cl_git_mkfile("./myrepo/a.txt", "a\n"); - cl_git_mkfile("./myrepo/b.txt", "b\n"); - - cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); - cl_git_pass(git_repository_index(&write_index, repo)); - cl_assert_equal_i(false, write_index->on_disk); - - cl_git_pass(git_index_open(&read_index, write_index->index_file_path)); - cl_assert_equal_i(false, read_index->on_disk); - - /* Stage two new files agaisnt the write_index */ - cl_git_pass(git_index_add_bypath(write_index, "a.txt")); - cl_git_pass(git_index_add_bypath(write_index, "b.txt")); - - cl_assert_equal_sz(2, git_index_entrycount(write_index)); - - /* Persist the index changes to disk */ - cl_git_pass(git_index_write(write_index)); - cl_assert_equal_i(true, write_index->on_disk); - - /* Sync the changes back into the read_index */ - cl_assert_equal_sz(0, git_index_entrycount(read_index)); - - cl_git_pass(git_index_read(read_index, true)); - cl_assert_equal_i(true, read_index->on_disk); - - cl_assert_equal_sz(2, git_index_entrycount(read_index)); - - /* Remove the index file from the filesystem */ - cl_git_pass(p_unlink(write_index->index_file_path)); - - /* Sync the changes back into the read_index */ - cl_git_pass(git_index_read(read_index, true)); - cl_assert_equal_i(false, read_index->on_disk); - cl_assert_equal_sz(0, git_index_entrycount(read_index)); - - git_index_free(read_index); - git_index_free(write_index); - git_repository_free(repo); -} diff --git a/tests-clar/main.c b/tests-clar/main.c deleted file mode 100644 index 6b498939d..000000000 --- a/tests-clar/main.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "clar_libgit2.h" - -#ifdef _WIN32 -int __cdecl main(int argc, char *argv[]) -#else -int main(int argc, char *argv[]) -#endif -{ - int res; - - git_threads_init(); - - /* Run the test suite */ - res = clar_test(argc, argv); - - giterr_clear(); - git_threads_shutdown(); - - return res; -} diff --git a/tests-clar/merge/merge_helpers.c b/tests-clar/merge/merge_helpers.c deleted file mode 100644 index 43619be0d..000000000 --- a/tests-clar/merge/merge_helpers.c +++ /dev/null @@ -1,333 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "refs.h" -#include "tree.h" -#include "merge_helpers.h" -#include "merge.h" -#include "git2/merge.h" -#include "git2/sys/index.h" - -int merge_trees_from_branches( - git_index **index, git_repository *repo, - const char *ours_name, const char *theirs_name, - git_merge_tree_opts *opts) -{ - git_commit *our_commit, *their_commit, *ancestor_commit = NULL; - git_tree *our_tree, *their_tree, *ancestor_tree = NULL; - git_oid our_oid, their_oid, ancestor_oid; - git_buf branch_buf = GIT_BUF_INIT; - int error; - - git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours_name); - cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr)); - cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid)); - - git_buf_clear(&branch_buf); - git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs_name); - cl_git_pass(git_reference_name_to_id(&their_oid, repo, branch_buf.ptr)); - cl_git_pass(git_commit_lookup(&their_commit, repo, &their_oid)); - - error = git_merge_base(&ancestor_oid, repo, git_commit_id(our_commit), git_commit_id(their_commit)); - - if (error != GIT_ENOTFOUND) { - cl_git_pass(error); - - cl_git_pass(git_commit_lookup(&ancestor_commit, repo, &ancestor_oid)); - cl_git_pass(git_commit_tree(&ancestor_tree, ancestor_commit)); - } - - cl_git_pass(git_commit_tree(&our_tree, our_commit)); - cl_git_pass(git_commit_tree(&their_tree, their_commit)); - - cl_git_pass(git_merge_trees(index, repo, ancestor_tree, our_tree, their_tree, opts)); - - git_buf_free(&branch_buf); - git_tree_free(our_tree); - git_tree_free(their_tree); - git_tree_free(ancestor_tree); - git_commit_free(our_commit); - git_commit_free(their_commit); - git_commit_free(ancestor_commit); - - return 0; -} - -int merge_branches(git_merge_result **result, git_repository *repo, const char *ours_branch, const char *theirs_branch, git_merge_opts *opts) -{ - git_reference *head_ref, *theirs_ref; - git_merge_head *theirs_head; - git_checkout_opts head_checkout_opts = GIT_CHECKOUT_OPTS_INIT; - - head_checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - cl_git_pass(git_reference_symbolic_create(&head_ref, repo, "HEAD", ours_branch, 1)); - cl_git_pass(git_checkout_head(repo, &head_checkout_opts)); - - cl_git_pass(git_reference_lookup(&theirs_ref, repo, theirs_branch)); - cl_git_pass(git_merge_head_from_ref(&theirs_head, repo, theirs_ref)); - - cl_git_pass(git_merge(result, repo, (const git_merge_head **)&theirs_head, 1, opts)); - - git_reference_free(head_ref); - git_reference_free(theirs_ref); - git_merge_head_free(theirs_head); - - return 0; -} - -void merge__dump_index_entries(git_vector *index_entries) -{ - size_t i; - const git_index_entry *index_entry; - - printf ("\nINDEX [%d]:\n", (int)index_entries->length); - for (i = 0; i < index_entries->length; i++) { - index_entry = index_entries->contents[i]; - - printf("%o ", index_entry->mode); - printf("%s ", git_oid_allocfmt(&index_entry->oid)); - printf("%d ", git_index_entry_stage(index_entry)); - printf("%s ", index_entry->path); - printf("\n"); - } - printf("\n"); -} - -void merge__dump_names(git_index *index) -{ - size_t i; - const git_index_name_entry *conflict_name; - - for (i = 0; i < git_index_name_entrycount(index); i++) { - conflict_name = git_index_name_get_byindex(index, i); - - printf("%s %s %s\n", conflict_name->ancestor, conflict_name->ours, conflict_name->theirs); - } - printf("\n"); -} - -void merge__dump_reuc(git_index *index) -{ - size_t i; - const git_index_reuc_entry *reuc; - - printf ("\nREUC:\n"); - for (i = 0; i < git_index_reuc_entrycount(index); i++) { - reuc = git_index_reuc_get_byindex(index, i); - - printf("%s ", reuc->path); - printf("%o ", reuc->mode[0]); - printf("%s\n", git_oid_allocfmt(&reuc->oid[0])); - printf(" %o ", reuc->mode[1]); - printf(" %s\n", git_oid_allocfmt(&reuc->oid[1])); - printf(" %o ", reuc->mode[2]); - printf(" %s ", git_oid_allocfmt(&reuc->oid[2])); - printf("\n"); - } - printf("\n"); -} - -static int index_entry_eq_merge_index_entry(const struct merge_index_entry *expected, const git_index_entry *actual) -{ - git_oid expected_oid; - bool test_oid; - - if (strlen(expected->oid_str) != 0) { - cl_git_pass(git_oid_fromstr(&expected_oid, expected->oid_str)); - test_oid = 1; - } else - test_oid = 0; - - if (actual->mode != expected->mode || - (test_oid && git_oid_cmp(&actual->oid, &expected_oid) != 0) || - git_index_entry_stage(actual) != expected->stage) - return 0; - - if (actual->mode == 0 && (actual->path != NULL || strlen(expected->path) > 0)) - return 0; - - if (actual->mode != 0 && (strcmp(actual->path, expected->path) != 0)) - return 0; - - return 1; -} - -static int name_entry_eq(const char *expected, const char *actual) -{ - if (strlen(expected) == 0) - return (actual == NULL) ? 1 : 0; - - return (strcmp(expected, actual) == 0) ? 1 : 0; -} - -static int name_entry_eq_merge_name_entry(const struct merge_name_entry *expected, const git_index_name_entry *actual) -{ - if (name_entry_eq(expected->ancestor_path, actual->ancestor) == 0 || - name_entry_eq(expected->our_path, actual->ours) == 0 || - name_entry_eq(expected->their_path, actual->theirs) == 0) - return 0; - - return 1; -} - -static int index_conflict_data_eq_merge_diff(const struct merge_index_conflict_data *expected, git_merge_diff *actual) -{ - if (!index_entry_eq_merge_index_entry(&expected->ancestor.entry, &actual->ancestor_entry) || - !index_entry_eq_merge_index_entry(&expected->ours.entry, &actual->our_entry) || - !index_entry_eq_merge_index_entry(&expected->theirs.entry, &actual->their_entry)) - return 0; - - if (expected->ours.status != actual->our_status || - expected->theirs.status != actual->their_status) - return 0; - - return 1; -} - -int merge_test_merge_conflicts(git_vector *conflicts, const struct merge_index_conflict_data expected[], size_t expected_len) -{ - git_merge_diff *actual; - size_t i; - - if (conflicts->length != expected_len) - return 0; - - for (i = 0; i < expected_len; i++) { - actual = conflicts->contents[i]; - - if (!index_conflict_data_eq_merge_diff(&expected[i], actual)) - return 0; - } - - return 1; -} - -int merge_test_index(git_index *index, const struct merge_index_entry expected[], size_t expected_len) -{ - size_t i; - const git_index_entry *index_entry; - - /* - dump_index_entries(&index->entries); - */ - - if (git_index_entrycount(index) != expected_len) - return 0; - - for (i = 0; i < expected_len; i++) { - if ((index_entry = git_index_get_byindex(index, i)) == NULL) - return 0; - - if (!index_entry_eq_merge_index_entry(&expected[i], index_entry)) - return 0; - } - - return 1; -} - -int merge_test_names(git_index *index, const struct merge_name_entry expected[], size_t expected_len) -{ - size_t i; - const git_index_name_entry *name_entry; - - /* - dump_names(index); - */ - - if (git_index_name_entrycount(index) != expected_len) - return 0; - - for (i = 0; i < expected_len; i++) { - if ((name_entry = git_index_name_get_byindex(index, i)) == NULL) - return 0; - - if (! name_entry_eq_merge_name_entry(&expected[i], name_entry)) - return 0; - } - - return 1; -} - -int merge_test_reuc(git_index *index, const struct merge_reuc_entry expected[], size_t expected_len) -{ - size_t i; - const git_index_reuc_entry *reuc_entry; - git_oid expected_oid; - - /* - dump_reuc(index); - */ - - if (git_index_reuc_entrycount(index) != expected_len) - return 0; - - for (i = 0; i < expected_len; i++) { - if ((reuc_entry = git_index_reuc_get_byindex(index, i)) == NULL) - return 0; - - if (strcmp(reuc_entry->path, expected[i].path) != 0 || - reuc_entry->mode[0] != expected[i].ancestor_mode || - reuc_entry->mode[1] != expected[i].our_mode || - reuc_entry->mode[2] != expected[i].their_mode) - return 0; - - if (expected[i].ancestor_mode > 0) { - cl_git_pass(git_oid_fromstr(&expected_oid, expected[i].ancestor_oid_str)); - - if (git_oid_cmp(&reuc_entry->oid[0], &expected_oid) != 0) - return 0; - } - - if (expected[i].our_mode > 0) { - cl_git_pass(git_oid_fromstr(&expected_oid, expected[i].our_oid_str)); - - if (git_oid_cmp(&reuc_entry->oid[1], &expected_oid) != 0) - return 0; - } - - if (expected[i].their_mode > 0) { - cl_git_pass(git_oid_fromstr(&expected_oid, expected[i].their_oid_str)); - - if (git_oid_cmp(&reuc_entry->oid[2], &expected_oid) != 0) - return 0; - } - } - - return 1; -} - -int dircount(void *payload, git_buf *pathbuf) -{ - int *entries = payload; - size_t len = git_buf_len(pathbuf); - - if (len < 5 || strcmp(pathbuf->ptr + (git_buf_len(pathbuf) - 5), "/.git") != 0) - (*entries)++; - - return 0; -} - -int merge_test_workdir(git_repository *repo, const struct merge_index_entry expected[], size_t expected_len) -{ - size_t actual_len = 0, i; - git_oid actual_oid, expected_oid; - git_buf wd = GIT_BUF_INIT; - - git_buf_puts(&wd, repo->workdir); - git_path_direach(&wd, 0, dircount, &actual_len); - - if (actual_len != expected_len) - return 0; - - for (i = 0; i < expected_len; i++) { - git_blob_create_fromworkdir(&actual_oid, repo, expected[i].path); - git_oid_fromstr(&expected_oid, expected[i].oid_str); - - if (git_oid_cmp(&actual_oid, &expected_oid) != 0) - return 0; - } - - git_buf_free(&wd); - - return 1; -} diff --git a/tests-clar/merge/merge_helpers.h b/tests-clar/merge/merge_helpers.h deleted file mode 100644 index ae3274437..000000000 --- a/tests-clar/merge/merge_helpers.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef INCLUDE_cl_merge_helpers_h__ -#define INCLUDE_cl_merge_helpers_h__ - -#include "merge.h" -#include "git2/merge.h" - -struct merge_index_entry { - uint16_t mode; - char oid_str[41]; - int stage; - char path[128]; -}; - -struct merge_name_entry { - char ancestor_path[128]; - char our_path[128]; - char their_path[128]; -}; - -struct merge_index_with_status { - struct merge_index_entry entry; - unsigned int status; -}; - -struct merge_reuc_entry { - char path[128]; - unsigned int ancestor_mode; - unsigned int our_mode; - unsigned int their_mode; - char ancestor_oid_str[41]; - char our_oid_str[41]; - char their_oid_str[41]; -}; - -struct merge_index_conflict_data { - struct merge_index_with_status ancestor; - struct merge_index_with_status ours; - struct merge_index_with_status theirs; - git_merge_diff_type_t change_type; -}; - -int merge_trees_from_branches( - git_index **index, git_repository *repo, - const char *ours_name, const char *theirs_name, - git_merge_tree_opts *opts); - -int merge_branches(git_merge_result **result, git_repository *repo, - const char *ours_branch, const char *theirs_branch, git_merge_opts *opts); - -int merge_test_diff_list(git_merge_diff_list *diff_list, const struct merge_index_entry expected[], size_t expected_len); - -int merge_test_merge_conflicts(git_vector *conflicts, const struct merge_index_conflict_data expected[], size_t expected_len); - -int merge_test_index(git_index *index, const struct merge_index_entry expected[], size_t expected_len); - -int merge_test_names(git_index *index, const struct merge_name_entry expected[], size_t expected_len); - -int merge_test_reuc(git_index *index, const struct merge_reuc_entry expected[], size_t expected_len); - -int merge_test_workdir(git_repository *repo, const struct merge_index_entry expected[], size_t expected_len); - -#endif diff --git a/tests-clar/merge/trees/automerge.c b/tests-clar/merge/trees/automerge.c deleted file mode 100644 index 746ce5068..000000000 --- a/tests-clar/merge/trees/automerge.c +++ /dev/null @@ -1,217 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/repository.h" -#include "git2/merge.h" -#include "buffer.h" -#include "merge.h" -#include "../merge_helpers.h" -#include "fileops.h" - -static git_repository *repo; - -#define TEST_REPO_PATH "merge-resolve" -#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" - -#define THEIRS_AUTOMERGE_BRANCH "branch" - -#define THEIRS_UNRELATED_BRANCH "unrelated" -#define THEIRS_UNRELATED_OID "55b4e4687e7a0d9ca367016ed930f385d4022e6f" -#define THEIRS_UNRELATED_PARENT "d6cf6c7741b3316826af1314042550c97ded1d50" - -#define OURS_DIRECTORY_FILE "df_side1" -#define THEIRS_DIRECTORY_FILE "df_side2" - -/* Non-conflicting files, index entries are common to every merge operation */ -#define ADDED_IN_MASTER_INDEX_ENTRY \ - { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" } -#define AUTOMERGEABLE_INDEX_ENTRY \ - { 0100644, "f2e1550a0c9e53d5811175864a29536642ae3821", 0, "automergeable.txt" } -#define CHANGED_IN_BRANCH_INDEX_ENTRY \ - { 0100644, "4eb04c9e79e88f6640d01ff5b25ca2a60764f216", 0, "changed-in-branch.txt" } -#define CHANGED_IN_MASTER_INDEX_ENTRY \ - { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" } -#define UNCHANGED_INDEX_ENTRY \ - { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" } - -/* Expected REUC entries */ -#define AUTOMERGEABLE_REUC_ENTRY \ - { "automergeable.txt", 0100644, 0100644, 0100644, \ - "6212c31dab5e482247d7977e4f0dd3601decf13b", \ - "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", \ - "058541fc37114bfc1dddf6bd6bffc7fae5c2e6fe" } -#define CONFLICTING_REUC_ENTRY \ - { "conflicting.txt", 0100644, 0100644, 0100644, \ - "d427e0b2e138501a3d15cc376077a3631e15bd46", \ - "4e886e602529caa9ab11d71f86634bd1b6e0de10", \ - "2bd0a343aeef7a2cf0d158478966a6e587ff3863" } -#define REMOVED_IN_BRANCH_REUC_ENTRY \ - { "removed-in-branch.txt", 0100644, 0100644, 0, \ - "dfe3f22baa1f6fce5447901c3086bae368de6bdd", \ - "dfe3f22baa1f6fce5447901c3086bae368de6bdd", \ - "" } -#define REMOVED_IN_MASTER_REUC_ENTRY \ - { "removed-in-master.txt", 0100644, 0, 0100644, \ - "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", \ - "", \ - "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5" } - -#define AUTOMERGEABLE_MERGED_FILE \ - "this file is changed in master\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is changed in branch\n" - -#define AUTOMERGEABLE_MERGED_FILE_CRLF \ - "this file is changed in master\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is changed in branch\r\n" - -// Fixture setup and teardown -void test_merge_trees_automerge__initialize(void) -{ - repo = cl_git_sandbox_init(TEST_REPO_PATH); -} - -void test_merge_trees_automerge__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_merge_trees_automerge__automerge(void) -{ - git_index *index; - const git_index_entry *entry; - git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; - git_blob *blob; - - struct merge_index_entry merge_index_entries[] = { - ADDED_IN_MASTER_INDEX_ENTRY, - AUTOMERGEABLE_INDEX_ENTRY, - CHANGED_IN_BRANCH_INDEX_ENTRY, - CHANGED_IN_MASTER_INDEX_ENTRY, - - { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, - { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, - { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, - - UNCHANGED_INDEX_ENTRY, - }; - - struct merge_reuc_entry merge_reuc_entries[] = { - AUTOMERGEABLE_REUC_ENTRY, - REMOVED_IN_BRANCH_REUC_ENTRY, - REMOVED_IN_MASTER_REUC_ENTRY - }; - - cl_git_pass(merge_trees_from_branches(&index, repo, "master", THEIRS_AUTOMERGE_BRANCH, &opts)); - - cl_assert(merge_test_index(index, merge_index_entries, 8)); - cl_assert(merge_test_reuc(index, merge_reuc_entries, 3)); - - cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL); - cl_assert(entry->file_size == strlen(AUTOMERGEABLE_MERGED_FILE)); - - cl_git_pass(git_object_lookup((git_object **)&blob, repo, &entry->oid, GIT_OBJ_BLOB)); - cl_assert(memcmp(git_blob_rawcontent(blob), AUTOMERGEABLE_MERGED_FILE, (size_t)entry->file_size) == 0); - - git_index_free(index); - git_blob_free(blob); -} - -void test_merge_trees_automerge__favor_ours(void) -{ - git_index *index; - git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; - - struct merge_index_entry merge_index_entries[] = { - ADDED_IN_MASTER_INDEX_ENTRY, - AUTOMERGEABLE_INDEX_ENTRY, - CHANGED_IN_BRANCH_INDEX_ENTRY, - CHANGED_IN_MASTER_INDEX_ENTRY, - { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, - UNCHANGED_INDEX_ENTRY, - }; - - struct merge_reuc_entry merge_reuc_entries[] = { - AUTOMERGEABLE_REUC_ENTRY, - CONFLICTING_REUC_ENTRY, - REMOVED_IN_BRANCH_REUC_ENTRY, - REMOVED_IN_MASTER_REUC_ENTRY, - }; - - opts.automerge_flags = GIT_MERGE_AUTOMERGE_FAVOR_OURS; - - cl_git_pass(merge_trees_from_branches(&index, repo, "master", THEIRS_AUTOMERGE_BRANCH, &opts)); - - cl_assert(merge_test_index(index, merge_index_entries, 6)); - cl_assert(merge_test_reuc(index, merge_reuc_entries, 4)); - - git_index_free(index); -} - -void test_merge_trees_automerge__favor_theirs(void) -{ - git_index *index; - git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; - - struct merge_index_entry merge_index_entries[] = { - ADDED_IN_MASTER_INDEX_ENTRY, - AUTOMERGEABLE_INDEX_ENTRY, - CHANGED_IN_BRANCH_INDEX_ENTRY, - CHANGED_IN_MASTER_INDEX_ENTRY, - { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 0, "conflicting.txt" }, - UNCHANGED_INDEX_ENTRY, - }; - - struct merge_reuc_entry merge_reuc_entries[] = { - AUTOMERGEABLE_REUC_ENTRY, - CONFLICTING_REUC_ENTRY, - REMOVED_IN_BRANCH_REUC_ENTRY, - REMOVED_IN_MASTER_REUC_ENTRY, - }; - - opts.automerge_flags = GIT_MERGE_AUTOMERGE_FAVOR_THEIRS; - - cl_git_pass(merge_trees_from_branches(&index, repo, "master", THEIRS_AUTOMERGE_BRANCH, &opts)); - - cl_assert(merge_test_index(index, merge_index_entries, 6)); - cl_assert(merge_test_reuc(index, merge_reuc_entries, 4)); - - git_index_free(index); -} - -void test_merge_trees_automerge__unrelated(void) -{ - git_index *index; - git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; - - struct merge_index_entry merge_index_entries[] = { - { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, - { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 2, "automergeable.txt" }, - { 0100644, "d07ec190c306ec690bac349e87d01c4358e49bb2", 3, "automergeable.txt" }, - { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, - { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, - { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, - { 0100644, "4b253da36a0ae8bfce63aeabd8c5b58429925594", 3, "conflicting.txt" }, - { 0100644, "ef58fdd8086c243bdc81f99e379acacfd21d32d6", 0, "new-in-unrelated1.txt" }, - { 0100644, "948ba6e701c1edab0c2d394fb7c5538334129793", 0, "new-in-unrelated2.txt" }, - { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, - { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, - }; - - cl_git_pass(merge_trees_from_branches(&index, repo, "master", THEIRS_UNRELATED_BRANCH, &opts)); - - cl_assert(merge_test_index(index, merge_index_entries, 11)); - - git_index_free(index); -} diff --git a/tests-clar/merge/trees/modeconflict.c b/tests-clar/merge/trees/modeconflict.c deleted file mode 100644 index d858b8f66..000000000 --- a/tests-clar/merge/trees/modeconflict.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/repository.h" -#include "git2/merge.h" -#include "buffer.h" -#include "merge.h" -#include "../merge_helpers.h" -#include "fileops.h" - -static git_repository *repo; - -#define TEST_REPO_PATH "merge-resolve" - -#define DF_SIDE1_BRANCH "df_side1" -#define DF_SIDE2_BRANCH "df_side2" - -// Fixture setup and teardown -void test_merge_trees_modeconflict__initialize(void) -{ - repo = cl_git_sandbox_init(TEST_REPO_PATH); -} - -void test_merge_trees_modeconflict__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_merge_trees_modeconflict__df_conflict(void) -{ - git_index *index; - - struct merge_index_entry merge_index_entries[] = { - { 0100644, "49130a28ef567af9a6a6104c38773fedfa5f9742", 2, "dir-10" }, - { 0100644, "6c06dcd163587c2cc18be44857e0b71116382aeb", 3, "dir-10" }, - { 0100644, "43aafd43bea779ec74317dc361f45ae3f532a505", 0, "dir-6" }, - { 0100644, "a031a28ae70e33a641ce4b8a8f6317f1ab79dee4", 3, "dir-7" }, - { 0100644, "5012fd565b1393bdfda1805d4ec38ce6619e1fd1", 1, "dir-7/file.txt" }, - { 0100644, "a5563304ddf6caba25cb50323a2ea6f7dbfcadca", 2, "dir-7/file.txt" }, - { 0100644, "e9ad6ec3e38364a3d07feda7c4197d4d845c53b5", 0, "dir-8" }, - { 0100644, "3ef4d30382ca33fdeba9fda895a99e0891ba37aa", 2, "dir-9" }, - { 0100644, "fc4c636d6515e9e261f9260dbcf3cc6eca97ea08", 1, "dir-9/file.txt" }, - { 0100644, "76ab0e2868197ec158ddd6c78d8a0d2fd73d38f9", 3, "dir-9/file.txt" }, - { 0100644, "5c2411f8075f48a6b2fdb85ebc0d371747c4df15", 0, "file-1/new" }, - { 0100644, "a39a620dae5bc8b4e771cd4d251b7d080401a21e", 1, "file-2" }, - { 0100644, "d963979c237d08b6ba39062ee7bf64c7d34a27f8", 2, "file-2" }, - { 0100644, "5c341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d", 0, "file-2/new" }, - { 0100644, "9efe7723802d4305142eee177e018fee1572c4f4", 0, "file-3/new" }, - { 0100644, "bacac9b3493509aa15e1730e1545fc0919d1dae0", 1, "file-4" }, - { 0100644, "7663fce0130db092936b137cabd693ec234eb060", 3, "file-4" }, - { 0100644, "e49f917b448d1340b31d76e54ba388268fd4c922", 0, "file-4/new" }, - { 0100644, "cab2cf23998b40f1af2d9d9a756dc9e285a8df4b", 2, "file-5/new" }, - { 0100644, "f5504f36e6f4eb797a56fc5bac6c6c7f32969bf2", 3, "file-5/new" }, - }; - - cl_git_pass(merge_trees_from_branches(&index, repo, DF_SIDE1_BRANCH, DF_SIDE2_BRANCH, NULL)); - - cl_assert(merge_test_index(index, merge_index_entries, 20)); - - git_index_free(index); -} diff --git a/tests-clar/merge/trees/renames.c b/tests-clar/merge/trees/renames.c deleted file mode 100644 index 427b6bd8f..000000000 --- a/tests-clar/merge/trees/renames.c +++ /dev/null @@ -1,252 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/repository.h" -#include "git2/merge.h" -#include "buffer.h" -#include "merge.h" -#include "../merge_helpers.h" -#include "fileops.h" - -static git_repository *repo; - -#define TEST_REPO_PATH "merge-resolve" - -#define BRANCH_RENAME_OURS "rename_conflict_ours" -#define BRANCH_RENAME_THEIRS "rename_conflict_theirs" - -// Fixture setup and teardown -void test_merge_trees_renames__initialize(void) -{ - repo = cl_git_sandbox_init(TEST_REPO_PATH); -} - -void test_merge_trees_renames__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_merge_trees_renames__index(void) -{ - git_index *index; - git_merge_tree_opts *opts = NULL; - - struct merge_index_entry merge_index_entries[] = { - { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, - { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, - { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 1, "0b-rewritten-in-ours.txt" }, - { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 2, "0b-rewritten-in-ours.txt" }, - { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 3, "0b-rewritten-in-ours.txt" }, - { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, - { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 1, "0c-rewritten-in-theirs.txt" }, - { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 2, "0c-rewritten-in-theirs.txt" }, - { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 3, "0c-rewritten-in-theirs.txt" }, - { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, - { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, - { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, - { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, - { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, - { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 2, "3a-newname-in-ours-deleted-in-theirs.txt" }, - { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 1, "3a-renamed-in-ours-deleted-in-theirs.txt" }, - { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 3, "3b-newname-in-theirs-deleted-in-ours.txt" }, - { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 1, "3b-renamed-in-theirs-deleted-in-ours.txt" }, - { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 2, "4a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 3, "4a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 1, "4a-renamed-in-ours-added-in-theirs.txt" }, - { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 2, "4b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 3, "4b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 1, "4b-renamed-in-theirs-added-in-ours.txt" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 2, "5a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 3, "5a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 1, "5a-renamed-in-ours-added-in-theirs.txt" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 3, "5a-renamed-in-ours-added-in-theirs.txt" }, - { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 2, "5b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 3, "5b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 1, "5b-renamed-in-theirs-added-in-ours.txt" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 2, "5b-renamed-in-theirs-added-in-ours.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 2, "6-both-renamed-1-to-2-ours.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 3, "6-both-renamed-1-to-2-theirs.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 1, "6-both-renamed-1-to-2.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "7-both-renamed-side-1.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "7-both-renamed-side-1.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "7-both-renamed-side-2.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "7-both-renamed-side-2.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" }, - }; - - struct merge_name_entry merge_name_entries[] = { - { - "3a-renamed-in-ours-deleted-in-theirs.txt", - "3a-newname-in-ours-deleted-in-theirs.txt", - "" - }, - - { - "3b-renamed-in-theirs-deleted-in-ours.txt", - "", - "3b-newname-in-theirs-deleted-in-ours.txt", - }, - - { - "4a-renamed-in-ours-added-in-theirs.txt", - "4a-newname-in-ours-added-in-theirs.txt", - "", - }, - - { - "4b-renamed-in-theirs-added-in-ours.txt", - "", - "4b-newname-in-theirs-added-in-ours.txt", - }, - - { - "5a-renamed-in-ours-added-in-theirs.txt", - "5a-newname-in-ours-added-in-theirs.txt", - "5a-renamed-in-ours-added-in-theirs.txt", - }, - - { - "5b-renamed-in-theirs-added-in-ours.txt", - "5b-renamed-in-theirs-added-in-ours.txt", - "5b-newname-in-theirs-added-in-ours.txt", - }, - - { - "6-both-renamed-1-to-2.txt", - "6-both-renamed-1-to-2-ours.txt", - "6-both-renamed-1-to-2-theirs.txt", - }, - - { - "7-both-renamed-side-1.txt", - "7-both-renamed.txt", - "7-both-renamed-side-1.txt", - }, - - { - "7-both-renamed-side-2.txt", - "7-both-renamed-side-2.txt", - "7-both-renamed.txt", - }, - }; - - struct merge_reuc_entry merge_reuc_entries[] = { - { "1a-newname-in-ours-edited-in-theirs.txt", - 0, 0100644, 0, - "", - "c3d02eeef75183df7584d8d13ac03053910c1301", - "" }, - - { "1a-newname-in-ours.txt", - 0, 0100644, 0, - "", - "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", - "" }, - - { "1a-renamed-in-ours-edited-in-theirs.txt", - 0100644, 0, 0100644, - "c3d02eeef75183df7584d8d13ac03053910c1301", - "", - "0d872f8e871a30208305978ecbf9e66d864f1638" }, - - { "1a-renamed-in-ours.txt", - 0100644, 0, 0100644, - "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", - "", - "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb" }, - - { "1b-newname-in-theirs-edited-in-ours.txt", - 0, 0, 0100644, - "", - "", - "241a1005cd9b980732741b74385b891142bcba28" }, - - { "1b-newname-in-theirs.txt", - 0, 0, 0100644, - "", - "", - "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136" }, - - { "1b-renamed-in-theirs-edited-in-ours.txt", - 0100644, 0100644, 0, - "241a1005cd9b980732741b74385b891142bcba28", - "ed9523e62e453e50dd9be1606af19399b96e397a", - "" }, - - { "1b-renamed-in-theirs.txt", - 0100644, 0100644, 0, - "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", - "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", - "" }, - - { "2-newname-in-both.txt", - 0, 0100644, 0100644, - "", - "178940b450f238a56c0d75b7955cb57b38191982", - "178940b450f238a56c0d75b7955cb57b38191982" }, - - { "2-renamed-in-both.txt", - 0100644, 0, 0, - "178940b450f238a56c0d75b7955cb57b38191982", - "", - "" }, - }; - - cl_git_pass(merge_trees_from_branches(&index, repo, - BRANCH_RENAME_OURS, BRANCH_RENAME_THEIRS, - opts)); - - cl_assert(merge_test_index(index, merge_index_entries, 41)); - cl_assert(merge_test_names(index, merge_name_entries, 9)); - cl_assert(merge_test_reuc(index, merge_reuc_entries, 10)); - - git_index_free(index); -} - -void test_merge_trees_renames__no_rename_index(void) -{ - git_index *index; - git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; - - struct merge_index_entry merge_index_entries[] = { - { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, - { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, - { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 1, "0b-rewritten-in-ours.txt" }, - { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 2, "0b-rewritten-in-ours.txt" }, - { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 3, "0b-rewritten-in-ours.txt" }, - { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, - { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 1, "0c-rewritten-in-theirs.txt" }, - { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 2, "0c-rewritten-in-theirs.txt" }, - { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 3, "0c-rewritten-in-theirs.txt" }, - { 0100644, "c3d02eeef75183df7584d8d13ac03053910c1301", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, - { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, - { 0100644, "c3d02eeef75183df7584d8d13ac03053910c1301", 1, "1a-renamed-in-ours-edited-in-theirs.txt" }, - { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 3, "1a-renamed-in-ours-edited-in-theirs.txt" }, - { 0100644, "241a1005cd9b980732741b74385b891142bcba28", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, - { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, - { 0100644, "241a1005cd9b980732741b74385b891142bcba28", 1, "1b-renamed-in-theirs-edited-in-ours.txt" }, - { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 2, "1b-renamed-in-theirs-edited-in-ours.txt" }, - { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, - { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, - { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, - { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 2, "4a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 3, "4a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 2, "4b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 3, "4b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 2, "5a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 3, "5a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 2, "5b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 3, "5b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-ours.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-theirs.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" }, - }; - - cl_git_pass(merge_trees_from_branches(&index, repo, - BRANCH_RENAME_OURS, BRANCH_RENAME_THEIRS, - &opts)); - - cl_assert(merge_test_index(index, merge_index_entries, 32)); - - git_index_free(index); -} diff --git a/tests-clar/merge/trees/treediff.c b/tests-clar/merge/trees/treediff.c deleted file mode 100644 index 357859df3..000000000 --- a/tests-clar/merge/trees/treediff.c +++ /dev/null @@ -1,542 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/tree.h" -#include "merge.h" -#include "../merge_helpers.h" -#include "diff.h" -#include "hashsig.h" - -static git_repository *repo; - -#define TEST_REPO_PATH "merge-resolve" - -#define TREE_OID_ANCESTOR "0d52e3a556e189ba0948ae56780918011c1b167d" -#define TREE_OID_MASTER "1f81433e3161efbf250576c58fede7f6b836f3d3" -#define TREE_OID_BRANCH "eea9286df54245fea72c5b557291470eb825f38f" -#define TREE_OID_RENAMES1 "f5f9dd5886a6ee20272be0aafc790cba43b31931" -#define TREE_OID_RENAMES2 "5fbfbdc04b4eca46f54f4853a3c5a1dce28f5165" - -#define TREE_OID_DF_ANCESTOR "b8a3a806d3950e8c0a03a34f234a92eff0e2c68d" -#define TREE_OID_DF_SIDE1 "ee1d6f164893c1866a323f072eeed36b855656be" -#define TREE_OID_DF_SIDE2 "6178885b38fe96e825ac0f492c0a941f288b37f6" - -#define TREE_OID_RENAME_CONFLICT_ANCESTOR "476dbb3e207313d1d8aaa120c6ad204bf1295e53" -#define TREE_OID_RENAME_CONFLICT_OURS "c4efe31e9decccc8b2b4d3df9aac2cdfe2995618" -#define TREE_OID_RENAME_CONFLICT_THEIRS "9e7f4359c469f309b6057febf4c6e80742cbed5b" - -void test_merge_trees_treediff__initialize(void) -{ - repo = cl_git_sandbox_init(TEST_REPO_PATH); -} - -void test_merge_trees_treediff__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -static void test_find_differences( - const char *ancestor_oidstr, - const char *ours_oidstr, - const char *theirs_oidstr, - struct merge_index_conflict_data *treediff_conflict_data, - size_t treediff_conflict_data_len) -{ - git_merge_diff_list *merge_diff_list = git_merge_diff_list__alloc(repo); - git_oid ancestor_oid, ours_oid, theirs_oid; - git_tree *ancestor_tree, *ours_tree, *theirs_tree; - - git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; - opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; - opts.target_limit = 1000; - opts.rename_threshold = 50; - - opts.metric = git__malloc(sizeof(git_diff_similarity_metric)); - cl_assert(opts.metric != NULL); - - opts.metric->file_signature = git_diff_find_similar__hashsig_for_file; - opts.metric->buffer_signature = git_diff_find_similar__hashsig_for_buf; - opts.metric->free_signature = git_diff_find_similar__hashsig_free; - opts.metric->similarity = git_diff_find_similar__calc_similarity; - opts.metric->payload = (void *)GIT_HASHSIG_SMART_WHITESPACE; - - cl_git_pass(git_oid_fromstr(&ancestor_oid, ancestor_oidstr)); - cl_git_pass(git_oid_fromstr(&ours_oid, ours_oidstr)); - cl_git_pass(git_oid_fromstr(&theirs_oid, theirs_oidstr)); - - cl_git_pass(git_tree_lookup(&ancestor_tree, repo, &ancestor_oid)); - cl_git_pass(git_tree_lookup(&ours_tree, repo, &ours_oid)); - cl_git_pass(git_tree_lookup(&theirs_tree, repo, &theirs_oid)); - - cl_git_pass(git_merge_diff_list__find_differences(merge_diff_list, ancestor_tree, ours_tree, theirs_tree)); - cl_git_pass(git_merge_diff_list__find_renames(repo, merge_diff_list, &opts)); - - /* - dump_merge_index(merge_index); - */ - - cl_assert(treediff_conflict_data_len == merge_diff_list->conflicts.length); - - cl_assert(merge_test_merge_conflicts(&merge_diff_list->conflicts, treediff_conflict_data, treediff_conflict_data_len)); - - git_tree_free(ancestor_tree); - git_tree_free(ours_tree); - git_tree_free(theirs_tree); - - git_merge_diff_list__free(merge_diff_list); - - git__free(opts.metric); -} - -void test_merge_trees_treediff__simple(void) -{ - struct merge_index_conflict_data treediff_conflict_data[] = { - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, GIT_DELTA_ADDED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE - }, - - { - { { 0100644, "6212c31dab5e482247d7977e4f0dd3601decf13b", 0, "automergeable.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" }, GIT_DELTA_MODIFIED }, - { { 0100644, "058541fc37114bfc1dddf6bd6bffc7fae5c2e6fe", 0, "automergeable.txt" }, GIT_DELTA_MODIFIED }, - GIT_MERGE_DIFF_BOTH_MODIFIED - }, - - { - { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "4eb04c9e79e88f6640d01ff5b25ca2a60764f216", 0, "changed-in-branch.txt" }, GIT_DELTA_MODIFIED }, - GIT_MERGE_DIFF_NONE - }, - - { - { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, GIT_DELTA_MODIFIED }, - { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE - }, - - { - { { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 0, "conflicting.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, GIT_DELTA_MODIFIED }, - { { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 0, "conflicting.txt" }, GIT_DELTA_MODIFIED }, - GIT_MERGE_DIFF_BOTH_MODIFIED - }, - - { - { { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - GIT_MERGE_DIFF_NONE - }, - - { - { { 0100644, "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", 0, "removed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - { { 0100644, "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", 0, "removed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE - }, - }; - - test_find_differences(TREE_OID_ANCESTOR, TREE_OID_MASTER, TREE_OID_BRANCH, treediff_conflict_data, 7); -} - -void test_merge_trees_treediff__df_conflicts(void) -{ - struct merge_index_conflict_data treediff_conflict_data[] = { - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "49130a28ef567af9a6a6104c38773fedfa5f9742", 0, "dir-10" }, GIT_DELTA_ADDED }, - { { 0100644, "6c06dcd163587c2cc18be44857e0b71116382aeb", 0, "dir-10" }, GIT_DELTA_ADDED }, - GIT_MERGE_DIFF_BOTH_ADDED, - }, - - { - { { 0100644, "242591eb280ee9eeb2ce63524b9a8b9bc4cb515d", 0, "dir-10/file.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - GIT_MERGE_DIFF_BOTH_DELETED, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "43aafd43bea779ec74317dc361f45ae3f532a505", 0, "dir-6" }, GIT_DELTA_ADDED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "cf8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d", 0, "dir-6/file.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "cf8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d", 0, "dir-6/file.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "a031a28ae70e33a641ce4b8a8f6317f1ab79dee4", 0, "dir-7" }, GIT_DELTA_ADDED }, - GIT_MERGE_DIFF_DIRECTORY_FILE, - }, - - { - { { 0100644, "5012fd565b1393bdfda1805d4ec38ce6619e1fd1", 0, "dir-7/file.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "a5563304ddf6caba25cb50323a2ea6f7dbfcadca", 0, "dir-7/file.txt" }, GIT_DELTA_MODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - GIT_MERGE_DIFF_DF_CHILD, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "e9ad6ec3e38364a3d07feda7c4197d4d845c53b5", 0, "dir-8" }, GIT_DELTA_ADDED }, - { {0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "f20c9063fa0bda9a397c96947a7b687305c49753", 0, "dir-8/file.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - { { 0100644, "f20c9063fa0bda9a397c96947a7b687305c49753", 0, "dir-8/file.txt" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "3ef4d30382ca33fdeba9fda895a99e0891ba37aa", 0, "dir-9" }, GIT_DELTA_ADDED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_DIRECTORY_FILE, - }, - - { - { { 0100644, "fc4c636d6515e9e261f9260dbcf3cc6eca97ea08", 0, "dir-9/file.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - { { 0100644, "76ab0e2868197ec158ddd6c78d8a0d2fd73d38f9", 0, "dir-9/file.txt" }, GIT_DELTA_MODIFIED }, - GIT_MERGE_DIFF_DF_CHILD, - }, - - { - { { 0100644, "1e4ff029aee68d0d69ef9eb6efa6cbf1ec732f99", 0, "file-1" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "1e4ff029aee68d0d69ef9eb6efa6cbf1ec732f99", 0, "file-1" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "5c2411f8075f48a6b2fdb85ebc0d371747c4df15", 0, "file-1/new" }, GIT_DELTA_ADDED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "a39a620dae5bc8b4e771cd4d251b7d080401a21e", 0, "file-2" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "d963979c237d08b6ba39062ee7bf64c7d34a27f8", 0, "file-2" }, GIT_DELTA_MODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - GIT_MERGE_DIFF_DIRECTORY_FILE, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "5c341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d", 0, "file-2/new" }, GIT_DELTA_ADDED }, - GIT_MERGE_DIFF_DF_CHILD, - }, - - { - { { 0100644, "032ebc5ab85d9553bb187d3cd40875ff23a63ed0", 0, "file-3" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - { { 0100644, "032ebc5ab85d9553bb187d3cd40875ff23a63ed0", 0, "file-3" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "9efe7723802d4305142eee177e018fee1572c4f4", 0, "file-3/new" }, GIT_DELTA_ADDED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "bacac9b3493509aa15e1730e1545fc0919d1dae0", 0, "file-4" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - { { 0100644, "7663fce0130db092936b137cabd693ec234eb060", 0, "file-4" }, GIT_DELTA_MODIFIED }, - GIT_MERGE_DIFF_DIRECTORY_FILE, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "e49f917b448d1340b31d76e54ba388268fd4c922", 0, "file-4/new" }, GIT_DELTA_ADDED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_DF_CHILD, - }, - - { - { { 0100644, "ac4045f965119e6998f4340ed0f411decfb3ec05", 0, "file-5" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - GIT_MERGE_DIFF_BOTH_DELETED, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "cab2cf23998b40f1af2d9d9a756dc9e285a8df4b", 0, "file-5/new" }, GIT_DELTA_ADDED }, - { { 0100644, "f5504f36e6f4eb797a56fc5bac6c6c7f32969bf2", 0, "file-5/new" }, GIT_DELTA_ADDED }, - GIT_MERGE_DIFF_BOTH_ADDED, - }, - }; - - test_find_differences(TREE_OID_DF_ANCESTOR, TREE_OID_DF_SIDE1, TREE_OID_DF_SIDE2, treediff_conflict_data, 20); -} - -void test_merge_trees_treediff__strict_renames(void) -{ - struct merge_index_conflict_data treediff_conflict_data[] = { - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, GIT_DELTA_ADDED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "6212c31dab5e482247d7977e4f0dd3601decf13b", 0, "automergeable.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" }, GIT_DELTA_MODIFIED }, - { { 0100644, "6212c31dab5e482247d7977e4f0dd3601decf13b", 0, "automergeable.txt" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, GIT_DELTA_MODIFIED }, - { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 0, "conflicting.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, GIT_DELTA_MODIFIED }, - { { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 0, "conflicting.txt" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "renamed-in-branch.txt" }, GIT_DELTA_RENAMED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", 0, "removed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - { { 0100644, "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", 0, "removed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "renamed.txt" }, GIT_DELTA_ADDED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "copied.txt" }, GIT_DELTA_RENAMED }, - GIT_MERGE_DIFF_NONE, - }, - }; - - test_find_differences(TREE_OID_ANCESTOR, TREE_OID_MASTER, TREE_OID_RENAMES1, treediff_conflict_data, 8); -} - -void test_merge_trees_treediff__rename_conflicts(void) -{ - struct merge_index_conflict_data treediff_conflict_data[] = { - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, GIT_DELTA_ADDED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-rewritten-in-ours.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 0, "0b-rewritten-in-ours.txt" }, GIT_DELTA_MODIFIED }, - { { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 0, "0b-rewritten-in-ours.txt" }, GIT_DELTA_MODIFIED }, - GIT_MERGE_DIFF_BOTH_MODIFIED, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, GIT_DELTA_ADDED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-rewritten-in-theirs.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 0, "0c-rewritten-in-theirs.txt" }, GIT_DELTA_MODIFIED }, - { { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 0, "0c-rewritten-in-theirs.txt" }, GIT_DELTA_MODIFIED }, - GIT_MERGE_DIFF_BOTH_MODIFIED, - }, - - { - { { 0100644, "c3d02eeef75183df7584d8d13ac03053910c1301", 0, "1a-renamed-in-ours-edited-in-theirs.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "c3d02eeef75183df7584d8d13ac03053910c1301", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, GIT_DELTA_RENAMED }, - { { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-renamed-in-ours-edited-in-theirs.txt" }, GIT_DELTA_MODIFIED }, - GIT_MERGE_DIFF_RENAMED_MODIFIED, - }, - - { - { { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-renamed-in-ours.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, GIT_DELTA_RENAMED }, - { { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-renamed-in-ours.txt" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "241a1005cd9b980732741b74385b891142bcba28", 0, "1b-renamed-in-theirs-edited-in-ours.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-renamed-in-theirs-edited-in-ours.txt" }, GIT_DELTA_MODIFIED }, - { { 0100644, "241a1005cd9b980732741b74385b891142bcba28", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, GIT_DELTA_RENAMED }, - GIT_MERGE_DIFF_RENAMED_MODIFIED, - }, - - { - { { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-renamed-in-theirs.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-renamed-in-theirs.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, GIT_DELTA_RENAMED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-renamed-in-both.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, GIT_DELTA_RENAMED }, - { { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, GIT_DELTA_RENAMED }, - GIT_MERGE_DIFF_BOTH_RENAMED, - }, - - { - { { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-renamed-in-ours-deleted-in-theirs.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, GIT_DELTA_RENAMED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - GIT_MERGE_DIFF_RENAMED_DELETED, - }, - - { - { { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-renamed-in-theirs-deleted-in-ours.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - { { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, GIT_DELTA_RENAMED }, - GIT_MERGE_DIFF_RENAMED_DELETED, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 0, "4a-newname-in-ours-added-in-theirs.txt" }, GIT_DELTA_ADDED }, - GIT_MERGE_DIFF_RENAMED_ADDED, - }, - - { - { { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-renamed-in-ours-added-in-theirs.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-newname-in-ours-added-in-theirs.txt" }, GIT_DELTA_RENAMED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - GIT_MERGE_DIFF_RENAMED_ADDED, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 0, "4b-newname-in-theirs-added-in-ours.txt" }, GIT_DELTA_ADDED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_RENAMED_ADDED, - }, - - { - { { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 0, "4b-renamed-in-theirs-added-in-ours.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - { { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 0, "4b-newname-in-theirs-added-in-ours.txt" }, GIT_DELTA_RENAMED }, - GIT_MERGE_DIFF_RENAMED_ADDED, - }, - - { - { { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "5-both-renamed-1-to-2.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "5-both-renamed-1-to-2-ours.txt" }, GIT_DELTA_RENAMED }, - { { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "5-both-renamed-1-to-2-theirs.txt" }, GIT_DELTA_RENAMED }, - GIT_MERGE_DIFF_BOTH_RENAMED_1_TO_2, - }, - - { - { { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "6-both-renamed-side-1.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "6-both-renamed.txt" }, GIT_DELTA_RENAMED }, - { { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "6-both-renamed-side-1.txt" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1, - }, - - { - { { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "6-both-renamed-side-2.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "6-both-renamed-side-2.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "6-both-renamed.txt" }, GIT_DELTA_RENAMED }, - GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1, - }, - }; - test_find_differences(TREE_OID_RENAME_CONFLICT_ANCESTOR, - TREE_OID_RENAME_CONFLICT_OURS, TREE_OID_RENAME_CONFLICT_THEIRS, treediff_conflict_data, 18); -} - -void test_merge_trees_treediff__best_renames(void) -{ - struct merge_index_conflict_data treediff_conflict_data[] = { - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, GIT_DELTA_ADDED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "6212c31dab5e482247d7977e4f0dd3601decf13b", 0, "automergeable.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" }, GIT_DELTA_MODIFIED }, - { { 0100644, "45299c1ca5e07bba1fd90843056fb559f96b1f5a", 0, "renamed-90.txt" }, GIT_DELTA_RENAMED }, - GIT_MERGE_DIFF_RENAMED_MODIFIED, - }, - - { - { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, GIT_DELTA_MODIFIED }, - { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 0, "conflicting.txt" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, GIT_DELTA_MODIFIED }, - { { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 0, "conflicting.txt" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0100644, "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", 0, "removed-in-master.txt" },GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_DELETED }, - { { 0100644, "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", 0, "removed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, - GIT_MERGE_DIFF_MODIFIED_DELETED, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "5843febcb23480df0b5edb22a21c59c772bb8e29", 0, "renamed-50.txt" }, GIT_DELTA_ADDED }, - GIT_MERGE_DIFF_NONE, - }, - - { - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, - { { 0100644, "a77a56a49f8f3ae242e02717f18ebbc60c5cc543", 0, "renamed-75.txt" }, GIT_DELTA_ADDED }, - GIT_MERGE_DIFF_NONE, - }, - }; - - test_find_differences(TREE_OID_ANCESTOR, TREE_OID_MASTER, TREE_OID_RENAMES2, treediff_conflict_data, 7); -} diff --git a/tests-clar/merge/trees/trivial.c b/tests-clar/merge/trees/trivial.c deleted file mode 100644 index bfd5dfed3..000000000 --- a/tests-clar/merge/trees/trivial.c +++ /dev/null @@ -1,397 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/repository.h" -#include "git2/merge.h" -#include "merge.h" -#include "../merge_helpers.h" -#include "refs.h" -#include "fileops.h" -#include "git2/sys/index.h" - -static git_repository *repo; - -#define TEST_REPO_PATH "merge-resolve" -#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" - - -// Fixture setup and teardown -void test_merge_trees_trivial__initialize(void) -{ - repo = cl_git_sandbox_init(TEST_REPO_PATH); -} - -void test_merge_trees_trivial__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - - -static int merge_trivial(git_index **index, const char *ours, const char *theirs, bool automerge) -{ - git_commit *our_commit, *their_commit, *ancestor_commit; - git_tree *our_tree, *their_tree, *ancestor_tree; - git_oid our_oid, their_oid, ancestor_oid; - git_buf branch_buf = GIT_BUF_INIT; - git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; - - opts.automerge_flags |= automerge ? 0 : GIT_MERGE_AUTOMERGE_NONE; - - git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours); - cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr)); - cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid)); - - git_buf_clear(&branch_buf); - git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs); - cl_git_pass(git_reference_name_to_id(&their_oid, repo, branch_buf.ptr)); - cl_git_pass(git_commit_lookup(&their_commit, repo, &their_oid)); - - cl_git_pass(git_merge_base(&ancestor_oid, repo, git_commit_id(our_commit), git_commit_id(their_commit))); - cl_git_pass(git_commit_lookup(&ancestor_commit, repo, &ancestor_oid)); - - cl_git_pass(git_commit_tree(&ancestor_tree, ancestor_commit)); - cl_git_pass(git_commit_tree(&our_tree, our_commit)); - cl_git_pass(git_commit_tree(&their_tree, their_commit)); - - cl_git_pass(git_merge_trees(index, repo, ancestor_tree, our_tree, their_tree, &opts)); - - git_buf_free(&branch_buf); - git_tree_free(our_tree); - git_tree_free(their_tree); - git_tree_free(ancestor_tree); - git_commit_free(our_commit); - git_commit_free(their_commit); - git_commit_free(ancestor_commit); - - return 0; -} - -static int merge_trivial_conflict_entrycount(git_index *index) -{ - const git_index_entry *entry; - int count = 0; - size_t i; - - for (i = 0; i < git_index_entrycount(index); i++) { - cl_assert(entry = git_index_get_byindex(index, i)); - - if (git_index_entry_stage(entry) > 0) - count++; - } - - return count; -} - -/* 2ALT: ancest:(empty)+, head:*empty*, remote:remote = result:remote */ -void test_merge_trees_trivial__2alt(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-2alt", "trivial-2alt-branch", 0)); - - cl_assert(entry = git_index_get_bypath(result, "new-in-branch.txt", 0)); - cl_assert(git_index_reuc_entrycount(result) == 0); - cl_assert(merge_trivial_conflict_entrycount(result) == 0); - - git_index_free(result); -} - -/* 3ALT: ancest:(empty)+, head:head, remote:*empty* = result:head */ -void test_merge_trees_trivial__3alt(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-3alt", "trivial-3alt-branch", 0)); - - cl_assert(entry = git_index_get_bypath(result, "new-in-3alt.txt", 0)); - cl_assert(git_index_reuc_entrycount(result) == 0); - cl_assert(merge_trivial_conflict_entrycount(result) == 0); - - git_index_free(result); -} - -/* 4: ancest:(empty)^, head:head, remote:remote = result:no merge */ -void test_merge_trees_trivial__4(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-4", "trivial-4-branch", 0)); - - cl_assert((entry = git_index_get_bypath(result, "new-and-different.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(result) == 0); - - cl_assert(merge_trivial_conflict_entrycount(result) == 2); - cl_assert(entry = git_index_get_bypath(result, "new-and-different.txt", 2)); - cl_assert(entry = git_index_get_bypath(result, "new-and-different.txt", 3)); - - git_index_free(result); -} - -/* 5ALT: ancest:*, head:head, remote:head = result:head */ -void test_merge_trees_trivial__5alt_1(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-5alt-1", "trivial-5alt-1-branch", 0)); - - cl_assert(entry = git_index_get_bypath(result, "new-and-same.txt", 0)); - cl_assert(git_index_reuc_entrycount(result) == 0); - cl_assert(merge_trivial_conflict_entrycount(result) == 0); - - git_index_free(result); -} - -/* 5ALT: ancest:*, head:head, remote:head = result:head */ -void test_merge_trees_trivial__5alt_2(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-5alt-2", "trivial-5alt-2-branch", 0)); - - cl_assert(entry = git_index_get_bypath(result, "modified-to-same.txt", 0)); - cl_assert(git_index_reuc_entrycount(result) == 0); - cl_assert(merge_trivial_conflict_entrycount(result) == 0); - - git_index_free(result); -} - -/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */ -void test_merge_trees_trivial__6(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-6", "trivial-6-branch", 0)); - - cl_assert((entry = git_index_get_bypath(result, "removed-in-both.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(result) == 0); - - cl_assert(merge_trivial_conflict_entrycount(result) == 1); - cl_assert(entry = git_index_get_bypath(result, "removed-in-both.txt", 1)); - - git_index_free(result); -} - -/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */ -void test_merge_trees_trivial__6_automerge(void) -{ - git_index *result; - const git_index_entry *entry; - const git_index_reuc_entry *reuc; - - cl_git_pass(merge_trivial(&result, "trivial-6", "trivial-6-branch", 1)); - - cl_assert((entry = git_index_get_bypath(result, "removed-in-both.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(result) == 1); - cl_assert(reuc = git_index_reuc_get_bypath(result, "removed-in-both.txt")); - - cl_assert(merge_trivial_conflict_entrycount(result) == 0); - - git_index_free(result); -} - -/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */ -void test_merge_trees_trivial__8(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-8", "trivial-8-branch", 0)); - - cl_assert((entry = git_index_get_bypath(result, "removed-in-8.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(result) == 0); - - cl_assert(merge_trivial_conflict_entrycount(result) == 2); - cl_assert(entry = git_index_get_bypath(result, "removed-in-8.txt", 1)); - cl_assert(entry = git_index_get_bypath(result, "removed-in-8.txt", 3)); - - git_index_free(result); -} - -/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */ -void test_merge_trees_trivial__8_automerge(void) -{ - git_index *result; - const git_index_entry *entry; - const git_index_reuc_entry *reuc; - - cl_git_pass(merge_trivial(&result, "trivial-8", "trivial-8-branch", 1)); - - cl_assert((entry = git_index_get_bypath(result, "removed-in-8.txt", 0)) == NULL); - - cl_assert(git_index_reuc_entrycount(result) == 1); - cl_assert(reuc = git_index_reuc_get_bypath(result, "removed-in-8.txt")); - - cl_assert(merge_trivial_conflict_entrycount(result) == 0); - - git_index_free(result); -} - -/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */ -void test_merge_trees_trivial__7(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-7", "trivial-7-branch", 0)); - - cl_assert((entry = git_index_get_bypath(result, "removed-in-7.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(result) == 0); - - cl_assert(merge_trivial_conflict_entrycount(result) == 2); - cl_assert(entry = git_index_get_bypath(result, "removed-in-7.txt", 1)); - cl_assert(entry = git_index_get_bypath(result, "removed-in-7.txt", 3)); - - git_index_free(result); -} - -/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */ -void test_merge_trees_trivial__7_automerge(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-7", "trivial-7-branch", 0)); - - cl_assert((entry = git_index_get_bypath(result, "removed-in-7.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(result) == 0); - - cl_assert(merge_trivial_conflict_entrycount(result) == 2); - cl_assert(entry = git_index_get_bypath(result, "removed-in-7.txt", 1)); - cl_assert(entry = git_index_get_bypath(result, "removed-in-7.txt", 3)); - - git_index_free(result); -} - -/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */ -void test_merge_trees_trivial__10(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-10", "trivial-10-branch", 0)); - - cl_assert((entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(result) == 0); - - cl_assert(merge_trivial_conflict_entrycount(result) == 2); - cl_assert(entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 1)); - cl_assert(entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 2)); - - git_index_free(result); -} - -/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */ -void test_merge_trees_trivial__10_automerge(void) -{ - git_index *result; - const git_index_entry *entry; - const git_index_reuc_entry *reuc; - - cl_git_pass(merge_trivial(&result, "trivial-10", "trivial-10-branch", 1)); - - cl_assert((entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 0)) == NULL); - - cl_assert(git_index_reuc_entrycount(result) == 1); - cl_assert(reuc = git_index_reuc_get_bypath(result, "removed-in-10-branch.txt")); - - cl_assert(merge_trivial_conflict_entrycount(result) == 0); - - git_index_free(result); -} - -/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */ -void test_merge_trees_trivial__9(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-9", "trivial-9-branch", 0)); - - cl_assert((entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(result) == 0); - - cl_assert(merge_trivial_conflict_entrycount(result) == 2); - cl_assert(entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 1)); - cl_assert(entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 2)); - - git_index_free(result); -} - -/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */ -void test_merge_trees_trivial__9_automerge(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-9", "trivial-9-branch", 1)); - - cl_assert((entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(result) == 0); - - cl_assert(merge_trivial_conflict_entrycount(result) == 2); - cl_assert(entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 1)); - cl_assert(entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 2)); - - git_index_free(result); -} - -/* 13: ancest:ancest+, head:head, remote:ancest = result:head */ -void test_merge_trees_trivial__13(void) -{ - git_index *result; - const git_index_entry *entry; - git_oid expected_oid; - - cl_git_pass(merge_trivial(&result, "trivial-13", "trivial-13-branch", 0)); - - cl_assert(entry = git_index_get_bypath(result, "modified-in-13.txt", 0)); - cl_git_pass(git_oid_fromstr(&expected_oid, "1cff9ec6a47a537380dedfdd17c9e76d74259a2b")); - cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0); - - cl_assert(git_index_reuc_entrycount(result) == 0); - cl_assert(merge_trivial_conflict_entrycount(result) == 0); - - git_index_free(result); -} - -/* 14: ancest:ancest+, head:ancest, remote:remote = result:remote */ -void test_merge_trees_trivial__14(void) -{ - git_index *result; - const git_index_entry *entry; - git_oid expected_oid; - - cl_git_pass(merge_trivial(&result, "trivial-14", "trivial-14-branch", 0)); - - cl_assert(entry = git_index_get_bypath(result, "modified-in-14-branch.txt", 0)); - cl_git_pass(git_oid_fromstr(&expected_oid, "26153a3ff3649b6c2bb652d3f06878c6e0a172f9")); - cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0); - - cl_assert(git_index_reuc_entrycount(result) == 0); - cl_assert(merge_trivial_conflict_entrycount(result) == 0); - - git_index_free(result); -} - -/* 11: ancest:ancest+, head:head, remote:remote = result:no merge */ -void test_merge_trees_trivial__11(void) -{ - git_index *result; - const git_index_entry *entry; - - cl_git_pass(merge_trivial(&result, "trivial-11", "trivial-11-branch", 0)); - - cl_assert((entry = git_index_get_bypath(result, "modified-in-both.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(result) == 0); - - cl_assert(merge_trivial_conflict_entrycount(result) == 3); - cl_assert(entry = git_index_get_bypath(result, "modified-in-both.txt", 1)); - cl_assert(entry = git_index_get_bypath(result, "modified-in-both.txt", 2)); - cl_assert(entry = git_index_get_bypath(result, "modified-in-both.txt", 3)); - - git_index_free(result); -} diff --git a/tests-clar/merge/workdir/fastforward.c b/tests-clar/merge/workdir/fastforward.c deleted file mode 100644 index 861f38354..000000000 --- a/tests-clar/merge/workdir/fastforward.c +++ /dev/null @@ -1,148 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/repository.h" -#include "git2/merge.h" -#include "git2/sys/index.h" -#include "merge.h" -#include "../merge_helpers.h" -#include "refs.h" - -static git_repository *repo; -static git_index *repo_index; - -#define TEST_REPO_PATH "merge-resolve" -#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" - -#define THEIRS_FASTFORWARD_BRANCH "ff_branch" -#define THEIRS_FASTFORWARD_OID "fd89f8cffb663ac89095a0f9764902e93ceaca6a" - -#define THEIRS_NOFASTFORWARD_BRANCH "branch" -#define THEIRS_NOFASTFORWARD_OID "7cb63eed597130ba4abb87b3e544b85021905520" - - -// Fixture setup and teardown -void test_merge_workdir_fastforward__initialize(void) -{ - repo = cl_git_sandbox_init(TEST_REPO_PATH); - git_repository_index(&repo_index, repo); -} - -void test_merge_workdir_fastforward__cleanup(void) -{ - git_index_free(repo_index); - cl_git_sandbox_cleanup(); -} - -static git_merge_result *merge_fastforward_branch(int flags) -{ - git_reference *their_ref; - git_merge_head *their_heads[1]; - git_merge_result *result; - git_merge_opts opts = GIT_MERGE_OPTS_INIT; - - opts.merge_flags = flags; - - cl_git_pass(git_reference_lookup(&their_ref, repo, GIT_REFS_HEADS_DIR THEIRS_FASTFORWARD_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref)); - - cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); - - git_merge_head_free(their_heads[0]); - git_reference_free(their_ref); - - return result; -} - -void test_merge_workdir_fastforward__fastforward(void) -{ - git_merge_result *result; - git_oid expected, ff_oid; - - cl_git_pass(git_oid_fromstr(&expected, THEIRS_FASTFORWARD_OID)); - - cl_assert(result = merge_fastforward_branch(0)); - cl_assert(git_merge_result_is_fastforward(result)); - cl_git_pass(git_merge_result_fastforward_oid(&ff_oid, result)); - cl_assert(git_oid_cmp(&ff_oid, &expected) == 0); - - git_merge_result_free(result); -} - -void test_merge_workdir_fastforward__fastforward_only(void) -{ - git_merge_result *result; - git_merge_opts opts = GIT_MERGE_OPTS_INIT; - git_reference *their_ref; - git_merge_head *their_head; - int error; - - opts.merge_flags = GIT_MERGE_FASTFORWARD_ONLY; - - cl_git_pass(git_reference_lookup(&their_ref, repo, GIT_REFS_HEADS_DIR THEIRS_NOFASTFORWARD_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref)); - - cl_git_fail((error = git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts))); - cl_assert(error == GIT_ENONFASTFORWARD); - - git_merge_head_free(their_head); - git_reference_free(their_ref); -} - -void test_merge_workdir_fastforward__no_fastforward(void) -{ - git_merge_result *result; - - struct merge_index_entry merge_index_entries[] = { - { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, - { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" }, - { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, - { 0100644, "bd9cb4cd0a770cb9adcb5fce212142ef40ea1c35", 0, "changed-in-master.txt" }, - { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, - { 0100644, "364bbe4ce80c7bd31e6307dce77d46e3e1759fb3", 0, "new-in-ff.txt" }, - { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, - { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, - }; - - cl_assert(result = merge_fastforward_branch(GIT_MERGE_NO_FASTFORWARD)); - cl_assert(!git_merge_result_is_fastforward(result)); - - cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - - git_merge_result_free(result); -} - -void test_merge_workdir_fastforward__uptodate(void) -{ - git_reference *their_ref; - git_merge_head *their_heads[1]; - git_merge_result *result; - - cl_git_pass(git_reference_lookup(&their_ref, repo, GIT_HEAD_FILE)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref)); - - cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, NULL)); - - cl_assert(git_merge_result_is_uptodate(result)); - - git_merge_head_free(their_heads[0]); - git_reference_free(their_ref); - git_merge_result_free(result); -} - -void test_merge_workdir_fastforward__uptodate_merging_prev_commit(void) -{ - git_oid their_oid; - git_merge_head *their_heads[1]; - git_merge_result *result; - - cl_git_pass(git_oid_fromstr(&their_oid, "c607fc30883e335def28cd686b51f6cfa02b06ec")); - cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oid)); - - cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, NULL)); - - cl_assert(git_merge_result_is_uptodate(result)); - - git_merge_head_free(their_heads[0]); - git_merge_result_free(result); -} - diff --git a/tests-clar/merge/workdir/renames.c b/tests-clar/merge/workdir/renames.c deleted file mode 100644 index d38397983..000000000 --- a/tests-clar/merge/workdir/renames.c +++ /dev/null @@ -1,156 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/repository.h" -#include "git2/merge.h" -#include "buffer.h" -#include "merge.h" -#include "../merge_helpers.h" -#include "fileops.h" -#include "refs.h" - -static git_repository *repo; - -#define TEST_REPO_PATH "merge-resolve" - -#define BRANCH_RENAME_OURS "rename_conflict_ours" -#define BRANCH_RENAME_THEIRS "rename_conflict_theirs" - -// Fixture setup and teardown -void test_merge_workdir_renames__initialize(void) -{ - repo = cl_git_sandbox_init(TEST_REPO_PATH); -} - -void test_merge_workdir_renames__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_merge_workdir_renames__renames(void) -{ - git_merge_result *result; - git_merge_opts opts = GIT_MERGE_OPTS_INIT; - - struct merge_index_entry merge_index_entries[] = { - { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, - { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, - { 0100644, "8aac75de2a34b4d340bf62a6e58197269cb55797", 0, "0b-rewritten-in-ours.txt" }, - { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, - { 0100644, "7edc726325da726751a4195e434e4377b0f67f9a", 0, "0c-rewritten-in-theirs.txt" }, - { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, - { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, - { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, - { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, - { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, - { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, - { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, - { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-newname-in-ours-added-in-theirs.txt~HEAD" }, - { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 0, "4a-newname-in-ours-added-in-theirs.txt~rename_conflict_theirs" }, - { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 0, "4b-newname-in-theirs-added-in-ours.txt~HEAD" }, - { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 0, "4b-newname-in-theirs-added-in-ours.txt~rename_conflict_theirs" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 0, "5a-newname-in-ours-added-in-theirs.txt~HEAD" }, - { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 0, "5a-newname-in-ours-added-in-theirs.txt~rename_conflict_theirs" }, - { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 0, "5b-newname-in-theirs-added-in-ours.txt~HEAD" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 0, "5b-newname-in-theirs-added-in-ours.txt~rename_conflict_theirs" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-ours.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-theirs.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt~HEAD" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" }, - }; - - opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; - opts.merge_tree_opts.rename_threshold = 50; - - cl_git_pass(merge_branches(&result, repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &opts)); - cl_assert(merge_test_workdir(repo, merge_index_entries, 24)); - - git_merge_result_free(result); -} - -void test_merge_workdir_renames__ours(void) -{ - git_index *index; - git_merge_result *result; - git_merge_opts opts = GIT_MERGE_OPTS_INIT; - - struct merge_index_entry merge_index_entries[] = { - { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, - { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, - { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 0, "0b-rewritten-in-ours.txt" }, - { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, - { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 0, "0c-rewritten-in-theirs.txt" }, - { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, - { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, - { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, - { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, - { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, - { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, - { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, - { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 0, "4b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 0, "5a-newname-in-ours-added-in-theirs.txt" }, - { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 0, "5b-newname-in-theirs-added-in-ours.txt" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 0, "5b-renamed-in-theirs-added-in-ours.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-ours.txt" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed-side-2.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt" }, - }; - - opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; - opts.merge_tree_opts.rename_threshold = 50; - opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS; - - cl_git_pass(merge_branches(&result, repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &opts)); - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_write(index)); - cl_assert(merge_test_workdir(repo, merge_index_entries, 20)); - - git_merge_result_free(result); - git_index_free(index); -} - -void test_merge_workdir_renames__similar(void) -{ - git_merge_result *result; - git_merge_opts opts = GIT_MERGE_OPTS_INIT; - - /* - * Note: this differs slightly from the core git merge result - there, 4a is - * tracked as a rename/delete instead of a rename/add and the theirs side - * is not placed in workdir in any form. - */ - struct merge_index_entry merge_index_entries[] = { - { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, - { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, - { 0100644, "8aac75de2a34b4d340bf62a6e58197269cb55797", 0, "0b-rewritten-in-ours.txt" }, - { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, - { 0100644, "7edc726325da726751a4195e434e4377b0f67f9a", 0, "0c-rewritten-in-theirs.txt" }, - { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, - { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, - { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, - { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, - { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, - { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, - { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, - { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-newname-in-ours-added-in-theirs.txt~HEAD" }, - { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 0, "4a-newname-in-ours-added-in-theirs.txt~rename_conflict_theirs" }, - { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 0, "4b-newname-in-theirs-added-in-ours.txt~HEAD" }, - { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 0, "4b-newname-in-theirs-added-in-ours.txt~rename_conflict_theirs" }, - { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 0, "5a-newname-in-ours-added-in-theirs.txt~HEAD" }, - { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 0, "5a-newname-in-ours-added-in-theirs.txt~rename_conflict_theirs" }, - { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 0, "5b-newname-in-theirs-added-in-ours.txt~HEAD" }, - { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 0, "5b-newname-in-theirs-added-in-ours.txt~rename_conflict_theirs" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-ours.txt" }, - { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-theirs.txt" }, - { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt~HEAD" }, - { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" }, - }; - - opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; - opts.merge_tree_opts.rename_threshold = 50; - - cl_git_pass(merge_branches(&result, repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &opts)); - cl_assert(merge_test_workdir(repo, merge_index_entries, 24)); - - git_merge_result_free(result); -} - diff --git a/tests-clar/merge/workdir/setup.c b/tests-clar/merge/workdir/setup.c deleted file mode 100644 index 870d55ef2..000000000 --- a/tests-clar/merge/workdir/setup.c +++ /dev/null @@ -1,1057 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/repository.h" -#include "git2/merge.h" -#include "merge.h" -#include "refs.h" -#include "fileops.h" - -static git_repository *repo; -static git_index *repo_index; - -#define TEST_REPO_PATH "merge-resolve" -#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" - -#define ORIG_HEAD "bd593285fc7fe4ca18ccdbabf027f5d689101452" - -#define THEIRS_SIMPLE_BRANCH "branch" -#define THEIRS_SIMPLE_OID "7cb63eed597130ba4abb87b3e544b85021905520" - -#define OCTO1_BRANCH "octo1" -#define OCTO1_OID "16f825815cfd20a07a75c71554e82d8eede0b061" - -#define OCTO2_BRANCH "octo2" -#define OCTO2_OID "158dc7bedb202f5b26502bf3574faa7f4238d56c" - -#define OCTO3_BRANCH "octo3" -#define OCTO3_OID "50ce7d7d01217679e26c55939eef119e0c93e272" - -#define OCTO4_BRANCH "octo4" -#define OCTO4_OID "54269b3f6ec3d7d4ede24dd350dd5d605495c3ae" - -#define OCTO5_BRANCH "octo5" -#define OCTO5_OID "e4f618a2c3ed0669308735727df5ebf2447f022f" - -// Fixture setup and teardown -void test_merge_workdir_setup__initialize(void) -{ - repo = cl_git_sandbox_init(TEST_REPO_PATH); - git_repository_index(&repo_index, repo); -} - -void test_merge_workdir_setup__cleanup(void) -{ - git_index_free(repo_index); - cl_git_sandbox_cleanup(); -} - -static bool test_file_contents(const char *filename, const char *expected) -{ - git_buf file_path_buf = GIT_BUF_INIT, file_buf = GIT_BUF_INIT; - bool equals; - - git_buf_printf(&file_path_buf, "%s/%s", git_repository_path(repo), filename); - - cl_git_pass(git_futils_readbuffer(&file_buf, file_path_buf.ptr)); - equals = (strcmp(file_buf.ptr, expected) == 0); - - git_buf_free(&file_path_buf); - git_buf_free(&file_buf); - - return equals; -} - -static void write_file_contents(const char *filename, const char *output) -{ - git_buf file_path_buf = GIT_BUF_INIT; - - git_buf_printf(&file_path_buf, "%s/%s", git_repository_path(repo), - filename); - cl_git_rewritefile(file_path_buf.ptr, output); - - git_buf_free(&file_path_buf); -} - -/* git merge octo1 */ -void test_merge_workdir_setup__one_branch(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_merge_head *our_head, *their_heads[1]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'\n")); - - git_reference_free(octo1_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); -} - -/* git merge --no-ff octo1 */ -void test_merge_workdir_setup__no_fastforward(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_merge_head *our_head, *their_heads[1]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, GIT_MERGE_NO_FASTFORWARD)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'\n")); - - git_reference_free(octo1_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); -} - -/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 */ -void test_merge_workdir_setup__one_oid(void) -{ - git_oid our_oid; - git_oid octo1_oid; - git_merge_head *our_head, *their_heads[1]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'\n")); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); -} - -/* git merge octo1 octo2 */ -void test_merge_workdir_setup__two_branches(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_reference *octo2_ref; - git_merge_head *our_head, *their_heads[2]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO2_BRANCH "'\n")); - - git_reference_free(octo1_ref); - git_reference_free(octo2_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); -} - -/* git merge octo1 octo2 octo3 */ -void test_merge_workdir_setup__three_branches(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_reference *octo2_ref; - git_reference *octo3_ref; - git_merge_head *our_head, *their_heads[3]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); - - cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO2_BRANCH "' and '" OCTO3_BRANCH "'\n")); - - git_reference_free(octo1_ref); - git_reference_free(octo2_ref); - git_reference_free(octo3_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); -} - -/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 158dc7bedb202f5b26502bf3574faa7f4238d56c 50ce7d7d01217679e26c55939eef119e0c93e272 */ -void test_merge_workdir_setup__three_oids(void) -{ - git_oid our_oid; - git_oid octo1_oid; - git_oid octo2_oid; - git_oid octo3_oid; - git_merge_head *our_head, *their_heads[3]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid)); - - cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo2_oid)); - - cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo3_oid)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; commit '" OCTO2_OID "'; commit '" OCTO3_OID "'\n")); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); -} - -/* git merge octo1 158dc7bedb202f5b26502bf3574faa7f4238d56c */ -void test_merge_workdir_setup__branches_and_oids_1(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_oid octo2_oid; - git_merge_head *our_head, *their_heads[2]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo2_oid)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'; commit '" OCTO2_OID "'\n")); - - git_reference_free(octo1_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); -} - -/* git merge octo1 158dc7bedb202f5b26502bf3574faa7f4238d56c octo3 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae */ -void test_merge_workdir_setup__branches_and_oids_2(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_oid octo2_oid; - git_reference *octo3_ref; - git_oid octo4_oid; - git_merge_head *our_head, *their_heads[4]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo2_oid)); - - cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref)); - - cl_git_pass(git_oid_fromstr(&octo4_oid, OCTO4_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[3], repo, &octo4_oid)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "'; commit '" OCTO2_OID "'; commit '" OCTO4_OID "'\n")); - - git_reference_free(octo1_ref); - git_reference_free(octo3_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); - git_merge_head_free(their_heads[3]); -} - -/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 octo2 50ce7d7d01217679e26c55939eef119e0c93e272 octo4 */ -void test_merge_workdir_setup__branches_and_oids_3(void) -{ - git_oid our_oid; - git_oid octo1_oid; - git_reference *octo2_ref; - git_oid octo3_oid; - git_reference *octo4_ref; - git_merge_head *our_head, *their_heads[4]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid)); - - cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); - - cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo3_oid)); - - cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[3], repo, octo4_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; branches '" OCTO2_BRANCH "' and '" OCTO4_BRANCH "'; commit '" OCTO3_OID "'\n")); - - git_reference_free(octo2_ref); - git_reference_free(octo4_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); - git_merge_head_free(their_heads[3]); -} - -/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 octo2 50ce7d7d01217679e26c55939eef119e0c93e272 octo4 octo5 */ -void test_merge_workdir_setup__branches_and_oids_4(void) -{ - git_oid our_oid; - git_oid octo1_oid; - git_reference *octo2_ref; - git_oid octo3_oid; - git_reference *octo4_ref; - git_reference *octo5_ref; - git_merge_head *our_head, *their_heads[5]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid)); - - cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); - - cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo3_oid)); - - cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[3], repo, octo4_ref)); - - cl_git_pass(git_reference_lookup(&octo5_ref, repo, GIT_REFS_HEADS_DIR OCTO5_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[4], repo, octo5_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 5, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n" OCTO5_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; branches '" OCTO2_BRANCH "', '" OCTO4_BRANCH "' and '" OCTO5_BRANCH "'; commit '" OCTO3_OID "'\n")); - - git_reference_free(octo2_ref); - git_reference_free(octo4_ref); - git_reference_free(octo5_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); - git_merge_head_free(their_heads[3]); - git_merge_head_free(their_heads[4]); -} - -/* git merge octo1 octo1 octo1 */ -void test_merge_workdir_setup__three_same_branches(void) -{ - git_oid our_oid; - git_reference *octo1_1_ref; - git_reference *octo1_2_ref; - git_reference *octo1_3_ref; - git_merge_head *our_head, *their_heads[3]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_1_ref)); - - cl_git_pass(git_reference_lookup(&octo1_2_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo1_2_ref)); - - cl_git_pass(git_reference_lookup(&octo1_3_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo1_3_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO1_OID "\n" OCTO1_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO1_BRANCH "' and '" OCTO1_BRANCH "'\n")); - - git_reference_free(octo1_1_ref); - git_reference_free(octo1_2_ref); - git_reference_free(octo1_3_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); -} - -/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 16f825815cfd20a07a75c71554e82d8eede0b061 16f825815cfd20a07a75c71554e82d8eede0b061 */ -void test_merge_workdir_setup__three_same_oids(void) -{ - git_oid our_oid; - git_oid octo1_1_oid; - git_oid octo1_2_oid; - git_oid octo1_3_oid; - git_merge_head *our_head, *their_heads[3]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_oid_fromstr(&octo1_1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_1_oid)); - - cl_git_pass(git_oid_fromstr(&octo1_2_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo1_2_oid)); - - cl_git_pass(git_oid_fromstr(&octo1_3_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo1_3_oid)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO1_OID "\n" OCTO1_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; commit '" OCTO1_OID "'; commit '" OCTO1_OID "'\n")); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); -} - -static int create_remote_tracking_branch(const char *branch_name, const char *oid_str) -{ - int error = 0; - - git_buf remotes_path = GIT_BUF_INIT, - origin_path = GIT_BUF_INIT, - filename = GIT_BUF_INIT, - data = GIT_BUF_INIT; - - if ((error = git_buf_puts(&remotes_path, git_repository_path(repo))) < 0 || - (error = git_buf_puts(&remotes_path, GIT_REFS_REMOTES_DIR)) < 0) - goto done; - - if (!git_path_exists(git_buf_cstr(&remotes_path)) && - (error = p_mkdir(git_buf_cstr(&remotes_path), 0777)) < 0) - goto done; - - if ((error = git_buf_puts(&origin_path, git_buf_cstr(&remotes_path))) < 0 || - (error = git_buf_puts(&origin_path, "origin")) < 0) - goto done; - - if (!git_path_exists(git_buf_cstr(&origin_path)) && - (error = p_mkdir(git_buf_cstr(&origin_path), 0777)) < 0) - goto done; - - if ((error = git_buf_puts(&filename, git_buf_cstr(&origin_path))) < 0 || - (error = git_buf_puts(&filename, "/")) < 0 || - (error = git_buf_puts(&filename, branch_name)) < 0 || - (error = git_buf_puts(&data, oid_str)) < 0 || - (error = git_buf_puts(&data, "\n")) < 0) - goto done; - - cl_git_rewritefile(git_buf_cstr(&filename), git_buf_cstr(&data)); - -done: - git_buf_free(&remotes_path); - git_buf_free(&origin_path); - git_buf_free(&filename); - git_buf_free(&data); - - return error; -} - -/* git merge refs/remotes/origin/octo1 */ -void test_merge_workdir_setup__remote_tracking_one_branch(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_merge_head *our_head, *their_heads[1]; - - cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID)); - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branch 'refs/remotes/origin/" OCTO1_BRANCH "'\n")); - - git_reference_free(octo1_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); -} - -/* git merge refs/remotes/origin/octo1 refs/remotes/origin/octo2 */ -void test_merge_workdir_setup__remote_tracking_two_branches(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_reference *octo2_ref; - git_merge_head *our_head, *their_heads[2]; - - cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID)); - cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID)); - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branches 'refs/remotes/origin/" OCTO1_BRANCH "' and 'refs/remotes/origin/" OCTO2_BRANCH "'\n")); - - git_reference_free(octo1_ref); - git_reference_free(octo2_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); -} - -/* git merge refs/remotes/origin/octo1 refs/remotes/origin/octo2 refs/remotes/origin/octo3 */ -void test_merge_workdir_setup__remote_tracking_three_branches(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_reference *octo2_ref; - git_reference *octo3_ref; - git_merge_head *our_head, *their_heads[3]; - - cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID)); - cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID)); - cl_git_pass(create_remote_tracking_branch(OCTO3_BRANCH, OCTO3_OID)); - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); - - cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO3_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branches 'refs/remotes/origin/" OCTO1_BRANCH "', 'refs/remotes/origin/" OCTO2_BRANCH "' and 'refs/remotes/origin/" OCTO3_BRANCH "'\n")); - - git_reference_free(octo1_ref); - git_reference_free(octo2_ref); - git_reference_free(octo3_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); -} - -/* git merge octo1 refs/remotes/origin/octo2 */ -void test_merge_workdir_setup__normal_branch_and_remote_tracking_branch(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_reference *octo2_ref; - git_merge_head *our_head, *their_heads[2]; - - cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID)); - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "', remote-tracking branch 'refs/remotes/origin/" OCTO2_BRANCH "'\n")); - - git_reference_free(octo1_ref); - git_reference_free(octo2_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); -} - -/* git merge refs/remotes/origin/octo1 octo2 */ -void test_merge_workdir_setup__remote_tracking_branch_and_normal_branch(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_reference *octo2_ref; - git_merge_head *our_head, *their_heads[2]; - - cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID)); - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO2_BRANCH "', remote-tracking branch 'refs/remotes/origin/" OCTO1_BRANCH "'\n")); - - git_reference_free(octo1_ref); - git_reference_free(octo2_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); -} - -/* git merge octo1 refs/remotes/origin/octo2 octo3 refs/remotes/origin/octo4 */ -void test_merge_workdir_setup__two_remote_tracking_branch_and_two_normal_branches(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_reference *octo2_ref; - git_reference *octo3_ref; - git_reference *octo4_ref; - git_merge_head *our_head, *their_heads[4]; - - cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID)); - cl_git_pass(create_remote_tracking_branch(OCTO4_BRANCH, OCTO4_OID)); - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); - - cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref)); - - cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO4_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[3], repo, octo4_ref)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "', remote-tracking branches 'refs/remotes/origin/" OCTO2_BRANCH "' and 'refs/remotes/origin/" OCTO4_BRANCH "'\n")); - - git_reference_free(octo1_ref); - git_reference_free(octo2_ref); - git_reference_free(octo3_ref); - git_reference_free(octo4_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); - git_merge_head_free(their_heads[3]); -} - -/* git pull origin branch octo1 */ -void test_merge_workdir_setup__pull_one(void) -{ - git_oid our_oid; - git_oid octo1_1_oid; - git_merge_head *our_head, *their_heads[1]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_oid_fromstr(&octo1_1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_1_oid)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch 'octo1' of http://remote.url/repo.git\n")); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); -} - -/* git pull origin octo1 octo2 */ -void test_merge_workdir_setup__pull_two(void) -{ - git_oid our_oid; - git_oid octo1_oid; - git_oid octo2_oid; - git_merge_head *our_head, *their_heads[2]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_oid)); - - cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.url/repo.git", &octo2_oid)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO2_BRANCH "' of http://remote.url/repo.git\n")); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); -} - -/* git pull origin octo1 octo2 octo3 */ -void test_merge_workdir_setup__pull_three(void) -{ - git_oid our_oid; - git_oid octo1_oid; - git_oid octo2_oid; - git_oid octo3_oid; - git_merge_head *our_head, *their_heads[3]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_oid)); - - cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.url/repo.git", &octo2_oid)); - - cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.url/repo.git", &octo3_oid)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO2_BRANCH "' and '" OCTO3_BRANCH "' of http://remote.url/repo.git\n")); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); -} - -void test_merge_workdir_setup__three_remotes(void) -{ - git_oid our_oid; - git_oid octo1_oid; - git_oid octo2_oid; - git_oid octo3_oid; - git_merge_head *our_head, *their_heads[3]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.first/repo.git", &octo1_oid)); - - cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.second/repo.git", &octo2_oid)); - - cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.third/repo.git", &octo3_oid)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "' of http://remote.first/repo.git, branch '" OCTO2_BRANCH "' of http://remote.second/repo.git, branch '" OCTO3_BRANCH "' of http://remote.third/repo.git\n")); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); -} - -void test_merge_workdir_setup__two_remotes(void) -{ - git_oid our_oid; - git_oid octo1_oid; - git_oid octo2_oid; - git_oid octo3_oid; - git_oid octo4_oid; - git_merge_head *our_head, *their_heads[4]; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.first/repo.git", &octo1_oid)); - - cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.second/repo.git", &octo2_oid)); - - cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.first/repo.git", &octo3_oid)); - - cl_git_pass(git_oid_fromstr(&octo4_oid, OCTO4_OID)); - cl_git_pass(git_merge_head_from_fetchhead(&their_heads[3], repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH, "http://remote.second/repo.git", &octo4_oid)); - - cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "' of http://remote.first/repo.git, branches '" OCTO2_BRANCH "' and '" OCTO4_BRANCH "' of http://remote.second/repo.git\n")); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_head_free(their_heads[1]); - git_merge_head_free(their_heads[2]); - git_merge_head_free(their_heads[3]); -} - -struct merge_head_cb_data { - const char **oid_str; - unsigned int len; - - unsigned int i; -}; - -static int merge_head_foreach_cb(const git_oid *oid, void *payload) -{ - git_oid expected_oid; - struct merge_head_cb_data *cb_data = payload; - - git_oid_fromstr(&expected_oid, cb_data->oid_str[cb_data->i]); - cl_assert(git_oid_cmp(&expected_oid, oid) == 0); - cb_data->i++; - return 0; -} - -void test_merge_workdir_setup__head_notfound(void) -{ - int error; - - cl_git_fail((error = git_repository_mergehead_foreach(repo, - merge_head_foreach_cb, NULL))); - cl_assert(error == GIT_ENOTFOUND); -} - -void test_merge_workdir_setup__head_invalid_oid(void) -{ - int error; - - write_file_contents(GIT_MERGE_HEAD_FILE, "invalid-oid\n"); - - cl_git_fail((error = git_repository_mergehead_foreach(repo, - merge_head_foreach_cb, NULL))); - cl_assert(error == -1); -} - -void test_merge_workdir_setup__head_foreach_nonewline(void) -{ - int error; - - write_file_contents(GIT_MERGE_HEAD_FILE, THEIRS_SIMPLE_OID); - - cl_git_fail((error = git_repository_mergehead_foreach(repo, - merge_head_foreach_cb, NULL))); - cl_assert(error == -1); -} - -void test_merge_workdir_setup__head_foreach_one(void) -{ - const char *expected = THEIRS_SIMPLE_OID; - - struct merge_head_cb_data cb_data = { &expected, 1 }; - - write_file_contents(GIT_MERGE_HEAD_FILE, THEIRS_SIMPLE_OID "\n"); - - cl_git_pass(git_repository_mergehead_foreach(repo, - merge_head_foreach_cb, &cb_data)); - - cl_assert(cb_data.i == cb_data.len); -} - -void test_merge_workdir_setup__head_foreach_octopus(void) -{ - const char *expected[] = { THEIRS_SIMPLE_OID, - OCTO1_OID, OCTO2_OID, OCTO3_OID, OCTO4_OID, OCTO5_OID }; - - struct merge_head_cb_data cb_data = { expected, 6 }; - - write_file_contents(GIT_MERGE_HEAD_FILE, - THEIRS_SIMPLE_OID "\n" - OCTO1_OID "\n" - OCTO2_OID "\n" - OCTO3_OID "\n" - OCTO4_OID "\n" - OCTO5_OID "\n"); - - cl_git_pass(git_repository_mergehead_foreach(repo, - merge_head_foreach_cb, &cb_data)); - - cl_assert(cb_data.i == cb_data.len); -} - -void test_merge_workdir_setup__retained_after_success(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_merge_head *our_head, *their_heads[1]; - git_merge_result *result; - git_merge_opts opts = GIT_MERGE_OPTS_INIT; - - opts.merge_flags |= GIT_MERGE_NO_FASTFORWARD; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_heads[0], 1, &opts)); - - cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); - cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); - cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); - cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'\n")); - - git_reference_free(octo1_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_result_free(result); -} - -void test_merge_workdir_setup__removed_after_failure(void) -{ - git_oid our_oid; - git_reference *octo1_ref; - git_merge_head *our_head, *their_heads[1]; - git_merge_result *result; - git_merge_opts opts = GIT_MERGE_OPTS_INIT; - - opts.merge_flags |= GIT_MERGE_NO_FASTFORWARD; - - cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); - cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); - - cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); - - cl_git_rewritefile("merge-resolve/new-in-octo1.txt", - "Conflicting file!\n\nMerge will fail!\n"); - - cl_git_fail(git_merge( - &result, repo, (const git_merge_head **)&their_heads[0], 1, &opts)); - - cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_HEAD_FILE)); - cl_assert(!git_path_exists("merge-resolve/" GIT_ORIG_HEAD_FILE)); - cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_MODE_FILE)); - cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_MSG_FILE)); - - git_reference_free(octo1_ref); - - git_merge_head_free(our_head); - git_merge_head_free(their_heads[0]); - git_merge_result_free(result); -} diff --git a/tests-clar/merge/workdir/simple.c b/tests-clar/merge/workdir/simple.c deleted file mode 100644 index 4a3b86ee4..000000000 --- a/tests-clar/merge/workdir/simple.c +++ /dev/null @@ -1,491 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/repository.h" -#include "git2/merge.h" -#include "buffer.h" -#include "merge.h" -#include "../merge_helpers.h" -#include "refs.h" -#include "fileops.h" - -static git_repository *repo; -static git_index *repo_index; - -#define TEST_REPO_PATH "merge-resolve" -#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" - -#define THEIRS_SIMPLE_BRANCH "branch" -#define THEIRS_SIMPLE_OID "7cb63eed597130ba4abb87b3e544b85021905520" - -#define THEIRS_UNRELATED_BRANCH "unrelated" -#define THEIRS_UNRELATED_OID "55b4e4687e7a0d9ca367016ed930f385d4022e6f" -#define THEIRS_UNRELATED_PARENT "d6cf6c7741b3316826af1314042550c97ded1d50" - -#define OURS_DIRECTORY_FILE "df_side1" -#define THEIRS_DIRECTORY_FILE "fc90237dc4891fa6c69827fc465632225e391618" - - -/* Non-conflicting files, index entries are common to every merge operation */ -#define ADDED_IN_MASTER_INDEX_ENTRY \ - { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, \ - "added-in-master.txt" } -#define AUTOMERGEABLE_INDEX_ENTRY \ - { 0100644, "f2e1550a0c9e53d5811175864a29536642ae3821", 0, \ - "automergeable.txt" } -#define CHANGED_IN_BRANCH_INDEX_ENTRY \ - { 0100644, "4eb04c9e79e88f6640d01ff5b25ca2a60764f216", 0, \ - "changed-in-branch.txt" } -#define CHANGED_IN_MASTER_INDEX_ENTRY \ - { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, \ - "changed-in-master.txt" } -#define UNCHANGED_INDEX_ENTRY \ - { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, \ - "unchanged.txt" } - -/* Unrelated files */ -#define UNRELATED_NEW1 \ - { 0100644, "ef58fdd8086c243bdc81f99e379acacfd21d32d6", 0, \ - "new-in-unrelated1.txt" } -#define UNRELATED_NEW2 \ - { 0100644, "948ba6e701c1edab0c2d394fb7c5538334129793", 0, \ - "new-in-unrelated2.txt" } - -/* Expected REUC entries */ -#define AUTOMERGEABLE_REUC_ENTRY \ - { "automergeable.txt", 0100644, 0100644, 0100644, \ - "6212c31dab5e482247d7977e4f0dd3601decf13b", \ - "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", \ - "058541fc37114bfc1dddf6bd6bffc7fae5c2e6fe" } -#define CONFLICTING_REUC_ENTRY \ - { "conflicting.txt", 0100644, 0100644, 0100644, \ - "d427e0b2e138501a3d15cc376077a3631e15bd46", \ - "4e886e602529caa9ab11d71f86634bd1b6e0de10", \ - "2bd0a343aeef7a2cf0d158478966a6e587ff3863" } -#define REMOVED_IN_BRANCH_REUC_ENTRY \ - { "removed-in-branch.txt", 0100644, 0100644, 0, \ - "dfe3f22baa1f6fce5447901c3086bae368de6bdd", \ - "dfe3f22baa1f6fce5447901c3086bae368de6bdd", \ - "" } -#define REMOVED_IN_MASTER_REUC_ENTRY \ - { "removed-in-master.txt", 0100644, 0, 0100644, \ - "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", \ - "", \ - "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5" } - -#define AUTOMERGEABLE_MERGED_FILE \ - "this file is changed in master\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is changed in branch\n" - -#define AUTOMERGEABLE_MERGED_FILE_CRLF \ - "this file is changed in master\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is automergeable\r\n" \ - "this file is changed in branch\r\n" - -#define CONFLICTING_DIFF3_FILE \ - "<<<<<<< HEAD\n" \ - "this file is changed in master and branch\n" \ - "=======\n" \ - "this file is changed in branch and master\n" \ - ">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n" - -// Fixture setup and teardown -void test_merge_workdir_simple__initialize(void) -{ - repo = cl_git_sandbox_init(TEST_REPO_PATH); - git_repository_index(&repo_index, repo); -} - -void test_merge_workdir_simple__cleanup(void) -{ - git_index_free(repo_index); - cl_git_sandbox_cleanup(); -} - -static git_merge_result *merge_simple_branch(int automerge_flags, int checkout_strategy) -{ - git_oid their_oids[1]; - git_merge_head *their_heads[1]; - git_merge_result *result; - git_merge_opts opts = GIT_MERGE_OPTS_INIT; - - cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_SIMPLE_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0])); - - opts.merge_tree_opts.automerge_flags = automerge_flags; - opts.checkout_opts.checkout_strategy = checkout_strategy; - cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); - - git_merge_head_free(their_heads[0]); - - return result; -} - -static void set_core_autocrlf_to(git_repository *repo, bool value) -{ - git_config *cfg; - - cl_git_pass(git_repository_config(&cfg, repo)); - cl_git_pass(git_config_set_bool(cfg, "core.autocrlf", value)); - - git_config_free(cfg); -} - -void test_merge_workdir_simple__automerge(void) -{ - git_index *index; - const git_index_entry *entry; - git_merge_result *result; - git_buf automergeable_buf = GIT_BUF_INIT; - - struct merge_index_entry merge_index_entries[] = { - ADDED_IN_MASTER_INDEX_ENTRY, - AUTOMERGEABLE_INDEX_ENTRY, - CHANGED_IN_BRANCH_INDEX_ENTRY, - CHANGED_IN_MASTER_INDEX_ENTRY, - - { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, - { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, - { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, - - UNCHANGED_INDEX_ENTRY, - }; - - struct merge_reuc_entry merge_reuc_entries[] = { - AUTOMERGEABLE_REUC_ENTRY, - REMOVED_IN_BRANCH_REUC_ENTRY, - REMOVED_IN_MASTER_REUC_ENTRY - }; - - - set_core_autocrlf_to(repo, false); - - cl_assert(result = merge_simple_branch(0, 0)); - cl_assert(!git_merge_result_is_fastforward(result)); - - cl_git_pass(git_futils_readbuffer(&automergeable_buf, - TEST_REPO_PATH "/automergeable.txt")); - cl_assert(strcmp(automergeable_buf.ptr, AUTOMERGEABLE_MERGED_FILE) == 0); - git_buf_free(&automergeable_buf); - - cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); - cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); - - git_merge_result_free(result); - - git_repository_index(&index, repo); - - cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL); - cl_assert(entry->file_size == strlen(AUTOMERGEABLE_MERGED_FILE)); - - git_index_free(index); -} - -void test_merge_workdir_simple__automerge_crlf(void) -{ -#ifdef GIT_WIN32 - git_index *index; - const git_index_entry *entry; - - git_merge_result *result; - git_buf automergeable_buf = GIT_BUF_INIT; - - struct merge_index_entry merge_index_entries[] = { - ADDED_IN_MASTER_INDEX_ENTRY, - AUTOMERGEABLE_INDEX_ENTRY, - CHANGED_IN_BRANCH_INDEX_ENTRY, - CHANGED_IN_MASTER_INDEX_ENTRY, - - { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, - { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, - { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, - - UNCHANGED_INDEX_ENTRY, - }; - - struct merge_reuc_entry merge_reuc_entries[] = { - AUTOMERGEABLE_REUC_ENTRY, - REMOVED_IN_BRANCH_REUC_ENTRY, - REMOVED_IN_MASTER_REUC_ENTRY - }; - - set_core_autocrlf_to(repo, true); - - cl_assert(result = merge_simple_branch(0, 0)); - cl_assert(!git_merge_result_is_fastforward(result)); - - cl_git_pass(git_futils_readbuffer(&automergeable_buf, - TEST_REPO_PATH "/automergeable.txt")); - cl_assert(strcmp(automergeable_buf.ptr, AUTOMERGEABLE_MERGED_FILE_CRLF) == 0); - git_buf_free(&automergeable_buf); - - cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); - cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); - - git_merge_result_free(result); - - git_repository_index(&index, repo); - - cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL); - cl_assert(entry->file_size == strlen(AUTOMERGEABLE_MERGED_FILE_CRLF)); - - git_index_free(index); -#endif /* GIT_WIN32 */ -} - -void test_merge_workdir_simple__diff3(void) -{ - git_merge_result *result; - git_buf conflicting_buf = GIT_BUF_INIT; - - struct merge_index_entry merge_index_entries[] = { - ADDED_IN_MASTER_INDEX_ENTRY, - AUTOMERGEABLE_INDEX_ENTRY, - CHANGED_IN_BRANCH_INDEX_ENTRY, - CHANGED_IN_MASTER_INDEX_ENTRY, - - { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, - { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, - { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, - - UNCHANGED_INDEX_ENTRY, - }; - - struct merge_reuc_entry merge_reuc_entries[] = { - AUTOMERGEABLE_REUC_ENTRY, - REMOVED_IN_BRANCH_REUC_ENTRY, - REMOVED_IN_MASTER_REUC_ENTRY - }; - - cl_assert(result = merge_simple_branch(0, 0)); - cl_assert(!git_merge_result_is_fastforward(result)); - - cl_git_pass(git_futils_readbuffer(&conflicting_buf, - TEST_REPO_PATH "/conflicting.txt")); - cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_DIFF3_FILE) == 0); - git_buf_free(&conflicting_buf); - - cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); - cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); - - git_merge_result_free(result); -} - -void test_merge_workdir_simple__checkout_ours(void) -{ - git_merge_result *result; - - struct merge_index_entry merge_index_entries[] = { - ADDED_IN_MASTER_INDEX_ENTRY, - AUTOMERGEABLE_INDEX_ENTRY, - CHANGED_IN_BRANCH_INDEX_ENTRY, - CHANGED_IN_MASTER_INDEX_ENTRY, - - { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, - { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, - { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, - - UNCHANGED_INDEX_ENTRY, - }; - - struct merge_reuc_entry merge_reuc_entries[] = { - AUTOMERGEABLE_REUC_ENTRY, - REMOVED_IN_BRANCH_REUC_ENTRY, - REMOVED_IN_MASTER_REUC_ENTRY - }; - - cl_assert(result = merge_simple_branch(0, GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS)); - cl_assert(!git_merge_result_is_fastforward(result)); - - cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); - cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); - - cl_assert(git_path_exists(TEST_REPO_PATH "/conflicting.txt")); - - git_merge_result_free(result); -} - -void test_merge_workdir_simple__favor_ours(void) -{ - git_merge_result *result; - - struct merge_index_entry merge_index_entries[] = { - ADDED_IN_MASTER_INDEX_ENTRY, - AUTOMERGEABLE_INDEX_ENTRY, - CHANGED_IN_BRANCH_INDEX_ENTRY, - CHANGED_IN_MASTER_INDEX_ENTRY, - { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, - UNCHANGED_INDEX_ENTRY, - }; - - struct merge_reuc_entry merge_reuc_entries[] = { - AUTOMERGEABLE_REUC_ENTRY, - CONFLICTING_REUC_ENTRY, - REMOVED_IN_BRANCH_REUC_ENTRY, - REMOVED_IN_MASTER_REUC_ENTRY, - }; - - cl_assert(result = merge_simple_branch(GIT_MERGE_AUTOMERGE_FAVOR_OURS, 0)); - cl_assert(!git_merge_result_is_fastforward(result)); - - cl_assert(merge_test_index(repo_index, merge_index_entries, 6)); - cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4)); - - git_merge_result_free(result); -} - -void test_merge_workdir_simple__favor_theirs(void) -{ - git_merge_result *result; - - struct merge_index_entry merge_index_entries[] = { - ADDED_IN_MASTER_INDEX_ENTRY, - AUTOMERGEABLE_INDEX_ENTRY, - CHANGED_IN_BRANCH_INDEX_ENTRY, - CHANGED_IN_MASTER_INDEX_ENTRY, - { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 0, "conflicting.txt" }, - UNCHANGED_INDEX_ENTRY, - }; - - struct merge_reuc_entry merge_reuc_entries[] = { - AUTOMERGEABLE_REUC_ENTRY, - CONFLICTING_REUC_ENTRY, - REMOVED_IN_BRANCH_REUC_ENTRY, - REMOVED_IN_MASTER_REUC_ENTRY, - }; - - cl_assert(result = merge_simple_branch(GIT_MERGE_AUTOMERGE_FAVOR_THEIRS, 0)); - cl_assert(!git_merge_result_is_fastforward(result)); - - cl_assert(merge_test_index(repo_index, merge_index_entries, 6)); - cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4)); - - git_merge_result_free(result); -} - -void test_merge_workdir_simple__directory_file(void) -{ - git_reference *head; - git_oid their_oids[1], head_commit_id; - git_merge_head *their_heads[1]; - git_merge_result *result; - git_merge_opts opts = GIT_MERGE_OPTS_INIT; - git_commit *head_commit; - - struct merge_index_entry merge_index_entries[] = { - { 0100644, "49130a28ef567af9a6a6104c38773fedfa5f9742", 2, "dir-10" }, - { 0100644, "6c06dcd163587c2cc18be44857e0b71116382aeb", 3, "dir-10" }, - { 0100644, "43aafd43bea779ec74317dc361f45ae3f532a505", 0, "dir-6" }, - { 0100644, "a031a28ae70e33a641ce4b8a8f6317f1ab79dee4", 3, "dir-7" }, - { 0100644, "5012fd565b1393bdfda1805d4ec38ce6619e1fd1", 1, "dir-7/file.txt" }, - { 0100644, "a5563304ddf6caba25cb50323a2ea6f7dbfcadca", 2, "dir-7/file.txt" }, - { 0100644, "e9ad6ec3e38364a3d07feda7c4197d4d845c53b5", 0, "dir-8" }, - { 0100644, "3ef4d30382ca33fdeba9fda895a99e0891ba37aa", 2, "dir-9" }, - { 0100644, "fc4c636d6515e9e261f9260dbcf3cc6eca97ea08", 1, "dir-9/file.txt" }, - { 0100644, "76ab0e2868197ec158ddd6c78d8a0d2fd73d38f9", 3, "dir-9/file.txt" }, - { 0100644, "5c2411f8075f48a6b2fdb85ebc0d371747c4df15", 0, "file-1/new" }, - { 0100644, "a39a620dae5bc8b4e771cd4d251b7d080401a21e", 1, "file-2" }, - { 0100644, "d963979c237d08b6ba39062ee7bf64c7d34a27f8", 2, "file-2" }, - { 0100644, "5c341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d", 0, "file-2/new" }, - { 0100644, "9efe7723802d4305142eee177e018fee1572c4f4", 0, "file-3/new" }, - { 0100644, "bacac9b3493509aa15e1730e1545fc0919d1dae0", 1, "file-4" }, - { 0100644, "7663fce0130db092936b137cabd693ec234eb060", 3, "file-4" }, - { 0100644, "e49f917b448d1340b31d76e54ba388268fd4c922", 0, "file-4/new" }, - { 0100644, "cab2cf23998b40f1af2d9d9a756dc9e285a8df4b", 2, "file-5/new" }, - { 0100644, "f5504f36e6f4eb797a56fc5bac6c6c7f32969bf2", 3, "file-5/new" }, - }; - - cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_DIR OURS_DIRECTORY_FILE, 1)); - cl_git_pass(git_reference_name_to_id(&head_commit_id, repo, GIT_HEAD_FILE)); - cl_git_pass(git_commit_lookup(&head_commit, repo, &head_commit_id)); - cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD)); - - cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_DIRECTORY_FILE)); - cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0])); - - opts.merge_tree_opts.automerge_flags = 0; - cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); - - cl_assert(merge_test_index(repo_index, merge_index_entries, 20)); - - git_reference_free(head); - git_commit_free(head_commit); - git_merge_head_free(their_heads[0]); - git_merge_result_free(result); -} - -void test_merge_workdir_simple__unrelated(void) -{ - git_oid their_oids[1]; - git_merge_head *their_heads[1]; - git_merge_result *result; - git_merge_opts opts = GIT_MERGE_OPTS_INIT; - - struct merge_index_entry merge_index_entries[] = { - { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, - { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" }, - { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, - { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, - { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, - { 0100644, "ef58fdd8086c243bdc81f99e379acacfd21d32d6", 0, "new-in-unrelated1.txt" }, - { 0100644, "948ba6e701c1edab0c2d394fb7c5538334129793", 0, "new-in-unrelated2.txt" }, - { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, - { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, - }; - - cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_PARENT)); - cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0])); - - opts.merge_tree_opts.automerge_flags = 0; - cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); - - cl_assert(merge_test_index(repo_index, merge_index_entries, 9)); - - git_merge_head_free(their_heads[0]); - git_merge_result_free(result); -} - -void test_merge_workdir_simple__unrelated_with_conflicts(void) -{ - git_oid their_oids[1]; - git_merge_head *their_heads[1]; - git_merge_result *result; - git_merge_opts opts = GIT_MERGE_OPTS_INIT; - - struct merge_index_entry merge_index_entries[] = { - { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, - { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 2, "automergeable.txt" }, - { 0100644, "d07ec190c306ec690bac349e87d01c4358e49bb2", 3, "automergeable.txt" }, - { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, - { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, - { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, - { 0100644, "4b253da36a0ae8bfce63aeabd8c5b58429925594", 3, "conflicting.txt" }, - { 0100644, "ef58fdd8086c243bdc81f99e379acacfd21d32d6", 0, "new-in-unrelated1.txt" }, - { 0100644, "948ba6e701c1edab0c2d394fb7c5538334129793", 0, "new-in-unrelated2.txt" }, - { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, - { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, - }; - - cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_OID)); - cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0])); - - opts.merge_tree_opts.automerge_flags = 0; - cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); - - cl_assert(merge_test_index(repo_index, merge_index_entries, 11)); - - git_merge_head_free(their_heads[0]); - git_merge_result_free(result); -} - diff --git a/tests-clar/merge/workdir/trivial.c b/tests-clar/merge/workdir/trivial.c deleted file mode 100644 index 9f9566243..000000000 --- a/tests-clar/merge/workdir/trivial.c +++ /dev/null @@ -1,341 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/repository.h" -#include "git2/merge.h" -#include "git2/sys/index.h" -#include "merge.h" -#include "../merge_helpers.h" -#include "refs.h" -#include "fileops.h" - -static git_repository *repo; -static git_index *repo_index; - -#define TEST_REPO_PATH "merge-resolve" -#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" - - -// Fixture setup and teardown -void test_merge_workdir_trivial__initialize(void) -{ - repo = cl_git_sandbox_init(TEST_REPO_PATH); - git_repository_index(&repo_index, repo); -} - -void test_merge_workdir_trivial__cleanup(void) -{ - git_index_free(repo_index); - cl_git_sandbox_cleanup(); -} - - -static int merge_trivial(const char *ours, const char *theirs, bool automerge) -{ - git_buf branch_buf = GIT_BUF_INIT; - git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; - git_reference *our_ref, *their_ref; - git_merge_head *their_heads[1]; - git_merge_opts opts = GIT_MERGE_OPTS_INIT; - git_merge_result *result; - - checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; - - opts.merge_tree_opts.automerge_flags |= automerge ? 0 : GIT_MERGE_AUTOMERGE_NONE; - - git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours); - cl_git_pass(git_reference_symbolic_create(&our_ref, repo, "HEAD", branch_buf.ptr, 1)); - - cl_git_pass(git_checkout_head(repo, &checkout_opts)); - - git_buf_clear(&branch_buf); - git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs); - cl_git_pass(git_reference_lookup(&their_ref, repo, branch_buf.ptr)); - cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref)); - - cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); - - git_buf_free(&branch_buf); - git_reference_free(our_ref); - git_reference_free(their_ref); - git_merge_head_free(their_heads[0]); - git_merge_result_free(result); - - return 0; -} - -static size_t merge_trivial_conflict_entrycount(void) -{ - const git_index_entry *entry; - size_t count = 0; - size_t i; - - for (i = 0; i < git_index_entrycount(repo_index); i++) { - cl_assert(entry = git_index_get_byindex(repo_index, i)); - - if (git_index_entry_stage(entry) > 0) - count++; - } - - return count; -} - -/* 2ALT: ancest:(empty)+, head:*empty*, remote:remote = result:remote */ -void test_merge_workdir_trivial__2alt(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-2alt", "trivial-2alt-branch", 0)); - - cl_assert(entry = git_index_get_bypath(repo_index, "new-in-branch.txt", 0)); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - cl_assert(merge_trivial_conflict_entrycount() == 0); -} - -/* 3ALT: ancest:(empty)+, head:head, remote:*empty* = result:head */ -void test_merge_workdir_trivial__3alt(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-3alt", "trivial-3alt-branch", 0)); - - cl_assert(entry = git_index_get_bypath(repo_index, "new-in-3alt.txt", 0)); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - cl_assert(merge_trivial_conflict_entrycount() == 0); -} - -/* 4: ancest:(empty)^, head:head, remote:remote = result:no merge */ -void test_merge_workdir_trivial__4(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-4", "trivial-4-branch", 0)); - - cl_assert((entry = git_index_get_bypath(repo_index, "new-and-different.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - - cl_assert(merge_trivial_conflict_entrycount() == 2); - cl_assert(entry = git_index_get_bypath(repo_index, "new-and-different.txt", 2)); - cl_assert(entry = git_index_get_bypath(repo_index, "new-and-different.txt", 3)); -} - -/* 5ALT: ancest:*, head:head, remote:head = result:head */ -void test_merge_workdir_trivial__5alt_1(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-5alt-1", "trivial-5alt-1-branch", 0)); - - cl_assert(entry = git_index_get_bypath(repo_index, "new-and-same.txt", 0)); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - cl_assert(merge_trivial_conflict_entrycount() == 0); -} - -/* 5ALT: ancest:*, head:head, remote:head = result:head */ -void test_merge_workdir_trivial__5alt_2(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-5alt-2", "trivial-5alt-2-branch", 0)); - - cl_assert(entry = git_index_get_bypath(repo_index, "modified-to-same.txt", 0)); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - cl_assert(merge_trivial_conflict_entrycount() == 0); -} - -/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */ -void test_merge_workdir_trivial__6(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-6", "trivial-6-branch", 0)); - - cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - - cl_assert(merge_trivial_conflict_entrycount() == 1); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 1)); -} - -/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */ -void test_merge_workdir_trivial__6_automerge(void) -{ - const git_index_entry *entry; - const git_index_reuc_entry *reuc; - - cl_git_pass(merge_trivial("trivial-6", "trivial-6-branch", 1)); - - cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(repo_index) == 1); - cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "removed-in-both.txt")); - - cl_assert(merge_trivial_conflict_entrycount() == 0); -} - -/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */ -void test_merge_workdir_trivial__8(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-8", "trivial-8-branch", 0)); - - cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - - cl_assert(merge_trivial_conflict_entrycount() == 2); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 1)); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 3)); -} - -/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */ -void test_merge_workdir_trivial__8_automerge(void) -{ - const git_index_entry *entry; - const git_index_reuc_entry *reuc; - - cl_git_pass(merge_trivial("trivial-8", "trivial-8-branch", 1)); - - cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 0)) == NULL); - - cl_assert(git_index_reuc_entrycount(repo_index) == 1); - cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "removed-in-8.txt")); - - cl_assert(merge_trivial_conflict_entrycount() == 0); -} - -/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */ -void test_merge_workdir_trivial__7(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-7", "trivial-7-branch", 0)); - - cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - - cl_assert(merge_trivial_conflict_entrycount() == 2); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 1)); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 3)); -} - -/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */ -void test_merge_workdir_trivial__7_automerge(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-7", "trivial-7-branch", 0)); - - cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - - cl_assert(merge_trivial_conflict_entrycount() == 2); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 1)); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 3)); -} - -/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */ -void test_merge_workdir_trivial__10(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-10", "trivial-10-branch", 0)); - - cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - - cl_assert(merge_trivial_conflict_entrycount() == 2); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 1)); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 2)); -} - -/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */ -void test_merge_workdir_trivial__10_automerge(void) -{ - const git_index_entry *entry; - const git_index_reuc_entry *reuc; - - cl_git_pass(merge_trivial("trivial-10", "trivial-10-branch", 1)); - - cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 0)) == NULL); - - cl_assert(git_index_reuc_entrycount(repo_index) == 1); - cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "removed-in-10-branch.txt")); - - cl_assert(merge_trivial_conflict_entrycount() == 0); -} - -/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */ -void test_merge_workdir_trivial__9(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-9", "trivial-9-branch", 0)); - - cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - - cl_assert(merge_trivial_conflict_entrycount() == 2); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 1)); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 2)); -} - -/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */ -void test_merge_workdir_trivial__9_automerge(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-9", "trivial-9-branch", 1)); - - cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - - cl_assert(merge_trivial_conflict_entrycount() == 2); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 1)); - cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 2)); -} - -/* 13: ancest:ancest+, head:head, remote:ancest = result:head */ -void test_merge_workdir_trivial__13(void) -{ - const git_index_entry *entry; - git_oid expected_oid; - - cl_git_pass(merge_trivial("trivial-13", "trivial-13-branch", 0)); - - cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-13.txt", 0)); - cl_git_pass(git_oid_fromstr(&expected_oid, "1cff9ec6a47a537380dedfdd17c9e76d74259a2b")); - cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0); - - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - cl_assert(merge_trivial_conflict_entrycount() == 0); -} - -/* 14: ancest:ancest+, head:ancest, remote:remote = result:remote */ -void test_merge_workdir_trivial__14(void) -{ - const git_index_entry *entry; - git_oid expected_oid; - - cl_git_pass(merge_trivial("trivial-14", "trivial-14-branch", 0)); - - cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-14-branch.txt", 0)); - cl_git_pass(git_oid_fromstr(&expected_oid, "26153a3ff3649b6c2bb652d3f06878c6e0a172f9")); - cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0); - - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - cl_assert(merge_trivial_conflict_entrycount() == 0); -} - -/* 11: ancest:ancest+, head:head, remote:remote = result:no merge */ -void test_merge_workdir_trivial__11(void) -{ - const git_index_entry *entry; - - cl_git_pass(merge_trivial("trivial-11", "trivial-11-branch", 0)); - - cl_assert((entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 0)) == NULL); - cl_assert(git_index_reuc_entrycount(repo_index) == 0); - - cl_assert(merge_trivial_conflict_entrycount() == 3); - cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 1)); - cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 2)); - cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 3)); -} diff --git a/tests-clar/network/cred.c b/tests-clar/network/cred.c deleted file mode 100644 index 6994cc0c3..000000000 --- a/tests-clar/network/cred.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "clar_libgit2.h" - -#include "git2/cred_helpers.h" - -void test_network_cred__stock_userpass_validates_args(void) -{ - git_cred_userpass_payload payload = {0}; - - cl_git_fail(git_cred_userpass(NULL, NULL, NULL, 0, NULL)); - - payload.username = "user"; - cl_git_fail(git_cred_userpass(NULL, NULL, NULL, 0, &payload)); - - payload.username = NULL; - payload.username = "pass"; - cl_git_fail(git_cred_userpass(NULL, NULL, NULL, 0, &payload)); -} - -void test_network_cred__stock_userpass_validates_that_method_is_allowed(void) -{ - git_cred *cred; - git_cred_userpass_payload payload = {"user", "pass"}; - - cl_git_fail(git_cred_userpass(&cred, NULL, NULL, 0, &payload)); - cl_git_pass(git_cred_userpass(&cred, NULL, NULL, GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload)); - cred->free(cred); -} - -void test_network_cred__stock_userpass_properly_handles_username_in_url(void) -{ - git_cred *cred; - git_cred_userpass_plaintext *plain; - git_cred_userpass_payload payload = {"alice", "password"}; - - cl_git_pass(git_cred_userpass(&cred, NULL, NULL, GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload)); - plain = (git_cred_userpass_plaintext*)cred; - cl_assert_equal_s(plain->username, "alice"); - cred->free(cred); - - cl_git_pass(git_cred_userpass(&cred, NULL, "bob", GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload)); - plain = (git_cred_userpass_plaintext*)cred; - cl_assert_equal_s(plain->username, "alice"); - cred->free(cred); - - payload.username = NULL; - cl_git_pass(git_cred_userpass(&cred, NULL, "bob", GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload)); - plain = (git_cred_userpass_plaintext*)cred; - cl_assert_equal_s(plain->username, "bob"); - cred->free(cred); -} diff --git a/tests-clar/network/fetchlocal.c b/tests-clar/network/fetchlocal.c deleted file mode 100644 index 28c7115bf..000000000 --- a/tests-clar/network/fetchlocal.c +++ /dev/null @@ -1,88 +0,0 @@ -#include "clar_libgit2.h" - -#include "buffer.h" -#include "path.h" -#include "remote.h" - -static int transfer_cb(const git_transfer_progress *stats, void *payload) -{ - int *callcount = (int*)payload; - GIT_UNUSED(stats); - (*callcount)++; - return 0; -} - -static void cleanup_local_repo(void *path) -{ - cl_fixture_cleanup((char *)path); -} - -void test_network_fetchlocal__complete(void) -{ - git_repository *repo; - git_remote *origin; - int callcount = 0; - git_strarray refnames = {0}; - - const char *url = cl_git_fixture_url("testrepo.git"); - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - - callbacks.transfer_progress = transfer_cb; - callbacks.payload = &callcount; - - cl_set_cleanup(&cleanup_local_repo, "foo"); - cl_git_pass(git_repository_init(&repo, "foo", true)); - - cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(origin)); - cl_git_pass(git_remote_update_tips(origin)); - - cl_git_pass(git_reference_list(&refnames, repo)); - cl_assert_equal_i(19, (int)refnames.count); - cl_assert(callcount > 0); - - git_strarray_free(&refnames); - git_remote_free(origin); - git_repository_free(repo); -} - -static void cleanup_sandbox(void *unused) -{ - GIT_UNUSED(unused); - cl_git_sandbox_cleanup(); -} - -void test_network_fetchlocal__partial(void) -{ - git_repository *repo = cl_git_sandbox_init("partial-testrepo"); - git_remote *origin; - int callcount = 0; - git_strarray refnames = {0}; - const char *url; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - - callbacks.transfer_progress = transfer_cb; - callbacks.payload = &callcount; - - cl_set_cleanup(&cleanup_sandbox, NULL); - cl_git_pass(git_reference_list(&refnames, repo)); - cl_assert_equal_i(1, (int)refnames.count); - - url = cl_git_fixture_url("testrepo.git"); - cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); - git_remote_set_callbacks(origin, &callbacks); - cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(origin)); - cl_git_pass(git_remote_update_tips(origin)); - - git_strarray_free(&refnames); - - cl_git_pass(git_reference_list(&refnames, repo)); - cl_assert_equal_i(20, (int)refnames.count); /* 18 remote + 1 local */ - cl_assert(callcount > 0); - - git_strarray_free(&refnames); - git_remote_free(origin); -} diff --git a/tests-clar/network/refspecs.c b/tests-clar/network/refspecs.c deleted file mode 100644 index 676a1fa99..000000000 --- a/tests-clar/network/refspecs.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "clar_libgit2.h" -#include "refspec.h" -#include "remote.h" - -static void assert_refspec(unsigned int direction, const char *input, bool is_expected_to_be_valid) -{ - git_refspec refspec; - int error; - - error = git_refspec__parse(&refspec, input, direction == GIT_DIRECTION_FETCH); - git_refspec__free(&refspec); - - if (is_expected_to_be_valid) - cl_assert_equal_i(0, error); - else - cl_assert_equal_i(GIT_ERROR, error); -} - -void test_network_refspecs__parsing(void) -{ - // Ported from https://github.com/git/git/blob/abd2bde78bd994166900290434a2048e660dabed/t/t5511-refspec.sh - - assert_refspec(GIT_DIRECTION_PUSH, "", false); - assert_refspec(GIT_DIRECTION_PUSH, ":", true); - assert_refspec(GIT_DIRECTION_PUSH, "::", false); - assert_refspec(GIT_DIRECTION_PUSH, "+:", true); - - assert_refspec(GIT_DIRECTION_FETCH, "", true); - assert_refspec(GIT_DIRECTION_PUSH, ":", true); - assert_refspec(GIT_DIRECTION_FETCH, "::", false); - - assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*:refs/remotes/frotz/*", true); - assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*:refs/remotes/frotz", false); - assert_refspec(GIT_DIRECTION_PUSH, "refs/heads:refs/remotes/frotz/*", false); - assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/master:refs/remotes/frotz/xyzzy", true); - - /* - * These have invalid LHS, but we do not have a formal "valid sha-1 - * expression syntax checker" so they are not checked with the current - * code. They will be caught downstream anyway, but we may want to - * have tighter check later... - */ - //assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/master::refs/remotes/frotz/xyzzy", false); - //assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/maste :refs/remotes/frotz/xyzzy", false); - - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*:refs/remotes/frotz/*", true); - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*:refs/remotes/frotz", false); - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads:refs/remotes/frotz/*", false); - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/master:refs/remotes/frotz/xyzzy", true); - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/master::refs/remotes/frotz/xyzzy", false); - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/maste :refs/remotes/frotz/xyzzy", false); - - assert_refspec(GIT_DIRECTION_PUSH, "master~1:refs/remotes/frotz/backup", true); - assert_refspec(GIT_DIRECTION_FETCH, "master~1:refs/remotes/frotz/backup", false); - assert_refspec(GIT_DIRECTION_PUSH, "HEAD~4:refs/remotes/frotz/new", true); - assert_refspec(GIT_DIRECTION_FETCH, "HEAD~4:refs/remotes/frotz/new", false); - - assert_refspec(GIT_DIRECTION_PUSH, "HEAD", true); - assert_refspec(GIT_DIRECTION_FETCH, "HEAD", true); - assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/ nitfol", false); - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/ nitfol", false); - - assert_refspec(GIT_DIRECTION_PUSH, "HEAD:", false); - assert_refspec(GIT_DIRECTION_FETCH, "HEAD:", true); - assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/ nitfol:", false); - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/ nitfol:", false); - - assert_refspec(GIT_DIRECTION_PUSH, ":refs/remotes/frotz/deleteme", true); - assert_refspec(GIT_DIRECTION_FETCH, ":refs/remotes/frotz/HEAD-to-me", true); - assert_refspec(GIT_DIRECTION_PUSH, ":refs/remotes/frotz/delete me", false); - assert_refspec(GIT_DIRECTION_FETCH, ":refs/remotes/frotz/HEAD to me", false); - - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/for-linus:refs/remotes/mine/*-blah", false); - assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/for-linus:refs/remotes/mine/*-blah", false); - - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads*/for-linus:refs/remotes/mine/*", false); - assert_refspec(GIT_DIRECTION_PUSH, "refs/heads*/for-linus:refs/remotes/mine/*", false); - - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/*/for-linus:refs/remotes/mine/*", false); - assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/*/for-linus:refs/remotes/mine/*", false); - - assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/for-linus:refs/remotes/mine/*", true); - assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/for-linus:refs/remotes/mine/*", true); - - assert_refspec(GIT_DIRECTION_FETCH, "master", true); - assert_refspec(GIT_DIRECTION_PUSH, "master", true); -} diff --git a/tests-clar/network/remote/createthenload.c b/tests-clar/network/remote/createthenload.c deleted file mode 100644 index ac6cfccd3..000000000 --- a/tests-clar/network/remote/createthenload.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "clar_libgit2.h" - -static git_remote *_remote; -static git_repository *_repo; -static git_config *_config; -static char url[] = "http://github.com/libgit2/libgit2.git"; - -void test_network_remote_createthenload__initialize(void) -{ - cl_fixture_sandbox("testrepo.git"); - - cl_git_pass(git_repository_open(&_repo, "testrepo.git")); - - cl_git_pass(git_repository_config(&_config, _repo)); - cl_git_pass(git_config_set_string(_config, "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*")); - cl_git_pass(git_config_set_string(_config, "remote.origin.url", url)); - git_config_free(_config); - - cl_git_pass(git_remote_load(&_remote, _repo, "origin")); -} - -void test_network_remote_createthenload__cleanup(void) -{ - git_remote_free(_remote); - _remote = NULL; - - git_repository_free(_repo); - _repo = NULL; - - cl_fixture_cleanup("testrepo.git"); -} - -void test_network_remote_createthenload__parsing(void) -{ - cl_assert_equal_s(git_remote_name(_remote), "origin"); - cl_assert_equal_s(git_remote_url(_remote), url); -} diff --git a/tests-clar/network/remote/isvalidname.c b/tests-clar/network/remote/isvalidname.c deleted file mode 100644 index c26fbd0a5..000000000 --- a/tests-clar/network/remote/isvalidname.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "clar_libgit2.h" - -void test_network_remote_isvalidname__can_detect_invalid_formats(void) -{ - cl_assert_equal_i(false, git_remote_is_valid_name("/")); - cl_assert_equal_i(false, git_remote_is_valid_name("//")); - cl_assert_equal_i(false, git_remote_is_valid_name(".lock")); - cl_assert_equal_i(false, git_remote_is_valid_name("a.lock")); - cl_assert_equal_i(false, git_remote_is_valid_name("/no/leading/slash")); - cl_assert_equal_i(false, git_remote_is_valid_name("no/trailing/slash/")); -} - -void test_network_remote_isvalidname__wont_hopefully_choke_on_valid_formats(void) -{ - cl_assert_equal_i(true, git_remote_is_valid_name("webmatrix")); - cl_assert_equal_i(true, git_remote_is_valid_name("yishaigalatzer/rules")); -} diff --git a/tests-clar/network/remote/local.c b/tests-clar/network/remote/local.c deleted file mode 100644 index 309142925..000000000 --- a/tests-clar/network/remote/local.c +++ /dev/null @@ -1,234 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "path.h" -#include "posix.h" - -static git_repository *repo; -static git_buf file_path_buf = GIT_BUF_INIT; -static git_remote *remote; - -void test_network_remote_local__initialize(void) -{ - cl_git_pass(git_repository_init(&repo, "remotelocal/", 0)); - cl_assert(repo != NULL); -} - -void test_network_remote_local__cleanup(void) -{ - git_buf_free(&file_path_buf); - - git_remote_free(remote); - remote = NULL; - - git_repository_free(repo); - repo = NULL; - - cl_fixture_cleanup("remotelocal"); -} - -static void connect_to_local_repository(const char *local_repository) -{ - git_buf_sets(&file_path_buf, cl_git_path_url(local_repository)); - - cl_git_pass(git_remote_create_inmemory(&remote, repo, NULL, git_buf_cstr(&file_path_buf))); - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); -} - -void test_network_remote_local__connected(void) -{ - connect_to_local_repository(cl_fixture("testrepo.git")); - cl_assert(git_remote_connected(remote)); - - git_remote_disconnect(remote); - cl_assert(!git_remote_connected(remote)); -} - -void test_network_remote_local__retrieve_advertised_references(void) -{ - const git_remote_head **refs; - size_t refs_len; - - connect_to_local_repository(cl_fixture("testrepo.git")); - - cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); - - cl_assert_equal_i(refs_len, 28); -} - -void test_network_remote_local__retrieve_advertised_references_after_disconnect(void) -{ - const git_remote_head **refs; - size_t refs_len; - - connect_to_local_repository(cl_fixture("testrepo.git")); - git_remote_disconnect(remote); - - cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); - - cl_assert_equal_i(refs_len, 28); -} - -void test_network_remote_local__retrieve_advertised_references_from_spaced_repository(void) -{ - const git_remote_head **refs; - size_t refs_len; - - cl_fixture_sandbox("testrepo.git"); - cl_git_pass(p_rename("testrepo.git", "spaced testrepo.git")); - - connect_to_local_repository("spaced testrepo.git"); - - cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); - - cl_assert_equal_i(refs_len, 28); - - git_remote_free(remote); /* Disconnect from the "spaced repo" before the cleanup */ - remote = NULL; - - cl_fixture_cleanup("spaced testrepo.git"); -} - -void test_network_remote_local__nested_tags_are_completely_peeled(void) -{ - const git_remote_head **refs; - size_t refs_len, i; - - connect_to_local_repository(cl_fixture("testrepo.git")); - - cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); - - for (i = 0; i < refs_len; i++) { - if (!strcmp(refs[i]->name, "refs/tags/test^{}")) - cl_git_pass(git_oid_streq(&refs[i]->oid, "e90810b8df3e80c413d903f631643c716887138d")); - } -} - -void test_network_remote_local__shorthand_fetch_refspec0(void) -{ - const char *refspec = "master:remotes/sloppy/master"; - const char *refspec2 = "master:boh/sloppy/master"; - - git_reference *ref; - - connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_add_fetch(remote, refspec)); - cl_git_pass(git_remote_add_fetch(remote, refspec2)); - - cl_git_pass(git_remote_download(remote)); - cl_git_pass(git_remote_update_tips(remote)); - - cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/sloppy/master")); - git_reference_free(ref); - - cl_git_pass(git_reference_lookup(&ref, repo, "refs/heads/boh/sloppy/master")); - git_reference_free(ref); -} - -void test_network_remote_local__shorthand_fetch_refspec1(void) -{ - const char *refspec = "master"; - const char *refspec2 = "hard_tag"; - - git_reference *ref; - - connect_to_local_repository(cl_fixture("testrepo.git")); - git_remote_clear_refspecs(remote); - cl_git_pass(git_remote_add_fetch(remote, refspec)); - cl_git_pass(git_remote_add_fetch(remote, refspec2)); - - cl_git_pass(git_remote_download(remote)); - cl_git_pass(git_remote_update_tips(remote)); - - cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/master")); - - cl_git_fail(git_reference_lookup(&ref, repo, "refs/tags/hard_tag")); -} - -void test_network_remote_local__tagopt(void) -{ - git_reference *ref; - - connect_to_local_repository(cl_fixture("testrepo.git")); - git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL); - - cl_git_pass(git_remote_download(remote)); - cl_git_pass(git_remote_update_tips(remote)); - - - cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/master")); - - cl_git_pass(git_reference_lookup(&ref, repo, "refs/tags/hard_tag")); - git_reference_free(ref); -} - -void test_network_remote_local__push_to_bare_remote(void) -{ - /* Should be able to push to a bare remote */ - git_remote *localremote; - git_push *push; - - /* Get some commits */ - connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_add_fetch(remote, "master:master")); - cl_git_pass(git_remote_download(remote)); - cl_git_pass(git_remote_update_tips(remote)); - git_remote_disconnect(remote); - - /* Set up an empty bare repo to push into */ - { - git_repository *localbarerepo; - cl_git_pass(git_repository_init(&localbarerepo, "./localbare.git", 1)); - git_repository_free(localbarerepo); - } - - /* Connect to the bare repo */ - cl_git_pass(git_remote_create_inmemory(&localremote, repo, NULL, "./localbare.git")); - cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH)); - - /* Try to push */ - cl_git_pass(git_push_new(&push, localremote)); - cl_git_pass(git_push_add_refspec(push, "refs/heads/master:")); - cl_git_pass(git_push_finish(push)); - cl_assert(git_push_unpack_ok(push)); - - /* Clean up */ - git_push_free(push); - git_remote_free(localremote); - cl_fixture_cleanup("localbare.git"); -} - -void test_network_remote_local__push_to_non_bare_remote(void) -{ - /* Shouldn't be able to push to a non-bare remote */ - git_remote *localremote; - git_push *push; - - /* Get some commits */ - connect_to_local_repository(cl_fixture("testrepo.git")); - cl_git_pass(git_remote_add_fetch(remote, "master:master")); - cl_git_pass(git_remote_download(remote)); - cl_git_pass(git_remote_update_tips(remote)); - git_remote_disconnect(remote); - - /* Set up an empty non-bare repo to push into */ - { - git_repository *remoterepo = NULL; - cl_git_pass(git_repository_init(&remoterepo, "localnonbare", 0)); - git_repository_free(remoterepo); - } - - /* Connect to the bare repo */ - cl_git_pass(git_remote_create_inmemory(&localremote, repo, NULL, "./localnonbare")); - cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH)); - - /* Try to push */ - cl_git_pass(git_push_new(&push, localremote)); - cl_git_pass(git_push_add_refspec(push, "refs/heads/master:")); - cl_git_fail_with(git_push_finish(push), GIT_EBAREREPO); - cl_assert_equal_i(0, git_push_unpack_ok(push)); - - /* Clean up */ - git_push_free(push); - git_remote_free(localremote); - cl_fixture_cleanup("localbare.git"); -} diff --git a/tests-clar/network/remote/remotes.c b/tests-clar/network/remote/remotes.c deleted file mode 100644 index 954ded82c..000000000 --- a/tests-clar/network/remote/remotes.c +++ /dev/null @@ -1,510 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "refspec.h" -#include "remote.h" - -static git_remote *_remote; -static git_repository *_repo; -static const git_refspec *_refspec; - -void test_network_remote_remotes__initialize(void) -{ - _repo = cl_git_sandbox_init("testrepo.git"); - - cl_git_pass(git_remote_load(&_remote, _repo, "test")); - - _refspec = git_remote_get_refspec(_remote, 0); - cl_assert(_refspec != NULL); -} - -void test_network_remote_remotes__cleanup(void) -{ - git_remote_free(_remote); - _remote = NULL; - - cl_git_sandbox_cleanup(); -} - -void test_network_remote_remotes__parsing(void) -{ - git_remote *_remote2 = NULL; - - cl_assert_equal_s(git_remote_name(_remote), "test"); - cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); - cl_assert(git_remote_pushurl(_remote) == NULL); - - cl_assert_equal_s(git_remote__urlfordirection(_remote, GIT_DIRECTION_FETCH), - "git://github.com/libgit2/libgit2"); - cl_assert_equal_s(git_remote__urlfordirection(_remote, GIT_DIRECTION_PUSH), - "git://github.com/libgit2/libgit2"); - - cl_git_pass(git_remote_load(&_remote2, _repo, "test_with_pushurl")); - cl_assert_equal_s(git_remote_name(_remote2), "test_with_pushurl"); - cl_assert_equal_s(git_remote_url(_remote2), "git://github.com/libgit2/fetchlibgit2"); - cl_assert_equal_s(git_remote_pushurl(_remote2), "git://github.com/libgit2/pushlibgit2"); - - cl_assert_equal_s(git_remote__urlfordirection(_remote2, GIT_DIRECTION_FETCH), - "git://github.com/libgit2/fetchlibgit2"); - cl_assert_equal_s(git_remote__urlfordirection(_remote2, GIT_DIRECTION_PUSH), - "git://github.com/libgit2/pushlibgit2"); - - git_remote_free(_remote2); -} - -void test_network_remote_remotes__pushurl(void) -{ - cl_git_pass(git_remote_set_pushurl(_remote, "git://github.com/libgit2/notlibgit2")); - cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/notlibgit2"); - - cl_git_pass(git_remote_set_pushurl(_remote, NULL)); - cl_assert(git_remote_pushurl(_remote) == NULL); -} - -void test_network_remote_remotes__error_when_no_push_available(void) -{ - git_remote *r; - git_transport *t; - git_push *p; - - cl_git_pass(git_remote_create_inmemory(&r, _repo, NULL, cl_fixture("testrepo.git"))); - - cl_git_pass(git_transport_local(&t,r,NULL)); - - /* Make sure that push is really not available */ - t->push = NULL; - cl_git_pass(git_remote_set_transport(r, t)); - - cl_git_pass(git_remote_connect(r, GIT_DIRECTION_PUSH)); - cl_git_pass(git_push_new(&p, r)); - cl_git_pass(git_push_add_refspec(p, "refs/heads/master")); - cl_git_fail_with(git_push_finish(p), GIT_ERROR); - - git_push_free(p); - git_remote_free(r); -} - -void test_network_remote_remotes__parsing_ssh_remote(void) -{ - cl_assert( git_remote_valid_url("git@github.com:libgit2/libgit2.git") ); -} - -void test_network_remote_remotes__parsing_local_path_fails_if_path_not_found(void) -{ - cl_assert( !git_remote_valid_url("/home/git/repos/libgit2.git") ); -} - -void test_network_remote_remotes__supported_transport_methods_are_supported(void) -{ - cl_assert( git_remote_supported_url("git://github.com/libgit2/libgit2") ); -} - -void test_network_remote_remotes__unsupported_transport_methods_are_unsupported(void) -{ -#ifndef GIT_SSH - cl_assert( !git_remote_supported_url("git@github.com:libgit2/libgit2.git") ); -#endif -} - -void test_network_remote_remotes__refspec_parsing(void) -{ - cl_assert_equal_s(git_refspec_src(_refspec), "refs/heads/*"); - cl_assert_equal_s(git_refspec_dst(_refspec), "refs/remotes/test/*"); -} - -void test_network_remote_remotes__add_fetchspec(void) -{ - size_t size; - - size = git_remote_refspec_count(_remote); - - cl_git_pass(git_remote_add_fetch(_remote, "refs/*:refs/*")); - - size++; - cl_assert_equal_i((int)size, (int)git_remote_refspec_count(_remote)); - - _refspec = git_remote_get_refspec(_remote, size - 1); - cl_assert_equal_s(git_refspec_src(_refspec), "refs/*"); - cl_assert_equal_s(git_refspec_dst(_refspec), "refs/*"); - cl_assert_equal_s(git_refspec_string(_refspec), "refs/*:refs/*"); - cl_assert_equal_b(_refspec->push, false); -} - -void test_network_remote_remotes__add_pushspec(void) -{ - size_t size; - - size = git_remote_refspec_count(_remote); - - cl_git_pass(git_remote_add_push(_remote, "refs/*:refs/*")); - size++; - cl_assert_equal_i((int)size, (int)git_remote_refspec_count(_remote)); - - _refspec = git_remote_get_refspec(_remote, size - 1); - cl_assert_equal_s(git_refspec_src(_refspec), "refs/*"); - cl_assert_equal_s(git_refspec_dst(_refspec), "refs/*"); - cl_assert_equal_s(git_refspec_string(_refspec), "refs/*:refs/*"); - - cl_assert_equal_b(_refspec->push, true); -} - -void test_network_remote_remotes__save(void) -{ - git_strarray array; - const char *fetch_refspec1 = "refs/heads/ns1/*:refs/remotes/upstream/ns1/*"; - const char *fetch_refspec2 = "refs/heads/ns2/*:refs/remotes/upstream/ns2/*"; - const char *push_refspec1 = "refs/heads/ns1/*:refs/heads/ns1/*"; - const char *push_refspec2 = "refs/heads/ns2/*:refs/heads/ns2/*"; - - git_remote_free(_remote); - _remote = NULL; - - /* Set up the remote and save it to config */ - cl_git_pass(git_remote_create(&_remote, _repo, "upstream", "git://github.com/libgit2/libgit2")); - git_remote_clear_refspecs(_remote); - - cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec1)); - cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec2)); - cl_git_pass(git_remote_add_push(_remote, push_refspec1)); - cl_git_pass(git_remote_add_push(_remote, push_refspec2)); - cl_git_pass(git_remote_set_pushurl(_remote, "git://github.com/libgit2/libgit2_push")); - cl_git_pass(git_remote_save(_remote)); - git_remote_free(_remote); - _remote = NULL; - - /* Load it from config and make sure everything matches */ - cl_git_pass(git_remote_load(&_remote, _repo, "upstream")); - - cl_git_pass(git_remote_get_fetch_refspecs(&array, _remote)); - cl_assert_equal_i(2, (int)array.count); - cl_assert_equal_s(fetch_refspec1, array.strings[0]); - cl_assert_equal_s(fetch_refspec2, array.strings[1]); - git_strarray_free(&array); - - cl_git_pass(git_remote_get_push_refspecs(&array, _remote)); - cl_assert_equal_i(2, (int)array.count); - cl_assert_equal_s(push_refspec1, array.strings[0]); - cl_assert_equal_s(push_refspec2, array.strings[1]); - git_strarray_free(&array); - - cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); - cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/libgit2_push"); - - /* remove the pushurl again and see if we can save that too */ - cl_git_pass(git_remote_set_pushurl(_remote, NULL)); - cl_git_pass(git_remote_save(_remote)); - git_remote_free(_remote); - _remote = NULL; - - cl_git_pass(git_remote_load(&_remote, _repo, "upstream")); - cl_assert(git_remote_pushurl(_remote) == NULL); -} - -void test_network_remote_remotes__fnmatch(void) -{ - cl_assert(git_refspec_src_matches(_refspec, "refs/heads/master")); - cl_assert(git_refspec_src_matches(_refspec, "refs/heads/multi/level/branch")); -} - -void test_network_remote_remotes__transform(void) -{ - char ref[1024] = {0}; - - cl_git_pass(git_refspec_transform(ref, sizeof(ref), _refspec, "refs/heads/master")); - cl_assert_equal_s(ref, "refs/remotes/test/master"); -} - -void test_network_remote_remotes__transform_destination_to_source(void) -{ - char ref[1024] = {0}; - - cl_git_pass(git_refspec_rtransform(ref, sizeof(ref), _refspec, "refs/remotes/test/master")); - cl_assert_equal_s(ref, "refs/heads/master"); -} - -void test_network_remote_remotes__transform_r(void) -{ - git_buf buf = GIT_BUF_INIT; - - cl_git_pass(git_refspec_transform_r(&buf, _refspec, "refs/heads/master")); - cl_assert_equal_s(git_buf_cstr(&buf), "refs/remotes/test/master"); - git_buf_free(&buf); -} - -void test_network_remote_remotes__missing_refspecs(void) -{ - git_config *cfg; - - git_remote_free(_remote); - _remote = NULL; - - cl_git_pass(git_repository_config(&cfg, _repo)); - cl_git_pass(git_config_set_string(cfg, "remote.specless.url", "http://example.com")); - cl_git_pass(git_remote_load(&_remote, _repo, "specless")); - - git_config_free(cfg); -} - -void test_network_remote_remotes__list(void) -{ - git_strarray list; - git_config *cfg; - - cl_git_pass(git_remote_list(&list, _repo)); - cl_assert(list.count == 5); - git_strarray_free(&list); - - cl_git_pass(git_repository_config(&cfg, _repo)); - - /* Create a new remote */ - cl_git_pass(git_config_set_string(cfg, "remote.specless.url", "http://example.com")); - - /* Update a remote (previously without any url/pushurl entry) */ - cl_git_pass(git_config_set_string(cfg, "remote.no-remote-url.pushurl", "http://example.com")); - - cl_git_pass(git_remote_list(&list, _repo)); - cl_assert(list.count == 7); - git_strarray_free(&list); - - git_config_free(cfg); -} - -void test_network_remote_remotes__loading_a_missing_remote_returns_ENOTFOUND(void) -{ - git_remote_free(_remote); - _remote = NULL; - - cl_assert_equal_i(GIT_ENOTFOUND, git_remote_load(&_remote, _repo, "just-left-few-minutes-ago")); -} - -void test_network_remote_remotes__loading_with_an_invalid_name_returns_EINVALIDSPEC(void) -{ - git_remote_free(_remote); - _remote = NULL; - - cl_assert_equal_i(GIT_EINVALIDSPEC, git_remote_load(&_remote, _repo, "Inv@{id")); -} - -/* - * $ git remote add addtest http://github.com/libgit2/libgit2 - * - * $ cat .git/config - * [...] - * [remote "addtest"] - * url = http://github.com/libgit2/libgit2 - * fetch = +refs/heads/\*:refs/remotes/addtest/\* - */ -void test_network_remote_remotes__add(void) -{ - git_remote_free(_remote); - _remote = NULL; - - cl_git_pass(git_remote_create(&_remote, _repo, "addtest", "http://github.com/libgit2/libgit2")); - cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, git_remote_autotag(_remote)); - - git_remote_free(_remote); - _remote = NULL; - - cl_git_pass(git_remote_load(&_remote, _repo, "addtest")); - cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, git_remote_autotag(_remote)); - - _refspec = git_vector_get(&_remote->refspecs, 0); - cl_assert_equal_s("refs/heads/*", git_refspec_src(_refspec)); - cl_assert(git_refspec_force(_refspec) == 1); - cl_assert_equal_s("refs/remotes/addtest/*", git_refspec_dst(_refspec)); - cl_assert_equal_s(git_remote_url(_remote), "http://github.com/libgit2/libgit2"); -} - -void test_network_remote_remotes__cannot_add_a_nameless_remote(void) -{ - git_remote *remote; - - cl_assert_equal_i( - GIT_EINVALIDSPEC, - git_remote_create(&remote, _repo, NULL, "git://github.com/libgit2/libgit2")); -} - -void test_network_remote_remotes__cannot_save_an_inmemory_remote(void) -{ - git_remote *remote; - - cl_git_pass(git_remote_create_inmemory(&remote, _repo, NULL, "git://github.com/libgit2/libgit2")); - - cl_assert_equal_p(NULL, git_remote_name(remote)); - - cl_git_fail(git_remote_save(remote)); - git_remote_free(remote); -} - -void test_network_remote_remotes__cannot_add_a_remote_with_an_invalid_name(void) -{ - git_remote *remote = NULL; - - cl_assert_equal_i( - GIT_EINVALIDSPEC, - git_remote_create(&remote, _repo, "Inv@{id", "git://github.com/libgit2/libgit2")); - cl_assert_equal_p(remote, NULL); - - cl_assert_equal_i( - GIT_EINVALIDSPEC, - git_remote_create(&remote, _repo, "", "git://github.com/libgit2/libgit2")); - cl_assert_equal_p(remote, NULL); -} - -void test_network_remote_remotes__tagopt(void) -{ - const char *opt; - git_config *cfg; - - cl_git_pass(git_repository_config(&cfg, _repo)); - - git_remote_set_autotag(_remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL); - cl_git_pass(git_remote_save(_remote)); - cl_git_pass(git_config_get_string(&opt, cfg, "remote.test.tagopt")); - cl_assert_equal_s("--tags", opt); - - git_remote_set_autotag(_remote, GIT_REMOTE_DOWNLOAD_TAGS_NONE); - cl_git_pass(git_remote_save(_remote)); - cl_git_pass(git_config_get_string(&opt, cfg, "remote.test.tagopt")); - cl_assert_equal_s("--no-tags", opt); - - git_remote_set_autotag(_remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); - cl_git_pass(git_remote_save(_remote)); - cl_assert(git_config_get_string(&opt, cfg, "remote.test.tagopt") == GIT_ENOTFOUND); - - git_config_free(cfg); -} - -void test_network_remote_remotes__can_load_with_an_empty_url(void) -{ - git_remote *remote = NULL; - - cl_git_pass(git_remote_load(&remote, _repo, "empty-remote-url")); - - cl_assert(remote->url == NULL); - cl_assert(remote->pushurl == NULL); - - cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - - cl_assert(giterr_last() != NULL); - cl_assert(giterr_last()->klass == GITERR_INVALID); - - git_remote_free(remote); -} - -void test_network_remote_remotes__can_load_with_only_an_empty_pushurl(void) -{ - git_remote *remote = NULL; - - cl_git_pass(git_remote_load(&remote, _repo, "empty-remote-pushurl")); - - cl_assert(remote->url == NULL); - cl_assert(remote->pushurl == NULL); - - cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - - git_remote_free(remote); -} - -void test_network_remote_remotes__returns_ENOTFOUND_when_neither_url_nor_pushurl(void) -{ - git_remote *remote = NULL; - - cl_git_fail_with( - git_remote_load(&remote, _repo, "no-remote-url"), GIT_ENOTFOUND); -} - -void test_network_remote_remotes__check_structure_version(void) -{ - git_transport transport = GIT_TRANSPORT_INIT; - const git_error *err; - - git_remote_free(_remote); - _remote = NULL; - cl_git_pass(git_remote_create_inmemory(&_remote, _repo, NULL, "test-protocol://localhost")); - - transport.version = 0; - cl_git_fail(git_remote_set_transport(_remote, &transport)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); - - giterr_clear(); - transport.version = 1024; - cl_git_fail(git_remote_set_transport(_remote, &transport)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); -} - -void assert_cannot_create_remote(const char *name, int expected_error) -{ - git_remote *remote = NULL; - - cl_git_fail_with( - git_remote_create(&remote, _repo, name, "git://github.com/libgit2/libgit2"), - expected_error); - - cl_assert_equal_p(remote, NULL); -} - -void test_network_remote_remotes__cannot_create_a_remote_which_name_conflicts_with_an_existing_remote(void) -{ - assert_cannot_create_remote("test", GIT_EEXISTS); -} - -void test_network_remote_remotes__cannot_create_a_remote_which_name_is_invalid(void) -{ - assert_cannot_create_remote("/", GIT_EINVALIDSPEC); - assert_cannot_create_remote("//", GIT_EINVALIDSPEC); - assert_cannot_create_remote(".lock", GIT_EINVALIDSPEC); - assert_cannot_create_remote("a.lock", GIT_EINVALIDSPEC); -} - -void test_network_remote_remote__git_remote_create_with_fetchspec(void) -{ - git_remote *remote; - git_strarray array; - - cl_git_pass(git_remote_create_with_fetchspec(&remote, _repo, "test-new", "git://github.com/libgit2/libgit2", "+refs/*:refs/*")); - git_remote_get_fetch_refspecs(&array, remote); - cl_assert_equal_s("+refs/*:refs/*", array.strings[0]); - git_remote_free(remote); -} - -static const char *fetch_refspecs[] = { - "+refs/heads/*:refs/remotes/origin/*", - "refs/tags/*:refs/tags/*", - "+refs/pull/*:refs/pull/*", -}; - -static const char *push_refspecs[] = { - "refs/heads/*:refs/heads/*", - "refs/tags/*:refs/tags/*", - "refs/notes/*:refs/notes/*", -}; - -void test_network_remote_remotes__query_refspecs(void) -{ - git_remote *remote; - git_strarray array; - int i; - - cl_git_pass(git_remote_create_inmemory(&remote, _repo, NULL, "git://github.com/libgit2/libgit2")); - - for (i = 0; i < 3; i++) { - cl_git_pass(git_remote_add_fetch(remote, fetch_refspecs[i])); - cl_git_pass(git_remote_add_push(remote, push_refspecs[i])); - } - - cl_git_pass(git_remote_get_fetch_refspecs(&array, remote)); - for (i = 0; i < 3; i++) { - cl_assert_equal_s(fetch_refspecs[i], array.strings[i]); - } - git_strarray_free(&array); - - cl_git_pass(git_remote_get_push_refspecs(&array, remote)); - for (i = 0; i < 3; i++) { - cl_assert_equal_s(push_refspecs[i], array.strings[i]); - } - git_strarray_free(&array); - - git_remote_free(remote); -} diff --git a/tests-clar/network/remote/rename.c b/tests-clar/network/remote/rename.c deleted file mode 100644 index ed98ee811..000000000 --- a/tests-clar/network/remote/rename.c +++ /dev/null @@ -1,174 +0,0 @@ -#include "clar_libgit2.h" -#include "config/config_helpers.h" - -#include "repository.h" - -static git_remote *_remote; -static git_repository *_repo; - -void test_network_remote_rename__initialize(void) -{ - _repo = cl_git_sandbox_init("testrepo.git"); - - cl_git_pass(git_remote_load(&_remote, _repo, "test")); -} - -void test_network_remote_rename__cleanup(void) -{ - git_remote_free(_remote); - _remote = NULL; - - cl_git_sandbox_cleanup(); -} - -static int dont_call_me_cb(const char *fetch_refspec, void *payload) -{ - GIT_UNUSED(fetch_refspec); - GIT_UNUSED(payload); - - cl_assert(false); - - return -1; -} - -void test_network_remote_rename__renaming_a_remote_moves_related_configuration_section(void) -{ - assert_config_entry_existence(_repo, "remote.test.fetch", true); - assert_config_entry_existence(_repo, "remote.just/renamed.fetch", false); - - cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL)); - - assert_config_entry_existence(_repo, "remote.test.fetch", false); - assert_config_entry_existence(_repo, "remote.just/renamed.fetch", true); -} - -void test_network_remote_rename__renaming_a_remote_updates_branch_related_configuration_entries(void) -{ - assert_config_entry_value(_repo, "branch.master.remote", "test"); - - cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL)); - - assert_config_entry_value(_repo, "branch.master.remote", "just/renamed"); -} - -void test_network_remote_rename__renaming_a_remote_updates_default_fetchrefspec(void) -{ - cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL)); - - assert_config_entry_value(_repo, "remote.just/renamed.fetch", "+refs/heads/*:refs/remotes/just/renamed/*"); -} - -void test_network_remote_rename__renaming_a_remote_without_a_fetchrefspec_doesnt_create_one(void) -{ - git_config *config; - - git_remote_free(_remote); - cl_git_pass(git_repository_config__weakptr(&config, _repo)); - cl_git_pass(git_config_delete_entry(config, "remote.test.fetch")); - - cl_git_pass(git_remote_load(&_remote, _repo, "test")); - - assert_config_entry_existence(_repo, "remote.test.fetch", false); - - cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL)); - - assert_config_entry_existence(_repo, "remote.just/renamed.fetch", false); -} - -static int ensure_refspecs(const char* refspec_name, void *payload) -{ - int i = 0; - bool found = false; - const char ** exp = (const char **)payload; - - while (exp[i]) { - if (strcmp(exp[i++], refspec_name)) - continue; - - found = true; - break; - } - - cl_assert(found); - - return 0; -} - -void test_network_remote_rename__renaming_a_remote_notifies_of_non_default_fetchrefspec(void) -{ - git_config *config; - - char *expected_refspecs[] = { - "+refs/*:refs/*", - NULL - }; - - git_remote_free(_remote); - cl_git_pass(git_repository_config__weakptr(&config, _repo)); - cl_git_pass(git_config_set_string(config, "remote.test.fetch", "+refs/*:refs/*")); - cl_git_pass(git_remote_load(&_remote, _repo, "test")); - - cl_git_pass(git_remote_rename(_remote, "just/renamed", ensure_refspecs, &expected_refspecs)); - - assert_config_entry_value(_repo, "remote.just/renamed.fetch", "+refs/*:refs/*"); -} - -void test_network_remote_rename__new_name_can_contain_dots(void) -{ - cl_git_pass(git_remote_rename(_remote, "just.renamed", dont_call_me_cb, NULL)); - cl_assert_equal_s("just.renamed", git_remote_name(_remote)); -} - -void test_network_remote_rename__new_name_must_conform_to_reference_naming_conventions(void) -{ - cl_assert_equal_i( - GIT_EINVALIDSPEC, - git_remote_rename(_remote, "new@{name", dont_call_me_cb, NULL)); -} - -void test_network_remote_rename__renamed_name_is_persisted(void) -{ - git_remote *renamed; - git_repository *another_repo; - - cl_git_fail(git_remote_load(&renamed, _repo, "just/renamed")); - - cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL)); - - cl_git_pass(git_repository_open(&another_repo, "testrepo.git")); - cl_git_pass(git_remote_load(&renamed, _repo, "just/renamed")); - - git_remote_free(renamed); - git_repository_free(another_repo); -} - -void test_network_remote_rename__cannot_overwrite_an_existing_remote(void) -{ - cl_assert_equal_i(GIT_EEXISTS, git_remote_rename(_remote, "test", dont_call_me_cb, NULL)); - cl_assert_equal_i(GIT_EEXISTS, git_remote_rename(_remote, "test_with_pushurl", dont_call_me_cb, NULL)); -} - -void test_network_remote_rename__renaming_a_remote_moves_the_underlying_reference(void) -{ - git_reference *underlying; - - cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&underlying, _repo, "refs/remotes/just/renamed")); - cl_git_pass(git_reference_lookup(&underlying, _repo, "refs/remotes/test/master")); - git_reference_free(underlying); - - cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL)); - - cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&underlying, _repo, "refs/remotes/test/master")); - cl_git_pass(git_reference_lookup(&underlying, _repo, "refs/remotes/just/renamed/master")); - git_reference_free(underlying); -} - -void test_network_remote_rename__cannot_rename_an_inmemory_remote(void) -{ - git_remote *remote; - - cl_git_pass(git_remote_create_inmemory(&remote, _repo, NULL, "file:///blah")); - cl_git_fail(git_remote_rename(remote, "newname", NULL, NULL)); - - git_remote_free(remote); -} diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c deleted file mode 100644 index 2a9c2f69f..000000000 --- a/tests-clar/network/urlparse.c +++ /dev/null @@ -1,193 +0,0 @@ -#include "clar_libgit2.h" -#include "netops.h" - -static char *host, *port, *path, *user, *pass; -static gitno_connection_data conndata; - -void test_network_urlparse__initialize(void) -{ - host = port = path = user = pass = NULL; - memset(&conndata, 0, sizeof(conndata)); -} - -void test_network_urlparse__cleanup(void) -{ -#define FREE_AND_NULL(x) if (x) { git__free(x); x = NULL; } - FREE_AND_NULL(host); - FREE_AND_NULL(port); - FREE_AND_NULL(path); - FREE_AND_NULL(user); - FREE_AND_NULL(pass); - - gitno_connection_data_free_ptrs(&conndata); -} - -void test_network_urlparse__trivial(void) -{ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "http://example.com/resource", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "8080"); - cl_assert_equal_s(path, "/resource"); - cl_assert_equal_p(user, NULL); - cl_assert_equal_p(pass, NULL); -} - -void test_network_urlparse__encoded_password(void) -{ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://user:pass%2fis%40bad@hostname.com:1234/", "1")); - cl_assert_equal_s(host, "hostname.com"); - cl_assert_equal_s(port, "1234"); - cl_assert_equal_s(path, "/"); - cl_assert_equal_s(user, "user"); - cl_assert_equal_s(pass, "pass/is@bad"); -} - -void test_network_urlparse__user(void) -{ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://user@example.com/resource", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "8080"); - cl_assert_equal_s(path, "/resource"); - cl_assert_equal_s(user, "user"); - cl_assert_equal_p(pass, NULL); -} - -void test_network_urlparse__user_pass(void) -{ - /* user:pass@hostname.tld/resource */ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://user:pass@example.com/resource", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "8080"); - cl_assert_equal_s(path, "/resource"); - cl_assert_equal_s(user, "user"); - cl_assert_equal_s(pass, "pass"); -} - -void test_network_urlparse__port(void) -{ - /* hostname.tld:port/resource */ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://example.com:9191/resource", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "9191"); - cl_assert_equal_s(path, "/resource"); - cl_assert_equal_p(user, NULL); - cl_assert_equal_p(pass, NULL); -} - -void test_network_urlparse__user_port(void) -{ - /* user@hostname.tld:port/resource */ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://user@example.com:9191/resource", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "9191"); - cl_assert_equal_s(path, "/resource"); - cl_assert_equal_s(user, "user"); - cl_assert_equal_p(pass, NULL); -} - -void test_network_urlparse__user_pass_port(void) -{ - /* user:pass@hostname.tld:port/resource */ - cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, - "https://user:pass@example.com:9191/resource", "8080")); - cl_assert_equal_s(host, "example.com"); - cl_assert_equal_s(port, "9191"); - cl_assert_equal_s(path, "/resource"); - cl_assert_equal_s(user, "user"); - cl_assert_equal_s(pass, "pass"); -} - -void test_network_urlparse__connection_data_http(void) -{ - cl_git_pass(gitno_connection_data_from_url(&conndata, - "http://example.com/foo/bar/baz", "bar/baz")); - cl_assert_equal_s(conndata.host, "example.com"); - cl_assert_equal_s(conndata.port, "80"); - cl_assert_equal_s(conndata.path, "/foo/"); - cl_assert_equal_p(conndata.user, NULL); - cl_assert_equal_p(conndata.pass, NULL); - cl_assert_equal_i(conndata.use_ssl, false); -} - -void test_network_urlparse__connection_data_ssl(void) -{ - cl_git_pass(gitno_connection_data_from_url(&conndata, - "https://example.com/foo/bar/baz", "bar/baz")); - cl_assert_equal_s(conndata.host, "example.com"); - cl_assert_equal_s(conndata.port, "443"); - cl_assert_equal_s(conndata.path, "/foo/"); - cl_assert_equal_p(conndata.user, NULL); - cl_assert_equal_p(conndata.pass, NULL); - cl_assert_equal_i(conndata.use_ssl, true); -} - -void test_network_urlparse__encoded_username_password(void) -{ - cl_git_pass(gitno_connection_data_from_url(&conndata, - "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz", "bar/baz")); - cl_assert_equal_s(conndata.host, "example.com"); - cl_assert_equal_s(conndata.port, "443"); - cl_assert_equal_s(conndata.path, "/foo/"); - cl_assert_equal_s(conndata.user, "user/name"); - cl_assert_equal_s(conndata.pass, "pass@word%zyx%v"); - cl_assert_equal_i(conndata.use_ssl, true); -} - -void test_network_urlparse__connection_data_cross_host_redirect(void) -{ - conndata.host = git__strdup("bar.com"); - cl_git_fail_with(gitno_connection_data_from_url(&conndata, - "https://foo.com/bar/baz", NULL), - -1); -} - -void test_network_urlparse__connection_data_http_downgrade(void) -{ - conndata.use_ssl = true; - cl_git_fail_with(gitno_connection_data_from_url(&conndata, - "http://foo.com/bar/baz", NULL), - -1); -} - -void test_network_urlparse__connection_data_relative_redirect(void) -{ - cl_git_pass(gitno_connection_data_from_url(&conndata, - "http://foo.com/bar/baz/biff", NULL)); - cl_git_pass(gitno_connection_data_from_url(&conndata, - "/zap/baz/biff?bam", NULL)); - cl_assert_equal_s(conndata.host, "foo.com"); - cl_assert_equal_s(conndata.port, "80"); - cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam"); - cl_assert_equal_p(conndata.user, NULL); - cl_assert_equal_p(conndata.pass, NULL); - cl_assert_equal_i(conndata.use_ssl, false); -} - -void test_network_urlparse__connection_data_relative_redirect_ssl(void) -{ - cl_git_pass(gitno_connection_data_from_url(&conndata, - "https://foo.com/bar/baz/biff", NULL)); - cl_git_pass(gitno_connection_data_from_url(&conndata, - "/zap/baz/biff?bam", NULL)); - cl_assert_equal_s(conndata.host, "foo.com"); - cl_assert_equal_s(conndata.port, "443"); - cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam"); - cl_assert_equal_p(conndata.user, NULL); - cl_assert_equal_p(conndata.pass, NULL); - cl_assert_equal_i(conndata.use_ssl, true); -} - -/* Run this under valgrind */ -void test_network_urlparse__connection_data_cleanup(void) -{ - cl_git_pass(gitno_connection_data_from_url(&conndata, - "http://foo.com/bar/baz/biff", "baz/biff")); - cl_git_pass(gitno_connection_data_from_url(&conndata, - "https://foo.com/bar/baz/biff", "baz/biff")); -} diff --git a/tests-clar/notes/notes.c b/tests-clar/notes/notes.c deleted file mode 100644 index 82dcaf8ca..000000000 --- a/tests-clar/notes/notes.c +++ /dev/null @@ -1,387 +0,0 @@ -#include "clar_libgit2.h" - -static git_repository *_repo; -static git_signature *_sig; - -void test_notes_notes__initialize(void) -{ - _repo = cl_git_sandbox_init("testrepo.git"); - cl_git_pass(git_signature_now(&_sig, "alice", "alice@example.com")); -} - -void test_notes_notes__cleanup(void) -{ - git_signature_free(_sig); - _sig = NULL; - - cl_git_sandbox_cleanup(); -} - -static void assert_note_equal(git_note *note, char *message, git_oid *note_oid) { - git_blob *blob; - - cl_assert_equal_s(git_note_message(note), message); - cl_assert(!git_oid_cmp(git_note_oid(note), note_oid)); - - cl_git_pass(git_blob_lookup(&blob, _repo, note_oid)); - cl_assert_equal_s(git_note_message(note), (const char *)git_blob_rawcontent(blob)); - - git_blob_free(blob); -} - -static void create_note(git_oid *note_oid, const char *canonical_namespace, const char *target_sha, const char *message) -{ - git_oid oid; - - cl_git_pass(git_oid_fromstr(&oid, target_sha)); - cl_git_pass(git_note_create(note_oid, _repo, _sig, _sig, canonical_namespace, &oid, message, 0)); -} - -static struct { - const char *note_sha; - const char *annotated_object_sha; -} -list_expectations[] = { - { "1c73b1f51762155d357bcd1fd4f2c409ef80065b", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045" }, - { "1c73b1f51762155d357bcd1fd4f2c409ef80065b", "9fd738e8f7967c078dceed8190330fc8648ee56a" }, - { "257b43746b6b46caa4aa788376c647cce0a33e2b", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750" }, - { "1ec1c8e03f461f4f5d3f3702172483662e7223f3", "c47800c7266a2be04c571c04d5a6614691ea99bd" }, - { NULL, NULL } -}; - -#define EXPECTATIONS_COUNT (sizeof(list_expectations)/sizeof(list_expectations[0])) - 1 - -static int note_list_cb( - const git_oid *blob_id, const git_oid *annotated_obj_id, void *payload) -{ - git_oid expected_note_oid, expected_target_oid; - - unsigned int *count = (unsigned int *)payload; - - cl_assert(*count < EXPECTATIONS_COUNT); - - cl_git_pass(git_oid_fromstr(&expected_note_oid, list_expectations[*count].note_sha)); - cl_assert(git_oid_cmp(&expected_note_oid, blob_id) == 0); - - cl_git_pass(git_oid_fromstr(&expected_target_oid, list_expectations[*count].annotated_object_sha)); - cl_assert(git_oid_cmp(&expected_target_oid, annotated_obj_id) == 0); - - (*count)++; - - return 0; -} - -/* - * $ git notes --ref i-can-see-dead-notes add -m "I decorate a65f" a65fedf39aefe402d3bb6e24df4d4f5fe4547750 - * $ git notes --ref i-can-see-dead-notes add -m "I decorate c478" c47800c7266a2be04c571c04d5a6614691ea99bd - * $ git notes --ref i-can-see-dead-notes add -m "I decorate 9fd7 and 4a20" 9fd738e8f7967c078dceed8190330fc8648ee56a - * $ git notes --ref i-can-see-dead-notes add -m "I decorate 9fd7 and 4a20" 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 - * - * $ git notes --ref i-can-see-dead-notes list - * 1c73b1f51762155d357bcd1fd4f2c409ef80065b 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 - * 1c73b1f51762155d357bcd1fd4f2c409ef80065b 9fd738e8f7967c078dceed8190330fc8648ee56a - * 257b43746b6b46caa4aa788376c647cce0a33e2b a65fedf39aefe402d3bb6e24df4d4f5fe4547750 - * 1ec1c8e03f461f4f5d3f3702172483662e7223f3 c47800c7266a2be04c571c04d5a6614691ea99bd - * - * $ git ls-tree refs/notes/i-can-see-dead-notes - * 100644 blob 1c73b1f51762155d357bcd1fd4f2c409ef80065b 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 - * 100644 blob 1c73b1f51762155d357bcd1fd4f2c409ef80065b 9fd738e8f7967c078dceed8190330fc8648ee56a - * 100644 blob 257b43746b6b46caa4aa788376c647cce0a33e2b a65fedf39aefe402d3bb6e24df4d4f5fe4547750 - * 100644 blob 1ec1c8e03f461f4f5d3f3702172483662e7223f3 c47800c7266a2be04c571c04d5a6614691ea99bd -*/ -void test_notes_notes__can_retrieve_a_list_of_notes_for_a_given_namespace(void) -{ - git_oid note_oid1, note_oid2, note_oid3, note_oid4; - unsigned int retrieved_notes = 0; - - create_note(¬e_oid1, "refs/notes/i-can-see-dead-notes", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "I decorate a65f\n"); - create_note(¬e_oid2, "refs/notes/i-can-see-dead-notes", "c47800c7266a2be04c571c04d5a6614691ea99bd", "I decorate c478\n"); - create_note(¬e_oid3, "refs/notes/i-can-see-dead-notes", "9fd738e8f7967c078dceed8190330fc8648ee56a", "I decorate 9fd7 and 4a20\n"); - create_note(¬e_oid4, "refs/notes/i-can-see-dead-notes", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", "I decorate 9fd7 and 4a20\n"); - - cl_git_pass(git_note_foreach -(_repo, "refs/notes/i-can-see-dead-notes", note_list_cb, &retrieved_notes)); - - cl_assert_equal_i(4, retrieved_notes); -} - -static int note_cancel_cb( - const git_oid *blob_id, const git_oid *annotated_obj_id, void *payload) -{ - unsigned int *count = (unsigned int *)payload; - - GIT_UNUSED(blob_id); - GIT_UNUSED(annotated_obj_id); - - (*count)++; - - return (*count > 2); -} - -void test_notes_notes__can_cancel_foreach(void) -{ - git_oid note_oid1, note_oid2, note_oid3, note_oid4; - unsigned int retrieved_notes = 0; - - create_note(¬e_oid1, "refs/notes/i-can-see-dead-notes", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "I decorate a65f\n"); - create_note(¬e_oid2, "refs/notes/i-can-see-dead-notes", "c47800c7266a2be04c571c04d5a6614691ea99bd", "I decorate c478\n"); - create_note(¬e_oid3, "refs/notes/i-can-see-dead-notes", "9fd738e8f7967c078dceed8190330fc8648ee56a", "I decorate 9fd7 and 4a20\n"); - create_note(¬e_oid4, "refs/notes/i-can-see-dead-notes", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", "I decorate 9fd7 and 4a20\n"); - - cl_assert_equal_i( - GIT_EUSER, - git_note_foreach(_repo, "refs/notes/i-can-see-dead-notes", - note_cancel_cb, &retrieved_notes)); -} - -void test_notes_notes__retrieving_a_list_of_notes_for_an_unknown_namespace_returns_ENOTFOUND(void) -{ - int error; - unsigned int retrieved_notes = 0; - - error = git_note_foreach(_repo, "refs/notes/i-am-not", note_list_cb, &retrieved_notes); - cl_git_fail(error); - cl_assert_equal_i(GIT_ENOTFOUND, error); - - cl_assert_equal_i(0, retrieved_notes); -} - -void test_notes_notes__inserting_a_note_without_passing_a_namespace_uses_the_default_namespace(void) -{ - git_oid note_oid, target_oid; - git_note *note, *default_namespace_note; - const char *default_ref; - - cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); - cl_git_pass(git_note_default_ref(&default_ref, _repo)); - - create_note(¬e_oid, NULL, "08b041783f40edfe12bb406c9c9a8a040177c125", "hello world\n"); - - cl_git_pass(git_note_read(¬e, _repo, NULL, &target_oid)); - cl_git_pass(git_note_read(&default_namespace_note, _repo, default_ref, &target_oid)); - - assert_note_equal(note, "hello world\n", ¬e_oid); - assert_note_equal(default_namespace_note, "hello world\n", ¬e_oid); - - git_note_free(note); - git_note_free(default_namespace_note); -} - -void test_notes_notes__can_insert_a_note_with_a_custom_namespace(void) -{ - git_oid note_oid, target_oid; - git_note *note; - - cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); - - create_note(¬e_oid, "refs/notes/some/namespace", "08b041783f40edfe12bb406c9c9a8a040177c125", "hello world on a custom namespace\n"); - - cl_git_pass(git_note_read(¬e, _repo, "refs/notes/some/namespace", &target_oid)); - - assert_note_equal(note, "hello world on a custom namespace\n", ¬e_oid); - - git_note_free(note); -} - -/* - * $ git notes --ref fanout list 8496071c1b46c854b31185ea97743be6a8774479 - * 08b041783f40edfe12bb406c9c9a8a040177c125 - */ -void test_notes_notes__creating_a_note_on_a_target_which_already_has_one_returns_EEXISTS(void) -{ - int error; - git_oid note_oid, target_oid; - - cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); - - create_note(¬e_oid, NULL, "08b041783f40edfe12bb406c9c9a8a040177c125", "hello world\n"); - error = git_note_create(¬e_oid, _repo, _sig, _sig, NULL, &target_oid, "hello world\n", 0); - cl_git_fail(error); - cl_assert_equal_i(GIT_EEXISTS, error); - - create_note(¬e_oid, "refs/notes/some/namespace", "08b041783f40edfe12bb406c9c9a8a040177c125", "hello world\n"); - error = git_note_create(¬e_oid, _repo, _sig, _sig, "refs/notes/some/namespace", &target_oid, "hello world\n", 0); - cl_git_fail(error); - cl_assert_equal_i(GIT_EEXISTS, error); -} - - -void test_notes_notes__creating_a_note_on_a_target_can_overwrite_existing_note(void) -{ - git_oid note_oid, target_oid; - git_note *note, *namespace_note; - - cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); - - create_note(¬e_oid, NULL, "08b041783f40edfe12bb406c9c9a8a040177c125", "hello old world\n"); - cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, NULL, &target_oid, "hello new world\n", 1)); - - cl_git_pass(git_note_read(¬e, _repo, NULL, &target_oid)); - assert_note_equal(note, "hello new world\n", ¬e_oid); - - create_note(¬e_oid, "refs/notes/some/namespace", "08b041783f40edfe12bb406c9c9a8a040177c125", "hello old world\n"); - cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, "refs/notes/some/namespace", &target_oid, "hello new ref world\n", 1)); - - cl_git_pass(git_note_read(&namespace_note, _repo, "refs/notes/some/namespace", &target_oid)); - assert_note_equal(namespace_note, "hello new ref world\n", ¬e_oid); - - git_note_free(note); - git_note_free(namespace_note); -} - -static char *messages[] = { - "08c041783f40edfe12bb406c9c9a8a040177c125", - "96c45fbe09ab7445fc7c60fd8d17f32494399343", - "48cc7e38dcfc1ec87e70ec03e08c3e83d7a16aa1", - "24c3eaafb681c3df668f9df96f58e7b8c756eb04", - "96ca1b6ccc7858ae94684777f85ac0e7447f7040", - "7ac2db4378a08bb244a427c357e0082ee0d57ac6", - "e6cba23dbf4ef84fe35e884f017f4e24dc228572", - "c8cf3462c7d8feba716deeb2ebe6583bd54589e2", - "39c16b9834c2d665ac5f68ad91dc5b933bad8549", - "f3c582b1397df6a664224ebbaf9d4cc952706597", - "29cec67037fe8e89977474988219016ae7f342a6", - "36c4cd238bf8e82e27b740e0741b025f2e8c79ab", - "f1c45a47c02e01d5a9a326f1d9f7f756373387f8", - "4aca84406f5daee34ab513a60717c8d7b1763ead", - "84ce167da452552f63ed8407b55d5ece4901845f", - NULL -}; - -#define MESSAGES_COUNT (sizeof(messages)/sizeof(messages[0])) - 1 - -/* - * $ git ls-tree refs/notes/fanout - * 040000 tree 4b22b35d44b5a4f589edf3dc89196399771796ea 84 - * - * $ git ls-tree 4b22b35 - * 040000 tree d71aab4f9b04b45ce09bcaa636a9be6231474759 96 - * - * $ git ls-tree d71aab4 - * 100644 blob 08b041783f40edfe12bb406c9c9a8a040177c125 071c1b46c854b31185ea97743be6a8774479 - */ -void test_notes_notes__can_insert_a_note_in_an_existing_fanout(void) -{ - size_t i; - git_oid note_oid, target_oid; - git_note *_note; - - cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); - - for (i = 0; i < MESSAGES_COUNT; i++) { - cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, "refs/notes/fanout", &target_oid, messages[i], 0)); - cl_git_pass(git_note_read(&_note, _repo, "refs/notes/fanout", &target_oid)); - git_note_free(_note); - - git_oid_cpy(&target_oid, ¬e_oid); - } -} - -/* - * $ git notes --ref fanout list 8496071c1b46c854b31185ea97743be6a8774479 - * 08b041783f40edfe12bb406c9c9a8a040177c125 - */ -void test_notes_notes__can_read_a_note_in_an_existing_fanout(void) -{ - git_oid note_oid, target_oid; - git_note *note; - - cl_git_pass(git_oid_fromstr(&target_oid, "8496071c1b46c854b31185ea97743be6a8774479")); - cl_git_pass(git_note_read(¬e, _repo, "refs/notes/fanout", &target_oid)); - - cl_git_pass(git_oid_fromstr(¬e_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); - cl_assert(!git_oid_cmp(git_note_oid(note), ¬e_oid)); - - git_note_free(note); -} - -void test_notes_notes__can_remove_a_note_in_an_existing_fanout(void) -{ - git_oid target_oid; - git_note *note; - - cl_git_pass(git_oid_fromstr(&target_oid, "8496071c1b46c854b31185ea97743be6a8774479")); - cl_git_pass(git_note_remove(_repo, "refs/notes/fanout", _sig, _sig, &target_oid)); - - cl_git_fail(git_note_read(¬e, _repo, "refs/notes/fanout", &target_oid)); -} - -void test_notes_notes__removing_a_note_which_doesnt_exists_returns_ENOTFOUND(void) -{ - int error; - git_oid target_oid; - - cl_git_pass(git_oid_fromstr(&target_oid, "8496071c1b46c854b31185ea97743be6a8774479")); - cl_git_pass(git_note_remove(_repo, "refs/notes/fanout", _sig, _sig, &target_oid)); - - error = git_note_remove(_repo, "refs/notes/fanout", _sig, _sig, &target_oid); - cl_git_fail(error); - cl_assert_equal_i(GIT_ENOTFOUND, error); -} - -void test_notes_notes__can_iterate_default_namespace(void) -{ - git_note_iterator *iter; - git_note *note; - git_oid note_id, annotated_id; - git_oid note_created[2]; - const char* note_message[] = { - "I decorate a65f\n", - "I decorate c478\n" - }; - int i, err; - - create_note(¬e_created[0], "refs/notes/commits", - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", note_message[0]); - create_note(¬e_created[1], "refs/notes/commits", - "c47800c7266a2be04c571c04d5a6614691ea99bd", note_message[1]); - - cl_git_pass(git_note_iterator_new(&iter, _repo, NULL)); - - for (i = 0; (err = git_note_next(¬e_id, &annotated_id, iter)) >= 0; ++i) { - cl_git_pass(git_note_read(¬e, _repo, NULL, &annotated_id)); - cl_assert_equal_s(git_note_message(note), note_message[i]); - git_note_free(note); - } - - cl_assert_equal_i(GIT_ITEROVER, err); - cl_assert_equal_i(2, i); - git_note_iterator_free(iter); -} - -void test_notes_notes__can_iterate_custom_namespace(void) -{ - git_note_iterator *iter; - git_note *note; - git_oid note_id, annotated_id; - git_oid note_created[2]; - const char* note_message[] = { - "I decorate a65f\n", - "I decorate c478\n" - }; - int i, err; - - create_note(¬e_created[0], "refs/notes/beer", - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", note_message[0]); - create_note(¬e_created[1], "refs/notes/beer", - "c47800c7266a2be04c571c04d5a6614691ea99bd", note_message[1]); - - cl_git_pass(git_note_iterator_new(&iter, _repo, "refs/notes/beer")); - - for (i = 0; (err = git_note_next(¬e_id, &annotated_id, iter)) >= 0; ++i) { - cl_git_pass(git_note_read(¬e, _repo, "refs/notes/beer", &annotated_id)); - cl_assert_equal_s(git_note_message(note), note_message[i]); - git_note_free(note); - } - - cl_assert_equal_i(GIT_ITEROVER, err); - cl_assert_equal_i(2, i); - git_note_iterator_free(iter); -} - -void test_notes_notes__empty_iterate(void) -{ - git_note_iterator *iter; - - cl_git_fail(git_note_iterator_new(&iter, _repo, "refs/notes/commits")); -} diff --git a/tests-clar/notes/notesref.c b/tests-clar/notes/notesref.c deleted file mode 100644 index c89b71ba5..000000000 --- a/tests-clar/notes/notesref.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "clar_libgit2.h" - -#include "notes.h" - -static git_repository *_repo; -static git_note *_note; -static git_signature *_sig; -static git_config *_cfg; - -void test_notes_notesref__initialize(void) -{ - cl_fixture_sandbox("testrepo.git"); - cl_git_pass(git_repository_open(&_repo, "testrepo.git")); -} - -void test_notes_notesref__cleanup(void) -{ - git_note_free(_note); - _note = NULL; - - git_signature_free(_sig); - _sig = NULL; - - git_config_free(_cfg); - _cfg = NULL; - - git_repository_free(_repo); - _repo = NULL; - - cl_fixture_cleanup("testrepo.git"); -} - -void test_notes_notesref__config_corenotesref(void) -{ - git_oid oid, note_oid; - const char *default_ref; - - cl_git_pass(git_signature_now(&_sig, "alice", "alice@example.com")); - cl_git_pass(git_oid_fromstr(&oid, "8496071c1b46c854b31185ea97743be6a8774479")); - - cl_git_pass(git_repository_config(&_cfg, _repo)); - - cl_git_pass(git_config_set_string(_cfg, "core.notesRef", "refs/notes/mydefaultnotesref")); - - cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, NULL, &oid, "test123test\n", 0)); - - cl_git_pass(git_note_read(&_note, _repo, NULL, &oid)); - cl_assert_equal_s("test123test\n", git_note_message(_note)); - cl_assert(!git_oid_cmp(git_note_oid(_note), ¬e_oid)); - - git_note_free(_note); - - cl_git_pass(git_note_read(&_note, _repo, "refs/notes/mydefaultnotesref", &oid)); - cl_assert_equal_s("test123test\n", git_note_message(_note)); - cl_assert(!git_oid_cmp(git_note_oid(_note), ¬e_oid)); - - cl_git_pass(git_note_default_ref(&default_ref, _repo)); - cl_assert_equal_s("refs/notes/mydefaultnotesref", default_ref); - - cl_git_pass(git_config_delete_entry(_cfg, "core.notesRef")); - - cl_git_pass(git_note_default_ref(&default_ref, _repo)); - cl_assert_equal_s(GIT_NOTES_DEFAULT_REF, default_ref); -} diff --git a/tests-clar/object/blob/filter.c b/tests-clar/object/blob/filter.c deleted file mode 100644 index 0b2d6bf9e..000000000 --- a/tests-clar/object/blob/filter.c +++ /dev/null @@ -1,143 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" -#include "blob.h" -#include "buf_text.h" - -static git_repository *g_repo = NULL; - -#define CRLF_NUM_TEST_OBJECTS 9 - -static const char *g_crlf_raw[CRLF_NUM_TEST_OBJECTS] = { - "", - "foo\nbar\n", - "foo\rbar\r", - "foo\r\nbar\r\n", - "foo\nbar\rboth\r\nreversed\n\ragain\nproblems\r", - "123\n\000\001\002\003\004abc\255\254\253\r\n", - "\xEF\xBB\xBFThis is UTF-8\n", - "\xEF\xBB\xBF\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\r\n\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\r\n", - "\xFE\xFF\x00T\x00h\x00i\x00s\x00!" -}; - -static git_off_t g_crlf_raw_len[CRLF_NUM_TEST_OBJECTS] = { - -1, -1, -1, -1, -1, 17, -1, -1, 12 -}; - -static git_oid g_crlf_oids[CRLF_NUM_TEST_OBJECTS]; - -static git_buf g_crlf_filtered[CRLF_NUM_TEST_OBJECTS] = { - { "", 0, 0 }, - { "foo\nbar\n", 0, 8 }, - { "foo\rbar\r", 0, 8 }, - { "foo\nbar\n", 0, 8 }, - { "foo\nbar\rboth\nreversed\n\ragain\nproblems\r", 0, 38 }, - { "123\n\000\001\002\003\004abc\255\254\253\n", 0, 16 }, - { "\xEF\xBB\xBFThis is UTF-8\n", 0, 17 }, - { "\xEF\xBB\xBF\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\n\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\n", 0, 29 }, - { "\xFE\xFF\x00T\x00h\x00i\x00s\x00!", 0, 12 } -}; - -static git_buf_text_stats g_crlf_filtered_stats[CRLF_NUM_TEST_OBJECTS] = { - { 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 2, 0, 6, 0 }, - { 0, 0, 2, 0, 0, 6, 0 }, - { 0, 0, 2, 2, 2, 6, 0 }, - { 0, 0, 4, 4, 1, 31, 0 }, - { 0, 1, 1, 2, 1, 9, 5 }, - { GIT_BOM_UTF8, 0, 0, 1, 0, 16, 0 }, - { GIT_BOM_UTF8, 0, 2, 2, 2, 27, 0 }, - { GIT_BOM_UTF16_BE, 5, 0, 0, 0, 7, 5 }, -}; - -void test_object_blob_filter__initialize(void) -{ - int i; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) { - if (g_crlf_raw_len[i] < 0) - g_crlf_raw_len[i] = strlen(g_crlf_raw[i]); - - cl_git_pass(git_blob_create_frombuffer( - &g_crlf_oids[i], g_repo, g_crlf_raw[i], (size_t)g_crlf_raw_len[i])); - } -} - -void test_object_blob_filter__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_object_blob_filter__unfiltered(void) -{ - int i; - git_blob *blob; - - for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) { - size_t raw_len = (size_t)g_crlf_raw_len[i]; - - cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i])); - - cl_assert_equal_sz(raw_len, (size_t)git_blob_rawsize(blob)); - cl_assert_equal_i( - 0, memcmp(g_crlf_raw[i], git_blob_rawcontent(blob), raw_len)); - - git_blob_free(blob); - } -} - -void test_object_blob_filter__stats(void) -{ - int i; - git_blob *blob; - git_buf buf = GIT_BUF_INIT; - git_buf_text_stats stats; - - for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) { - cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i])); - cl_git_pass(git_blob__getbuf(&buf, blob)); - git_buf_text_gather_stats(&stats, &buf, false); - cl_assert_equal_i( - 0, memcmp(&g_crlf_filtered_stats[i], &stats, sizeof(stats))); - git_blob_free(blob); - } - - git_buf_free(&buf); -} - -void test_object_blob_filter__to_odb(void) -{ - git_filter_list *fl = NULL; - git_config *cfg; - int i; - git_blob *blob; - git_buf out = GIT_BUF_INIT; - - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_assert(cfg); - - git_attr_cache_flush(g_repo); - cl_git_append2file("empty_standard_repo/.gitattributes", "*.txt text\n"); - - cl_git_pass(git_filter_list_load( - &fl, g_repo, NULL, "filename.txt", GIT_FILTER_TO_ODB)); - cl_assert(fl != NULL); - - for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) { - cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i])); - - cl_git_pass(git_filter_list_apply_to_blob(&out, fl, blob)); - - cl_assert_equal_sz(g_crlf_filtered[i].size, out.size); - - cl_assert_equal_i( - 0, memcmp(out.ptr, g_crlf_filtered[i].ptr, out.size)); - - git_blob_free(blob); - } - - git_filter_list_free(fl); - git_buf_free(&out); - git_config_free(cfg); -} diff --git a/tests-clar/object/blob/fromchunks.c b/tests-clar/object/blob/fromchunks.c deleted file mode 100644 index 03ed4efb4..000000000 --- a/tests-clar/object/blob/fromchunks.c +++ /dev/null @@ -1,119 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "posix.h" -#include "path.h" -#include "fileops.h" - -static git_repository *repo; -static char textual_content[] = "libgit2\n\r\n\0"; - -void test_object_blob_fromchunks__initialize(void) -{ - repo = cl_git_sandbox_init("testrepo.git"); -} - -void test_object_blob_fromchunks__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -static int text_chunked_source_cb(char *content, size_t max_length, void *payload) -{ - int *count; - - GIT_UNUSED(max_length); - - count = (int *)payload; - (*count)--; - - if (*count == 0) - return 0; - - strcpy(content, textual_content); - return (int)strlen(textual_content); -} - -void test_object_blob_fromchunks__can_create_a_blob_from_a_in_memory_chunk_provider(void) -{ - git_oid expected_oid, oid; - git_object *blob; - int howmany = 7; - - cl_git_pass(git_oid_fromstr(&expected_oid, "321cbdf08803c744082332332838df6bd160f8f9")); - - cl_git_fail_with( - git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY), - GIT_ENOTFOUND); - - cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany)); - - cl_git_pass(git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY)); - cl_assert(git_oid_cmp(&expected_oid, git_object_id(blob)) == 0); - - git_object_free(blob); -} - -void test_object_blob_fromchunks__doesnot_overwrite_an_already_existing_object(void) -{ - git_buf path = GIT_BUF_INIT; - git_buf content = GIT_BUF_INIT; - git_oid expected_oid, oid; - int howmany = 7; - - cl_git_pass(git_oid_fromstr(&expected_oid, "321cbdf08803c744082332332838df6bd160f8f9")); - - cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany)); - - /* Let's replace the content of the blob file storage with something else... */ - cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/32/1cbdf08803c744082332332838df6bd160f8f9")); - cl_git_pass(p_unlink(git_buf_cstr(&path))); - cl_git_mkfile(git_buf_cstr(&path), "boom"); - - /* ...request a creation of the same blob... */ - howmany = 7; - cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany)); - - /* ...and ensure the content of the faked blob file hasn't been altered */ - cl_git_pass(git_futils_readbuffer(&content, git_buf_cstr(&path))); - cl_assert(!git__strcmp("boom", git_buf_cstr(&content))); - - git_buf_free(&path); - git_buf_free(&content); -} - -#define GITATTR "* text=auto\n" \ - "*.txt text\n" \ - "*.data binary\n" - -static void write_attributes(git_repository *repo) -{ - git_buf buf = GIT_BUF_INIT; - - cl_git_pass(git_buf_joinpath(&buf, git_repository_path(repo), "info")); - cl_git_pass(git_buf_joinpath(&buf, git_buf_cstr(&buf), "attributes")); - - cl_git_pass(git_futils_mkpath2file(git_buf_cstr(&buf), 0777)); - cl_git_rewritefile(git_buf_cstr(&buf), GITATTR); - - git_buf_free(&buf); -} - -static void assert_named_chunked_blob(const char *expected_sha, const char *fake_name) -{ - git_oid expected_oid, oid; - int howmany = 7; - - cl_git_pass(git_oid_fromstr(&expected_oid, expected_sha)); - - cl_git_pass(git_blob_create_fromchunks(&oid, repo, fake_name, text_chunked_source_cb, &howmany)); - cl_assert(git_oid_cmp(&expected_oid, &oid) == 0); -} - -void test_object_blob_fromchunks__creating_a_blob_from_chunks_honors_the_attributes_directives(void) -{ - write_attributes(repo); - - assert_named_chunked_blob("321cbdf08803c744082332332838df6bd160f8f9", "dummy.data"); - assert_named_chunked_blob("e9671e138a780833cb689753570fd10a55be84fb", "dummy.txt"); - assert_named_chunked_blob("e9671e138a780833cb689753570fd10a55be84fb", "dummy.dunno"); -} diff --git a/tests-clar/object/blob/write.c b/tests-clar/object/blob/write.c deleted file mode 100644 index 203bc67c1..000000000 --- a/tests-clar/object/blob/write.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "posix.h" -#include "path.h" -#include "fileops.h" - -static git_repository *repo; - -#define WORKDIR "empty_standard_repo" -#define BARE_REPO "testrepo.git" -#define ELSEWHERE "elsewhere" - -typedef int (*blob_creator_fn)( - git_oid *, - git_repository *, - const char *); - -void test_object_blob_write__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -static void assert_blob_creation(const char *path_to_file, const char *blob_from_path, blob_creator_fn creator) -{ - git_oid oid; - cl_git_mkfile(path_to_file, "1..2...3... Can you hear me?\n"); - - cl_must_pass(creator(&oid, repo, blob_from_path)); - cl_assert(git_oid_streq(&oid, "da5e4f20c91c81b44a7e298f3d3fb3fe2f178e32") == 0); -} - -void test_object_blob_write__can_create_a_blob_in_a_standard_repo_from_a_file_located_in_the_working_directory(void) -{ - repo = cl_git_sandbox_init(WORKDIR); - - assert_blob_creation(WORKDIR "/test.txt", "test.txt", &git_blob_create_fromworkdir); -} - -void test_object_blob_write__can_create_a_blob_in_a_standard_repo_from_a_absolute_filepath_pointing_outside_of_the_working_directory(void) -{ - git_buf full_path = GIT_BUF_INIT; - - repo = cl_git_sandbox_init(WORKDIR); - - cl_must_pass(p_mkdir(ELSEWHERE, 0777)); - cl_must_pass(git_path_prettify_dir(&full_path, ELSEWHERE, NULL)); - cl_must_pass(git_buf_puts(&full_path, "test.txt")); - - assert_blob_creation(ELSEWHERE "/test.txt", git_buf_cstr(&full_path), &git_blob_create_fromdisk); - - git_buf_free(&full_path); - cl_must_pass(git_futils_rmdir_r(ELSEWHERE, NULL, GIT_RMDIR_REMOVE_FILES)); -} - -void test_object_blob_write__can_create_a_blob_in_a_bare_repo_from_a_absolute_filepath(void) -{ - git_buf full_path = GIT_BUF_INIT; - - repo = cl_git_sandbox_init(BARE_REPO); - - cl_must_pass(p_mkdir(ELSEWHERE, 0777)); - cl_must_pass(git_path_prettify_dir(&full_path, ELSEWHERE, NULL)); - cl_must_pass(git_buf_puts(&full_path, "test.txt")); - - assert_blob_creation(ELSEWHERE "/test.txt", git_buf_cstr(&full_path), &git_blob_create_fromdisk); - - git_buf_free(&full_path); - cl_must_pass(git_futils_rmdir_r(ELSEWHERE, NULL, GIT_RMDIR_REMOVE_FILES)); -} diff --git a/tests-clar/object/cache.c b/tests-clar/object/cache.c deleted file mode 100644 index b927b2514..000000000 --- a/tests-clar/object/cache.c +++ /dev/null @@ -1,287 +0,0 @@ -#include "clar_libgit2.h" -#include "repository.h" - -static git_repository *g_repo; - -void test_object_cache__initialize(void) -{ - g_repo = NULL; -} - -void test_object_cache__cleanup(void) -{ - git_repository_free(g_repo); - g_repo = NULL; - - git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJ_BLOB, (size_t)0); -} - -static struct { - git_otype type; - const char *sha; -} g_data[] = { - /* HEAD */ - { GIT_OBJ_BLOB, "a8233120f6ad708f843d861ce2b7228ec4e3dec6" }, /* README */ - { GIT_OBJ_BLOB, "3697d64be941a53d4ae8f6a271e4e3fa56b022cc" }, /* branch_file.txt */ - { GIT_OBJ_BLOB, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd" }, /* new.txt */ - - /* refs/heads/subtrees */ - { GIT_OBJ_BLOB, "1385f264afb75a56a5bec74243be9b367ba4ca08" }, /* README */ - { GIT_OBJ_TREE, "f1425cef211cc08caa31e7b545ffb232acb098c3" }, /* ab */ - { GIT_OBJ_BLOB, "d6c93164c249c8000205dd4ec5cbca1b516d487f" }, /* ab/4.txt */ - { GIT_OBJ_TREE, "9a03079b8a8ee85a0bee58bf9be3da8b62414ed4" }, /* ab/c */ - { GIT_OBJ_BLOB, "270b8ea76056d5cad83af921837702d3e3c2924d" }, /* ab/c/3.txt */ - { GIT_OBJ_TREE, "b6361fc6a97178d8fc8639fdeed71c775ab52593" }, /* ab/de */ - { GIT_OBJ_BLOB, "e7b4ad382349ff96dd8199000580b9b1e2042eb0" }, /* ab/de/2.txt */ - { GIT_OBJ_TREE, "3259a6bd5b57fb9c1281bb7ed3167b50f224cb54" }, /* ab/de/fgh */ - { GIT_OBJ_BLOB, "1f67fc4386b2d171e0d21be1c447e12660561f9b" }, /* ab/de/fgh/1.txt */ - { GIT_OBJ_BLOB, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057" }, /* branch_file.txt */ - { GIT_OBJ_BLOB, "fa49b077972391ad58037050f2a75f74e3671e92" }, /* new.txt */ - - /* refs/heads/chomped */ - { GIT_OBJ_BLOB, "0266163a49e280c4f5ed1e08facd36a2bd716bcf" }, /* readme.txt */ - - { 0, NULL }, - { 0, NULL } -}; - -void test_object_cache__cache_everything(void) -{ - int i, start; - git_oid oid; - git_odb_object *odb_obj; - git_object *obj; - git_odb *odb; - - git_libgit2_opts( - GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJ_BLOB, (size_t)32767); - - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_repository_odb(&odb, g_repo)); - - start = (int)git_cache_size(&g_repo->objects); - - for (i = 0; g_data[i].sha != NULL; ++i) { - int count = (int)git_cache_size(&g_repo->objects); - - cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); - - /* alternate between loading raw and parsed objects */ - if ((i & 1) == 0) { - cl_git_pass(git_odb_read(&odb_obj, odb, &oid)); - cl_assert(g_data[i].type == git_odb_object_type(odb_obj)); - git_odb_object_free(odb_obj); - } else { - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - cl_assert(g_data[i].type == git_object_type(obj)); - git_object_free(obj); - } - - cl_assert_equal_i(count + 1, (int)git_cache_size(&g_repo->objects)); - } - - cl_assert_equal_i(i, (int)git_cache_size(&g_repo->objects) - start); - - git_odb_free(odb); - - for (i = 0; g_data[i].sha != NULL; ++i) { - int count = (int)git_cache_size(&g_repo->objects); - - cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - cl_assert(g_data[i].type == git_object_type(obj)); - git_object_free(obj); - - cl_assert_equal_i(count, (int)git_cache_size(&g_repo->objects)); - } -} - -void test_object_cache__cache_no_blobs(void) -{ - int i, start, nonblobs = 0; - git_oid oid; - git_odb_object *odb_obj; - git_object *obj; - git_odb *odb; - - git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJ_BLOB, (size_t)0); - - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_repository_odb(&odb, g_repo)); - - start = (int)git_cache_size(&g_repo->objects); - - for (i = 0; g_data[i].sha != NULL; ++i) { - int count = (int)git_cache_size(&g_repo->objects); - - cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); - - /* alternate between loading raw and parsed objects */ - if ((i & 1) == 0) { - cl_git_pass(git_odb_read(&odb_obj, odb, &oid)); - cl_assert(g_data[i].type == git_odb_object_type(odb_obj)); - git_odb_object_free(odb_obj); - } else { - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - cl_assert(g_data[i].type == git_object_type(obj)); - git_object_free(obj); - } - - if (g_data[i].type == GIT_OBJ_BLOB) - cl_assert_equal_i(count, (int)git_cache_size(&g_repo->objects)); - else { - cl_assert_equal_i(count + 1, (int)git_cache_size(&g_repo->objects)); - nonblobs++; - } - } - - cl_assert_equal_i(nonblobs, (int)git_cache_size(&g_repo->objects) - start); - - git_odb_free(odb); -} - -static void *cache_parsed(void *arg) -{ - int i; - git_oid oid; - git_object *obj; - - for (i = ((int *)arg)[1]; g_data[i].sha != NULL; i += 2) { - cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - cl_assert(g_data[i].type == git_object_type(obj)); - git_object_free(obj); - } - - for (i = 0; i < ((int *)arg)[1]; i += 2) { - cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - cl_assert(g_data[i].type == git_object_type(obj)); - git_object_free(obj); - } - - return arg; -} - -static void *cache_raw(void *arg) -{ - int i; - git_oid oid; - git_odb *odb; - git_odb_object *odb_obj; - - cl_git_pass(git_repository_odb(&odb, g_repo)); - - for (i = ((int *)arg)[1]; g_data[i].sha != NULL; i += 2) { - cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); - cl_git_pass(git_odb_read(&odb_obj, odb, &oid)); - cl_assert(g_data[i].type == git_odb_object_type(odb_obj)); - git_odb_object_free(odb_obj); - } - - for (i = 0; i < ((int *)arg)[1]; i += 2) { - cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); - cl_git_pass(git_odb_read(&odb_obj, odb, &oid)); - cl_assert(g_data[i].type == git_odb_object_type(odb_obj)); - git_odb_object_free(odb_obj); - } - - git_odb_free(odb); - - return arg; -} - -#define REPEAT 20 -#define THREADCOUNT 50 - -void test_object_cache__threadmania(void) -{ - int try, th, max_i; - void *data; - void *(*fn)(void *); - -#ifdef GIT_THREADS - git_thread t[THREADCOUNT]; -#endif - - for (max_i = 0; g_data[max_i].sha != NULL; ++max_i) - /* count up */; - - for (try = 0; try < REPEAT; ++try) { - - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); - - for (th = 0; th < THREADCOUNT; ++th) { - data = git__malloc(2 * sizeof(int)); - - ((int *)data)[0] = th; - ((int *)data)[1] = th % max_i; - - fn = (th & 1) ? cache_parsed : cache_raw; - -#ifdef GIT_THREADS - cl_git_pass(git_thread_create(&t[th], NULL, fn, data)); -#else - cl_assert(fn(data) == data); - git__free(data); -#endif - } - -#ifdef GIT_THREADS - for (th = 0; th < THREADCOUNT; ++th) { - cl_git_pass(git_thread_join(t[th], &data)); - cl_assert_equal_i(th, ((int *)data)[0]); - git__free(data); - } -#endif - - git_repository_free(g_repo); - g_repo = NULL; - } -} - -static void *cache_quick(void *arg) -{ - git_oid oid; - git_object *obj; - - cl_git_pass(git_oid_fromstr(&oid, g_data[4].sha)); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - cl_assert(g_data[4].type == git_object_type(obj)); - git_object_free(obj); - - return arg; -} - -void test_object_cache__fast_thread_rush(void) -{ - int try, th, data[THREADCOUNT*2]; -#ifdef GIT_THREADS - git_thread t[THREADCOUNT*2]; -#endif - - for (try = 0; try < REPEAT; ++try) { - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); - - for (th = 0; th < THREADCOUNT*2; ++th) { - data[th] = th; -#ifdef GIT_THREADS - cl_git_pass( - git_thread_create(&t[th], NULL, cache_quick, &data[th])); -#else - cl_assert(cache_quick(&data[th]) == &data[th]); -#endif - } - -#ifdef GIT_THREADS - for (th = 0; th < THREADCOUNT*2; ++th) { - void *rval; - cl_git_pass(git_thread_join(t[th], &rval)); - cl_assert_equal_i(th, *((int *)rval)); - } -#endif - - git_repository_free(g_repo); - g_repo = NULL; - } -} diff --git a/tests-clar/object/commit/commitstagedfile.c b/tests-clar/object/commit/commitstagedfile.c deleted file mode 100644 index 9867ab418..000000000 --- a/tests-clar/object/commit/commitstagedfile.c +++ /dev/null @@ -1,132 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" - -static git_repository *repo; - -void test_object_commit_commitstagedfile__initialize(void) -{ - cl_fixture("treebuilder"); - cl_git_pass(git_repository_init(&repo, "treebuilder/", 0)); - cl_assert(repo != NULL); -} - -void test_object_commit_commitstagedfile__cleanup(void) -{ - git_repository_free(repo); - repo = NULL; - - cl_fixture_cleanup("treebuilder"); -} - -void test_object_commit_commitstagedfile__generate_predictable_object_ids(void) -{ - git_index *index; - const git_index_entry *entry; - git_oid expected_blob_oid, tree_oid, expected_tree_oid, commit_oid, expected_commit_oid; - git_signature *signature; - git_tree *tree; - char buffer[128]; - - /* - * The test below replicates the following git scenario - * - * $ echo "test" > test.txt - * $ git hash-object test.txt - * 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 - * - * $ git add . - * $ git commit -m "Initial commit" - * - * $ git log - * commit 1fe3126578fc4eca68c193e4a3a0a14a0704624d - * Author: nulltoken - * Date: Wed Dec 14 08:29:03 2011 +0100 - * - * Initial commit - * - * $ git show 1fe3 --format=raw - * commit 1fe3126578fc4eca68c193e4a3a0a14a0704624d - * tree 2b297e643c551e76cfa1f93810c50811382f9117 - * author nulltoken 1323847743 +0100 - * committer nulltoken 1323847743 +0100 - * - * Initial commit - * - * diff --git a/test.txt b/test.txt - * new file mode 100644 - * index 0000000..9daeafb - * --- /dev/null - * +++ b/test.txt - * @@ -0,0 +1 @@ - * +test - * - * $ git ls-tree 2b297 - * 100644 blob 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 test.txt - */ - - cl_git_pass(git_oid_fromstr(&expected_commit_oid, "1fe3126578fc4eca68c193e4a3a0a14a0704624d")); - cl_git_pass(git_oid_fromstr(&expected_tree_oid, "2b297e643c551e76cfa1f93810c50811382f9117")); - cl_git_pass(git_oid_fromstr(&expected_blob_oid, "9daeafb9864cf43055ae93beb0afd6c7d144bfa4")); - - /* - * Add a new file to the index - */ - cl_git_mkfile("treebuilder/test.txt", "test\n"); - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add_bypath(index, "test.txt")); - - entry = git_index_get_byindex(index, 0); - - cl_assert(git_oid_cmp(&expected_blob_oid, &entry->oid) == 0); - - /* - * Information about index entry should match test file - */ - { - struct stat st; - cl_must_pass(p_lstat("treebuilder/test.txt", &st)); - cl_assert(entry->file_size == st.st_size); -#ifndef _WIN32 - /* - * Windows doesn't populate these fields, and the signage is - * wrong in the Windows version of the struct, so lets avoid - * the "comparing signed and unsigned" compilation warning in - * that case. - */ - cl_assert(entry->uid == st.st_uid); - cl_assert(entry->gid == st.st_gid); -#endif - } - - /* - * Build the tree from the index - */ - cl_git_pass(git_index_write_tree(&tree_oid, index)); - - cl_assert(git_oid_cmp(&expected_tree_oid, &tree_oid) == 0); - - /* - * Commit the staged file - */ - cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); - cl_git_pass(git_tree_lookup(&tree, repo, &tree_oid)); - - cl_assert_equal_i(16, git_message_prettify(buffer, 128, "Initial commit", 0)); - - cl_git_pass(git_commit_create_v( - &commit_oid, - repo, - "HEAD", - signature, - signature, - NULL, - buffer, - tree, - 0)); - - cl_assert(git_oid_cmp(&expected_commit_oid, &commit_oid) == 0); - - git_signature_free(signature); - git_tree_free(tree); - git_index_free(index); -} diff --git a/tests-clar/object/lookup.c b/tests-clar/object/lookup.c deleted file mode 100644 index cfa6d4678..000000000 --- a/tests-clar/object/lookup.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "clar_libgit2.h" - -#include "repository.h" - -static git_repository *g_repo; - -void test_object_lookup__initialize(void) -{ - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); -} - -void test_object_lookup__cleanup(void) -{ - git_repository_free(g_repo); - g_repo = NULL; -} - -void test_object_lookup__lookup_wrong_type_returns_enotfound(void) -{ - const char *commit = "e90810b8df3e80c413d903f631643c716887138d"; - git_oid oid; - git_object *object; - - cl_git_pass(git_oid_fromstr(&oid, commit)); - cl_assert_equal_i( - GIT_ENOTFOUND, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_TAG)); -} - -void test_object_lookup__lookup_nonexisting_returns_enotfound(void) -{ - const char *unknown = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; - git_oid oid; - git_object *object; - - cl_git_pass(git_oid_fromstr(&oid, unknown)); - cl_assert_equal_i( - GIT_ENOTFOUND, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_ANY)); -} - -void test_object_lookup__lookup_wrong_type_by_abbreviated_id_returns_enotfound(void) -{ - const char *commit = "e90810b"; - git_oid oid; - git_object *object; - - cl_git_pass(git_oid_fromstrn(&oid, commit, strlen(commit))); - cl_assert_equal_i( - GIT_ENOTFOUND, git_object_lookup_prefix(&object, g_repo, &oid, strlen(commit), GIT_OBJ_TAG)); -} - -void test_object_lookup__lookup_wrong_type_eventually_returns_enotfound(void) -{ - const char *commit = "e90810b8df3e80c413d903f631643c716887138d"; - git_oid oid; - git_object *object; - - cl_git_pass(git_oid_fromstr(&oid, commit)); - - cl_git_pass(git_object_lookup(&object, g_repo, &oid, GIT_OBJ_COMMIT)); - git_object_free(object); - - cl_assert_equal_i( - GIT_ENOTFOUND, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_TAG)); -} - diff --git a/tests-clar/object/lookupbypath.c b/tests-clar/object/lookupbypath.c deleted file mode 100644 index 31aac7647..000000000 --- a/tests-clar/object/lookupbypath.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "clar_libgit2.h" - -#include "repository.h" - -static git_repository *g_repo; -static git_tree *g_root_tree; -static git_commit *g_head_commit; -static git_object *g_expectedobject, - *g_actualobject; - -void test_object_lookupbypath__initialize(void) -{ - git_reference *head; - git_tree_entry *tree_entry; - - cl_git_pass(git_repository_open(&g_repo, cl_fixture("attr/.gitted"))); - - cl_git_pass(git_repository_head(&head, g_repo)); - cl_git_pass(git_reference_peel((git_object**)&g_head_commit, head, GIT_OBJ_COMMIT)); - cl_git_pass(git_commit_tree(&g_root_tree, g_head_commit)); - cl_git_pass(git_tree_entry_bypath(&tree_entry, g_root_tree, "subdir/subdir_test2.txt")); - cl_git_pass(git_object_lookup(&g_expectedobject, g_repo, git_tree_entry_id(tree_entry), - GIT_OBJ_ANY)); - - git_tree_entry_free(tree_entry); - git_reference_free(head); - - g_actualobject = NULL; -} -void test_object_lookupbypath__cleanup(void) -{ - git_object_free(g_actualobject); - git_object_free(g_expectedobject); - git_tree_free(g_root_tree); - git_commit_free(g_head_commit); - g_expectedobject = NULL; - git_repository_free(g_repo); - g_repo = NULL; -} - -void test_object_lookupbypath__errors(void) -{ - cl_assert_equal_i(GIT_EINVALIDSPEC, - git_object_lookup_bypath(&g_actualobject, (git_object*)g_root_tree, - "subdir/subdir_test2.txt", GIT_OBJ_TREE)); // It's not a tree - cl_assert_equal_i(GIT_ENOTFOUND, - git_object_lookup_bypath(&g_actualobject, (git_object*)g_root_tree, - "file/doesnt/exist", GIT_OBJ_ANY)); -} - -void test_object_lookupbypath__from_root_tree(void) -{ - cl_git_pass(git_object_lookup_bypath(&g_actualobject, (git_object*)g_root_tree, - "subdir/subdir_test2.txt", GIT_OBJ_BLOB)); - cl_assert_equal_i(0, git_oid_cmp(git_object_id(g_expectedobject), - git_object_id(g_actualobject))); -} - -void test_object_lookupbypath__from_head_commit(void) -{ - cl_git_pass(git_object_lookup_bypath(&g_actualobject, (git_object*)g_head_commit, - "subdir/subdir_test2.txt", GIT_OBJ_BLOB)); - cl_assert_equal_i(0, git_oid_cmp(git_object_id(g_expectedobject), - git_object_id(g_actualobject))); -} - -void test_object_lookupbypath__from_subdir_tree(void) -{ - git_tree_entry *entry = NULL; - git_tree *tree = NULL; - - cl_git_pass(git_tree_entry_bypath(&entry, g_root_tree, "subdir")); - cl_git_pass(git_tree_lookup(&tree, g_repo, git_tree_entry_id(entry))); - - cl_git_pass(git_object_lookup_bypath(&g_actualobject, (git_object*)tree, - "subdir_test2.txt", GIT_OBJ_BLOB)); - cl_assert_equal_i(0, git_oid_cmp(git_object_id(g_expectedobject), - git_object_id(g_actualobject))); - - git_tree_entry_free(entry); - git_tree_free(tree); -} - diff --git a/tests-clar/object/message.c b/tests-clar/object/message.c deleted file mode 100644 index 7ef6374b3..000000000 --- a/tests-clar/object/message.c +++ /dev/null @@ -1,236 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "message.h" - -static void assert_message_prettifying(char *expected_output, char *input, int strip_comments) -{ - git_buf prettified_message = GIT_BUF_INIT; - - git_message__prettify(&prettified_message, input, strip_comments); - cl_assert_equal_s(expected_output, git_buf_cstr(&prettified_message)); - - git_buf_free(&prettified_message); -} - -#define t40 "A quick brown fox jumps over the lazy do" -#define s40 " " -#define sss s40 s40 s40 s40 s40 s40 s40 s40 s40 s40 // # 400 -#define ttt t40 t40 t40 t40 t40 t40 t40 t40 t40 t40 // # 400 - -/* Ported from git.git */ -/* see https://github.com/git/git/blob/master/t/t0030-stripspace.sh */ -void test_object_message__long_lines_without_spaces_should_be_unchanged(void) -{ - assert_message_prettifying(ttt "\n", ttt, 0); - assert_message_prettifying(ttt ttt "\n", ttt ttt, 0); - assert_message_prettifying(ttt ttt ttt "\n", ttt ttt ttt, 0); - assert_message_prettifying(ttt ttt ttt ttt "\n", ttt ttt ttt ttt, 0); -} - -void test_object_message__lines_with_spaces_at_the_beginning_should_be_unchanged(void) -{ - assert_message_prettifying(sss ttt "\n", sss ttt, 0); - assert_message_prettifying(sss sss ttt "\n", sss sss ttt, 0); - assert_message_prettifying(sss sss sss ttt "\n", sss sss sss ttt, 0); -} - -void test_object_message__lines_with_intermediate_spaces_should_be_unchanged(void) -{ - assert_message_prettifying(ttt sss ttt "\n", ttt sss ttt, 0); - assert_message_prettifying(ttt sss sss ttt "\n", ttt sss sss ttt, 0); -} - -void test_object_message__consecutive_blank_lines_should_be_unified(void) -{ - assert_message_prettifying(ttt "\n\n" ttt "\n", ttt "\n\n\n\n\n" ttt "\n", 0); - assert_message_prettifying(ttt ttt "\n\n" ttt "\n", ttt ttt "\n\n\n\n\n" ttt "\n", 0); - assert_message_prettifying(ttt ttt ttt "\n\n" ttt "\n", ttt ttt ttt "\n\n\n\n\n" ttt "\n", 0); - - assert_message_prettifying(ttt "\n\n" ttt ttt "\n", ttt "\n\n\n\n\n" ttt ttt "\n", 0); - assert_message_prettifying(ttt "\n\n" ttt ttt ttt "\n", ttt "\n\n\n\n\n" ttt ttt ttt "\n", 0); - - assert_message_prettifying(ttt "\n\n" ttt "\n", ttt "\n\t\n \n\n \t\t\n" ttt "\n", 0); - assert_message_prettifying(ttt ttt "\n\n" ttt "\n", ttt ttt "\n\t\n \n\n \t\t\n" ttt "\n", 0); - assert_message_prettifying(ttt ttt ttt "\n\n" ttt "\n", ttt ttt ttt "\n\t\n \n\n \t\t\n" ttt "\n", 0); - - assert_message_prettifying(ttt "\n\n" ttt ttt "\n", ttt "\n\t\n \n\n \t\t\n" ttt ttt "\n", 0); - assert_message_prettifying(ttt "\n\n" ttt ttt ttt "\n", ttt "\n\t\n \n\n \t\t\n" ttt ttt ttt "\n", 0); -} - -void test_object_message__only_consecutive_blank_lines_should_be_completely_removed(void) -{ - assert_message_prettifying("", "\n", 0); - assert_message_prettifying("", "\n\n\n", 0); - assert_message_prettifying("", sss "\n" sss "\n" sss "\n", 0); - assert_message_prettifying("", sss sss "\n" sss "\n\n", 0); -} - -void test_object_message__consecutive_blank_lines_at_the_beginning_should_be_removed(void) -{ - assert_message_prettifying(ttt "\n", "\n" ttt "\n", 0); - assert_message_prettifying(ttt "\n", "\n\n\n" ttt "\n", 0); - assert_message_prettifying(ttt ttt "\n", "\n\n\n" ttt ttt "\n", 0); - assert_message_prettifying(ttt ttt ttt "\n", "\n\n\n" ttt ttt ttt "\n", 0); - assert_message_prettifying(ttt ttt ttt ttt "\n", "\n\n\n" ttt ttt ttt ttt "\n", 0); - assert_message_prettifying(ttt "\n", sss "\n" sss "\n" sss "\n" ttt "\n", 0); - assert_message_prettifying(ttt "\n", "\n" sss "\n" sss sss "\n" ttt "\n", 0); - assert_message_prettifying(ttt "\n", sss sss "\n" sss "\n\n" ttt "\n", 0); - assert_message_prettifying(ttt "\n", sss sss sss "\n\n\n" ttt "\n", 0); - assert_message_prettifying(ttt "\n", "\n" sss sss sss "\n\n" ttt "\n", 0); - assert_message_prettifying(ttt "\n", "\n\n" sss sss sss "\n" ttt "\n", 0); -} - -void test_object_message__consecutive_blank_lines_at_the_end_should_be_removed(void) -{ - assert_message_prettifying(ttt "\n", ttt "\n\n", 0); - assert_message_prettifying(ttt "\n", ttt "\n\n\n\n", 0); - assert_message_prettifying(ttt ttt "\n", ttt ttt "\n\n\n\n", 0); - assert_message_prettifying(ttt ttt ttt "\n", ttt ttt ttt "\n\n\n\n", 0); - assert_message_prettifying(ttt ttt ttt ttt "\n", ttt ttt ttt ttt "\n\n\n\n", 0); - assert_message_prettifying(ttt "\n", ttt "\n" sss "\n" sss "\n" sss "\n", 0); - assert_message_prettifying(ttt "\n", ttt "\n\n" sss "\n" sss sss "\n", 0); - assert_message_prettifying(ttt "\n", ttt "\n" sss sss "\n" sss "\n\n", 0); - assert_message_prettifying(ttt "\n", ttt "\n" sss sss sss "\n\n\n", 0); - assert_message_prettifying(ttt "\n", ttt "\n\n" sss sss sss "\n\n", 0); - assert_message_prettifying(ttt "\n", ttt "\n\n\n" sss sss sss "\n\n", 0); -} - -void test_object_message__text_without_newline_at_end_should_end_with_newline(void) -{ - assert_message_prettifying(ttt "\n", ttt, 0); - assert_message_prettifying(ttt ttt "\n", ttt ttt, 0); - assert_message_prettifying(ttt ttt ttt "\n", ttt ttt ttt, 0); - assert_message_prettifying(ttt ttt ttt ttt "\n", ttt ttt ttt ttt, 0); -} - -void test_object_message__text_plus_spaces_without_newline_should_not_show_spaces_and_end_with_newline(void) -{ - assert_message_prettifying(ttt "\n", ttt sss, 0); - assert_message_prettifying(ttt ttt "\n", ttt ttt sss, 0); - assert_message_prettifying(ttt ttt ttt "\n", ttt ttt ttt sss, 0); - assert_message_prettifying(ttt "\n", ttt sss sss, 0); - assert_message_prettifying(ttt ttt "\n", ttt ttt sss sss, 0); - assert_message_prettifying(ttt "\n", ttt sss sss sss, 0); -} - -void test_object_message__text_plus_spaces_ending_with_newline_should_be_cleaned_and_newline_must_remain(void){ - assert_message_prettifying(ttt "\n", ttt sss "\n", 0); - assert_message_prettifying(ttt "\n", ttt sss sss "\n", 0); - assert_message_prettifying(ttt "\n", ttt sss sss sss "\n", 0); - assert_message_prettifying(ttt ttt "\n", ttt ttt sss "\n", 0); - assert_message_prettifying(ttt ttt "\n", ttt ttt sss sss "\n", 0); - assert_message_prettifying(ttt ttt ttt "\n", ttt ttt ttt sss "\n", 0); -} - -void test_object_message__spaces_with_newline_at_end_should_be_replaced_with_empty_string(void) -{ - assert_message_prettifying("", sss "\n", 0); - assert_message_prettifying("", sss sss "\n", 0); - assert_message_prettifying("", sss sss sss "\n", 0); - assert_message_prettifying("", sss sss sss sss "\n", 0); -} - -void test_object_message__spaces_without_newline_at_end_should_be_replaced_with_empty_string(void) -{ - assert_message_prettifying("", "", 0); - assert_message_prettifying("", sss sss, 0); - assert_message_prettifying("", sss sss sss, 0); - assert_message_prettifying("", sss sss sss sss, 0); -} - -void test_object_message__consecutive_text_lines_should_be_unchanged(void) -{ - assert_message_prettifying(ttt ttt "\n" ttt "\n", ttt ttt "\n" ttt "\n", 0); - assert_message_prettifying(ttt "\n" ttt ttt "\n" ttt "\n", ttt "\n" ttt ttt "\n" ttt "\n", 0); - assert_message_prettifying(ttt "\n" ttt "\n" ttt "\n" ttt ttt "\n", ttt "\n" ttt "\n" ttt "\n" ttt ttt "\n", 0); - assert_message_prettifying(ttt "\n" ttt "\n\n" ttt ttt "\n" ttt "\n", ttt "\n" ttt "\n\n" ttt ttt "\n" ttt "\n", 0); - assert_message_prettifying(ttt ttt "\n\n" ttt "\n" ttt ttt "\n", ttt ttt "\n\n" ttt "\n" ttt ttt "\n", 0); - assert_message_prettifying(ttt "\n" ttt ttt "\n\n" ttt "\n", ttt "\n" ttt ttt "\n\n" ttt "\n", 0); -} - -void test_object_message__strip_comments(void) -{ - assert_message_prettifying("", "# comment", 1); - assert_message_prettifying("", "# comment\n", 1); - assert_message_prettifying("", "# comment \n", 1); - - assert_message_prettifying(ttt "\n", ttt "\n" "# comment\n", 1); - assert_message_prettifying(ttt "\n", "# comment\n" ttt "\n", 1); - assert_message_prettifying(ttt "\n" ttt "\n", ttt "\n" "# comment\n" ttt "\n", 1); -} - -void test_object_message__keep_comments(void) -{ - assert_message_prettifying("# comment\n", "# comment", 0); - assert_message_prettifying("# comment\n", "# comment\n", 0); - assert_message_prettifying("# comment\n", "# comment \n", 0); - - assert_message_prettifying(ttt "\n" "# comment\n", ttt "\n" "# comment\n", 0); - assert_message_prettifying("# comment\n" ttt "\n", "# comment\n" ttt "\n", 0); - assert_message_prettifying(ttt "\n" "# comment\n" ttt "\n", ttt "\n" "# comment\n" ttt "\n", 0); -} - -void test_object_message__message_prettify(void) -{ - char buffer[100]; - - cl_assert(git_message_prettify(buffer, sizeof(buffer), "", 0) == 1); - cl_assert_equal_s(buffer, ""); - cl_assert(git_message_prettify(buffer, sizeof(buffer), "", 1) == 1); - cl_assert_equal_s(buffer, ""); - - cl_assert_equal_i(7, git_message_prettify(buffer, sizeof(buffer), "Short", 0)); - cl_assert_equal_s("Short\n", buffer); - cl_assert_equal_i(7, git_message_prettify(buffer, sizeof(buffer), "Short", 1)); - cl_assert_equal_s("Short\n", buffer); - - cl_assert(git_message_prettify(buffer, sizeof(buffer), "This is longer\nAnd multiline\n# with some comments still in\n", 0) > 0); - cl_assert_equal_s(buffer, "This is longer\nAnd multiline\n# with some comments still in\n"); - - cl_assert(git_message_prettify(buffer, sizeof(buffer), "This is longer\nAnd multiline\n# with some comments still in\n", 1) > 0); - cl_assert_equal_s(buffer, "This is longer\nAnd multiline\n"); - - /* try out overflow */ - cl_assert(git_message_prettify(buffer, sizeof(buffer), - "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" - "1234567890" "1234567890" "1234567890" "1234567890" "12345678", - 0) > 0); - cl_assert_equal_s(buffer, - "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" - "1234567890" "1234567890" "1234567890" "1234567890" "12345678\n"); - - cl_assert(git_message_prettify(buffer, sizeof(buffer), - "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" - "1234567890" "1234567890" "1234567890" "1234567890" "12345678\n", - 0) > 0); - cl_assert_equal_s(buffer, - "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" - "1234567890" "1234567890" "1234567890" "1234567890" "12345678\n"); - - cl_git_fail(git_message_prettify(buffer, sizeof(buffer), - "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" - "1234567890" "1234567890" "1234567890" "1234567890" "123456789", - 0)); - cl_git_fail(git_message_prettify(buffer, sizeof(buffer), - "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" - "1234567890" "1234567890" "1234567890" "1234567890" "123456789\n", - 0)); - cl_git_fail(git_message_prettify(buffer, sizeof(buffer), - "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" - "1234567890" "1234567890" "1234567890" "1234567890" "1234567890", - 0)); - cl_git_fail(git_message_prettify(buffer, sizeof(buffer), - "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" - "1234567890" "1234567890" "1234567890" "1234567890" "1234567890""x", - 0)); - - cl_assert(git_message_prettify(buffer, sizeof(buffer), - "1234567890" "1234567890" "1234567890" "1234567890" "1234567890\n" - "# 1234567890" "1234567890" "1234567890" "1234567890" "1234567890\n" - "1234567890", - 1) > 0); - - cl_assert(git_message_prettify(NULL, 0, "", 0) == 1); - cl_assert(git_message_prettify(NULL, 0, "Short test", 0) == 12); - cl_assert(git_message_prettify(NULL, 0, "Test\n# with\nComments", 1) == 15); -} diff --git a/tests-clar/object/peel.c b/tests-clar/object/peel.c deleted file mode 100644 index b6c9c7a3b..000000000 --- a/tests-clar/object/peel.c +++ /dev/null @@ -1,105 +0,0 @@ -#include "clar_libgit2.h" - -static git_repository *g_repo; - -void test_object_peel__initialize(void) -{ - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); -} - -void test_object_peel__cleanup(void) -{ - git_repository_free(g_repo); - g_repo = NULL; -} - -static void assert_peel( - const char *sha, - git_otype requested_type, - const char* expected_sha, - git_otype expected_type) -{ - git_oid oid, expected_oid; - git_object *obj; - git_object *peeled; - - cl_git_pass(git_oid_fromstr(&oid, sha)); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - - cl_git_pass(git_object_peel(&peeled, obj, requested_type)); - - cl_git_pass(git_oid_fromstr(&expected_oid, expected_sha)); - cl_assert_equal_i(0, git_oid_cmp(&expected_oid, git_object_id(peeled))); - - cl_assert_equal_i(expected_type, git_object_type(peeled)); - - git_object_free(peeled); - git_object_free(obj); -} - -static void assert_peel_error(int error, const char *sha, git_otype requested_type) -{ - git_oid oid; - git_object *obj; - git_object *peeled; - - cl_git_pass(git_oid_fromstr(&oid, sha)); - cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); - - cl_assert_equal_i(error, git_object_peel(&peeled, obj, requested_type)); - - git_object_free(obj); -} - -void test_object_peel__peeling_an_object_into_its_own_type_returns_another_instance_of_it(void) -{ - assert_peel("e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_COMMIT, - "e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_COMMIT); - assert_peel("7b4384978d2493e851f9cca7858815fac9b10980", GIT_OBJ_TAG, - "7b4384978d2493e851f9cca7858815fac9b10980", GIT_OBJ_TAG); - assert_peel("53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE, - "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE); - assert_peel("0266163a49e280c4f5ed1e08facd36a2bd716bcf", GIT_OBJ_BLOB, - "0266163a49e280c4f5ed1e08facd36a2bd716bcf", GIT_OBJ_BLOB); -} - -void test_object_peel__can_peel_a_tag(void) -{ - assert_peel("7b4384978d2493e851f9cca7858815fac9b10980", GIT_OBJ_COMMIT, - "e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_COMMIT); - assert_peel("7b4384978d2493e851f9cca7858815fac9b10980", GIT_OBJ_TREE, - "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE); -} - -void test_object_peel__can_peel_a_commit(void) -{ - assert_peel("e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_TREE, - "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE); -} - -void test_object_peel__cannot_peel_a_tree(void) -{ - assert_peel_error(GIT_EAMBIGUOUS, "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_BLOB); -} - -void test_object_peel__cannot_peel_a_blob(void) -{ - assert_peel_error(GIT_ENOTFOUND, "0266163a49e280c4f5ed1e08facd36a2bd716bcf", GIT_OBJ_COMMIT); -} - -void test_object_peel__target_any_object_for_type_change(void) -{ - /* tag to commit */ - assert_peel("7b4384978d2493e851f9cca7858815fac9b10980", GIT_OBJ_ANY, - "e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_COMMIT); - - /* commit to tree */ - assert_peel("e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_ANY, - "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE); - - /* fail to peel tree */ - assert_peel_error(GIT_EAMBIGUOUS, "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_ANY); - - /* fail to peel blob */ - assert_peel_error(GIT_ENOTFOUND, "0266163a49e280c4f5ed1e08facd36a2bd716bcf", GIT_OBJ_ANY); -} diff --git a/tests-clar/object/raw/chars.c b/tests-clar/object/raw/chars.c deleted file mode 100644 index 206bf7119..000000000 --- a/tests-clar/object/raw/chars.c +++ /dev/null @@ -1,41 +0,0 @@ - -#include "clar_libgit2.h" - -#include "odb.h" - -void test_object_raw_chars__find_invalid_chars_in_oid(void) -{ - git_oid out; - unsigned char exp[] = { - 0x16, 0xa6, 0x77, 0x70, 0xb7, - 0xd8, 0xd7, 0x23, 0x17, 0xc4, - 0xb7, 0x75, 0x21, 0x3c, 0x23, - 0xa8, 0xbd, 0x74, 0xf5, 0xe0, - }; - char in[41] = "16a67770b7d8d72317c4b775213c23a8bd74f5e0"; - unsigned int i; - - for (i = 0; i < 256; i++) { - in[38] = (char)i; - if (git__fromhex(i) >= 0) { - exp[19] = (unsigned char)(git__fromhex(i) << 4); - cl_git_pass(git_oid_fromstr(&out, in)); - cl_assert(memcmp(out.id, exp, sizeof(out.id)) == 0); - } else { - cl_git_fail(git_oid_fromstr(&out, in)); - } - } -} - -void test_object_raw_chars__build_valid_oid_from_raw_bytes(void) -{ - git_oid out; - unsigned char exp[] = { - 0x16, 0xa6, 0x77, 0x70, 0xb7, - 0xd8, 0xd7, 0x23, 0x17, 0xc4, - 0xb7, 0x75, 0x21, 0x3c, 0x23, - 0xa8, 0xbd, 0x74, 0xf5, 0xe0, - }; - git_oid_fromraw(&out, exp); - cl_git_pass(memcmp(out.id, exp, sizeof(out.id))); -} diff --git a/tests-clar/object/raw/compare.c b/tests-clar/object/raw/compare.c deleted file mode 100644 index 1c9ce4b81..000000000 --- a/tests-clar/object/raw/compare.c +++ /dev/null @@ -1,124 +0,0 @@ - -#include "clar_libgit2.h" - -#include "odb.h" - -void test_object_raw_compare__succeed_on_copy_oid(void) -{ - git_oid a, b; - unsigned char exp[] = { - 0x16, 0xa6, 0x77, 0x70, 0xb7, - 0xd8, 0xd7, 0x23, 0x17, 0xc4, - 0xb7, 0x75, 0x21, 0x3c, 0x23, - 0xa8, 0xbd, 0x74, 0xf5, 0xe0, - }; - memset(&b, 0, sizeof(b)); - git_oid_fromraw(&a, exp); - git_oid_cpy(&b, &a); - cl_git_pass(memcmp(a.id, exp, sizeof(a.id))); -} - -void test_object_raw_compare__succeed_on_oid_comparison_lesser(void) -{ - git_oid a, b; - unsigned char a_in[] = { - 0x16, 0xa6, 0x77, 0x70, 0xb7, - 0xd8, 0xd7, 0x23, 0x17, 0xc4, - 0xb7, 0x75, 0x21, 0x3c, 0x23, - 0xa8, 0xbd, 0x74, 0xf5, 0xe0, - }; - unsigned char b_in[] = { - 0x16, 0xa6, 0x77, 0x70, 0xb7, - 0xd8, 0xd7, 0x23, 0x17, 0xc4, - 0xb7, 0x75, 0x21, 0x3c, 0x23, - 0xa8, 0xbd, 0x74, 0xf5, 0xf0, - }; - git_oid_fromraw(&a, a_in); - git_oid_fromraw(&b, b_in); - cl_assert(git_oid_cmp(&a, &b) < 0); -} - -void test_object_raw_compare__succeed_on_oid_comparison_equal(void) -{ - git_oid a, b; - unsigned char a_in[] = { - 0x16, 0xa6, 0x77, 0x70, 0xb7, - 0xd8, 0xd7, 0x23, 0x17, 0xc4, - 0xb7, 0x75, 0x21, 0x3c, 0x23, - 0xa8, 0xbd, 0x74, 0xf5, 0xe0, - }; - git_oid_fromraw(&a, a_in); - git_oid_fromraw(&b, a_in); - cl_assert(git_oid_cmp(&a, &b) == 0); -} - -void test_object_raw_compare__succeed_on_oid_comparison_greater(void) -{ - git_oid a, b; - unsigned char a_in[] = { - 0x16, 0xa6, 0x77, 0x70, 0xb7, - 0xd8, 0xd7, 0x23, 0x17, 0xc4, - 0xb7, 0x75, 0x21, 0x3c, 0x23, - 0xa8, 0xbd, 0x74, 0xf5, 0xe0, - }; - unsigned char b_in[] = { - 0x16, 0xa6, 0x77, 0x70, 0xb7, - 0xd8, 0xd7, 0x23, 0x17, 0xc4, - 0xb7, 0x75, 0x21, 0x3c, 0x23, - 0xa8, 0xbd, 0x74, 0xf5, 0xd0, - }; - git_oid_fromraw(&a, a_in); - git_oid_fromraw(&b, b_in); - cl_assert(git_oid_cmp(&a, &b) > 0); -} - -void test_object_raw_compare__compare_fmt_oids(void) -{ - const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0"; - git_oid in; - char out[GIT_OID_HEXSZ + 1]; - - cl_git_pass(git_oid_fromstr(&in, exp)); - - /* Format doesn't touch the last byte */ - out[GIT_OID_HEXSZ] = 'Z'; - git_oid_fmt(out, &in); - cl_assert(out[GIT_OID_HEXSZ] == 'Z'); - - /* Format produced the right result */ - out[GIT_OID_HEXSZ] = '\0'; - cl_assert_equal_s(exp, out); -} - -void test_object_raw_compare__compare_allocfmt_oids(void) -{ - const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0"; - git_oid in; - char *out; - - cl_git_pass(git_oid_fromstr(&in, exp)); - - out = git_oid_allocfmt(&in); - cl_assert(out); - cl_assert_equal_s(exp, out); - git__free(out); -} - -void test_object_raw_compare__compare_pathfmt_oids(void) -{ - const char *exp1 = "16a0123456789abcdef4b775213c23a8bd74f5e0"; - const char *exp2 = "16/a0123456789abcdef4b775213c23a8bd74f5e0"; - git_oid in; - char out[GIT_OID_HEXSZ + 2]; - - cl_git_pass(git_oid_fromstr(&in, exp1)); - - /* Format doesn't touch the last byte */ - out[GIT_OID_HEXSZ + 1] = 'Z'; - git_oid_pathfmt(out, &in); - cl_assert(out[GIT_OID_HEXSZ + 1] == 'Z'); - - /* Format produced the right result */ - out[GIT_OID_HEXSZ + 1] = '\0'; - cl_assert_equal_s(exp2, out); -} diff --git a/tests-clar/object/raw/convert.c b/tests-clar/object/raw/convert.c deleted file mode 100644 index 88b1380a4..000000000 --- a/tests-clar/object/raw/convert.c +++ /dev/null @@ -1,112 +0,0 @@ - -#include "clar_libgit2.h" - -#include "odb.h" - -void test_object_raw_convert__succeed_on_oid_to_string_conversion(void) -{ - const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0"; - git_oid in; - char out[GIT_OID_HEXSZ + 1]; - char *str; - int i; - - cl_git_pass(git_oid_fromstr(&in, exp)); - - /* NULL buffer pointer, returns static empty string */ - str = git_oid_tostr(NULL, sizeof(out), &in); - cl_assert(str && *str == '\0' && str != out); - - /* zero buffer size, returns static empty string */ - str = git_oid_tostr(out, 0, &in); - cl_assert(str && *str == '\0' && str != out); - - /* NULL oid pointer, sets existing buffer to empty string */ - str = git_oid_tostr(out, sizeof(out), NULL); - cl_assert(str && *str == '\0' && str == out); - - /* n == 1, returns out as an empty string */ - str = git_oid_tostr(out, 1, &in); - cl_assert(str && *str == '\0' && str == out); - - for (i = 1; i < GIT_OID_HEXSZ; i++) { - out[i+1] = 'Z'; - str = git_oid_tostr(out, i+1, &in); - /* returns out containing c-string */ - cl_assert(str && str == out); - /* must be '\0' terminated */ - cl_assert(*(str+i) == '\0'); - /* must not touch bytes past end of string */ - cl_assert(*(str+(i+1)) == 'Z'); - /* i == n-1 charaters of string */ - cl_git_pass(strncmp(exp, out, i)); - } - - /* returns out as hex formatted c-string */ - str = git_oid_tostr(out, sizeof(out), &in); - cl_assert(str && str == out && *(str+GIT_OID_HEXSZ) == '\0'); - cl_assert_equal_s(exp, out); -} - -void test_object_raw_convert__succeed_on_oid_to_string_conversion_big(void) -{ - const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0"; - git_oid in; - char big[GIT_OID_HEXSZ + 1 + 3]; /* note + 4 => big buffer */ - char *str; - - cl_git_pass(git_oid_fromstr(&in, exp)); - - /* place some tail material */ - big[GIT_OID_HEXSZ+0] = 'W'; /* should be '\0' afterwards */ - big[GIT_OID_HEXSZ+1] = 'X'; /* should remain untouched */ - big[GIT_OID_HEXSZ+2] = 'Y'; /* ditto */ - big[GIT_OID_HEXSZ+3] = 'Z'; /* ditto */ - - /* returns big as hex formatted c-string */ - str = git_oid_tostr(big, sizeof(big), &in); - cl_assert(str && str == big && *(str+GIT_OID_HEXSZ) == '\0'); - cl_assert_equal_s(exp, big); - - /* check tail material is untouched */ - cl_assert(str && str == big && *(str+GIT_OID_HEXSZ+1) == 'X'); - cl_assert(str && str == big && *(str+GIT_OID_HEXSZ+2) == 'Y'); - cl_assert(str && str == big && *(str+GIT_OID_HEXSZ+3) == 'Z'); -} - -static void check_partial_oid( - char *buffer, size_t count, const git_oid *oid, const char *expected) -{ - git_oid_nfmt(buffer, count, oid); - buffer[count] = '\0'; - cl_assert_equal_s(expected, buffer); -} - -void test_object_raw_convert__convert_oid_partially(void) -{ - const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0"; - git_oid in; - char big[GIT_OID_HEXSZ + 1 + 3]; /* note + 4 => big buffer */ - - cl_git_pass(git_oid_fromstr(&in, exp)); - - git_oid_nfmt(big, sizeof(big), &in); - cl_assert_equal_s(exp, big); - - git_oid_nfmt(big, GIT_OID_HEXSZ + 1, &in); - cl_assert_equal_s(exp, big); - - check_partial_oid(big, 1, &in, "1"); - check_partial_oid(big, 2, &in, "16"); - check_partial_oid(big, 3, &in, "16a"); - check_partial_oid(big, 4, &in, "16a0"); - check_partial_oid(big, 5, &in, "16a01"); - - check_partial_oid(big, GIT_OID_HEXSZ, &in, exp); - check_partial_oid( - big, GIT_OID_HEXSZ - 1, &in, "16a0123456789abcdef4b775213c23a8bd74f5e"); - check_partial_oid( - big, GIT_OID_HEXSZ - 2, &in, "16a0123456789abcdef4b775213c23a8bd74f5"); - check_partial_oid( - big, GIT_OID_HEXSZ - 3, &in, "16a0123456789abcdef4b775213c23a8bd74f"); -} diff --git a/tests-clar/object/raw/data.h b/tests-clar/object/raw/data.h deleted file mode 100644 index cf23819f1..000000000 --- a/tests-clar/object/raw/data.h +++ /dev/null @@ -1,323 +0,0 @@ - -/* - * Raw data - */ -static unsigned char commit_data[] = { - 0x74, 0x72, 0x65, 0x65, 0x20, 0x64, 0x66, 0x66, - 0x32, 0x64, 0x61, 0x39, 0x30, 0x62, 0x32, 0x35, - 0x34, 0x65, 0x31, 0x62, 0x65, 0x62, 0x38, 0x38, - 0x39, 0x64, 0x31, 0x66, 0x31, 0x66, 0x31, 0x32, - 0x38, 0x38, 0x62, 0x65, 0x31, 0x38, 0x30, 0x33, - 0x37, 0x38, 0x32, 0x64, 0x66, 0x0a, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x20, 0x41, 0x20, 0x55, - 0x20, 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, - 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x3e, 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, - 0x31, 0x34, 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, - 0x30, 0x30, 0x30, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x74, 0x65, 0x72, 0x20, 0x43, 0x20, - 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72, - 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, - 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34, - 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30, - 0x30, 0x0a, 0x0a, 0x41, 0x20, 0x6f, 0x6e, 0x65, - 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x73, 0x75, 0x6d, - 0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x54, 0x68, - 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x6f, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, - 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72, - 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70, - 0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x0a, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x2d, 0x6f, 0x66, 0x2d, - 0x62, 0x79, 0x3a, 0x20, 0x41, 0x20, 0x55, 0x20, - 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, 0x61, - 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x3e, 0x0a, -}; - - -static unsigned char tree_data[] = { - 0x31, 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x6f, - 0x6e, 0x65, 0x00, 0x8b, 0x13, 0x78, 0x91, 0x79, - 0x1f, 0xe9, 0x69, 0x27, 0xad, 0x78, 0xe6, 0x4b, - 0x0a, 0xad, 0x7b, 0xde, 0xd0, 0x8b, 0xdc, 0x31, - 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x73, 0x6f, - 0x6d, 0x65, 0x00, 0xfd, 0x84, 0x30, 0xbc, 0x86, - 0x4c, 0xfc, 0xd5, 0xf1, 0x0e, 0x55, 0x90, 0xf8, - 0xa4, 0x47, 0xe0, 0x1b, 0x94, 0x2b, 0xfe, 0x31, - 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x74, 0x77, - 0x6f, 0x00, 0x78, 0x98, 0x19, 0x22, 0x61, 0x3b, - 0x2a, 0xfb, 0x60, 0x25, 0x04, 0x2f, 0xf6, 0xbd, - 0x87, 0x8a, 0xc1, 0x99, 0x4e, 0x85, 0x31, 0x30, - 0x30, 0x36, 0x34, 0x34, 0x20, 0x7a, 0x65, 0x72, - 0x6f, 0x00, 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, - 0xd6, 0x43, 0x4b, 0x8b, 0x29, 0xae, 0x77, 0x5a, - 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91, -}; - -static unsigned char tag_data[] = { - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x33, - 0x64, 0x37, 0x66, 0x38, 0x61, 0x36, 0x61, 0x66, - 0x30, 0x37, 0x36, 0x63, 0x38, 0x63, 0x33, 0x66, - 0x32, 0x30, 0x30, 0x37, 0x31, 0x61, 0x38, 0x39, - 0x33, 0x35, 0x63, 0x64, 0x62, 0x65, 0x38, 0x32, - 0x32, 0x38, 0x35, 0x39, 0x34, 0x64, 0x31, 0x0a, - 0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x0a, 0x74, 0x61, 0x67, 0x20, - 0x76, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0a, 0x74, - 0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x43, 0x20, - 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72, - 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, - 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34, - 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30, - 0x30, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, - 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, - 0x61, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x30, - 0x2e, 0x30, 0x2e, 0x31, 0x0a, -}; - -/* - * Dummy data - */ -static unsigned char zero_data[] = { - 0x00, -}; - -static unsigned char one_data[] = { - 0x0a, -}; - -static unsigned char two_data[] = { - 0x61, 0x0a, -}; - -static unsigned char some_data[] = { - 0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68, - 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, - 0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, - 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, - 0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, - 0x6e, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69, - 0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, - 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0a, - 0x20, 0x2a, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e, - 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, - 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, - 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, - 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, - 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x2a, 0x20, 0x61, - 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, - 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, - 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, - 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x2a, 0x0a, - 0x20, 0x2a, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, - 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, - 0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x20, 0x2a, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, - 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x6c, - 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x70, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e, - 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, - 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20, - 0x2a, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, - 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69, - 0x6e, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x62, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74, - 0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x67, - 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0a, 0x20, 0x2a, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, - 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, - 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, - 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e, - 0x79, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x2a, - 0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20, - 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, - 0x65, 0x2e, 0x20, 0x20, 0x28, 0x54, 0x68, 0x65, - 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, - 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, - 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, - 0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, - 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, - 0x64, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79, - 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65, - 0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, - 0x74, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, - 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x0a, 0x20, 0x2a, 0x20, 0x6d, - 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e, - 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65, - 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x0a, 0x20, - 0x2a, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62, - 0x69, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, - 0x29, 0x0a, 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, - 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, - 0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, - 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61, - 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, - 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, - 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74, - 0x0a, 0x20, 0x2a, 0x20, 0x57, 0x49, 0x54, 0x48, - 0x4f, 0x55, 0x54, 0x20, 0x41, 0x4e, 0x59, 0x20, - 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59, - 0x3b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, - 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69, - 0x65, 0x64, 0x20, 0x77, 0x61, 0x72, 0x72, 0x61, - 0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x0a, 0x20, - 0x2a, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41, - 0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, - 0x59, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x49, 0x54, - 0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52, - 0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49, - 0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55, - 0x52, 0x50, 0x4f, 0x53, 0x45, 0x2e, 0x20, 0x20, - 0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x47, 0x4e, 0x55, 0x0a, 0x20, 0x2a, 0x20, 0x47, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, - 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x64, - 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a, - 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x59, 0x6f, - 0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, - 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x72, 0x65, - 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, - 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, - 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, - 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, - 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, - 0x20, 0x2a, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, - 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, - 0x20, 0x43, 0x4f, 0x50, 0x59, 0x49, 0x4e, 0x47, - 0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, - 0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, - 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x2a, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, - 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, - 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x35, 0x31, 0x20, - 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x6c, 0x69, 0x6e, - 0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2c, - 0x20, 0x46, 0x69, 0x66, 0x74, 0x68, 0x20, 0x46, - 0x6c, 0x6f, 0x6f, 0x72, 0x2c, 0x0a, 0x20, 0x2a, - 0x20, 0x42, 0x6f, 0x73, 0x74, 0x6f, 0x6e, 0x2c, - 0x20, 0x4d, 0x41, 0x20, 0x30, 0x32, 0x31, 0x31, - 0x30, 0x2d, 0x31, 0x33, 0x30, 0x31, 0x2c, 0x20, - 0x55, 0x53, 0x41, 0x2e, 0x0a, 0x20, 0x2a, 0x2f, - 0x0a, -}; - -/* - * SHA1 Hashes - */ -static char *commit_id = "3d7f8a6af076c8c3f20071a8935cdbe8228594d1"; -static char *tree_id = "dff2da90b254e1beb889d1f1f1288be1803782df"; -static char *tag_id = "09d373e1dfdc16b129ceec6dd649739911541e05"; -static char *zero_id = "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"; -static char *one_id = "8b137891791fe96927ad78e64b0aad7bded08bdc"; -static char *two_id = "78981922613b2afb6025042ff6bd878ac1994e85"; -static char *some_id = "fd8430bc864cfcd5f10e5590f8a447e01b942bfe"; - -/* - * In-memory objects - */ -static git_rawobj tree_obj = { - tree_data, - sizeof(tree_data), - GIT_OBJ_TREE -}; - -static git_rawobj tag_obj = { - tag_data, - sizeof(tag_data), - GIT_OBJ_TAG -}; - -static git_rawobj zero_obj = { - zero_data, - 0, - GIT_OBJ_BLOB -}; - -static git_rawobj one_obj = { - one_data, - sizeof(one_data), - GIT_OBJ_BLOB -}; - -static git_rawobj two_obj = { - two_data, - sizeof(two_data), - GIT_OBJ_BLOB -}; - -static git_rawobj commit_obj = { - commit_data, - sizeof(commit_data), - GIT_OBJ_COMMIT -}; - -static git_rawobj some_obj = { - some_data, - sizeof(some_data), - GIT_OBJ_BLOB -}; - -static git_rawobj junk_obj = { - NULL, - 0, - GIT_OBJ_BAD -}; diff --git a/tests-clar/object/raw/fromstr.c b/tests-clar/object/raw/fromstr.c deleted file mode 100644 index 8c11c105f..000000000 --- a/tests-clar/object/raw/fromstr.c +++ /dev/null @@ -1,30 +0,0 @@ - -#include "clar_libgit2.h" - -#include "odb.h" - -void test_object_raw_fromstr__fail_on_invalid_oid_string(void) -{ - git_oid out; - cl_git_fail(git_oid_fromstr(&out, "")); - cl_git_fail(git_oid_fromstr(&out, "moo")); - cl_git_fail(git_oid_fromstr(&out, "16a67770b7d8d72317c4b775213c23a8bd74f5ez")); -} - -void test_object_raw_fromstr__succeed_on_valid_oid_string(void) -{ - git_oid out; - unsigned char exp[] = { - 0x16, 0xa6, 0x77, 0x70, 0xb7, - 0xd8, 0xd7, 0x23, 0x17, 0xc4, - 0xb7, 0x75, 0x21, 0x3c, 0x23, - 0xa8, 0xbd, 0x74, 0xf5, 0xe0, - }; - - cl_git_pass(git_oid_fromstr(&out, "16a67770b7d8d72317c4b775213c23a8bd74f5e0")); - cl_git_pass(memcmp(out.id, exp, sizeof(out.id))); - - cl_git_pass(git_oid_fromstr(&out, "16A67770B7D8D72317C4b775213C23A8BD74F5E0")); - cl_git_pass(memcmp(out.id, exp, sizeof(out.id))); - -} diff --git a/tests-clar/object/raw/hash.c b/tests-clar/object/raw/hash.c deleted file mode 100644 index ede31e145..000000000 --- a/tests-clar/object/raw/hash.c +++ /dev/null @@ -1,166 +0,0 @@ - -#include "clar_libgit2.h" - -#include "odb.h" -#include "hash.h" - -#include "data.h" - -static void hash_object_pass(git_oid *oid, git_rawobj *obj) -{ - cl_git_pass(git_odb_hash(oid, obj->data, obj->len, obj->type)); -} -static void hash_object_fail(git_oid *oid, git_rawobj *obj) -{ - cl_git_fail(git_odb_hash(oid, obj->data, obj->len, obj->type)); -} - -static char *hello_id = "22596363b3de40b06f981fb85d82312e8c0ed511"; -static char *hello_text = "hello world\n"; - -static char *bye_id = "ce08fe4884650f067bd5703b6a59a8b3b3c99a09"; -static char *bye_text = "bye world\n"; - -void test_object_raw_hash__hash_by_blocks(void) -{ - git_hash_ctx ctx; - git_oid id1, id2; - - cl_git_pass(git_hash_ctx_init(&ctx)); - - /* should already be init'd */ - cl_git_pass(git_hash_update(&ctx, hello_text, strlen(hello_text))); - cl_git_pass(git_hash_final(&id2, &ctx)); - cl_git_pass(git_oid_fromstr(&id1, hello_id)); - cl_assert(git_oid_cmp(&id1, &id2) == 0); - - /* reinit should permit reuse */ - cl_git_pass(git_hash_init(&ctx)); - cl_git_pass(git_hash_update(&ctx, bye_text, strlen(bye_text))); - cl_git_pass(git_hash_final(&id2, &ctx)); - cl_git_pass(git_oid_fromstr(&id1, bye_id)); - cl_assert(git_oid_cmp(&id1, &id2) == 0); - - git_hash_ctx_cleanup(&ctx); -} - -void test_object_raw_hash__hash_buffer_in_single_call(void) -{ - git_oid id1, id2; - - cl_git_pass(git_oid_fromstr(&id1, hello_id)); - git_hash_buf(&id2, hello_text, strlen(hello_text)); - cl_assert(git_oid_cmp(&id1, &id2) == 0); -} - -void test_object_raw_hash__hash_vector(void) -{ - git_oid id1, id2; - git_buf_vec vec[2]; - - cl_git_pass(git_oid_fromstr(&id1, hello_id)); - - vec[0].data = hello_text; - vec[0].len = 4; - vec[1].data = hello_text+4; - vec[1].len = strlen(hello_text)-4; - - git_hash_vec(&id2, vec, 2); - - cl_assert(git_oid_cmp(&id1, &id2) == 0); -} - -void test_object_raw_hash__hash_junk_data(void) -{ - git_oid id, id_zero; - - cl_git_pass(git_oid_fromstr(&id_zero, zero_id)); - - /* invalid types: */ - junk_obj.data = some_data; - hash_object_fail(&id, &junk_obj); - - junk_obj.type = GIT_OBJ__EXT1; - hash_object_fail(&id, &junk_obj); - - junk_obj.type = GIT_OBJ__EXT2; - hash_object_fail(&id, &junk_obj); - - junk_obj.type = GIT_OBJ_OFS_DELTA; - hash_object_fail(&id, &junk_obj); - - junk_obj.type = GIT_OBJ_REF_DELTA; - hash_object_fail(&id, &junk_obj); - - /* data can be NULL only if len is zero: */ - junk_obj.type = GIT_OBJ_BLOB; - junk_obj.data = NULL; - hash_object_pass(&id, &junk_obj); - cl_assert(git_oid_cmp(&id, &id_zero) == 0); - - junk_obj.len = 1; - hash_object_fail(&id, &junk_obj); -} - -void test_object_raw_hash__hash_commit_object(void) -{ - git_oid id1, id2; - - cl_git_pass(git_oid_fromstr(&id1, commit_id)); - hash_object_pass(&id2, &commit_obj); - cl_assert(git_oid_cmp(&id1, &id2) == 0); -} - -void test_object_raw_hash__hash_tree_object(void) -{ - git_oid id1, id2; - - cl_git_pass(git_oid_fromstr(&id1, tree_id)); - hash_object_pass(&id2, &tree_obj); - cl_assert(git_oid_cmp(&id1, &id2) == 0); -} - -void test_object_raw_hash__hash_tag_object(void) -{ - git_oid id1, id2; - - cl_git_pass(git_oid_fromstr(&id1, tag_id)); - hash_object_pass(&id2, &tag_obj); - cl_assert(git_oid_cmp(&id1, &id2) == 0); -} - -void test_object_raw_hash__hash_zero_length_object(void) -{ - git_oid id1, id2; - - cl_git_pass(git_oid_fromstr(&id1, zero_id)); - hash_object_pass(&id2, &zero_obj); - cl_assert(git_oid_cmp(&id1, &id2) == 0); -} - -void test_object_raw_hash__hash_one_byte_object(void) -{ - git_oid id1, id2; - - cl_git_pass(git_oid_fromstr(&id1, one_id)); - hash_object_pass(&id2, &one_obj); - cl_assert(git_oid_cmp(&id1, &id2) == 0); -} - -void test_object_raw_hash__hash_two_byte_object(void) -{ - git_oid id1, id2; - - cl_git_pass(git_oid_fromstr(&id1, two_id)); - hash_object_pass(&id2, &two_obj); - cl_assert(git_oid_cmp(&id1, &id2) == 0); -} - -void test_object_raw_hash__hash_multi_byte_object(void) -{ - git_oid id1, id2; - - cl_git_pass(git_oid_fromstr(&id1, some_id)); - hash_object_pass(&id2, &some_obj); - cl_assert(git_oid_cmp(&id1, &id2) == 0); -} diff --git a/tests-clar/object/raw/short.c b/tests-clar/object/raw/short.c deleted file mode 100644 index 813cd86b6..000000000 --- a/tests-clar/object/raw/short.c +++ /dev/null @@ -1,137 +0,0 @@ - -#include "clar_libgit2.h" - -#include "odb.h" -#include "hash.h" - -void test_object_raw_short__oid_shortener_no_duplicates(void) -{ - git_oid_shorten *os; - int min_len; - - os = git_oid_shorten_new(0); - cl_assert(os != NULL); - - git_oid_shorten_add(os, "22596363b3de40b06f981fb85d82312e8c0ed511"); - git_oid_shorten_add(os, "ce08fe4884650f067bd5703b6a59a8b3b3c99a09"); - git_oid_shorten_add(os, "16a0123456789abcdef4b775213c23a8bd74f5e0"); - min_len = git_oid_shorten_add(os, "ce08fe4884650f067bd5703b6a59a8b3b3c99a09"); - - cl_assert(min_len == GIT_OID_HEXSZ + 1); - - git_oid_shorten_free(os); -} - -static int insert_sequential_oids( - char ***out, git_oid_shorten *os, int n, int fail) -{ - int i, min_len = 0; - char numbuf[16]; - git_oid oid; - char **oids = git__calloc(n, sizeof(char *)); - cl_assert(oids != NULL); - - for (i = 0; i < n; ++i) { - p_snprintf(numbuf, sizeof(numbuf), "%u", (unsigned int)i); - git_hash_buf(&oid, numbuf, strlen(numbuf)); - - oids[i] = git__malloc(GIT_OID_HEXSZ + 1); - cl_assert(oids[i]); - git_oid_nfmt(oids[i], GIT_OID_HEXSZ + 1, &oid); - - min_len = git_oid_shorten_add(os, oids[i]); - - /* After "fail", we expect git_oid_shorten_add to fail */ - if (fail >= 0 && i >= fail) - cl_assert(min_len < 0); - else - cl_assert(min_len >= 0); - } - - *out = oids; - - return min_len; -} - -static void free_oids(int n, char **oids) -{ - int i; - - for (i = 0; i < n; ++i) { - git__free(oids[i]); - } - git__free(oids); -} - -void test_object_raw_short__oid_shortener_stresstest_git_oid_shorten(void) -{ -#define MAX_OIDS 1000 - - git_oid_shorten *os; - size_t i, j; - int min_len = 0, found_collision; - char **oids; - - os = git_oid_shorten_new(0); - cl_assert(os != NULL); - - /* - * Insert in the shortener 1000 unique SHA1 ids - */ - min_len = insert_sequential_oids(&oids, os, MAX_OIDS, MAX_OIDS); - cl_assert(min_len > 0); - - /* - * Compare the first `min_char - 1` characters of each - * SHA1 OID. If the minimizer worked, we should find at - * least one collision - */ - found_collision = 0; - for (i = 0; i < MAX_OIDS; ++i) { - for (j = i + 1; j < MAX_OIDS; ++j) { - if (memcmp(oids[i], oids[j], min_len - 1) == 0) - found_collision = 1; - } - } - cl_assert_equal_b(true, found_collision); - - /* - * Compare the first `min_char` characters of each - * SHA1 OID. If the minimizer worked, every single preffix - * should be unique. - */ - found_collision = 0; - for (i = 0; i < MAX_OIDS; ++i) { - for (j = i + 1; j < MAX_OIDS; ++j) { - if (memcmp(oids[i], oids[j], min_len) == 0) - found_collision = 1; - } - } - cl_assert_equal_b(false, found_collision); - - /* cleanup */ - free_oids(MAX_OIDS, oids); - git_oid_shorten_free(os); - -#undef MAX_OIDS -} - -void test_object_raw_short__oid_shortener_too_much_oids(void) -{ - /* The magic number of oids at which an oid_shortener will fail. - * This was experimentally established. */ -#define MAX_OIDS 24556 - - git_oid_shorten *os; - char **oids; - - os = git_oid_shorten_new(0); - cl_assert(os != NULL); - - cl_assert(insert_sequential_oids(&oids, os, MAX_OIDS, MAX_OIDS - 1) < 0); - - free_oids(MAX_OIDS, oids); - git_oid_shorten_free(os); - -#undef MAX_OIDS -} diff --git a/tests-clar/object/raw/size.c b/tests-clar/object/raw/size.c deleted file mode 100644 index 930c6de23..000000000 --- a/tests-clar/object/raw/size.c +++ /dev/null @@ -1,13 +0,0 @@ - -#include "clar_libgit2.h" - -#include "odb.h" - -void test_object_raw_size__validate_oid_size(void) -{ - git_oid out; - cl_assert(20 == GIT_OID_RAWSZ); - cl_assert(40 == GIT_OID_HEXSZ); - cl_assert(sizeof(out) == GIT_OID_RAWSZ); - cl_assert(sizeof(out.id) == GIT_OID_RAWSZ); -} diff --git a/tests-clar/object/raw/type2string.c b/tests-clar/object/raw/type2string.c deleted file mode 100644 index a3585487f..000000000 --- a/tests-clar/object/raw/type2string.c +++ /dev/null @@ -1,54 +0,0 @@ - -#include "clar_libgit2.h" - -#include "odb.h" -#include "hash.h" - -void test_object_raw_type2string__convert_type_to_string(void) -{ - cl_assert_equal_s(git_object_type2string(GIT_OBJ_BAD), ""); - cl_assert_equal_s(git_object_type2string(GIT_OBJ__EXT1), ""); - cl_assert_equal_s(git_object_type2string(GIT_OBJ_COMMIT), "commit"); - cl_assert_equal_s(git_object_type2string(GIT_OBJ_TREE), "tree"); - cl_assert_equal_s(git_object_type2string(GIT_OBJ_BLOB), "blob"); - cl_assert_equal_s(git_object_type2string(GIT_OBJ_TAG), "tag"); - cl_assert_equal_s(git_object_type2string(GIT_OBJ__EXT2), ""); - cl_assert_equal_s(git_object_type2string(GIT_OBJ_OFS_DELTA), "OFS_DELTA"); - cl_assert_equal_s(git_object_type2string(GIT_OBJ_REF_DELTA), "REF_DELTA"); - - cl_assert_equal_s(git_object_type2string(-2), ""); - cl_assert_equal_s(git_object_type2string(8), ""); - cl_assert_equal_s(git_object_type2string(1234), ""); -} - -void test_object_raw_type2string__convert_string_to_type(void) -{ - cl_assert(git_object_string2type(NULL) == GIT_OBJ_BAD); - cl_assert(git_object_string2type("") == GIT_OBJ_BAD); - cl_assert(git_object_string2type("commit") == GIT_OBJ_COMMIT); - cl_assert(git_object_string2type("tree") == GIT_OBJ_TREE); - cl_assert(git_object_string2type("blob") == GIT_OBJ_BLOB); - cl_assert(git_object_string2type("tag") == GIT_OBJ_TAG); - cl_assert(git_object_string2type("OFS_DELTA") == GIT_OBJ_OFS_DELTA); - cl_assert(git_object_string2type("REF_DELTA") == GIT_OBJ_REF_DELTA); - - cl_assert(git_object_string2type("CoMmIt") == GIT_OBJ_BAD); - cl_assert(git_object_string2type("hohoho") == GIT_OBJ_BAD); -} - -void test_object_raw_type2string__check_type_is_loose(void) -{ - cl_assert(git_object_typeisloose(GIT_OBJ_BAD) == 0); - cl_assert(git_object_typeisloose(GIT_OBJ__EXT1) == 0); - cl_assert(git_object_typeisloose(GIT_OBJ_COMMIT) == 1); - cl_assert(git_object_typeisloose(GIT_OBJ_TREE) == 1); - cl_assert(git_object_typeisloose(GIT_OBJ_BLOB) == 1); - cl_assert(git_object_typeisloose(GIT_OBJ_TAG) == 1); - cl_assert(git_object_typeisloose(GIT_OBJ__EXT2) == 0); - cl_assert(git_object_typeisloose(GIT_OBJ_OFS_DELTA) == 0); - cl_assert(git_object_typeisloose(GIT_OBJ_REF_DELTA) == 0); - - cl_assert(git_object_typeisloose(-2) == 0); - cl_assert(git_object_typeisloose(8) == 0); - cl_assert(git_object_typeisloose(1234) == 0); -} diff --git a/tests-clar/object/raw/write.c b/tests-clar/object/raw/write.c deleted file mode 100644 index 273f08f2c..000000000 --- a/tests-clar/object/raw/write.c +++ /dev/null @@ -1,462 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/odb_backend.h" - -#include "fileops.h" -#include "odb.h" - -typedef struct object_data { - char *id; /* object id (sha1) */ - char *dir; /* object store (fan-out) directory name */ - char *file; /* object store filename */ -} object_data; - -static const char *odb_dir = "test-objects"; - -void test_body(object_data *d, git_rawobj *o); - - - -// Helpers -static void remove_object_files(object_data *d) -{ - cl_git_pass(p_unlink(d->file)); - cl_git_pass(p_rmdir(d->dir)); - cl_assert(errno != ENOTEMPTY); - cl_git_pass(p_rmdir(odb_dir) < 0); -} - -static void streaming_write(git_oid *oid, git_odb *odb, git_rawobj *raw) -{ - git_odb_stream *stream; - int error; - - cl_git_pass(git_odb_open_wstream(&stream, odb, raw->len, raw->type)); - git_odb_stream_write(stream, raw->data, raw->len); - error = git_odb_stream_finalize_write(oid, stream); - git_odb_stream_free(stream); - cl_git_pass(error); -} - -static void check_object_files(object_data *d) -{ - cl_assert(git_path_exists(d->dir)); - cl_assert(git_path_exists(d->file)); -} - -static void cmp_objects(git_rawobj *o1, git_rawobj *o2) -{ - cl_assert(o1->type == o2->type); - cl_assert(o1->len == o2->len); - if (o1->len > 0) - cl_assert(memcmp(o1->data, o2->data, o1->len) == 0); -} - -static void make_odb_dir(void) -{ - cl_git_pass(p_mkdir(odb_dir, GIT_OBJECT_DIR_MODE)); -} - - -// Standard test form -void test_body(object_data *d, git_rawobj *o) -{ - git_odb *db; - git_oid id1, id2; - git_odb_object *obj; - git_rawobj tmp; - - make_odb_dir(); - cl_git_pass(git_odb_open(&db, odb_dir)); - cl_git_pass(git_oid_fromstr(&id1, d->id)); - - streaming_write(&id2, db, o); - cl_assert(git_oid_cmp(&id1, &id2) == 0); - check_object_files(d); - - cl_git_pass(git_odb_read(&obj, db, &id1)); - - tmp.data = obj->buffer; - tmp.len = obj->cached.size; - tmp.type = obj->cached.type; - - cmp_objects(&tmp, o); - - git_odb_object_free(obj); - git_odb_free(db); - remove_object_files(d); -} - - -void test_object_raw_write__loose_object(void) -{ - object_data commit = { - "3d7f8a6af076c8c3f20071a8935cdbe8228594d1", - "test-objects/3d", - "test-objects/3d/7f8a6af076c8c3f20071a8935cdbe8228594d1", - }; - - unsigned char commit_data[] = { - 0x74, 0x72, 0x65, 0x65, 0x20, 0x64, 0x66, 0x66, - 0x32, 0x64, 0x61, 0x39, 0x30, 0x62, 0x32, 0x35, - 0x34, 0x65, 0x31, 0x62, 0x65, 0x62, 0x38, 0x38, - 0x39, 0x64, 0x31, 0x66, 0x31, 0x66, 0x31, 0x32, - 0x38, 0x38, 0x62, 0x65, 0x31, 0x38, 0x30, 0x33, - 0x37, 0x38, 0x32, 0x64, 0x66, 0x0a, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x20, 0x41, 0x20, 0x55, - 0x20, 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, - 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x3e, 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, - 0x31, 0x34, 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, - 0x30, 0x30, 0x30, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x74, 0x65, 0x72, 0x20, 0x43, 0x20, - 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72, - 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, - 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34, - 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30, - 0x30, 0x0a, 0x0a, 0x41, 0x20, 0x6f, 0x6e, 0x65, - 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x73, 0x75, 0x6d, - 0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x54, 0x68, - 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x6f, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, - 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72, - 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70, - 0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x0a, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x2d, 0x6f, 0x66, 0x2d, - 0x62, 0x79, 0x3a, 0x20, 0x41, 0x20, 0x55, 0x20, - 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, 0x61, - 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x3e, 0x0a, - }; - - git_rawobj commit_obj = { - commit_data, - sizeof(commit_data), - GIT_OBJ_COMMIT - }; - - test_body(&commit, &commit_obj); -} - -void test_object_raw_write__loose_tree(void) -{ - static object_data tree = { - "dff2da90b254e1beb889d1f1f1288be1803782df", - "test-objects/df", - "test-objects/df/f2da90b254e1beb889d1f1f1288be1803782df", - }; - - static unsigned char tree_data[] = { - 0x31, 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x6f, - 0x6e, 0x65, 0x00, 0x8b, 0x13, 0x78, 0x91, 0x79, - 0x1f, 0xe9, 0x69, 0x27, 0xad, 0x78, 0xe6, 0x4b, - 0x0a, 0xad, 0x7b, 0xde, 0xd0, 0x8b, 0xdc, 0x31, - 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x73, 0x6f, - 0x6d, 0x65, 0x00, 0xfd, 0x84, 0x30, 0xbc, 0x86, - 0x4c, 0xfc, 0xd5, 0xf1, 0x0e, 0x55, 0x90, 0xf8, - 0xa4, 0x47, 0xe0, 0x1b, 0x94, 0x2b, 0xfe, 0x31, - 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x74, 0x77, - 0x6f, 0x00, 0x78, 0x98, 0x19, 0x22, 0x61, 0x3b, - 0x2a, 0xfb, 0x60, 0x25, 0x04, 0x2f, 0xf6, 0xbd, - 0x87, 0x8a, 0xc1, 0x99, 0x4e, 0x85, 0x31, 0x30, - 0x30, 0x36, 0x34, 0x34, 0x20, 0x7a, 0x65, 0x72, - 0x6f, 0x00, 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, - 0xd6, 0x43, 0x4b, 0x8b, 0x29, 0xae, 0x77, 0x5a, - 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91, - }; - - static git_rawobj tree_obj = { - tree_data, - sizeof(tree_data), - GIT_OBJ_TREE - }; - - test_body(&tree, &tree_obj); -} - -void test_object_raw_write__loose_tag(void) -{ - static object_data tag = { - "09d373e1dfdc16b129ceec6dd649739911541e05", - "test-objects/09", - "test-objects/09/d373e1dfdc16b129ceec6dd649739911541e05", - }; - - static unsigned char tag_data[] = { - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x33, - 0x64, 0x37, 0x66, 0x38, 0x61, 0x36, 0x61, 0x66, - 0x30, 0x37, 0x36, 0x63, 0x38, 0x63, 0x33, 0x66, - 0x32, 0x30, 0x30, 0x37, 0x31, 0x61, 0x38, 0x39, - 0x33, 0x35, 0x63, 0x64, 0x62, 0x65, 0x38, 0x32, - 0x32, 0x38, 0x35, 0x39, 0x34, 0x64, 0x31, 0x0a, - 0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x0a, 0x74, 0x61, 0x67, 0x20, - 0x76, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0a, 0x74, - 0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x43, 0x20, - 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72, - 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, - 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34, - 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30, - 0x30, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, - 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, - 0x61, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x30, - 0x2e, 0x30, 0x2e, 0x31, 0x0a, - }; - - static git_rawobj tag_obj = { - tag_data, - sizeof(tag_data), - GIT_OBJ_TAG - }; - - - test_body(&tag, &tag_obj); -} - -void test_object_raw_write__zero_length(void) -{ - static object_data zero = { - "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", - "test-objects/e6", - "test-objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391", - }; - - static unsigned char zero_data[] = { - 0x00 /* dummy data */ - }; - - static git_rawobj zero_obj = { - zero_data, - 0, - GIT_OBJ_BLOB - }; - - test_body(&zero, &zero_obj); -} - -void test_object_raw_write__one_byte(void) -{ - static object_data one = { - "8b137891791fe96927ad78e64b0aad7bded08bdc", - "test-objects/8b", - "test-objects/8b/137891791fe96927ad78e64b0aad7bded08bdc", - }; - - static unsigned char one_data[] = { - 0x0a, - }; - - static git_rawobj one_obj = { - one_data, - sizeof(one_data), - GIT_OBJ_BLOB - }; - - test_body(&one, &one_obj); -} - -void test_object_raw_write__two_byte(void) -{ - static object_data two = { - "78981922613b2afb6025042ff6bd878ac1994e85", - "test-objects/78", - "test-objects/78/981922613b2afb6025042ff6bd878ac1994e85", - }; - - static unsigned char two_data[] = { - 0x61, 0x0a, - }; - - static git_rawobj two_obj = { - two_data, - sizeof(two_data), - GIT_OBJ_BLOB - }; - - test_body(&two, &two_obj); -} - -void test_object_raw_write__several_bytes(void) -{ - static object_data some = { - "fd8430bc864cfcd5f10e5590f8a447e01b942bfe", - "test-objects/fd", - "test-objects/fd/8430bc864cfcd5f10e5590f8a447e01b942bfe", - }; - - static unsigned char some_data[] = { - 0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68, - 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, - 0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, - 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, - 0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, - 0x6e, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69, - 0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, - 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0a, - 0x20, 0x2a, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e, - 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, - 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, - 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, - 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, - 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x2a, 0x20, 0x61, - 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, - 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, - 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, - 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x2a, 0x0a, - 0x20, 0x2a, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, - 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, - 0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x20, 0x2a, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, - 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x6c, - 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x70, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e, - 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, - 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20, - 0x2a, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, - 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69, - 0x6e, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x62, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74, - 0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x67, - 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0a, 0x20, 0x2a, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, - 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, - 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, - 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e, - 0x79, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x2a, - 0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20, - 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, - 0x65, 0x2e, 0x20, 0x20, 0x28, 0x54, 0x68, 0x65, - 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, - 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, - 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, - 0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, - 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, - 0x64, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79, - 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65, - 0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, - 0x74, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, - 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x0a, 0x20, 0x2a, 0x20, 0x6d, - 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e, - 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65, - 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x0a, 0x20, - 0x2a, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62, - 0x69, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, - 0x29, 0x0a, 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, - 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, - 0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, - 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61, - 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, - 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, - 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74, - 0x0a, 0x20, 0x2a, 0x20, 0x57, 0x49, 0x54, 0x48, - 0x4f, 0x55, 0x54, 0x20, 0x41, 0x4e, 0x59, 0x20, - 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59, - 0x3b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, - 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69, - 0x65, 0x64, 0x20, 0x77, 0x61, 0x72, 0x72, 0x61, - 0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x0a, 0x20, - 0x2a, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41, - 0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, - 0x59, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x49, 0x54, - 0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52, - 0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49, - 0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55, - 0x52, 0x50, 0x4f, 0x53, 0x45, 0x2e, 0x20, 0x20, - 0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x47, 0x4e, 0x55, 0x0a, 0x20, 0x2a, 0x20, 0x47, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, - 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x64, - 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a, - 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x59, 0x6f, - 0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, - 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x72, 0x65, - 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, - 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, - 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, - 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, - 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, - 0x20, 0x2a, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, - 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, - 0x20, 0x43, 0x4f, 0x50, 0x59, 0x49, 0x4e, 0x47, - 0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, - 0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, - 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x2a, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, - 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, - 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x35, 0x31, 0x20, - 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x6c, 0x69, 0x6e, - 0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2c, - 0x20, 0x46, 0x69, 0x66, 0x74, 0x68, 0x20, 0x46, - 0x6c, 0x6f, 0x6f, 0x72, 0x2c, 0x0a, 0x20, 0x2a, - 0x20, 0x42, 0x6f, 0x73, 0x74, 0x6f, 0x6e, 0x2c, - 0x20, 0x4d, 0x41, 0x20, 0x30, 0x32, 0x31, 0x31, - 0x30, 0x2d, 0x31, 0x33, 0x30, 0x31, 0x2c, 0x20, - 0x55, 0x53, 0x41, 0x2e, 0x0a, 0x20, 0x2a, 0x2f, - 0x0a, - }; - - static git_rawobj some_obj = { - some_data, - sizeof(some_data), - GIT_OBJ_BLOB - }; - - test_body(&some, &some_obj); -} diff --git a/tests-clar/object/tag/list.c b/tests-clar/object/tag/list.c deleted file mode 100644 index 6d5a24347..000000000 --- a/tests-clar/object/tag/list.c +++ /dev/null @@ -1,115 +0,0 @@ -#include "clar_libgit2.h" - -#include "tag.h" - -static git_repository *g_repo; - -#define MAX_USED_TAGS 6 - -struct pattern_match_t -{ - const char* pattern; - const size_t expected_matches; - const char* expected_results[MAX_USED_TAGS]; -}; - -// Helpers -static void ensure_tag_pattern_match(git_repository *repo, - const struct pattern_match_t* data) -{ - int already_found[MAX_USED_TAGS] = { 0 }; - git_strarray tag_list; - int error = 0; - size_t sucessfully_found = 0; - size_t i, j; - - cl_assert(data->expected_matches <= MAX_USED_TAGS); - - if ((error = git_tag_list_match(&tag_list, data->pattern, repo)) < 0) - goto exit; - - if (tag_list.count != data->expected_matches) - { - error = GIT_ERROR; - goto exit; - } - - // we have to be prepared that tags come in any order. - for (i = 0; i < tag_list.count; i++) - { - for (j = 0; j < data->expected_matches; j++) - { - if (!already_found[j] && !strcmp(data->expected_results[j], tag_list.strings[i])) - { - already_found[j] = 1; - sucessfully_found++; - break; - } - } - } - cl_assert_equal_i((int)sucessfully_found, (int)data->expected_matches); - -exit: - git_strarray_free(&tag_list); - cl_git_pass(error); -} - -// Fixture setup and teardown -void test_object_tag_list__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_object_tag_list__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_object_tag_list__list_all(void) -{ - // list all tag names from the repository - git_strarray tag_list; - - cl_git_pass(git_tag_list(&tag_list, g_repo)); - - cl_assert_equal_i((int)tag_list.count, 6); - - git_strarray_free(&tag_list); -} - -static const struct pattern_match_t matches[] = { - // All tags, including a packed one and two namespaced ones. - { "", 6, { "e90810b", "point_to_blob", "test", "packed-tag", "foo/bar", "foo/foo/bar" } }, - - // beginning with - { "t*", 1, { "test" } }, - - // ending with - { "*b", 2, { "e90810b", "point_to_blob" } }, - - // exact match - { "e", 0 }, - { "e90810b", 1, { "e90810b" } }, - - // either or - { "e90810[ab]", 1, { "e90810b" } }, - - // glob in the middle - { "foo/*/bar", 1, { "foo/foo/bar" } }, - - // The matching of '*' is based on plain string matching analog to the regular expression ".*" - // => a '/' in the tag name has no special meaning. - // Compare to `git tag -l "*bar"` - { "*bar", 2, { "foo/bar", "foo/foo/bar" } }, - - // End of list - { NULL } -}; - -void test_object_tag_list__list_by_pattern(void) -{ - // list all tag names from the repository matching a specified pattern - size_t i = 0; - while (matches[i].pattern) - ensure_tag_pattern_match(g_repo, &matches[i++]); -} diff --git a/tests-clar/object/tag/peel.c b/tests-clar/object/tag/peel.c deleted file mode 100644 index e2cd8d6a8..000000000 --- a/tests-clar/object/tag/peel.c +++ /dev/null @@ -1,61 +0,0 @@ -#include "clar_libgit2.h" -#include "tag.h" - -static git_repository *repo; -static git_tag *tag; -static git_object *target; - -void test_object_tag_peel__initialize(void) -{ - cl_fixture_sandbox("testrepo.git"); - cl_git_pass(git_repository_open(&repo, "testrepo.git")); -} - -void test_object_tag_peel__cleanup(void) -{ - git_tag_free(tag); - tag = NULL; - - git_object_free(target); - target = NULL; - - git_repository_free(repo); - repo = NULL; - - cl_fixture_cleanup("testrepo.git"); -} - -static void retrieve_tag_from_oid(git_tag **tag_out, git_repository *repo, const char *sha) -{ - git_oid oid; - - cl_git_pass(git_oid_fromstr(&oid, sha)); - cl_git_pass(git_tag_lookup(tag_out, repo, &oid)); -} - -void test_object_tag_peel__can_peel_to_a_commit(void) -{ - retrieve_tag_from_oid(&tag, repo, "7b4384978d2493e851f9cca7858815fac9b10980"); - - cl_git_pass(git_tag_peel(&target, tag)); - cl_assert(git_object_type(target) == GIT_OBJ_COMMIT); - cl_git_pass(git_oid_streq(git_object_id(target), "e90810b8df3e80c413d903f631643c716887138d")); -} - -void test_object_tag_peel__can_peel_several_nested_tags_to_a_commit(void) -{ - retrieve_tag_from_oid(&tag, repo, "b25fa35b38051e4ae45d4222e795f9df2e43f1d1"); - - cl_git_pass(git_tag_peel(&target, tag)); - cl_assert(git_object_type(target) == GIT_OBJ_COMMIT); - cl_git_pass(git_oid_streq(git_object_id(target), "e90810b8df3e80c413d903f631643c716887138d")); -} - -void test_object_tag_peel__can_peel_to_a_non_commit(void) -{ - retrieve_tag_from_oid(&tag, repo, "521d87c1ec3aef9824daf6d96cc0ae3710766d91"); - - cl_git_pass(git_tag_peel(&target, tag)); - cl_assert(git_object_type(target) == GIT_OBJ_BLOB); - cl_git_pass(git_oid_streq(git_object_id(target), "1385f264afb75a56a5bec74243be9b367ba4ca08")); -} diff --git a/tests-clar/object/tag/read.c b/tests-clar/object/tag/read.c deleted file mode 100644 index c9787a413..000000000 --- a/tests-clar/object/tag/read.c +++ /dev/null @@ -1,142 +0,0 @@ -#include "clar_libgit2.h" - -#include "tag.h" - -static const char *tag1_id = "b25fa35b38051e4ae45d4222e795f9df2e43f1d1"; -static const char *tag2_id = "7b4384978d2493e851f9cca7858815fac9b10980"; -static const char *tagged_commit = "e90810b8df3e80c413d903f631643c716887138d"; -static const char *bad_tag_id = "eda9f45a2a98d4c17a09d681d88569fa4ea91755"; -static const char *badly_tagged_commit = "e90810b8df3e80c413d903f631643c716887138d"; -static const char *short_tag_id = "5da7760512a953e3c7c4e47e4392c7a4338fb729"; -static const char *short_tagged_commit = "4a5ed60bafcf4638b7c8356bd4ce1916bfede93c"; -static const char *taggerless = "4a23e2e65ad4e31c4c9db7dc746650bfad082679"; - -static git_repository *g_repo; - -// Fixture setup and teardown -void test_object_tag_read__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_object_tag_read__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - - -void test_object_tag_read__parse(void) -{ - // read and parse a tag from the repository - git_tag *tag1, *tag2; - git_commit *commit; - git_oid id1, id2, id_commit; - - git_oid_fromstr(&id1, tag1_id); - git_oid_fromstr(&id2, tag2_id); - git_oid_fromstr(&id_commit, tagged_commit); - - cl_git_pass(git_tag_lookup(&tag1, g_repo, &id1)); - - cl_assert_equal_s(git_tag_name(tag1), "test"); - cl_assert(git_tag_target_type(tag1) == GIT_OBJ_TAG); - - cl_git_pass(git_tag_target((git_object **)&tag2, tag1)); - cl_assert(tag2 != NULL); - - cl_assert(git_oid_cmp(&id2, git_tag_id(tag2)) == 0); - - cl_git_pass(git_tag_target((git_object **)&commit, tag2)); - cl_assert(commit != NULL); - - cl_assert(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0); - - git_tag_free(tag1); - git_tag_free(tag2); - git_commit_free(commit); -} - -void test_object_tag_read__parse_without_tagger(void) -{ - // read and parse a tag without a tagger field - git_repository *bad_tag_repo; - git_tag *bad_tag; - git_commit *commit; - git_oid id, id_commit; - - // TODO: This is a little messy - cl_git_pass(git_repository_open(&bad_tag_repo, cl_fixture("bad_tag.git"))); - - git_oid_fromstr(&id, bad_tag_id); - git_oid_fromstr(&id_commit, badly_tagged_commit); - - cl_git_pass(git_tag_lookup(&bad_tag, bad_tag_repo, &id)); - cl_assert(bad_tag != NULL); - - cl_assert_equal_s(git_tag_name(bad_tag), "e90810b"); - cl_assert(git_oid_cmp(&id, git_tag_id(bad_tag)) == 0); - cl_assert(bad_tag->tagger == NULL); - - cl_git_pass(git_tag_target((git_object **)&commit, bad_tag)); - cl_assert(commit != NULL); - - cl_assert(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0); - - - git_tag_free(bad_tag); - git_commit_free(commit); - git_repository_free(bad_tag_repo); -} - -void test_object_tag_read__parse_without_message(void) -{ - // read and parse a tag without a message field - git_repository *short_tag_repo; - git_tag *short_tag; - git_commit *commit; - git_oid id, id_commit; - - // TODO: This is a little messy - cl_git_pass(git_repository_open(&short_tag_repo, cl_fixture("short_tag.git"))); - - git_oid_fromstr(&id, short_tag_id); - git_oid_fromstr(&id_commit, short_tagged_commit); - - cl_git_pass(git_tag_lookup(&short_tag, short_tag_repo, &id)); - cl_assert(short_tag != NULL); - - cl_assert_equal_s(git_tag_name(short_tag), "no_description"); - cl_assert(git_oid_cmp(&id, git_tag_id(short_tag)) == 0); - cl_assert(short_tag->message == NULL); - - cl_git_pass(git_tag_target((git_object **)&commit, short_tag)); - cl_assert(commit != NULL); - - cl_assert(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0); - - git_tag_free(short_tag); - git_commit_free(commit); - git_repository_free(short_tag_repo); -} - -void test_object_tag_read__without_tagger_nor_message(void) -{ - git_tag *tag; - git_oid id; - git_repository *repo; - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - - cl_git_pass(git_oid_fromstr(&id, taggerless)); - - cl_git_pass(git_tag_lookup(&tag, repo, &id)); - - cl_assert_equal_s(git_tag_name(tag), "taggerless"); - cl_assert(git_tag_target_type(tag) == GIT_OBJ_COMMIT); - - cl_assert(tag->message == NULL); - cl_assert(tag->tagger == NULL); - - git_tag_free(tag); - git_repository_free(repo); -} diff --git a/tests-clar/object/tag/write.c b/tests-clar/object/tag/write.c deleted file mode 100644 index 68e4b6c61..000000000 --- a/tests-clar/object/tag/write.c +++ /dev/null @@ -1,260 +0,0 @@ -#include "clar_libgit2.h" - -static const char* tagger_name = "Vicent Marti"; -static const char* tagger_email = "vicent@github.com"; -static const char* tagger_message = "This is my tag.\n\nThere are many tags, but this one is mine\n"; - -static const char *tag2_id = "7b4384978d2493e851f9cca7858815fac9b10980"; -static const char *tagged_commit = "e90810b8df3e80c413d903f631643c716887138d"; - -static git_repository *g_repo; - -// Fixture setup and teardown -void test_object_tag_write__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_object_tag_write__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_object_tag_write__basic(void) -{ - // write a tag to the repository and read it again - git_tag *tag; - git_oid target_id, tag_id; - git_signature *tagger; - const git_signature *tagger1; - git_reference *ref_tag; - git_object *target; - - git_oid_fromstr(&target_id, tagged_commit); - cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); - - /* create signature */ - cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60)); - - cl_git_pass( - git_tag_create(&tag_id, g_repo, - "the-tag", target, tagger, tagger_message, 0) - ); - - git_object_free(target); - git_signature_free(tagger); - - cl_git_pass(git_tag_lookup(&tag, g_repo, &tag_id)); - cl_assert(git_oid_cmp(git_tag_target_id(tag), &target_id) == 0); - - /* Check attributes were set correctly */ - tagger1 = git_tag_tagger(tag); - cl_assert(tagger1 != NULL); - cl_assert_equal_s(tagger1->name, tagger_name); - cl_assert_equal_s(tagger1->email, tagger_email); - cl_assert(tagger1->when.time == 123456789); - cl_assert(tagger1->when.offset == 60); - - cl_assert_equal_s(git_tag_message(tag), tagger_message); - - cl_git_pass(git_reference_lookup(&ref_tag, g_repo, "refs/tags/the-tag")); - cl_assert(git_oid_cmp(git_reference_target(ref_tag), &tag_id) == 0); - cl_git_pass(git_reference_delete(ref_tag)); - git_reference_free(ref_tag); - - git_tag_free(tag); -} - -void test_object_tag_write__overwrite(void) -{ - // Attempt to write a tag bearing the same name than an already existing tag - git_oid target_id, tag_id; - git_signature *tagger; - git_object *target; - - git_oid_fromstr(&target_id, tagged_commit); - cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); - - /* create signature */ - cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60)); - - cl_assert_equal_i(GIT_EEXISTS, git_tag_create( - &tag_id, /* out id */ - g_repo, - "e90810b", - target, - tagger, - tagger_message, - 0)); - - git_object_free(target); - git_signature_free(tagger); -} - -void test_object_tag_write__replace(void) -{ - // Replace an already existing tag - git_oid target_id, tag_id, old_tag_id; - git_signature *tagger; - git_reference *ref_tag; - git_object *target; - - git_oid_fromstr(&target_id, tagged_commit); - cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); - - cl_git_pass(git_reference_lookup(&ref_tag, g_repo, "refs/tags/e90810b")); - git_oid_cpy(&old_tag_id, git_reference_target(ref_tag)); - git_reference_free(ref_tag); - - /* create signature */ - cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60)); - - cl_git_pass(git_tag_create( - &tag_id, /* out id */ - g_repo, - "e90810b", - target, - tagger, - tagger_message, - 1)); - - git_object_free(target); - git_signature_free(tagger); - - cl_git_pass(git_reference_lookup(&ref_tag, g_repo, "refs/tags/e90810b")); - cl_assert(git_oid_cmp(git_reference_target(ref_tag), &tag_id) == 0); - cl_assert(git_oid_cmp(git_reference_target(ref_tag), &old_tag_id) != 0); - - git_reference_free(ref_tag); -} - -void test_object_tag_write__lightweight(void) -{ - // write a lightweight tag to the repository and read it again - git_oid target_id, object_id; - git_reference *ref_tag; - git_object *target; - - git_oid_fromstr(&target_id, tagged_commit); - cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); - - cl_git_pass(git_tag_create_lightweight( - &object_id, - g_repo, - "light-tag", - target, - 0)); - - git_object_free(target); - - cl_assert(git_oid_cmp(&object_id, &target_id) == 0); - - cl_git_pass(git_reference_lookup(&ref_tag, g_repo, "refs/tags/light-tag")); - cl_assert(git_oid_cmp(git_reference_target(ref_tag), &target_id) == 0); - - cl_git_pass(git_tag_delete(g_repo, "light-tag")); - - git_reference_free(ref_tag); -} - -void test_object_tag_write__lightweight_over_existing(void) -{ - // Attempt to write a lightweight tag bearing the same name than an already existing tag - git_oid target_id, object_id, existing_object_id; - git_object *target; - - git_oid_fromstr(&target_id, tagged_commit); - cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); - - cl_assert_equal_i(GIT_EEXISTS, git_tag_create_lightweight( - &object_id, - g_repo, - "e90810b", - target, - 0)); - - git_oid_fromstr(&existing_object_id, tag2_id); - cl_assert(git_oid_cmp(&object_id, &existing_object_id) == 0); - - git_object_free(target); -} - -void test_object_tag_write__delete(void) -{ - // Delete an already existing tag - git_reference *ref_tag; - - cl_git_pass(git_tag_delete(g_repo, "e90810b")); - - cl_git_fail(git_reference_lookup(&ref_tag, g_repo, "refs/tags/e90810b")); - - git_reference_free(ref_tag); -} - -void test_object_tag_write__creating_with_an_invalid_name_returns_EINVALIDSPEC(void) -{ - git_oid target_id, tag_id; - git_signature *tagger; - git_object *target; - - git_oid_fromstr(&target_id, tagged_commit); - cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); - - cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60)); - - cl_assert_equal_i(GIT_EINVALIDSPEC, - git_tag_create(&tag_id, g_repo, - "Inv@{id", target, tagger, tagger_message, 0) - ); - - cl_assert_equal_i(GIT_EINVALIDSPEC, - git_tag_create_lightweight(&tag_id, g_repo, - "Inv@{id", target, 0) - ); - - git_object_free(target); - git_signature_free(tagger); -} - -void test_object_tag_write__deleting_with_an_invalid_name_returns_EINVALIDSPEC(void) -{ - cl_assert_equal_i(GIT_EINVALIDSPEC, git_tag_delete(g_repo, "Inv@{id")); -} - -void create_annotation(git_oid *tag_id, const char *name) -{ - git_object *target; - git_oid target_id; - git_signature *tagger; - - cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60)); - - git_oid_fromstr(&target_id, tagged_commit); - cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); - - cl_git_pass(git_tag_annotation_create(tag_id, g_repo, name, target, tagger, "boom!")); - git_object_free(target); - git_signature_free(tagger); -} - -void test_object_tag_write__creating_an_annotation_stores_the_new_object_in_the_odb(void) -{ - git_oid tag_id; - git_tag *tag; - - create_annotation(&tag_id, "new_tag"); - - cl_git_pass(git_tag_lookup(&tag, g_repo, &tag_id)); - cl_assert_equal_s("new_tag", git_tag_name(tag)); - - git_tag_free(tag); -} - -void test_object_tag_write__creating_an_annotation_does_not_create_a_reference(void) -{ - git_oid tag_id; - git_reference *tag_ref; - - create_annotation(&tag_id, "new_tag"); - cl_git_fail_with(git_reference_lookup(&tag_ref, g_repo, "refs/tags/new_tag"), GIT_ENOTFOUND); -} diff --git a/tests-clar/object/tree/attributes.c b/tests-clar/object/tree/attributes.c deleted file mode 100644 index 85216cd1b..000000000 --- a/tests-clar/object/tree/attributes.c +++ /dev/null @@ -1,115 +0,0 @@ -#include "clar_libgit2.h" -#include "tree.h" - -static const char *blob_oid = "3d0970ec547fc41ef8a5882dde99c6adce65b021"; -static const char *tree_oid = "1b05fdaa881ee45b48cbaa5e9b037d667a47745e"; - -void test_object_tree_attributes__ensure_correctness_of_attributes_on_insertion(void) -{ - git_treebuilder *builder; - git_oid oid; - - cl_git_pass(git_oid_fromstr(&oid, blob_oid)); - - cl_git_pass(git_treebuilder_create(&builder, NULL)); - - cl_git_fail(git_treebuilder_insert(NULL, builder, "one.txt", &oid, (git_filemode_t)0777777)); - cl_git_fail(git_treebuilder_insert(NULL, builder, "one.txt", &oid, (git_filemode_t)0100666)); - cl_git_fail(git_treebuilder_insert(NULL, builder, "one.txt", &oid, (git_filemode_t)0000001)); - - git_treebuilder_free(builder); -} - -void test_object_tree_attributes__group_writable_tree_entries_created_with_an_antique_git_version_can_still_be_accessed(void) -{ - git_repository *repo; - git_oid tid; - git_tree *tree; - const git_tree_entry *entry; - - cl_git_pass(git_repository_open(&repo, cl_fixture("deprecated-mode.git"))); - - cl_git_pass(git_oid_fromstr(&tid, tree_oid)); - cl_git_pass(git_tree_lookup(&tree, repo, &tid)); - - entry = git_tree_entry_byname(tree, "old_mode.txt"); - cl_assert_equal_i( - GIT_FILEMODE_BLOB, - git_tree_entry_filemode(entry)); - - git_tree_free(tree); - git_repository_free(repo); -} - -void test_object_tree_attributes__treebuilder_reject_invalid_filemode(void) -{ - git_treebuilder *builder; - git_oid bid; - const git_tree_entry *entry; - - cl_git_pass(git_oid_fromstr(&bid, blob_oid)); - cl_git_pass(git_treebuilder_create(&builder, NULL)); - - cl_git_fail(git_treebuilder_insert( - &entry, - builder, - "normalized.txt", - &bid, - GIT_FILEMODE_BLOB_GROUP_WRITABLE)); - - git_treebuilder_free(builder); -} - -void test_object_tree_attributes__normalize_attributes_when_creating_a_tree_from_an_existing_one(void) -{ - git_repository *repo; - git_treebuilder *builder; - git_oid tid, tid2; - git_tree *tree; - const git_tree_entry *entry; - - repo = cl_git_sandbox_init("deprecated-mode.git"); - - cl_git_pass(git_oid_fromstr(&tid, tree_oid)); - cl_git_pass(git_tree_lookup(&tree, repo, &tid)); - - cl_git_pass(git_treebuilder_create(&builder, tree)); - - entry = git_treebuilder_get(builder, "old_mode.txt"); - cl_assert_equal_i( - GIT_FILEMODE_BLOB, - git_tree_entry_filemode(entry)); - - cl_git_pass(git_treebuilder_write(&tid2, repo, builder)); - git_treebuilder_free(builder); - git_tree_free(tree); - - cl_git_pass(git_tree_lookup(&tree, repo, &tid2)); - entry = git_tree_entry_byname(tree, "old_mode.txt"); - cl_assert_equal_i( - GIT_FILEMODE_BLOB, - git_tree_entry_filemode(entry)); - - git_tree_free(tree); - cl_git_sandbox_cleanup(); -} - -void test_object_tree_attributes__normalize_600(void) -{ - git_oid id; - git_tree *tree; - git_repository *repo; - const git_tree_entry *entry; - - repo = cl_git_sandbox_init("deprecated-mode.git"); - - git_oid_fromstr(&id, "0810fb7818088ff5ac41ee49199b51473b1bd6c7"); - cl_git_pass(git_tree_lookup(&tree, repo, &id)); - - entry = git_tree_entry_byname(tree, "ListaTeste.xml"); - cl_assert_equal_i(git_tree_entry_filemode(entry), GIT_FILEMODE_BLOB); - cl_assert_equal_i(git_tree_entry_filemode_raw(entry), 0100600); - - git_tree_free(tree); - cl_git_sandbox_cleanup(); -} diff --git a/tests-clar/object/tree/duplicateentries.c b/tests-clar/object/tree/duplicateentries.c deleted file mode 100644 index 9262f9a1a..000000000 --- a/tests-clar/object/tree/duplicateentries.c +++ /dev/null @@ -1,157 +0,0 @@ -#include "clar_libgit2.h" -#include "tree.h" - -static git_repository *_repo; - -void test_object_tree_duplicateentries__initialize(void) { - _repo = cl_git_sandbox_init("testrepo"); -} - -void test_object_tree_duplicateentries__cleanup(void) { - cl_git_sandbox_cleanup(); -} - -/* - * $ git show --format=raw refs/heads/dir - * commit 144344043ba4d4a405da03de3844aa829ae8be0e - * tree d52a8fe84ceedf260afe4f0287bbfca04a117e83 - * parent cf80f8de9f1185bf3a05f993f6121880dd0cfbc9 - * author Ben Straub 1343755506 -0700 - * committer Ben Straub 1343755506 -0700 - * - * Change a file mode - * - * diff --git a/a/b.txt b/a/b.txt - * old mode 100644 - * new mode 100755 - * - * $ git ls-tree d52a8fe84ceedf260afe4f0287bbfca04a117e83 - * 100644 blob a8233120f6ad708f843d861ce2b7228ec4e3dec6 README - * 040000 tree 4e0883eeeeebc1fb1735161cea82f7cb5fab7e63 a - * 100644 blob 45b983be36b73c0788dc9cbcb76cbb80fc7bb057 branch_file.txt - * 100644 blob a71586c1dfe8a71c6cbf6c129f404c5642ff31bd new.txt - */ - -static void tree_checker( - git_oid *tid, - const char *expected_sha, - git_filemode_t expected_filemode) -{ - git_tree *tree; - const git_tree_entry *entry; - git_oid oid; - - cl_git_pass(git_tree_lookup(&tree, _repo, tid)); - cl_assert_equal_i(1, (int)git_tree_entrycount(tree)); - entry = git_tree_entry_byindex(tree, 0); - - cl_git_pass(git_oid_fromstr(&oid, expected_sha)); - - cl_assert_equal_i(0, git_oid_cmp(&oid, git_tree_entry_id(entry))); - cl_assert_equal_i(expected_filemode, git_tree_entry_filemode(entry)); - - git_tree_free(tree); -} - -static void tree_creator(git_oid *out, void (*fn)(git_treebuilder *)) -{ - git_treebuilder *builder; - - cl_git_pass(git_treebuilder_create(&builder, NULL)); - - fn(builder); - - cl_git_pass(git_treebuilder_write(out, _repo, builder)); - git_treebuilder_free(builder); -} - -static void two_blobs(git_treebuilder *bld) -{ - git_oid oid; - const git_tree_entry *entry; - - cl_git_pass(git_oid_fromstr(&oid, - "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); /* blob oid (README) */ - - cl_git_pass(git_treebuilder_insert( - &entry, bld, "duplicate", &oid, - GIT_FILEMODE_BLOB)); - - cl_git_pass(git_oid_fromstr(&oid, - "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd")); /* blob oid (new.txt) */ - - cl_git_pass(git_treebuilder_insert( - &entry, bld, "duplicate", &oid, - GIT_FILEMODE_BLOB)); -} - -static void one_blob_and_one_tree(git_treebuilder *bld) -{ - git_oid oid; - const git_tree_entry *entry; - - cl_git_pass(git_oid_fromstr(&oid, - "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); /* blob oid (README) */ - - cl_git_pass(git_treebuilder_insert( - &entry, bld, "duplicate", &oid, - GIT_FILEMODE_BLOB)); - - cl_git_pass(git_oid_fromstr(&oid, - "4e0883eeeeebc1fb1735161cea82f7cb5fab7e63")); /* tree oid (a) */ - - cl_git_pass(git_treebuilder_insert( - &entry, bld, "duplicate", &oid, - GIT_FILEMODE_TREE)); -} - -void test_object_tree_duplicateentries__cannot_create_a_duplicate_entry_through_the_treebuilder(void) -{ - git_oid tid; - - tree_creator(&tid, two_blobs); - tree_checker(&tid, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd", GIT_FILEMODE_BLOB); - - tree_creator(&tid, one_blob_and_one_tree); - tree_checker(&tid, "4e0883eeeeebc1fb1735161cea82f7cb5fab7e63", GIT_FILEMODE_TREE); -} - -static void add_fake_conflicts(git_index *index) -{ - git_index_entry ancestor_entry, our_entry, their_entry; - - memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); - memset(&our_entry, 0x0, sizeof(git_index_entry)); - memset(&their_entry, 0x0, sizeof(git_index_entry)); - - ancestor_entry.path = "duplicate"; - ancestor_entry.mode = GIT_FILEMODE_BLOB; - ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); - git_oid_fromstr(&ancestor_entry.oid, "a8233120f6ad708f843d861ce2b7228ec4e3dec6"); - - our_entry.path = "duplicate"; - our_entry.mode = GIT_FILEMODE_BLOB; - ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT); - git_oid_fromstr(&our_entry.oid, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057"); - - their_entry.path = "duplicate"; - their_entry.mode = GIT_FILEMODE_BLOB; - ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT); - git_oid_fromstr(&their_entry.oid, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd"); - - cl_git_pass(git_index_conflict_add(index, &ancestor_entry, &our_entry, &their_entry)); -} - -void test_object_tree_duplicateentries__cannot_create_a_duplicate_entry_building_a_tree_from_a_index_with_conflicts(void) -{ - git_index *index; - git_oid tid; - - cl_git_pass(git_repository_index(&index, _repo)); - - add_fake_conflicts(index); - - cl_assert_equal_i(GIT_EUNMERGED, git_index_write_tree(&tid, index)); - - git_index_free(index); -} diff --git a/tests-clar/object/tree/frompath.c b/tests-clar/object/tree/frompath.c deleted file mode 100644 index 86ca47e94..000000000 --- a/tests-clar/object/tree/frompath.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "clar_libgit2.h" - -static git_repository *repo; -static git_tree *tree; - -void test_object_tree_frompath__initialize(void) -{ - git_oid id; - const char *tree_with_subtrees_oid = "ae90f12eea699729ed24555e40b9fd669da12a12"; - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - cl_assert(repo != NULL); - - cl_git_pass(git_oid_fromstr(&id, tree_with_subtrees_oid)); - cl_git_pass(git_tree_lookup(&tree, repo, &id)); - cl_assert(tree != NULL); -} - -void test_object_tree_frompath__cleanup(void) -{ - git_tree_free(tree); - tree = NULL; - - git_repository_free(repo); - repo = NULL; -} - -static void assert_tree_from_path( - git_tree *root, - const char *path, - const char *expected_entry_name) -{ - git_tree_entry *entry; - - cl_git_pass(git_tree_entry_bypath(&entry, root, path)); - cl_assert_equal_s(git_tree_entry_name(entry), expected_entry_name); - git_tree_entry_free(entry); -} - -void test_object_tree_frompath__retrieve_tree_from_path_to_treeentry(void) -{ - git_tree_entry *e; - - assert_tree_from_path(tree, "README", "README"); - assert_tree_from_path(tree, "ab/de/fgh/1.txt", "1.txt"); - assert_tree_from_path(tree, "ab/de/fgh", "fgh"); - assert_tree_from_path(tree, "ab/de/fgh/", "fgh"); - assert_tree_from_path(tree, "ab/de", "de"); - assert_tree_from_path(tree, "ab/", "ab"); - assert_tree_from_path(tree, "ab/de/", "de"); - - cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "i-do-not-exist.txt")); - cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "README/")); - cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "ab/de/fgh/i-do-not-exist.txt")); - cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "nope/de/fgh/1.txt")); - cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "ab/me-neither/fgh/2.txt")); - cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "ab/me-neither/fgh/2.txt/")); -} - -void test_object_tree_frompath__fail_when_processing_an_invalid_path(void) -{ - git_tree_entry *e; - - cl_must_fail(git_tree_entry_bypath(&e, tree, "/")); - cl_must_fail(git_tree_entry_bypath(&e, tree, "/ab")); - cl_must_fail(git_tree_entry_bypath(&e, tree, "/ab/de")); - cl_must_fail(git_tree_entry_bypath(&e, tree, "ab//de")); -} diff --git a/tests-clar/object/tree/read.c b/tests-clar/object/tree/read.c deleted file mode 100644 index 59a809bf1..000000000 --- a/tests-clar/object/tree/read.c +++ /dev/null @@ -1,75 +0,0 @@ -#include "clar_libgit2.h" - -#include "tree.h" - -static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd"; - -static git_repository *g_repo; - -// Fixture setup and teardown -void test_object_tree_read__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_object_tree_read__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - - - -void test_object_tree_read__loaded(void) -{ - // acces randomly the entries on a loaded tree - git_oid id; - git_tree *tree; - - git_oid_fromstr(&id, tree_oid); - - cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); - - cl_assert(git_tree_entry_byname(tree, "README") != NULL); - cl_assert(git_tree_entry_byname(tree, "NOTEXISTS") == NULL); - cl_assert(git_tree_entry_byname(tree, "") == NULL); - cl_assert(git_tree_entry_byindex(tree, 0) != NULL); - cl_assert(git_tree_entry_byindex(tree, 2) != NULL); - cl_assert(git_tree_entry_byindex(tree, 3) == NULL); - cl_assert(git_tree_entry_byindex(tree, (unsigned int)-1) == NULL); - - git_tree_free(tree); -} - -void test_object_tree_read__two(void) -{ - // read a tree from the repository - git_oid id; - git_tree *tree; - const git_tree_entry *entry; - git_object *obj; - - git_oid_fromstr(&id, tree_oid); - - cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); - - cl_assert(git_tree_entrycount(tree) == 3); - - /* GH-86: git_object_lookup() should also check the type if the object comes from the cache */ - cl_assert(git_object_lookup(&obj, g_repo, &id, GIT_OBJ_TREE) == 0); - cl_assert(obj != NULL); - git_object_free(obj); - obj = NULL; - cl_git_fail(git_object_lookup(&obj, g_repo, &id, GIT_OBJ_BLOB)); - cl_assert(obj == NULL); - - entry = git_tree_entry_byname(tree, "README"); - cl_assert(entry != NULL); - - cl_assert_equal_s(git_tree_entry_name(entry), "README"); - - cl_git_pass(git_tree_entry_to_object(&obj, g_repo, entry)); - cl_assert(obj != NULL); - - git_object_free(obj); - git_tree_free(tree); -} diff --git a/tests-clar/object/tree/walk.c b/tests-clar/object/tree/walk.c deleted file mode 100644 index 1207e864c..000000000 --- a/tests-clar/object/tree/walk.c +++ /dev/null @@ -1,177 +0,0 @@ -#include "clar_libgit2.h" -#include "tree.h" - -static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd"; -static git_repository *g_repo; - -void test_object_tree_walk__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_object_tree_walk__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -static int treewalk_count_cb( - const char *root, const git_tree_entry *entry, void *payload) -{ - int *count = payload; - - GIT_UNUSED(root); - GIT_UNUSED(entry); - - (*count) += 1; - - return 0; -} - -void test_object_tree_walk__0(void) -{ - git_oid id; - git_tree *tree; - int ct; - - git_oid_fromstr(&id, tree_oid); - - cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); - - ct = 0; - cl_git_pass(git_tree_walk(tree, GIT_TREEWALK_PRE, treewalk_count_cb, &ct)); - cl_assert_equal_i(3, ct); - - ct = 0; - cl_git_pass(git_tree_walk(tree, GIT_TREEWALK_POST, treewalk_count_cb, &ct)); - cl_assert_equal_i(3, ct); - - git_tree_free(tree); -} - - -static int treewalk_stop_cb( - const char *root, const git_tree_entry *entry, void *payload) -{ - int *count = payload; - - GIT_UNUSED(root); - GIT_UNUSED(entry); - - (*count) += 1; - - return (*count == 2) ? -1 : 0; -} - -static int treewalk_stop_immediately_cb( - const char *root, const git_tree_entry *entry, void *payload) -{ - GIT_UNUSED(root); - GIT_UNUSED(entry); - GIT_UNUSED(payload); - return -100; -} - -void test_object_tree_walk__1(void) -{ - git_oid id; - git_tree *tree; - int ct; - - git_oid_fromstr(&id, tree_oid); - - cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); - - ct = 0; - cl_assert_equal_i( - GIT_EUSER, git_tree_walk(tree, GIT_TREEWALK_PRE, treewalk_stop_cb, &ct)); - cl_assert_equal_i(2, ct); - - ct = 0; - cl_assert_equal_i( - GIT_EUSER, git_tree_walk(tree, GIT_TREEWALK_POST, treewalk_stop_cb, &ct)); - cl_assert_equal_i(2, ct); - - cl_assert_equal_i( - GIT_EUSER, git_tree_walk( - tree, GIT_TREEWALK_PRE, treewalk_stop_immediately_cb, NULL)); - - cl_assert_equal_i( - GIT_EUSER, git_tree_walk( - tree, GIT_TREEWALK_POST, treewalk_stop_immediately_cb, NULL)); - - git_tree_free(tree); -} - - -struct treewalk_skip_data { - int files; - int dirs; - const char *skip; - const char *stop; -}; - -static int treewalk_skip_de_cb( - const char *root, const git_tree_entry *entry, void *payload) -{ - struct treewalk_skip_data *data = payload; - const char *name = git_tree_entry_name(entry); - - GIT_UNUSED(root); - - if (git_tree_entry_type(entry) == GIT_OBJ_TREE) - data->dirs++; - else - data->files++; - - if (data->skip && !strcmp(name, data->skip)) - return 1; - else if (data->stop && !strcmp(name, data->stop)) - return -1; - else - return 0; -} - -void test_object_tree_walk__2(void) -{ - git_oid id; - git_tree *tree; - struct treewalk_skip_data data; - - /* look up a deep tree */ - git_oid_fromstr(&id, "ae90f12eea699729ed24555e40b9fd669da12a12"); - cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); - - memset(&data, 0, sizeof(data)); - data.skip = "de"; - - cl_assert_equal_i(0, git_tree_walk( - tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); - cl_assert_equal_i(5, data.files); - cl_assert_equal_i(3, data.dirs); - - memset(&data, 0, sizeof(data)); - data.stop = "3.txt"; - - cl_assert_equal_i(GIT_EUSER, git_tree_walk( - tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); - cl_assert_equal_i(3, data.files); - cl_assert_equal_i(2, data.dirs); - - memset(&data, 0, sizeof(data)); - data.skip = "new.txt"; - - cl_assert_equal_i(0, git_tree_walk( - tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); - cl_assert_equal_i(7, data.files); - cl_assert_equal_i(4, data.dirs); - - memset(&data, 0, sizeof(data)); - data.stop = "new.txt"; - - cl_assert_equal_i(GIT_EUSER, git_tree_walk( - tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); - cl_assert_equal_i(7, data.files); - cl_assert_equal_i(4, data.dirs); - - git_tree_free(tree); -} diff --git a/tests-clar/object/tree/write.c b/tests-clar/object/tree/write.c deleted file mode 100644 index 468c0ccd1..000000000 --- a/tests-clar/object/tree/write.c +++ /dev/null @@ -1,262 +0,0 @@ -#include "clar_libgit2.h" - -#include "tree.h" - -static const char *blob_oid = "fa49b077972391ad58037050f2a75f74e3671e92"; -static const char *first_tree = "181037049a54a1eb5fab404658a3a250b44335d7"; -static const char *second_tree = "f60079018b664e4e79329a7ef9559c8d9e0378d1"; -static const char *third_tree = "eb86d8b81d6adbd5290a935d6c9976882de98488"; - -static git_repository *g_repo; - -// Fixture setup and teardown -void test_object_tree_write__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_object_tree_write__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_object_tree_write__from_memory(void) -{ - // write a tree from a memory - git_treebuilder *builder; - git_tree *tree; - git_oid id, bid, rid, id2; - - git_oid_fromstr(&id, first_tree); - git_oid_fromstr(&id2, second_tree); - git_oid_fromstr(&bid, blob_oid); - - //create a second tree from first tree using `git_treebuilder_insert` on REPOSITORY_FOLDER. - cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); - cl_git_pass(git_treebuilder_create(&builder, tree)); - - cl_git_fail(git_treebuilder_insert(NULL, builder, "", - &bid, GIT_FILEMODE_BLOB)); - cl_git_fail(git_treebuilder_insert(NULL, builder, "/", - &bid, GIT_FILEMODE_BLOB)); - cl_git_fail(git_treebuilder_insert(NULL, builder, ".git", - &bid, GIT_FILEMODE_BLOB)); - cl_git_fail(git_treebuilder_insert(NULL, builder, "..", - &bid, GIT_FILEMODE_BLOB)); - cl_git_fail(git_treebuilder_insert(NULL, builder, ".", - &bid, GIT_FILEMODE_BLOB)); - cl_git_fail(git_treebuilder_insert(NULL, builder, "folder/new.txt", - &bid, GIT_FILEMODE_BLOB)); - - cl_git_pass(git_treebuilder_insert( - NULL, builder, "new.txt", &bid, GIT_FILEMODE_BLOB)); - - cl_git_pass(git_treebuilder_write(&rid, g_repo, builder)); - - cl_assert(git_oid_cmp(&rid, &id2) == 0); - - git_treebuilder_free(builder); - git_tree_free(tree); -} - -void test_object_tree_write__subtree(void) -{ - // write a hierarchical tree from a memory - git_treebuilder *builder; - git_tree *tree; - git_oid id, bid, subtree_id, id2, id3; - git_oid id_hiearar; - - git_oid_fromstr(&id, first_tree); - git_oid_fromstr(&id2, second_tree); - git_oid_fromstr(&id3, third_tree); - git_oid_fromstr(&bid, blob_oid); - - //create subtree - cl_git_pass(git_treebuilder_create(&builder, NULL)); - cl_git_pass(git_treebuilder_insert( - NULL, builder, "new.txt", &bid, GIT_FILEMODE_BLOB)); //-V536 - cl_git_pass(git_treebuilder_write(&subtree_id, g_repo, builder)); - git_treebuilder_free(builder); - - // create parent tree - cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); - cl_git_pass(git_treebuilder_create(&builder, tree)); - cl_git_pass(git_treebuilder_insert( - NULL, builder, "new", &subtree_id, GIT_FILEMODE_TREE)); //-V536 - cl_git_pass(git_treebuilder_write(&id_hiearar, g_repo, builder)); - git_treebuilder_free(builder); - git_tree_free(tree); - - cl_assert(git_oid_cmp(&id_hiearar, &id3) == 0); - - // check data is correct - cl_git_pass(git_tree_lookup(&tree, g_repo, &id_hiearar)); - cl_assert(2 == git_tree_entrycount(tree)); - git_tree_free(tree); -} - -/* - * And the Lord said: Is this tree properly sorted? - */ -void test_object_tree_write__sorted_subtrees(void) -{ - git_treebuilder *builder; - unsigned int i; - int position_c = -1, position_cake = -1, position_config = -1; - - struct { - unsigned int attr; - const char *filename; - } entries[] = { - { GIT_FILEMODE_BLOB, ".gitattributes" }, - { GIT_FILEMODE_BLOB, ".gitignore" }, - { GIT_FILEMODE_BLOB, ".htaccess" }, - { GIT_FILEMODE_BLOB, "Capfile" }, - { GIT_FILEMODE_BLOB, "Makefile"}, - { GIT_FILEMODE_BLOB, "README"}, - { GIT_FILEMODE_TREE, "app"}, - { GIT_FILEMODE_TREE, "cake"}, - { GIT_FILEMODE_TREE, "config"}, - { GIT_FILEMODE_BLOB, "c"}, - { GIT_FILEMODE_BLOB, "git_test.txt"}, - { GIT_FILEMODE_BLOB, "htaccess.htaccess"}, - { GIT_FILEMODE_BLOB, "index.php"}, - { GIT_FILEMODE_TREE, "plugins"}, - { GIT_FILEMODE_TREE, "schemas"}, - { GIT_FILEMODE_TREE, "ssl-certs"}, - { GIT_FILEMODE_TREE, "vendors"} - }; - - git_oid blank_oid, tree_oid; - - memset(&blank_oid, 0x0, sizeof(blank_oid)); - - cl_git_pass(git_treebuilder_create(&builder, NULL)); - - for (i = 0; i < ARRAY_SIZE(entries); ++i) { - cl_git_pass(git_treebuilder_insert(NULL, - builder, entries[i].filename, &blank_oid, entries[i].attr)); - } - - cl_git_pass(git_treebuilder_write(&tree_oid, g_repo, builder)); - - for (i = 0; i < builder->entries.length; ++i) { - git_tree_entry *entry = git_vector_get(&builder->entries, i); - - if (strcmp(entry->filename, "c") == 0) - position_c = i; - - if (strcmp(entry->filename, "cake") == 0) - position_cake = i; - - if (strcmp(entry->filename, "config") == 0) - position_config = i; - } - - cl_assert(position_c != -1); - cl_assert(position_cake != -1); - cl_assert(position_config != -1); - - cl_assert(position_c < position_cake); - cl_assert(position_cake < position_config); - - git_treebuilder_free(builder); -} - -void test_object_tree_write__removing_and_re_adding_in_treebuilder(void) -{ - git_treebuilder *builder; - int i, aardvark_i, apple_i, apple_after_i, apple_extra_i, last_i; - git_oid blank_oid, tree_oid; - git_tree *tree; - struct { - unsigned int attr; - const char *filename; - } entries[] = { - { GIT_FILEMODE_BLOB, "aardvark" }, - { GIT_FILEMODE_BLOB, ".first" }, - { GIT_FILEMODE_BLOB, "apple" }, - { GIT_FILEMODE_BLOB, "last"}, - { GIT_FILEMODE_BLOB, "apple_after"}, - { GIT_FILEMODE_BLOB, "after_aardvark"}, - { 0, NULL }, - }; - - memset(&blank_oid, 0x0, sizeof(blank_oid)); - - cl_git_pass(git_treebuilder_create(&builder, NULL)); - - cl_assert_equal_i(0, (int)git_treebuilder_entrycount(builder)); - - for (i = 0; entries[i].filename; ++i) - cl_git_pass(git_treebuilder_insert(NULL, - builder, entries[i].filename, &blank_oid, entries[i].attr)); - - cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder)); - - cl_git_pass(git_treebuilder_remove(builder, "apple")); - cl_assert_equal_i(5, (int)git_treebuilder_entrycount(builder)); - - cl_git_pass(git_treebuilder_remove(builder, "apple_after")); - cl_assert_equal_i(4, (int)git_treebuilder_entrycount(builder)); - - cl_git_pass(git_treebuilder_insert( - NULL, builder, "before_last", &blank_oid, GIT_FILEMODE_BLOB)); - cl_assert_equal_i(5, (int)git_treebuilder_entrycount(builder)); - - /* reinsert apple_after */ - cl_git_pass(git_treebuilder_insert( - NULL, builder, "apple_after", &blank_oid, GIT_FILEMODE_BLOB)); - cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder)); - - cl_git_pass(git_treebuilder_remove(builder, "last")); - cl_assert_equal_i(5, (int)git_treebuilder_entrycount(builder)); - - /* reinsert last */ - cl_git_pass(git_treebuilder_insert( - NULL, builder, "last", &blank_oid, GIT_FILEMODE_BLOB)); - cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder)); - - cl_git_pass(git_treebuilder_insert( - NULL, builder, "apple_extra", &blank_oid, GIT_FILEMODE_BLOB)); - cl_assert_equal_i(7, (int)git_treebuilder_entrycount(builder)); - - cl_git_pass(git_treebuilder_write(&tree_oid, g_repo, builder)); - - git_treebuilder_free(builder); - - cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_oid)); - - cl_assert_equal_i(7, (int)git_tree_entrycount(tree)); - - cl_assert(git_tree_entry_byname(tree, ".first") != NULL); - cl_assert(git_tree_entry_byname(tree, "apple") == NULL); - cl_assert(git_tree_entry_byname(tree, "apple_after") != NULL); - cl_assert(git_tree_entry_byname(tree, "apple_extra") != NULL); - cl_assert(git_tree_entry_byname(tree, "last") != NULL); - - aardvark_i = apple_i = apple_after_i = apple_extra_i = last_i = -1; - - for (i = 0; i < 7; ++i) { - const git_tree_entry *entry = git_tree_entry_byindex(tree, i); - - if (!strcmp(entry->filename, "aardvark")) - aardvark_i = i; - else if (!strcmp(entry->filename, "apple")) - apple_i = i; - else if (!strcmp(entry->filename, "apple_after")) - apple_after_i = i; - else if (!strcmp(entry->filename, "apple_extra")) - apple_extra_i = i; - else if (!strcmp(entry->filename, "last")) - last_i = i; - } - - cl_assert_equal_i(-1, apple_i); - cl_assert_equal_i(6, last_i); - cl_assert(aardvark_i < apple_after_i); - cl_assert(apple_after_i < apple_extra_i); - - git_tree_free(tree); -} diff --git a/tests-clar/odb/alternates.c b/tests-clar/odb/alternates.c deleted file mode 100644 index c75f6feaa..000000000 --- a/tests-clar/odb/alternates.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "clar_libgit2.h" -#include "odb.h" -#include "filebuf.h" - -static git_buf destpath, filepath; -static const char *paths[] = { - "A.git", "B.git", "C.git", "D.git", "E.git", "F.git", "G.git" -}; -static git_filebuf file; -static git_repository *repo; - -void test_odb_alternates__cleanup(void) -{ - size_t i; - - git_buf_free(&destpath); - git_buf_free(&filepath); - - for (i = 0; i < ARRAY_SIZE(paths); i++) - cl_fixture_cleanup(paths[i]); -} - -static void init_linked_repo(const char *path, const char *alternate) -{ - git_buf_clear(&destpath); - git_buf_clear(&filepath); - - cl_git_pass(git_repository_init(&repo, path, 1)); - cl_git_pass(git_path_prettify(&destpath, alternate, NULL)); - cl_git_pass(git_buf_joinpath(&destpath, destpath.ptr, "objects")); - cl_git_pass(git_buf_joinpath(&filepath, git_repository_path(repo), "objects/info")); - cl_git_pass(git_futils_mkdir(filepath.ptr, NULL, 0755, GIT_MKDIR_PATH)); - cl_git_pass(git_buf_joinpath(&filepath, filepath.ptr , "alternates")); - - cl_git_pass(git_filebuf_open(&file, git_buf_cstr(&filepath), 0, 0666)); - git_filebuf_printf(&file, "%s\n", git_buf_cstr(&destpath)); - cl_git_pass(git_filebuf_commit(&file)); - - git_repository_free(repo); -} - -void test_odb_alternates__chained(void) -{ - git_commit *commit; - git_oid oid; - - /* Set the alternate A -> testrepo.git */ - init_linked_repo(paths[0], cl_fixture("testrepo.git")); - - /* Set the alternate B -> A */ - init_linked_repo(paths[1], paths[0]); - - /* Now load B and see if we can find an object from testrepo.git */ - cl_git_pass(git_repository_open(&repo, paths[1])); - git_oid_fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - git_commit_free(commit); - git_repository_free(repo); -} - -void test_odb_alternates__long_chain(void) -{ - git_commit *commit; - git_oid oid; - size_t i; - - /* Set the alternate A -> testrepo.git */ - init_linked_repo(paths[0], cl_fixture("testrepo.git")); - - /* Set up the five-element chain */ - for (i = 1; i < ARRAY_SIZE(paths); i++) { - init_linked_repo(paths[i], paths[i-1]); - } - - /* Now load the last one and see if we can find an object from testrepo.git */ - cl_git_pass(git_repository_open(&repo, paths[ARRAY_SIZE(paths)-1])); - git_oid_fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - cl_git_fail(git_commit_lookup(&commit, repo, &oid)); - git_repository_free(repo); -} diff --git a/tests-clar/odb/backend/nonrefreshing.c b/tests-clar/odb/backend/nonrefreshing.c deleted file mode 100644 index b43529479..000000000 --- a/tests-clar/odb/backend/nonrefreshing.c +++ /dev/null @@ -1,274 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/sys/odb_backend.h" -#include "repository.h" - -typedef struct fake_backend { - git_odb_backend parent; - - git_error_code error_code; - - int exists_calls; - int read_calls; - int read_header_calls; - int read_prefix_calls; -} fake_backend; - -static git_repository *_repo; -static fake_backend *_fake; -static git_oid _oid; - -static int fake_backend__exists(git_odb_backend *backend, const git_oid *oid) -{ - fake_backend *fake; - - GIT_UNUSED(oid); - - fake = (fake_backend *)backend; - - fake->exists_calls++; - - return (fake->error_code == GIT_OK); -} - -static int fake_backend__read( - void **buffer_p, size_t *len_p, git_otype *type_p, - git_odb_backend *backend, const git_oid *oid) -{ - fake_backend *fake; - - GIT_UNUSED(buffer_p); - GIT_UNUSED(len_p); - GIT_UNUSED(type_p); - GIT_UNUSED(oid); - - fake = (fake_backend *)backend; - - fake->read_calls++; - - *len_p = 0; - *buffer_p = NULL; - *type_p = GIT_OBJ_BLOB; - - return fake->error_code; -} - -static int fake_backend__read_header( - size_t *len_p, git_otype *type_p, - git_odb_backend *backend, const git_oid *oid) -{ - fake_backend *fake; - - GIT_UNUSED(len_p); - GIT_UNUSED(type_p); - GIT_UNUSED(oid); - - fake = (fake_backend *)backend; - - fake->read_header_calls++; - - *len_p = 0; - *type_p = GIT_OBJ_BLOB; - - return fake->error_code; -} - -static int fake_backend__read_prefix( - git_oid *out_oid, void **buffer_p, size_t *len_p, git_otype *type_p, - git_odb_backend *backend, const git_oid *short_oid, size_t len) -{ - fake_backend *fake; - - GIT_UNUSED(out_oid); - GIT_UNUSED(buffer_p); - GIT_UNUSED(len_p); - GIT_UNUSED(type_p); - GIT_UNUSED(short_oid); - GIT_UNUSED(len); - - fake = (fake_backend *)backend; - - fake->read_prefix_calls++; - - *len_p = 0; - *buffer_p = NULL; - *type_p = GIT_OBJ_BLOB; - - return fake->error_code; -} - -static void fake_backend__free(git_odb_backend *_backend) -{ - fake_backend *backend; - - backend = (fake_backend *)_backend; - - git__free(backend); -} - -static int build_fake_backend( - git_odb_backend **out, - git_error_code error_code) -{ - fake_backend *backend; - - backend = git__calloc(1, sizeof(fake_backend)); - GITERR_CHECK_ALLOC(backend); - - backend->parent.version = GIT_ODB_BACKEND_VERSION; - - backend->parent.refresh = NULL; - backend->error_code = error_code; - - backend->parent.read = fake_backend__read; - backend->parent.read_prefix = fake_backend__read_prefix; - backend->parent.read_header = fake_backend__read_header; - backend->parent.exists = fake_backend__exists; - backend->parent.free = &fake_backend__free; - - *out = (git_odb_backend *)backend; - - return 0; -} - -static void setup_repository_and_backend(git_error_code error_code) -{ - git_odb *odb = NULL; - git_odb_backend *backend = NULL; - - _repo = cl_git_sandbox_init("testrepo.git"); - - cl_git_pass(build_fake_backend(&backend, error_code)); - - cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); - cl_git_pass(git_odb_add_backend(odb, backend, 10)); - - _fake = (fake_backend *)backend; - - cl_git_pass(git_oid_fromstr(&_oid, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")); -} - -void test_odb_backend_nonrefreshing__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_odb_backend_nonrefreshing__exists_is_invoked_once_on_failure(void) -{ - git_odb *odb; - - setup_repository_and_backend(GIT_ENOTFOUND); - - cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); - cl_assert_equal_b(false, git_odb_exists(odb, &_oid)); - - cl_assert_equal_i(1, _fake->exists_calls); -} - -void test_odb_backend_nonrefreshing__read_is_invoked_once_on_failure(void) -{ - git_object *obj; - - setup_repository_and_backend(GIT_ENOTFOUND); - - cl_git_fail_with( - git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY), - GIT_ENOTFOUND); - - cl_assert_equal_i(1, _fake->read_calls); -} - -void test_odb_backend_nonrefreshing__readprefix_is_invoked_once_on_failure(void) -{ - git_object *obj; - - setup_repository_and_backend(GIT_ENOTFOUND); - - cl_git_fail_with( - git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY), - GIT_ENOTFOUND); - - cl_assert_equal_i(1, _fake->read_prefix_calls); -} - -void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_failure(void) -{ - git_odb *odb; - size_t len; - git_otype type; - - setup_repository_and_backend(GIT_ENOTFOUND); - - cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); - - cl_git_fail_with( - git_odb_read_header(&len, &type, odb, &_oid), - GIT_ENOTFOUND); - - cl_assert_equal_i(1, _fake->read_header_calls); -} - -void test_odb_backend_nonrefreshing__exists_is_invoked_once_on_success(void) -{ - git_odb *odb; - - setup_repository_and_backend(GIT_OK); - - cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); - cl_assert_equal_b(true, git_odb_exists(odb, &_oid)); - - cl_assert_equal_i(1, _fake->exists_calls); -} - -void test_odb_backend_nonrefreshing__read_is_invoked_once_on_success(void) -{ - git_object *obj; - - setup_repository_and_backend(GIT_OK); - - cl_git_pass(git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY)); - - cl_assert_equal_i(1, _fake->read_calls); - - git_object_free(obj); -} - -void test_odb_backend_nonrefreshing__readprefix_is_invoked_once_on_success(void) -{ - git_object *obj; - - setup_repository_and_backend(GIT_OK); - - cl_git_pass(git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY)); - - cl_assert_equal_i(1, _fake->read_prefix_calls); - - git_object_free(obj); -} - -void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_success(void) -{ - git_odb *odb; - size_t len; - git_otype type; - - setup_repository_and_backend(GIT_OK); - - cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); - - cl_git_pass(git_odb_read_header(&len, &type, odb, &_oid)); - - cl_assert_equal_i(1, _fake->read_header_calls); -} - -void test_odb_backend_nonrefreshing__read_is_invoked_once_when_revparsing_a_full_oid(void) -{ - git_object *obj; - - setup_repository_and_backend(GIT_ENOTFOUND); - - cl_git_fail_with( - git_revparse_single(&obj, _repo, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"), - GIT_ENOTFOUND); - - cl_assert_equal_i(1, _fake->read_calls); -} diff --git a/tests-clar/odb/foreach.c b/tests-clar/odb/foreach.c deleted file mode 100644 index f643d9621..000000000 --- a/tests-clar/odb/foreach.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "clar_libgit2.h" -#include "odb.h" -#include "git2/odb_backend.h" -#include "pack.h" - -static git_odb *_odb; -static git_repository *_repo; -static int nobj; - -void test_odb_foreach__cleanup(void) -{ - git_odb_free(_odb); - git_repository_free(_repo); - - _odb = NULL; - _repo = NULL; -} - -static int foreach_cb(const git_oid *oid, void *data) -{ - GIT_UNUSED(data); - GIT_UNUSED(oid); - - nobj++; - - return 0; -} - -/* - * $ git --git-dir tests-clar/resources/testrepo.git count-objects --verbose - * count: 47 - * size: 4 - * in-pack: 1640 - * packs: 3 - * size-pack: 425 - * prune-packable: 0 - * garbage: 0 - */ -void test_odb_foreach__foreach(void) -{ - cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); - git_repository_odb(&_odb, _repo); - - cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL)); - cl_assert_equal_i(47 + 1640, nobj); /* count + in-pack */ -} - -void test_odb_foreach__one_pack(void) -{ - git_odb_backend *backend = NULL; - - cl_git_pass(git_odb_new(&_odb)); - cl_git_pass(git_odb_backend_one_pack(&backend, cl_fixture("testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx"))); - cl_git_pass(git_odb_add_backend(_odb, backend, 1)); - _repo = NULL; - - nobj = 0; - cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL)); - cl_assert(nobj == 1628); -} - -static int foreach_stop_cb(const git_oid *oid, void *data) -{ - GIT_UNUSED(data); - GIT_UNUSED(oid); - - nobj++; - - return (nobj == 1000); -} - -void test_odb_foreach__interrupt_foreach(void) -{ - nobj = 0; - cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); - git_repository_odb(&_odb, _repo); - - cl_assert_equal_i(GIT_EUSER, git_odb_foreach(_odb, foreach_stop_cb, NULL)); - cl_assert(nobj == 1000); -} diff --git a/tests-clar/odb/loose.c b/tests-clar/odb/loose.c deleted file mode 100644 index a85f1430d..000000000 --- a/tests-clar/odb/loose.c +++ /dev/null @@ -1,146 +0,0 @@ -#include "clar_libgit2.h" -#include "odb.h" -#include "git2/odb_backend.h" -#include "posix.h" -#include "loose_data.h" - -#ifdef __ANDROID_API__ -# define S_IREAD S_IRUSR -# define S_IWRITE S_IWUSR -#endif - -static void write_object_files(object_data *d) -{ - int fd; - - if (p_mkdir(d->dir, GIT_OBJECT_DIR_MODE) < 0) - cl_assert(errno == EEXIST); - - cl_assert((fd = p_creat(d->file, S_IREAD | S_IWRITE)) >= 0); - cl_must_pass(p_write(fd, d->bytes, d->blen)); - - p_close(fd); -} - -static void cmp_objects(git_rawobj *o, object_data *d) -{ - cl_assert(o->type == git_object_string2type(d->type)); - cl_assert(o->len == d->dlen); - - if (o->len > 0) - cl_assert(memcmp(o->data, d->data, o->len) == 0); -} - -static void test_read_object(object_data *data) -{ - git_oid id; - git_odb_object *obj; - git_odb *odb; - git_rawobj tmp; - - write_object_files(data); - - cl_git_pass(git_odb_open(&odb, "test-objects")); - cl_git_pass(git_oid_fromstr(&id, data->id)); - cl_git_pass(git_odb_read(&obj, odb, &id)); - - tmp.data = obj->buffer; - tmp.len = obj->cached.size; - tmp.type = obj->cached.type; - - cmp_objects(&tmp, data); - - git_odb_object_free(obj); - git_odb_free(odb); -} - -void test_odb_loose__initialize(void) -{ - cl_must_pass(p_mkdir("test-objects", GIT_OBJECT_DIR_MODE)); -} - -void test_odb_loose__cleanup(void) -{ - cl_fixture_cleanup("test-objects"); -} - -void test_odb_loose__exists(void) -{ - git_oid id, id2; - git_odb *odb; - - write_object_files(&one); - cl_git_pass(git_odb_open(&odb, "test-objects")); - - cl_git_pass(git_oid_fromstr(&id, one.id)); - - cl_assert(git_odb_exists(odb, &id)); - - /* Test for a non-existant object */ - cl_git_pass(git_oid_fromstr(&id2, "8b137891791fe96927ad78e64b0aad7bded08baa")); - cl_assert(!git_odb_exists(odb, &id2)); - - git_odb_free(odb); -} - -void test_odb_loose__simple_reads(void) -{ - test_read_object(&commit); - test_read_object(&tree); - test_read_object(&tag); - test_read_object(&zero); - test_read_object(&one); - test_read_object(&two); - test_read_object(&some); -} - -void test_write_object_permission( - mode_t dir_mode, mode_t file_mode, - mode_t expected_dir_mode, mode_t expected_file_mode) -{ - git_odb *odb; - git_odb_backend *backend; - git_oid oid; - struct stat statbuf; - mode_t mask, os_mask; - - /* Windows does not return group/user bits from stat, - * files are never executable. - */ -#ifdef GIT_WIN32 - os_mask = 0600; -#else - os_mask = 0777; -#endif - - mask = p_umask(0); - p_umask(mask); - - cl_git_pass(git_odb_new(&odb)); - cl_git_pass(git_odb_backend_loose(&backend, "test-objects", -1, 0, dir_mode, file_mode)); - 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)); - - cl_git_pass(p_stat("test-objects/67", &statbuf)); - cl_assert_equal_i(statbuf.st_mode & os_mask, (expected_dir_mode & ~mask) & os_mask); - - cl_git_pass(p_stat("test-objects/67/b808feb36201507a77f85e6d898f0a2836e4a5", &statbuf)); - cl_assert_equal_i(statbuf.st_mode & os_mask, (expected_file_mode & ~mask) & os_mask); - - git_odb_free(odb); -} - -void test_odb_loose__permissions_standard(void) -{ - test_write_object_permission(0, 0, GIT_OBJECT_DIR_MODE, GIT_OBJECT_FILE_MODE); -} - -void test_odb_loose_permissions_readonly(void) -{ - test_write_object_permission(0777, 0444, 0777, 0444); -} - -void test_odb_loose__permissions_readwrite(void) -{ - test_write_object_permission(0777, 0666, 0777, 0666); -} diff --git a/tests-clar/odb/loose_data.h b/tests-clar/odb/loose_data.h deleted file mode 100644 index c10c9bc7f..000000000 --- a/tests-clar/odb/loose_data.h +++ /dev/null @@ -1,522 +0,0 @@ -typedef struct object_data { - unsigned char *bytes; /* (compressed) bytes stored in object store */ - size_t blen; /* length of data in object store */ - char *id; /* object id (sha1) */ - char *type; /* object type */ - char *dir; /* object store (fan-out) directory name */ - char *file; /* object store filename */ - unsigned char *data; /* (uncompressed) object data */ - size_t dlen; /* length of (uncompressed) object data */ -} object_data; - -/* one == 8b137891791fe96927ad78e64b0aad7bded08bdc */ -static unsigned char one_bytes[] = { - 0x31, 0x78, 0x9c, 0xe3, 0x02, 0x00, 0x00, 0x0b, - 0x00, 0x0b, -}; - -static unsigned char one_data[] = { - 0x0a, -}; - -static object_data one = { - one_bytes, - sizeof(one_bytes), - "8b137891791fe96927ad78e64b0aad7bded08bdc", - "blob", - "test-objects/8b", - "test-objects/8b/137891791fe96927ad78e64b0aad7bded08bdc", - one_data, - sizeof(one_data), -}; - - -/* commit == 3d7f8a6af076c8c3f20071a8935cdbe8228594d1 */ -static unsigned char commit_bytes[] = { - 0x78, 0x01, 0x85, 0x50, 0xc1, 0x6a, 0xc3, 0x30, - 0x0c, 0xdd, 0xd9, 0x5f, 0xa1, 0xfb, 0x96, 0x12, - 0xbb, 0x29, 0x71, 0x46, 0x19, 0x2b, 0x3d, 0x97, - 0x1d, 0xd6, 0x7d, 0x80, 0x1d, 0xcb, 0x89, 0x21, - 0xb6, 0x82, 0xed, 0x40, 0xf3, 0xf7, 0xf3, 0x48, - 0x29, 0x3b, 0x6d, 0xd2, 0xe5, 0xbd, 0x27, 0xbd, - 0x27, 0x50, 0x4f, 0xde, 0xbb, 0x0c, 0xfb, 0x43, - 0xf3, 0x94, 0x23, 0x22, 0x18, 0x6b, 0x85, 0x51, - 0x5d, 0xad, 0xc5, 0xa1, 0x41, 0xae, 0x51, 0x4b, - 0xd9, 0x19, 0x6e, 0x4b, 0x0b, 0x29, 0x35, 0x72, - 0x59, 0xef, 0x5b, 0x29, 0x8c, 0x65, 0x6a, 0xc9, - 0x23, 0x45, 0x38, 0xc1, 0x17, 0x5c, 0x7f, 0xc0, - 0x71, 0x13, 0xde, 0xf1, 0xa6, 0xfc, 0x3c, 0xe1, - 0xae, 0x27, 0xff, 0x06, 0x5c, 0x88, 0x56, 0xf2, - 0x46, 0x74, 0x2d, 0x3c, 0xd7, 0xa5, 0x58, 0x51, - 0xcb, 0xb9, 0x8c, 0x11, 0xce, 0xf0, 0x01, 0x97, - 0x0d, 0x1e, 0x1f, 0xea, 0x3f, 0x6e, 0x76, 0x02, - 0x0a, 0x58, 0x4d, 0x2e, 0x20, 0x6c, 0x1e, 0x48, - 0x8b, 0xf7, 0x2a, 0xae, 0x8c, 0x5d, 0x47, 0x04, - 0x4d, 0x66, 0x05, 0xb2, 0x90, 0x0b, 0xbe, 0xcf, - 0x3d, 0xa6, 0xa4, 0x06, 0x7c, 0x29, 0x3c, 0x64, - 0xe5, 0x82, 0x0b, 0x03, 0xd8, 0x25, 0x96, 0x8d, - 0x08, 0x78, 0x9b, 0x27, 0x15, 0x54, 0x76, 0x14, - 0xd8, 0xdd, 0x35, 0x2f, 0x71, 0xa6, 0x84, 0x8f, - 0x90, 0x51, 0x85, 0x01, 0x13, 0xb8, 0x90, 0x23, - 0x99, 0xa5, 0x47, 0x03, 0x7a, 0xfd, 0x15, 0xbf, - 0x63, 0xec, 0xd3, 0x0d, 0x01, 0x4d, 0x45, 0xb6, - 0xd2, 0xeb, 0xeb, 0xdf, 0xef, 0x60, 0xdf, 0xef, - 0x1f, 0x78, 0x35, -}; - -static unsigned char commit_data[] = { - 0x74, 0x72, 0x65, 0x65, 0x20, 0x64, 0x66, 0x66, - 0x32, 0x64, 0x61, 0x39, 0x30, 0x62, 0x32, 0x35, - 0x34, 0x65, 0x31, 0x62, 0x65, 0x62, 0x38, 0x38, - 0x39, 0x64, 0x31, 0x66, 0x31, 0x66, 0x31, 0x32, - 0x38, 0x38, 0x62, 0x65, 0x31, 0x38, 0x30, 0x33, - 0x37, 0x38, 0x32, 0x64, 0x66, 0x0a, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x20, 0x41, 0x20, 0x55, - 0x20, 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, - 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, - 0x6d, 0x3e, 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, - 0x31, 0x34, 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, - 0x30, 0x30, 0x30, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x74, 0x65, 0x72, 0x20, 0x43, 0x20, - 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72, - 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, - 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34, - 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30, - 0x30, 0x0a, 0x0a, 0x41, 0x20, 0x6f, 0x6e, 0x65, - 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x73, 0x75, 0x6d, - 0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x54, 0x68, - 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x6f, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, - 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72, - 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70, - 0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x0a, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x2d, 0x6f, 0x66, 0x2d, - 0x62, 0x79, 0x3a, 0x20, 0x41, 0x20, 0x55, 0x20, - 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, 0x61, - 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, - 0x3e, 0x0a, -}; - -static object_data commit = { - commit_bytes, - sizeof(commit_bytes), - "3d7f8a6af076c8c3f20071a8935cdbe8228594d1", - "commit", - "test-objects/3d", - "test-objects/3d/7f8a6af076c8c3f20071a8935cdbe8228594d1", - commit_data, - sizeof(commit_data), -}; - -/* tree == dff2da90b254e1beb889d1f1f1288be1803782df */ -static unsigned char tree_bytes[] = { - 0x78, 0x01, 0x2b, 0x29, 0x4a, 0x4d, 0x55, 0x30, - 0x34, 0x32, 0x63, 0x30, 0x34, 0x30, 0x30, 0x33, - 0x31, 0x51, 0xc8, 0xcf, 0x4b, 0x65, 0xe8, 0x16, - 0xae, 0x98, 0x58, 0x29, 0xff, 0x32, 0x53, 0x7d, - 0x6d, 0xc5, 0x33, 0x6f, 0xae, 0xb5, 0xd5, 0xf7, - 0x2e, 0x74, 0xdf, 0x81, 0x4a, 0x17, 0xe7, 0xe7, - 0xa6, 0x32, 0xfc, 0x6d, 0x31, 0xd8, 0xd3, 0xe6, - 0xf3, 0xe7, 0xea, 0x47, 0xbe, 0xd0, 0x09, 0x3f, - 0x96, 0xb8, 0x3f, 0x90, 0x9e, 0xa2, 0xfd, 0x0f, - 0x2a, 0x5f, 0x52, 0x9e, 0xcf, 0x50, 0x31, 0x43, - 0x52, 0x29, 0xd1, 0x5a, 0xeb, 0x77, 0x82, 0x2a, - 0x8b, 0xfe, 0xb7, 0xbd, 0xed, 0x5d, 0x07, 0x67, - 0xfa, 0xb5, 0x42, 0xa5, 0xab, 0x52, 0x8b, 0xf2, - 0x19, 0x9e, 0xcd, 0x7d, 0x34, 0x7b, 0xd3, 0xc5, - 0x6b, 0xce, 0xde, 0xdd, 0x9a, 0xeb, 0xca, 0xa3, - 0x6e, 0x1c, 0x7a, 0xd2, 0x13, 0x3c, 0x11, 0x00, - 0xe2, 0xaa, 0x38, 0x57, -}; - -static unsigned char tree_data[] = { - 0x31, 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x6f, - 0x6e, 0x65, 0x00, 0x8b, 0x13, 0x78, 0x91, 0x79, - 0x1f, 0xe9, 0x69, 0x27, 0xad, 0x78, 0xe6, 0x4b, - 0x0a, 0xad, 0x7b, 0xde, 0xd0, 0x8b, 0xdc, 0x31, - 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x73, 0x6f, - 0x6d, 0x65, 0x00, 0xfd, 0x84, 0x30, 0xbc, 0x86, - 0x4c, 0xfc, 0xd5, 0xf1, 0x0e, 0x55, 0x90, 0xf8, - 0xa4, 0x47, 0xe0, 0x1b, 0x94, 0x2b, 0xfe, 0x31, - 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x74, 0x77, - 0x6f, 0x00, 0x78, 0x98, 0x19, 0x22, 0x61, 0x3b, - 0x2a, 0xfb, 0x60, 0x25, 0x04, 0x2f, 0xf6, 0xbd, - 0x87, 0x8a, 0xc1, 0x99, 0x4e, 0x85, 0x31, 0x30, - 0x30, 0x36, 0x34, 0x34, 0x20, 0x7a, 0x65, 0x72, - 0x6f, 0x00, 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, - 0xd6, 0x43, 0x4b, 0x8b, 0x29, 0xae, 0x77, 0x5a, - 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91, -}; - -static object_data tree = { - tree_bytes, - sizeof(tree_bytes), - "dff2da90b254e1beb889d1f1f1288be1803782df", - "tree", - "test-objects/df", - "test-objects/df/f2da90b254e1beb889d1f1f1288be1803782df", - tree_data, - sizeof(tree_data), -}; - -/* tag == 09d373e1dfdc16b129ceec6dd649739911541e05 */ -static unsigned char tag_bytes[] = { - 0x78, 0x01, 0x35, 0x4e, 0xcb, 0x0a, 0xc2, 0x40, - 0x10, 0xf3, 0xbc, 0x5f, 0x31, 0x77, 0xa1, 0xec, - 0xa3, 0xed, 0x6e, 0x41, 0x44, 0xf0, 0x2c, 0x5e, - 0xfc, 0x81, 0xe9, 0x76, 0xb6, 0xad, 0xb4, 0xb4, - 0x6c, 0x07, 0xd1, 0xbf, 0x77, 0x44, 0x0d, 0x39, - 0x84, 0x10, 0x92, 0x30, 0xf6, 0x60, 0xbc, 0xdb, - 0x2d, 0xed, 0x9d, 0x22, 0x83, 0xeb, 0x7c, 0x0a, - 0x58, 0x63, 0xd2, 0xbe, 0x8e, 0x21, 0xba, 0x64, - 0xb5, 0xf6, 0x06, 0x43, 0xe3, 0xaa, 0xd8, 0xb5, - 0x14, 0xac, 0x0d, 0x55, 0x53, 0x76, 0x46, 0xf1, - 0x6b, 0x25, 0x88, 0xcb, 0x3c, 0x8f, 0xac, 0x58, - 0x3a, 0x1e, 0xba, 0xd0, 0x85, 0xd8, 0xd8, 0xf7, - 0x94, 0xe1, 0x0c, 0x57, 0xb8, 0x8c, 0xcc, 0x22, - 0x0f, 0xdf, 0x90, 0xc8, 0x13, 0x3d, 0x71, 0x5e, - 0x27, 0x2a, 0xc4, 0x39, 0x82, 0xb1, 0xd6, 0x07, - 0x53, 0xda, 0xc6, 0xc3, 0x5e, 0x0b, 0x94, 0xba, - 0x0d, 0xe3, 0x06, 0x42, 0x1e, 0x08, 0x3e, 0x95, - 0xbf, 0x4b, 0x69, 0xc9, 0x90, 0x69, 0x22, 0xdc, - 0xe8, 0xbf, 0xf2, 0x06, 0x42, 0x9a, 0x36, 0xb1, -}; - -static unsigned char tag_data[] = { - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x33, - 0x64, 0x37, 0x66, 0x38, 0x61, 0x36, 0x61, 0x66, - 0x30, 0x37, 0x36, 0x63, 0x38, 0x63, 0x33, 0x66, - 0x32, 0x30, 0x30, 0x37, 0x31, 0x61, 0x38, 0x39, - 0x33, 0x35, 0x63, 0x64, 0x62, 0x65, 0x38, 0x32, - 0x32, 0x38, 0x35, 0x39, 0x34, 0x64, 0x31, 0x0a, - 0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x0a, 0x74, 0x61, 0x67, 0x20, - 0x76, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0a, 0x74, - 0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x43, 0x20, - 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72, - 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, - 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34, - 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30, - 0x30, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, - 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, - 0x61, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x30, - 0x2e, 0x30, 0x2e, 0x31, 0x0a, -}; - -static object_data tag = { - tag_bytes, - sizeof(tag_bytes), - "09d373e1dfdc16b129ceec6dd649739911541e05", - "tag", - "test-objects/09", - "test-objects/09/d373e1dfdc16b129ceec6dd649739911541e05", - tag_data, - sizeof(tag_data), -}; - -/* zero == e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 */ -static unsigned char zero_bytes[] = { - 0x78, 0x01, 0x4b, 0xca, 0xc9, 0x4f, 0x52, 0x30, - 0x60, 0x00, 0x00, 0x09, 0xb0, 0x01, 0xf0, -}; - -static unsigned char zero_data[] = { - 0x00 /* dummy data */ -}; - -static object_data zero = { - zero_bytes, - sizeof(zero_bytes), - "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", - "blob", - "test-objects/e6", - "test-objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391", - zero_data, - 0, -}; - -/* two == 78981922613b2afb6025042ff6bd878ac1994e85 */ -static unsigned char two_bytes[] = { - 0x78, 0x01, 0x4b, 0xca, 0xc9, 0x4f, 0x52, 0x30, - 0x62, 0x48, 0xe4, 0x02, 0x00, 0x0e, 0x64, 0x02, - 0x5d, -}; - -static unsigned char two_data[] = { - 0x61, 0x0a, -}; - -static object_data two = { - two_bytes, - sizeof(two_bytes), - "78981922613b2afb6025042ff6bd878ac1994e85", - "blob", - "test-objects/78", - "test-objects/78/981922613b2afb6025042ff6bd878ac1994e85", - two_data, - sizeof(two_data), -}; - -/* some == fd8430bc864cfcd5f10e5590f8a447e01b942bfe */ -static unsigned char some_bytes[] = { - 0x78, 0x01, 0x7d, 0x54, 0xc1, 0x4e, 0xe3, 0x30, - 0x10, 0xdd, 0x33, 0x5f, 0x31, 0xc7, 0x5d, 0x94, - 0xa5, 0x84, 0xd5, 0x22, 0xad, 0x7a, 0x0a, 0x15, - 0x85, 0x48, 0xd0, 0x56, 0x49, 0x2a, 0xd4, 0xa3, - 0x13, 0x4f, 0x88, 0x85, 0x63, 0x47, 0xb6, 0x43, - 0xc9, 0xdf, 0xef, 0x8c, 0x69, 0x17, 0x56, 0x0b, - 0x7b, 0xaa, 0x62, 0x7b, 0xde, 0xbc, 0xf7, 0xe6, - 0x4d, 0x6b, 0x6d, 0x6b, 0x48, 0xd3, 0xcb, 0x5f, - 0x5f, 0x66, 0xa7, 0x27, 0x70, 0x0a, 0x55, 0xa7, - 0x3c, 0xb4, 0x4a, 0x23, 0xf0, 0xaf, 0x43, 0x04, - 0x6f, 0xdb, 0xb0, 0x17, 0x0e, 0xe7, 0x30, 0xd9, - 0x11, 0x1a, 0x61, 0xc0, 0xa1, 0x54, 0x3e, 0x38, - 0x55, 0x8f, 0x81, 0x9e, 0x05, 0x10, 0x46, 0xce, - 0xac, 0x83, 0xde, 0x4a, 0xd5, 0x4e, 0x0c, 0x42, - 0x67, 0xa3, 0x91, 0xe8, 0x20, 0x74, 0x08, 0x01, - 0x5d, 0xef, 0xc1, 0xb6, 0xf1, 0xe3, 0x66, 0xb5, - 0x85, 0x1b, 0x34, 0xe8, 0x84, 0x86, 0xcd, 0x58, - 0x6b, 0xd5, 0xc0, 0x9d, 0x6a, 0xd0, 0x78, 0x4c, - 0xe0, 0x19, 0x9d, 0x57, 0xd6, 0xc0, 0x45, 0xc2, - 0x18, 0xc2, 0xc3, 0xc0, 0x0f, 0x7c, 0x87, 0x12, - 0xea, 0x29, 0x56, 0x2f, 0x99, 0x4f, 0x79, 0xe0, - 0x03, 0x4b, 0x4b, 0x4d, 0x44, 0xa0, 0x92, 0x33, - 0x2a, 0xe0, 0x9a, 0xdc, 0x80, 0x90, 0x52, 0xf1, - 0x11, 0x04, 0x1b, 0x4b, 0x06, 0xea, 0xae, 0x3c, - 0xe3, 0x7a, 0x50, 0x74, 0x4a, 0x84, 0xfe, 0xc3, - 0x81, 0x41, 0xf8, 0x89, 0x18, 0x43, 0x67, 0x9d, - 0x87, 0x47, 0xf5, 0x8c, 0x51, 0xf6, 0x68, 0xb4, - 0xea, 0x55, 0x20, 0x2a, 0x6f, 0x80, 0xdc, 0x42, - 0x2b, 0xf3, 0x14, 0x2b, 0x1a, 0xdb, 0x0f, 0xe4, - 0x9a, 0x64, 0x84, 0xa3, 0x90, 0xa8, 0xf9, 0x8f, - 0x9d, 0x86, 0x9e, 0xd3, 0xab, 0x5a, 0x99, 0xc8, - 0xd9, 0xc3, 0x5e, 0x85, 0x0e, 0x2c, 0xb5, 0x73, - 0x30, 0x38, 0xfb, 0xe8, 0x44, 0xef, 0x5f, 0x95, - 0x1b, 0xc9, 0xd0, 0xef, 0x3c, 0x26, 0x32, 0x1e, - 0xff, 0x2d, 0xb6, 0x23, 0x7b, 0x3f, 0xd1, 0x3c, - 0x78, 0x1a, 0x0d, 0xcb, 0xe6, 0xf6, 0xd4, 0x44, - 0x99, 0x47, 0x1a, 0x9e, 0xed, 0x23, 0xb5, 0x91, - 0x6a, 0xdf, 0x53, 0x39, 0x03, 0xf8, 0x5a, 0xb1, - 0x0f, 0x1f, 0xce, 0x81, 0x11, 0xde, 0x01, 0x7a, - 0x90, 0x16, 0xc4, 0x30, 0xe8, 0x89, 0xed, 0x7b, - 0x65, 0x4b, 0xd7, 0x03, 0x36, 0xc1, 0xcf, 0xa1, - 0xa5, 0xb1, 0xe3, 0x8b, 0xe8, 0x07, 0x4d, 0xf3, - 0x23, 0x25, 0x13, 0x35, 0x27, 0xf5, 0x8c, 0x11, - 0xd3, 0xa0, 0x9a, 0xa8, 0xf5, 0x38, 0x7d, 0xce, - 0x55, 0xc2, 0x71, 0x79, 0x13, 0xc7, 0xa3, 0xda, - 0x77, 0x68, 0xc0, 0xd8, 0x10, 0xdd, 0x24, 0x8b, - 0x15, 0x59, 0xc5, 0x10, 0xe2, 0x20, 0x99, 0x8e, - 0xf0, 0x05, 0x9b, 0x31, 0x88, 0x5a, 0xe3, 0xd9, - 0x37, 0xba, 0xe2, 0xdb, 0xbf, 0x92, 0xfa, 0x66, - 0x16, 0x97, 0x47, 0xd9, 0x9d, 0x1d, 0x28, 0x7c, - 0x9d, 0x08, 0x1c, 0xc7, 0xbd, 0xd2, 0x1a, 0x6a, - 0x04, 0xf2, 0xa2, 0x1d, 0x75, 0x02, 0x14, 0x5d, - 0xc6, 0x78, 0xc8, 0xab, 0xdb, 0xf5, 0xb6, 0x82, - 0x6c, 0xb5, 0x83, 0x87, 0xac, 0x28, 0xb2, 0x55, - 0xb5, 0x9b, 0xc7, 0xc1, 0xb0, 0xb7, 0xf8, 0x4c, - 0xbc, 0x38, 0x0e, 0x8a, 0x04, 0x2a, 0x62, 0x41, - 0x6b, 0xe0, 0x84, 0x09, 0x13, 0xe9, 0xe1, 0xea, - 0xfb, 0xeb, 0x62, 0x71, 0x4b, 0x25, 0xd9, 0x55, - 0x7e, 0x97, 0x57, 0x3b, 0x20, 0x33, 0x96, 0x79, - 0xb5, 0xba, 0x2e, 0x4b, 0x58, 0xae, 0x0b, 0xc8, - 0x60, 0x93, 0x15, 0x55, 0xbe, 0xd8, 0xde, 0x65, - 0x05, 0x6c, 0xb6, 0xc5, 0x66, 0x5d, 0x5e, 0x93, - 0xf7, 0x25, 0x65, 0x98, 0x41, 0x29, 0x86, 0x0c, - 0xf2, 0xf1, 0x14, 0xa2, 0xb3, 0xbd, 0x75, 0x08, - 0x12, 0x83, 0x50, 0xda, 0x1f, 0x23, 0xbe, 0xa3, - 0x1d, 0xf4, 0x9d, 0x1d, 0xb5, 0x84, 0x4e, 0x50, - 0x38, 0x1d, 0x36, 0x48, 0x21, 0x95, 0xd1, 0xac, - 0x81, 0x99, 0x1d, 0xc1, 0x3f, 0x41, 0xe6, 0x9e, - 0x42, 0x5b, 0x0a, 0x48, 0xcc, 0x5f, 0xe0, 0x7d, - 0x3f, 0xc4, 0x6f, 0x0e, 0xfe, 0xc0, 0x2d, 0xfe, - 0x01, 0x2c, 0xd6, 0x9b, 0x5d, 0xbe, 0xba, 0x21, - 0xca, 0x79, 0xcb, 0xe3, 0x49, 0x60, 0xef, 0x68, - 0x05, 0x28, 0x9b, 0x8c, 0xc1, 0x12, 0x3e, 0xdb, - 0xc7, 0x04, 0x7e, 0xa6, 0x74, 0x29, 0xcc, 0x13, - 0xed, 0x07, 0x94, 0x81, 0xd6, 0x96, 0xaa, 0x97, - 0xaa, 0xa5, 0xc0, 0x2f, 0xb5, 0xb5, 0x2e, 0xe6, - 0xfc, 0xca, 0xfa, 0x60, 0x4d, 0x02, 0xf7, 0x19, - 0x9c, 0x5f, 0xa4, 0xe9, 0xf9, 0xf7, 0xf4, 0xc7, - 0x79, 0x9a, 0xc0, 0xb6, 0xcc, 0x58, 0xec, 0xec, - 0xe4, 0x37, 0x22, 0xfa, 0x8b, 0x53, -}; - -static unsigned char some_data[] = { - 0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68, - 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, - 0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, - 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, - 0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, - 0x6e, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69, - 0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, - 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0a, - 0x20, 0x2a, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e, - 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, - 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, - 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, - 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, - 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x2a, 0x20, 0x61, - 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, - 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, - 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, - 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x2a, 0x0a, - 0x20, 0x2a, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, - 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, - 0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x20, 0x2a, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, - 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x6c, - 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x70, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e, - 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, - 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20, - 0x2a, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, - 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69, - 0x6e, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x62, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74, - 0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x67, - 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0a, 0x20, 0x2a, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, - 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, - 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, - 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e, - 0x79, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x2a, - 0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20, - 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, - 0x65, 0x2e, 0x20, 0x20, 0x28, 0x54, 0x68, 0x65, - 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, - 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, - 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, - 0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, - 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, - 0x64, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79, - 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65, - 0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, - 0x74, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, - 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x0a, 0x20, 0x2a, 0x20, 0x6d, - 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e, - 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65, - 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x0a, 0x20, - 0x2a, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62, - 0x69, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, - 0x29, 0x0a, 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, - 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, - 0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, - 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61, - 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, - 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, - 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74, - 0x0a, 0x20, 0x2a, 0x20, 0x57, 0x49, 0x54, 0x48, - 0x4f, 0x55, 0x54, 0x20, 0x41, 0x4e, 0x59, 0x20, - 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59, - 0x3b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, - 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69, - 0x65, 0x64, 0x20, 0x77, 0x61, 0x72, 0x72, 0x61, - 0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x0a, 0x20, - 0x2a, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41, - 0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, - 0x59, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x49, 0x54, - 0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52, - 0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49, - 0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55, - 0x52, 0x50, 0x4f, 0x53, 0x45, 0x2e, 0x20, 0x20, - 0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x47, 0x4e, 0x55, 0x0a, 0x20, 0x2a, 0x20, 0x47, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, - 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x64, - 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a, - 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x59, 0x6f, - 0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, - 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x72, 0x65, - 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, - 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, - 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, - 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, - 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, - 0x20, 0x2a, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, - 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, - 0x61, 0x6d, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, - 0x20, 0x43, 0x4f, 0x50, 0x59, 0x49, 0x4e, 0x47, - 0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, - 0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, - 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x2a, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, - 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, - 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x35, 0x31, 0x20, - 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x6c, 0x69, 0x6e, - 0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2c, - 0x20, 0x46, 0x69, 0x66, 0x74, 0x68, 0x20, 0x46, - 0x6c, 0x6f, 0x6f, 0x72, 0x2c, 0x0a, 0x20, 0x2a, - 0x20, 0x42, 0x6f, 0x73, 0x74, 0x6f, 0x6e, 0x2c, - 0x20, 0x4d, 0x41, 0x20, 0x30, 0x32, 0x31, 0x31, - 0x30, 0x2d, 0x31, 0x33, 0x30, 0x31, 0x2c, 0x20, - 0x55, 0x53, 0x41, 0x2e, 0x0a, 0x20, 0x2a, 0x2f, - 0x0a, -}; - -static object_data some = { - some_bytes, - sizeof(some_bytes), - "fd8430bc864cfcd5f10e5590f8a447e01b942bfe", - "blob", - "test-objects/fd", - "test-objects/fd/8430bc864cfcd5f10e5590f8a447e01b942bfe", - some_data, - sizeof(some_data), -}; diff --git a/tests-clar/odb/mixed.c b/tests-clar/odb/mixed.c deleted file mode 100644 index 51970ceec..000000000 --- a/tests-clar/odb/mixed.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "clar_libgit2.h" -#include "odb.h" - -static git_odb *_odb; - -void test_odb_mixed__initialize(void) -{ - cl_git_pass(git_odb_open(&_odb, cl_fixture("duplicate.git/objects"))); -} - -void test_odb_mixed__cleanup(void) -{ - git_odb_free(_odb); - _odb = NULL; -} - -void test_odb_mixed__dup_oid(void) { - const char hex[] = "ce013625030ba8dba906f756967f9e9ca394464a"; - const char short_hex[] = "ce01362"; - git_oid oid; - git_odb_object *obj; - - cl_git_pass(git_oid_fromstr(&oid, hex)); - cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, GIT_OID_HEXSZ)); - git_odb_object_free(obj); - cl_git_pass(git_oid_fromstrn(&oid, short_hex, sizeof(short_hex) - 1)); - cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, sizeof(short_hex) - 1)); - git_odb_object_free(obj); -} - -/* some known sha collisions of file content: - * 'aabqhq' and 'aaazvc' with prefix 'dea509d0' (+ '9' and + 'b') - * 'aaeufo' and 'aaaohs' with prefix '81b5bff5' (+ 'f' and + 'b') - * 'aafewy' and 'aaepta' with prefix '739e3c4c' - * 'aahsyn' and 'aadrjg' with prefix '0ddeaded' (+ '9' and + 'e') - */ - -void test_odb_mixed__dup_oid_prefix_0(void) { - char hex[10]; - git_oid oid; - git_odb_object *obj; - - /* ambiguous in the same pack file */ - - strncpy(hex, "dea509d0", sizeof(hex)); - cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); - cl_assert_equal_i( - GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); - - strncpy(hex, "dea509d09", sizeof(hex)); - cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); - cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); - git_odb_object_free(obj); - - strncpy(hex, "dea509d0b", sizeof(hex)); - cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); - cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); - git_odb_object_free(obj); - - /* ambiguous in different pack files */ - - strncpy(hex, "81b5bff5", sizeof(hex)); - cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); - cl_assert_equal_i( - GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); - - strncpy(hex, "81b5bff5b", sizeof(hex)); - cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); - cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); - git_odb_object_free(obj); - - strncpy(hex, "81b5bff5f", sizeof(hex)); - cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); - cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); - git_odb_object_free(obj); - - /* ambiguous in pack file and loose */ - - strncpy(hex, "0ddeaded", sizeof(hex)); - cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); - cl_assert_equal_i( - GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); - - strncpy(hex, "0ddeaded9", sizeof(hex)); - cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); - cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); - git_odb_object_free(obj); - - strncpy(hex, "0ddeadede", sizeof(hex)); - cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); - cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); - git_odb_object_free(obj); -} diff --git a/tests-clar/odb/pack_data.h b/tests-clar/odb/pack_data.h deleted file mode 100644 index e6371beb1..000000000 --- a/tests-clar/odb/pack_data.h +++ /dev/null @@ -1,151 +0,0 @@ - -static const char *packed_objects[] = { - "0266163a49e280c4f5ed1e08facd36a2bd716bcf", - "53fc32d17276939fc79ed05badaef2db09990016", - "6336846bd5c88d32f93ae57d846683e61ab5c530", - "6dcf9bf7541ee10456529833502442f385010c3d", - "bed08a0b30b72a9d4aed7f1af8c8ca124e8d64b9", - "e90810b8df3e80c413d903f631643c716887138d", - "fc3c3a2083e9f6f89e6bd53e9420e70d1e357c9b", - "fc58168adf502d0c0ef614c3111a7038fc8c09c8", - "fd0ec0333948dfe23265ac46be0205a436a8c3a5", - "fd8430bc864cfcd5f10e5590f8a447e01b942bfe", - "fd899f45951c15c1c5f7c34b1c864e91bd6556c6", - "fda23b974899e7e1f938619099280bfda13bdca9", - "fdbec189efb657c8325962b494875987881a356b", - "fe1ca6bd22b5d8353ce6c2f3aba80805c438a7a5", - "fe3a6a42c87ff1239370c741a265f3997add87c1", - "deb106bfd2d36ecf9f0079224c12022201a39ad1", - "dec93efc79e60f2680de3e666755d335967eec30", - "def425bf8568b9c1e20879bf5be6f9c52b7361c4", - "df48000ac4f48570054e3a71a81916357997b680", - "dfae6ed8f6dd8acc3b40a31811ea316239223559", - "dff79e27d3d2cdc09790ded80fe2ea8ff5d61034", - "e00e46abe4c542e17c8bc83d72cf5be8018d7b0e", - "e01b107b4f77f8f98645adac0206a504f2d29d7c", - "e032d863f512c47b479bd984f8b6c8061f66b7d4", - "e044baa468a1c74f9f9da36805445f6888358b49", - "e04529998989ba8ae3419538dd57969af819b241", - "e0637ddfbea67c8d7f557c709e095af8906e9176", - "e0743ad4031231e71700abdc6fdbe94f189d20e5", - "cf33ac7a3d8b2b8f6bb266518aadbf59de397608", - "cf5f7235b9c9689b133f6ea12015720b411329bd", - "cf6cccf1297284833a9a03138a1f5738fa1c6c94", - "cf7992bde17ce7a79cab5f0c1fcbe8a0108721ed", - "cfe3a027ab12506d4144ee8a35669ae8fc4b7ab1", - "cfe96f31dfad7bab49977aa1df7302f7fafcb025", - "cff54d138945ef4de384e9d2759291d0c13ea90a", - "d01f7573ac34c2f502bd1cf18cde73480c741151", - "d03f567593f346a1ca96a57f8191def098d126e3", - "d047b47aadf88501238f36f5c17dd0a50dc62087", - "d0a0d63086fae3b0682af7261df21f7d0f7f066d", - "d0a44bd6ed0be21b725a96c0891bbc79bc1a540c", - "d0d7e736e536a41bcb885005f8bf258c61cad682", - "d0e7959d4b95ffec6198df6f5a7ae259b23a5f50", - "bf2fe2acca17d13356ce802ba9dc8343f710dfb7", - "bf55f407d6d9418e51f42ea7a3a6aadf17388349", - "bf92206f8b633b88a66dca4a911777630b06fbac", - "bfaf8c42eb8842abe206179fee864cfba87e3ca9", - "bfe05675d4e8f6b59d50932add8790f1a06b10ee", - "bff8618112330763327cfa6ce6e914db84f51ddf", - "bff873e9853ed99fed52c25f7ad29f78b27dcec2", - "c01c3fae7251098d7af1b459bcd0786e81d4616d", - "c0220fca67f48b8a5d4163d53b1486224be3a198", - "c02d0b160b82ee72469c269f13de4c26a7ea09cb", - "c059510ad1b45ab58390e042d7dee1ac46703854", - "c07204a1897aeeaa3c248d29dbfa9b033baf9755", - "c073337a4dd7276931b4b3fdbc3f0040e9441793", - "0fd7e4bfba5b3a82be88d1057757ca8b2c5e6d26", - "100746511cc45c9f1ad6721c4ef5be49222fee4d", - "1088490171d9b984d68b8b9be9ca003f4eafff59", - "1093c8ff4cb78fcf5f79dbbeedcb6e824bd4e253", - "10aa3fa72afab7ee31e116ae06442fe0f7b79df2", - "10b759e734e8299aa0dca08be935d95d886127b6", - "111d5ccf0bb010c4e8d7af3eedfa12ef4c5e265b", - "11261fbff21758444d426356ff6327ee01e90752", - "112998d425717bb922ce74e8f6f0f831d8dc4510", - "2ef4e5d838b6507bd61d457cf6466662b791c5c0", - "2ef4faa0f82efa00eeac6cae9e8b2abccc8566ee", - "2f06098183b0d7be350acbe39cdbaccff2df0c4a", - "2f1c5d509ac5bffb3c62f710a1c2c542e126dfd1", - "2f205b20fc16423c42b3ba51b2ea78d7b9ff3578", - "2f9b6b6e3d9250ba09360734aa47973a993b59d1", - "30c62a2d5a8d644f1311d4f7fe3f6a788e4c8188", - "31438e245492d85fd6da4d1406eba0fbde8332a4", - "3184a3abdfea231992254929ff4e275898e5bbf6", - "3188ffdbb3a3d52e0f78f30c484533899224436e", - "32581d0093429770d044a60eb0e9cc0462bedb13", - "32679a9544d83e5403202c4d5efb61ad02492847", - "4e7e9f60b7e2049b7f5697daf133161a18ef688f", - "4e8cda27ddc8be7db875ceb0f360c37734724c6d", - "4ea481c61c59ab55169b7cbaae536ad50b49d6f0", - "4f0adcd0e61eabe06fe32be66b16559537124b7a", - "4f1355c91100d12f9e7202f91b245df0c110867c", - "4f6eadeb08b9d0d1e8b1b3eac8a34940adf29a2d", - "4f9339df943c53117a5fc8e86e2f38716ff3a668", - "4fc3874b118752e40de556b1c3e7b4a9f1737d00", - "4ff1dd0992dd6baafdb5e166be6f9f23b59bdf87", - "5018a35e0b7e2eec7ce5050baf9c7343f3f74164", - "50298f44a45eda3a29dae82dbe911b5aa176ac07", - "502acd164fb115768d723144da2e7bb5a24891bb", - "50330c02bd4fd95c9db1fcf2f97f4218e42b7226", - "5052bf355d9f8c52446561a39733a8767bf31e37", - "6f2cd729ae42988c1dd43588d3a6661ba48ad7a0", - "6f4e2c42d9138bfbf3e0f908f1308828cc6f2178", - "6f6a17db05a83620cef4572761831c20a70ba9b9", - "6faad60901e36538634f0d8b8ff3f21f83503c71", - "6fc72e46de3df0c3842dab302bbacf697a63abab", - "6fdccd49f442a7204399ca9b418f017322dbded8", - "6fe7568fc3861c334cb008fd85d57d9647249ef5", - "700f55d91d7b55665594676a4bada1f1457a0598", - "702bd70595a7b19afc48a1f784a6505be68469d4", - "7033f9ee0e52b08cb5679cd49b7b7999eaf9eaf8", - "70957110ce446c4e250f865760fb3da513cdcc92", - "8ec696a4734f16479d091bc70574d23dd9fe7443", - "8ed341c55ed4d6f4cdc8bf4f0ca18a08c93f6962", - "8edc2805f1f11b63e44bf81f4557f8b473612b69", - "8ef9060a954118a698fc10e20acdc430566a100f", - "8f0c4b543f4bb6eb1518ecfc3d4699e43108d393", - "8fac94df3035405c2e60b3799153ce7c428af6b9", - "904c0ac12b23548de524adae712241b423d765a3", - "90bbaa9a809c3a768d873a9cc7d52b4f3bf3d1b9", - "90d4d2f0fc362beabbbf76b4ffda0828229c198d", - "90f9ff6755330b685feff6c3d81782ee3592ab04", - "91822c50ebe4f9bf5bbb8308ecf9f6557062775c", - "91d973263a55708fa8255867b3202d81ef9c2868", - "af292c99c6148d772af3315a1c74e83330e7ead7", - "af3b99d5be330dbbce0b9250c3a5fb05911908cc", - "af55d0cdeb280af2db8697e5afa506e081012719", - "af795e498d411142ddb073e8ca2c5447c3295a4c", - "afadc73a392f8cc8e2cc77dd62a7433dd3bafa8c", - "affd84ed8ec7ce67612fe3c12a80f8164b101f6a", - "b0941f9c70ffe67f0387a827b338e64ecf3190f0", - "b0a3077f9ef6e093f8d9869bdb0c07095bd722cb", - "b0a8568a7614806378a54db5706ee3b06ae58693", - "b0fb7372f242233d1d35ce7d8e74d3990cbc5841", - "b10489944b9ead17427551759d180d10203e06ba", - "b196a807b323f2748ffc6b1d42cd0812d04c9a40", - "b1bb1d888f0c5e19278536d49fa77db035fac7ae" -}; - -static const char *loose_objects[] = { - "45b983be36b73c0788dc9cbcb76cbb80fc7bb057", - "a8233120f6ad708f843d861ce2b7228ec4e3dec6", - "fd093bff70906175335656e6ce6ae05783708765", - "c47800c7266a2be04c571c04d5a6614691ea99bd", - "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd", - "8496071c1b46c854b31185ea97743be6a8774479", - "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", - "814889a078c031f61ed08ab5fa863aea9314344d", - "5b5b025afb0b4c913b4c338a42934a3863bf3644", - "1385f264afb75a56a5bec74243be9b367ba4ca08", - "f60079018b664e4e79329a7ef9559c8d9e0378d1", - "be3563ae3f795b2b4353bcce3a527ad0a4f7f644", - "75057dd4114e74cca1d750d0aee1647c903cb60a", - "fa49b077972391ad58037050f2a75f74e3671e92", - "9fd738e8f7967c078dceed8190330fc8648ee56a", - "1810dff58d8a660512d4832e740f692884338ccd", - "181037049a54a1eb5fab404658a3a250b44335d7", - "a4a7dce85cf63874e984719f4fdd239f5145052f", - "4a202b346bb0fb0db7eff3cffeb3c70babbd2045" -}; diff --git a/tests-clar/odb/pack_data_one.h b/tests-clar/odb/pack_data_one.h deleted file mode 100644 index 13570ba78..000000000 --- a/tests-clar/odb/pack_data_one.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Just a few to make sure it's working, the rest is tested already */ -static const char *packed_objects_one[] = { - "9fcf811e00fa469688943a9152c16d4ee90fb9a9", - "a93f42a5b5e9de40fa645a9ff1e276a021c9542b", - "12bf5f3e3470d90db177ccf1b5e8126409377fc6", - "ed1ea164cdbe3c4b200fb4fa19861ea90eaee222", - "dfae6ed8f6dd8acc3b40a31811ea316239223559", - "aefe66d192771201e369fde830530f4475beec30", - "775e4b4c1296e9e3104f2a36ca9cf9356a130959", - "412ec4e4a6a7419bc1be00561fe474e54cb499fe", - "236e7579fed7763be77209efb8708960982f3cb3", - "09fe9364461cf60dd1c46b0e9545b1e47bb1a297", - "d76d8a6390d1cf32138d98a91b1eb7e0275a12f5", - "d0fdf2dcff2f548952eec536ccc6d266550041bc", - "a20d733a9fa79fa5b4cbb9639864f93325ec27a6", - "785d3fe8e7db5ade2c2242fecd46c32a7f4dc59f", - "4d8d0fd9cb6045075385701c3f933ec13345e9c4", - "0cfd861bd547b6520d1fc2e190e8359e0a9c9b90" -}; diff --git a/tests-clar/odb/packed.c b/tests-clar/odb/packed.c deleted file mode 100644 index b4f549b58..000000000 --- a/tests-clar/odb/packed.c +++ /dev/null @@ -1,79 +0,0 @@ -#include "clar_libgit2.h" -#include "odb.h" -#include "pack_data.h" - -static git_odb *_odb; - -void test_odb_packed__initialize(void) -{ - cl_git_pass(git_odb_open(&_odb, cl_fixture("testrepo.git/objects"))); -} - -void test_odb_packed__cleanup(void) -{ - git_odb_free(_odb); - _odb = NULL; -} - -void test_odb_packed__mass_read(void) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(packed_objects); ++i) { - git_oid id; - git_odb_object *obj; - - cl_git_pass(git_oid_fromstr(&id, packed_objects[i])); - cl_assert(git_odb_exists(_odb, &id) == 1); - cl_git_pass(git_odb_read(&obj, _odb, &id)); - - git_odb_object_free(obj); - } -} - -void test_odb_packed__read_header_0(void) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(packed_objects); ++i) { - git_oid id; - git_odb_object *obj; - size_t len; - git_otype type; - - cl_git_pass(git_oid_fromstr(&id, packed_objects[i])); - - cl_git_pass(git_odb_read(&obj, _odb, &id)); - cl_git_pass(git_odb_read_header(&len, &type, _odb, &id)); - - cl_assert(obj->cached.size == len); - cl_assert(obj->cached.type == type); - - git_odb_object_free(obj); - } -} - -void test_odb_packed__read_header_1(void) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(loose_objects); ++i) { - git_oid id; - git_odb_object *obj; - size_t len; - git_otype type; - - cl_git_pass(git_oid_fromstr(&id, loose_objects[i])); - - cl_assert(git_odb_exists(_odb, &id) == 1); - - cl_git_pass(git_odb_read(&obj, _odb, &id)); - cl_git_pass(git_odb_read_header(&len, &type, _odb, &id)); - - cl_assert(obj->cached.size == len); - cl_assert(obj->cached.type == type); - - git_odb_object_free(obj); - } -} - diff --git a/tests-clar/odb/packed_one.c b/tests-clar/odb/packed_one.c deleted file mode 100644 index 0c6ed387b..000000000 --- a/tests-clar/odb/packed_one.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/odb_backend.h" - -#include "pack_data_one.h" -#include "pack.h" - -static git_odb *_odb; - -void test_odb_packed_one__initialize(void) -{ - git_odb_backend *backend = NULL; - - cl_git_pass(git_odb_new(&_odb)); - cl_git_pass(git_odb_backend_one_pack(&backend, cl_fixture("testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx"))); - cl_git_pass(git_odb_add_backend(_odb, backend, 1)); -} - -void test_odb_packed_one__cleanup(void) -{ - git_odb_free(_odb); - _odb = NULL; -} - -void test_odb_packed_one__mass_read(void) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(packed_objects_one); ++i) { - git_oid id; - git_odb_object *obj; - - cl_git_pass(git_oid_fromstr(&id, packed_objects_one[i])); - cl_assert(git_odb_exists(_odb, &id) == 1); - cl_git_pass(git_odb_read(&obj, _odb, &id)); - - git_odb_object_free(obj); - } -} - -void test_odb_packed_one__read_header_0(void) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(packed_objects_one); ++i) { - git_oid id; - git_odb_object *obj; - size_t len; - git_otype type; - - cl_git_pass(git_oid_fromstr(&id, packed_objects_one[i])); - - cl_git_pass(git_odb_read(&obj, _odb, &id)); - cl_git_pass(git_odb_read_header(&len, &type, _odb, &id)); - - cl_assert(obj->cached.size == len); - cl_assert(obj->cached.type == type); - - git_odb_object_free(obj); - } -} diff --git a/tests-clar/odb/sorting.c b/tests-clar/odb/sorting.c deleted file mode 100644 index 147a160c8..000000000 --- a/tests-clar/odb/sorting.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/sys/odb_backend.h" - -typedef struct { - git_odb_backend base; - size_t position; -} fake_backend; - -static git_odb_backend *new_backend(size_t position) -{ - fake_backend *b; - - b = git__calloc(1, sizeof(fake_backend)); - if (b == NULL) - return NULL; - - b->base.version = GIT_ODB_BACKEND_VERSION; - b->position = position; - return (git_odb_backend *)b; -} - -static void check_backend_sorting(git_odb *odb) -{ - size_t i, max_i = git_odb_num_backends(odb); - fake_backend *internal; - - for (i = 0; i < max_i; ++i) { - cl_git_pass(git_odb_get_backend((git_odb_backend **)&internal, odb, i)); - cl_assert(internal != NULL); - cl_assert_equal_sz(i, internal->position); - } -} - -static git_odb *_odb; - -void test_odb_sorting__initialize(void) -{ - cl_git_pass(git_odb_new(&_odb)); -} - -void test_odb_sorting__cleanup(void) -{ - git_odb_free(_odb); - _odb = NULL; -} - -void test_odb_sorting__basic_backends_sorting(void) -{ - cl_git_pass(git_odb_add_backend(_odb, new_backend(0), 5)); - cl_git_pass(git_odb_add_backend(_odb, new_backend(2), 3)); - cl_git_pass(git_odb_add_backend(_odb, new_backend(1), 4)); - cl_git_pass(git_odb_add_backend(_odb, new_backend(3), 1)); - - check_backend_sorting(_odb); -} - -void test_odb_sorting__alternate_backends_sorting(void) -{ - cl_git_pass(git_odb_add_backend(_odb, new_backend(0), 5)); - cl_git_pass(git_odb_add_backend(_odb, new_backend(2), 3)); - cl_git_pass(git_odb_add_backend(_odb, new_backend(1), 4)); - cl_git_pass(git_odb_add_backend(_odb, new_backend(3), 1)); - cl_git_pass(git_odb_add_alternate(_odb, new_backend(4), 5)); - cl_git_pass(git_odb_add_alternate(_odb, new_backend(6), 3)); - cl_git_pass(git_odb_add_alternate(_odb, new_backend(5), 4)); - cl_git_pass(git_odb_add_alternate(_odb, new_backend(7), 1)); - - check_backend_sorting(_odb); -} diff --git a/tests-clar/odb/streamwrite.c b/tests-clar/odb/streamwrite.c deleted file mode 100644 index 591a20040..000000000 --- a/tests-clar/odb/streamwrite.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/odb_backend.h" - -static git_repository *repo; -static git_odb *odb; -static git_odb_stream *stream; - -void test_odb_streamwrite__initialize(void) -{ - repo = cl_git_sandbox_init("testrepo.git"); - cl_git_pass(git_repository_odb(&odb, repo)); - - cl_git_pass(git_odb_open_wstream(&stream, odb, 14, GIT_OBJ_BLOB)); - cl_assert_equal_sz(14, stream->declared_size); -} - -void test_odb_streamwrite__cleanup(void) -{ - git_odb_stream_free(stream); - git_odb_free(odb); - cl_git_sandbox_cleanup(); -} - -void test_odb_streamwrite__can_accept_chunks(void) -{ - git_oid oid; - - cl_git_pass(git_odb_stream_write(stream, "deadbeef", 8)); - cl_assert_equal_sz(8, stream->received_bytes); - - cl_git_pass(git_odb_stream_write(stream, "deadbeef", 6)); - cl_assert_equal_sz(8 + 6, stream->received_bytes); - - cl_git_pass(git_odb_stream_finalize_write(&oid, stream)); -} - -void test_odb_streamwrite__can_detect_missing_bytes(void) -{ - git_oid oid; - - cl_git_pass(git_odb_stream_write(stream, "deadbeef", 8)); - cl_assert_equal_sz(8, stream->received_bytes); - - cl_git_pass(git_odb_stream_write(stream, "deadbeef", 4)); - cl_assert_equal_sz(8 + 4, stream->received_bytes); - - cl_git_fail(git_odb_stream_finalize_write(&oid, stream)); -} - -void test_odb_streamwrite__can_detect_additional_bytes(void) -{ - cl_git_pass(git_odb_stream_write(stream, "deadbeef", 8)); - cl_assert_equal_sz(8, stream->received_bytes); - - cl_git_fail(git_odb_stream_write(stream, "deadbeef", 7)); -} diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c deleted file mode 100644 index aa3d6b26a..000000000 --- a/tests-clar/online/clone.c +++ /dev/null @@ -1,256 +0,0 @@ -#include "clar_libgit2.h" - -#include "git2/clone.h" -#include "git2/cred_helpers.h" -#include "remote.h" -#include "fileops.h" -#include "refs.h" - -#define LIVE_REPO_URL "http://github.com/libgit2/TestGitRepository" -#define LIVE_EMPTYREPO_URL "http://github.com/libgit2/TestEmptyRepository" -#define BB_REPO_URL "https://libgit2@bitbucket.org/libgit2/testgitrepository.git" -#define BB_REPO_URL_WITH_PASS "https://libgit2:libgit2@bitbucket.org/libgit2/testgitrepository.git" -#define BB_REPO_URL_WITH_WRONG_PASS "https://libgit2:wrong@bitbucket.org/libgit2/testgitrepository.git" -#define ASSEMBLA_REPO_URL "https://libgit2:_Libgit2@git.assembla.com/libgit2-test-repos.git" - -static git_repository *g_repo; -static git_clone_options g_options; - -void test_online_clone__initialize(void) -{ - git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT; - git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; - - g_repo = NULL; - - memset(&g_options, 0, sizeof(git_clone_options)); - g_options.version = GIT_CLONE_OPTIONS_VERSION; - g_options.checkout_opts = dummy_opts; - g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; - g_options.remote_callbacks = dummy_callbacks; -} - -void test_online_clone__cleanup(void) -{ - if (g_repo) { - git_repository_free(g_repo); - g_repo = NULL; - } - cl_fixture_cleanup("./foo"); -} - -void test_online_clone__network_full(void) -{ - git_remote *origin; - - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); - cl_assert(!git_repository_is_bare(g_repo)); - cl_git_pass(git_remote_load(&origin, g_repo, "origin")); - - cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, origin->download_tags); - - git_remote_free(origin); -} - -void test_online_clone__network_bare(void) -{ - git_remote *origin; - - g_options.bare = true; - - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); - cl_assert(git_repository_is_bare(g_repo)); - cl_git_pass(git_remote_load(&origin, g_repo, "origin")); - - git_remote_free(origin); -} - -void test_online_clone__empty_repository(void) -{ - git_reference *head; - - cl_git_pass(git_clone(&g_repo, LIVE_EMPTYREPO_URL, "./foo", &g_options)); - - cl_assert_equal_i(true, git_repository_is_empty(g_repo)); - cl_assert_equal_i(true, git_repository_head_unborn(g_repo)); - - cl_git_pass(git_reference_lookup(&head, g_repo, GIT_HEAD_FILE)); - cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); - cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); - - git_reference_free(head); -} - -static void checkout_progress(const char *path, size_t cur, size_t tot, void *payload) -{ - bool *was_called = (bool*)payload; - GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot); - (*was_called) = true; -} - -static int fetch_progress(const git_transfer_progress *stats, void *payload) -{ - bool *was_called = (bool*)payload; - GIT_UNUSED(stats); - (*was_called) = true; - return 0; -} - -void test_online_clone__can_checkout_a_cloned_repo(void) -{ - git_buf path = GIT_BUF_INIT; - git_reference *head; - bool checkout_progress_cb_was_called = false, - fetch_progress_cb_was_called = false; - - g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - g_options.checkout_opts.progress_cb = &checkout_progress; - g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called; - g_options.remote_callbacks.transfer_progress = &fetch_progress; - g_options.remote_callbacks.payload = &fetch_progress_cb_was_called; - - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); - - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); - cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path))); - - cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); - cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); - cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); - - cl_assert_equal_i(true, checkout_progress_cb_was_called); - cl_assert_equal_i(true, fetch_progress_cb_was_called); - - git_reference_free(head); - git_buf_free(&path); -} - -void test_online_clone__clone_into(void) -{ - git_buf path = GIT_BUF_INIT; - git_remote *remote; - git_reference *head; - git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - - bool checkout_progress_cb_was_called = false, - fetch_progress_cb_was_called = false; - - checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - checkout_opts.progress_cb = &checkout_progress; - checkout_opts.progress_payload = &checkout_progress_cb_was_called; - - cl_git_pass(git_repository_init(&g_repo, "./foo", false)); - cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL)); - - callbacks.transfer_progress = &fetch_progress; - callbacks.payload = &fetch_progress_cb_was_called; - git_remote_set_callbacks(remote, &callbacks); - - cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL)); - - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); - cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path))); - - cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); - cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); - cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); - - cl_assert_equal_i(true, checkout_progress_cb_was_called); - cl_assert_equal_i(true, fetch_progress_cb_was_called); - - git_remote_free(remote); - git_reference_free(head); - git_buf_free(&path); -} - -static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *payload) -{ - int *callcount = (int*)payload; - GIT_UNUSED(refname); GIT_UNUSED(a); GIT_UNUSED(b); - *callcount = *callcount + 1; - return 0; -} - -void test_online_clone__custom_remote_callbacks(void) -{ - int callcount = 0; - - g_options.remote_callbacks.update_tips = update_tips; - g_options.remote_callbacks.payload = &callcount; - - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); - cl_assert(callcount > 0); -} - -void test_online_clone__credentials(void) -{ - /* Remote URL environment variable must be set. User and password are optional. */ - const char *remote_url = cl_getenv("GITTEST_REMOTE_URL"); - git_cred_userpass_payload user_pass = { - cl_getenv("GITTEST_REMOTE_USER"), - cl_getenv("GITTEST_REMOTE_PASS") - }; - - if (!remote_url) return; - - g_options.remote_callbacks.credentials = git_cred_userpass; - g_options.remote_callbacks.payload = &user_pass; - - cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options)); - git_repository_free(g_repo); g_repo = NULL; - cl_fixture_cleanup("./foo"); -} - -void test_online_clone__bitbucket_style(void) -{ - git_cred_userpass_payload user_pass = { - "libgit2", "libgit2" - }; - - g_options.remote_callbacks.credentials = git_cred_userpass; - g_options.remote_callbacks.payload = &user_pass; - - cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options)); - git_repository_free(g_repo); g_repo = NULL; - cl_fixture_cleanup("./foo"); - - /* User and pass from URL */ - user_pass.password = "wrong"; - cl_git_pass(git_clone(&g_repo, BB_REPO_URL_WITH_PASS, "./foo", &g_options)); - git_repository_free(g_repo); g_repo = NULL; - cl_fixture_cleanup("./foo"); - - /* Wrong password in URL, fall back to user_pass */ - user_pass.password = "libgit2"; - cl_git_pass(git_clone(&g_repo, BB_REPO_URL_WITH_WRONG_PASS, "./foo", &g_options)); - git_repository_free(g_repo); g_repo = NULL; - cl_fixture_cleanup("./foo"); -} - -void test_online_clone__assembla_style(void) -{ - cl_git_pass(git_clone(&g_repo, ASSEMBLA_REPO_URL, "./foo", NULL)); -} - -static int cancel_at_half(const git_transfer_progress *stats, void *payload) -{ - GIT_UNUSED(payload); - - if (stats->received_objects > (stats->total_objects/2)) - return 1; - return 0; -} - -void test_online_clone__can_cancel(void) -{ - g_options.remote_callbacks.transfer_progress = cancel_at_half; - - cl_git_fail_with(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), GIT_EUSER); -} - - - - - - diff --git a/tests-clar/online/fetch.c b/tests-clar/online/fetch.c deleted file mode 100644 index 5153a7ae0..000000000 --- a/tests-clar/online/fetch.c +++ /dev/null @@ -1,171 +0,0 @@ -#include "clar_libgit2.h" - -static git_repository *_repo; -static int counter; - -void test_online_fetch__initialize(void) -{ - cl_git_pass(git_repository_init(&_repo, "./fetch", 0)); -} - -void test_online_fetch__cleanup(void) -{ - git_repository_free(_repo); - _repo = NULL; - - cl_fixture_cleanup("./fetch"); -} - -static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *data) -{ - GIT_UNUSED(refname); GIT_UNUSED(a); GIT_UNUSED(b); GIT_UNUSED(data); - - ++counter; - - return 0; -} - -static int progress(const git_transfer_progress *stats, void *payload) -{ - size_t *bytes_received = (size_t *)payload; - *bytes_received = stats->received_bytes; - return 0; -} - -static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) -{ - git_remote *remote; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - size_t bytes_received = 0; - - callbacks.transfer_progress = progress; - callbacks.update_tips = update_tips; - callbacks.payload = &bytes_received; - counter = 0; - - cl_git_pass(git_remote_create(&remote, _repo, "test", url)); - git_remote_set_callbacks(remote, &callbacks); - git_remote_set_autotag(remote, flag); - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(remote)); - cl_git_pass(git_remote_update_tips(remote)); - git_remote_disconnect(remote); - cl_assert_equal_i(counter, n); - cl_assert(bytes_received > 0); - - git_remote_free(remote); -} - -void test_online_fetch__default_git(void) -{ - do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); -} - -void test_online_fetch__default_http(void) -{ - do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); -} - -void test_online_fetch__default_https(void) -{ - do_fetch("https://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); -} - -void test_online_fetch__no_tags_git(void) -{ - do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3); -} - -void test_online_fetch__no_tags_http(void) -{ - do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3); -} - -static int transferProgressCallback(const git_transfer_progress *stats, void *payload) -{ - bool *invoked = (bool *)payload; - - GIT_UNUSED(stats); - *invoked = true; - return 0; -} - -void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date(void) -{ - git_repository *_repository; - bool invoked = false; - git_remote *remote; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - git_clone_options opts = GIT_CLONE_OPTIONS_INIT; - opts.bare = true; - - cl_git_pass(git_clone(&_repository, "https://github.com/libgit2/TestGitRepository.git", - "./fetch/lg2", &opts)); - git_repository_free(_repository); - - cl_git_pass(git_repository_open(&_repository, "./fetch/lg2")); - - cl_git_pass(git_remote_load(&remote, _repository, "origin")); - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - - cl_assert_equal_i(false, invoked); - - callbacks.transfer_progress = &transferProgressCallback; - callbacks.payload = &invoked; - git_remote_set_callbacks(remote, &callbacks); - cl_git_pass(git_remote_download(remote)); - - cl_assert_equal_i(false, invoked); - - cl_git_pass(git_remote_update_tips(remote)); - git_remote_disconnect(remote); - - git_remote_free(remote); - git_repository_free(_repository); -} - -static int cancel_at_half(const git_transfer_progress *stats, void *payload) -{ - GIT_UNUSED(payload); - - if (stats->received_objects > (stats->total_objects/2)) - return -1; - return 0; -} - -void test_online_fetch__can_cancel(void) -{ - git_remote *remote; - size_t bytes_received = 0; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - - cl_git_pass(git_remote_create(&remote, _repo, "test", - "http://github.com/libgit2/TestGitRepository.git")); - - callbacks.transfer_progress = cancel_at_half; - callbacks.payload = &bytes_received; - git_remote_set_callbacks(remote, &callbacks); - - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_fail_with(git_remote_download(remote), GIT_EUSER); - git_remote_disconnect(remote); - git_remote_free(remote); -} - -void test_online_fetch__ls_disconnected(void) -{ - const git_remote_head **refs; - size_t refs_len_before, refs_len_after; - git_remote *remote; - - cl_git_pass(git_remote_create(&remote, _repo, "test", - "http://github.com/libgit2/TestGitRepository.git")); - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_ls(&refs, &refs_len_before, remote)); - git_remote_disconnect(remote); - cl_git_pass(git_remote_ls(&refs, &refs_len_after, remote)); - - cl_assert_equal_i(refs_len_before, refs_len_after); - - git_remote_free(remote); -} diff --git a/tests-clar/online/fetchhead.c b/tests-clar/online/fetchhead.c deleted file mode 100644 index 57b183f88..000000000 --- a/tests-clar/online/fetchhead.c +++ /dev/null @@ -1,91 +0,0 @@ -#include "clar_libgit2.h" - -#include "fileops.h" -#include "fetchhead.h" -#include "../fetchhead/fetchhead_data.h" -#include "git2/clone.h" - -#define LIVE_REPO_URL "git://github.com/libgit2/TestGitRepository" - -static git_repository *g_repo; -static git_clone_options g_options; - -void test_online_fetchhead__initialize(void) -{ - git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; - g_repo = NULL; - - memset(&g_options, 0, sizeof(git_clone_options)); - g_options.version = GIT_CLONE_OPTIONS_VERSION; - g_options.remote_callbacks = dummy_callbacks; -} - -void test_online_fetchhead__cleanup(void) -{ - if (g_repo) { - git_repository_free(g_repo); - g_repo = NULL; - } - - cl_fixture_cleanup("./foo"); -} - -static void fetchhead_test_clone(void) -{ - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); -} - -static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fetchhead) -{ - git_remote *remote; - git_buf fetchhead_buf = GIT_BUF_INIT; - int equals = 0; - - cl_git_pass(git_remote_load(&remote, g_repo, "origin")); - git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); - - if(fetchspec != NULL) { - git_remote_clear_refspecs(remote); - git_remote_add_fetch(remote, fetchspec); - } - - cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(remote)); - cl_git_pass(git_remote_update_tips(remote)); - git_remote_disconnect(remote); - git_remote_free(remote); - - cl_git_pass(git_futils_readbuffer(&fetchhead_buf, "./foo/.git/FETCH_HEAD")); - - equals = (strcmp(fetchhead_buf.ptr, expected_fetchhead) == 0); - - git_buf_free(&fetchhead_buf); - - cl_assert(equals); -} - -void test_online_fetchhead__wildcard_spec(void) -{ - fetchhead_test_clone(); - fetchhead_test_fetch(NULL, FETCH_HEAD_WILDCARD_DATA); -} - -void test_online_fetchhead__explicit_spec(void) -{ - fetchhead_test_clone(); - fetchhead_test_fetch("refs/heads/first-merge:refs/remotes/origin/first-merge", FETCH_HEAD_EXPLICIT_DATA); -} - -void test_online_fetchhead__no_merges(void) -{ - git_config *config; - - fetchhead_test_clone(); - - cl_git_pass(git_repository_config(&config, g_repo)); - cl_git_pass(git_config_delete_entry(config, "branch.master.remote")); - cl_git_pass(git_config_delete_entry(config, "branch.master.merge")); - git_config_free(config); - - fetchhead_test_fetch(NULL, FETCH_HEAD_NO_MERGE_DATA); -} diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c deleted file mode 100644 index aeb1ab47d..000000000 --- a/tests-clar/online/push.c +++ /dev/null @@ -1,770 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "posix.h" -#include "vector.h" -#include "../submodule/submodule_helpers.h" -#include "push_util.h" -#include "refspec.h" -#include "remote.h" - -static git_repository *_repo; - -static char *_remote_ssh_key; -static char *_remote_ssh_pubkey; -static char *_remote_ssh_passphrase; - -static char *_remote_url; -static char *_remote_user; -static char *_remote_pass; - -static int cred_acquire_cb(git_cred **, const char *, const char *, unsigned int, void *); - -static git_remote *_remote; -static record_callbacks_data _record_cbs_data = {{ 0 }}; -static git_remote_callbacks _record_cbs = RECORD_CALLBACKS_INIT(&_record_cbs_data); - -static git_oid _oid_b6; -static git_oid _oid_b5; -static git_oid _oid_b4; -static git_oid _oid_b3; -static git_oid _oid_b2; -static git_oid _oid_b1; - -static git_oid _tag_commit; -static git_oid _tag_tree; -static git_oid _tag_blob; -static git_oid _tag_lightweight; -static git_oid _tag_tag; - -static int cred_acquire_cb( - git_cred **cred, - const char *url, - const char *user_from_url, - unsigned int allowed_types, - void *payload) -{ - GIT_UNUSED(url); - GIT_UNUSED(user_from_url); - GIT_UNUSED(payload); - - if (GIT_CREDTYPE_SSH_KEY & allowed_types) { - if (!_remote_user || !_remote_ssh_pubkey || !_remote_ssh_key || !_remote_ssh_passphrase) { - printf("GITTEST_REMOTE_USER, GITTEST_REMOTE_SSH_PUBKEY, GITTEST_REMOTE_SSH_KEY and GITTEST_REMOTE_SSH_PASSPHRASE must be set\n"); - return -1; - } - return git_cred_ssh_key_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase); - } - - if (GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) { - if (!_remote_user || !_remote_pass) { - printf("GITTEST_REMOTE_USER and GITTEST_REMOTE_PASS must be set\n"); - return -1; - } - - return git_cred_userpass_plaintext_new(cred, _remote_user, _remote_pass); - } - - return -1; -} - -/* the results of a push status. when used for expected values, msg may be NULL - * to indicate that it should not be matched. */ -typedef struct { - const char *ref; - int success; - const char *msg; -} push_status; - -/** - * git_push_status_foreach callback that records status entries. - * @param data (git_vector *) of push_status instances - */ -static int record_push_status_cb(const char *ref, const char *msg, void *data) -{ - git_vector *statuses = (git_vector *)data; - push_status *s; - - cl_assert(s = git__malloc(sizeof(*s))); - s->ref = ref; - s->success = (msg == NULL); - s->msg = msg; - - git_vector_insert(statuses, s); - - return 0; -} - -static void do_verify_push_status(git_push *push, const push_status expected[], const size_t expected_len) -{ - git_vector actual = GIT_VECTOR_INIT; - push_status *iter; - bool failed = false; - size_t i; - - git_push_status_foreach(push, record_push_status_cb, &actual); - - if (expected_len != actual.length) - failed = true; - else - git_vector_foreach(&actual, i, iter) - if (strcmp(expected[i].ref, iter->ref) || - (expected[i].success != iter->success) || - (expected[i].msg && (!iter->msg || strcmp(expected[i].msg, iter->msg)))) { - failed = true; - break; - } - - if (failed) { - git_buf msg = GIT_BUF_INIT; - - git_buf_puts(&msg, "Expected and actual push statuses differ:\nEXPECTED:\n"); - - for(i = 0; i < expected_len; i++) { - git_buf_printf(&msg, "%s: %s\n", - expected[i].ref, - expected[i].success ? "success" : "failed"); - } - - git_buf_puts(&msg, "\nACTUAL:\n"); - - git_vector_foreach(&actual, i, iter) { - if (iter->success) - git_buf_printf(&msg, "%s: success\n", iter->ref); - else - git_buf_printf(&msg, "%s: failed with message: %s", iter->ref, iter->msg); - } - - cl_fail(git_buf_cstr(&msg)); - - git_buf_free(&msg); - } - - git_vector_foreach(&actual, i, iter) - git__free(iter); - - git_vector_free(&actual); -} - -/** - * Verifies that after git_push_finish(), refs on a remote have the expected - * names, oids, and order. - * - * @param remote remote to verify - * @param expected_refs expected remote refs after push - * @param expected_refs_len length of expected_refs - */ -static void verify_refs(git_remote *remote, expected_ref expected_refs[], size_t expected_refs_len) -{ - const git_remote_head **actual_refs; - size_t actual_refs_len; - - git_remote_ls(&actual_refs, &actual_refs_len, remote); - verify_remote_refs(actual_refs, actual_refs_len, expected_refs, expected_refs_len); -} - -/** - * Verifies that after git_push_update_tips(), remote tracking branches have the expected - * names and oids. - * - * @param remote remote to verify - * @param expected_refs expected remote refs after push - * @param expected_refs_len length of expected_refs - */ -static void verify_tracking_branches(git_remote *remote, expected_ref expected_refs[], size_t expected_refs_len) -{ - git_refspec *fetch_spec; - size_t i, j; - git_buf msg = GIT_BUF_INIT; - git_buf ref_name = GIT_BUF_INIT; - git_vector actual_refs = GIT_VECTOR_INIT; - git_branch_iterator *iter; - char *actual_ref; - git_oid oid; - int failed = 0, error; - git_branch_t branch_type; - git_reference *ref; - - /* Get current remote branches */ - cl_git_pass(git_branch_iterator_new(&iter, remote->repo, GIT_BRANCH_REMOTE)); - - while ((error = git_branch_next(&ref, &branch_type, iter)) == 0) { - cl_assert_equal_i(branch_type, GIT_BRANCH_REMOTE); - - cl_git_pass(git_vector_insert(&actual_refs, git__strdup(git_reference_name(ref)))); - } - - cl_assert_equal_i(error, GIT_ITEROVER); - - /* Loop through expected refs, make sure they exist */ - for (i = 0; i < expected_refs_len; i++) { - - /* Convert remote reference name into tracking branch name. - * If the spec is not under refs/heads/, then skip. - */ - fetch_spec = git_remote__matching_refspec(remote, expected_refs[i].name); - if (!fetch_spec) - continue; - - cl_git_pass(git_refspec_transform_r(&ref_name, fetch_spec, expected_refs[i].name)); - - /* Find matching remote branch */ - git_vector_foreach(&actual_refs, j, actual_ref) { - if (!strcmp(git_buf_cstr(&ref_name), actual_ref)) - break; - } - - if (j == actual_refs.length) { - git_buf_printf(&msg, "Did not find expected tracking branch '%s'.", git_buf_cstr(&ref_name)); - failed = 1; - goto failed; - } - - /* Make sure tracking branch is at expected commit ID */ - cl_git_pass(git_reference_name_to_id(&oid, remote->repo, actual_ref)); - - if (git_oid_cmp(expected_refs[i].oid, &oid) != 0) { - git_buf_puts(&msg, "Tracking branch commit does not match expected ID."); - failed = 1; - goto failed; - } - - git__free(actual_ref); - cl_git_pass(git_vector_remove(&actual_refs, j)); - } - - /* Make sure there are no extra branches */ - if (actual_refs.length > 0) { - git_buf_puts(&msg, "Unexpected remote tracking branches exist."); - failed = 1; - goto failed; - } - -failed: - - if(failed) - cl_fail(git_buf_cstr(&msg)); - - git_vector_foreach(&actual_refs, i, actual_ref) - git__free(actual_ref); - - git_vector_free(&actual_refs); - git_buf_free(&msg); - git_buf_free(&ref_name); - return; -} - -void test_online_push__initialize(void) -{ - git_vector delete_specs = GIT_VECTOR_INIT; - const git_remote_head **heads; - size_t i, heads_len; - char *curr_del_spec; - - _repo = cl_git_sandbox_init("push_src"); - - cl_fixture_sandbox("testrepo.git"); - cl_rename("push_src/submodule/.gitted", "push_src/submodule/.git"); - - rewrite_gitmodules(git_repository_workdir(_repo)); - - /* git log --format=oneline --decorate --graph - * *-. 951bbbb90e2259a4c8950db78946784fb53fcbce (HEAD, b6) merge b3, b4, and b5 to b6 - * |\ \ - * | | * fa38b91f199934685819bea316186d8b008c52a2 (b5) added submodule named 'submodule' pointing to '../testrepo.git' - * | * | 27b7ce66243eb1403862d05f958c002312df173d (b4) edited fold\b.txt - * | |/ - * * | d9b63a88223d8367516f50bd131a5f7349b7f3e4 (b3) edited a.txt - * |/ - * * a78705c3b2725f931d3ee05348d83cc26700f247 (b2, b1) added fold and fold/b.txt - * * 5c0bb3d1b9449d1cc69d7519fd05166f01840915 added a.txt - */ - git_oid_fromstr(&_oid_b6, "951bbbb90e2259a4c8950db78946784fb53fcbce"); - git_oid_fromstr(&_oid_b5, "fa38b91f199934685819bea316186d8b008c52a2"); - git_oid_fromstr(&_oid_b4, "27b7ce66243eb1403862d05f958c002312df173d"); - git_oid_fromstr(&_oid_b3, "d9b63a88223d8367516f50bd131a5f7349b7f3e4"); - git_oid_fromstr(&_oid_b2, "a78705c3b2725f931d3ee05348d83cc26700f247"); - git_oid_fromstr(&_oid_b1, "a78705c3b2725f931d3ee05348d83cc26700f247"); - - git_oid_fromstr(&_tag_commit, "805c54522e614f29f70d2413a0470247d8b424ac"); - git_oid_fromstr(&_tag_tree, "ff83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e"); - git_oid_fromstr(&_tag_blob, "b483ae7ba66decee9aee971f501221dea84b1498"); - git_oid_fromstr(&_tag_lightweight, "951bbbb90e2259a4c8950db78946784fb53fcbce"); - git_oid_fromstr(&_tag_tag, "eea4f2705eeec2db3813f2430829afce99cd00b5"); - - /* Remote URL environment variable must be set. User and password are optional. */ - _remote_url = cl_getenv("GITTEST_REMOTE_URL"); - _remote_user = cl_getenv("GITTEST_REMOTE_USER"); - _remote_pass = cl_getenv("GITTEST_REMOTE_PASS"); - _remote_ssh_key = cl_getenv("GITTEST_REMOTE_SSH_KEY"); - _remote_ssh_pubkey = cl_getenv("GITTEST_REMOTE_SSH_PUBKEY"); - _remote_ssh_passphrase = cl_getenv("GITTEST_REMOTE_SSH_PASSPHRASE"); - _remote = NULL; - - if (_remote_url) { - cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url)); - - record_callbacks_data_clear(&_record_cbs_data); - git_remote_set_callbacks(_remote, &_record_cbs); - - cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); - - /* Clean up previously pushed branches. Fails if receive.denyDeletes is - * set on the remote. Also, on Git 1.7.0 and newer, you must run - * 'git config receive.denyDeleteCurrent ignore' in the remote repo in - * order to delete the remote branch pointed to by HEAD (usually master). - * See: https://raw.github.com/git/git/master/Documentation/RelNotes/1.7.0.txt - */ - cl_git_pass(git_remote_ls(&heads, &heads_len, _remote)); - cl_git_pass(create_deletion_refspecs(&delete_specs, heads, heads_len)); - if (delete_specs.length) { - git_push *push; - - cl_git_pass(git_push_new(&push, _remote)); - - git_vector_foreach(&delete_specs, i, curr_del_spec) { - git_push_add_refspec(push, curr_del_spec); - git__free(curr_del_spec); - } - - cl_git_pass(git_push_finish(push)); - git_push_free(push); - } - - git_remote_disconnect(_remote); - git_vector_free(&delete_specs); - - /* Now that we've deleted everything, fetch from the remote */ - cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_FETCH)); - cl_git_pass(git_remote_download(_remote)); - cl_git_pass(git_remote_update_tips(_remote)); - git_remote_disconnect(_remote); - } else - printf("GITTEST_REMOTE_URL unset; skipping push test\n"); -} - -void test_online_push__cleanup(void) -{ - if (_remote) - git_remote_free(_remote); - _remote = NULL; - - /* Freed by cl_git_sandbox_cleanup */ - _repo = NULL; - - record_callbacks_data_clear(&_record_cbs_data); - - cl_fixture_cleanup("testrepo.git"); - cl_git_sandbox_cleanup(); -} - -static int push_pack_progress_cb(int stage, unsigned int current, unsigned int total, void* payload) -{ - int *was_called = (int *) payload; - GIT_UNUSED(stage); GIT_UNUSED(current); GIT_UNUSED(total); - *was_called = 1; - return 0; -} - -static int push_transfer_progress_cb(unsigned int current, unsigned int total, size_t bytes, void* payload) -{ - int *was_called = (int *) payload; - GIT_UNUSED(current); GIT_UNUSED(total); GIT_UNUSED(bytes); - *was_called = 1; - return 0; -} - -/** - * Calls push and relists refs on remote to verify success. - * - * @param refspecs refspecs to push - * @param refspecs_len length of refspecs - * @param expected_refs expected remote refs after push - * @param expected_refs_len length of expected_refs - * @param expected_ret expected return value from git_push_finish() - * @param check_progress_cb Check that the push progress callbacks are called - */ -static void do_push(const char *refspecs[], size_t refspecs_len, - push_status expected_statuses[], size_t expected_statuses_len, - expected_ref expected_refs[], size_t expected_refs_len, int expected_ret, int check_progress_cb) -{ - git_push *push; - git_push_options opts = GIT_PUSH_OPTIONS_INIT; - size_t i; - int ret; - int pack_progress_called = 0, transfer_progress_called = 0; - - if (_remote) { - /* Auto-detect the number of threads to use */ - opts.pb_parallelism = 0; - - cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); - - cl_git_pass(git_push_new(&push, _remote)); - cl_git_pass(git_push_set_options(push, &opts)); - - if (check_progress_cb) - cl_git_pass(git_push_set_callbacks(push, push_pack_progress_cb, &pack_progress_called, push_transfer_progress_cb, &transfer_progress_called)); - - for (i = 0; i < refspecs_len; i++) - cl_git_pass(git_push_add_refspec(push, refspecs[i])); - - if (expected_ret < 0) { - cl_git_fail(ret = git_push_finish(push)); - cl_assert_equal_i(0, git_push_unpack_ok(push)); - } - else { - cl_git_pass(ret = git_push_finish(push)); - cl_assert_equal_i(1, git_push_unpack_ok(push)); - } - - if (check_progress_cb) { - cl_assert_equal_i(1, pack_progress_called); - cl_assert_equal_i(1, transfer_progress_called); - } - - do_verify_push_status(push, expected_statuses, expected_statuses_len); - - cl_assert_equal_i(expected_ret, ret); - - verify_refs(_remote, expected_refs, expected_refs_len); - - cl_git_pass(git_push_update_tips(push)); - verify_tracking_branches(_remote, expected_refs, expected_refs_len); - - git_push_free(push); - - git_remote_disconnect(_remote); - } -} - -/* Call push_finish() without ever calling git_push_add_refspec() */ -void test_online_push__noop(void) -{ - do_push(NULL, 0, NULL, 0, NULL, 0, 0, 0); -} - -void test_online_push__b1(void) -{ - const char *specs[] = { "refs/heads/b1:refs/heads/b1" }; - push_status exp_stats[] = { { "refs/heads/b1", 1 } }; - expected_ref exp_refs[] = { { "refs/heads/b1", &_oid_b1 } }; - do_push(specs, ARRAY_SIZE(specs), - exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0, 1); -} - -void test_online_push__b2(void) -{ - const char *specs[] = { "refs/heads/b2:refs/heads/b2" }; - push_status exp_stats[] = { { "refs/heads/b2", 1 } }; - expected_ref exp_refs[] = { { "refs/heads/b2", &_oid_b2 } }; - do_push(specs, ARRAY_SIZE(specs), - exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0, 1); -} - -void test_online_push__b3(void) -{ - const char *specs[] = { "refs/heads/b3:refs/heads/b3" }; - push_status exp_stats[] = { { "refs/heads/b3", 1 } }; - expected_ref exp_refs[] = { { "refs/heads/b3", &_oid_b3 } }; - do_push(specs, ARRAY_SIZE(specs), - exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0, 1); -} - -void test_online_push__b4(void) -{ - const char *specs[] = { "refs/heads/b4:refs/heads/b4" }; - push_status exp_stats[] = { { "refs/heads/b4", 1 } }; - expected_ref exp_refs[] = { { "refs/heads/b4", &_oid_b4 } }; - do_push(specs, ARRAY_SIZE(specs), - exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0, 1); -} - -void test_online_push__b5(void) -{ - const char *specs[] = { "refs/heads/b5:refs/heads/b5" }; - push_status exp_stats[] = { { "refs/heads/b5", 1 } }; - expected_ref exp_refs[] = { { "refs/heads/b5", &_oid_b5 } }; - do_push(specs, ARRAY_SIZE(specs), - exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0, 1); -} - -void test_online_push__multi(void) -{ - const char *specs[] = { - "refs/heads/b1:refs/heads/b1", - "refs/heads/b2:refs/heads/b2", - "refs/heads/b3:refs/heads/b3", - "refs/heads/b4:refs/heads/b4", - "refs/heads/b5:refs/heads/b5" - }; - push_status exp_stats[] = { - { "refs/heads/b1", 1 }, - { "refs/heads/b2", 1 }, - { "refs/heads/b3", 1 }, - { "refs/heads/b4", 1 }, - { "refs/heads/b5", 1 } - }; - expected_ref exp_refs[] = { - { "refs/heads/b1", &_oid_b1 }, - { "refs/heads/b2", &_oid_b2 }, - { "refs/heads/b3", &_oid_b3 }, - { "refs/heads/b4", &_oid_b4 }, - { "refs/heads/b5", &_oid_b5 } - }; - do_push(specs, ARRAY_SIZE(specs), - exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0, 1); -} - -void test_online_push__implicit_tgt(void) -{ - const char *specs1[] = { "refs/heads/b1:" }; - push_status exp_stats1[] = { { "refs/heads/b1", 1 } }; - expected_ref exp_refs1[] = { { "refs/heads/b1", &_oid_b1 } }; - - const char *specs2[] = { "refs/heads/b2:" }; - push_status exp_stats2[] = { { "refs/heads/b2", 1 } }; - expected_ref exp_refs2[] = { - { "refs/heads/b1", &_oid_b1 }, - { "refs/heads/b2", &_oid_b2 } - }; - - do_push(specs1, ARRAY_SIZE(specs1), - exp_stats1, ARRAY_SIZE(exp_stats1), - exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1); - do_push(specs2, ARRAY_SIZE(specs2), - exp_stats2, ARRAY_SIZE(exp_stats2), - exp_refs2, ARRAY_SIZE(exp_refs2), 0, 0); -} - -void test_online_push__fast_fwd(void) -{ - /* Fast forward b1 in tgt from _oid_b1 to _oid_b6. */ - - const char *specs_init[] = { "refs/heads/b1:refs/heads/b1" }; - push_status exp_stats_init[] = { { "refs/heads/b1", 1 } }; - expected_ref exp_refs_init[] = { { "refs/heads/b1", &_oid_b1 } }; - - const char *specs_ff[] = { "refs/heads/b6:refs/heads/b1" }; - push_status exp_stats_ff[] = { { "refs/heads/b1", 1 } }; - expected_ref exp_refs_ff[] = { { "refs/heads/b1", &_oid_b6 } }; - - /* Do a force push to reset b1 in target back to _oid_b1 */ - const char *specs_reset[] = { "+refs/heads/b1:refs/heads/b1" }; - /* Force should have no effect on a fast forward push */ - const char *specs_ff_force[] = { "+refs/heads/b6:refs/heads/b1" }; - - do_push(specs_init, ARRAY_SIZE(specs_init), - exp_stats_init, ARRAY_SIZE(exp_stats_init), - exp_refs_init, ARRAY_SIZE(exp_refs_init), 0, 1); - - do_push(specs_ff, ARRAY_SIZE(specs_ff), - exp_stats_ff, ARRAY_SIZE(exp_stats_ff), - exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0, 0); - - do_push(specs_reset, ARRAY_SIZE(specs_reset), - exp_stats_init, ARRAY_SIZE(exp_stats_init), - exp_refs_init, ARRAY_SIZE(exp_refs_init), 0, 0); - - do_push(specs_ff_force, ARRAY_SIZE(specs_ff_force), - exp_stats_ff, ARRAY_SIZE(exp_stats_ff), - exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0, 0); -} - -void test_online_push__tag_commit(void) -{ - const char *specs[] = { "refs/tags/tag-commit:refs/tags/tag-commit" }; - push_status exp_stats[] = { { "refs/tags/tag-commit", 1 } }; - expected_ref exp_refs[] = { { "refs/tags/tag-commit", &_tag_commit } }; - do_push(specs, ARRAY_SIZE(specs), - exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0, 1); -} - -void test_online_push__tag_tree(void) -{ - const char *specs[] = { "refs/tags/tag-tree:refs/tags/tag-tree" }; - push_status exp_stats[] = { { "refs/tags/tag-tree", 1 } }; - expected_ref exp_refs[] = { { "refs/tags/tag-tree", &_tag_tree } }; - do_push(specs, ARRAY_SIZE(specs), - exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0, 1); -} - -void test_online_push__tag_blob(void) -{ - const char *specs[] = { "refs/tags/tag-blob:refs/tags/tag-blob" }; - push_status exp_stats[] = { { "refs/tags/tag-blob", 1 } }; - expected_ref exp_refs[] = { { "refs/tags/tag-blob", &_tag_blob } }; - do_push(specs, ARRAY_SIZE(specs), - exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0, 1); -} - -void test_online_push__tag_lightweight(void) -{ - const char *specs[] = { "refs/tags/tag-lightweight:refs/tags/tag-lightweight" }; - push_status exp_stats[] = { { "refs/tags/tag-lightweight", 1 } }; - expected_ref exp_refs[] = { { "refs/tags/tag-lightweight", &_tag_lightweight } }; - do_push(specs, ARRAY_SIZE(specs), - exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0, 1); -} - -void test_online_push__tag_to_tag(void) -{ - const char *specs[] = { "refs/tags/tag-tag:refs/tags/tag-tag" }; - push_status exp_stats[] = { { "refs/tags/tag-tag", 1 } }; - expected_ref exp_refs[] = { { "refs/tags/tag-tag", &_tag_tag } }; - do_push(specs, ARRAY_SIZE(specs), - exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0, 0); -} - -void test_online_push__force(void) -{ - const char *specs1[] = {"refs/heads/b3:refs/heads/tgt"}; - push_status exp_stats1[] = { { "refs/heads/tgt", 1 } }; - expected_ref exp_refs1[] = { { "refs/heads/tgt", &_oid_b3 } }; - - const char *specs2[] = {"refs/heads/b4:refs/heads/tgt"}; - - const char *specs2_force[] = {"+refs/heads/b4:refs/heads/tgt"}; - push_status exp_stats2_force[] = { { "refs/heads/tgt", 1 } }; - expected_ref exp_refs2_force[] = { { "refs/heads/tgt", &_oid_b4 } }; - - do_push(specs1, ARRAY_SIZE(specs1), - exp_stats1, ARRAY_SIZE(exp_stats1), - exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1); - - do_push(specs2, ARRAY_SIZE(specs2), - NULL, 0, - exp_refs1, ARRAY_SIZE(exp_refs1), GIT_ENONFASTFORWARD, 0); - - /* Non-fast-forward update with force should pass. */ - do_push(specs2_force, ARRAY_SIZE(specs2_force), - exp_stats2_force, ARRAY_SIZE(exp_stats2_force), - exp_refs2_force, ARRAY_SIZE(exp_refs2_force), 0, 1); -} - -void test_online_push__delete(void) -{ - const char *specs1[] = { - "refs/heads/b1:refs/heads/tgt1", - "refs/heads/b1:refs/heads/tgt2" - }; - push_status exp_stats1[] = { - { "refs/heads/tgt1", 1 }, - { "refs/heads/tgt2", 1 } - }; - expected_ref exp_refs1[] = { - { "refs/heads/tgt1", &_oid_b1 }, - { "refs/heads/tgt2", &_oid_b1 } - }; - - const char *specs_del_fake[] = { ":refs/heads/fake" }; - /* Force has no effect for delete. */ - const char *specs_del_fake_force[] = { "+:refs/heads/fake" }; - push_status exp_stats_fake[] = { { "refs/heads/fake", 1 } }; - - const char *specs_delete[] = { ":refs/heads/tgt1" }; - push_status exp_stats_delete[] = { { "refs/heads/tgt1", 1 } }; - expected_ref exp_refs_delete[] = { { "refs/heads/tgt2", &_oid_b1 } }; - /* Force has no effect for delete. */ - const char *specs_delete_force[] = { "+:refs/heads/tgt1" }; - - do_push(specs1, ARRAY_SIZE(specs1), - exp_stats1, ARRAY_SIZE(exp_stats1), - exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1); - - /* When deleting a non-existent branch, the git client sends zero for both - * the old and new commit id. This should succeed on the server with the - * same status report as if the branch were actually deleted. The server - * returns a warning on the side-band iff the side-band is supported. - * Since libgit2 doesn't support the side-band yet, there are no warnings. - */ - do_push(specs_del_fake, ARRAY_SIZE(specs_del_fake), - exp_stats_fake, 1, - exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0); - do_push(specs_del_fake_force, ARRAY_SIZE(specs_del_fake_force), - exp_stats_fake, 1, - exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0); - - /* Delete one of the pushed branches. */ - do_push(specs_delete, ARRAY_SIZE(specs_delete), - exp_stats_delete, ARRAY_SIZE(exp_stats_delete), - exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0, 0); - - /* Re-push branches and retry delete with force. */ - do_push(specs1, ARRAY_SIZE(specs1), - exp_stats1, ARRAY_SIZE(exp_stats1), - exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0); - do_push(specs_delete_force, ARRAY_SIZE(specs_delete_force), - exp_stats_delete, ARRAY_SIZE(exp_stats_delete), - exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0, 0); -} - -void test_online_push__bad_refspecs(void) -{ - /* All classes of refspecs that should be rejected by - * git_push_add_refspec() should go in this test. - */ - git_push *push; - - if (_remote) { -// cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); - cl_git_pass(git_push_new(&push, _remote)); - - /* Unexpanded branch names not supported */ - cl_git_fail(git_push_add_refspec(push, "b6:b6")); - - git_push_free(push); - } -} - -void test_online_push__expressions(void) -{ - /* TODO: Expressions in refspecs doesn't actually work yet */ - const char *specs_left_expr[] = { "refs/heads/b2~1:refs/heads/b2" }; - - /* expect not NULL to indicate failure (core git replies "funny refname", - * other servers may be less pithy. */ - const char *specs_right_expr[] = { "refs/heads/b2:refs/heads/b2~1" }; - push_status exp_stats_right_expr[] = { { "refs/heads/b2~1", 0 } }; - - /* TODO: Find a more precise way of checking errors than a exit code of -1. */ - do_push(specs_left_expr, ARRAY_SIZE(specs_left_expr), - NULL, 0, - NULL, 0, -1, 0); - - do_push(specs_right_expr, ARRAY_SIZE(specs_right_expr), - exp_stats_right_expr, ARRAY_SIZE(exp_stats_right_expr), - NULL, 0, 0, 1); -} - -void test_online_push__notes(void) -{ - git_oid note_oid, *target_oid, expected_oid; - git_signature *signature; - const char *specs[] = { "refs/notes/commits:refs/notes/commits" }; - push_status exp_stats[] = { { "refs/notes/commits", 1 } }; - expected_ref exp_refs[] = { { "refs/notes/commits", &expected_oid } }; - git_oid_fromstr(&expected_oid, "8461a99b27b7043e58ff6e1f5d2cf07d282534fb"); - - target_oid = &_oid_b6; - - /* Create note to push */ - cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ - cl_git_pass(git_note_create(¬e_oid, _repo, signature, signature, NULL, target_oid, "hello world\n", 0)); - - do_push(specs, ARRAY_SIZE(specs), - exp_stats, ARRAY_SIZE(exp_stats), - exp_refs, ARRAY_SIZE(exp_refs), 0, 1); - - git_signature_free(signature); -} diff --git a/tests-clar/online/push_util.c b/tests-clar/online/push_util.c deleted file mode 100644 index 038c144db..000000000 --- a/tests-clar/online/push_util.c +++ /dev/null @@ -1,132 +0,0 @@ - -#include "clar_libgit2.h" -#include "buffer.h" -#include "vector.h" -#include "push_util.h" - -const git_oid OID_ZERO = {{ 0 }}; - -void updated_tip_free(updated_tip *t) -{ - git__free(t->name); - git__free(t->old_oid); - git__free(t->new_oid); - git__free(t); -} - -void record_callbacks_data_clear(record_callbacks_data *data) -{ - size_t i; - updated_tip *tip; - - git_vector_foreach(&data->updated_tips, i, tip) - updated_tip_free(tip); - - git_vector_free(&data->updated_tips); -} - -int record_update_tips_cb(const char *refname, const git_oid *a, const git_oid *b, void *data) -{ - updated_tip *t; - record_callbacks_data *record_data = (record_callbacks_data *)data; - - cl_assert(t = git__malloc(sizeof(*t))); - - cl_assert(t->name = git__strdup(refname)); - cl_assert(t->old_oid = git__malloc(sizeof(*t->old_oid))); - git_oid_cpy(t->old_oid, a); - - cl_assert(t->new_oid = git__malloc(sizeof(*t->new_oid))); - git_oid_cpy(t->new_oid, b); - - git_vector_insert(&record_data->updated_tips, t); - - return 0; -} - -int create_deletion_refspecs(git_vector *out, const git_remote_head **heads, size_t heads_len) -{ - git_buf del_spec = GIT_BUF_INIT; - size_t i; - - for (i = 0; i < heads_len; i++) { - const git_remote_head *head = heads[i]; - /* Ignore malformed ref names (which also saves us from tag^{} */ - if (!git_reference_is_valid_name(head->name)) - return 0; - - /* Create a refspec that deletes a branch in the remote */ - if (strcmp(head->name, "refs/heads/master")) { - cl_git_pass(git_buf_putc(&del_spec, ':')); - cl_git_pass(git_buf_puts(&del_spec, head->name)); - cl_git_pass(git_vector_insert(out, git_buf_detach(&del_spec))); - } - } - - return 0; -} - -int record_ref_cb(git_remote_head *head, void *payload) -{ - git_vector *refs = (git_vector *) payload; - return git_vector_insert(refs, head); -} - -void verify_remote_refs(const git_remote_head *actual_refs[], size_t actual_refs_len, const expected_ref expected_refs[], size_t expected_refs_len) -{ - size_t i, j = 0; - git_buf msg = GIT_BUF_INIT; - const git_remote_head *actual; - char *oid_str; - bool master_present = false; - - /* We don't care whether "master" is present on the other end or not */ - for (i = 0; i < actual_refs_len; i++) { - actual = actual_refs[i]; - if (!strcmp(actual->name, "refs/heads/master")) { - master_present = true; - break; - } - } - - if (expected_refs_len + (master_present ? 1 : 0) != actual_refs_len) - goto failed; - - for (i = 0; i < actual_refs_len; i++) { - actual = actual_refs[i]; - if (master_present && !strcmp(actual->name, "refs/heads/master")) - continue; - - if (strcmp(expected_refs[j].name, actual->name) || - git_oid_cmp(expected_refs[j].oid, &actual->oid)) - goto failed; - - j++; - } - - return; - -failed: - git_buf_puts(&msg, "Expected and actual refs differ:\nEXPECTED:\n"); - - for(i = 0; i < expected_refs_len; i++) { - cl_assert(oid_str = git_oid_allocfmt(expected_refs[i].oid)); - cl_git_pass(git_buf_printf(&msg, "%s = %s\n", expected_refs[i].name, oid_str)); - git__free(oid_str); - } - - git_buf_puts(&msg, "\nACTUAL:\n"); - for (i = 0; i < actual_refs_len; i++) { - actual = actual_refs[i]; - if (master_present && !strcmp(actual->name, "refs/heads/master")) - continue; - - cl_assert(oid_str = git_oid_allocfmt(&actual->oid)); - cl_git_pass(git_buf_printf(&msg, "%s = %s\n", actual->name, oid_str)); - git__free(oid_str); - } - - cl_fail(git_buf_cstr(&msg)); - - git_buf_free(&msg); -} diff --git a/tests-clar/online/push_util.h b/tests-clar/online/push_util.h deleted file mode 100644 index a7207c49e..000000000 --- a/tests-clar/online/push_util.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef INCLUDE_cl_push_util_h__ -#define INCLUDE_cl_push_util_h__ - -#include "git2/oid.h" - -/* Constant for zero oid */ -extern const git_oid OID_ZERO; - -/** - * Macro for initializing git_remote_callbacks to use test helpers that - * record data in a record_callbacks_data instance. - * @param data pointer to a record_callbacks_data instance - */ -#define RECORD_CALLBACKS_INIT(data) \ - { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, record_update_tips_cb, data } - -typedef struct { - char *name; - git_oid *old_oid; - git_oid *new_oid; -} updated_tip; - -typedef struct { - git_vector updated_tips; -} record_callbacks_data; - -typedef struct { - const char *name; - const git_oid *oid; -} expected_ref; - -void updated_tip_free(updated_tip *t); - -void record_callbacks_data_clear(record_callbacks_data *data); - -/** - * Callback for git_remote_update_tips that records updates - * - * @param data (git_vector *) of updated_tip instances - */ -int record_update_tips_cb(const char *refname, const git_oid *a, const git_oid *b, void *data); - -/** - * Create a set of refspecs that deletes each of the inputs - * - * @param out the vector in which to store the refspecs - * @param heads the remote heads - * @param heads_len the size of the array - */ -int create_deletion_refspecs(git_vector *out, const git_remote_head **heads, size_t heads_len); - -/** - * Callback for git_remote_list that adds refspecs to vector - * - * @param head a ref on the remote - * @param payload (git_vector *) of git_remote_head instances - */ -int record_ref_cb(git_remote_head *head, void *payload); - -/** - * Verifies that refs on remote stored by record_ref_cb match the expected - * names, oids, and order. - * - * @param actual_refs actual refs in the remote - * @param actual_refs_len length of actual_refs - * @param expected_refs expected remote refs - * @param expected_refs_len length of expected_refs - */ -void verify_remote_refs(const git_remote_head *actual_refs[], size_t actual_refs_len, const expected_ref expected_refs[], size_t expected_refs_len); - -#endif /* INCLUDE_cl_push_util_h__ */ diff --git a/tests-clar/pack/indexer.c b/tests-clar/pack/indexer.c deleted file mode 100644 index 07963a9e7..000000000 --- a/tests-clar/pack/indexer.c +++ /dev/null @@ -1,126 +0,0 @@ -#include "clar_libgit2.h" -#include -#include "fileops.h" -#include "hash.h" -#include "iterator.h" -#include "vector.h" -#include "posix.h" - - -/* - * This is a packfile with three objects. The second is a delta which - * depends on the third, which is also a delta. - */ -unsigned char out_of_order_pack[] = { - 0x50, 0x41, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, - 0x32, 0x78, 0x9c, 0x63, 0x67, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x76, - 0xe6, 0x8f, 0xe8, 0x12, 0x9b, 0x54, 0x6b, 0x10, 0x1a, 0xee, 0x95, 0x10, - 0xc5, 0x32, 0x8e, 0x7f, 0x21, 0xca, 0x1d, 0x18, 0x78, 0x9c, 0x63, 0x62, - 0x66, 0x4e, 0xcb, 0xcf, 0x07, 0x00, 0x02, 0xac, 0x01, 0x4d, 0x75, 0x01, - 0xd7, 0x71, 0x36, 0x66, 0xf4, 0xde, 0x82, 0x27, 0x76, 0xc7, 0x62, 0x2c, - 0x10, 0xf1, 0xb0, 0x7d, 0xe2, 0x80, 0xdc, 0x78, 0x9c, 0x63, 0x62, 0x62, - 0x62, 0xb7, 0x03, 0x00, 0x00, 0x69, 0x00, 0x4c, 0xde, 0x7d, 0xaa, 0xe4, - 0x19, 0x87, 0x58, 0x80, 0x61, 0x09, 0x9a, 0x33, 0xca, 0x7a, 0x31, 0x92, - 0x6f, 0xae, 0x66, 0x75 -}; -unsigned int out_of_order_pack_len = 112; - -/* - * Packfile with two objects. The second is a delta against an object - * which is not in the packfile - */ -unsigned char thin_pack[] = { - 0x50, 0x41, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, - 0x32, 0x78, 0x9c, 0x63, 0x67, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x76, - 0xe6, 0x8f, 0xe8, 0x12, 0x9b, 0x54, 0x6b, 0x10, 0x1a, 0xee, 0x95, 0x10, - 0xc5, 0x32, 0x8e, 0x7f, 0x21, 0xca, 0x1d, 0x18, 0x78, 0x9c, 0x63, 0x62, - 0x66, 0x4e, 0xcb, 0xcf, 0x07, 0x00, 0x02, 0xac, 0x01, 0x4d, 0x42, 0x52, - 0x3a, 0x6f, 0x39, 0xd1, 0xfe, 0x66, 0x68, 0x6b, 0xa5, 0xe5, 0xe2, 0x97, - 0xac, 0x94, 0x6c, 0x76, 0x0b, 0x04 -}; -unsigned int thin_pack_len = 78; - -unsigned char base_obj[] = { 07, 076 }; -unsigned int base_obj_len = 2; - -void test_pack_indexer__out_of_order(void) -{ - git_indexer *idx; - git_transfer_progress stats; - - cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); - cl_git_pass(git_indexer_append(idx, out_of_order_pack, out_of_order_pack_len, &stats)); - cl_git_pass(git_indexer_commit(idx, &stats)); - - cl_assert_equal_i(stats.total_objects, 3); - cl_assert_equal_i(stats.received_objects, 3); - cl_assert_equal_i(stats.indexed_objects, 3); - - git_indexer_free(idx); -} - -void test_pack_indexer__fix_thin(void) -{ - git_indexer *idx; - git_transfer_progress stats; - git_repository *repo; - git_odb *odb; - git_oid id, should_id; - - cl_git_pass(git_repository_init(&repo, "thin.git", true)); - cl_git_pass(git_repository_odb(&odb, repo)); - - /* Store the missing base into your ODB so the indexer can fix the pack */ - cl_git_pass(git_odb_write(&id, odb, base_obj, base_obj_len, GIT_OBJ_BLOB)); - git_oid_fromstr(&should_id, "e68fe8129b546b101aee9510c5328e7f21ca1d18"); - cl_assert(!git_oid_cmp(&id, &should_id)); - - cl_git_pass(git_indexer_new(&idx, ".", 0, odb, NULL, NULL)); - cl_git_pass(git_indexer_append(idx, thin_pack, thin_pack_len, &stats)); - cl_git_pass(git_indexer_commit(idx, &stats)); - - cl_assert_equal_i(stats.total_objects, 2); - cl_assert_equal_i(stats.received_objects, 2); - cl_assert_equal_i(stats.indexed_objects, 2); - cl_assert_equal_i(stats.local_objects, 1); - - git_oid_fromstr(&should_id, "11f0f69b334728fdd8bc86b80499f22f29d85b15"); - cl_assert(!git_oid_cmp(git_indexer_hash(idx), &should_id)); - - git_indexer_free(idx); - git_odb_free(odb); - git_repository_free(repo); - - /* - * The pack's name/hash only tells us what objects there are, - * so we need to go through the packfile again in order to - * figure out whether we calculated the trailer correctly. - */ - { - unsigned char buffer[128]; - int fd; - ssize_t read; - struct stat st; - const char *name = "pack-11f0f69b334728fdd8bc86b80499f22f29d85b15.pack"; - - fd = p_open(name, O_RDONLY); - cl_assert(fd != -1); - - cl_git_pass(p_stat(name, &st)); - - cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); - read = p_read(fd, buffer, sizeof(buffer)); - cl_assert(read != -1); - p_close(fd); - - cl_git_pass(git_indexer_append(idx, buffer, read, &stats)); - cl_git_pass(git_indexer_commit(idx, &stats)); - - cl_assert_equal_i(stats.total_objects, 3); - cl_assert_equal_i(stats.received_objects, 3); - cl_assert_equal_i(stats.indexed_objects, 3); - cl_assert_equal_i(stats.local_objects, 0); - - git_indexer_free(idx); - } -} diff --git a/tests-clar/pack/packbuilder.c b/tests-clar/pack/packbuilder.c deleted file mode 100644 index 54d1e8022..000000000 --- a/tests-clar/pack/packbuilder.c +++ /dev/null @@ -1,204 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "pack.h" -#include "hash.h" -#include "iterator.h" -#include "vector.h" -#include "posix.h" - -static git_repository *_repo; -static git_revwalk *_revwalker; -static git_packbuilder *_packbuilder; -static git_indexer *_indexer; -static git_vector _commits; -static int _commits_is_initialized; - -void test_pack_packbuilder__initialize(void) -{ - _repo = cl_git_sandbox_init("testrepo.git"); - cl_git_pass(git_revwalk_new(&_revwalker, _repo)); - cl_git_pass(git_packbuilder_new(&_packbuilder, _repo)); - cl_git_pass(git_vector_init(&_commits, 0, NULL)); - _commits_is_initialized = 1; -} - -void test_pack_packbuilder__cleanup(void) -{ - git_oid *o; - unsigned int i; - - if (_commits_is_initialized) { - _commits_is_initialized = 0; - git_vector_foreach(&_commits, i, o) { - git__free(o); - } - git_vector_free(&_commits); - } - - git_packbuilder_free(_packbuilder); - _packbuilder = NULL; - - git_revwalk_free(_revwalker); - _revwalker = NULL; - - git_indexer_free(_indexer); - _indexer = NULL; - - cl_git_sandbox_cleanup(); - _repo = NULL; -} - -static void seed_packbuilder(void) -{ - git_oid oid, *o; - unsigned int i; - - git_revwalk_sorting(_revwalker, GIT_SORT_TIME); - cl_git_pass(git_revwalk_push_ref(_revwalker, "HEAD")); - - while (git_revwalk_next(&oid, _revwalker) == 0) { - o = git__malloc(GIT_OID_RAWSZ); - cl_assert(o != NULL); - git_oid_cpy(o, &oid); - cl_git_pass(git_vector_insert(&_commits, o)); - } - - git_vector_foreach(&_commits, i, o) { - cl_git_pass(git_packbuilder_insert(_packbuilder, o, NULL)); - } - - git_vector_foreach(&_commits, i, o) { - git_object *obj; - cl_git_pass(git_object_lookup(&obj, _repo, o, GIT_OBJ_COMMIT)); - cl_git_pass(git_packbuilder_insert_tree(_packbuilder, - git_commit_tree_id((git_commit *)obj))); - git_object_free(obj); - } -} - -static int feed_indexer(void *ptr, size_t len, void *payload) -{ - git_transfer_progress *stats = (git_transfer_progress *)payload; - - return git_indexer_append(_indexer, ptr, len, stats); -} - -void test_pack_packbuilder__create_pack(void) -{ - git_transfer_progress stats; - git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT; - git_hash_ctx ctx; - git_oid hash; - char hex[41]; hex[40] = '\0'; - - seed_packbuilder(); - - cl_git_pass(git_indexer_new(&_indexer, ".", 0, NULL, NULL, NULL)); - cl_git_pass(git_packbuilder_foreach(_packbuilder, feed_indexer, &stats)); - cl_git_pass(git_indexer_commit(_indexer, &stats)); - - git_oid_fmt(hex, git_indexer_hash(_indexer)); - git_buf_printf(&path, "pack-%s.pack", hex); - - /* - * By default, packfiles are created with only one thread. - * Therefore we can predict the object ordering and make sure - * we create exactly the same pack as git.git does when *not* - * reusing existing deltas (as libgit2). - * - * $ cd tests-clar/resources/testrepo.git - * $ git rev-list --objects HEAD | \ - * git pack-objects -q --no-reuse-delta --threads=1 pack - * $ sha1sum git-80e61eb315239ef3c53033e37fee43b744d57122.pack - * 5d410bdf97cf896f9007681b92868471d636954b - * - */ - - cl_git_pass(git_futils_readbuffer(&buf, git_buf_cstr(&path))); - - cl_git_pass(git_hash_ctx_init(&ctx)); - cl_git_pass(git_hash_update(&ctx, buf.ptr, buf.size)); - cl_git_pass(git_hash_final(&hash, &ctx)); - git_hash_ctx_cleanup(&ctx); - - git_buf_free(&path); - git_buf_free(&buf); - - git_oid_fmt(hex, &hash); - - cl_assert_equal_s(hex, "5d410bdf97cf896f9007681b92868471d636954b"); -} - -void test_pack_packbuilder__get_hash(void) -{ - char hex[41]; hex[40] = '\0'; - - seed_packbuilder(); - - git_packbuilder_write(_packbuilder, ".", 0, NULL, NULL); - git_oid_fmt(hex, git_packbuilder_hash(_packbuilder)); - - cl_assert_equal_s(hex, "80e61eb315239ef3c53033e37fee43b744d57122"); -} - -static void test_write_pack_permission(mode_t given, mode_t expected) -{ - struct stat statbuf; - mode_t mask, os_mask; - - seed_packbuilder(); - - git_packbuilder_write(_packbuilder, ".", given, NULL, NULL); - - /* Windows does not return group/user bits from stat, - * files are never executable. - */ -#ifdef GIT_WIN32 - os_mask = 0600; -#else - os_mask = 0777; -#endif - - mask = p_umask(0); - p_umask(mask); - - cl_git_pass(p_stat("pack-80e61eb315239ef3c53033e37fee43b744d57122.idx", &statbuf)); - cl_assert_equal_i(statbuf.st_mode & os_mask, (expected & ~mask) & os_mask); - - cl_git_pass(p_stat("pack-80e61eb315239ef3c53033e37fee43b744d57122.pack", &statbuf)); - cl_assert_equal_i(statbuf.st_mode & os_mask, (expected & ~mask) & os_mask); -} - -void test_pack_packbuilder__permissions_standard(void) -{ - test_write_pack_permission(0, GIT_PACK_FILE_MODE); -} - -void test_pack_packbuilder__permissions_readonly(void) -{ - test_write_pack_permission(0444, 0444); -} - -void test_pack_packbuilder__permissions_readwrite(void) -{ - test_write_pack_permission(0666, 0666); -} - -static git_transfer_progress stats; -static int foreach_cb(void *buf, size_t len, void *payload) -{ - git_indexer *idx = (git_indexer *) payload; - cl_git_pass(git_indexer_append(idx, buf, len, &stats)); - return 0; -} - -void test_pack_packbuilder__foreach(void) -{ - git_indexer *idx; - - seed_packbuilder(); - cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); - cl_git_pass(git_packbuilder_foreach(_packbuilder, foreach_cb, idx)); - cl_git_pass(git_indexer_commit(idx, &stats)); - git_indexer_free(idx); -} diff --git a/tests-clar/refs/branches/create.c b/tests-clar/refs/branches/create.c deleted file mode 100644 index 693a592a3..000000000 --- a/tests-clar/refs/branches/create.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" - -static git_repository *repo; -static git_commit *target; -static git_reference *branch; - -void test_refs_branches_create__initialize(void) -{ - cl_fixture_sandbox("testrepo.git"); - cl_git_pass(git_repository_open(&repo, "testrepo.git")); - - branch = NULL; -} - -void test_refs_branches_create__cleanup(void) -{ - git_reference_free(branch); - branch = NULL; - - git_commit_free(target); - target = NULL; - - git_repository_free(repo); - repo = NULL; - - cl_fixture_cleanup("testrepo.git"); -} - -static void retrieve_target_from_oid(git_commit **out, git_repository *repo, const char *sha) -{ - git_oid oid; - - cl_git_pass(git_oid_fromstr(&oid, sha)); - cl_git_pass(git_commit_lookup(out, repo, &oid)); -} - -static void retrieve_known_commit(git_commit **commit, git_repository *repo) -{ - retrieve_target_from_oid(commit, repo, "e90810b8df3e80c413d903f631643c716887138d"); -} - -#define NEW_BRANCH_NAME "new-branch-on-the-block" - -void test_refs_branches_create__can_create_a_local_branch(void) -{ - retrieve_known_commit(&target, repo); - - cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, 0)); - cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target))); -} - -void test_refs_branches_create__can_not_create_a_branch_if_its_name_collide_with_an_existing_one(void) -{ - retrieve_known_commit(&target, repo); - - cl_assert_equal_i(GIT_EEXISTS, git_branch_create(&branch, repo, "br2", target, 0)); -} - -void test_refs_branches_create__can_force_create_over_an_existing_branch(void) -{ - retrieve_known_commit(&target, repo); - - cl_git_pass(git_branch_create(&branch, repo, "br2", target, 1)); - cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target))); - cl_assert_equal_s("refs/heads/br2", git_reference_name(branch)); -} - - -void test_refs_branches_create__creating_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void) -{ - retrieve_known_commit(&target, repo); - - cl_assert_equal_i(GIT_EINVALIDSPEC, - git_branch_create(&branch, repo, "inv@{id", target, 0)); -} \ No newline at end of file diff --git a/tests-clar/refs/branches/delete.c b/tests-clar/refs/branches/delete.c deleted file mode 100644 index de90cb734..000000000 --- a/tests-clar/refs/branches/delete.c +++ /dev/null @@ -1,117 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" -#include "repo/repo_helpers.h" -#include "config/config_helpers.h" - -static git_repository *repo; -static git_reference *fake_remote; - -void test_refs_branches_delete__initialize(void) -{ - git_oid id; - - cl_fixture_sandbox("testrepo.git"); - cl_git_pass(git_repository_open(&repo, "testrepo.git")); - - cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); - cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0)); -} - -void test_refs_branches_delete__cleanup(void) -{ - git_reference_free(fake_remote); - fake_remote = NULL; - - git_repository_free(repo); - repo = NULL; - - cl_fixture_cleanup("testrepo.git"); -} - -void test_refs_branches_delete__can_not_delete_a_branch_pointed_at_by_HEAD(void) -{ - git_reference *head; - git_reference *branch; - - /* Ensure HEAD targets the local master branch */ - cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE)); - cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); - git_reference_free(head); - - cl_git_pass(git_branch_lookup(&branch, repo, "master", GIT_BRANCH_LOCAL)); - cl_git_fail(git_branch_delete(branch)); - git_reference_free(branch); -} - -void test_refs_branches_delete__can_delete_a_branch_even_if_HEAD_is_missing(void) -{ - git_reference *head; - git_reference *branch; - - cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE)); - git_reference_delete(head); - git_reference_free(head); - - cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL)); - cl_git_pass(git_branch_delete(branch)); - git_reference_free(branch); -} - -void test_refs_branches_delete__can_delete_a_branch_when_HEAD_is_unborn(void) -{ - git_reference *branch; - - make_head_unborn(repo, NON_EXISTING_HEAD); - - cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL)); - cl_git_pass(git_branch_delete(branch)); - git_reference_free(branch); -} - -void test_refs_branches_delete__can_delete_a_branch_pointed_at_by_detached_HEAD(void) -{ - git_reference *head, *branch; - - cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE)); - cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); - cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); - git_reference_free(head); - - /* Detach HEAD and make it target the commit that "master" points to */ - git_repository_detach_head(repo); - - cl_git_pass(git_branch_lookup(&branch, repo, "master", GIT_BRANCH_LOCAL)); - cl_git_pass(git_branch_delete(branch)); - git_reference_free(branch); -} - -void test_refs_branches_delete__can_delete_a_local_branch(void) -{ - git_reference *branch; - cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL)); - cl_git_pass(git_branch_delete(branch)); - git_reference_free(branch); -} - -void test_refs_branches_delete__can_delete_a_remote_branch(void) -{ - git_reference *branch; - cl_git_pass(git_branch_lookup(&branch, repo, "nulltoken/master", GIT_BRANCH_REMOTE)); - cl_git_pass(git_branch_delete(branch)); - git_reference_free(branch); -} - -void test_refs_branches_delete__deleting_a_branch_removes_related_configuration_data(void) -{ - git_reference *branch; - - assert_config_entry_existence(repo, "branch.track-local.remote", true); - assert_config_entry_existence(repo, "branch.track-local.merge", true); - - cl_git_pass(git_branch_lookup(&branch, repo, "track-local", GIT_BRANCH_LOCAL)); - cl_git_pass(git_branch_delete(branch)); - git_reference_free(branch); - - assert_config_entry_existence(repo, "branch.track-local.remote", false); - assert_config_entry_existence(repo, "branch.track-local.merge", false); -} diff --git a/tests-clar/refs/branches/ishead.c b/tests-clar/refs/branches/ishead.c deleted file mode 100644 index b1ad09c3e..000000000 --- a/tests-clar/refs/branches/ishead.c +++ /dev/null @@ -1,116 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" -#include "repo/repo_helpers.h" - -static git_repository *repo; -static git_reference *branch; - -void test_refs_branches_ishead__initialize(void) -{ - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); -} - -void test_refs_branches_ishead__cleanup(void) -{ - git_reference_free(branch); - branch = NULL; - - git_repository_free(repo); - repo = NULL; -} - -void test_refs_branches_ishead__can_tell_if_a_branch_is_pointed_at_by_HEAD(void) -{ - cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master")); - - cl_assert_equal_i(true, git_branch_is_head(branch)); -} - -void test_refs_branches_ishead__can_properly_handle_unborn_HEAD(void) -{ - git_repository_free(repo); - - repo = cl_git_sandbox_init("testrepo.git"); - - make_head_unborn(repo, NON_EXISTING_HEAD); - - cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master")); - - cl_assert_equal_i(false, git_branch_is_head(branch)); - - cl_git_sandbox_cleanup(); - repo = NULL; -} - -void test_refs_branches_ishead__can_properly_handle_missing_HEAD(void) -{ - git_repository_free(repo); - - repo = cl_git_sandbox_init("testrepo.git"); - - delete_head(repo); - - cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master")); - - cl_assert_equal_i(false, git_branch_is_head(branch)); - - cl_git_sandbox_cleanup(); - repo = NULL; -} - -void test_refs_branches_ishead__can_tell_if_a_branch_is_not_pointed_at_by_HEAD(void) -{ - cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/br2")); - - cl_assert_equal_i(false, git_branch_is_head(branch)); -} - -void test_refs_branches_ishead__wont_be_fooled_by_a_non_branch(void) -{ - cl_git_pass(git_reference_lookup(&branch, repo, "refs/tags/e90810b")); - - cl_assert_equal_i(false, git_branch_is_head(branch)); -} - -/* - * $ git init . - * Initialized empty Git repository in d:/temp/tempee/.git/ - * - * $ touch a && git add a - * $ git commit -m" boom" - * [master (root-commit) b47b758] boom - * 0 files changed - * create mode 100644 a - * - * $ echo "ref: refs/heads/master" > .git/refs/heads/linked - * $ echo "ref: refs/heads/linked" > .git/refs/heads/super - * $ echo "ref: refs/heads/super" > .git/HEAD - * - * $ git branch - * linked -> master - * * master - * super -> master - */ -void test_refs_branches_ishead__only_direct_references_are_considered(void) -{ - git_reference *linked, *super, *head; - - git_repository_free(repo); - repo = cl_git_sandbox_init("testrepo.git"); - - cl_git_pass(git_reference_symbolic_create(&linked, repo, "refs/heads/linked", "refs/heads/master", 0)); - cl_git_pass(git_reference_symbolic_create(&super, repo, "refs/heads/super", "refs/heads/linked", 0)); - cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, "refs/heads/super", 1)); - - cl_assert_equal_i(false, git_branch_is_head(linked)); - cl_assert_equal_i(false, git_branch_is_head(super)); - - cl_git_pass(git_repository_head(&branch, repo)); - cl_assert_equal_s("refs/heads/master", git_reference_name(branch)); - - git_reference_free(linked); - git_reference_free(super); - git_reference_free(head); - cl_git_sandbox_cleanup(); - repo = NULL; -} diff --git a/tests-clar/refs/branches/iterator.c b/tests-clar/refs/branches/iterator.c deleted file mode 100644 index 904c6a146..000000000 --- a/tests-clar/refs/branches/iterator.c +++ /dev/null @@ -1,151 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" - -static git_repository *repo; -static git_reference *fake_remote; - -void test_refs_branches_iterator__initialize(void) -{ - git_oid id; - - cl_fixture_sandbox("testrepo.git"); - cl_git_pass(git_repository_open(&repo, "testrepo.git")); - - cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); - cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0)); -} - -void test_refs_branches_iterator__cleanup(void) -{ - git_reference_free(fake_remote); - fake_remote = NULL; - - git_repository_free(repo); - repo = NULL; - - cl_fixture_cleanup("testrepo.git"); - - cl_git_sandbox_cleanup(); -} - -static void assert_retrieval(unsigned int flags, unsigned int expected_count) -{ - git_branch_iterator *iter; - git_reference *ref; - int count = 0, error; - git_branch_t type; - - cl_git_pass(git_branch_iterator_new(&iter, repo, flags)); - while ((error = git_branch_next(&ref, &type, iter)) == 0) { - count++; - git_reference_free(ref); - } - - git_branch_iterator_free(iter); - cl_assert_equal_i(error, GIT_ITEROVER); - cl_assert_equal_i(expected_count, count); -} - -void test_refs_branches_iterator__retrieve_all_branches(void) -{ - assert_retrieval(GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, 14); -} - -void test_refs_branches_iterator__retrieve_remote_branches(void) -{ - assert_retrieval(GIT_BRANCH_REMOTE, 2); -} - -void test_refs_branches_iterator__retrieve_local_branches(void) -{ - assert_retrieval(GIT_BRANCH_LOCAL, 12); -} - -struct expectations { - const char *branch_name; - int encounters; -}; - -static void assert_branch_has_been_found(struct expectations *findings, const char* expected_branch_name) -{ - int pos = 0; - - for (pos = 0; findings[pos].branch_name; ++pos) { - if (strcmp(expected_branch_name, findings[pos].branch_name) == 0) { - cl_assert_equal_i(1, findings[pos].encounters); - return; - } - } - - cl_fail("expected branch not found in list."); -} - -static void contains_branches(struct expectations exp[], git_branch_iterator *iter) -{ - git_reference *ref; - git_branch_t type; - int error, pos = 0; - - while ((error = git_branch_next(&ref, &type, iter)) == 0) { - for (pos = 0; exp[pos].branch_name; ++pos) { - if (strcmp(git_reference_shorthand(ref), exp[pos].branch_name) == 0) - exp[pos].encounters++; - } - - git_reference_free(ref); - } - - cl_assert_equal_i(error, GIT_ITEROVER); -} - -/* - * $ git branch -r - * nulltoken/HEAD -> nulltoken/master - * nulltoken/master - */ -void test_refs_branches_iterator__retrieve_remote_symbolic_HEAD_when_present(void) -{ - git_branch_iterator *iter; - struct expectations exp[] = { - { "nulltoken/HEAD", 0 }, - { "nulltoken/master", 0 }, - { NULL, 0 } - }; - - git_reference_free(fake_remote); - cl_git_pass(git_reference_symbolic_create(&fake_remote, repo, "refs/remotes/nulltoken/HEAD", "refs/remotes/nulltoken/master", 0)); - - assert_retrieval(GIT_BRANCH_REMOTE, 3); - - cl_git_pass(git_branch_iterator_new(&iter, repo, GIT_BRANCH_REMOTE)); - contains_branches(exp, iter); - git_branch_iterator_free(iter); - - assert_branch_has_been_found(exp, "nulltoken/HEAD"); - assert_branch_has_been_found(exp, "nulltoken/master"); -} - -void test_refs_branches_iterator__mix_of_packed_and_loose(void) -{ - git_branch_iterator *iter; - struct expectations exp[] = { - { "master", 0 }, - { "origin/HEAD", 0 }, - { "origin/master", 0 }, - { "origin/packed", 0 }, - { NULL, 0 } - }; - git_repository *r2; - - r2 = cl_git_sandbox_init("testrepo2"); - - cl_git_pass(git_branch_iterator_new(&iter, r2, GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE)); - contains_branches(exp, iter); - - git_branch_iterator_free(iter); - - assert_branch_has_been_found(exp, "master"); - assert_branch_has_been_found(exp, "origin/HEAD"); - assert_branch_has_been_found(exp, "origin/master"); - assert_branch_has_been_found(exp, "origin/packed"); -} diff --git a/tests-clar/refs/branches/lookup.c b/tests-clar/refs/branches/lookup.c deleted file mode 100644 index 95d49a4b3..000000000 --- a/tests-clar/refs/branches/lookup.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" - -static git_repository *repo; -static git_reference *branch; - -void test_refs_branches_lookup__initialize(void) -{ - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - - branch = NULL; -} - -void test_refs_branches_lookup__cleanup(void) -{ - git_reference_free(branch); - branch = NULL; - - git_repository_free(repo); - repo = NULL; -} - -void test_refs_branches_lookup__can_retrieve_a_local_branch(void) -{ - cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL)); -} - -void test_refs_branches_lookup__can_retrieve_a_remote_tracking_branch(void) -{ - cl_git_pass(git_branch_lookup(&branch, repo, "test/master", GIT_BRANCH_REMOTE)); -} - -void test_refs_branches_lookup__trying_to_retrieve_an_unknown_branch_returns_ENOTFOUND(void) -{ - cl_assert_equal_i(GIT_ENOTFOUND, git_branch_lookup(&branch, repo, "where/are/you", GIT_BRANCH_LOCAL)); - cl_assert_equal_i(GIT_ENOTFOUND, git_branch_lookup(&branch, repo, "over/here", GIT_BRANCH_REMOTE)); -} - -void test_refs_branches_lookup__trying_to_retrieve_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void) -{ - cl_assert_equal_i(GIT_EINVALIDSPEC, - git_branch_lookup(&branch, repo, "are/you/inv@{id", GIT_BRANCH_LOCAL)); - cl_assert_equal_i(GIT_EINVALIDSPEC, - git_branch_lookup(&branch, repo, "yes/i am", GIT_BRANCH_REMOTE)); -} diff --git a/tests-clar/refs/branches/move.c b/tests-clar/refs/branches/move.c deleted file mode 100644 index ecf14e006..000000000 --- a/tests-clar/refs/branches/move.c +++ /dev/null @@ -1,146 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" -#include "config/config_helpers.h" - -static git_repository *repo; - -void test_refs_branches_move__initialize(void) -{ - repo = cl_git_sandbox_init("testrepo.git"); -} - -void test_refs_branches_move__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -#define NEW_BRANCH_NAME "new-branch-on-the-block" - -void test_refs_branches_move__can_move_a_local_branch(void) -{ - git_reference *original_ref, *new_ref; - - cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); - - cl_git_pass(git_branch_move(&new_ref, original_ref, NEW_BRANCH_NAME, 0)); - cl_assert_equal_s(GIT_REFS_HEADS_DIR NEW_BRANCH_NAME, git_reference_name(new_ref)); - - git_reference_free(original_ref); - git_reference_free(new_ref); -} - -void test_refs_branches_move__can_move_a_local_branch_to_a_different_namespace(void) -{ - git_reference *original_ref, *new_ref, *newer_ref; - - cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); - - /* Downward */ - cl_git_pass(git_branch_move(&new_ref, original_ref, "somewhere/" NEW_BRANCH_NAME, 0)); - git_reference_free(original_ref); - - /* Upward */ - cl_git_pass(git_branch_move(&newer_ref, new_ref, "br2", 0)); - git_reference_free(new_ref); - - git_reference_free(newer_ref); -} - -void test_refs_branches_move__can_move_a_local_branch_to_a_partially_colliding_namespace(void) -{ - git_reference *original_ref, *new_ref, *newer_ref; - - cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); - - /* Downward */ - cl_git_pass(git_branch_move(&new_ref, original_ref, "br2/" NEW_BRANCH_NAME, 0)); - git_reference_free(original_ref); - - /* Upward */ - cl_git_pass(git_branch_move(&newer_ref, new_ref, "br2", 0)); - git_reference_free(new_ref); - - git_reference_free(newer_ref); -} - -void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_collide_with_an_existing_one(void) -{ - git_reference *original_ref, *new_ref; - - cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); - - cl_assert_equal_i(GIT_EEXISTS, git_branch_move(&new_ref, original_ref, "master", 0)); - - git_reference_free(original_ref); -} - -void test_refs_branches_move__moving_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void) -{ - git_reference *original_ref, *new_ref; - - cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); - - cl_assert_equal_i(GIT_EINVALIDSPEC, git_branch_move(&new_ref, original_ref, "Inv@{id", 0)); - - git_reference_free(original_ref); -} - -void test_refs_branches_move__can_not_move_a_non_branch(void) -{ - git_reference *tag, *new_ref; - - cl_git_pass(git_reference_lookup(&tag, repo, "refs/tags/e90810b")); - cl_git_fail(git_branch_move(&new_ref, tag, NEW_BRANCH_NAME, 0)); - - git_reference_free(tag); -} - -void test_refs_branches_move__can_force_move_over_an_existing_branch(void) -{ - git_reference *original_ref, *new_ref; - - cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); - - cl_git_pass(git_branch_move(&new_ref, original_ref, "master", 1)); - - git_reference_free(original_ref); - git_reference_free(new_ref); -} - -void test_refs_branches_move__moving_a_branch_moves_related_configuration_data(void) -{ - git_reference *branch; - git_reference *new_branch; - - cl_git_pass(git_branch_lookup(&branch, repo, "track-local", GIT_BRANCH_LOCAL)); - - assert_config_entry_existence(repo, "branch.track-local.remote", true); - assert_config_entry_existence(repo, "branch.track-local.merge", true); - assert_config_entry_existence(repo, "branch.moved.remote", false); - assert_config_entry_existence(repo, "branch.moved.merge", false); - - cl_git_pass(git_branch_move(&new_branch, branch, "moved", 0)); - git_reference_free(branch); - - assert_config_entry_existence(repo, "branch.track-local.remote", false); - assert_config_entry_existence(repo, "branch.track-local.merge", false); - assert_config_entry_existence(repo, "branch.moved.remote", true); - assert_config_entry_existence(repo, "branch.moved.merge", true); - - git_reference_free(new_branch); -} - -void test_refs_branches_move__moving_the_branch_pointed_at_by_HEAD_updates_HEAD(void) -{ - git_reference *branch; - git_reference *new_branch; - - cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master")); - cl_git_pass(git_branch_move(&new_branch, branch, "master2", 0)); - git_reference_free(branch); - git_reference_free(new_branch); - - cl_git_pass(git_repository_head(&branch, repo)); - cl_assert_equal_s("refs/heads/master2", git_reference_name(branch)); - git_reference_free(branch); -} diff --git a/tests-clar/refs/branches/name.c b/tests-clar/refs/branches/name.c deleted file mode 100644 index 176f836a4..000000000 --- a/tests-clar/refs/branches/name.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "clar_libgit2.h" -#include "branch.h" - -static git_repository *repo; -static git_reference *ref; - -void test_refs_branches_name__initialize(void) -{ - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); -} - -void test_refs_branches_name__cleanup(void) -{ - git_reference_free(ref); - ref = NULL; - - git_repository_free(repo); - repo = NULL; -} - -void test_refs_branches_name__can_get_local_branch_name(void) -{ - const char *name; - - cl_git_pass(git_branch_lookup(&ref,repo,"master",GIT_BRANCH_LOCAL)); - cl_git_pass(git_branch_name(&name,ref)); - cl_assert_equal_s("master",name); -} - -void test_refs_branches_name__can_get_remote_branch_name(void) -{ - const char *name; - - cl_git_pass(git_branch_lookup(&ref,repo,"test/master",GIT_BRANCH_REMOTE)); - cl_git_pass(git_branch_name(&name,ref)); - cl_assert_equal_s("test/master",name); -} - -void test_refs_branches_name__error_when_ref_is_no_branch(void) -{ - const char *name; - - cl_git_pass(git_reference_lookup(&ref,repo,"refs/notes/fanout")); - cl_git_fail(git_branch_name(&name,ref)); -} diff --git a/tests-clar/refs/branches/remote.c b/tests-clar/refs/branches/remote.c deleted file mode 100644 index c110adb33..000000000 --- a/tests-clar/refs/branches/remote.c +++ /dev/null @@ -1,86 +0,0 @@ -#include "clar_libgit2.h" -#include "branch.h" -#include "remote.h" - -static git_repository *g_repo; -static const char *remote_tracking_branch_name = "refs/remotes/test/master"; -static const char *expected_remote_name = "test"; -static int expected_remote_name_length; - -void test_refs_branches_remote__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); - - expected_remote_name_length = (int)strlen(expected_remote_name) + 1; -} - -void test_refs_branches_remote__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_refs_branches_remote__can_get_remote_for_branch(void) -{ - char remotename[1024] = {0}; - - cl_assert_equal_i(expected_remote_name_length, - git_branch_remote_name(NULL, 0, g_repo, remote_tracking_branch_name)); - - cl_assert_equal_i(expected_remote_name_length, - git_branch_remote_name(remotename, expected_remote_name_length, g_repo, - remote_tracking_branch_name)); - - cl_assert_equal_s("test", remotename); -} - -void test_refs_branches_remote__insufficient_buffer_returns_error(void) -{ - char remotename[1024] = {0}; - - cl_assert_equal_i(expected_remote_name_length, - git_branch_remote_name(NULL, 0, g_repo, remote_tracking_branch_name)); - - cl_git_fail_with(git_branch_remote_name(remotename, - expected_remote_name_length - 1, g_repo, remote_tracking_branch_name), - expected_remote_name_length); -} - -void test_refs_branches_remote__no_matching_remote_returns_error(void) -{ - const char *unknown = "refs/remotes/nonexistent/master"; - - giterr_clear(); - cl_git_fail_with(git_branch_remote_name( - NULL, 0, g_repo, unknown), GIT_ENOTFOUND); - cl_assert(giterr_last() != NULL); -} - -void test_refs_branches_remote__local_remote_returns_error(void) -{ - const char *local = "refs/heads/master"; - - giterr_clear(); - cl_git_fail_with(git_branch_remote_name( - NULL, 0, g_repo, local), GIT_ERROR); - cl_assert(giterr_last() != NULL); -} - -void test_refs_branches_remote__ambiguous_remote_returns_error(void) -{ - git_remote *remote; - - /* Create the remote */ - cl_git_pass(git_remote_create(&remote, g_repo, "addtest", "http://github.com/libgit2/libgit2")); - - /* Update the remote fetch spec */ - git_remote_clear_refspecs(remote); - cl_git_pass(git_remote_add_fetch(remote, "refs/heads/*:refs/remotes/test/*")); - cl_git_pass(git_remote_save(remote)); - - git_remote_free(remote); - - giterr_clear(); - cl_git_fail_with(git_branch_remote_name(NULL, 0, g_repo, - remote_tracking_branch_name), GIT_EAMBIGUOUS); - cl_assert(giterr_last() != NULL); -} diff --git a/tests-clar/refs/branches/upstream.c b/tests-clar/refs/branches/upstream.c deleted file mode 100644 index 69e55a0c5..000000000 --- a/tests-clar/refs/branches/upstream.c +++ /dev/null @@ -1,143 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" - -static git_repository *repo; -static git_reference *branch, *upstream; - -void test_refs_branches_upstream__initialize(void) -{ - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - - branch = NULL; - upstream = NULL; -} - -void test_refs_branches_upstream__cleanup(void) -{ - git_reference_free(upstream); - git_reference_free(branch); - branch = NULL; - - git_repository_free(repo); - repo = NULL; -} - -void test_refs_branches_upstream__can_retrieve_the_remote_tracking_reference_of_a_local_branch(void) -{ - cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master")); - - cl_git_pass(git_branch_upstream(&upstream, branch)); - - cl_assert_equal_s("refs/remotes/test/master", git_reference_name(upstream)); -} - -void test_refs_branches_upstream__can_retrieve_the_local_upstream_reference_of_a_local_branch(void) -{ - cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/track-local")); - - cl_git_pass(git_branch_upstream(&upstream, branch)); - - cl_assert_equal_s("refs/heads/master", git_reference_name(upstream)); -} - -void test_refs_branches_upstream__cannot_retrieve_a_remote_upstream_reference_from_a_non_branch(void) -{ - cl_git_pass(git_reference_lookup(&branch, repo, "refs/tags/e90810b")); - - cl_git_fail(git_branch_upstream(&upstream, branch)); -} - -void test_refs_branches_upstream__trying_to_retrieve_a_remote_tracking_reference_from_a_plain_local_branch_returns_GIT_ENOTFOUND(void) -{ - cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/subtrees")); - - cl_assert_equal_i(GIT_ENOTFOUND, git_branch_upstream(&upstream, branch)); -} - -void test_refs_branches_upstream__trying_to_retrieve_a_remote_tracking_reference_from_a_branch_with_no_fetchspec_returns_GIT_ENOTFOUND(void) -{ - cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/cannot-fetch")); - - cl_assert_equal_i(GIT_ENOTFOUND, git_branch_upstream(&upstream, branch)); -} - -static void assert_merge_and_or_remote_key_missing(git_repository *repository, const git_commit *target, const char *entry_name) -{ - git_reference *branch; - - cl_assert_equal_i(GIT_OBJ_COMMIT, git_object_type((git_object*)target)); - cl_git_pass(git_branch_create(&branch, repository, entry_name, (git_commit*)target, 0)); - - cl_assert_equal_i(GIT_ENOTFOUND, git_branch_upstream(&upstream, branch)); - - git_reference_free(branch); -} - -void test_refs_branches_upstream__retrieve_a_remote_tracking_reference_from_a_branch_with_no_remote_returns_GIT_ENOTFOUND(void) -{ - git_reference *head; - git_repository *repository; - git_commit *target; - - repository = cl_git_sandbox_init("testrepo.git"); - - cl_git_pass(git_repository_head(&head, repository)); - cl_git_pass(git_reference_peel(((git_object **)&target), head, GIT_OBJ_COMMIT)); - git_reference_free(head); - - assert_merge_and_or_remote_key_missing(repository, target, "remoteless"); - assert_merge_and_or_remote_key_missing(repository, target, "mergeless"); - assert_merge_and_or_remote_key_missing(repository, target, "mergeandremoteless"); - - git_commit_free(target); - - cl_git_sandbox_cleanup(); -} - -void test_refs_branches_upstream__set_unset_upstream(void) -{ - git_reference *branch; - git_repository *repository; - const char *value; - git_config *config; - - repository = cl_git_sandbox_init("testrepo.git"); - - /* remote */ - cl_git_pass(git_reference_lookup(&branch, repository, "refs/heads/test")); - cl_git_pass(git_branch_set_upstream(branch, "test/master")); - - cl_git_pass(git_repository_config(&config, repository)); - cl_git_pass(git_config_get_string(&value, config, "branch.test.remote")); - cl_assert_equal_s(value, "test"); - cl_git_pass(git_config_get_string(&value, config, "branch.test.merge")); - cl_assert_equal_s(value, "refs/heads/master"); - - git_reference_free(branch); - - /* local */ - cl_git_pass(git_reference_lookup(&branch, repository, "refs/heads/test")); - cl_git_pass(git_branch_set_upstream(branch, "master")); - - cl_git_pass(git_config_get_string(&value, config, "branch.test.remote")); - cl_assert_equal_s(value, "."); - cl_git_pass(git_config_get_string(&value, config, "branch.test.merge")); - cl_assert_equal_s(value, "refs/heads/master"); - - /* unset */ - cl_git_pass(git_branch_set_upstream(branch, NULL)); - cl_git_fail_with(git_config_get_string(&value, config, "branch.test.merge"), GIT_ENOTFOUND); - cl_git_fail_with(git_config_get_string(&value, config, "branch.test.remote"), GIT_ENOTFOUND); - - git_reference_free(branch); - - cl_git_pass(git_reference_lookup(&branch, repository, "refs/heads/master")); - cl_git_pass(git_branch_set_upstream(branch, NULL)); - cl_git_fail_with(git_config_get_string(&value, config, "branch.master.merge"), GIT_ENOTFOUND); - cl_git_fail_with(git_config_get_string(&value, config, "branch.master.remote"), GIT_ENOTFOUND); - - git_reference_free(branch); - - git_config_free(config); - cl_git_sandbox_cleanup(); -} diff --git a/tests-clar/refs/branches/upstreamname.c b/tests-clar/refs/branches/upstreamname.c deleted file mode 100644 index f05607d44..000000000 --- a/tests-clar/refs/branches/upstreamname.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "clar_libgit2.h" -#include "branch.h" - -static git_repository *repo; -static git_buf upstream_name; - -void test_refs_branches_upstreamname__initialize(void) -{ - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - - git_buf_init(&upstream_name, 0); -} - -void test_refs_branches_upstreamname__cleanup(void) -{ - git_buf_free(&upstream_name); - - git_repository_free(repo); - repo = NULL; -} - -void test_refs_branches_upstreamname__can_retrieve_the_remote_tracking_reference_name_of_a_local_branch(void) -{ - cl_git_pass(git_branch_upstream__name( - &upstream_name, repo, "refs/heads/master")); - - cl_assert_equal_s("refs/remotes/test/master", git_buf_cstr(&upstream_name)); -} - -void test_refs_branches_upstreamname__can_retrieve_the_local_upstream_reference_name_of_a_local_branch(void) -{ - cl_git_pass(git_branch_upstream__name( - &upstream_name, repo, "refs/heads/track-local")); - - cl_assert_equal_s("refs/heads/master", git_buf_cstr(&upstream_name)); -} - -void test_refs_branches_upstreamname__can_return_the_size_of_thelocal_upstream_reference_name_of_a_local_branch(void) -{ - cl_assert_equal_i((int)strlen("refs/heads/master") + 1, - git_branch_upstream_name(NULL, 0, repo, "refs/heads/track-local")); -} diff --git a/tests-clar/refs/crashes.c b/tests-clar/refs/crashes.c deleted file mode 100644 index 5a1885a7a..000000000 --- a/tests-clar/refs/crashes.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "clar_libgit2.h" - -void test_refs_crashes__double_free(void) -{ - git_repository *repo; - git_reference *ref, *ref2; - const char *REFNAME = "refs/heads/xxx"; - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_reference_symbolic_create(&ref, repo, REFNAME, "refs/heads/master", 0)); - cl_git_pass(git_reference_lookup(&ref2, repo, REFNAME)); - cl_git_pass(git_reference_delete(ref)); - git_reference_free(ref); - git_reference_free(ref2); - - /* reference is gone from disk, so reloading it will fail */ - cl_git_fail(git_reference_lookup(&ref2, repo, REFNAME)); - - git_repository_free(repo); -} diff --git a/tests-clar/refs/create.c b/tests-clar/refs/create.c deleted file mode 100644 index 85ff05aa9..000000000 --- a/tests-clar/refs/create.c +++ /dev/null @@ -1,168 +0,0 @@ -#include "clar_libgit2.h" - -#include "repository.h" -#include "git2/reflog.h" -#include "reflog.h" -#include "ref_helpers.h" - -static const char *current_master_tip = "099fabac3a9ea935598528c27f866e34089c2eff"; -static const char *current_head_target = "refs/heads/master"; - -static git_repository *g_repo; - -void test_refs_create__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_refs_create__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_refs_create__symbolic(void) -{ - // create a new symbolic reference - git_reference *new_reference, *looked_up_ref, *resolved_ref; - git_repository *repo2; - git_oid id; - - const char *new_head_tracker = "ANOTHER_HEAD_TRACKER"; - - git_oid_fromstr(&id, current_master_tip); - - /* Create and write the new symbolic reference */ - cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0)); - - /* 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); - - /* ...peeled.. */ - cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref)); - cl_assert(git_reference_type(resolved_ref) == GIT_REF_OID); - - /* ...and that it points to the current master tip */ - cl_assert(git_oid_cmp(&id, git_reference_target(resolved_ref)) == 0); - git_reference_free(looked_up_ref); - git_reference_free(resolved_ref); - - /* Similar test with a fresh new repository */ - cl_git_pass(git_repository_open(&repo2, "testrepo")); - - cl_git_pass(git_reference_lookup(&looked_up_ref, repo2, new_head_tracker)); - cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref)); - cl_assert(git_oid_cmp(&id, git_reference_target(resolved_ref)) == 0); - - git_repository_free(repo2); - - git_reference_free(new_reference); - git_reference_free(looked_up_ref); - git_reference_free(resolved_ref); -} - -void test_refs_create__deep_symbolic(void) -{ - // create a deep symbolic reference - git_reference *new_reference, *looked_up_ref, *resolved_ref; - git_oid id; - - const char *new_head_tracker = "deep/rooted/tracker"; - - git_oid_fromstr(&id, current_master_tip); - - cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0)); - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head_tracker)); - cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref)); - cl_assert(git_oid_cmp(&id, git_reference_target(resolved_ref)) == 0); - - git_reference_free(new_reference); - git_reference_free(looked_up_ref); - git_reference_free(resolved_ref); -} - -void test_refs_create__oid(void) -{ - // create a new OID reference - git_reference *new_reference, *looked_up_ref; - git_repository *repo2; - git_oid id; - - const char *new_head = "refs/heads/new-head"; - - git_oid_fromstr(&id, current_master_tip); - - /* Create and write the new object id reference */ - cl_git_pass(git_reference_create(&new_reference, g_repo, new_head, &id, 0)); - - /* Ensure the reference can be looked-up... */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head)); - cl_assert(git_reference_type(looked_up_ref) & GIT_REF_OID); - cl_assert(reference_is_packed(looked_up_ref) == 0); - cl_assert_equal_s(looked_up_ref->name, new_head); - - /* ...and that it points to the current master tip */ - cl_assert(git_oid_cmp(&id, git_reference_target(looked_up_ref)) == 0); - git_reference_free(looked_up_ref); - - /* Similar test with a fresh new repository */ - cl_git_pass(git_repository_open(&repo2, "testrepo")); - - cl_git_pass(git_reference_lookup(&looked_up_ref, repo2, new_head)); - cl_assert(git_oid_cmp(&id, git_reference_target(looked_up_ref)) == 0); - - git_repository_free(repo2); - - git_reference_free(new_reference); - git_reference_free(looked_up_ref); -} - -void test_refs_create__oid_unknown(void) -{ - // Can not create a new OID reference which targets at an unknown id - git_reference *new_reference, *looked_up_ref; - git_oid id; - - const char *new_head = "refs/heads/new-head"; - - git_oid_fromstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644"); - - /* Create and write the new object id reference */ - cl_git_fail(git_reference_create(&new_reference, g_repo, new_head, &id, 0)); - - /* Ensure the reference can't be looked-up... */ - cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, new_head)); -} - -void test_refs_create__propagate_eexists(void) -{ - int error; - git_oid oid; - git_reference *ref; - - /* Make sure it works for oid and for symbolic both */ - git_oid_fromstr(&oid, current_master_tip); - error = git_reference_create(&ref, g_repo, current_head_target, &oid, false); - cl_assert(error == GIT_EEXISTS); - - error = git_reference_symbolic_create(&ref, g_repo, "HEAD", current_head_target, false); - cl_assert(error == GIT_EEXISTS); -} - -void test_refs_create__creating_a_reference_with_an_invalid_name_returns_EINVALIDSPEC(void) -{ - git_reference *new_reference; - git_oid id; - - const char *name = "refs/heads/inv@{id"; - - git_oid_fromstr(&id, current_master_tip); - - cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_create( - &new_reference, g_repo, name, &id, 0)); - - cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_symbolic_create( - &new_reference, g_repo, name, current_head_target, 0)); -} diff --git a/tests-clar/refs/delete.c b/tests-clar/refs/delete.c deleted file mode 100644 index 973768aeb..000000000 --- a/tests-clar/refs/delete.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "clar_libgit2.h" - -#include "fileops.h" -#include "git2/reflog.h" -#include "git2/refdb.h" -#include "reflog.h" -#include "ref_helpers.h" - -static const char *packed_test_head_name = "refs/heads/packed-test"; -static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"; - -static git_repository *g_repo; - - - -void test_refs_delete__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_refs_delete__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - - - -void test_refs_delete__packed_loose(void) -{ - // deleting a ref which is both packed and loose should remove both tracks in the filesystem - git_reference *looked_up_ref, *another_looked_up_ref; - git_buf temp_path = GIT_BUF_INIT; - - /* Ensure the loose reference exists on the file system */ - cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), packed_test_head_name)); - cl_assert(git_path_exists(temp_path.ptr)); - - /* Lookup the reference */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name)); - - /* Ensure it's the loose version that has been found */ - cl_assert(reference_is_packed(looked_up_ref) == 0); - - /* Now that the reference is deleted... */ - cl_git_pass(git_reference_delete(looked_up_ref)); - git_reference_free(looked_up_ref); - - /* Looking up the reference once again should not retrieve it */ - cl_git_fail(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name)); - - /* Ensure the loose reference doesn't exist any longer on the file system */ - cl_assert(!git_path_exists(temp_path.ptr)); - - git_reference_free(another_looked_up_ref); - git_buf_free(&temp_path); -} - -void test_refs_delete__packed_only(void) -{ - // can delete a just packed reference - git_reference *ref; - git_refdb *refdb; - git_oid id; - const char *new_ref = "refs/heads/new_ref"; - - git_oid_fromstr(&id, current_master_tip); - - /* Create and write the new object id reference */ - cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &id, 0)); - git_reference_free(ref); - - /* Lookup the reference */ - cl_git_pass(git_reference_lookup(&ref, g_repo, new_ref)); - - /* Ensure it's a loose reference */ - cl_assert(reference_is_packed(ref) == 0); - - /* Pack all existing references */ - cl_git_pass(git_repository_refdb(&refdb, g_repo)); - cl_git_pass(git_refdb_compress(refdb)); - - /* Reload the reference from disk */ - git_reference_free(ref); - cl_git_pass(git_reference_lookup(&ref, g_repo, new_ref)); - - /* Ensure it's a packed reference */ - cl_assert(reference_is_packed(ref) == 1); - - /* This should pass */ - cl_git_pass(git_reference_delete(ref)); - git_reference_free(ref); - git_refdb_free(refdb); -} diff --git a/tests-clar/refs/foreachglob.c b/tests-clar/refs/foreachglob.c deleted file mode 100644 index 2c458082f..000000000 --- a/tests-clar/refs/foreachglob.c +++ /dev/null @@ -1,95 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" - -static git_repository *repo; -static git_reference *fake_remote; - -void test_refs_foreachglob__initialize(void) -{ - git_oid id; - - cl_fixture_sandbox("testrepo.git"); - cl_git_pass(git_repository_open(&repo, "testrepo.git")); - - cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); - cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0)); -} - -void test_refs_foreachglob__cleanup(void) -{ - git_reference_free(fake_remote); - fake_remote = NULL; - - git_repository_free(repo); - repo = NULL; - - cl_fixture_cleanup("testrepo.git"); -} - -static int count_cb(const char *reference_name, void *payload) -{ - int *count = (int *)payload; - - GIT_UNUSED(reference_name); - - (*count)++; - - return 0; -} - -static void assert_retrieval(const char *glob, int expected_count) -{ - int count = 0; - - cl_git_pass(git_reference_foreach_glob(repo, glob, count_cb, &count)); - - cl_assert_equal_i(expected_count, count); -} - -void test_refs_foreachglob__retrieve_all_refs(void) -{ - /* 12 heads (including one packed head) + 1 note + 2 remotes + 7 tags */ - assert_retrieval("*", 22); -} - -void test_refs_foreachglob__retrieve_remote_branches(void) -{ - assert_retrieval("refs/remotes/*", 2); -} - -void test_refs_foreachglob__retrieve_local_branches(void) -{ - assert_retrieval("refs/heads/*", 12); -} - -void test_refs_foreachglob__retrieve_partially_named_references(void) -{ - /* - * refs/heads/packed-test, refs/heads/test - * refs/remotes/test/master, refs/tags/test - */ - - assert_retrieval("*test*", 4); -} - - -static int interrupt_cb(const char *reference_name, void *payload) -{ - int *count = (int *)payload; - - GIT_UNUSED(reference_name); - - (*count)++; - - return (*count == 11); -} - -void test_refs_foreachglob__can_cancel(void) -{ - int count = 0; - - cl_assert_equal_i(GIT_EUSER, git_reference_foreach_glob( - repo, "*", interrupt_cb, &count) ); - - cl_assert_equal_i(11, count); -} diff --git a/tests-clar/refs/isvalidname.c b/tests-clar/refs/isvalidname.c deleted file mode 100644 index 65c70ba4d..000000000 --- a/tests-clar/refs/isvalidname.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "clar_libgit2.h" - -void test_refs_isvalidname__can_detect_invalid_formats(void) -{ - cl_assert_equal_i(false, git_reference_is_valid_name("refs/tags/0.17.0^{}")); - cl_assert_equal_i(false, git_reference_is_valid_name("TWO/LEVELS")); - cl_assert_equal_i(false, git_reference_is_valid_name("ONE.LEVEL")); - cl_assert_equal_i(false, git_reference_is_valid_name("HEAD/")); - cl_assert_equal_i(false, git_reference_is_valid_name("NO_TRAILING_UNDERSCORE_")); - cl_assert_equal_i(false, git_reference_is_valid_name("_NO_LEADING_UNDERSCORE")); - cl_assert_equal_i(false, git_reference_is_valid_name("HEAD/aa")); - cl_assert_equal_i(false, git_reference_is_valid_name("lower_case")); - cl_assert_equal_i(false, git_reference_is_valid_name("/stupid/name/master")); - cl_assert_equal_i(false, git_reference_is_valid_name("/")); - cl_assert_equal_i(false, git_reference_is_valid_name("//")); - cl_assert_equal_i(false, git_reference_is_valid_name("")); - cl_assert_equal_i(false, git_reference_is_valid_name("refs/heads/sub.lock/webmatrix")); -} - -void test_refs_isvalidname__wont_hopefully_choke_on_valid_formats(void) -{ - cl_assert_equal_i(true, git_reference_is_valid_name("refs/tags/0.17.0")); - cl_assert_equal_i(true, git_reference_is_valid_name("refs/LEVELS")); - cl_assert_equal_i(true, git_reference_is_valid_name("HEAD")); - cl_assert_equal_i(true, git_reference_is_valid_name("ONE_LEVEL")); - cl_assert_equal_i(true, git_reference_is_valid_name("refs/stash")); - cl_assert_equal_i(true, git_reference_is_valid_name("refs/remotes/origin/bim_with_3d@11296")); - cl_assert_equal_i(true, git_reference_is_valid_name("refs/master{yesterday")); - cl_assert_equal_i(true, git_reference_is_valid_name("refs/master}yesterday")); - cl_assert_equal_i(true, git_reference_is_valid_name("refs/master{yesterday}")); -} diff --git a/tests-clar/refs/iterator.c b/tests-clar/refs/iterator.c deleted file mode 100644 index 266410fdf..000000000 --- a/tests-clar/refs/iterator.c +++ /dev/null @@ -1,97 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" -#include "vector.h" - -static git_repository *repo; - -void test_refs_iterator__initialize(void) -{ - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); -} - -void test_refs_iterator__cleanup(void) -{ - git_repository_free(repo); -} - -static const char *refnames[] = { - "refs/heads/br2", - "refs/heads/cannot-fetch", - "refs/heads/chomped", - "refs/heads/haacked", - "refs/heads/master", - "refs/heads/not-good", - "refs/heads/packed", - "refs/heads/packed-test", - "refs/heads/subtrees", - "refs/heads/test", - "refs/heads/track-local", - "refs/heads/trailing", - "refs/notes/fanout", - "refs/remotes/test/master", - "refs/tags/annotated_tag_to_blob", - "refs/tags/e90810b", - "refs/tags/hard_tag", - "refs/tags/point_to_blob", - "refs/tags/taggerless", - "refs/tags/test", - "refs/tags/wrapped_tag", -}; - -static int refcmp_cb(const void *a, const void *b) -{ - const git_reference *refa = (const git_reference *)a; - const git_reference *refb = (const git_reference *)b; - - return strcmp(refa->name, refb->name); -} - -void test_refs_iterator__list(void) -{ - git_reference_iterator *iter; - git_vector output; - git_reference *ref; - int error; - size_t i; - - cl_git_pass(git_vector_init(&output, 32, &refcmp_cb)); - cl_git_pass(git_reference_iterator_new(&iter, repo)); - - do { - error = git_reference_next(&ref, iter); - cl_assert(error == 0 || error == GIT_ITEROVER); - if (error != GIT_ITEROVER) { - cl_git_pass(git_vector_insert(&output, ref)); - } - } while (!error); - - git_reference_iterator_free(iter); - cl_assert_equal_sz(output.length, ARRAY_SIZE(refnames)); - - git_vector_sort(&output); - - git_vector_foreach(&output, i, ref) { - cl_assert_equal_s(ref->name, refnames[i]); - git_reference_free(ref); - } - - git_vector_free(&output); -} - -void test_refs_iterator__empty(void) -{ - git_reference_iterator *iter; - git_odb *odb; - git_reference *ref; - git_repository *empty; - - cl_git_pass(git_odb_new(&odb)); - cl_git_pass(git_repository_wrap_odb(&empty, odb)); - - cl_git_pass(git_reference_iterator_new(&iter, empty)); - cl_assert_equal_i(GIT_ITEROVER, git_reference_next(&ref, iter)); - - git_reference_iterator_free(iter); - git_odb_free(odb); - git_repository_free(empty); -} diff --git a/tests-clar/refs/list.c b/tests-clar/refs/list.c deleted file mode 100644 index de5c0fd3d..000000000 --- a/tests-clar/refs/list.c +++ /dev/null @@ -1,57 +0,0 @@ -#include "clar_libgit2.h" - -#include "repository.h" -#include "git2/reflog.h" -#include "reflog.h" - -static git_repository *g_repo; - - - -void test_refs_list__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_refs_list__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - - - -void test_refs_list__all(void) -{ - // try to list all the references in our test repo - git_strarray ref_list; - - cl_git_pass(git_reference_list(&ref_list, g_repo)); - - /*{ - unsigned short i; - for (i = 0; i < ref_list.count; ++i) - printf("# %s\n", ref_list.strings[i]); - }*/ - - /* 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, 14); - - git_strarray_free(&ref_list); -} - -void test_refs_list__do_not_retrieve_references_which_name_end_with_a_lock_extension(void) -{ - git_strarray ref_list; - - /* Create a fake locked reference */ - cl_git_mkfile( - "./testrepo/.git/refs/heads/hanwen.lock", - "144344043ba4d4a405da03de3844aa829ae8be0e\n"); - - cl_git_pass(git_reference_list(&ref_list, g_repo)); - cl_assert_equal_i((int)ref_list.count, 14); - - git_strarray_free(&ref_list); -} diff --git a/tests-clar/refs/listall.c b/tests-clar/refs/listall.c deleted file mode 100644 index c696fbb2e..000000000 --- a/tests-clar/refs/listall.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" - -static git_repository *repo; -static git_strarray ref_list; - -static void ensure_no_refname_starts_with_a_forward_slash(const char *path) -{ - size_t i; - - cl_git_pass(git_repository_open(&repo, path)); - cl_git_pass(git_reference_list(&ref_list, repo)); - - cl_assert(ref_list.count > 0); - - for (i = 0; i < ref_list.count; i++) - cl_assert(git__prefixcmp(ref_list.strings[i], "/") != 0); - - git_strarray_free(&ref_list); - git_repository_free(repo); -} - -void test_refs_listall__from_repository_opened_through_workdir_path(void) -{ - cl_fixture_sandbox("status"); - cl_git_pass(p_rename("status/.gitted", "status/.git")); - - ensure_no_refname_starts_with_a_forward_slash("status"); - - cl_fixture_cleanup("status"); -} - -void test_refs_listall__from_repository_opened_through_gitdir_path(void) -{ - ensure_no_refname_starts_with_a_forward_slash(cl_fixture("testrepo.git")); -} - -void test_refs_listall__from_repository_with_no_trailing_newline(void) -{ - cl_git_pass(git_repository_open(&repo, cl_fixture("bad_tag.git"))); - cl_git_pass(git_reference_list(&ref_list, repo)); - - cl_assert(ref_list.count > 0); - - git_strarray_free(&ref_list); - git_repository_free(repo); -} diff --git a/tests-clar/refs/lookup.c b/tests-clar/refs/lookup.c deleted file mode 100644 index 2e31cf0f6..000000000 --- a/tests-clar/refs/lookup.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" - -static git_repository *g_repo; - -void test_refs_lookup__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); -} - -void test_refs_lookup__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_refs_lookup__with_resolve(void) -{ - git_reference *a, *b, *temp; - - cl_git_pass(git_reference_lookup(&temp, g_repo, "HEAD")); - cl_git_pass(git_reference_resolve(&a, temp)); - git_reference_free(temp); - - cl_git_pass(git_reference_lookup_resolved(&b, g_repo, "HEAD", 5)); - cl_assert(git_reference_cmp(a, b) == 0); - git_reference_free(b); - - cl_git_pass(git_reference_lookup_resolved(&b, g_repo, "HEAD_TRACKER", 5)); - cl_assert(git_reference_cmp(a, b) == 0); - git_reference_free(b); - - git_reference_free(a); -} - -void test_refs_lookup__invalid_name(void) -{ - git_oid oid; - cl_git_fail(git_reference_name_to_id(&oid, g_repo, "/refs/tags/point_to_blob")); -} - -void test_refs_lookup__oid(void) -{ - git_oid tag, expected; - - cl_git_pass(git_reference_name_to_id(&tag, g_repo, "refs/tags/point_to_blob")); - cl_git_pass(git_oid_fromstr(&expected, "1385f264afb75a56a5bec74243be9b367ba4ca08")); - cl_assert(git_oid_cmp(&tag, &expected) == 0); -} - -void test_refs_lookup__namespace(void) -{ - int error; - git_reference *ref; - - error = git_reference_lookup(&ref, g_repo, "refs/heads"); - cl_assert_equal_i(error, GIT_ENOTFOUND); - - error = git_reference_lookup(&ref, g_repo, "refs/heads/"); - cl_assert_equal_i(error, GIT_EINVALIDSPEC); -} diff --git a/tests-clar/refs/normalize.c b/tests-clar/refs/normalize.c deleted file mode 100644 index 7f313ef38..000000000 --- a/tests-clar/refs/normalize.c +++ /dev/null @@ -1,403 +0,0 @@ -#include "clar_libgit2.h" - -#include "repository.h" -#include "git2/reflog.h" -#include "reflog.h" - -// Helpers -static void ensure_refname_normalized( - unsigned int flags, - const char *input_refname, - const char *expected_refname) -{ - char buffer_out[GIT_REFNAME_MAX]; - - cl_git_pass(git_reference_normalize_name(buffer_out, sizeof(buffer_out), input_refname, flags)); - - cl_assert_equal_s(expected_refname, buffer_out); -} - -static void ensure_refname_invalid(unsigned int flags, const char *input_refname) -{ - char buffer_out[GIT_REFNAME_MAX]; - - cl_assert_equal_i( - GIT_EINVALIDSPEC, - git_reference_normalize_name(buffer_out, sizeof(buffer_out), input_refname, flags)); -} - -void test_refs_normalize__can_normalize_a_direct_reference_name(void) -{ - ensure_refname_normalized( - GIT_REF_FORMAT_NORMAL, "refs/dummy/a", "refs/dummy/a"); - ensure_refname_normalized( - GIT_REF_FORMAT_NORMAL, "refs/stash", "refs/stash"); - ensure_refname_normalized( - GIT_REF_FORMAT_NORMAL, "refs/tags/a", "refs/tags/a"); - ensure_refname_normalized( - GIT_REF_FORMAT_NORMAL, "refs/heads/a/b", "refs/heads/a/b"); - ensure_refname_normalized( - GIT_REF_FORMAT_NORMAL, "refs/heads/a./b", "refs/heads/a./b"); - ensure_refname_normalized( - GIT_REF_FORMAT_NORMAL, "refs/heads/v@ation", "refs/heads/v@ation"); - ensure_refname_normalized( - GIT_REF_FORMAT_NORMAL, "refs///heads///a", "refs/heads/a"); -} - -void test_refs_normalize__cannot_normalize_any_direct_reference_name(void) -{ - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "a"); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "/a"); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "//a"); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, ""); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "/refs/heads/a/"); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "refs/heads/a/"); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "refs/heads/a."); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "refs/heads/a.lock"); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "refs/heads/foo?bar"); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "refs/heads\foo"); - ensure_refname_normalized( - GIT_REF_FORMAT_NORMAL, "refs/heads/v@ation", "refs/heads/v@ation"); - ensure_refname_normalized( - GIT_REF_FORMAT_NORMAL, "refs///heads///a", "refs/heads/a"); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "refs/heads/.a/b"); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "refs/heads/foo/../bar"); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "refs/heads/foo..bar"); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "refs/heads/./foo"); - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "refs/heads/v@{ation"); -} - -void test_refs_normalize__symbolic(void) -{ - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, ""); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "heads\foo"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "/"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "///"); - - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "ALL_CAPS_AND_UNDERSCORES", "ALL_CAPS_AND_UNDERSCORES"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/MixedCasing", "refs/MixedCasing"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs///heads///a", "refs/heads/a"); - - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "HEAD", "HEAD"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "MERGE_HEAD", "MERGE_HEAD"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "FETCH_HEAD", "FETCH_HEAD"); -} - -/* Ported from JGit, BSD licence. - * See https://github.com/spearce/JGit/commit/e4bf8f6957bbb29362575d641d1e77a02d906739 - * - * Copyright (C) 2009, Google Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Git Development Community nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -void test_refs_normalize__jgit_suite(void) -{ - // tests borrowed from JGit - -/* EmptyString */ - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, ""); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "/"); - -/* MustHaveTwoComponents */ - ensure_refname_invalid( - GIT_REF_FORMAT_NORMAL, "master"); - ensure_refname_normalized( - GIT_REF_FORMAT_NORMAL, "heads/master", "heads/master"); - -/* ValidHead */ - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master", "refs/heads/master"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/pu", "refs/heads/pu"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/z", "refs/heads/z"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/FoO", "refs/heads/FoO"); - -/* ValidTag */ - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/tags/v1.0", "refs/tags/v1.0"); - -/* NoLockSuffix */ - ensure_refname_invalid(GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master.lock"); - -/* NoDirectorySuffix */ - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master/"); - -/* NoSpace */ - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/i haz space"); - -/* NoAsciiControlCharacters */ - { - char c; - char buffer[GIT_REFNAME_MAX]; - for (c = '\1'; c < ' '; c++) { - strncpy(buffer, "refs/heads/mast", 15); - strncpy(buffer + 15, (const char *)&c, 1); - strncpy(buffer + 16, "er", 2); - buffer[18 - 1] = '\0'; - ensure_refname_invalid(GIT_REF_FORMAT_ALLOW_ONELEVEL, buffer); - } - } - -/* NoBareDot */ - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/."); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/.."); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/./master"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/../master"); - -/* NoLeadingOrTrailingDot */ - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "."); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/.bar"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/..bar"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/bar."); - -/* ContainsDot */ - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/m.a.s.t.e.r", "refs/heads/m.a.s.t.e.r"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master..pu"); - -/* NoMagicRefCharacters */ - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master^"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/^master"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "^refs/heads/master"); - - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master~"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/~master"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "~refs/heads/master"); - - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master:"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/:master"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, ":refs/heads/master"); - -/* ShellGlob */ - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master?"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/?master"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "?refs/heads/master"); - - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master["); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/[master"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "[refs/heads/master"); - - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master*"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/*master"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "*refs/heads/master"); - -/* ValidSpecialCharacters */ - ensure_refname_normalized - (GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/!", "refs/heads/!"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/\"", "refs/heads/\""); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/#", "refs/heads/#"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/$", "refs/heads/$"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/%", "refs/heads/%"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/&", "refs/heads/&"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/'", "refs/heads/'"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/(", "refs/heads/("); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/)", "refs/heads/)"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/+", "refs/heads/+"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/,", "refs/heads/,"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/-", "refs/heads/-"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/;", "refs/heads/;"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/<", "refs/heads/<"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/=", "refs/heads/="); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/>", "refs/heads/>"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/@", "refs/heads/@"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/]", "refs/heads/]"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/_", "refs/heads/_"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/`", "refs/heads/`"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/{", "refs/heads/{"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/|", "refs/heads/|"); - ensure_refname_normalized( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/}", "refs/heads/}"); - - // This is valid on UNIX, but not on Windows - // hence we make in invalid due to non-portability - // - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/\\"); - -/* UnicodeNames */ - /* - * Currently this fails. - * ensure_refname_normalized(GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/\u00e5ngstr\u00f6m", "refs/heads/\u00e5ngstr\u00f6m"); - */ - -/* RefLogQueryIsValidRef */ - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master@{1}"); - ensure_refname_invalid( - GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master@{1.hour.ago}"); -} - -void test_refs_normalize__buffer_has_to_be_big_enough_to_hold_the_normalized_version(void) -{ - char buffer_out[21]; - - cl_git_pass(git_reference_normalize_name( - buffer_out, 21, "refs//heads///long///name", GIT_REF_FORMAT_NORMAL)); - cl_git_fail(git_reference_normalize_name( - buffer_out, 20, "refs//heads///long///name", GIT_REF_FORMAT_NORMAL)); -} - -#define ONE_LEVEL_AND_REFSPEC \ - GIT_REF_FORMAT_ALLOW_ONELEVEL \ - | GIT_REF_FORMAT_REFSPEC_PATTERN - -void test_refs_normalize__refspec_pattern(void) -{ - ensure_refname_invalid( - GIT_REF_FORMAT_REFSPEC_PATTERN, "heads/*foo/bar"); - ensure_refname_invalid( - GIT_REF_FORMAT_REFSPEC_PATTERN, "heads/foo*/bar"); - ensure_refname_invalid( - GIT_REF_FORMAT_REFSPEC_PATTERN, "heads/f*o/bar"); - - ensure_refname_invalid( - GIT_REF_FORMAT_REFSPEC_PATTERN, "foo"); - ensure_refname_normalized( - ONE_LEVEL_AND_REFSPEC, "FOO", "FOO"); - - ensure_refname_normalized( - GIT_REF_FORMAT_REFSPEC_PATTERN, "foo/bar", "foo/bar"); - ensure_refname_normalized( - ONE_LEVEL_AND_REFSPEC, "foo/bar", "foo/bar"); - - ensure_refname_normalized( - GIT_REF_FORMAT_REFSPEC_PATTERN, "*/foo", "*/foo"); - ensure_refname_normalized( - ONE_LEVEL_AND_REFSPEC, "*/foo", "*/foo"); - - ensure_refname_normalized( - GIT_REF_FORMAT_REFSPEC_PATTERN, "foo/*/bar", "foo/*/bar"); - ensure_refname_normalized( - ONE_LEVEL_AND_REFSPEC, "foo/*/bar", "foo/*/bar"); - - ensure_refname_invalid( - GIT_REF_FORMAT_REFSPEC_PATTERN, "*"); - ensure_refname_normalized( - ONE_LEVEL_AND_REFSPEC, "*", "*"); - - ensure_refname_invalid( - GIT_REF_FORMAT_REFSPEC_PATTERN, "foo/*/*"); - ensure_refname_invalid( - ONE_LEVEL_AND_REFSPEC, "foo/*/*"); - - ensure_refname_invalid( - GIT_REF_FORMAT_REFSPEC_PATTERN, "*/foo/*"); - ensure_refname_invalid( - ONE_LEVEL_AND_REFSPEC, "*/foo/*"); - - ensure_refname_invalid( - GIT_REF_FORMAT_REFSPEC_PATTERN, "*/*/foo"); - ensure_refname_invalid( - ONE_LEVEL_AND_REFSPEC, "*/*/foo"); -} diff --git a/tests-clar/refs/overwrite.c b/tests-clar/refs/overwrite.c deleted file mode 100644 index ebe72069c..000000000 --- a/tests-clar/refs/overwrite.c +++ /dev/null @@ -1,136 +0,0 @@ -#include "clar_libgit2.h" - -#include "repository.h" -#include "git2/reflog.h" -#include "reflog.h" - -static const char *ref_name = "refs/heads/other"; -static const char *ref_master_name = "refs/heads/master"; -static const char *ref_branch_name = "refs/heads/branch"; -static const char *ref_test_name = "refs/heads/test"; - -static git_repository *g_repo; - -void test_refs_overwrite__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_refs_overwrite__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_refs_overwrite__symbolic(void) -{ - // Overwrite an existing symbolic reference - git_reference *ref, *branch_ref; - - /* The target needds to exist and we need to check the name has changed */ - cl_git_pass(git_reference_symbolic_create(&branch_ref, g_repo, ref_branch_name, ref_master_name, 0)); - cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_branch_name, 0)); - git_reference_free(ref); - - /* Ensure it points to the right place*/ - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); - cl_assert(git_reference_type(ref) & GIT_REF_SYMBOLIC); - cl_assert_equal_s(git_reference_symbolic_target(ref), ref_branch_name); - git_reference_free(ref); - - /* Ensure we can't create it unless we force it to */ - cl_git_fail(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0)); - cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 1)); - git_reference_free(ref); - - /* Ensure it points to the right place */ - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); - cl_assert(git_reference_type(ref) & GIT_REF_SYMBOLIC); - cl_assert_equal_s(git_reference_symbolic_target(ref), ref_master_name); - - git_reference_free(ref); - git_reference_free(branch_ref); -} - -void test_refs_overwrite__object_id(void) -{ - // Overwrite an existing object id reference - git_reference *ref; - git_oid id; - - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); - cl_assert(git_reference_type(ref) & GIT_REF_OID); - git_oid_cpy(&id, git_reference_target(ref)); - git_reference_free(ref); - - /* Create it */ - cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 0)); - git_reference_free(ref); - - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_test_name)); - cl_assert(git_reference_type(ref) & GIT_REF_OID); - git_oid_cpy(&id, git_reference_target(ref)); - git_reference_free(ref); - - /* Ensure we can't overwrite unless we force it */ - cl_git_fail(git_reference_create(&ref, g_repo, ref_name, &id, 0)); - cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 1)); - git_reference_free(ref); - - /* Ensure it has been overwritten */ - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); - cl_assert(!git_oid_cmp(&id, git_reference_target(ref))); - - git_reference_free(ref); -} - -void test_refs_overwrite__object_id_with_symbolic(void) -{ - // Overwrite an existing object id reference with a symbolic one - git_reference *ref; - git_oid id; - - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); - cl_assert(git_reference_type(ref) & GIT_REF_OID); - git_oid_cpy(&id, git_reference_target(ref)); - git_reference_free(ref); - - cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 0)); - git_reference_free(ref); - cl_git_fail(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0)); - cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 1)); - git_reference_free(ref); - - /* Ensure it points to the right place */ - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); - cl_assert(git_reference_type(ref) & GIT_REF_SYMBOLIC); - cl_assert_equal_s(git_reference_symbolic_target(ref), ref_master_name); - - git_reference_free(ref); -} - -void test_refs_overwrite__symbolic_with_object_id(void) -{ - // Overwrite an existing symbolic reference with an object id one - git_reference *ref; - git_oid id; - - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); - cl_assert(git_reference_type(ref) & GIT_REF_OID); - git_oid_cpy(&id, git_reference_target(ref)); - git_reference_free(ref); - - /* Create the symbolic ref */ - cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0)); - git_reference_free(ref); - /* It shouldn't overwrite unless we tell it to */ - cl_git_fail(git_reference_create(&ref, g_repo, ref_name, &id, 0)); - cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 1)); - git_reference_free(ref); - - /* Ensure it points to the right place */ - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); - cl_assert(git_reference_type(ref) & GIT_REF_OID); - cl_assert(!git_oid_cmp(git_reference_target(ref), &id)); - - git_reference_free(ref); -} diff --git a/tests-clar/refs/pack.c b/tests-clar/refs/pack.c deleted file mode 100644 index 849a052aa..000000000 --- a/tests-clar/refs/pack.c +++ /dev/null @@ -1,105 +0,0 @@ -#include "clar_libgit2.h" - -#include "fileops.h" -#include "git2/reflog.h" -#include "git2/refdb.h" -#include "reflog.h" -#include "refs.h" -#include "ref_helpers.h" - -static const char *loose_tag_ref_name = "refs/tags/e90810b"; - -static git_repository *g_repo; - -void test_refs_pack__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_refs_pack__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -static void packall(void) -{ - git_refdb *refdb; - - cl_git_pass(git_repository_refdb(&refdb, g_repo)); - cl_git_pass(git_refdb_compress(refdb)); - git_refdb_free(refdb); -} - -void test_refs_pack__empty(void) -{ - /* create a packfile for an empty folder */ - git_buf temp_path = GIT_BUF_INIT; - - cl_git_pass(git_buf_join_n(&temp_path, '/', 3, git_repository_path(g_repo), GIT_REFS_HEADS_DIR, "empty_dir")); - cl_git_pass(git_futils_mkdir_r(temp_path.ptr, NULL, GIT_REFS_DIR_MODE)); - git_buf_free(&temp_path); - - packall(); -} - -void test_refs_pack__loose(void) -{ - /* create a packfile from all the loose refs in a repo */ - git_reference *reference; - git_buf temp_path = GIT_BUF_INIT; - - /* Ensure a known loose ref can be looked up */ - cl_git_pass(git_reference_lookup(&reference, g_repo, loose_tag_ref_name)); - cl_assert(reference_is_packed(reference) == 0); - cl_assert_equal_s(reference->name, loose_tag_ref_name); - git_reference_free(reference); - - /* - * We are now trying to pack also a loose reference - * called `points_to_blob`, to make sure we can properly - * pack weak tags - */ - packall(); - - /* Ensure the packed-refs file exists */ - cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), GIT_PACKEDREFS_FILE)); - cl_assert(git_path_exists(temp_path.ptr)); - - /* Ensure the known ref can still be looked up but is now packed */ - cl_git_pass(git_reference_lookup(&reference, g_repo, loose_tag_ref_name)); - cl_assert(reference_is_packed(reference)); - cl_assert_equal_s(reference->name, loose_tag_ref_name); - - /* Ensure the known ref has been removed from the loose folder structure */ - cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), loose_tag_ref_name)); - cl_assert(!git_path_exists(temp_path.ptr)); - - git_reference_free(reference); - git_buf_free(&temp_path); -} - -void test_refs_pack__symbolic(void) -{ - /* create a packfile from loose refs skipping symbolic refs */ - int i; - git_oid head; - git_reference *ref; - char name[128]; - - cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); - - /* make a bunch of references */ - - for (i = 0; i < 100; ++i) { - snprintf(name, sizeof(name), "refs/heads/symbolic-%03d", i); - cl_git_pass(git_reference_symbolic_create( - &ref, g_repo, name, "refs/heads/master", 0)); - git_reference_free(ref); - - snprintf(name, sizeof(name), "refs/heads/direct-%03d", i); - cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0)); - git_reference_free(ref); - } - - packall(); -} diff --git a/tests-clar/refs/peel.c b/tests-clar/refs/peel.c deleted file mode 100644 index f2fb6e259..000000000 --- a/tests-clar/refs/peel.c +++ /dev/null @@ -1,119 +0,0 @@ -#include "clar_libgit2.h" - -static git_repository *g_repo; -static git_repository *g_peel_repo; - -void test_refs_peel__initialize(void) -{ - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_repository_open(&g_peel_repo, cl_fixture("peeled.git"))); -} - -void test_refs_peel__cleanup(void) -{ - git_repository_free(g_repo); - g_repo = NULL; - git_repository_free(g_peel_repo); - g_peel_repo = NULL; -} - -static void assert_peel_generic( - git_repository *repo, - const char *ref_name, - git_otype requested_type, - const char* expected_sha, - git_otype expected_type) -{ - git_oid expected_oid; - git_reference *ref; - git_object *peeled; - - cl_git_pass(git_reference_lookup(&ref, repo, ref_name)); - - cl_git_pass(git_reference_peel(&peeled, ref, requested_type)); - - cl_git_pass(git_oid_fromstr(&expected_oid, expected_sha)); - cl_assert_equal_i(0, git_oid_cmp(&expected_oid, git_object_id(peeled))); - - cl_assert_equal_i(expected_type, git_object_type(peeled)); - - git_object_free(peeled); - git_reference_free(ref); -} - -static void assert_peel( - const char *ref_name, - git_otype requested_type, - const char* expected_sha, - git_otype expected_type) -{ - assert_peel_generic(g_repo, ref_name, requested_type, - expected_sha, expected_type); -} - -static void assert_peel_error(int error, const char *ref_name, git_otype requested_type) -{ - git_reference *ref; - git_object *peeled; - - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); - - cl_assert_equal_i(error, git_reference_peel(&peeled, ref, requested_type)); - - git_reference_free(ref); -} - -void test_refs_peel__can_peel_a_tag(void) -{ - assert_peel("refs/tags/test", GIT_OBJ_TAG, - "b25fa35b38051e4ae45d4222e795f9df2e43f1d1", GIT_OBJ_TAG); - assert_peel("refs/tags/test", GIT_OBJ_COMMIT, - "e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_COMMIT); - assert_peel("refs/tags/test", GIT_OBJ_TREE, - "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE); - assert_peel("refs/tags/point_to_blob", GIT_OBJ_BLOB, - "1385f264afb75a56a5bec74243be9b367ba4ca08", GIT_OBJ_BLOB); -} - -void test_refs_peel__can_peel_a_branch(void) -{ - assert_peel("refs/heads/master", GIT_OBJ_COMMIT, - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", GIT_OBJ_COMMIT); - assert_peel("refs/heads/master", GIT_OBJ_TREE, - "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162", GIT_OBJ_TREE); -} - -void test_refs_peel__can_peel_a_symbolic_reference(void) -{ - assert_peel("HEAD", GIT_OBJ_COMMIT, - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", GIT_OBJ_COMMIT); - assert_peel("HEAD", GIT_OBJ_TREE, - "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162", GIT_OBJ_TREE); -} - -void test_refs_peel__cannot_peel_into_a_non_existing_target(void) -{ - assert_peel_error(GIT_ENOTFOUND, "refs/tags/point_to_blob", GIT_OBJ_TAG); -} - -void test_refs_peel__can_peel_into_any_non_tag_object(void) -{ - assert_peel("refs/heads/master", GIT_OBJ_ANY, - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", GIT_OBJ_COMMIT); - assert_peel("refs/tags/point_to_blob", GIT_OBJ_ANY, - "1385f264afb75a56a5bec74243be9b367ba4ca08", GIT_OBJ_BLOB); - assert_peel("refs/tags/test", GIT_OBJ_ANY, - "e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_COMMIT); -} - -void test_refs_peel__can_peel_fully_peeled_packed_refs(void) -{ - assert_peel_generic(g_peel_repo, - "refs/tags/tag-inside-tags", GIT_OBJ_ANY, - "0df1a5865c8abfc09f1f2182e6a31be550e99f07", - GIT_OBJ_COMMIT); - assert_peel_generic(g_peel_repo, - "refs/foo/tag-outside-tags", GIT_OBJ_ANY, - "0df1a5865c8abfc09f1f2182e6a31be550e99f07", - GIT_OBJ_COMMIT); -} diff --git a/tests-clar/refs/read.c b/tests-clar/refs/read.c deleted file mode 100644 index 35cf17e9e..000000000 --- a/tests-clar/refs/read.c +++ /dev/null @@ -1,284 +0,0 @@ -#include "clar_libgit2.h" - -#include "repository.h" -#include "git2/reflog.h" -#include "reflog.h" -#include "ref_helpers.h" - -static const char *loose_tag_ref_name = "refs/tags/e90810b"; -static const char *non_existing_tag_ref_name = "refs/tags/i-do-not-exist"; -static const char *head_tracker_sym_ref_name = "HEAD_TRACKER"; -static const char *current_head_target = "refs/heads/master"; -static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"; -static const char *packed_head_name = "refs/heads/packed"; -static const char *packed_test_head_name = "refs/heads/packed-test"; - -static git_repository *g_repo; - -void test_refs_read__initialize(void) -{ - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); -} - -void test_refs_read__cleanup(void) -{ - git_repository_free(g_repo); - g_repo = NULL; -} - -void test_refs_read__loose_tag(void) -{ - // lookup a loose tag reference - git_reference *reference; - git_object *object; - git_buf ref_name_from_tag_name = GIT_BUF_INIT; - - cl_git_pass(git_reference_lookup(&reference, g_repo, loose_tag_ref_name)); - cl_assert(git_reference_type(reference) & GIT_REF_OID); - cl_assert(reference_is_packed(reference) == 0); - cl_assert_equal_s(reference->name, loose_tag_ref_name); - - cl_git_pass(git_object_lookup(&object, g_repo, git_reference_target(reference), GIT_OBJ_ANY)); - cl_assert(object != NULL); - cl_assert(git_object_type(object) == GIT_OBJ_TAG); - - /* Ensure the name of the tag matches the name of the reference */ - cl_git_pass(git_buf_joinpath(&ref_name_from_tag_name, GIT_REFS_TAGS_DIR, git_tag_name((git_tag *)object))); - cl_assert_equal_s(ref_name_from_tag_name.ptr, loose_tag_ref_name); - git_buf_free(&ref_name_from_tag_name); - - git_object_free(object); - - git_reference_free(reference); -} - -void test_refs_read__nonexisting_tag(void) -{ - // lookup a loose tag reference that doesn't exist - git_reference *reference; - - cl_git_fail(git_reference_lookup(&reference, g_repo, non_existing_tag_ref_name)); - - git_reference_free(reference); -} - - -void test_refs_read__symbolic(void) -{ - // lookup a symbolic reference - git_reference *reference, *resolved_ref; - git_object *object; - git_oid id; - - cl_git_pass(git_reference_lookup(&reference, g_repo, GIT_HEAD_FILE)); - cl_assert(git_reference_type(reference) & GIT_REF_SYMBOLIC); - cl_assert(reference_is_packed(reference) == 0); - cl_assert_equal_s(reference->name, GIT_HEAD_FILE); - - cl_git_pass(git_reference_resolve(&resolved_ref, reference)); - cl_assert(git_reference_type(resolved_ref) == GIT_REF_OID); - - cl_git_pass(git_object_lookup(&object, g_repo, git_reference_target(resolved_ref), GIT_OBJ_ANY)); - cl_assert(object != NULL); - cl_assert(git_object_type(object) == GIT_OBJ_COMMIT); - - git_oid_fromstr(&id, current_master_tip); - cl_assert(git_oid_cmp(&id, git_object_id(object)) == 0); - - git_object_free(object); - - git_reference_free(reference); - git_reference_free(resolved_ref); -} - -void test_refs_read__nested_symbolic(void) -{ - // lookup a nested symbolic reference - git_reference *reference, *resolved_ref; - git_object *object; - git_oid id; - - cl_git_pass(git_reference_lookup(&reference, g_repo, head_tracker_sym_ref_name)); - cl_assert(git_reference_type(reference) & GIT_REF_SYMBOLIC); - cl_assert(reference_is_packed(reference) == 0); - cl_assert_equal_s(reference->name, head_tracker_sym_ref_name); - - cl_git_pass(git_reference_resolve(&resolved_ref, reference)); - cl_assert(git_reference_type(resolved_ref) == GIT_REF_OID); - - cl_git_pass(git_object_lookup(&object, g_repo, git_reference_target(resolved_ref), GIT_OBJ_ANY)); - cl_assert(object != NULL); - cl_assert(git_object_type(object) == GIT_OBJ_COMMIT); - - git_oid_fromstr(&id, current_master_tip); - cl_assert(git_oid_cmp(&id, git_object_id(object)) == 0); - - git_object_free(object); - - git_reference_free(reference); - git_reference_free(resolved_ref); -} - -void test_refs_read__head_then_master(void) -{ - // lookup the HEAD and resolve the master branch - git_reference *reference, *resolved_ref, *comp_base_ref; - - cl_git_pass(git_reference_lookup(&reference, g_repo, head_tracker_sym_ref_name)); - cl_git_pass(git_reference_resolve(&comp_base_ref, reference)); - git_reference_free(reference); - - cl_git_pass(git_reference_lookup(&reference, g_repo, GIT_HEAD_FILE)); - cl_git_pass(git_reference_resolve(&resolved_ref, reference)); - cl_git_pass(git_oid_cmp(git_reference_target(comp_base_ref), git_reference_target(resolved_ref))); - git_reference_free(reference); - git_reference_free(resolved_ref); - - cl_git_pass(git_reference_lookup(&reference, g_repo, current_head_target)); - cl_git_pass(git_reference_resolve(&resolved_ref, reference)); - cl_git_pass(git_oid_cmp(git_reference_target(comp_base_ref), git_reference_target(resolved_ref))); - git_reference_free(reference); - git_reference_free(resolved_ref); - - git_reference_free(comp_base_ref); -} - -void test_refs_read__master_then_head(void) -{ - // lookup the master branch and then the HEAD - git_reference *reference, *master_ref, *resolved_ref; - - cl_git_pass(git_reference_lookup(&master_ref, g_repo, current_head_target)); - cl_git_pass(git_reference_lookup(&reference, g_repo, GIT_HEAD_FILE)); - - cl_git_pass(git_reference_resolve(&resolved_ref, reference)); - cl_git_pass(git_oid_cmp(git_reference_target(master_ref), git_reference_target(resolved_ref))); - - git_reference_free(reference); - git_reference_free(resolved_ref); - git_reference_free(master_ref); -} - - -void test_refs_read__packed(void) -{ - // lookup a packed reference - git_reference *reference; - git_object *object; - - cl_git_pass(git_reference_lookup(&reference, g_repo, packed_head_name)); - cl_assert(git_reference_type(reference) & GIT_REF_OID); - cl_assert(reference_is_packed(reference)); - cl_assert_equal_s(reference->name, packed_head_name); - - cl_git_pass(git_object_lookup(&object, g_repo, git_reference_target(reference), GIT_OBJ_ANY)); - cl_assert(object != NULL); - cl_assert(git_object_type(object) == GIT_OBJ_COMMIT); - - git_object_free(object); - - git_reference_free(reference); -} - -void test_refs_read__loose_first(void) -{ - // assure that a loose reference is looked up before a packed reference - git_reference *reference; - - cl_git_pass(git_reference_lookup(&reference, g_repo, packed_head_name)); - git_reference_free(reference); - cl_git_pass(git_reference_lookup(&reference, g_repo, packed_test_head_name)); - cl_assert(git_reference_type(reference) & GIT_REF_OID); - cl_assert(reference_is_packed(reference) == 0); - cl_assert_equal_s(reference->name, packed_test_head_name); - - git_reference_free(reference); -} - -void test_refs_read__chomped(void) -{ - git_reference *test, *chomped; - - cl_git_pass(git_reference_lookup(&test, g_repo, "refs/heads/test")); - cl_git_pass(git_reference_lookup(&chomped, g_repo, "refs/heads/chomped")); - cl_git_pass(git_oid_cmp(git_reference_target(test), git_reference_target(chomped))); - - git_reference_free(test); - git_reference_free(chomped); -} - -void test_refs_read__trailing(void) -{ - git_reference *test, *trailing; - - cl_git_pass(git_reference_lookup(&test, g_repo, "refs/heads/test")); - cl_git_pass(git_reference_lookup(&trailing, g_repo, "refs/heads/trailing")); - cl_git_pass(git_oid_cmp(git_reference_target(test), git_reference_target(trailing))); - git_reference_free(trailing); - cl_git_pass(git_reference_lookup(&trailing, g_repo, "FETCH_HEAD")); - - git_reference_free(test); - git_reference_free(trailing); -} - -void test_refs_read__unfound_return_ENOTFOUND(void) -{ - git_reference *reference; - git_oid id; - - cl_assert_equal_i(GIT_ENOTFOUND, - git_reference_lookup(&reference, g_repo, "TEST_MASTER")); - cl_assert_equal_i(GIT_ENOTFOUND, - git_reference_lookup(&reference, g_repo, "refs/test/master")); - cl_assert_equal_i(GIT_ENOTFOUND, - git_reference_lookup(&reference, g_repo, "refs/tags/test/master")); - cl_assert_equal_i(GIT_ENOTFOUND, - git_reference_lookup(&reference, g_repo, "refs/tags/test/farther/master")); - - cl_assert_equal_i(GIT_ENOTFOUND, - git_reference_name_to_id(&id, g_repo, "refs/tags/test/farther/master")); -} - -static void assert_is_branch(const char *name, bool expected_branchness) -{ - git_reference *reference; - cl_git_pass(git_reference_lookup(&reference, g_repo, name)); - cl_assert_equal_i(expected_branchness, git_reference_is_branch(reference)); - git_reference_free(reference); -} - -void test_refs_read__can_determine_if_a_reference_is_a_local_branch(void) -{ - assert_is_branch("refs/heads/master", true); - assert_is_branch("refs/heads/packed", true); - assert_is_branch("refs/remotes/test/master", false); - assert_is_branch("refs/tags/e90810b", false); -} - -static void assert_is_tag(const char *name, bool expected_tagness) -{ - git_reference *reference; - cl_git_pass(git_reference_lookup(&reference, g_repo, name)); - cl_assert_equal_i(expected_tagness, git_reference_is_tag(reference)); - git_reference_free(reference); -} - -void test_refs_read__can_determine_if_a_reference_is_a_tag(void) -{ - assert_is_tag("refs/tags/e90810b", true); - assert_is_tag("refs/tags/test", true); - assert_is_tag("refs/heads/packed", false); - assert_is_tag("refs/remotes/test/master", false); -} - -void test_refs_read__invalid_name_returns_EINVALIDSPEC(void) -{ - git_reference *reference; - git_oid id; - - cl_assert_equal_i(GIT_EINVALIDSPEC, - git_reference_lookup(&reference, g_repo, "refs/heads/Inv@{id")); - - cl_assert_equal_i(GIT_EINVALIDSPEC, - git_reference_name_to_id(&id, g_repo, "refs/heads/Inv@{id")); -} diff --git a/tests-clar/refs/ref_helpers.c b/tests-clar/refs/ref_helpers.c deleted file mode 100644 index 7676e65a7..000000000 --- a/tests-clar/refs/ref_helpers.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "git2/repository.h" -#include "git2/refs.h" -#include "common.h" -#include "util.h" -#include "buffer.h" -#include "path.h" - -int reference_is_packed(git_reference *ref) -{ - git_buf ref_path = GIT_BUF_INIT; - int packed; - - assert(ref); - - if (git_buf_joinpath(&ref_path, - git_repository_path(git_reference_owner(ref)), - git_reference_name(ref)) < 0) - return -1; - - packed = !git_path_isfile(ref_path.ptr); - - git_buf_free(&ref_path); - - return packed; -} diff --git a/tests-clar/refs/ref_helpers.h b/tests-clar/refs/ref_helpers.h deleted file mode 100644 index 0ef55bfce..000000000 --- a/tests-clar/refs/ref_helpers.h +++ /dev/null @@ -1 +0,0 @@ -int reference_is_packed(git_reference *ref); diff --git a/tests-clar/refs/reflog/drop.c b/tests-clar/refs/reflog/drop.c deleted file mode 100644 index 916bd9933..000000000 --- a/tests-clar/refs/reflog/drop.c +++ /dev/null @@ -1,115 +0,0 @@ -#include "clar_libgit2.h" - -#include "reflog.h" - -static git_repository *g_repo; -static git_reflog *g_reflog; -static size_t entrycount; - -void test_refs_reflog_drop__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); - - git_reflog_read(&g_reflog, g_repo, "HEAD"); - entrycount = git_reflog_entrycount(g_reflog); -} - -void test_refs_reflog_drop__cleanup(void) -{ - git_reflog_free(g_reflog); - g_reflog = NULL; - - cl_git_sandbox_cleanup(); -} - -void test_refs_reflog_drop__dropping_a_non_exisiting_entry_from_the_log_returns_ENOTFOUND(void) -{ - cl_assert_equal_i(GIT_ENOTFOUND, git_reflog_drop(g_reflog, entrycount, 0)); - - cl_assert_equal_sz(entrycount, git_reflog_entrycount(g_reflog)); -} - -void test_refs_reflog_drop__can_drop_an_entry(void) -{ - cl_assert(entrycount > 4); - - cl_git_pass(git_reflog_drop(g_reflog, 2, 0)); - cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); -} - -void test_refs_reflog_drop__can_drop_an_entry_and_rewrite_the_log_history(void) -{ - const git_reflog_entry *before_current; - const git_reflog_entry *after_current; - git_oid before_current_old_oid, before_current_cur_oid; - - cl_assert(entrycount > 4); - - before_current = git_reflog_entry_byindex(g_reflog, 1); - - git_oid_cpy(&before_current_old_oid, &before_current->oid_old); - git_oid_cpy(&before_current_cur_oid, &before_current->oid_cur); - - cl_git_pass(git_reflog_drop(g_reflog, 1, 1)); - - cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); - - after_current = git_reflog_entry_byindex(g_reflog, 0); - - cl_assert_equal_i(0, git_oid_cmp(&before_current_old_oid, &after_current->oid_old)); - cl_assert(0 != git_oid_cmp(&before_current_cur_oid, &after_current->oid_cur)); -} - -void test_refs_reflog_drop__can_drop_the_oldest_entry(void) -{ - const git_reflog_entry *entry; - - cl_assert(entrycount > 2); - - cl_git_pass(git_reflog_drop(g_reflog, entrycount - 1, 0)); - cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); - - entry = git_reflog_entry_byindex(g_reflog, entrycount - 2); - cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) != 0); -} - -void test_refs_reflog_drop__can_drop_the_oldest_entry_and_rewrite_the_log_history(void) -{ - const git_reflog_entry *entry; - - cl_assert(entrycount > 2); - - cl_git_pass(git_reflog_drop(g_reflog, entrycount - 1, 1)); - cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); - - entry = git_reflog_entry_byindex(g_reflog, entrycount - 2); - cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) == 0); -} - -void test_refs_reflog_drop__can_drop_all_the_entries(void) -{ - cl_assert(--entrycount > 0); - - do { - cl_git_pass(git_reflog_drop(g_reflog, 0, 1)); - } while (--entrycount > 0); - - cl_git_pass(git_reflog_drop(g_reflog, 0, 1)); - - cl_assert_equal_i(0, (int)git_reflog_entrycount(g_reflog)); -} - -void test_refs_reflog_drop__can_persist_deletion_on_disk(void) -{ - cl_assert(entrycount > 2); - - cl_git_pass(git_reflog_drop(g_reflog, 0, 1)); - cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); - cl_git_pass(git_reflog_write(g_reflog)); - - git_reflog_free(g_reflog); - - git_reflog_read(&g_reflog, g_repo, "HEAD"); - - cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); -} diff --git a/tests-clar/refs/reflog/reflog.c b/tests-clar/refs/reflog/reflog.c deleted file mode 100644 index bcd224270..000000000 --- a/tests-clar/refs/reflog/reflog.c +++ /dev/null @@ -1,209 +0,0 @@ -#include "clar_libgit2.h" - -#include "fileops.h" -#include "git2/reflog.h" -#include "reflog.h" - - -static const char *new_ref = "refs/heads/test-reflog"; -static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"; -#define commit_msg "commit: bla bla" - -static git_repository *g_repo; - - -// helpers -static void assert_signature(const git_signature *expected, const git_signature *actual) -{ - cl_assert(actual); - cl_assert_equal_s(expected->name, actual->name); - cl_assert_equal_s(expected->email, actual->email); - cl_assert(expected->when.offset == actual->when.offset); - cl_assert(expected->when.time == actual->when.time); -} - - -// Fixture setup and teardown -void test_refs_reflog_reflog__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); -} - -void test_refs_reflog_reflog__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -static void assert_appends(const git_signature *committer, const git_oid *oid) -{ - git_repository *repo2; - git_reference *lookedup_ref; - git_reflog *reflog; - const git_reflog_entry *entry; - - /* Reopen a new instance of the repository */ - cl_git_pass(git_repository_open(&repo2, "testrepo.git")); - - /* Lookup the previously created branch */ - cl_git_pass(git_reference_lookup(&lookedup_ref, repo2, new_ref)); - - /* Read and parse the reflog for this branch */ - cl_git_pass(git_reflog_read(&reflog, repo2, new_ref)); - cl_assert_equal_i(2, (int)git_reflog_entrycount(reflog)); - - entry = git_reflog_entry_byindex(reflog, 1); - assert_signature(committer, entry->committer); - cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) == 0); - cl_assert(git_oid_cmp(oid, &entry->oid_cur) == 0); - cl_assert(entry->msg == NULL); - - entry = git_reflog_entry_byindex(reflog, 0); - assert_signature(committer, entry->committer); - cl_assert(git_oid_cmp(oid, &entry->oid_old) == 0); - cl_assert(git_oid_cmp(oid, &entry->oid_cur) == 0); - cl_assert_equal_s(commit_msg, entry->msg); - - git_reflog_free(reflog); - git_repository_free(repo2); - - git_reference_free(lookedup_ref); -} - -void test_refs_reflog_reflog__append_then_read(void) -{ - /* write a reflog for a given reference and ensure it can be read back */ - git_reference *ref; - git_oid oid; - git_signature *committer; - git_reflog *reflog; - - /* Create a new branch pointing at the HEAD */ - git_oid_fromstr(&oid, current_master_tip); - cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &oid, 0)); - git_reference_free(ref); - - cl_git_pass(git_signature_now(&committer, "foo", "foo@bar")); - - cl_git_pass(git_reflog_read(&reflog, g_repo, new_ref)); - - cl_git_fail(git_reflog_append(reflog, &oid, committer, "no inner\nnewline")); - cl_git_pass(git_reflog_append(reflog, &oid, committer, NULL)); - cl_git_pass(git_reflog_append(reflog, &oid, committer, commit_msg "\n")); - cl_git_pass(git_reflog_write(reflog)); - git_reflog_free(reflog); - - assert_appends(committer, &oid); - - git_signature_free(committer); -} - -void test_refs_reflog_reflog__append_to_then_read(void) -{ - /* write a reflog for a given reference and ensure it can be read back */ - git_reference *ref; - git_oid oid; - git_signature *committer; - - /* Create a new branch pointing at the HEAD */ - git_oid_fromstr(&oid, current_master_tip); - cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &oid, 0)); - git_reference_free(ref); - - cl_git_pass(git_signature_now(&committer, "foo", "foo@bar")); - - cl_git_fail(git_reflog_append_to(g_repo, new_ref, &oid, committer, "no inner\nnewline")); - cl_git_pass(git_reflog_append_to(g_repo, new_ref, &oid, committer, NULL)); - cl_git_pass(git_reflog_append_to(g_repo, new_ref, &oid, committer, commit_msg "\n")); - - assert_appends(committer, &oid); - - git_signature_free(committer); -} - -void test_refs_reflog_reflog__renaming_the_reference_moves_the_reflog(void) -{ - git_reference *master, *new_master; - git_buf master_log_path = GIT_BUF_INIT, moved_log_path = GIT_BUF_INIT; - - git_buf_joinpath(&master_log_path, git_repository_path(g_repo), GIT_REFLOG_DIR); - git_buf_puts(&moved_log_path, git_buf_cstr(&master_log_path)); - git_buf_joinpath(&master_log_path, git_buf_cstr(&master_log_path), "refs/heads/master"); - git_buf_joinpath(&moved_log_path, git_buf_cstr(&moved_log_path), "refs/moved"); - - cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&master_log_path))); - cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&moved_log_path))); - - cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master")); - cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0)); - git_reference_free(master); - - cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&master_log_path))); - cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&moved_log_path))); - - git_reference_free(new_master); - git_buf_free(&moved_log_path); - git_buf_free(&master_log_path); -} - -static void assert_has_reflog(bool expected_result, const char *name) -{ - git_reference *ref; - - cl_git_pass(git_reference_lookup(&ref, g_repo, name)); - - cl_assert_equal_i(expected_result, git_reference_has_log(ref)); - - git_reference_free(ref); -} - -void test_refs_reflog_reflog__reference_has_reflog(void) -{ - assert_has_reflog(true, "HEAD"); - assert_has_reflog(true, "refs/heads/master"); - assert_has_reflog(false, "refs/heads/subtrees"); -} - -void test_refs_reflog_reflog__reading_the_reflog_from_a_reference_with_no_log_returns_an_empty_one(void) -{ - git_reflog *reflog; - const char *refname = "refs/heads/subtrees"; - git_buf subtrees_log_path = GIT_BUF_INIT; - - git_buf_join_n(&subtrees_log_path, '/', 3, git_repository_path(g_repo), GIT_REFLOG_DIR, refname); - cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&subtrees_log_path))); - - cl_git_pass(git_reflog_read(&reflog, g_repo, refname)); - - cl_assert_equal_i(0, (int)git_reflog_entrycount(reflog)); - - git_reflog_free(reflog); - git_buf_free(&subtrees_log_path); -} - -void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void) -{ - git_reference *master, *new_master; - git_buf master_log_path = GIT_BUF_INIT, moved_log_path = GIT_BUF_INIT; - git_reflog *reflog; - - cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master")); - cl_git_pass(git_reflog_read(&reflog, g_repo, "refs/heads/master")); - - cl_git_pass(git_reflog_write(reflog)); - - cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0)); - git_reference_free(master); - - cl_git_fail(git_reflog_write(reflog)); - - git_reflog_free(reflog); - git_reference_free(new_master); - git_buf_free(&moved_log_path); - git_buf_free(&master_log_path); -} - -void test_refs_reflog_reflog__renaming_with_an_invalid_name_returns_EINVALIDSPEC(void) -{ - cl_assert_equal_i(GIT_EINVALIDSPEC, - git_reflog_rename(g_repo, "refs/heads/master", "refs/heads/Inv@{id")); -} diff --git a/tests-clar/refs/rename.c b/tests-clar/refs/rename.c deleted file mode 100644 index 543bc4d62..000000000 --- a/tests-clar/refs/rename.c +++ /dev/null @@ -1,367 +0,0 @@ -#include "clar_libgit2.h" - -#include "fileops.h" -#include "git2/reflog.h" -#include "reflog.h" -#include "refs.h" -#include "ref_helpers.h" - -static const char *loose_tag_ref_name = "refs/tags/e90810b"; -static const char *packed_head_name = "refs/heads/packed"; -static const char *packed_test_head_name = "refs/heads/packed-test"; -static const char *ref_one_name = "refs/heads/one/branch"; -static const char *ref_one_name_new = "refs/heads/two/branch"; -static const char *ref_two_name = "refs/heads/two"; -static const char *ref_master_name = "refs/heads/master"; -static const char *ref_two_name_new = "refs/heads/two/two"; - -static git_repository *g_repo; - - - -void test_refs_rename__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_refs_rename__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - - - -void test_refs_rename__loose(void) -{ - // rename a loose reference - git_reference *looked_up_ref, *new_ref, *another_looked_up_ref; - git_buf temp_path = GIT_BUF_INIT; - const char *new_name = "refs/tags/Nemo/knows/refs.kung-fu"; - - /* Ensure the ref doesn't exist on the file system */ - cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), new_name)); - cl_assert(!git_path_exists(temp_path.ptr)); - - /* Retrieval of the reference to rename */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, loose_tag_ref_name)); - - /* ... which is indeed loose */ - cl_assert(reference_is_packed(looked_up_ref) == 0); - - /* Now that the reference is renamed... */ - cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, new_name, 0)); - cl_assert_equal_s(new_ref->name, new_name); - git_reference_free(looked_up_ref); - - /* ...It can't be looked-up with the old name... */ - cl_git_fail(git_reference_lookup(&another_looked_up_ref, g_repo, loose_tag_ref_name)); - - /* ...but the new name works ok... */ - cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, new_name)); - cl_assert_equal_s(new_ref->name, new_name); - - /* .. the new ref is loose... */ - cl_assert(reference_is_packed(another_looked_up_ref) == 0); - cl_assert(reference_is_packed(new_ref) == 0); - - /* ...and the ref can be found in the file system */ - cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), new_name)); - cl_assert(git_path_exists(temp_path.ptr)); - - git_reference_free(new_ref); - git_reference_free(another_looked_up_ref); - git_buf_free(&temp_path); -} - -void test_refs_rename__packed(void) -{ - // rename a packed reference (should make it loose) - git_reference *looked_up_ref, *new_ref, *another_looked_up_ref; - git_buf temp_path = GIT_BUF_INIT; - const char *brand_new_name = "refs/heads/brand_new_name"; - - /* Ensure the ref doesn't exist on the file system */ - cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), packed_head_name)); - cl_assert(!git_path_exists(temp_path.ptr)); - - /* The reference can however be looked-up... */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name)); - - /* .. and it's packed */ - cl_assert(reference_is_packed(looked_up_ref) != 0); - - /* Now that the reference is renamed... */ - cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, brand_new_name, 0)); - cl_assert_equal_s(new_ref->name, brand_new_name); - git_reference_free(looked_up_ref); - - /* ...It can't be looked-up with the old name... */ - cl_git_fail(git_reference_lookup(&another_looked_up_ref, g_repo, packed_head_name)); - - /* ...but the new name works ok... */ - cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, brand_new_name)); - cl_assert_equal_s(another_looked_up_ref->name, brand_new_name); - - /* .. the ref is no longer packed... */ - cl_assert(reference_is_packed(another_looked_up_ref) == 0); - cl_assert(reference_is_packed(new_ref) == 0); - - /* ...and the ref now happily lives in the file system */ - cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), brand_new_name)); - cl_assert(git_path_exists(temp_path.ptr)); - - git_reference_free(new_ref); - git_reference_free(another_looked_up_ref); - git_buf_free(&temp_path); -} - -void test_refs_rename__packed_doesnt_pack_others(void) -{ - // renaming a packed reference does not pack another reference which happens to be in both loose and pack state - git_reference *looked_up_ref, *another_looked_up_ref, *renamed_ref; - git_buf temp_path = GIT_BUF_INIT; - const char *brand_new_name = "refs/heads/brand_new_name"; - - /* Ensure the other reference exists on the file system */ - cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), packed_test_head_name)); - cl_assert(git_path_exists(temp_path.ptr)); - - /* Lookup the other reference */ - cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name)); - - /* Ensure it's loose */ - cl_assert(reference_is_packed(another_looked_up_ref) == 0); - git_reference_free(another_looked_up_ref); - - /* Lookup the reference to rename */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name)); - - /* Ensure it's packed */ - cl_assert(reference_is_packed(looked_up_ref) != 0); - - /* Now that the reference is renamed... */ - cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, brand_new_name, 0)); - git_reference_free(looked_up_ref); - - /* Lookup the other reference */ - cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name)); - - /* Ensure it's loose */ - cl_assert(reference_is_packed(another_looked_up_ref) == 0); - - /* Ensure the other ref still exists on the file system */ - cl_assert(git_path_exists(temp_path.ptr)); - - git_reference_free(renamed_ref); - git_reference_free(another_looked_up_ref); - git_buf_free(&temp_path); -} - -void test_refs_rename__name_collision(void) -{ - // can not rename a reference with the name of an existing reference - git_reference *looked_up_ref, *renamed_ref; - - /* An existing reference... */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name)); - - /* Can not be renamed to the name of another existing reference. */ - cl_git_fail(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 0)); - git_reference_free(looked_up_ref); - - /* Failure to rename it hasn't corrupted its state */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name)); - cl_assert_equal_s(looked_up_ref->name, packed_head_name); - - git_reference_free(looked_up_ref); -} - -void test_refs_rename__invalid_name(void) -{ - // can not rename a reference with an invalid name - git_reference *looked_up_ref, *renamed_ref; - - /* An existing oid reference... */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name)); - - /* Can not be renamed with an invalid name. */ - cl_assert_equal_i( - GIT_EINVALIDSPEC, - git_reference_rename(&renamed_ref, looked_up_ref, "Hello! I'm a very invalid name.", 0)); - - /* Can not be renamed outside of the refs hierarchy - * unless it's ALL_CAPS_AND_UNDERSCORES. - */ - cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_rename(&renamed_ref, looked_up_ref, "i-will-sudo-you", 0)); - - /* Failure to rename it hasn't corrupted its state */ - git_reference_free(looked_up_ref); - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name)); - cl_assert_equal_s(looked_up_ref->name, packed_test_head_name); - - git_reference_free(looked_up_ref); -} - -void test_refs_rename__force_loose_packed(void) -{ - // can force-rename a packed reference with the name of an existing loose and packed reference - git_reference *looked_up_ref, *renamed_ref; - git_oid oid; - - /* An existing reference... */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name)); - git_oid_cpy(&oid, git_reference_target(looked_up_ref)); - - /* Can be force-renamed to the name of another existing reference. */ - cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 1)); - git_reference_free(looked_up_ref); - git_reference_free(renamed_ref); - - /* Check we actually renamed it */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name)); - cl_assert_equal_s(looked_up_ref->name, packed_test_head_name); - cl_assert(!git_oid_cmp(&oid, git_reference_target(looked_up_ref))); - git_reference_free(looked_up_ref); - - /* And that the previous one doesn't exist any longer */ - cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name)); -} - -void test_refs_rename__force_loose(void) -{ - // can force-rename a loose reference with the name of an existing loose reference - git_reference *looked_up_ref, *renamed_ref; - git_oid oid; - - /* An existing reference... */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/br2")); - git_oid_cpy(&oid, git_reference_target(looked_up_ref)); - - /* Can be force-renamed to the name of another existing reference. */ - cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, "refs/heads/test", 1)); - git_reference_free(looked_up_ref); - git_reference_free(renamed_ref); - - /* Check we actually renamed it */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/test")); - cl_assert_equal_s(looked_up_ref->name, "refs/heads/test"); - cl_assert(!git_oid_cmp(&oid, git_reference_target(looked_up_ref))); - git_reference_free(looked_up_ref); - - /* And that the previous one doesn't exist any longer */ - cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/br2")); - - git_reference_free(looked_up_ref); -} - - -void test_refs_rename__overwrite(void) -{ - // can not overwrite name of existing reference - git_reference *ref, *ref_one, *ref_one_new, *ref_two; - git_refdb *refdb; - git_oid id; - - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); - cl_assert(git_reference_type(ref) & GIT_REF_OID); - - git_oid_cpy(&id, git_reference_target(ref)); - - /* Create loose references */ - cl_git_pass(git_reference_create(&ref_one, g_repo, ref_one_name, &id, 0)); - cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name, &id, 0)); - - /* Pack everything */ - cl_git_pass(git_repository_refdb(&refdb, g_repo)); - cl_git_pass(git_refdb_compress(refdb)); - - /* Attempt to create illegal reference */ - cl_git_fail(git_reference_create(&ref_one_new, g_repo, ref_one_name_new, &id, 0)); - - /* Illegal reference couldn't be created so this is supposed to fail */ - cl_git_fail(git_reference_lookup(&ref_one_new, g_repo, ref_one_name_new)); - - git_reference_free(ref); - git_reference_free(ref_one); - git_reference_free(ref_one_new); - git_reference_free(ref_two); - git_refdb_free(refdb); -} - - -void test_refs_rename__prefix(void) -{ - // can be renamed to a new name prefixed with the old name - git_reference *ref, *ref_two, *looked_up_ref, *renamed_ref; - git_oid id; - - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); - cl_assert(git_reference_type(ref) & GIT_REF_OID); - - git_oid_cpy(&id, git_reference_target(ref)); - - /* Create loose references */ - cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name, &id, 0)); - - /* An existing reference... */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name)); - - /* Can be rename to a new name starting with the old name. */ - cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name_new, 0)); - git_reference_free(looked_up_ref); - git_reference_free(renamed_ref); - - /* Check we actually renamed it */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new)); - cl_assert_equal_s(looked_up_ref->name, ref_two_name_new); - git_reference_free(looked_up_ref); - cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name)); - - git_reference_free(ref); - git_reference_free(ref_two); - git_reference_free(looked_up_ref); -} - -void test_refs_rename__move_up(void) -{ - // can move a reference to a upper reference hierarchy - git_reference *ref, *ref_two, *looked_up_ref, *renamed_ref; - git_oid id; - - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); - cl_assert(git_reference_type(ref) & GIT_REF_OID); - - git_oid_cpy(&id, git_reference_target(ref)); - - /* Create loose references */ - cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name_new, &id, 0)); - git_reference_free(ref_two); - - /* An existing reference... */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new)); - - /* Can be renamed upward the reference tree. */ - cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name, 0)); - git_reference_free(looked_up_ref); - git_reference_free(renamed_ref); - - /* Check we actually renamed it */ - cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name)); - cl_assert_equal_s(looked_up_ref->name, ref_two_name); - git_reference_free(looked_up_ref); - - cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new)); - git_reference_free(ref); - git_reference_free(looked_up_ref); -} - -void test_refs_rename__propagate_eexists(void) -{ - git_reference *ref, *new_ref; - - cl_git_pass(git_reference_lookup(&ref, g_repo, packed_head_name)); - - cl_assert_equal_i(GIT_EEXISTS, git_reference_rename(&new_ref, ref, packed_test_head_name, 0)); - - git_reference_free(ref); -} diff --git a/tests-clar/refs/revparse.c b/tests-clar/refs/revparse.c deleted file mode 100644 index 37d3981bb..000000000 --- a/tests-clar/refs/revparse.c +++ /dev/null @@ -1,813 +0,0 @@ -#include "clar_libgit2.h" - -#include "git2/revparse.h" -#include "buffer.h" -#include "refs.h" -#include "path.h" - -static git_repository *g_repo; -static git_object *g_obj; - -/* Helpers */ -static void test_object_and_ref_inrepo( - const char *spec, - const char *expected_oid, - const char *expected_refname, - git_repository *repo, - bool assert_reference_retrieval) -{ - char objstr[64] = {0}; - git_object *obj = NULL; - git_reference *ref = NULL; - int error; - - error = git_revparse_ext(&obj, &ref, repo, spec); - - if (expected_oid != NULL) { - cl_assert_equal_i(0, error); - git_oid_fmt(objstr, git_object_id(obj)); - cl_assert_equal_s(objstr, expected_oid); - } else - cl_assert_equal_i(GIT_ENOTFOUND, error); - - if (assert_reference_retrieval) { - if (expected_refname == NULL) - cl_assert(NULL == ref); - else - cl_assert_equal_s(expected_refname, git_reference_name(ref)); - } - - git_object_free(obj); - git_reference_free(ref); -} - -static void test_object_inrepo(const char *spec, const char *expected_oid, git_repository *repo) -{ - test_object_and_ref_inrepo(spec, expected_oid, NULL, repo, false); -} - -static void test_id_inrepo( - const char *spec, - const char *expected_left, - const char *expected_right, - git_revparse_mode_t expected_flags, - git_repository *repo) -{ - git_revspec revspec; - int error = git_revparse(&revspec, repo, spec); - - if (expected_left) { - char str[64] = {0}; - cl_assert_equal_i(0, error); - git_oid_fmt(str, git_object_id(revspec.from)); - cl_assert_equal_s(str, expected_left); - git_object_free(revspec.from); - } else { - cl_assert_equal_i(GIT_ENOTFOUND, error); - } - - if (expected_right) { - char str[64] = {0}; - git_oid_fmt(str, git_object_id(revspec.to)); - cl_assert_equal_s(str, expected_right); - git_object_free(revspec.to); - } - - if (expected_flags) - cl_assert_equal_i(expected_flags, revspec.flags); -} - -static void test_object(const char *spec, const char *expected_oid) -{ - test_object_inrepo(spec, expected_oid, g_repo); -} - -static void test_object_and_ref(const char *spec, const char *expected_oid, const char *expected_refname) -{ - test_object_and_ref_inrepo(spec, expected_oid, expected_refname, g_repo, true); -} - -static void test_rangelike(const char *rangelike, - const char *expected_left, - const char *expected_right, - git_revparse_mode_t expected_revparseflags) -{ - char objstr[64] = {0}; - git_revspec revspec; - int error; - - error = git_revparse(&revspec, g_repo, rangelike); - - if (expected_left != NULL) { - cl_assert_equal_i(0, error); - cl_assert_equal_i(revspec.flags, expected_revparseflags); - git_oid_fmt(objstr, git_object_id(revspec.from)); - cl_assert_equal_s(objstr, expected_left); - git_oid_fmt(objstr, git_object_id(revspec.to)); - cl_assert_equal_s(objstr, expected_right); - } else - cl_assert(error != 0); - - git_object_free(revspec.from); - git_object_free(revspec.to); -} - - -static void test_id( - const char *spec, - const char *expected_left, - const char *expected_right, - git_revparse_mode_t expected_flags) -{ - test_id_inrepo(spec, expected_left, expected_right, expected_flags, g_repo); -} - -void test_refs_revparse__initialize(void) -{ - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); -} - -void test_refs_revparse__cleanup(void) -{ - git_repository_free(g_repo); -} - -void test_refs_revparse__nonexistant_object(void) -{ - test_object("this-does-not-exist", NULL); - test_object("this-does-not-exist^1", NULL); - test_object("this-does-not-exist~2", NULL); -} - -static void assert_invalid_single_spec(const char *invalid_spec) -{ - cl_assert_equal_i( - GIT_EINVALIDSPEC, git_revparse_single(&g_obj, g_repo, invalid_spec)); -} - -void test_refs_revparse__invalid_reference_name(void) -{ - assert_invalid_single_spec("this doesn't make sense"); - assert_invalid_single_spec("Inv@{id"); - assert_invalid_single_spec(""); -} - -void test_refs_revparse__shas(void) -{ - test_object("c47800c7266a2be04c571c04d5a6614691ea99bd", "c47800c7266a2be04c571c04d5a6614691ea99bd"); - test_object("c47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd"); -} - -void test_refs_revparse__head(void) -{ - test_object("HEAD", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("HEAD^0", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("HEAD~0", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("master", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); -} - -void test_refs_revparse__full_refs(void) -{ - test_object("refs/heads/master", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("refs/heads/test", "e90810b8df3e80c413d903f631643c716887138d"); - test_object("refs/tags/test", "b25fa35b38051e4ae45d4222e795f9df2e43f1d1"); -} - -void test_refs_revparse__partial_refs(void) -{ - test_object("point_to_blob", "1385f264afb75a56a5bec74243be9b367ba4ca08"); - test_object("packed-test", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045"); - test_object("br2", "a4a7dce85cf63874e984719f4fdd239f5145052f"); -} - -void test_refs_revparse__describe_output(void) -{ - test_object("blah-7-gc47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd"); - test_object("not-good", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); -} - -void test_refs_revparse__nth_parent(void) -{ - assert_invalid_single_spec("be3563a^-1"); - assert_invalid_single_spec("^"); - assert_invalid_single_spec("be3563a^{tree}^"); - assert_invalid_single_spec("point_to_blob^{blob}^"); - assert_invalid_single_spec("this doesn't make sense^1"); - - test_object("be3563a^1", "9fd738e8f7967c078dceed8190330fc8648ee56a"); - test_object("be3563a^", "9fd738e8f7967c078dceed8190330fc8648ee56a"); - test_object("be3563a^2", "c47800c7266a2be04c571c04d5a6614691ea99bd"); - test_object("be3563a^1^1", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045"); - test_object("be3563a^^", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045"); - test_object("be3563a^2^1", "5b5b025afb0b4c913b4c338a42934a3863bf3644"); - test_object("be3563a^0", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - test_object("be3563a^{commit}^", "9fd738e8f7967c078dceed8190330fc8648ee56a"); - - test_object("be3563a^42", NULL); -} - -void test_refs_revparse__not_tag(void) -{ - test_object("point_to_blob^{}", "1385f264afb75a56a5bec74243be9b367ba4ca08"); - test_object("wrapped_tag^{}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("master^{}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("master^{tree}^{}", "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"); - test_object("e90810b^{}", "e90810b8df3e80c413d903f631643c716887138d"); - test_object("tags/e90810b^{}", "e90810b8df3e80c413d903f631643c716887138d"); - test_object("e908^{}", "e90810b8df3e80c413d903f631643c716887138d"); -} - -void test_refs_revparse__to_type(void) -{ - assert_invalid_single_spec("wrapped_tag^{trip}"); - test_object("point_to_blob^{commit}", NULL); - cl_assert_equal_i( - GIT_EAMBIGUOUS, git_revparse_single(&g_obj, g_repo, "wrapped_tag^{blob}")); - - test_object("wrapped_tag^{commit}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("wrapped_tag^{tree}", "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"); - test_object("point_to_blob^{blob}", "1385f264afb75a56a5bec74243be9b367ba4ca08"); - test_object("master^{commit}^{commit}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); -} - -void test_refs_revparse__linear_history(void) -{ - assert_invalid_single_spec("~"); - test_object("foo~bar", NULL); - - assert_invalid_single_spec("master~bar"); - assert_invalid_single_spec("master~-1"); - assert_invalid_single_spec("master~0bar"); - assert_invalid_single_spec("this doesn't make sense~2"); - assert_invalid_single_spec("be3563a^{tree}~"); - assert_invalid_single_spec("point_to_blob^{blob}~"); - - test_object("master~0", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("master~1", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - test_object("master~2", "9fd738e8f7967c078dceed8190330fc8648ee56a"); - test_object("master~1~1", "9fd738e8f7967c078dceed8190330fc8648ee56a"); - test_object("master~~", "9fd738e8f7967c078dceed8190330fc8648ee56a"); -} - -void test_refs_revparse__chaining(void) -{ - assert_invalid_single_spec("master@{0}@{0}"); - assert_invalid_single_spec("@{u}@{-1}"); - assert_invalid_single_spec("@{-1}@{-1}"); - assert_invalid_single_spec("@{-3}@{0}"); - - test_object("master@{0}~1^1", "9fd738e8f7967c078dceed8190330fc8648ee56a"); - test_object("@{u}@{0}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - test_object("@{-1}@{0}", "a4a7dce85cf63874e984719f4fdd239f5145052f"); - test_object("@{-4}@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - test_object("master~1^1", "9fd738e8f7967c078dceed8190330fc8648ee56a"); - test_object("master~1^2", "c47800c7266a2be04c571c04d5a6614691ea99bd"); - test_object("master^1^2~1", "5b5b025afb0b4c913b4c338a42934a3863bf3644"); - test_object("master^^2^", "5b5b025afb0b4c913b4c338a42934a3863bf3644"); - test_object("master^1^1^1^1^1", "8496071c1b46c854b31185ea97743be6a8774479"); - test_object("master^^1^2^1", NULL); -} - -void test_refs_revparse__upstream(void) -{ - assert_invalid_single_spec("e90810b@{u}"); - assert_invalid_single_spec("refs/tags/e90810b@{u}"); - test_object("refs/heads/e90810b@{u}", NULL); - - test_object("master@{upstream}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - test_object("@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - test_object("master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - test_object("heads/master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - test_object("refs/heads/master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); -} - -void test_refs_revparse__ordinal(void) -{ - assert_invalid_single_spec("master@{-2}"); - - /* TODO: make the test below actually fail - * cl_git_fail(git_revparse_single(&g_obj, g_repo, "master@{1a}")); - */ - - test_object("nope@{0}", NULL); - test_object("master@{31415}", NULL); - test_object("@{1000}", NULL); - test_object("@{2}", NULL); - - test_object("@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - - test_object("master@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("master@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - test_object("heads/master@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - test_object("refs/heads/master@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); -} - -void test_refs_revparse__previous_head(void) -{ - assert_invalid_single_spec("@{-xyz}"); - assert_invalid_single_spec("@{-0}"); - assert_invalid_single_spec("@{-1b}"); - - test_object("@{-42}", NULL); - - test_object("@{-2}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("@{-1}", "a4a7dce85cf63874e984719f4fdd239f5145052f"); -} - -static void create_fake_stash_reference_and_reflog(git_repository *repo) -{ - git_reference *master, *new_master; - git_buf log_path = GIT_BUF_INIT; - - git_buf_joinpath(&log_path, git_repository_path(repo), "logs/refs/fakestash"); - - cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&log_path))); - - cl_git_pass(git_reference_lookup(&master, repo, "refs/heads/master")); - cl_git_pass(git_reference_rename(&new_master, master, "refs/fakestash", 0)); - git_reference_free(master); - - cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&log_path))); - - git_buf_free(&log_path); - git_reference_free(new_master); -} - -void test_refs_revparse__reflog_of_a_ref_under_refs(void) -{ - git_repository *repo = cl_git_sandbox_init("testrepo.git"); - - test_object_inrepo("refs/fakestash", NULL, repo); - - create_fake_stash_reference_and_reflog(repo); - - /* - * $ git reflog -1 refs/fakestash - * a65fedf refs/fakestash@{0}: commit: checking in - * - * $ git reflog -1 refs/fakestash@{0} - * a65fedf refs/fakestash@{0}: commit: checking in - * - * $ git reflog -1 fakestash - * a65fedf fakestash@{0}: commit: checking in - * - * $ git reflog -1 fakestash@{0} - * a65fedf fakestash@{0}: commit: checking in - */ - test_object_inrepo("refs/fakestash", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); - test_object_inrepo("refs/fakestash@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); - test_object_inrepo("fakestash", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); - test_object_inrepo("fakestash@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); - - cl_git_sandbox_cleanup(); -} - -void test_refs_revparse__revwalk(void) -{ - test_object("master^{/not found in any commit}", NULL); - test_object("master^{/merge}", NULL); - assert_invalid_single_spec("master^{/((}"); - - test_object("master^{/anoth}", "5b5b025afb0b4c913b4c338a42934a3863bf3644"); - test_object("master^{/Merge}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - test_object("br2^{/Merge}", "a4a7dce85cf63874e984719f4fdd239f5145052f"); - test_object("master^{/fo.rth}", "9fd738e8f7967c078dceed8190330fc8648ee56a"); -} - -void test_refs_revparse__date(void) -{ - /* - * $ git reflog HEAD --date=iso - * a65fedf HEAD@{2012-04-30 08:23:41 -0900}: checkout: moving from br2 to master - * a4a7dce HEAD@{2012-04-30 08:23:37 -0900}: commit: checking in - * c47800c HEAD@{2012-04-30 08:23:28 -0900}: checkout: moving from master to br2 - * a65fedf HEAD@{2012-04-30 08:23:23 -0900}: commit: - * be3563a HEAD@{2012-04-30 10:22:43 -0700}: clone: from /Users/ben/src/libgit2/tes - * - * $ git reflog HEAD --date=raw - * a65fedf HEAD@{1335806621 -0900}: checkout: moving from br2 to master - * a4a7dce HEAD@{1335806617 -0900}: commit: checking in - * c47800c HEAD@{1335806608 -0900}: checkout: moving from master to br2 - * a65fedf HEAD@{1335806603 -0900}: commit: - * be3563a HEAD@{1335806563 -0700}: clone: from /Users/ben/src/libgit2/tests/resour - */ - test_object("HEAD@{10 years ago}", NULL); - - test_object("HEAD@{1 second}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("HEAD@{1 second ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("HEAD@{2 days ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - - /* - * $ git reflog master --date=iso - * a65fedf master@{2012-04-30 09:23:23 -0800}: commit: checking in - * be3563a master@{2012-04-30 09:22:43 -0800}: clone: from /Users/ben/src... - * - * $ git reflog master --date=raw - * a65fedf master@{1335806603 -0800}: commit: checking in - * be3563a master@{1335806563 -0800}: clone: from /Users/ben/src/libgit2/tests/reso - */ - - - /* - * $ git reflog -1 "master@{2012-04-30 17:22:42 +0000}" - * warning: Log for 'master' only goes back to Mon, 30 Apr 2012 09:22:43 -0800. - */ - test_object("master@{2012-04-30 17:22:42 +0000}", NULL); - test_object("master@{2012-04-30 09:22:42 -0800}", NULL); - - /* - * $ git reflog -1 "master@{2012-04-30 17:22:43 +0000}" - * be3563a master@{Mon Apr 30 09:22:43 2012 -0800}: clone: from /Users/ben/src/libg - */ - test_object("master@{2012-04-30 17:22:43 +0000}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - test_object("master@{2012-04-30 09:22:43 -0800}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); - - /* - * $ git reflog -1 "master@{2012-4-30 09:23:27 -0800}" - * a65fedf master@{Mon Apr 30 09:23:23 2012 -0800}: commit: checking in - */ - test_object("master@{2012-4-30 09:23:27 -0800}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - - /* - * $ git reflog -1 master@{2012-05-03} - * a65fedf master@{Mon Apr 30 09:23:23 2012 -0800}: commit: checking in - */ - test_object("master@{2012-05-03}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - - /* - * $ git reflog -1 "master@{1335806603}" - * a65fedf - * - * $ git reflog -1 "master@{1335806602}" - * be3563a - */ - test_object("master@{1335806603}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); - test_object("master@{1335806602}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); -} - -void test_refs_revparse__colon(void) -{ - assert_invalid_single_spec(":/"); - assert_invalid_single_spec("point_to_blob:readme.txt"); - cl_git_fail(git_revparse_single(&g_obj, g_repo, ":2:README")); /* Not implemented */ - - test_object(":/not found in any commit", NULL); - test_object("subtrees:ab/42.txt", NULL); - test_object("subtrees:ab/4.txt/nope", NULL); - test_object("subtrees:nope", NULL); - test_object("test/master^1:branch_file.txt", NULL); - - /* From tags */ - test_object("test:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf"); - test_object("tags/test:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf"); - test_object("e90810b:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf"); - test_object("tags/e90810b:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf"); - - /* From commits */ - test_object("a65f:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc"); - - /* From trees */ - test_object("a65f^{tree}:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc"); - test_object("944c:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc"); - - /* Retrieving trees */ - test_object("master:", "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"); - test_object("subtrees:", "ae90f12eea699729ed24555e40b9fd669da12a12"); - test_object("subtrees:ab", "f1425cef211cc08caa31e7b545ffb232acb098c3"); - test_object("subtrees:ab/", "f1425cef211cc08caa31e7b545ffb232acb098c3"); - - /* Retrieving blobs */ - test_object("subtrees:ab/4.txt", "d6c93164c249c8000205dd4ec5cbca1b516d487f"); - test_object("subtrees:ab/de/fgh/1.txt", "1f67fc4386b2d171e0d21be1c447e12660561f9b"); - test_object("master:README", "a8233120f6ad708f843d861ce2b7228ec4e3dec6"); - test_object("master:new.txt", "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd"); - test_object(":/Merge", "a4a7dce85cf63874e984719f4fdd239f5145052f"); - test_object(":/one", "c47800c7266a2be04c571c04d5a6614691ea99bd"); - test_object(":/packed commit t", "41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9"); - test_object("test/master^2:branch_file.txt", "45b983be36b73c0788dc9cbcb76cbb80fc7bb057"); - test_object("test/master@{1}:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc"); -} - -void test_refs_revparse__disambiguation(void) -{ - /* - * $ git show e90810b - * tag e90810b - * Tagger: Vicent Marti - * Date: Thu Aug 12 03:59:17 2010 +0200 - * - * This is a very simple tag. - * - * commit e90810b8df3e80c413d903f631643c716887138d - * Author: Vicent Marti - * Date: Thu Aug 5 18:42:20 2010 +0200 - * - * Test commit 2 - * - * diff --git a/readme.txt b/readme.txt - * index 6336846..0266163 100644 - * --- a/readme.txt - * +++ b/readme.txt - * @@ -1 +1,2 @@ - * Testing a readme.txt - * +Now we add a single line here - * - * $ git show-ref e90810b - * 7b4384978d2493e851f9cca7858815fac9b10980 refs/tags/e90810b - * - */ - test_object("e90810b", "7b4384978d2493e851f9cca7858815fac9b10980"); - - /* - * $ git show e90810 - * commit e90810b8df3e80c413d903f631643c716887138d - * Author: Vicent Marti - * Date: Thu Aug 5 18:42:20 2010 +0200 - * - * Test commit 2 - * - * diff --git a/readme.txt b/readme.txt - * index 6336846..0266163 100644 - * --- a/readme.txt - * +++ b/readme.txt - * @@ -1 +1,2 @@ - * Testing a readme.txt - * +Now we add a single line here - */ - test_object("e90810", "e90810b8df3e80c413d903f631643c716887138d"); -} - -void test_refs_revparse__a_too_short_objectid_returns_EAMBIGUOUS(void) -{ - cl_assert_equal_i( - GIT_EAMBIGUOUS, git_revparse_single(&g_obj, g_repo, "e90")); -} - -/* - * $ echo "aabqhq" | git hash-object -t blob --stdin - * dea509d0b3cb8ee0650f6ca210bc83f4678851ba - * - * $ echo "aaazvc" | git hash-object -t blob --stdin - * dea509d097ce692e167dfc6a48a7a280cc5e877e - */ -void test_refs_revparse__a_not_precise_enough_objectid_returns_EAMBIGUOUS(void) -{ - git_repository *repo; - git_index *index; - git_object *obj; - - repo = cl_git_sandbox_init("testrepo"); - - cl_git_mkfile("testrepo/one.txt", "aabqhq\n"); - cl_git_mkfile("testrepo/two.txt", "aaazvc\n"); - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add_bypath(index, "one.txt")); - cl_git_pass(git_index_add_bypath(index, "two.txt")); - - cl_git_fail_with(git_revparse_single(&obj, repo, "dea509d0"), GIT_EAMBIGUOUS); - - cl_git_pass(git_revparse_single(&obj, repo, "dea509d09")); - - git_object_free(obj); - git_index_free(index); - cl_git_sandbox_cleanup(); -} - -void test_refs_revparse__issue_994(void) -{ - git_repository *repo; - git_reference *head, *with_at; - git_object *target; - - repo = cl_git_sandbox_init("testrepo.git"); - - cl_assert_equal_i(GIT_ENOTFOUND, - git_revparse_single(&target, repo, "origin/bim_with_3d@11296")); - - cl_assert_equal_i(GIT_ENOTFOUND, - git_revparse_single(&target, repo, "refs/remotes/origin/bim_with_3d@11296")); - - - cl_git_pass(git_repository_head(&head, repo)); - cl_git_pass(git_reference_create( - &with_at, - repo, - "refs/remotes/origin/bim_with_3d@11296", - git_reference_target(head), - 0)); - - cl_git_pass(git_revparse_single(&target, repo, "origin/bim_with_3d@11296")); - git_object_free(target); - - cl_git_pass(git_revparse_single(&target, repo, "refs/remotes/origin/bim_with_3d@11296")); - git_object_free(target); - - git_reference_free(with_at); - git_reference_free(head); - cl_git_sandbox_cleanup(); -} - -/** - * $ git rev-parse blah-7-gc47800c - * c47800c7266a2be04c571c04d5a6614691ea99bd - * - * $ git rev-parse HEAD~3 - * 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 - * - * $ git branch blah-7-gc47800c HEAD~3 - * - * $ git rev-parse blah-7-gc47800c - * 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 - */ -void test_refs_revparse__try_to_retrieve_branch_before_described_tag(void) -{ - git_repository *repo; - git_reference *branch; - git_object *target; - char sha[GIT_OID_HEXSZ + 1]; - - repo = cl_git_sandbox_init("testrepo.git"); - - test_object_inrepo("blah-7-gc47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd", repo); - - cl_git_pass(git_revparse_single(&target, repo, "HEAD~3")); - cl_git_pass(git_branch_create(&branch, repo, "blah-7-gc47800c", (git_commit *)target, 0)); - - git_oid_tostr(sha, GIT_OID_HEXSZ + 1, git_object_id(target)); - - test_object_inrepo("blah-7-gc47800c", sha, repo); - - git_reference_free(branch); - git_object_free(target); - cl_git_sandbox_cleanup(); -} - -/** - * $ git rev-parse a65fedf39aefe402d3bb6e24df4d4f5fe4547750 - * a65fedf39aefe402d3bb6e24df4d4f5fe4547750 - * - * $ git rev-parse HEAD~3 - * 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 - * - * $ git branch a65fedf39aefe402d3bb6e24df4d4f5fe4547750 HEAD~3 - * - * $ git rev-parse a65fedf39aefe402d3bb6e24df4d4f5fe4547750 - * a65fedf39aefe402d3bb6e24df4d4f5fe4547750 - * - * $ git rev-parse heads/a65fedf39aefe402d3bb6e24df4d4f5fe4547750 - * 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 - */ -void test_refs_revparse__try_to_retrieve_sha_before_branch(void) -{ - git_repository *repo; - git_reference *branch; - git_object *target; - char sha[GIT_OID_HEXSZ + 1]; - - repo = cl_git_sandbox_init("testrepo.git"); - - test_object_inrepo("a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); - - cl_git_pass(git_revparse_single(&target, repo, "HEAD~3")); - cl_git_pass(git_branch_create(&branch, repo, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", (git_commit *)target, 0)); - - git_oid_tostr(sha, GIT_OID_HEXSZ + 1, git_object_id(target)); - - test_object_inrepo("a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); - test_object_inrepo("heads/a65fedf39aefe402d3bb6e24df4d4f5fe4547750", sha, repo); - - git_reference_free(branch); - git_object_free(target); - cl_git_sandbox_cleanup(); -} - -/** - * $ git rev-parse c47800 - * c47800c7266a2be04c571c04d5a6614691ea99bd - * - * $ git rev-parse HEAD~3 - * 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 - * - * $ git branch c47800 HEAD~3 - * - * $ git rev-parse c47800 - * 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 - */ -void test_refs_revparse__try_to_retrieve_branch_before_abbrev_sha(void) -{ - git_repository *repo; - git_reference *branch; - git_object *target; - char sha[GIT_OID_HEXSZ + 1]; - - repo = cl_git_sandbox_init("testrepo.git"); - - test_object_inrepo("c47800", "c47800c7266a2be04c571c04d5a6614691ea99bd", repo); - - cl_git_pass(git_revparse_single(&target, repo, "HEAD~3")); - cl_git_pass(git_branch_create(&branch, repo, "c47800", (git_commit *)target, 0)); - - git_oid_tostr(sha, GIT_OID_HEXSZ + 1, git_object_id(target)); - - test_object_inrepo("c47800", sha, repo); - - git_reference_free(branch); - git_object_free(target); - cl_git_sandbox_cleanup(); -} - - -void test_refs_revparse__range(void) -{ - assert_invalid_single_spec("be3563a^1..be3563a"); - - test_rangelike("be3563a^1..be3563a", - "9fd738e8f7967c078dceed8190330fc8648ee56a", - "be3563ae3f795b2b4353bcce3a527ad0a4f7f644", - GIT_REVPARSE_RANGE); - - test_rangelike("be3563a^1...be3563a", - "9fd738e8f7967c078dceed8190330fc8648ee56a", - "be3563ae3f795b2b4353bcce3a527ad0a4f7f644", - GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE); - - test_rangelike("be3563a^1.be3563a", NULL, NULL, 0); -} - -void test_refs_revparse__parses_range_operator(void) -{ - test_id("HEAD", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", NULL, GIT_REVPARSE_SINGLE); - test_id("HEAD~3..HEAD", - "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", - GIT_REVPARSE_RANGE); - - test_id("HEAD~3...HEAD", - "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", - GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE); -} - -void test_refs_revparse__ext_retrieves_both_the_reference_and_its_target(void) -{ - test_object_and_ref( - "master@{upstream}", - "be3563ae3f795b2b4353bcce3a527ad0a4f7f644", - "refs/remotes/test/master"); - - test_object_and_ref( - "@{-1}", - "a4a7dce85cf63874e984719f4fdd239f5145052f", - "refs/heads/br2"); -} - -void test_refs_revparse__ext_can_expand_short_reference_names(void) -{ - test_object_and_ref( - "master", - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", - "refs/heads/master"); - - test_object_and_ref( - "HEAD", - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", - "refs/heads/master"); - - test_object_and_ref( - "tags/test", - "b25fa35b38051e4ae45d4222e795f9df2e43f1d1", - "refs/tags/test"); -} - -void test_refs_revparse__ext_returns_NULL_reference_when_expression_points_at_a_revision(void) -{ - test_object_and_ref( - "HEAD~3", - "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", - NULL); - - test_object_and_ref( - "HEAD~0", - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", - NULL); - - test_object_and_ref( - "HEAD^0", - "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", - NULL); - - test_object_and_ref( - "@{-1}@{0}", - "a4a7dce85cf63874e984719f4fdd239f5145052f", - NULL); -} - -void test_refs_revparse__ext_returns_NULL_reference_when_expression_points_at_a_tree_content(void) -{ - test_object_and_ref( - "tags/test:readme.txt", - "0266163a49e280c4f5ed1e08facd36a2bd716bcf", - NULL); -} diff --git a/tests-clar/refs/setter.c b/tests-clar/refs/setter.c deleted file mode 100644 index 6d875f9b6..000000000 --- a/tests-clar/refs/setter.c +++ /dev/null @@ -1,99 +0,0 @@ -#include "clar_libgit2.h" - -#include "repository.h" -#include "git2/reflog.h" -#include "reflog.h" -#include "git2/refs.h" - -static const char *ref_name = "refs/heads/other"; -static const char *ref_master_name = "refs/heads/master"; -static const char *ref_test_name = "refs/heads/test"; - -static git_repository *g_repo; - -void test_refs_setter__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_refs_setter__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_refs_setter__update_direct(void) -{ - git_reference *ref, *test_ref, *new_ref; - git_oid id; - - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); - cl_assert(git_reference_type(ref) == GIT_REF_OID); - git_oid_cpy(&id, git_reference_target(ref)); - git_reference_free(ref); - - cl_git_pass(git_reference_lookup(&test_ref, g_repo, ref_test_name)); - cl_assert(git_reference_type(test_ref) == GIT_REF_OID); - - cl_git_pass(git_reference_set_target(&new_ref, test_ref, &id)); - - git_reference_free(test_ref); - git_reference_free(new_ref); - - cl_git_pass(git_reference_lookup(&test_ref, g_repo, ref_test_name)); - cl_assert(git_reference_type(test_ref) == GIT_REF_OID); - cl_assert(git_oid_cmp(&id, git_reference_target(test_ref)) == 0); - git_reference_free(test_ref); -} - -void test_refs_setter__update_symbolic(void) -{ - git_reference *head, *new_head; - - cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); - cl_assert(git_reference_type(head) == GIT_REF_SYMBOLIC); - cl_assert(strcmp(git_reference_symbolic_target(head), ref_master_name) == 0); - - cl_git_pass(git_reference_symbolic_set_target(&new_head, head, ref_test_name)); - git_reference_free(new_head); - git_reference_free(head); - - cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); - cl_assert(git_reference_type(head) == GIT_REF_SYMBOLIC); - cl_assert(strcmp(git_reference_symbolic_target(head), ref_test_name) == 0); - git_reference_free(head); -} - -void test_refs_setter__cant_update_direct_with_symbolic(void) -{ - // Overwrite an existing object id reference with a symbolic one - git_reference *ref, *new; - git_oid id; - - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); - cl_assert(git_reference_type(ref) == GIT_REF_OID); - git_oid_cpy(&id, git_reference_target(ref)); - - cl_git_fail(git_reference_symbolic_set_target(&new, ref, ref_name)); - - git_reference_free(ref); -} - -void test_refs_setter__cant_update_symbolic_with_direct(void) -{ - // Overwrite an existing symbolic reference with an object id one - git_reference *ref, *new; - git_oid id; - - cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); - cl_assert(git_reference_type(ref) == GIT_REF_OID); - git_oid_cpy(&id, git_reference_target(ref)); - git_reference_free(ref); - - /* Create the symbolic ref */ - cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0)); - - /* Can't set an OID on a direct ref */ - cl_git_fail(git_reference_set_target(&new, ref, &id)); - - git_reference_free(ref); -} diff --git a/tests-clar/refs/shorthand.c b/tests-clar/refs/shorthand.c deleted file mode 100644 index f995d26ca..000000000 --- a/tests-clar/refs/shorthand.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "clar_libgit2.h" - -#include "repository.h" - -void assert_shorthand(git_repository *repo, const char *refname, const char *shorthand) -{ - git_reference *ref; - - cl_git_pass(git_reference_lookup(&ref, repo, refname)); - cl_assert_equal_s(git_reference_shorthand(ref), shorthand); - git_reference_free(ref); -} - -void test_refs_shorthand__0(void) -{ - git_repository *repo; - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - - - assert_shorthand(repo, "refs/heads/master", "master"); - assert_shorthand(repo, "refs/tags/test", "test"); - assert_shorthand(repo, "refs/remotes/test/master", "test/master"); - assert_shorthand(repo, "refs/notes/fanout", "notes/fanout"); - - git_repository_free(repo); -} diff --git a/tests-clar/refs/unicode.c b/tests-clar/refs/unicode.c deleted file mode 100644 index b56012869..000000000 --- a/tests-clar/refs/unicode.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "clar_libgit2.h" - -static git_repository *repo; - -void test_refs_unicode__initialize(void) -{ - repo = cl_git_sandbox_init("testrepo.git"); -} - -void test_refs_unicode__cleanup(void) -{ - cl_git_sandbox_cleanup(); - repo = NULL; -} - -void test_refs_unicode__create_and_lookup(void) -{ - git_reference *ref0, *ref1, *ref2; - git_repository *repo2; - - const char *REFNAME = "refs/heads/" "\303\205" "ngstr" "\303\266" "m"; - const char *master = "refs/heads/master"; - - /* Create the reference */ - cl_git_pass(git_reference_lookup(&ref0, repo, master)); - cl_git_pass(git_reference_create( - &ref1, repo, REFNAME, git_reference_target(ref0), 0)); - cl_assert_equal_s(REFNAME, git_reference_name(ref1)); - git_reference_free(ref0); - - /* Lookup the reference in a different instance of the repository */ - cl_git_pass(git_repository_open(&repo2, "testrepo.git")); - - cl_git_pass(git_reference_lookup(&ref2, repo2, REFNAME)); - cl_assert_equal_i( - 0, git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2))); - cl_assert_equal_s(REFNAME, git_reference_name(ref2)); - git_reference_free(ref2); - -#if GIT_USE_ICONV - /* Lookup reference by decomposed unicode name */ - -#define REFNAME_DECOMPOSED "refs/heads/" "A" "\314\212" "ngstro" "\314\210" "m" - - cl_git_pass(git_reference_lookup(&ref2, repo2, REFNAME_DECOMPOSED)); - cl_assert_equal_i( - 0, git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2))); - cl_assert_equal_s(REFNAME, git_reference_name(ref2)); - git_reference_free(ref2); -#endif - - /* Cleanup */ - - git_reference_free(ref1); - git_repository_free(repo2); -} diff --git a/tests-clar/refs/update.c b/tests-clar/refs/update.c deleted file mode 100644 index 205b526a2..000000000 --- a/tests-clar/refs/update.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "clar_libgit2.h" - -#include "refs.h" - -static git_repository *g_repo; - -void test_refs_update__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); -} - -void test_refs_update__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_refs_update__updating_the_target_of_a_symref_with_an_invalid_name_returns_EINVALIDSPEC(void) -{ - git_reference *head; - - cl_git_pass(git_reference_lookup(&head, g_repo, GIT_HEAD_FILE)); - cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); - git_reference_free(head); - - cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_symbolic_create(&head, g_repo, GIT_HEAD_FILE, "refs/heads/inv@{id", 1)); -} diff --git a/tests-clar/repo/config.c b/tests-clar/repo/config.c deleted file mode 100644 index e77acc8c5..000000000 --- a/tests-clar/repo/config.c +++ /dev/null @@ -1,208 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include - -static git_buf path = GIT_BUF_INIT; - -void test_repo_config__initialize(void) -{ - cl_fixture_sandbox("empty_standard_repo"); - cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git")); - - git_buf_clear(&path); - - cl_must_pass(p_mkdir("alternate", 0777)); - cl_git_pass(git_path_prettify(&path, "alternate", NULL)); -} - -void test_repo_config__cleanup(void) -{ - cl_git_pass(git_path_prettify(&path, "alternate", NULL)); - cl_git_pass(git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)); - git_buf_free(&path); - cl_assert(!git_path_isdir("alternate")); - - cl_fixture_cleanup("empty_standard_repo"); -} - -void test_repo_config__open_missing_global(void) -{ - git_repository *repo; - git_config *config, *global; - - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); - - cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - cl_git_pass(git_repository_config(&config, repo)); - cl_git_pass(git_config_open_level(&global, config, GIT_CONFIG_LEVEL_GLOBAL)); - - cl_git_pass(git_config_set_string(global, "test.set", "42")); - - git_config_free(global); - git_config_free(config); - git_repository_free(repo); - - git_futils_dirs_global_shutdown(); -} - -void test_repo_config__open_missing_global_with_separators(void) -{ - git_repository *repo; - git_config *config, *global; - - cl_git_pass(git_buf_printf(&path, "%c%s", GIT_PATH_LIST_SEPARATOR, "dummy")); - - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); - - git_buf_free(&path); - - cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - cl_git_pass(git_repository_config(&config, repo)); - cl_git_pass(git_config_open_level(&global, config, GIT_CONFIG_LEVEL_GLOBAL)); - - cl_git_pass(git_config_set_string(global, "test.set", "42")); - - git_config_free(global); - git_config_free(config); - git_repository_free(repo); - - git_futils_dirs_global_shutdown(); -} - -#include "repository.h" - -void test_repo_config__read_no_configs(void) -{ - git_repository *repo; - int val; - - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); - - /* with none */ - - cl_must_pass(p_unlink("empty_standard_repo/.git/config")); - cl_assert(!git_path_isfile("empty_standard_repo/.git/config")); - - cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); - val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); - cl_assert_equal_i(GIT_ABBREV_DEFAULT, val); - git_repository_free(repo); - - git_futils_dirs_global_shutdown(); - - /* with just system */ - - cl_must_pass(p_mkdir("alternate/1", 0777)); - cl_git_pass(git_buf_joinpath(&path, path.ptr, "1")); - cl_git_rewritefile("alternate/1/gitconfig", "[core]\n\tabbrev = 10\n"); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); - - cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); - val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); - cl_assert_equal_i(10, val); - git_repository_free(repo); - - /* with xdg + system */ - - cl_must_pass(p_mkdir("alternate/2", 0777)); - path.ptr[path.size - 1] = '2'; - cl_git_rewritefile("alternate/2/config", "[core]\n\tabbrev = 20\n"); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); - - cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); - val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); - cl_assert_equal_i(20, val); - git_repository_free(repo); - - /* with global + xdg + system */ - - cl_must_pass(p_mkdir("alternate/3", 0777)); - path.ptr[path.size - 1] = '3'; - cl_git_rewritefile("alternate/3/.gitconfig", "[core]\n\tabbrev = 30\n"); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); - - cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); - val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); - cl_assert_equal_i(30, val); - git_repository_free(repo); - - /* with all configs */ - - cl_git_rewritefile("empty_standard_repo/.git/config", "[core]\n\tabbrev = 40\n"); - - cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); - val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); - cl_assert_equal_i(40, val); - git_repository_free(repo); - - /* with all configs but delete the files ? */ - - cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); - val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); - cl_assert_equal_i(40, val); - - cl_must_pass(p_unlink("empty_standard_repo/.git/config")); - cl_assert(!git_path_isfile("empty_standard_repo/.git/config")); - - cl_must_pass(p_unlink("alternate/1/gitconfig")); - cl_assert(!git_path_isfile("alternate/1/gitconfig")); - - cl_must_pass(p_unlink("alternate/2/config")); - cl_assert(!git_path_isfile("alternate/2/config")); - - cl_must_pass(p_unlink("alternate/3/.gitconfig")); - cl_assert(!git_path_isfile("alternate/3/.gitconfig")); - - git_repository__cvar_cache_clear(repo); - val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); - cl_assert_equal_i(40, val); - git_repository_free(repo); - - /* reopen */ - - cl_assert(!git_path_isfile("empty_standard_repo/.git/config")); - cl_assert(!git_path_isfile("alternate/3/.gitconfig")); - - cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - git_repository__cvar_cache_clear(repo); - val = -1; - cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); - cl_assert_equal_i(7, val); - git_repository_free(repo); - - cl_assert(!git_path_exists("empty_standard_repo/.git/config")); - cl_assert(!git_path_exists("alternate/3/.gitconfig")); - - git_futils_dirs_global_shutdown(); -} diff --git a/tests-clar/repo/discover.c b/tests-clar/repo/discover.c deleted file mode 100644 index f93ff2462..000000000 --- a/tests-clar/repo/discover.c +++ /dev/null @@ -1,142 +0,0 @@ -#include "clar_libgit2.h" - -#include "odb.h" -#include "fileops.h" -#include "repository.h" - -#define TEMP_REPO_FOLDER "temprepo/" -#define DISCOVER_FOLDER TEMP_REPO_FOLDER "discover.git" - -#define SUB_REPOSITORY_FOLDER_NAME "sub_repo" -#define SUB_REPOSITORY_FOLDER DISCOVER_FOLDER "/" SUB_REPOSITORY_FOLDER_NAME -#define SUB_REPOSITORY_FOLDER_SUB SUB_REPOSITORY_FOLDER "/sub" -#define SUB_REPOSITORY_FOLDER_SUB_SUB SUB_REPOSITORY_FOLDER_SUB "/subsub" -#define SUB_REPOSITORY_FOLDER_SUB_SUB_SUB SUB_REPOSITORY_FOLDER_SUB_SUB "/subsubsub" - -#define REPOSITORY_ALTERNATE_FOLDER DISCOVER_FOLDER "/alternate_sub_repo" -#define REPOSITORY_ALTERNATE_FOLDER_SUB REPOSITORY_ALTERNATE_FOLDER "/sub" -#define REPOSITORY_ALTERNATE_FOLDER_SUB_SUB REPOSITORY_ALTERNATE_FOLDER_SUB "/subsub" -#define REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/subsubsub" - -#define ALTERNATE_MALFORMED_FOLDER1 DISCOVER_FOLDER "/alternate_malformed_repo1" -#define ALTERNATE_MALFORMED_FOLDER2 DISCOVER_FOLDER "/alternate_malformed_repo2" -#define ALTERNATE_MALFORMED_FOLDER3 DISCOVER_FOLDER "/alternate_malformed_repo3" -#define ALTERNATE_NOT_FOUND_FOLDER DISCOVER_FOLDER "/alternate_not_found_repo" - -static void ensure_repository_discover(const char *start_path, - const char *ceiling_dirs, - const char *expected_path) -{ - char found_path[GIT_PATH_MAX]; - cl_git_pass(git_repository_discover(found_path, sizeof(found_path), start_path, 0, ceiling_dirs)); - //across_fs is always 0 as we can't automate the filesystem change tests - cl_assert_equal_s(found_path, expected_path); -} - -static void write_file(const char *path, const char *content) -{ - git_file file; - int error; - - if (git_path_exists(path)) { - cl_git_pass(p_unlink(path)); - } - - file = git_futils_creat_withpath(path, 0777, 0666); - cl_assert(file >= 0); - - error = p_write(file, content, strlen(content) * sizeof(char)); - p_close(file); - cl_git_pass(error); -} - -//no check is performed on ceiling_dirs length, so be sure it's long enough -static void append_ceiling_dir(git_buf *ceiling_dirs, const char *path) -{ - git_buf pretty_path = GIT_BUF_INIT; - char ceiling_separator[2] = { GIT_PATH_LIST_SEPARATOR, '\0' }; - - cl_git_pass(git_path_prettify_dir(&pretty_path, path, NULL)); - - if (ceiling_dirs->size > 0) - git_buf_puts(ceiling_dirs, ceiling_separator); - - git_buf_puts(ceiling_dirs, pretty_path.ptr); - - git_buf_free(&pretty_path); - cl_assert(git_buf_oom(ceiling_dirs) == 0); -} - -void test_repo_discover__0(void) -{ - // test discover - git_repository *repo; - git_buf ceiling_dirs_buf = GIT_BUF_INIT; - const char *ceiling_dirs; - char repository_path[GIT_PATH_MAX]; - char sub_repository_path[GIT_PATH_MAX]; - char found_path[GIT_PATH_MAX]; - const mode_t mode = 0777; - - git_futils_mkdir_r(DISCOVER_FOLDER, NULL, mode); - append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER); - ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf); - - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs)); - - cl_git_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1)); - cl_git_pass(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs)); - git_repository_free(repo); - - cl_git_pass(git_repository_init(&repo, SUB_REPOSITORY_FOLDER, 0)); - cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode)); - cl_git_pass(git_repository_discover(sub_repository_path, sizeof(sub_repository_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs)); - - cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode)); - ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, sub_repository_path); - ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path); - ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, sub_repository_path); - - cl_git_pass(git_futils_mkdir_r(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, NULL, mode)); - write_file(REPOSITORY_ALTERNATE_FOLDER "/" DOT_GIT, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT); - write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/" DOT_GIT, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT); - write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB "/" DOT_GIT, "gitdir: ../../../../"); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path); - - cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER1, NULL, mode)); - write_file(ALTERNATE_MALFORMED_FOLDER1 "/" DOT_GIT, "Anything but not gitdir:"); - cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER2, NULL, mode)); - write_file(ALTERNATE_MALFORMED_FOLDER2 "/" DOT_GIT, "gitdir:"); - cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER3, NULL, mode)); - write_file(ALTERNATE_MALFORMED_FOLDER3 "/" DOT_GIT, "gitdir: \n\n\n"); - cl_git_pass(git_futils_mkdir_r(ALTERNATE_NOT_FOUND_FOLDER, NULL, mode)); - write_file(ALTERNATE_NOT_FOUND_FOLDER "/" DOT_GIT, "gitdir: a_repository_that_surely_does_not_exist"); - cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs)); - cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs)); - cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs)); - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs)); - - append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER); - ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf); - - //this must pass as ceiling_directories cannot predent the current - //working directory to be checked - cl_git_pass(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs)); - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs)); - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs)); - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs)); - - //.gitfile redirection should not be affected by ceiling directories - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path); - ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path); - - cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, NULL, GIT_RMDIR_REMOVE_FILES)); - git_repository_free(repo); - git_buf_free(&ceiling_dirs_buf); -} - diff --git a/tests-clar/repo/getters.c b/tests-clar/repo/getters.c deleted file mode 100644 index b8ede126c..000000000 --- a/tests-clar/repo/getters.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "clar_libgit2.h" - -void test_repo_getters__is_empty_correctly_deals_with_pristine_looking_repos(void) -{ - git_repository *repo; - - repo = cl_git_sandbox_init("empty_bare.git"); - cl_git_remove_placeholders(git_repository_path(repo), "dummy-marker.txt"); - - cl_assert_equal_i(true, git_repository_is_empty(repo)); - - cl_git_sandbox_cleanup(); -} - -void test_repo_getters__is_empty_can_detect_used_repositories(void) -{ - git_repository *repo; - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - - cl_assert_equal_i(false, git_repository_is_empty(repo)); - - git_repository_free(repo); -} - -void test_repo_getters__retrieving_the_odb_honors_the_refcount(void) -{ - git_odb *odb; - git_repository *repo; - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - - cl_git_pass(git_repository_odb(&odb, repo)); - cl_assert(((git_refcount *)odb)->refcount.val == 2); - - git_repository_free(repo); - cl_assert(((git_refcount *)odb)->refcount.val == 1); - - git_odb_free(odb); -} diff --git a/tests-clar/repo/hashfile.c b/tests-clar/repo/hashfile.c deleted file mode 100644 index 4cc9f18b4..000000000 --- a/tests-clar/repo/hashfile.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" - -static git_repository *_repo; - -void test_repo_hashfile__initialize(void) -{ - _repo = cl_git_sandbox_init("status"); -} - -void test_repo_hashfile__cleanup(void) -{ - cl_git_sandbox_cleanup(); - _repo = NULL; -} - -void test_repo_hashfile__simple(void) -{ - git_oid a, b; - git_buf full = GIT_BUF_INIT; - - /* hash with repo relative path */ - cl_git_pass(git_odb_hashfile(&a, "status/current_file", GIT_OBJ_BLOB)); - cl_git_pass(git_repository_hashfile(&b, _repo, "current_file", GIT_OBJ_BLOB, NULL)); - cl_assert(git_oid_equal(&a, &b)); - - cl_git_pass(git_buf_joinpath(&full, git_repository_workdir(_repo), "current_file")); - - /* hash with full path */ - cl_git_pass(git_odb_hashfile(&a, full.ptr, GIT_OBJ_BLOB)); - cl_git_pass(git_repository_hashfile(&b, _repo, full.ptr, GIT_OBJ_BLOB, NULL)); - cl_assert(git_oid_equal(&a, &b)); - - /* hash with invalid type */ - cl_git_fail(git_odb_hashfile(&a, full.ptr, GIT_OBJ_ANY)); - cl_git_fail(git_repository_hashfile(&b, _repo, full.ptr, GIT_OBJ_OFS_DELTA, NULL)); - - git_buf_free(&full); -} - -void test_repo_hashfile__filtered(void) -{ - git_oid a, b; - - cl_repo_set_bool(_repo, "core.autocrlf", true); - - cl_git_append2file("status/.gitattributes", "*.txt text\n*.bin binary\n\n"); - - /* create some sample content with CRLF in it */ - cl_git_mkfile("status/testfile.txt", "content\r\n"); - cl_git_mkfile("status/testfile.bin", "other\r\nstuff\r\n"); - - /* not equal hashes because of filtering */ - cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJ_BLOB)); - cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_BLOB, NULL)); - cl_assert(git_oid_cmp(&a, &b)); - - /* equal hashes because filter is binary */ - cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJ_BLOB)); - cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJ_BLOB, NULL)); - cl_assert(git_oid_equal(&a, &b)); - - /* equal hashes when 'as_file' points to binary filtering */ - cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJ_BLOB)); - cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_BLOB, "foo.bin")); - cl_assert(git_oid_equal(&a, &b)); - - /* not equal hashes when 'as_file' points to text filtering */ - cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJ_BLOB)); - cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJ_BLOB, "foo.txt")); - cl_assert(git_oid_cmp(&a, &b)); - - /* equal hashes when 'as_file' is empty and turns off filtering */ - cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJ_BLOB)); - cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_BLOB, "")); - cl_assert(git_oid_equal(&a, &b)); - - cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJ_BLOB)); - cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJ_BLOB, "")); - cl_assert(git_oid_equal(&a, &b)); - - /* some hash type failures */ - cl_git_fail(git_odb_hashfile(&a, "status/testfile.txt", 0)); - cl_git_fail(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_ANY, NULL)); -} diff --git a/tests-clar/repo/head.c b/tests-clar/repo/head.c deleted file mode 100644 index 5a55984bd..000000000 --- a/tests-clar/repo/head.c +++ /dev/null @@ -1,196 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" -#include "repo_helpers.h" -#include "posix.h" - -static git_repository *repo; - -void test_repo_head__initialize(void) -{ - repo = cl_git_sandbox_init("testrepo.git"); -} - -void test_repo_head__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_repo_head__head_detached(void) -{ - git_reference *ref; - - cl_git_pass(git_repository_head_detached(repo)); - - cl_git_pass(git_repository_detach_head(repo)); - - cl_assert_equal_i(true, git_repository_head_detached(repo)); - - /* take the reop back to it's original state */ - cl_git_pass(git_reference_symbolic_create(&ref, repo, "HEAD", "refs/heads/master", 1)); - git_reference_free(ref); - - cl_assert_equal_i(false, git_repository_head_detached(repo)); -} - -void test_repo_head__unborn_head(void) -{ - git_reference *ref; - - cl_git_pass(git_repository_head_detached(repo)); - - make_head_unborn(repo, NON_EXISTING_HEAD); - - cl_assert(git_repository_head_unborn(repo) == 1); - - - /* take the repo back to it's original state */ - cl_git_pass(git_reference_symbolic_create(&ref, repo, "HEAD", "refs/heads/master", 1)); - cl_assert(git_repository_head_unborn(repo) == 0); - - git_reference_free(ref); -} - -void test_repo_head__set_head_Attaches_HEAD_to_un_unborn_branch_when_the_branch_doesnt_exist(void) -{ - git_reference *head; - - cl_git_pass(git_repository_set_head(repo, "refs/heads/doesnt/exist/yet")); - - cl_assert_equal_i(false, git_repository_head_detached(repo)); - - cl_assert_equal_i(GIT_EUNBORNBRANCH, git_repository_head(&head, repo)); -} - -void test_repo_head__set_head_Returns_ENOTFOUND_when_the_reference_doesnt_exist(void) -{ - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head(repo, "refs/tags/doesnt/exist/yet")); -} - -void test_repo_head__set_head_Fails_when_the_reference_points_to_a_non_commitish(void) -{ - cl_git_fail(git_repository_set_head(repo, "refs/tags/point_to_blob")); -} - -void test_repo_head__set_head_Attaches_HEAD_when_the_reference_points_to_a_branch(void) -{ - git_reference *head; - - cl_git_pass(git_repository_set_head(repo, "refs/heads/br2")); - - cl_assert_equal_i(false, git_repository_head_detached(repo)); - - cl_git_pass(git_repository_head(&head, repo)); - cl_assert_equal_s("refs/heads/br2", git_reference_name(head)); - - git_reference_free(head); -} - -static void assert_head_is_correctly_detached(void) -{ - git_reference *head; - git_object *commit; - - cl_assert_equal_i(true, git_repository_head_detached(repo)); - - cl_git_pass(git_repository_head(&head, repo)); - - cl_git_pass(git_object_lookup(&commit, repo, git_reference_target(head), GIT_OBJ_COMMIT)); - - git_object_free(commit); - git_reference_free(head); -} - -void test_repo_head__set_head_Detaches_HEAD_when_the_reference_doesnt_point_to_a_branch(void) -{ - cl_git_pass(git_repository_set_head(repo, "refs/tags/test")); - - cl_assert_equal_i(true, git_repository_head_detached(repo)); - - assert_head_is_correctly_detached(); -} - -void test_repo_head__set_head_detached_Return_ENOTFOUND_when_the_object_doesnt_exist(void) -{ - git_oid oid; - - cl_git_pass(git_oid_fromstr(&oid, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")); - - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head_detached(repo, &oid)); -} - -void test_repo_head__set_head_detached_Fails_when_the_object_isnt_a_commitish(void) -{ - git_object *blob; - - cl_git_pass(git_revparse_single(&blob, repo, "point_to_blob")); - - cl_git_fail(git_repository_set_head_detached(repo, git_object_id(blob))); - - git_object_free(blob); -} - -void test_repo_head__set_head_detached_Detaches_HEAD_and_make_it_point_to_the_peeled_commit(void) -{ - git_object *tag; - - cl_git_pass(git_revparse_single(&tag, repo, "tags/test")); - cl_assert_equal_i(GIT_OBJ_TAG, git_object_type(tag)); - - cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag))); - - assert_head_is_correctly_detached(); - - git_object_free(tag); -} - -void test_repo_head__detach_head_Detaches_HEAD_and_make_it_point_to_the_peeled_commit(void) -{ - cl_assert_equal_i(false, git_repository_head_detached(repo)); - - cl_git_pass(git_repository_detach_head(repo)); - - assert_head_is_correctly_detached(); -} - -void test_repo_head__detach_head_Fails_if_HEAD_and_point_to_a_non_commitish(void) -{ - git_reference *head; - - cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, "refs/tags/point_to_blob", 1)); - - cl_git_fail(git_repository_detach_head(repo)); - - git_reference_free(head); -} - -void test_repo_head__detaching_an_unborn_branch_returns_GIT_EUNBORNBRANCH(void) -{ - make_head_unborn(repo, NON_EXISTING_HEAD); - - cl_assert_equal_i(GIT_EUNBORNBRANCH, git_repository_detach_head(repo)); -} - -void test_repo_head__retrieving_an_unborn_branch_returns_GIT_EUNBORNBRANCH(void) -{ - git_reference *head; - - make_head_unborn(repo, NON_EXISTING_HEAD); - - cl_assert_equal_i(GIT_EUNBORNBRANCH, git_repository_head(&head, repo)); -} - -void test_repo_head__retrieving_a_missing_head_returns_GIT_ENOTFOUND(void) -{ - git_reference *head; - - delete_head(repo); - - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_head(&head, repo)); -} - -void test_repo_head__can_tell_if_an_unborn_head_is_detached(void) -{ - make_head_unborn(repo, NON_EXISTING_HEAD); - - cl_assert_equal_i(false, git_repository_head_detached(repo)); -} diff --git a/tests-clar/repo/headtree.c b/tests-clar/repo/headtree.c deleted file mode 100644 index e899ac399..000000000 --- a/tests-clar/repo/headtree.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "clar_libgit2.h" -#include "repository.h" -#include "repo_helpers.h" -#include "posix.h" - -static git_repository *repo; -static git_tree *tree; - -void test_repo_headtree__initialize(void) -{ - repo = cl_git_sandbox_init("testrepo.git"); - tree = NULL; -} - -void test_repo_headtree__cleanup(void) -{ - git_tree_free(tree); - cl_git_sandbox_cleanup(); -} - -void test_repo_headtree__can_retrieve_the_root_tree_from_a_detached_head(void) -{ - cl_git_pass(git_repository_detach_head(repo)); - - cl_git_pass(git_repository_head_tree(&tree, repo)); - - cl_assert(git_oid_streq(git_tree_id(tree), "az")); -} - -void test_repo_headtree__can_retrieve_the_root_tree_from_a_non_detached_head(void) -{ - cl_assert_equal_i(false, git_repository_head_detached(repo)); - - cl_git_pass(git_repository_head_tree(&tree, repo)); - - cl_assert(git_oid_streq(git_tree_id(tree), "az")); -} - -void test_repo_headtree__when_head_is_unborn_returns_EUNBORNBRANCH(void) -{ - make_head_unborn(repo, NON_EXISTING_HEAD); - - cl_assert_equal_i(true, git_repository_head_unborn(repo)); - - cl_assert_equal_i(GIT_EUNBORNBRANCH, git_repository_head_tree(&tree, repo)); -} - -void test_repo_headtree__when_head_is_missing_returns_ENOTFOUND(void) -{ - delete_head(repo); - - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_head_tree(&tree, repo)); -} diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c deleted file mode 100644 index aea383c64..000000000 --- a/tests-clar/repo/init.c +++ /dev/null @@ -1,606 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "repository.h" -#include "config.h" -#include "path.h" - -enum repo_mode { - STANDARD_REPOSITORY = 0, - BARE_REPOSITORY = 1 -}; - -static git_repository *_repo = NULL; -static mode_t g_umask = 0; - -void test_repo_init__initialize(void) -{ - _repo = NULL; - - /* load umask if not already loaded */ - if (!g_umask) { - g_umask = p_umask(022); - (void)p_umask(g_umask); - } -} - -static void cleanup_repository(void *path) -{ - git_repository_free(_repo); - _repo = NULL; - - cl_fixture_cleanup((const char *)path); -} - -static void ensure_repository_init( - const char *working_directory, - int is_bare, - const char *expected_path_repository, - const char *expected_working_directory) -{ - const char *workdir; - - cl_assert(!git_path_isdir(working_directory)); - - cl_git_pass(git_repository_init(&_repo, working_directory, is_bare)); - - workdir = git_repository_workdir(_repo); - if (workdir != NULL || expected_working_directory != NULL) { - cl_assert( - git__suffixcmp(workdir, expected_working_directory) == 0 - ); - } - - cl_assert( - git__suffixcmp(git_repository_path(_repo), expected_path_repository) == 0 - ); - - cl_assert(git_repository_is_bare(_repo) == is_bare); - -#ifdef GIT_WIN32 - if (!is_bare) { - DWORD fattrs = GetFileAttributes(git_repository_path(_repo)); - cl_assert((fattrs & FILE_ATTRIBUTE_HIDDEN) != 0); - } -#endif - - cl_assert(git_repository_is_empty(_repo)); -} - -void test_repo_init__standard_repo(void) -{ - cl_set_cleanup(&cleanup_repository, "testrepo"); - ensure_repository_init("testrepo/", 0, "testrepo/.git/", "testrepo/"); -} - -void test_repo_init__standard_repo_noslash(void) -{ - cl_set_cleanup(&cleanup_repository, "testrepo"); - ensure_repository_init("testrepo", 0, "testrepo/.git/", "testrepo/"); -} - -void test_repo_init__bare_repo(void) -{ - cl_set_cleanup(&cleanup_repository, "testrepo.git"); - ensure_repository_init("testrepo.git/", 1, "testrepo.git/", NULL); -} - -void test_repo_init__bare_repo_noslash(void) -{ - cl_set_cleanup(&cleanup_repository, "testrepo.git"); - ensure_repository_init("testrepo.git", 1, "testrepo.git/", NULL); -} - -void test_repo_init__bare_repo_escaping_current_workdir(void) -{ - git_buf path_repository = GIT_BUF_INIT; - git_buf path_current_workdir = GIT_BUF_INIT; - - cl_git_pass(git_path_prettify_dir(&path_current_workdir, ".", NULL)); - - cl_git_pass(git_buf_joinpath(&path_repository, git_buf_cstr(&path_current_workdir), "a/b/c")); - cl_git_pass(git_futils_mkdir_r(git_buf_cstr(&path_repository), NULL, GIT_DIR_MODE)); - - /* Change the current working directory */ - cl_git_pass(chdir(git_buf_cstr(&path_repository))); - - /* Initialize a bare repo with a relative path escaping out of the current working directory */ - cl_git_pass(git_repository_init(&_repo, "../d/e.git", 1)); - cl_git_pass(git__suffixcmp(git_repository_path(_repo), "/a/b/d/e.git/")); - - git_repository_free(_repo); - - /* Open a bare repo with a relative path escaping out of the current working directory */ - cl_git_pass(git_repository_open(&_repo, "../d/e.git")); - - cl_git_pass(chdir(git_buf_cstr(&path_current_workdir))); - - git_buf_free(&path_current_workdir); - git_buf_free(&path_repository); - - cleanup_repository("a"); -} - -void test_repo_init__reinit_bare_repo(void) -{ - cl_set_cleanup(&cleanup_repository, "reinit.git"); - - /* Initialize the repository */ - cl_git_pass(git_repository_init(&_repo, "reinit.git", 1)); - git_repository_free(_repo); - - /* Reinitialize the repository */ - cl_git_pass(git_repository_init(&_repo, "reinit.git", 1)); -} - -void test_repo_init__reinit_too_recent_bare_repo(void) -{ - git_config *config; - - /* Initialize the repository */ - cl_git_pass(git_repository_init(&_repo, "reinit.git", 1)); - git_repository_config(&config, _repo); - - /* - * Hack the config of the repository to make it look like it has - * been created by a recenter version of git/libgit2 - */ - cl_git_pass(git_config_set_int32(config, "core.repositoryformatversion", 42)); - - git_config_free(config); - git_repository_free(_repo); - - /* Try to reinitialize the repository */ - cl_git_fail(git_repository_init(&_repo, "reinit.git", 1)); - - cl_fixture_cleanup("reinit.git"); -} - -void test_repo_init__additional_templates(void) -{ - git_buf path = GIT_BUF_INIT; - - cl_set_cleanup(&cleanup_repository, "tester"); - - ensure_repository_init("tester", 0, "tester/.git/", "tester/"); - - cl_git_pass( - git_buf_joinpath(&path, git_repository_path(_repo), "description")); - cl_assert(git_path_isfile(git_buf_cstr(&path))); - - cl_git_pass( - git_buf_joinpath(&path, git_repository_path(_repo), "info/exclude")); - cl_assert(git_path_isfile(git_buf_cstr(&path))); - - cl_git_pass( - git_buf_joinpath(&path, git_repository_path(_repo), "hooks")); - cl_assert(git_path_isdir(git_buf_cstr(&path))); - /* won't confirm specific contents of hooks dir since it may vary */ - - git_buf_free(&path); -} - -static void assert_config_entry_on_init_bytype( - const char *config_key, int expected_value, bool is_bare) -{ - git_config *config; - int error, current_value; - const char *repo_path = is_bare ? - "config_entry/test.bare.git" : "config_entry/test.non.bare.git"; - - cl_set_cleanup(&cleanup_repository, "config_entry"); - - cl_git_pass(git_repository_init(&_repo, repo_path, is_bare)); - - cl_git_pass(git_repository_config(&config, _repo)); - error = git_config_get_bool(¤t_value, config, config_key); - git_config_free(config); - - if (expected_value >= 0) { - cl_assert_equal_i(0, error); - cl_assert_equal_i(expected_value, current_value); - } else { - cl_assert_equal_i(expected_value, error); - } -} - -static void assert_config_entry_on_init( - const char *config_key, int expected_value) -{ - assert_config_entry_on_init_bytype(config_key, expected_value, true); - git_repository_free(_repo); - - assert_config_entry_on_init_bytype(config_key, expected_value, false); -} - -void test_repo_init__detect_filemode(void) -{ - assert_config_entry_on_init("core.filemode", cl_is_chmod_supported()); -} - -void test_repo_init__detect_ignorecase(void) -{ - struct stat st; - bool found_without_match; - - cl_git_write2file("testCAPS", "whatever\n", 0, O_CREAT | O_WRONLY, 0666); - found_without_match = (p_stat("Testcaps", &st) == 0); - cl_must_pass(p_unlink("testCAPS")); - - assert_config_entry_on_init( - "core.ignorecase", found_without_match ? true : GIT_ENOTFOUND); -} - -void test_repo_init__detect_precompose_unicode_required(void) -{ -#ifdef GIT_USE_ICONV - char *composed = "ḱṷṓn", *decomposed = "ḱṷṓn"; - struct stat st; - bool found_with_nfd; - - cl_git_write2file(composed, "whatever\n", 0, O_CREAT | O_WRONLY, 0666); - found_with_nfd = (p_stat(decomposed, &st) == 0); - cl_must_pass(p_unlink(composed)); - - assert_config_entry_on_init("core.precomposeunicode", found_with_nfd); -#else - assert_config_entry_on_init("core.precomposeunicode", GIT_ENOTFOUND); -#endif -} - -void test_repo_init__reinit_doesnot_overwrite_ignorecase(void) -{ - git_config *config; - int current_value; - - /* Init a new repo */ - cl_set_cleanup(&cleanup_repository, "not.overwrite.git"); - cl_git_pass(git_repository_init(&_repo, "not.overwrite.git", 1)); - - /* Change the "core.ignorecase" config value to something unlikely */ - git_repository_config(&config, _repo); - git_config_set_int32(config, "core.ignorecase", 42); - git_config_free(config); - git_repository_free(_repo); - _repo = NULL; - - /* Reinit the repository */ - cl_git_pass(git_repository_init(&_repo, "not.overwrite.git", 1)); - git_repository_config(&config, _repo); - - /* Ensure the "core.ignorecase" config value hasn't been updated */ - cl_git_pass(git_config_get_int32(¤t_value, config, "core.ignorecase")); - cl_assert_equal_i(42, current_value); - - git_config_free(config); -} - -void test_repo_init__reinit_overwrites_filemode(void) -{ - int expected = cl_is_chmod_supported(), current_value; - - /* Init a new repo */ - cl_set_cleanup(&cleanup_repository, "overwrite.git"); - cl_git_pass(git_repository_init(&_repo, "overwrite.git", 1)); - - /* Change the "core.filemode" config value to something unlikely */ - cl_repo_set_bool(_repo, "core.filemode", !expected); - - git_repository_free(_repo); - _repo = NULL; - - /* Reinit the repository */ - cl_git_pass(git_repository_init(&_repo, "overwrite.git", 1)); - - /* Ensure the "core.filemode" config value has been reset */ - current_value = cl_repo_get_bool(_repo, "core.filemode"); - cl_assert_equal_i(expected, current_value); -} - -void test_repo_init__sets_logAllRefUpdates_according_to_type_of_repository(void) -{ - assert_config_entry_on_init_bytype("core.logallrefupdates", GIT_ENOTFOUND, true); - git_repository_free(_repo); - assert_config_entry_on_init_bytype("core.logallrefupdates", true, false); -} - -void test_repo_init__extended_0(void) -{ - git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; - - /* without MKDIR this should fail */ - cl_git_fail(git_repository_init_ext(&_repo, "extended", &opts)); - - /* make the directory first, then it should succeed */ - cl_git_pass(git_futils_mkdir("extended", NULL, 0775, 0)); - cl_git_pass(git_repository_init_ext(&_repo, "extended", &opts)); - - cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "/extended/")); - cl_assert(!git__suffixcmp(git_repository_path(_repo), "/extended/.git/")); - cl_assert(!git_repository_is_bare(_repo)); - cl_assert(git_repository_is_empty(_repo)); - - cleanup_repository("extended"); -} - -void test_repo_init__extended_1(void) -{ - git_reference *ref; - git_remote *remote; - struct stat st; - git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; - - opts.flags = GIT_REPOSITORY_INIT_MKPATH | - GIT_REPOSITORY_INIT_NO_DOTGIT_DIR; - opts.mode = GIT_REPOSITORY_INIT_SHARED_GROUP; - opts.workdir_path = "../c_wd"; - opts.description = "Awesomest test repository evah"; - opts.initial_head = "development"; - opts.origin_url = "https://github.com/libgit2/libgit2.git"; - - cl_git_pass(git_repository_init_ext(&_repo, "root/b/c.git", &opts)); - - cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "/c_wd/")); - cl_assert(!git__suffixcmp(git_repository_path(_repo), "/c.git/")); - cl_assert(git_path_isfile("root/b/c_wd/.git")); - cl_assert(!git_repository_is_bare(_repo)); - /* repo will not be counted as empty because we set head to "development" */ - cl_assert(!git_repository_is_empty(_repo)); - - cl_git_pass(git_path_lstat(git_repository_path(_repo), &st)); - cl_assert(S_ISDIR(st.st_mode)); - if (cl_is_chmod_supported()) - cl_assert((S_ISGID & st.st_mode) == S_ISGID); - else - cl_assert((S_ISGID & st.st_mode) == 0); - - cl_git_pass(git_reference_lookup(&ref, _repo, "HEAD")); - cl_assert(git_reference_type(ref) == GIT_REF_SYMBOLIC); - cl_assert_equal_s("refs/heads/development", git_reference_symbolic_target(ref)); - git_reference_free(ref); - - cl_git_pass(git_remote_load(&remote, _repo, "origin")); - cl_assert_equal_s("origin", git_remote_name(remote)); - cl_assert_equal_s(opts.origin_url, git_remote_url(remote)); - git_remote_free(remote); - - git_repository_free(_repo); - cl_fixture_cleanup("root"); -} - -#define CLEAR_FOR_CORE_FILEMODE(M) ((M) &= ~0177) - -static void assert_hooks_match( - const char *template_dir, - const char *repo_dir, - const char *hook_path, - bool core_filemode) -{ - git_buf expected = GIT_BUF_INIT; - git_buf actual = GIT_BUF_INIT; - struct stat expected_st, st; - - cl_git_pass(git_buf_joinpath(&expected, template_dir, hook_path)); - cl_git_pass(git_path_lstat(expected.ptr, &expected_st)); - - cl_git_pass(git_buf_joinpath(&actual, repo_dir, hook_path)); - cl_git_pass(git_path_lstat(actual.ptr, &st)); - - cl_assert(expected_st.st_size == st.st_size); - - if (GIT_MODE_TYPE(expected_st.st_mode) != GIT_FILEMODE_LINK) { - mode_t expected_mode = - GIT_MODE_TYPE(expected_st.st_mode) | - (GIT_PERMS_FOR_WRITE(expected_st.st_mode) & ~g_umask); - - if (!core_filemode) { - CLEAR_FOR_CORE_FILEMODE(expected_mode); - CLEAR_FOR_CORE_FILEMODE(st.st_mode); - } - - cl_assert_equal_i_fmt(expected_mode, st.st_mode, "%07o"); - } - - git_buf_free(&expected); - git_buf_free(&actual); -} - -static void assert_mode_seems_okay( - const char *base, const char *path, - git_filemode_t expect_mode, bool expect_setgid, bool core_filemode) -{ - git_buf full = GIT_BUF_INIT; - struct stat st; - - cl_git_pass(git_buf_joinpath(&full, base, path)); - cl_git_pass(git_path_lstat(full.ptr, &st)); - git_buf_free(&full); - - if (!core_filemode) { - CLEAR_FOR_CORE_FILEMODE(expect_mode); - CLEAR_FOR_CORE_FILEMODE(st.st_mode); - expect_setgid = false; - } - - if (S_ISGID != 0) - cl_assert_equal_b(expect_setgid, (st.st_mode & S_ISGID) != 0); - - cl_assert_equal_b( - GIT_PERMS_IS_EXEC(expect_mode), GIT_PERMS_IS_EXEC(st.st_mode)); - - cl_assert_equal_i_fmt( - GIT_MODE_TYPE(expect_mode), GIT_MODE_TYPE(st.st_mode), "%07o"); -} - -void test_repo_init__extended_with_template(void) -{ - git_buf expected = GIT_BUF_INIT; - git_buf actual = GIT_BUF_INIT; - git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; - int filemode; - - cl_set_cleanup(&cleanup_repository, "templated.git"); - - opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE | - GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; - opts.template_path = cl_fixture("template"); - - cl_git_pass(git_repository_init_ext(&_repo, "templated.git", &opts)); - - cl_assert(git_repository_is_bare(_repo)); - - cl_assert(!git__suffixcmp(git_repository_path(_repo), "/templated.git/")); - - cl_git_pass(git_futils_readbuffer( - &expected, cl_fixture("template/description"))); - cl_git_pass(git_futils_readbuffer( - &actual, "templated.git/description")); - - cl_assert_equal_s(expected.ptr, actual.ptr); - - git_buf_free(&expected); - git_buf_free(&actual); - - filemode = cl_repo_get_bool(_repo, "core.filemode"); - - assert_hooks_match( - cl_fixture("template"), git_repository_path(_repo), - "hooks/update.sample", filemode); - - assert_hooks_match( - cl_fixture("template"), git_repository_path(_repo), - "hooks/link.sample", filemode); -} - -void test_repo_init__extended_with_template_and_shared_mode(void) -{ - git_buf expected = GIT_BUF_INIT; - git_buf actual = GIT_BUF_INIT; - git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; - int filemode = true; - const char *repo_path = NULL; - - cl_set_cleanup(&cleanup_repository, "init_shared_from_tpl"); - - opts.flags = GIT_REPOSITORY_INIT_MKPATH | - GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; - opts.template_path = cl_fixture("template"); - opts.mode = GIT_REPOSITORY_INIT_SHARED_GROUP; - - cl_git_pass(git_repository_init_ext(&_repo, "init_shared_from_tpl", &opts)); - - cl_assert(!git_repository_is_bare(_repo)); - cl_assert(!git__suffixcmp(git_repository_path(_repo), "/init_shared_from_tpl/.git/")); - - filemode = cl_repo_get_bool(_repo, "core.filemode"); - - cl_git_pass(git_futils_readbuffer( - &expected, cl_fixture("template/description"))); - cl_git_pass(git_futils_readbuffer( - &actual, "init_shared_from_tpl/.git/description")); - - cl_assert_equal_s(expected.ptr, actual.ptr); - - git_buf_free(&expected); - git_buf_free(&actual); - - repo_path = git_repository_path(_repo); - assert_mode_seems_okay(repo_path, "hooks", - GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode); - assert_mode_seems_okay(repo_path, "info", - GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode); - assert_mode_seems_okay(repo_path, "description", - GIT_FILEMODE_BLOB, false, filemode); - - /* for a non-symlinked hook, it should have shared permissions now */ - assert_hooks_match( - cl_fixture("template"), git_repository_path(_repo), - "hooks/update.sample", filemode); - - /* for a symlinked hook, the permissions still should match the - * source link, not the GIT_REPOSITORY_INIT_SHARED_GROUP value - */ - assert_hooks_match( - cl_fixture("template"), git_repository_path(_repo), - "hooks/link.sample", filemode); -} - -void test_repo_init__can_reinit_an_initialized_repository(void) -{ - git_repository *reinit; - - cl_set_cleanup(&cleanup_repository, "extended"); - - cl_git_pass(git_futils_mkdir("extended", NULL, 0775, 0)); - cl_git_pass(git_repository_init(&_repo, "extended", false)); - - cl_git_pass(git_repository_init(&reinit, "extended", false)); - - cl_assert_equal_s(git_repository_path(_repo), git_repository_path(reinit)); - - git_repository_free(reinit); -} - -void test_repo_init__init_with_initial_commit(void) -{ - git_index *index; - - cl_set_cleanup(&cleanup_repository, "committed"); - - /* Initialize the repository */ - cl_git_pass(git_repository_init(&_repo, "committed", 0)); - - /* Init will be automatically created when requested for a new repo */ - cl_git_pass(git_repository_index(&index, _repo)); - - /* Create a file so we can commit it - * - * If you are writing code outside the test suite, you can create this - * file any way that you like, such as: - * FILE *fp = fopen("committed/file.txt", "w"); - * fputs("some stuff\n", fp); - * fclose(fp); - * We like to use the help functions because they do error detection - * in a way that's easily compatible with our test suite. - */ - cl_git_mkfile("committed/file.txt", "some stuff\n"); - - /* Add file to the index */ - cl_git_pass(git_index_add_bypath(index, "file.txt")); - cl_git_pass(git_index_write(index)); - - /* Intentionally not using cl_repo_commit_from_index here so this code - * can be used as an example of how an initial commit is typically - * made to a repository... - */ - - /* Make sure we're ready to use git_signature_default :-) */ - { - git_config *cfg, *local; - cl_git_pass(git_repository_config(&cfg, _repo)); - cl_git_pass(git_config_open_level(&local, cfg, GIT_CONFIG_LEVEL_LOCAL)); - cl_git_pass(git_config_set_string(local, "user.name", "Test User")); - cl_git_pass(git_config_set_string(local, "user.email", "t@example.com")); - git_config_free(local); - git_config_free(cfg); - } - - /* Create a commit with the new contents of the index */ - { - git_signature *sig; - git_oid tree_id, commit_id; - git_tree *tree; - - cl_git_pass(git_signature_default(&sig, _repo)); - cl_git_pass(git_index_write_tree(&tree_id, index)); - cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id)); - - cl_git_pass(git_commit_create_v( - &commit_id, _repo, "HEAD", sig, sig, - NULL, "First", tree, 0)); - - git_tree_free(tree); - git_signature_free(sig); - } - - git_index_free(index); -} diff --git a/tests-clar/repo/iterator.c b/tests-clar/repo/iterator.c deleted file mode 100644 index 56b51852c..000000000 --- a/tests-clar/repo/iterator.c +++ /dev/null @@ -1,962 +0,0 @@ -#include "clar_libgit2.h" -#include "iterator.h" -#include "repository.h" -#include "fileops.h" -#include - -static git_repository *g_repo; - -void test_repo_iterator__initialize(void) -{ -} - -void test_repo_iterator__cleanup(void) -{ - cl_git_sandbox_cleanup(); - g_repo = NULL; -} - -static void expect_iterator_items( - git_iterator *i, - int expected_flat, - const char **expected_flat_paths, - int expected_total, - const char **expected_total_paths) -{ - const git_index_entry *entry; - int count, error; - int no_trees = !(git_iterator_flags(i) & GIT_ITERATOR_INCLUDE_TREES); - bool v = false; - - if (expected_flat < 0) { v = true; expected_flat = -expected_flat; } - if (expected_total < 0) { v = true; expected_total = -expected_total; } - - if (v) fprintf(stderr, "== %s ==\n", no_trees ? "notrees" : "trees"); - - count = 0; - - while (!git_iterator_advance(&entry, i)) { - if (v) fprintf(stderr, " %s %07o\n", entry->path, (int)entry->mode); - - if (no_trees) - cl_assert(entry->mode != GIT_FILEMODE_TREE); - - if (expected_flat_paths) { - const char *expect_path = expected_flat_paths[count]; - size_t expect_len = strlen(expect_path); - - cl_assert_equal_s(expect_path, entry->path); - - if (expect_path[expect_len - 1] == '/') - cl_assert_equal_i(GIT_FILEMODE_TREE, entry->mode); - else - cl_assert(entry->mode != GIT_FILEMODE_TREE); - } - - if (++count > expected_flat) - break; - } - - cl_assert_equal_i(expected_flat, count); - - cl_git_pass(git_iterator_reset(i, NULL, NULL)); - - count = 0; - cl_git_pass(git_iterator_current(&entry, i)); - - if (v) fprintf(stderr, "-- %s --\n", no_trees ? "notrees" : "trees"); - - while (entry != NULL) { - if (v) fprintf(stderr, " %s %07o\n", entry->path, (int)entry->mode); - - if (no_trees) - cl_assert(entry->mode != GIT_FILEMODE_TREE); - - if (expected_total_paths) { - const char *expect_path = expected_total_paths[count]; - size_t expect_len = strlen(expect_path); - - cl_assert_equal_s(expect_path, entry->path); - - if (expect_path[expect_len - 1] == '/') - cl_assert_equal_i(GIT_FILEMODE_TREE, entry->mode); - else - cl_assert(entry->mode != GIT_FILEMODE_TREE); - } - - if (entry->mode == GIT_FILEMODE_TREE) { - error = git_iterator_advance_into(&entry, i); - - /* could return NOTFOUND if directory is empty */ - cl_assert(!error || error == GIT_ENOTFOUND); - - if (error == GIT_ENOTFOUND) { - error = git_iterator_advance(&entry, i); - cl_assert(!error || error == GIT_ITEROVER); - } - } else { - error = git_iterator_advance(&entry, i); - cl_assert(!error || error == GIT_ITEROVER); - } - - if (++count > expected_total) - break; - } - - cl_assert_equal_i(expected_total, count); -} - -/* Index contents (including pseudotrees): - * - * 0: a 5: F 10: k/ 16: L/ - * 1: B 6: g 11: k/1 17: L/1 - * 2: c 7: H 12: k/a 18: L/a - * 3: D 8: i 13: k/B 19: L/B - * 4: e 9: J 14: k/c 20: L/c - * 15: k/D 21: L/D - * - * 0: B 5: L/ 11: a 16: k/ - * 1: D 6: L/1 12: c 17: k/1 - * 2: F 7: L/B 13: e 18: k/B - * 3: H 8: L/D 14: g 19: k/D - * 4: J 9: L/a 15: i 20: k/a - * 10: L/c 21: k/c - */ - -void test_repo_iterator__index(void) -{ - git_iterator *i; - git_index *index; - - g_repo = cl_git_sandbox_init("icase"); - - cl_git_pass(git_repository_index(&index, g_repo)); - - /* autoexpand with no tree entries for index */ - cl_git_pass(git_iterator_for_index(&i, index, 0, NULL, NULL)); - expect_iterator_items(i, 20, NULL, 20, NULL); - git_iterator_free(i); - - /* auto expand with tree entries */ - cl_git_pass(git_iterator_for_index( - &i, index, GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - expect_iterator_items(i, 22, NULL, 22, NULL); - git_iterator_free(i); - - /* no auto expand (implies trees included) */ - cl_git_pass(git_iterator_for_index( - &i, index, GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); - expect_iterator_items(i, 12, NULL, 22, NULL); - git_iterator_free(i); - - git_index_free(index); -} - -void test_repo_iterator__index_icase(void) -{ - git_iterator *i; - git_index *index; - unsigned int caps; - - g_repo = cl_git_sandbox_init("icase"); - - cl_git_pass(git_repository_index(&index, g_repo)); - caps = git_index_caps(index); - - /* force case sensitivity */ - cl_git_pass(git_index_set_caps(index, caps & ~GIT_INDEXCAP_IGNORE_CASE)); - - /* autoexpand with no tree entries over range */ - cl_git_pass(git_iterator_for_index(&i, index, 0, "c", "k/D")); - expect_iterator_items(i, 7, NULL, 7, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_index(&i, index, 0, "k", "k/Z")); - expect_iterator_items(i, 3, NULL, 3, NULL); - git_iterator_free(i); - - /* auto expand with tree entries */ - cl_git_pass(git_iterator_for_index( - &i, index, GIT_ITERATOR_INCLUDE_TREES, "c", "k/D")); - expect_iterator_items(i, 8, NULL, 8, NULL); - git_iterator_free(i); - cl_git_pass(git_iterator_for_index( - &i, index, GIT_ITERATOR_INCLUDE_TREES, "k", "k/Z")); - expect_iterator_items(i, 4, NULL, 4, NULL); - git_iterator_free(i); - - /* no auto expand (implies trees included) */ - cl_git_pass(git_iterator_for_index( - &i, index, GIT_ITERATOR_DONT_AUTOEXPAND, "c", "k/D")); - expect_iterator_items(i, 5, NULL, 8, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_index( - &i, index, GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); - expect_iterator_items(i, 1, NULL, 4, NULL); - git_iterator_free(i); - - /* force case insensitivity */ - cl_git_pass(git_index_set_caps(index, caps | GIT_INDEXCAP_IGNORE_CASE)); - - /* autoexpand with no tree entries over range */ - cl_git_pass(git_iterator_for_index(&i, index, 0, "c", "k/D")); - expect_iterator_items(i, 13, NULL, 13, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_index(&i, index, 0, "k", "k/Z")); - expect_iterator_items(i, 5, NULL, 5, NULL); - git_iterator_free(i); - - /* auto expand with tree entries */ - cl_git_pass(git_iterator_for_index( - &i, index, GIT_ITERATOR_INCLUDE_TREES, "c", "k/D")); - expect_iterator_items(i, 14, NULL, 14, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_index( - &i, index, GIT_ITERATOR_INCLUDE_TREES, "k", "k/Z")); - expect_iterator_items(i, 6, NULL, 6, NULL); - git_iterator_free(i); - - /* no auto expand (implies trees included) */ - cl_git_pass(git_iterator_for_index( - &i, index, GIT_ITERATOR_DONT_AUTOEXPAND, "c", "k/D")); - expect_iterator_items(i, 9, NULL, 14, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_index( - &i, index, GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); - expect_iterator_items(i, 1, NULL, 6, NULL); - git_iterator_free(i); - - cl_git_pass(git_index_set_caps(index, caps)); - git_index_free(index); -} - -void test_repo_iterator__tree(void) -{ - git_iterator *i; - git_tree *head; - - g_repo = cl_git_sandbox_init("icase"); - - cl_git_pass(git_repository_head_tree(&head, g_repo)); - - /* auto expand with no tree entries */ - cl_git_pass(git_iterator_for_tree(&i, head, 0, NULL, NULL)); - expect_iterator_items(i, 20, NULL, 20, NULL); - git_iterator_free(i); - - /* auto expand with tree entries */ - cl_git_pass(git_iterator_for_tree( - &i, head, GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - expect_iterator_items(i, 22, NULL, 22, NULL); - git_iterator_free(i); - - /* no auto expand (implies trees included) */ - cl_git_pass(git_iterator_for_tree( - &i, head, GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); - expect_iterator_items(i, 12, NULL, 22, NULL); - git_iterator_free(i); - - git_tree_free(head); -} - -void test_repo_iterator__tree_icase(void) -{ - git_iterator *i; - git_tree *head; - git_iterator_flag_t flag; - - g_repo = cl_git_sandbox_init("icase"); - - cl_git_pass(git_repository_head_tree(&head, g_repo)); - - flag = GIT_ITERATOR_DONT_IGNORE_CASE; - - /* auto expand with no tree entries */ - cl_git_pass(git_iterator_for_tree(&i, head, flag, "c", "k/D")); - expect_iterator_items(i, 7, NULL, 7, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree(&i, head, flag, "k", "k/Z")); - expect_iterator_items(i, 3, NULL, 3, NULL); - git_iterator_free(i); - - /* auto expand with tree entries */ - cl_git_pass(git_iterator_for_tree( - &i, head, flag | GIT_ITERATOR_INCLUDE_TREES, "c", "k/D")); - expect_iterator_items(i, 8, NULL, 8, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree( - &i, head, flag | GIT_ITERATOR_INCLUDE_TREES, "k", "k/Z")); - expect_iterator_items(i, 4, NULL, 4, NULL); - git_iterator_free(i); - - /* no auto expand (implies trees included) */ - cl_git_pass(git_iterator_for_tree( - &i, head, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "c", "k/D")); - expect_iterator_items(i, 5, NULL, 8, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree( - &i, head, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); - expect_iterator_items(i, 1, NULL, 4, NULL); - git_iterator_free(i); - - flag = GIT_ITERATOR_IGNORE_CASE; - - /* auto expand with no tree entries */ - cl_git_pass(git_iterator_for_tree(&i, head, flag, "c", "k/D")); - expect_iterator_items(i, 13, NULL, 13, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree(&i, head, flag, "k", "k/Z")); - expect_iterator_items(i, 5, NULL, 5, NULL); - git_iterator_free(i); - - /* auto expand with tree entries */ - cl_git_pass(git_iterator_for_tree( - &i, head, flag | GIT_ITERATOR_INCLUDE_TREES, "c", "k/D")); - expect_iterator_items(i, 14, NULL, 14, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree( - &i, head, flag | GIT_ITERATOR_INCLUDE_TREES, "k", "k/Z")); - expect_iterator_items(i, 6, NULL, 6, NULL); - git_iterator_free(i); - - /* no auto expand (implies trees included) */ - cl_git_pass(git_iterator_for_tree( - &i, head, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "c", "k/D")); - expect_iterator_items(i, 9, NULL, 14, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree( - &i, head, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); - expect_iterator_items(i, 1, NULL, 6, NULL); - git_iterator_free(i); - - git_tree_free(head); -} - -void test_repo_iterator__tree_more(void) -{ - git_iterator *i; - git_tree *head; - static const char *expect_basic[] = { - "current_file", - "file_deleted", - "modified_file", - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_file_deleted", - "staged_delete_modified_file", - "subdir.txt", - "subdir/current_file", - "subdir/deleted_file", - "subdir/modified_file", - NULL, - }; - static const char *expect_trees[] = { - "current_file", - "file_deleted", - "modified_file", - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_file_deleted", - "staged_delete_modified_file", - "subdir.txt", - "subdir/", - "subdir/current_file", - "subdir/deleted_file", - "subdir/modified_file", - NULL, - }; - static const char *expect_noauto[] = { - "current_file", - "file_deleted", - "modified_file", - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_file_deleted", - "staged_delete_modified_file", - "subdir.txt", - "subdir/", - NULL - }; - - g_repo = cl_git_sandbox_init("status"); - - cl_git_pass(git_repository_head_tree(&head, g_repo)); - - /* auto expand with no tree entries */ - cl_git_pass(git_iterator_for_tree(&i, head, 0, NULL, NULL)); - expect_iterator_items(i, 12, expect_basic, 12, expect_basic); - git_iterator_free(i); - - /* auto expand with tree entries */ - cl_git_pass(git_iterator_for_tree( - &i, head, GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - expect_iterator_items(i, 13, expect_trees, 13, expect_trees); - git_iterator_free(i); - - /* no auto expand (implies trees included) */ - cl_git_pass(git_iterator_for_tree( - &i, head, GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); - expect_iterator_items(i, 10, expect_noauto, 13, expect_trees); - git_iterator_free(i); - - git_tree_free(head); -} - -/* "b=name,t=name", blob_id, tree_id */ -static void build_test_tree( - git_oid *out, git_repository *repo, const char *fmt, ...) -{ - git_oid *id; - git_treebuilder *builder; - const char *scan = fmt, *next; - char type, delimiter; - git_filemode_t mode = GIT_FILEMODE_BLOB; - git_buf name = GIT_BUF_INIT; - va_list arglist; - - cl_git_pass(git_treebuilder_create(&builder, NULL)); /* start builder */ - - va_start(arglist, fmt); - while (*scan) { - switch (type = *scan++) { - case 't': case 'T': mode = GIT_FILEMODE_TREE; break; - case 'b': case 'B': mode = GIT_FILEMODE_BLOB; break; - default: - cl_assert(type == 't' || type == 'T' || type == 'b' || type == 'B'); - } - - delimiter = *scan++; /* read and skip delimiter */ - for (next = scan; *next && *next != delimiter; ++next) - /* seek end */; - cl_git_pass(git_buf_set(&name, scan, (size_t)(next - scan))); - for (scan = next; *scan && (*scan == delimiter || *scan == ','); ++scan) - /* skip delimiter and optional comma */; - - id = va_arg(arglist, git_oid *); - - cl_git_pass(git_treebuilder_insert(NULL, builder, name.ptr, id, mode)); - } - va_end(arglist); - - cl_git_pass(git_treebuilder_write(out, repo, builder)); - - git_treebuilder_free(builder); - git_buf_free(&name); -} - -void test_repo_iterator__tree_case_conflicts_0(void) -{ - const char *blob_sha = "d44e18fb93b7107b5cd1b95d601591d77869a1b6"; - git_tree *tree; - git_oid blob_id, biga_id, littlea_id, tree_id; - git_iterator *i; - const char *expect_cs[] = { - "A/1.file", "A/3.file", "a/2.file", "a/4.file" }; - const char *expect_ci[] = { - "A/1.file", "a/2.file", "A/3.file", "a/4.file" }; - const char *expect_cs_trees[] = { - "A/", "A/1.file", "A/3.file", "a/", "a/2.file", "a/4.file" }; - const char *expect_ci_trees[] = { - "A/", "A/1.file", "a/2.file", "A/3.file", "a/4.file" }; - - g_repo = cl_git_sandbox_init("icase"); - - cl_git_pass(git_oid_fromstr(&blob_id, blob_sha)); /* lookup blob */ - - /* create tree with: A/1.file, A/3.file, a/2.file, a/4.file */ - build_test_tree( - &biga_id, g_repo, "b|1.file|,b|3.file|", &blob_id, &blob_id); - build_test_tree( - &littlea_id, g_repo, "b|2.file|,b|4.file|", &blob_id, &blob_id); - build_test_tree( - &tree_id, g_repo, "t|A|,t|a|", &biga_id, &littlea_id); - - cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); - - cl_git_pass(git_iterator_for_tree( - &i, tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)); - expect_iterator_items(i, 4, expect_cs, 4, expect_cs); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree( - &i, tree, GIT_ITERATOR_IGNORE_CASE, NULL, NULL)); - expect_iterator_items(i, 4, expect_ci, 4, expect_ci); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree( - &i, tree, GIT_ITERATOR_DONT_IGNORE_CASE | - GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - expect_iterator_items(i, 6, expect_cs_trees, 6, expect_cs_trees); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree( - &i, tree, GIT_ITERATOR_IGNORE_CASE | - GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - expect_iterator_items(i, 5, expect_ci_trees, 5, expect_ci_trees); - git_iterator_free(i); - - git_tree_free(tree); -} - -void test_repo_iterator__tree_case_conflicts_1(void) -{ - const char *blob_sha = "d44e18fb93b7107b5cd1b95d601591d77869a1b6"; - git_tree *tree; - git_oid blob_id, Ab_id, biga_id, littlea_id, tree_id; - git_iterator *i; - const char *expect_cs[] = { - "A/a", "A/b/1", "A/c", "a/C", "a/a", "a/b" }; - const char *expect_ci[] = { - "A/a", "a/b", "A/b/1", "A/c" }; - const char *expect_cs_trees[] = { - "A/", "A/a", "A/b/", "A/b/1", "A/c", "a/", "a/C", "a/a", "a/b" }; - const char *expect_ci_trees[] = { - "A/", "A/a", "a/b", "A/b/", "A/b/1", "A/c" }; - - g_repo = cl_git_sandbox_init("icase"); - - cl_git_pass(git_oid_fromstr(&blob_id, blob_sha)); /* lookup blob */ - - /* create: A/a A/b/1 A/c a/a a/b a/C */ - build_test_tree(&Ab_id, g_repo, "b|1|", &blob_id); - build_test_tree( - &biga_id, g_repo, "b|a|,t|b|,b|c|", &blob_id, &Ab_id, &blob_id); - build_test_tree( - &littlea_id, g_repo, "b|a|,b|b|,b|C|", &blob_id, &blob_id, &blob_id); - build_test_tree( - &tree_id, g_repo, "t|A|,t|a|", &biga_id, &littlea_id); - - cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); - - cl_git_pass(git_iterator_for_tree( - &i, tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)); - expect_iterator_items(i, 6, expect_cs, 6, expect_cs); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree( - &i, tree, GIT_ITERATOR_IGNORE_CASE, NULL, NULL)); - expect_iterator_items(i, 4, expect_ci, 4, expect_ci); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree( - &i, tree, GIT_ITERATOR_DONT_IGNORE_CASE | - GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - expect_iterator_items(i, 9, expect_cs_trees, 9, expect_cs_trees); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree( - &i, tree, GIT_ITERATOR_IGNORE_CASE | - GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - expect_iterator_items(i, 6, expect_ci_trees, 6, expect_ci_trees); - git_iterator_free(i); - - git_tree_free(tree); -} - -void test_repo_iterator__tree_case_conflicts_2(void) -{ - const char *blob_sha = "d44e18fb93b7107b5cd1b95d601591d77869a1b6"; - git_tree *tree; - git_oid blob_id, d1, d2, c1, c2, b1, b2, a1, a2, tree_id; - git_iterator *i; - const char *expect_cs[] = { - "A/B/C/D/16", "A/B/C/D/foo", "A/B/C/d/15", "A/B/C/d/FOO", - "A/B/c/D/14", "A/B/c/D/foo", "A/B/c/d/13", "A/B/c/d/FOO", - "A/b/C/D/12", "A/b/C/D/foo", "A/b/C/d/11", "A/b/C/d/FOO", - "A/b/c/D/10", "A/b/c/D/foo", "A/b/c/d/09", "A/b/c/d/FOO", - "a/B/C/D/08", "a/B/C/D/foo", "a/B/C/d/07", "a/B/C/d/FOO", - "a/B/c/D/06", "a/B/c/D/foo", "a/B/c/d/05", "a/B/c/d/FOO", - "a/b/C/D/04", "a/b/C/D/foo", "a/b/C/d/03", "a/b/C/d/FOO", - "a/b/c/D/02", "a/b/c/D/foo", "a/b/c/d/01", "a/b/c/d/FOO", }; - const char *expect_ci[] = { - "a/b/c/d/01", "a/b/c/D/02", "a/b/C/d/03", "a/b/C/D/04", - "a/B/c/d/05", "a/B/c/D/06", "a/B/C/d/07", "a/B/C/D/08", - "A/b/c/d/09", "A/b/c/D/10", "A/b/C/d/11", "A/b/C/D/12", - "A/B/c/d/13", "A/B/c/D/14", "A/B/C/d/15", "A/B/C/D/16", - "A/B/C/D/foo", }; - const char *expect_ci_trees[] = { - "A/", "A/B/", "A/B/C/", "A/B/C/D/", - "a/b/c/d/01", "a/b/c/D/02", "a/b/C/d/03", "a/b/C/D/04", - "a/B/c/d/05", "a/B/c/D/06", "a/B/C/d/07", "a/B/C/D/08", - "A/b/c/d/09", "A/b/c/D/10", "A/b/C/d/11", "A/b/C/D/12", - "A/B/c/d/13", "A/B/c/D/14", "A/B/C/d/15", "A/B/C/D/16", - "A/B/C/D/foo", }; - - g_repo = cl_git_sandbox_init("icase"); - - cl_git_pass(git_oid_fromstr(&blob_id, blob_sha)); /* lookup blob */ - - build_test_tree(&d1, g_repo, "b|16|,b|foo|", &blob_id, &blob_id); - build_test_tree(&d2, g_repo, "b|15|,b|FOO|", &blob_id, &blob_id); - build_test_tree(&c1, g_repo, "t|D|,t|d|", &d1, &d2); - build_test_tree(&d1, g_repo, "b|14|,b|foo|", &blob_id, &blob_id); - build_test_tree(&d2, g_repo, "b|13|,b|FOO|", &blob_id, &blob_id); - build_test_tree(&c2, g_repo, "t|D|,t|d|", &d1, &d2); - build_test_tree(&b1, g_repo, "t|C|,t|c|", &c1, &c2); - - build_test_tree(&d1, g_repo, "b|12|,b|foo|", &blob_id, &blob_id); - build_test_tree(&d2, g_repo, "b|11|,b|FOO|", &blob_id, &blob_id); - build_test_tree(&c1, g_repo, "t|D|,t|d|", &d1, &d2); - build_test_tree(&d1, g_repo, "b|10|,b|foo|", &blob_id, &blob_id); - build_test_tree(&d2, g_repo, "b|09|,b|FOO|", &blob_id, &blob_id); - build_test_tree(&c2, g_repo, "t|D|,t|d|", &d1, &d2); - build_test_tree(&b2, g_repo, "t|C|,t|c|", &c1, &c2); - - build_test_tree(&a1, g_repo, "t|B|,t|b|", &b1, &b2); - - build_test_tree(&d1, g_repo, "b|08|,b|foo|", &blob_id, &blob_id); - build_test_tree(&d2, g_repo, "b|07|,b|FOO|", &blob_id, &blob_id); - build_test_tree(&c1, g_repo, "t|D|,t|d|", &d1, &d2); - build_test_tree(&d1, g_repo, "b|06|,b|foo|", &blob_id, &blob_id); - build_test_tree(&d2, g_repo, "b|05|,b|FOO|", &blob_id, &blob_id); - build_test_tree(&c2, g_repo, "t|D|,t|d|", &d1, &d2); - build_test_tree(&b1, g_repo, "t|C|,t|c|", &c1, &c2); - - build_test_tree(&d1, g_repo, "b|04|,b|foo|", &blob_id, &blob_id); - build_test_tree(&d2, g_repo, "b|03|,b|FOO|", &blob_id, &blob_id); - build_test_tree(&c1, g_repo, "t|D|,t|d|", &d1, &d2); - build_test_tree(&d1, g_repo, "b|02|,b|foo|", &blob_id, &blob_id); - build_test_tree(&d2, g_repo, "b|01|,b|FOO|", &blob_id, &blob_id); - build_test_tree(&c2, g_repo, "t|D|,t|d|", &d1, &d2); - build_test_tree(&b2, g_repo, "t|C|,t|c|", &c1, &c2); - - build_test_tree(&a2, g_repo, "t|B|,t|b|", &b1, &b2); - - build_test_tree(&tree_id, g_repo, "t/A/,t/a/", &a1, &a2); - - cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); - - cl_git_pass(git_iterator_for_tree( - &i, tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)); - expect_iterator_items(i, 32, expect_cs, 32, expect_cs); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree( - &i, tree, GIT_ITERATOR_IGNORE_CASE, NULL, NULL)); - expect_iterator_items(i, 17, expect_ci, 17, expect_ci); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_tree( - &i, tree, GIT_ITERATOR_IGNORE_CASE | - GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - expect_iterator_items(i, 21, expect_ci_trees, 21, expect_ci_trees); - git_iterator_free(i); - - git_tree_free(tree); -} - -void test_repo_iterator__workdir(void) -{ - git_iterator *i; - - g_repo = cl_git_sandbox_init("icase"); - - /* auto expand with no tree entries */ - cl_git_pass(git_iterator_for_workdir(&i, g_repo, 0, NULL, NULL)); - expect_iterator_items(i, 20, NULL, 20, NULL); - git_iterator_free(i); - - /* auto expand with tree entries */ - cl_git_pass(git_iterator_for_workdir( - &i, g_repo, GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - expect_iterator_items(i, 22, NULL, 22, NULL); - git_iterator_free(i); - - /* no auto expand (implies trees included) */ - cl_git_pass(git_iterator_for_workdir( - &i, g_repo, GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); - expect_iterator_items(i, 12, NULL, 22, NULL); - git_iterator_free(i); -} - -void test_repo_iterator__workdir_icase(void) -{ - git_iterator *i; - git_iterator_flag_t flag; - - g_repo = cl_git_sandbox_init("icase"); - - flag = GIT_ITERATOR_DONT_IGNORE_CASE; - - /* auto expand with no tree entries */ - cl_git_pass(git_iterator_for_workdir(&i, g_repo, flag, "c", "k/D")); - expect_iterator_items(i, 7, NULL, 7, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_workdir(&i, g_repo, flag, "k", "k/Z")); - expect_iterator_items(i, 3, NULL, 3, NULL); - git_iterator_free(i); - - /* auto expand with tree entries */ - cl_git_pass(git_iterator_for_workdir( - &i, g_repo, flag | GIT_ITERATOR_INCLUDE_TREES, "c", "k/D")); - expect_iterator_items(i, 8, NULL, 8, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_workdir( - &i, g_repo, flag | GIT_ITERATOR_INCLUDE_TREES, "k", "k/Z")); - expect_iterator_items(i, 4, NULL, 4, NULL); - git_iterator_free(i); - - /* no auto expand (implies trees included) */ - cl_git_pass(git_iterator_for_workdir( - &i, g_repo, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "c", "k/D")); - expect_iterator_items(i, 5, NULL, 8, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_workdir( - &i, g_repo, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); - expect_iterator_items(i, 1, NULL, 4, NULL); - git_iterator_free(i); - - flag = GIT_ITERATOR_IGNORE_CASE; - - /* auto expand with no tree entries */ - cl_git_pass(git_iterator_for_workdir(&i, g_repo, flag, "c", "k/D")); - expect_iterator_items(i, 13, NULL, 13, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_workdir(&i, g_repo, flag, "k", "k/Z")); - expect_iterator_items(i, 5, NULL, 5, NULL); - git_iterator_free(i); - - /* auto expand with tree entries */ - cl_git_pass(git_iterator_for_workdir( - &i, g_repo, flag | GIT_ITERATOR_INCLUDE_TREES, "c", "k/D")); - expect_iterator_items(i, 14, NULL, 14, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_workdir( - &i, g_repo, flag | GIT_ITERATOR_INCLUDE_TREES, "k", "k/Z")); - expect_iterator_items(i, 6, NULL, 6, NULL); - git_iterator_free(i); - - /* no auto expand (implies trees included) */ - cl_git_pass(git_iterator_for_workdir( - &i, g_repo, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "c", "k/D")); - expect_iterator_items(i, 9, NULL, 14, NULL); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_workdir( - &i, g_repo, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); - expect_iterator_items(i, 1, NULL, 6, NULL); - git_iterator_free(i); -} - -static void build_workdir_tree(const char *root, int dirs, int subs) -{ - int i, j; - char buf[64], sub[64]; - - for (i = 0; i < dirs; ++i) { - if (i % 2 == 0) { - p_snprintf(buf, sizeof(buf), "%s/dir%02d", root, i); - cl_git_pass(git_futils_mkdir(buf, NULL, 0775, GIT_MKDIR_PATH)); - - p_snprintf(buf, sizeof(buf), "%s/dir%02d/file", root, i); - cl_git_mkfile(buf, buf); - buf[strlen(buf) - 5] = '\0'; - } else { - p_snprintf(buf, sizeof(buf), "%s/DIR%02d", root, i); - cl_git_pass(git_futils_mkdir(buf, NULL, 0775, GIT_MKDIR_PATH)); - } - - for (j = 0; j < subs; ++j) { - switch (j % 4) { - case 0: p_snprintf(sub, sizeof(sub), "%s/sub%02d", buf, j); break; - case 1: p_snprintf(sub, sizeof(sub), "%s/sUB%02d", buf, j); break; - case 2: p_snprintf(sub, sizeof(sub), "%s/Sub%02d", buf, j); break; - case 3: p_snprintf(sub, sizeof(sub), "%s/SUB%02d", buf, j); break; - } - cl_git_pass(git_futils_mkdir(sub, NULL, 0775, GIT_MKDIR_PATH)); - - if (j % 2 == 0) { - size_t sublen = strlen(sub); - memcpy(&sub[sublen], "/file", sizeof("/file")); - cl_git_mkfile(sub, sub); - sub[sublen] = '\0'; - } - } - } -} - -void test_repo_iterator__workdir_depth(void) -{ - git_iterator *iter; - - g_repo = cl_git_sandbox_init("icase"); - - build_workdir_tree("icase", 10, 10); - build_workdir_tree("icase/DIR01/sUB01", 50, 0); - build_workdir_tree("icase/dir02/sUB01", 50, 0); - - /* auto expand with no tree entries */ - cl_git_pass(git_iterator_for_workdir(&iter, g_repo, 0, NULL, NULL)); - expect_iterator_items(iter, 125, NULL, 125, NULL); - git_iterator_free(iter); - - /* auto expand with tree entries (empty dirs silently skipped) */ - cl_git_pass(git_iterator_for_workdir( - &iter, g_repo, GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - expect_iterator_items(iter, 337, NULL, 337, NULL); - git_iterator_free(iter); -} - -void test_repo_iterator__fs(void) -{ - git_iterator *i; - static const char *expect_base[] = { - "DIR01/Sub02/file", - "DIR01/sub00/file", - "current_file", - "dir00/Sub02/file", - "dir00/file", - "dir00/sub00/file", - "modified_file", - "new_file", - NULL, - }; - static const char *expect_trees[] = { - "DIR01/", - "DIR01/SUB03/", - "DIR01/Sub02/", - "DIR01/Sub02/file", - "DIR01/sUB01/", - "DIR01/sub00/", - "DIR01/sub00/file", - "current_file", - "dir00/", - "dir00/SUB03/", - "dir00/Sub02/", - "dir00/Sub02/file", - "dir00/file", - "dir00/sUB01/", - "dir00/sub00/", - "dir00/sub00/file", - "modified_file", - "new_file", - NULL, - }; - static const char *expect_noauto[] = { - "DIR01/", - "current_file", - "dir00/", - "modified_file", - "new_file", - NULL, - }; - - g_repo = cl_git_sandbox_init("status"); - - build_workdir_tree("status/subdir", 2, 4); - - cl_git_pass(git_iterator_for_filesystem( - &i, "status/subdir", 0, NULL, NULL)); - expect_iterator_items(i, 8, expect_base, 8, expect_base); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_filesystem( - &i, "status/subdir", GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - expect_iterator_items(i, 18, expect_trees, 18, expect_trees); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_filesystem( - &i, "status/subdir", GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); - expect_iterator_items(i, 5, expect_noauto, 18, expect_trees); - git_iterator_free(i); - - git__tsort((void **)expect_base, 8, (git__tsort_cmp)git__strcasecmp); - git__tsort((void **)expect_trees, 18, (git__tsort_cmp)git__strcasecmp); - git__tsort((void **)expect_noauto, 5, (git__tsort_cmp)git__strcasecmp); - - cl_git_pass(git_iterator_for_filesystem( - &i, "status/subdir", GIT_ITERATOR_IGNORE_CASE, NULL, NULL)); - expect_iterator_items(i, 8, expect_base, 8, expect_base); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_filesystem( - &i, "status/subdir", GIT_ITERATOR_IGNORE_CASE | - GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - expect_iterator_items(i, 18, expect_trees, 18, expect_trees); - git_iterator_free(i); - - cl_git_pass(git_iterator_for_filesystem( - &i, "status/subdir", GIT_ITERATOR_IGNORE_CASE | - GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); - expect_iterator_items(i, 5, expect_noauto, 18, expect_trees); - git_iterator_free(i); -} - -void test_repo_iterator__fs2(void) -{ - git_iterator *i; - static const char *expect_base[] = { - "heads/br2", - "heads/dir", - "heads/long-file-name", - "heads/master", - "heads/packed-test", - "heads/subtrees", - "heads/test", - "tags/e90810b", - "tags/foo/bar", - "tags/foo/foo/bar", - "tags/point_to_blob", - "tags/test", - NULL, - }; - - g_repo = cl_git_sandbox_init("testrepo"); - - cl_git_pass(git_iterator_for_filesystem( - &i, "testrepo/.git/refs", 0, NULL, NULL)); - expect_iterator_items(i, 12, expect_base, 12, expect_base); - git_iterator_free(i); -} - -void test_repo_iterator__fs_preserves_error(void) -{ - git_iterator *i; - const git_index_entry *e; - - if (!cl_is_chmod_supported()) - return; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_must_pass(p_mkdir("empty_standard_repo/r", 0777)); - cl_git_mkfile("empty_standard_repo/r/a", "hello"); - cl_must_pass(p_mkdir("empty_standard_repo/r/b", 0777)); - cl_git_mkfile("empty_standard_repo/r/b/problem", "not me"); - cl_must_pass(p_chmod("empty_standard_repo/r/b", 0000)); - cl_must_pass(p_mkdir("empty_standard_repo/r/c", 0777)); - cl_git_mkfile("empty_standard_repo/r/d", "final"); - - cl_git_pass(git_iterator_for_filesystem( - &i, "empty_standard_repo/r", 0, NULL, NULL)); - - cl_git_pass(git_iterator_advance(&e, i)); /* a */ - cl_git_fail(git_iterator_advance(&e, i)); /* b */ - cl_assert(giterr_last()); - cl_assert(giterr_last()->message != NULL); - /* skip 'c/' empty directory */ - cl_git_pass(git_iterator_advance(&e, i)); /* d */ - cl_assert_equal_i(GIT_ITEROVER, git_iterator_advance(&e, i)); - - cl_must_pass(p_chmod("empty_standard_repo/r/b", 0777)); - - git_iterator_free(i); -} diff --git a/tests-clar/repo/message.c b/tests-clar/repo/message.c deleted file mode 100644 index 629d40c12..000000000 --- a/tests-clar/repo/message.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "refs.h" -#include "posix.h" - -static git_repository *_repo; -static git_buf _path; -static char *_actual; - -void test_repo_message__initialize(void) -{ - _repo = cl_git_sandbox_init("testrepo.git"); -} - -void test_repo_message__cleanup(void) -{ - cl_git_sandbox_cleanup(); - git_buf_free(&_path); - git__free(_actual); - _actual = NULL; -} - -void test_repo_message__none(void) -{ - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(NULL, 0, _repo)); -} - -void test_repo_message__message(void) -{ - const char expected[] = "Test\n\nThis is a test of the emergency broadcast system\n"; - ssize_t len; - - cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), "MERGE_MSG")); - cl_git_mkfile(git_buf_cstr(&_path), expected); - - len = git_repository_message(NULL, 0, _repo); - cl_assert(len > 0); - - _actual = git__malloc(len + 1); - cl_assert(_actual != NULL); - - /* Test non truncation */ - cl_assert(git_repository_message(_actual, len, _repo) > 0); - cl_assert_equal_s(expected, _actual); - - /* Test truncation and that trailing NUL is inserted */ - cl_assert(git_repository_message(_actual, 6, _repo) > 0); - cl_assert_equal_s("Test\n", _actual); - - cl_git_pass(p_unlink(git_buf_cstr(&_path))); - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(NULL, 0, _repo)); -} diff --git a/tests-clar/repo/open.c b/tests-clar/repo/open.c deleted file mode 100644 index 7cfe041c2..000000000 --- a/tests-clar/repo/open.c +++ /dev/null @@ -1,376 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include - -void test_repo_open__cleanup(void) -{ - cl_git_sandbox_cleanup(); - - if (git_path_isdir("alternate")) - git_futils_rmdir_r("alternate", NULL, GIT_RMDIR_REMOVE_FILES); -} - -void test_repo_open__bare_empty_repo(void) -{ - git_repository *repo = cl_git_sandbox_init("empty_bare.git"); - - cl_assert(git_repository_path(repo) != NULL); - cl_assert(git__suffixcmp(git_repository_path(repo), "/") == 0); - cl_assert(git_repository_workdir(repo) == NULL); -} - -void test_repo_open__standard_empty_repo_through_gitdir(void) -{ - git_repository *repo; - - cl_git_pass(git_repository_open(&repo, cl_fixture("empty_standard_repo/.gitted"))); - - cl_assert(git_repository_path(repo) != NULL); - cl_assert(git__suffixcmp(git_repository_path(repo), "/") == 0); - - cl_assert(git_repository_workdir(repo) != NULL); - cl_assert(git__suffixcmp(git_repository_workdir(repo), "/") == 0); - - git_repository_free(repo); -} - -void test_repo_open__standard_empty_repo_through_workdir(void) -{ - git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_assert(git_repository_path(repo) != NULL); - cl_assert(git__suffixcmp(git_repository_path(repo), "/") == 0); - - cl_assert(git_repository_workdir(repo) != NULL); - cl_assert(git__suffixcmp(git_repository_workdir(repo), "/") == 0); -} - - -void test_repo_open__open_with_discover(void) -{ - static const char *variants[] = { - "attr", "attr/", "attr/.git", "attr/.git/", - "attr/sub", "attr/sub/", "attr/sub/sub", "attr/sub/sub/", - NULL - }; - git_repository *repo; - const char **scan; - - cl_fixture_sandbox("attr"); - cl_git_pass(p_rename("attr/.gitted", "attr/.git")); - - for (scan = variants; *scan != NULL; scan++) { - cl_git_pass(git_repository_open_ext(&repo, *scan, 0, NULL)); - cl_assert(git__suffixcmp(git_repository_path(repo), "attr/.git/") == 0); - cl_assert(git__suffixcmp(git_repository_workdir(repo), "attr/") == 0); - git_repository_free(repo); - } - - cl_fixture_cleanup("attr"); -} - -static void make_gitlink_dir(const char *dir, const char *linktext) -{ - git_buf path = GIT_BUF_INIT; - - cl_git_pass(git_futils_mkdir(dir, NULL, 0777, GIT_MKDIR_VERIFY_DIR)); - cl_git_pass(git_buf_joinpath(&path, dir, ".git")); - cl_git_rewritefile(path.ptr, linktext); - git_buf_free(&path); -} - -void test_repo_open__gitlinked(void) -{ - /* need to have both repo dir and workdir set up correctly */ - git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); - git_repository *repo2; - - make_gitlink_dir("alternate", "gitdir: ../empty_standard_repo/.git"); - - cl_git_pass(git_repository_open(&repo2, "alternate")); - - cl_assert(git_repository_path(repo2) != NULL); - cl_assert_(git__suffixcmp(git_repository_path(repo2), "empty_standard_repo/.git/") == 0, git_repository_path(repo2)); - cl_assert_equal_s(git_repository_path(repo), git_repository_path(repo2)); - - cl_assert(git_repository_workdir(repo2) != NULL); - cl_assert_(git__suffixcmp(git_repository_workdir(repo2), "alternate/") == 0, git_repository_workdir(repo2)); - - git_repository_free(repo2); -} - -void test_repo_open__from_git_new_workdir(void) -{ - /* The git-new-workdir script that ships with git sets up a bunch of - * symlinks to create a second workdir that shares the object db with - * another checkout. Libgit2 can open a repo that has been configured - * this way. - */ - cl_git_sandbox_init("empty_standard_repo"); - -#ifndef GIT_WIN32 - git_repository *repo2; - git_buf link_tgt = GIT_BUF_INIT, link = GIT_BUF_INIT, body = GIT_BUF_INIT; - const char **scan; - int link_fd; - static const char *links[] = { - "config", "refs", "logs/refs", "objects", "info", "hooks", - "packed-refs", "remotes", "rr-cache", "svn", NULL - }; - static const char *copies[] = { - "HEAD", NULL - }; - - cl_git_pass(p_mkdir("alternate", 0777)); - cl_git_pass(p_mkdir("alternate/.git", 0777)); - - for (scan = links; *scan != NULL; scan++) { - git_buf_joinpath(&link_tgt, "empty_standard_repo/.git", *scan); - if (git_path_exists(link_tgt.ptr)) { - git_buf_joinpath(&link_tgt, "../../empty_standard_repo/.git", *scan); - git_buf_joinpath(&link, "alternate/.git", *scan); - if (strchr(*scan, '/')) - git_futils_mkpath2file(link.ptr, 0777); - cl_assert_(symlink(link_tgt.ptr, link.ptr) == 0, strerror(errno)); - } - } - for (scan = copies; *scan != NULL; scan++) { - git_buf_joinpath(&link_tgt, "empty_standard_repo/.git", *scan); - if (git_path_exists(link_tgt.ptr)) { - git_buf_joinpath(&link, "alternate/.git", *scan); - cl_git_pass(git_futils_readbuffer(&body, link_tgt.ptr)); - - cl_assert((link_fd = git_futils_creat_withpath(link.ptr, 0777, 0666)) >= 0); - cl_must_pass(p_write(link_fd, body.ptr, body.size)); - p_close(link_fd); - } - } - - git_buf_free(&link_tgt); - git_buf_free(&link); - git_buf_free(&body); - - - cl_git_pass(git_repository_open(&repo2, "alternate")); - - cl_assert(git_repository_path(repo2) != NULL); - cl_assert_(git__suffixcmp(git_repository_path(repo2), "alternate/.git/") == 0, git_repository_path(repo2)); - - cl_assert(git_repository_workdir(repo2) != NULL); - cl_assert_(git__suffixcmp(git_repository_workdir(repo2), "alternate/") == 0, git_repository_workdir(repo2)); - - git_repository_free(repo2); -#endif -} - -void test_repo_open__failures(void) -{ - git_repository *base, *repo; - git_buf ceiling = GIT_BUF_INIT; - - base = cl_git_sandbox_init("attr"); - cl_git_pass(git_buf_sets(&ceiling, git_repository_workdir(base))); - - /* fail with no searching */ - cl_git_fail(git_repository_open(&repo, "attr/sub")); - cl_git_fail(git_repository_open_ext( - &repo, "attr/sub", GIT_REPOSITORY_OPEN_NO_SEARCH, NULL)); - - /* fail with ceiling too low */ - cl_git_pass(git_buf_joinpath(&ceiling, ceiling.ptr, "sub")); - cl_git_fail(git_repository_open_ext(&repo, "attr/sub", 0, ceiling.ptr)); - - /* fail with no repo */ - cl_git_pass(p_mkdir("alternate", 0777)); - cl_git_pass(p_mkdir("alternate/.git", 0777)); - cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL)); - cl_git_fail(git_repository_open_ext(&repo, "alternate/.git", 0, NULL)); - - git_buf_free(&ceiling); -} - -void test_repo_open__bad_gitlinks(void) -{ - git_repository *repo; - static const char *bad_links[] = { - "garbage\n", "gitdir", "gitdir:\n", "gitdir: foobar", - "gitdir: ../invalid", "gitdir: ../invalid2", - "gitdir: ../attr/.git with extra stuff", - NULL - }; - const char **scan; - - cl_git_sandbox_init("attr"); - - cl_git_pass(p_mkdir("invalid", 0777)); - cl_git_pass(git_futils_mkdir_r("invalid2/.git", NULL, 0777)); - - for (scan = bad_links; *scan != NULL; scan++) { - make_gitlink_dir("alternate", *scan); - cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL)); - } - - git_futils_rmdir_r("invalid", NULL, GIT_RMDIR_REMOVE_FILES); - git_futils_rmdir_r("invalid2", NULL, GIT_RMDIR_REMOVE_FILES); -} - -#ifdef GIT_WIN32 -static void unposix_path(git_buf *path) -{ - char *src, *tgt; - - src = tgt = path->ptr; - - /* convert "/d/..." to "d:\..." */ - if (src[0] == '/' && isalpha(src[1]) && src[2] == '/') { - *tgt++ = src[1]; - *tgt++ = ':'; - *tgt++ = '\\'; - src += 3; - } - - while (*src) { - *tgt++ = (*src == '/') ? '\\' : *src; - src++; - } - - *tgt = '\0'; -} -#endif - -void test_repo_open__win32_path(void) -{ -#ifdef GIT_WIN32 - git_repository *repo = cl_git_sandbox_init("empty_standard_repo"), *repo2; - git_buf winpath = GIT_BUF_INIT; - static const char *repo_path = "empty_standard_repo/.git/"; - static const char *repo_wd = "empty_standard_repo/"; - - cl_assert(git__suffixcmp(git_repository_path(repo), repo_path) == 0); - cl_assert(git__suffixcmp(git_repository_workdir(repo), repo_wd) == 0); - - cl_git_pass(git_buf_sets(&winpath, git_repository_path(repo))); - unposix_path(&winpath); - cl_git_pass(git_repository_open(&repo2, winpath.ptr)); - cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0); - cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0); - git_repository_free(repo2); - - cl_git_pass(git_buf_sets(&winpath, git_repository_path(repo))); - git_buf_truncate(&winpath, winpath.size - 1); /* remove trailing '/' */ - unposix_path(&winpath); - cl_git_pass(git_repository_open(&repo2, winpath.ptr)); - cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0); - cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0); - git_repository_free(repo2); - - cl_git_pass(git_buf_sets(&winpath, git_repository_workdir(repo))); - unposix_path(&winpath); - cl_git_pass(git_repository_open(&repo2, winpath.ptr)); - cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0); - cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0); - git_repository_free(repo2); - - cl_git_pass(git_buf_sets(&winpath, git_repository_workdir(repo))); - git_buf_truncate(&winpath, winpath.size - 1); /* remove trailing '/' */ - unposix_path(&winpath); - cl_git_pass(git_repository_open(&repo2, winpath.ptr)); - cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0); - cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0); - git_repository_free(repo2); - - git_buf_free(&winpath); -#endif -} - -void test_repo_open__opening_a_non_existing_repository_returns_ENOTFOUND(void) -{ - git_repository *repo; - cl_assert_equal_i(GIT_ENOTFOUND, git_repository_open(&repo, "i-do-not/exist")); -} - -void test_repo_open__no_config(void) -{ - git_buf path = GIT_BUF_INIT; - git_repository *repo; - git_config *config; - - cl_fixture_sandbox("empty_standard_repo"); - cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git")); - - /* remove local config */ - cl_git_pass(git_futils_rmdir_r( - "empty_standard_repo/.git/config", NULL, GIT_RMDIR_REMOVE_FILES)); - - /* isolate from system level configs */ - cl_must_pass(p_mkdir("alternate", 0777)); - cl_git_pass(git_path_prettify(&path, "alternate", NULL)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); - cl_git_pass(git_libgit2_opts( - GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); - - git_buf_free(&path); - - cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); - cl_git_pass(git_repository_config(&config, repo)); - - cl_git_pass(git_config_set_string(config, "test.set", "42")); - - git_config_free(config); - git_repository_free(repo); - cl_fixture_cleanup("empty_standard_repo"); - - git_futils_dirs_global_shutdown(); -} - -void test_repo_open__force_bare(void) -{ - /* need to have both repo dir and workdir set up correctly */ - git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); - git_repository *barerepo; - - make_gitlink_dir("alternate", "gitdir: ../empty_standard_repo/.git"); - - cl_assert(!git_repository_is_bare(repo)); - - cl_git_pass(git_repository_open(&barerepo, "alternate")); - cl_assert(!git_repository_is_bare(barerepo)); - git_repository_free(barerepo); - - cl_git_pass(git_repository_open_bare( - &barerepo, "empty_standard_repo/.git")); - cl_assert(git_repository_is_bare(barerepo)); - git_repository_free(barerepo); - - cl_git_fail(git_repository_open_bare(&barerepo, "alternate/.git")); - - cl_git_pass(git_repository_open_ext( - &barerepo, "alternate/.git", GIT_REPOSITORY_OPEN_BARE, NULL)); - cl_assert(git_repository_is_bare(barerepo)); - git_repository_free(barerepo); - - cl_git_pass(p_mkdir("empty_standard_repo/subdir", 0777)); - cl_git_mkfile("empty_standard_repo/subdir/something.txt", "something"); - - cl_git_fail(git_repository_open_bare( - &barerepo, "empty_standard_repo/subdir")); - - cl_git_pass(git_repository_open_ext( - &barerepo, "empty_standard_repo/subdir", GIT_REPOSITORY_OPEN_BARE, NULL)); - cl_assert(git_repository_is_bare(barerepo)); - git_repository_free(barerepo); - - cl_git_pass(p_mkdir("alternate/subdir", 0777)); - cl_git_pass(p_mkdir("alternate/subdir/sub2", 0777)); - cl_git_mkfile("alternate/subdir/sub2/something.txt", "something"); - - cl_git_fail(git_repository_open_bare(&barerepo, "alternate/subdir/sub2")); - - cl_git_pass(git_repository_open_ext( - &barerepo, "alternate/subdir/sub2", GIT_REPOSITORY_OPEN_BARE, NULL)); - cl_assert(git_repository_is_bare(barerepo)); - git_repository_free(barerepo); -} diff --git a/tests-clar/repo/pathspec.c b/tests-clar/repo/pathspec.c deleted file mode 100644 index 334066b67..000000000 --- a/tests-clar/repo/pathspec.c +++ /dev/null @@ -1,385 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/pathspec.h" - -static git_repository *g_repo; - -void test_repo_pathspec__initialize(void) -{ - g_repo = cl_git_sandbox_init("status"); -} - -void test_repo_pathspec__cleanup(void) -{ - cl_git_sandbox_cleanup(); - g_repo = NULL; -} - -static char *str0[] = { "*_file", "new_file", "garbage" }; -static char *str1[] = { "*_FILE", "NEW_FILE", "GARBAGE" }; -static char *str2[] = { "staged_*" }; -static char *str3[] = { "!subdir", "*_file", "new_file" }; -static char *str4[] = { "*" }; -static char *str5[] = { "S*" }; - -void test_repo_pathspec__workdir0(void) -{ - git_strarray s; - git_pathspec *ps; - git_pathspec_match_list *m; - - /* { "*_file", "new_file", "garbage" } */ - s.strings = str0; s.count = ARRAY_SIZE(str0); - cl_git_pass(git_pathspec_new(&ps, &s)); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, 0, ps)); - cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); - git_pathspec_match_list_free(m); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, - GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); - cl_assert_equal_s("garbage", git_pathspec_match_list_failed_entry(m, 0)); - git_pathspec_match_list_free(m); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, - GIT_PATHSPEC_FIND_FAILURES | GIT_PATHSPEC_FAILURES_ONLY, ps)); - cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); - git_pathspec_match_list_free(m); - - git_pathspec_free(ps); -} - -void test_repo_pathspec__workdir1(void) -{ - git_strarray s; - git_pathspec *ps; - git_pathspec_match_list *m; - - /* { "*_FILE", "NEW_FILE", "GARBAGE" } */ - s.strings = str1; s.count = ARRAY_SIZE(str1); - cl_git_pass(git_pathspec_new(&ps, &s)); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, - GIT_PATHSPEC_IGNORE_CASE, ps)); - cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); - git_pathspec_match_list_free(m); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, - GIT_PATHSPEC_USE_CASE, ps)); - cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); - git_pathspec_match_list_free(m); - - cl_git_fail(git_pathspec_match_workdir(&m, g_repo, - GIT_PATHSPEC_USE_CASE | GIT_PATHSPEC_NO_MATCH_ERROR, ps)); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, - GIT_PATHSPEC_IGNORE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); - git_pathspec_match_list_free(m); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, - GIT_PATHSPEC_USE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(3, git_pathspec_match_list_failed_entrycount(m)); - git_pathspec_match_list_free(m); - - git_pathspec_free(ps); -} - -void test_repo_pathspec__workdir2(void) -{ - git_strarray s; - git_pathspec *ps; - git_pathspec_match_list *m; - - /* { "staged_*" } */ - s.strings = str2; s.count = ARRAY_SIZE(str2); - cl_git_pass(git_pathspec_new(&ps, &s)); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, 0, ps)); - cl_assert_equal_sz(5, git_pathspec_match_list_entrycount(m)); - git_pathspec_match_list_free(m); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, - GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(5, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); - git_pathspec_match_list_free(m); - - cl_git_fail(git_pathspec_match_workdir(&m, g_repo, - GIT_PATHSPEC_NO_GLOB | GIT_PATHSPEC_NO_MATCH_ERROR, ps)); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, - GIT_PATHSPEC_NO_GLOB | GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); - git_pathspec_match_list_free(m); - - git_pathspec_free(ps); -} - -void test_repo_pathspec__workdir3(void) -{ - git_strarray s; - git_pathspec *ps; - git_pathspec_match_list *m; - - /* { "!subdir", "*_file", "new_file" } */ - s.strings = str3; s.count = ARRAY_SIZE(str3); - cl_git_pass(git_pathspec_new(&ps, &s)); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, 0, ps)); - cl_assert_equal_sz(7, git_pathspec_match_list_entrycount(m)); - git_pathspec_match_list_free(m); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, - GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(7, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); - - cl_assert_equal_s("current_file", git_pathspec_match_list_entry(m, 0)); - cl_assert_equal_s("modified_file", git_pathspec_match_list_entry(m, 1)); - cl_assert_equal_s("new_file", git_pathspec_match_list_entry(m, 2)); - cl_assert_equal_s("staged_changes_modified_file", git_pathspec_match_list_entry(m, 3)); - cl_assert_equal_s("staged_delete_modified_file", git_pathspec_match_list_entry(m, 4)); - cl_assert_equal_s("staged_new_file", git_pathspec_match_list_entry(m, 5)); - cl_assert_equal_s("staged_new_file_modified_file", git_pathspec_match_list_entry(m, 6)); - cl_assert_equal_s(NULL, git_pathspec_match_list_entry(m, 7)); - - git_pathspec_match_list_free(m); - - git_pathspec_free(ps); -} - -void test_repo_pathspec__workdir4(void) -{ - git_strarray s; - git_pathspec *ps; - git_pathspec_match_list *m; - - /* { "*" } */ - s.strings = str4; s.count = ARRAY_SIZE(str4); - cl_git_pass(git_pathspec_new(&ps, &s)); - - cl_git_pass(git_pathspec_match_workdir(&m, g_repo, 0, ps)); - cl_assert_equal_sz(13, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_s("这", git_pathspec_match_list_entry(m, 12)); - git_pathspec_match_list_free(m); - - git_pathspec_free(ps); -} - - -void test_repo_pathspec__index0(void) -{ - git_index *idx; - git_strarray s; - git_pathspec *ps; - git_pathspec_match_list *m; - - cl_git_pass(git_repository_index(&idx, g_repo)); - - /* { "*_file", "new_file", "garbage" } */ - s.strings = str0; s.count = ARRAY_SIZE(str0); - cl_git_pass(git_pathspec_new(&ps, &s)); - - cl_git_pass(git_pathspec_match_index(&m, idx, 0, ps)); - cl_assert_equal_sz(9, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); - cl_assert_equal_s("current_file", git_pathspec_match_list_entry(m, 0)); - cl_assert_equal_s("modified_file", git_pathspec_match_list_entry(m, 1)); - cl_assert_equal_s("staged_changes_modified_file", git_pathspec_match_list_entry(m, 2)); - cl_assert_equal_s("staged_new_file", git_pathspec_match_list_entry(m, 3)); - cl_assert_equal_s("staged_new_file_deleted_file", git_pathspec_match_list_entry(m, 4)); - cl_assert_equal_s("staged_new_file_modified_file", git_pathspec_match_list_entry(m, 5)); - cl_assert_equal_s("subdir/current_file", git_pathspec_match_list_entry(m, 6)); - cl_assert_equal_s("subdir/deleted_file", git_pathspec_match_list_entry(m, 7)); - cl_assert_equal_s("subdir/modified_file", git_pathspec_match_list_entry(m, 8)); - cl_assert_equal_s(NULL, git_pathspec_match_list_entry(m, 9)); - git_pathspec_match_list_free(m); - - cl_git_pass(git_pathspec_match_index(&m, idx, - GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(9, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(2, git_pathspec_match_list_failed_entrycount(m)); - cl_assert_equal_s("new_file", git_pathspec_match_list_failed_entry(m, 0)); - cl_assert_equal_s("garbage", git_pathspec_match_list_failed_entry(m, 1)); - cl_assert_equal_s(NULL, git_pathspec_match_list_failed_entry(m, 2)); - git_pathspec_match_list_free(m); - - git_pathspec_free(ps); - git_index_free(idx); -} - -void test_repo_pathspec__index1(void) -{ - /* Currently the USE_CASE and IGNORE_CASE flags don't work on the - * index because the index sort order for the index iterator is - * set by the index itself. I think the correct fix is for the - * index not to embed a global sort order but to support traversal - * in either case sensitive or insensitive order in a stateless - * manner. - * - * Anyhow, as it is, there is no point in doing this test. - */ -#if 0 - git_index *idx; - git_strarray s; - git_pathspec *ps; - git_pathspec_match_list *m; - - cl_git_pass(git_repository_index(&idx, g_repo)); - - /* { "*_FILE", "NEW_FILE", "GARBAGE" } */ - s.strings = str1; s.count = ARRAY_SIZE(str1); - cl_git_pass(git_pathspec_new(&ps, &s)); - - cl_git_pass(git_pathspec_match_index(&m, idx, - GIT_PATHSPEC_USE_CASE, ps)); - cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); - git_pathspec_match_list_free(m); - - cl_git_pass(git_pathspec_match_index(&m, idx, - GIT_PATHSPEC_USE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(3, git_pathspec_match_list_failed_entrycount(m)); - git_pathspec_match_list_free(m); - - cl_git_pass(git_pathspec_match_index(&m, idx, - GIT_PATHSPEC_IGNORE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(2, git_pathspec_match_list_failed_entrycount(m)); - git_pathspec_match_list_free(m); - - git_pathspec_free(ps); - git_index_free(idx); -#endif -} - -void test_repo_pathspec__tree0(void) -{ - git_object *tree; - git_strarray s; - git_pathspec *ps; - git_pathspec_match_list *m; - - /* { "*_file", "new_file", "garbage" } */ - s.strings = str0; s.count = ARRAY_SIZE(str0); - cl_git_pass(git_pathspec_new(&ps, &s)); - - cl_git_pass(git_revparse_single(&tree, g_repo, "HEAD~2^{tree}")); - - cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, - GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(4, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_s("current_file", git_pathspec_match_list_entry(m, 0)); - cl_assert_equal_s("modified_file", git_pathspec_match_list_entry(m, 1)); - cl_assert_equal_s("staged_changes_modified_file", git_pathspec_match_list_entry(m, 2)); - cl_assert_equal_s("staged_delete_modified_file", git_pathspec_match_list_entry(m, 3)); - cl_assert_equal_s(NULL, git_pathspec_match_list_entry(m, 4)); - cl_assert_equal_sz(2, git_pathspec_match_list_failed_entrycount(m)); - cl_assert_equal_s("new_file", git_pathspec_match_list_failed_entry(m, 0)); - cl_assert_equal_s("garbage", git_pathspec_match_list_failed_entry(m, 1)); - cl_assert_equal_s(NULL, git_pathspec_match_list_failed_entry(m, 2)); - git_pathspec_match_list_free(m); - - git_object_free(tree); - - cl_git_pass(git_revparse_single(&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, - GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(7, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_s("current_file", git_pathspec_match_list_entry(m, 0)); - cl_assert_equal_s("modified_file", git_pathspec_match_list_entry(m, 1)); - cl_assert_equal_s("staged_changes_modified_file", git_pathspec_match_list_entry(m, 2)); - cl_assert_equal_s("staged_delete_modified_file", git_pathspec_match_list_entry(m, 3)); - cl_assert_equal_s("subdir/current_file", git_pathspec_match_list_entry(m, 4)); - cl_assert_equal_s("subdir/deleted_file", git_pathspec_match_list_entry(m, 5)); - cl_assert_equal_s("subdir/modified_file", git_pathspec_match_list_entry(m, 6)); - cl_assert_equal_s(NULL, git_pathspec_match_list_entry(m, 7)); - cl_assert_equal_sz(2, git_pathspec_match_list_failed_entrycount(m)); - cl_assert_equal_s("new_file", git_pathspec_match_list_failed_entry(m, 0)); - cl_assert_equal_s("garbage", git_pathspec_match_list_failed_entry(m, 1)); - cl_assert_equal_s(NULL, git_pathspec_match_list_failed_entry(m, 2)); - git_pathspec_match_list_free(m); - - git_object_free(tree); - - git_pathspec_free(ps); -} - -void test_repo_pathspec__tree5(void) -{ - git_object *tree; - git_strarray s; - git_pathspec *ps; - git_pathspec_match_list *m; - - /* { "S*" } */ - s.strings = str5; s.count = ARRAY_SIZE(str5); - cl_git_pass(git_pathspec_new(&ps, &s)); - - cl_git_pass(git_revparse_single(&tree, g_repo, "HEAD~2^{tree}")); - - cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, - GIT_PATHSPEC_USE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); - git_pathspec_match_list_free(m); - - cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, - GIT_PATHSPEC_IGNORE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(5, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_s("staged_changes", git_pathspec_match_list_entry(m, 0)); - cl_assert_equal_s("staged_delete_modified_file", git_pathspec_match_list_entry(m, 4)); - cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); - git_pathspec_match_list_free(m); - - git_object_free(tree); - - cl_git_pass(git_revparse_single(&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, - GIT_PATHSPEC_IGNORE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); - cl_assert_equal_sz(9, git_pathspec_match_list_entrycount(m)); - cl_assert_equal_s("staged_changes", git_pathspec_match_list_entry(m, 0)); - cl_assert_equal_s("subdir.txt", git_pathspec_match_list_entry(m, 5)); - cl_assert_equal_s("subdir/current_file", git_pathspec_match_list_entry(m, 6)); - cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); - git_pathspec_match_list_free(m); - - git_object_free(tree); - - git_pathspec_free(ps); -} - -void test_repo_pathspec__in_memory(void) -{ - static char *strings[] = { "one", "two*", "!three*", "*four" }; - git_strarray s = { strings, ARRAY_SIZE(strings) }; - git_pathspec *ps; - - cl_git_pass(git_pathspec_new(&ps, &s)); - - cl_assert(git_pathspec_matches_path(ps, 0, "one")); - cl_assert(!git_pathspec_matches_path(ps, 0, "ONE")); - cl_assert(git_pathspec_matches_path(ps, GIT_PATHSPEC_IGNORE_CASE, "ONE")); - cl_assert(git_pathspec_matches_path(ps, 0, "two")); - cl_assert(git_pathspec_matches_path(ps, 0, "two.txt")); - cl_assert(!git_pathspec_matches_path(ps, 0, "three.txt")); - cl_assert(git_pathspec_matches_path(ps, 0, "anything.four")); - cl_assert(!git_pathspec_matches_path(ps, 0, "three.four")); - cl_assert(!git_pathspec_matches_path(ps, 0, "nomatch")); - cl_assert(!git_pathspec_matches_path(ps, GIT_PATHSPEC_NO_GLOB, "two")); - cl_assert(git_pathspec_matches_path(ps, GIT_PATHSPEC_NO_GLOB, "two*")); - cl_assert(!git_pathspec_matches_path(ps, GIT_PATHSPEC_NO_GLOB, "anyfour")); - cl_assert(git_pathspec_matches_path(ps, GIT_PATHSPEC_NO_GLOB, "*four")); - - git_pathspec_free(ps); -} diff --git a/tests-clar/repo/repo_helpers.c b/tests-clar/repo/repo_helpers.c deleted file mode 100644 index 3d477ff42..000000000 --- a/tests-clar/repo/repo_helpers.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "clar_libgit2.h" -#include "refs.h" -#include "repo_helpers.h" -#include "posix.h" - -void make_head_unborn(git_repository* repo, const char *target) -{ - git_reference *head; - - cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, target, 1)); - git_reference_free(head); -} - -void delete_head(git_repository* repo) -{ - git_buf head_path = GIT_BUF_INIT; - - cl_git_pass(git_buf_joinpath(&head_path, git_repository_path(repo), GIT_HEAD_FILE)); - cl_git_pass(p_unlink(git_buf_cstr(&head_path))); - - git_buf_free(&head_path); -} diff --git a/tests-clar/repo/repo_helpers.h b/tests-clar/repo/repo_helpers.h deleted file mode 100644 index 6783d5701..000000000 --- a/tests-clar/repo/repo_helpers.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "common.h" - -#define NON_EXISTING_HEAD "refs/heads/hide/and/seek" - -extern void make_head_unborn(git_repository* repo, const char *target); -extern void delete_head(git_repository* repo); diff --git a/tests-clar/repo/setters.c b/tests-clar/repo/setters.c deleted file mode 100644 index f34f1e471..000000000 --- a/tests-clar/repo/setters.c +++ /dev/null @@ -1,107 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/sys/repository.h" - -#include "buffer.h" -#include "posix.h" -#include "util.h" -#include "path.h" -#include "fileops.h" - -static git_repository *repo; - -void test_repo_setters__initialize(void) -{ - cl_fixture_sandbox("testrepo.git"); - cl_git_pass(git_repository_open(&repo, "testrepo.git")); - cl_must_pass(p_mkdir("new_workdir", 0777)); -} - -void test_repo_setters__cleanup(void) -{ - git_repository_free(repo); - repo = NULL; - - cl_fixture_cleanup("testrepo.git"); - cl_fixture_cleanup("new_workdir"); -} - -void test_repo_setters__setting_a_workdir_turns_a_bare_repository_into_a_standard_one(void) -{ - cl_assert(git_repository_is_bare(repo) == 1); - - cl_assert(git_repository_workdir(repo) == NULL); - cl_git_pass(git_repository_set_workdir(repo, "./new_workdir", false)); - - cl_assert(git_repository_workdir(repo) != NULL); - cl_assert(git_repository_is_bare(repo) == 0); -} - -void test_repo_setters__setting_a_workdir_prettifies_its_path(void) -{ - cl_git_pass(git_repository_set_workdir(repo, "./new_workdir", false)); - - cl_assert(git__suffixcmp(git_repository_workdir(repo), "new_workdir/") == 0); -} - -void test_repo_setters__setting_a_workdir_creates_a_gitlink(void) -{ - git_config *cfg; - const char *val; - git_buf content = GIT_BUF_INIT; - - cl_git_pass(git_repository_set_workdir(repo, "./new_workdir", true)); - - cl_assert(git_path_isfile("./new_workdir/.git")); - - cl_git_pass(git_futils_readbuffer(&content, "./new_workdir/.git")); - cl_assert(git__prefixcmp(git_buf_cstr(&content), "gitdir: ") == 0); - cl_assert(git__suffixcmp(git_buf_cstr(&content), "testrepo.git/") == 0); - git_buf_free(&content); - - cl_git_pass(git_repository_config(&cfg, repo)); - cl_git_pass(git_config_get_string(&val, cfg, "core.worktree")); - cl_assert(git__suffixcmp(val, "new_workdir/") == 0); - git_config_free(cfg); -} - -void test_repo_setters__setting_a_new_index_on_a_repo_which_has_already_loaded_one_properly_honors_the_refcount(void) -{ - git_index *new_index; - - cl_git_pass(git_index_open(&new_index, "./my-index")); - cl_assert(((git_refcount *)new_index)->refcount.val == 1); - - git_repository_set_index(repo, new_index); - cl_assert(((git_refcount *)new_index)->refcount.val == 2); - - git_repository_free(repo); - cl_assert(((git_refcount *)new_index)->refcount.val == 1); - - git_index_free(new_index); - - /* - * Ensure the cleanup method won't try to free the repo as it's already been taken care of - */ - repo = NULL; -} - -void test_repo_setters__setting_a_new_odb_on_a_repo_which_already_loaded_one_properly_honors_the_refcount(void) -{ - git_odb *new_odb; - - cl_git_pass(git_odb_open(&new_odb, "./testrepo.git/objects")); - cl_assert(((git_refcount *)new_odb)->refcount.val == 1); - - git_repository_set_odb(repo, new_odb); - cl_assert(((git_refcount *)new_odb)->refcount.val == 2); - - git_repository_free(repo); - cl_assert(((git_refcount *)new_odb)->refcount.val == 1); - - git_odb_free(new_odb); - - /* - * Ensure the cleanup method won't try to free the repo as it's already been taken care of - */ - repo = NULL; -} diff --git a/tests-clar/repo/shallow.c b/tests-clar/repo/shallow.c deleted file mode 100644 index 1cc66ae40..000000000 --- a/tests-clar/repo/shallow.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" - -static git_repository *g_repo; - -void test_repo_shallow__initialize(void) -{ -} - -void test_repo_shallow__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_repo_shallow__no_shallow_file(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); -} - -void test_repo_shallow__empty_shallow_file(void) -{ - g_repo = cl_git_sandbox_init("testrepo.git"); - cl_git_mkfile("testrepo.git/shallow", ""); - cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); -} - -void test_repo_shallow__shallow_repo(void) -{ - g_repo = cl_git_sandbox_init("shallow.git"); - cl_assert_equal_i(1, git_repository_is_shallow(g_repo)); -} - diff --git a/tests-clar/repo/state.c b/tests-clar/repo/state.c deleted file mode 100644 index 5a0a5f360..000000000 --- a/tests-clar/repo/state.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "refs.h" -#include "posix.h" -#include "fileops.h" - -static git_repository *_repo; -static git_buf _path; - -void test_repo_state__initialize(void) -{ - _repo = cl_git_sandbox_init("testrepo.git"); -} - -void test_repo_state__cleanup(void) -{ - cl_git_sandbox_cleanup(); - git_buf_free(&_path); -} - -static void setup_simple_state(const char *filename) -{ - cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), filename)); - git_futils_mkpath2file(git_buf_cstr(&_path), 0777); - cl_git_mkfile(git_buf_cstr(&_path), "dummy"); -} - -static void assert_repo_state(git_repository_state_t state) -{ - cl_assert_equal_i(state, git_repository_state(_repo)); -} - -void test_repo_state__none_with_HEAD_attached(void) -{ - assert_repo_state(GIT_REPOSITORY_STATE_NONE); -} - -void test_repo_state__none_with_HEAD_detached(void) -{ - cl_git_pass(git_repository_detach_head(_repo)); - assert_repo_state(GIT_REPOSITORY_STATE_NONE); -} - -void test_repo_state__merge(void) -{ - setup_simple_state(GIT_MERGE_HEAD_FILE); - assert_repo_state(GIT_REPOSITORY_STATE_MERGE); -} - -void test_repo_state__revert(void) -{ - setup_simple_state(GIT_REVERT_HEAD_FILE); - assert_repo_state(GIT_REPOSITORY_STATE_REVERT); -} - -void test_repo_state__cherry_pick(void) -{ - setup_simple_state(GIT_CHERRY_PICK_HEAD_FILE); - assert_repo_state(GIT_REPOSITORY_STATE_CHERRY_PICK); -} - -void test_repo_state__bisect(void) -{ - setup_simple_state(GIT_BISECT_LOG_FILE); - assert_repo_state(GIT_REPOSITORY_STATE_BISECT); -} - -void test_repo_state__rebase_interactive(void) -{ - setup_simple_state(GIT_REBASE_MERGE_INTERACTIVE_FILE); - assert_repo_state(GIT_REPOSITORY_STATE_REBASE_INTERACTIVE); -} - -void test_repo_state__rebase_merge(void) -{ - setup_simple_state(GIT_REBASE_MERGE_DIR "whatever"); - assert_repo_state(GIT_REPOSITORY_STATE_REBASE_MERGE); -} - -void test_repo_state__rebase(void) -{ - setup_simple_state(GIT_REBASE_APPLY_REBASING_FILE); - assert_repo_state(GIT_REPOSITORY_STATE_REBASE); -} - -void test_repo_state__apply_mailbox(void) -{ - setup_simple_state(GIT_REBASE_APPLY_APPLYING_FILE); - assert_repo_state(GIT_REPOSITORY_STATE_APPLY_MAILBOX); -} - -void test_repo_state__apply_mailbox_or_rebase(void) -{ - setup_simple_state(GIT_REBASE_APPLY_DIR "whatever"); - assert_repo_state(GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE); -} diff --git a/tests-clar/reset/default.c b/tests-clar/reset/default.c deleted file mode 100644 index e29e63550..000000000 --- a/tests-clar/reset/default.c +++ /dev/null @@ -1,180 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" -#include "reset_helpers.h" -#include "path.h" - -static git_repository *_repo; -static git_object *_target; -static git_strarray _pathspecs; -static git_index *_index; - -static void initialize(const char *repo_name) -{ - _repo = cl_git_sandbox_init(repo_name); - cl_git_pass(git_repository_index(&_index, _repo)); - - _target = NULL; - - _pathspecs.strings = NULL; - _pathspecs.count = 0; -} - -void test_reset_default__initialize(void) -{ - initialize("status"); -} - -void test_reset_default__cleanup(void) -{ - git_object_free(_target); - _target = NULL; - - git_index_free(_index); - _index = NULL; - - cl_git_sandbox_cleanup(); -} - -static void assert_content_in_index( - git_strarray *pathspecs, - bool should_exist, - git_strarray *expected_shas) -{ - size_t i, pos; - int error; - - for (i = 0; i < pathspecs->count; i++) { - error = git_index_find(&pos, _index, pathspecs->strings[i]); - - if (should_exist) { - const git_index_entry *entry; - - cl_assert(error != GIT_ENOTFOUND); - - entry = git_index_get_byindex(_index, pos); - cl_assert(entry != NULL); - - if (!expected_shas) - continue; - - cl_git_pass(git_oid_streq(&entry->oid, expected_shas->strings[i])); - } else - cl_assert_equal_i(should_exist, error != GIT_ENOTFOUND); - } -} - -void test_reset_default__resetting_filepaths_against_a_null_target_removes_them_from_the_index(void) -{ - char *paths[] = { "staged_changes", "staged_new_file" }; - - _pathspecs.strings = paths; - _pathspecs.count = 2; - - assert_content_in_index(&_pathspecs, true, NULL); - - cl_git_pass(git_reset_default(_repo, NULL, &_pathspecs)); - - assert_content_in_index(&_pathspecs, false, NULL); -} - -/* - * $ git ls-files --cached -s --abbrev=7 -- "staged*" - * 100644 55d316c 0 staged_changes - * 100644 a6be623 0 staged_changes_file_deleted - * ... - * - * $ git reset 0017bd4 -- staged_changes staged_changes_file_deleted - * Unstaged changes after reset: - * ... - * - * $ git ls-files --cached -s --abbrev=7 -- "staged*" - * 100644 32504b7 0 staged_changes - * 100644 061d42a 0 staged_changes_file_deleted - * ... - */ -void test_reset_default__resetting_filepaths_replaces_their_corresponding_index_entries(void) -{ - git_strarray before, after; - - char *paths[] = { "staged_changes", "staged_changes_file_deleted" }; - char *before_shas[] = { "55d316c9ba708999f1918e9677d01dfcae69c6b9", - "a6be623522ce87a1d862128ac42672604f7b468b" }; - char *after_shas[] = { "32504b727382542f9f089e24fddac5e78533e96c", - "061d42a44cacde5726057b67558821d95db96f19" }; - - _pathspecs.strings = paths; - _pathspecs.count = 2; - before.strings = before_shas; - before.count = 2; - after.strings = after_shas; - after.count = 2; - - cl_git_pass(git_revparse_single(&_target, _repo, "0017bd4")); - assert_content_in_index(&_pathspecs, true, &before); - - cl_git_pass(git_reset_default(_repo, _target, &_pathspecs)); - - assert_content_in_index(&_pathspecs, true, &after); -} - -/* - * $ git ls-files --cached -s --abbrev=7 -- conflicts-one.txt - * 100644 1f85ca5 1 conflicts-one.txt - * 100644 6aea5f2 2 conflicts-one.txt - * 100644 516bd85 3 conflicts-one.txt - * - * $ git reset 9a05ccb -- conflicts-one.txt - * Unstaged changes after reset: - * ... - * - * $ git ls-files --cached -s --abbrev=7 -- conflicts-one.txt - * 100644 1f85ca5 0 conflicts-one.txt - * - */ -void test_reset_default__resetting_filepaths_clears_previous_conflicts(void) -{ - const git_index_entry *conflict_entry[3]; - git_strarray after; - - char *paths[] = { "conflicts-one.txt" }; - char *after_shas[] = { "1f85ca51b8e0aac893a621b61a9c2661d6aa6d81" }; - - test_reset_default__cleanup(); - initialize("mergedrepo"); - - _pathspecs.strings = paths; - _pathspecs.count = 1; - after.strings = after_shas; - after.count = 1; - - cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], - &conflict_entry[2], _index, "conflicts-one.txt")); - - cl_git_pass(git_revparse_single(&_target, _repo, "9a05ccb")); - cl_git_pass(git_reset_default(_repo, _target, &_pathspecs)); - - assert_content_in_index(&_pathspecs, true, &after); - - cl_assert_equal_i(GIT_ENOTFOUND, git_index_conflict_get(&conflict_entry[0], - &conflict_entry[1], &conflict_entry[2], _index, "conflicts-one.txt")); -} - -/* -$ git reset HEAD -- "I_am_not_there.txt" "me_neither.txt" -Unstaged changes after reset: -... -*/ -void test_reset_default__resetting_unknown_filepaths_does_not_fail(void) -{ - char *paths[] = { "I_am_not_there.txt", "me_neither.txt" }; - - _pathspecs.strings = paths; - _pathspecs.count = 2; - - assert_content_in_index(&_pathspecs, false, NULL); - - cl_git_pass(git_revparse_single(&_target, _repo, "HEAD")); - cl_git_pass(git_reset_default(_repo, _target, &_pathspecs)); - - assert_content_in_index(&_pathspecs, false, NULL); -} diff --git a/tests-clar/reset/hard.c b/tests-clar/reset/hard.c deleted file mode 100644 index 1c0c84135..000000000 --- a/tests-clar/reset/hard.c +++ /dev/null @@ -1,200 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" -#include "reset_helpers.h" -#include "path.h" -#include "fileops.h" - -static git_repository *repo; -static git_object *target; - -void test_reset_hard__initialize(void) -{ - repo = cl_git_sandbox_init("status"); - target = NULL; -} - -void test_reset_hard__cleanup(void) -{ - if (target != NULL) { - git_object_free(target); - target = NULL; - } - - cl_git_sandbox_cleanup(); -} - -static int strequal_ignore_eol(const char *exp, const char *str) -{ - while (*exp && *str) { - if (*exp != *str) { - while (*exp == '\r' || *exp == '\n') ++exp; - while (*str == '\r' || *str == '\n') ++str; - if (*exp != *str) - return false; - } else { - exp++; str++; - } - } - return (!*exp && !*str); -} - -void test_reset_hard__resetting_reverts_modified_files(void) -{ - git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT; - int i; - static const char *files[4] = { - "current_file", - "modified_file", - "staged_new_file", - "staged_changes_modified_file" }; - static const char *before[4] = { - "current_file\n", - "modified_file\nmodified_file\n", - "staged_new_file\n", - "staged_changes_modified_file\nstaged_changes_modified_file\nstaged_changes_modified_file\n" - }; - static const char *after[4] = { - "current_file\n", - "modified_file\n", - NULL, - "staged_changes_modified_file\n" - }; - const char *wd = git_repository_workdir(repo); - - cl_assert(wd); - - for (i = 0; i < 4; ++i) { - cl_git_pass(git_buf_joinpath(&path, wd, files[i])); - cl_git_pass(git_futils_readbuffer(&content, path.ptr)); - cl_assert_equal_s(before[i], content.ptr); - } - - retrieve_target_from_oid( - &target, repo, "26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f"); - - cl_git_pass(git_reset(repo, target, GIT_RESET_HARD)); - - for (i = 0; i < 4; ++i) { - cl_git_pass(git_buf_joinpath(&path, wd, files[i])); - if (after[i]) { - cl_git_pass(git_futils_readbuffer(&content, path.ptr)); - cl_assert(strequal_ignore_eol(after[i], content.ptr)); - } else { - cl_assert(!git_path_exists(path.ptr)); - } - } - - git_buf_free(&content); - git_buf_free(&path); -} - -void test_reset_hard__cannot_reset_in_a_bare_repository(void) -{ - git_repository *bare; - - cl_git_pass(git_repository_open(&bare, cl_fixture("testrepo.git"))); - cl_assert(git_repository_is_bare(bare) == true); - - retrieve_target_from_oid(&target, bare, KNOWN_COMMIT_IN_BARE_REPO); - - cl_assert_equal_i(GIT_EBAREREPO, git_reset(bare, target, GIT_RESET_HARD)); - - git_repository_free(bare); -} - -static void index_entry_init(git_index *index, int side, git_oid *oid) -{ - git_index_entry entry; - - memset(&entry, 0x0, sizeof(git_index_entry)); - - entry.path = "conflicting_file"; - entry.flags = (side << GIT_IDXENTRY_STAGESHIFT); - entry.mode = 0100644; - git_oid_cpy(&entry.oid, oid); - - cl_git_pass(git_index_add(index, &entry)); -} - -static void unmerged_index_init(git_index *index, int entries) -{ - int write_ancestor = 1; - int write_ours = 2; - int write_theirs = 4; - git_oid ancestor, ours, theirs; - - git_oid_fromstr(&ancestor, "6bb0d9f700543ba3d318ba7075fc3bd696b4287b"); - git_oid_fromstr(&ours, "b19a1e93bec1317dc6097229e12afaffbfa74dc2"); - git_oid_fromstr(&theirs, "950b81b7eee953d050aa05a641f8e056c85dd1bd"); - - cl_git_rewritefile("status/conflicting_file", "conflicting file\n"); - - if (entries & write_ancestor) - index_entry_init(index, 1, &ancestor); - - if (entries & write_ours) - index_entry_init(index, 2, &ours); - - if (entries & write_theirs) - index_entry_init(index, 3, &theirs); -} - -void test_reset_hard__resetting_reverts_unmerged(void) -{ - git_index *index; - int entries; - - /* Ensure every permutation of non-zero stage entries results in the - * path being cleaned up. */ - for (entries = 1; entries < 8; entries++) { - cl_git_pass(git_repository_index(&index, repo)); - - unmerged_index_init(index, entries); - cl_git_pass(git_index_write(index)); - - retrieve_target_from_oid(&target, repo, "26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f"); - cl_git_pass(git_reset(repo, target, GIT_RESET_HARD)); - - cl_assert(git_path_exists("status/conflicting_file") == 0); - - git_object_free(target); - target = NULL; - - git_index_free(index); - } -} - -void test_reset_hard__cleans_up_merge(void) -{ - git_buf merge_head_path = GIT_BUF_INIT, - merge_msg_path = GIT_BUF_INIT, - merge_mode_path = GIT_BUF_INIT, - orig_head_path = GIT_BUF_INIT; - - cl_git_pass(git_buf_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD")); - cl_git_mkfile(git_buf_cstr(&merge_head_path), "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef\n"); - - cl_git_pass(git_buf_joinpath(&merge_msg_path, git_repository_path(repo), "MERGE_MSG")); - cl_git_mkfile(git_buf_cstr(&merge_msg_path), "Merge commit 0017bd4ab1ec30440b17bae1680cff124ab5f1f6\n"); - - cl_git_pass(git_buf_joinpath(&merge_mode_path, git_repository_path(repo), "MERGE_MODE")); - cl_git_mkfile(git_buf_cstr(&merge_mode_path), ""); - - cl_git_pass(git_buf_joinpath(&orig_head_path, git_repository_path(repo), "ORIG_HEAD")); - cl_git_mkfile(git_buf_cstr(&orig_head_path), "0017bd4ab1ec30440b17bae1680cff124ab5f1f6"); - - retrieve_target_from_oid(&target, repo, "0017bd4ab1ec30440b17bae1680cff124ab5f1f6"); - cl_git_pass(git_reset(repo, target, GIT_RESET_HARD)); - - cl_assert(!git_path_exists(git_buf_cstr(&merge_head_path))); - cl_assert(!git_path_exists(git_buf_cstr(&merge_msg_path))); - cl_assert(!git_path_exists(git_buf_cstr(&merge_mode_path))); - - cl_assert(git_path_exists(git_buf_cstr(&orig_head_path))); - cl_git_pass(p_unlink(git_buf_cstr(&orig_head_path))); - - git_buf_free(&merge_head_path); - git_buf_free(&merge_msg_path); - git_buf_free(&merge_mode_path); - git_buf_free(&orig_head_path); -} diff --git a/tests-clar/reset/mixed.c b/tests-clar/reset/mixed.c deleted file mode 100644 index 7b90c23f1..000000000 --- a/tests-clar/reset/mixed.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" -#include "reset_helpers.h" -#include "path.h" - -static git_repository *repo; -static git_object *target; - -void test_reset_mixed__initialize(void) -{ - repo = cl_git_sandbox_init("attr"); - target = NULL; -} - -void test_reset_mixed__cleanup(void) -{ - git_object_free(target); - target = NULL; - - cl_git_sandbox_cleanup(); -} - -void test_reset_mixed__cannot_reset_in_a_bare_repository(void) -{ - git_repository *bare; - - cl_git_pass(git_repository_open(&bare, cl_fixture("testrepo.git"))); - cl_assert(git_repository_is_bare(bare) == true); - - retrieve_target_from_oid(&target, bare, KNOWN_COMMIT_IN_BARE_REPO); - - cl_assert_equal_i(GIT_EBAREREPO, git_reset(bare, target, GIT_RESET_MIXED)); - - git_repository_free(bare); -} - -void test_reset_mixed__resetting_refreshes_the_index_to_the_commit_tree(void) -{ - unsigned int status; - - cl_git_pass(git_status_file(&status, repo, "macro_bad")); - cl_assert(status == GIT_STATUS_CURRENT); - retrieve_target_from_oid(&target, repo, "605812ab7fe421fdd325a935d35cb06a9234a7d7"); - - cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED)); - - cl_git_pass(git_status_file(&status, repo, "macro_bad")); - cl_assert(status == GIT_STATUS_WT_NEW); -} diff --git a/tests-clar/reset/reset_helpers.c b/tests-clar/reset/reset_helpers.c deleted file mode 100644 index 17edca4e9..000000000 --- a/tests-clar/reset/reset_helpers.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "clar_libgit2.h" -#include "reset_helpers.h" - -void retrieve_target_from_oid(git_object **object_out, git_repository *repo, const char *sha) -{ - git_oid oid; - - cl_git_pass(git_oid_fromstr(&oid, sha)); - cl_git_pass(git_object_lookup(object_out, repo, &oid, GIT_OBJ_ANY)); -} diff --git a/tests-clar/reset/reset_helpers.h b/tests-clar/reset/reset_helpers.h deleted file mode 100644 index 5dbe9d2c7..000000000 --- a/tests-clar/reset/reset_helpers.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "common.h" - -#define KNOWN_COMMIT_IN_BARE_REPO "e90810b8df3e80c413d903f631643c716887138d" -#define KNOWN_COMMIT_IN_ATTR_REPO "217878ab49e1314388ea2e32dc6fdb58a1b969e0" - -extern void retrieve_target_from_oid(git_object **object_out, git_repository *repo, const char *sha); diff --git a/tests-clar/reset/soft.c b/tests-clar/reset/soft.c deleted file mode 100644 index bd6fcc205..000000000 --- a/tests-clar/reset/soft.c +++ /dev/null @@ -1,157 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" -#include "reset_helpers.h" -#include "path.h" -#include "repo/repo_helpers.h" - -static git_repository *repo; -static git_object *target; - -void test_reset_soft__initialize(void) -{ - repo = cl_git_sandbox_init("testrepo.git"); -} - -void test_reset_soft__cleanup(void) -{ - git_object_free(target); - target = NULL; - - cl_git_sandbox_cleanup(); -} - -static void assert_reset_soft(bool should_be_detached) -{ - git_oid oid; - - cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); - cl_git_fail(git_oid_streq(&oid, KNOWN_COMMIT_IN_BARE_REPO)); - - retrieve_target_from_oid(&target, repo, KNOWN_COMMIT_IN_BARE_REPO); - - cl_assert(git_repository_head_detached(repo) == should_be_detached); - - cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT)); - - cl_assert(git_repository_head_detached(repo) == should_be_detached); - - cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); - cl_git_pass(git_oid_streq(&oid, KNOWN_COMMIT_IN_BARE_REPO)); -} - -void test_reset_soft__can_reset_the_non_detached_Head_to_the_specified_commit(void) -{ - assert_reset_soft(false); -} - -void test_reset_soft__can_reset_the_detached_Head_to_the_specified_commit(void) -{ - git_repository_detach_head(repo); - - assert_reset_soft(true); -} - -void test_reset_soft__resetting_to_the_commit_pointed_at_by_the_Head_does_not_change_the_target_of_the_Head(void) -{ - git_oid oid; - char raw_head_oid[GIT_OID_HEXSZ + 1]; - - cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); - git_oid_fmt(raw_head_oid, &oid); - raw_head_oid[GIT_OID_HEXSZ] = '\0'; - - retrieve_target_from_oid(&target, repo, raw_head_oid); - - cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT)); - - cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); - cl_git_pass(git_oid_streq(&oid, raw_head_oid)); -} - -void test_reset_soft__resetting_to_a_tag_sets_the_Head_to_the_peeled_commit(void) -{ - git_oid oid; - - /* b25fa35 is a tag, pointing to another tag which points to commit e90810b */ - retrieve_target_from_oid(&target, repo, "b25fa35b38051e4ae45d4222e795f9df2e43f1d1"); - - cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT)); - - cl_assert(git_repository_head_detached(repo) == false); - cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); - cl_git_pass(git_oid_streq(&oid, KNOWN_COMMIT_IN_BARE_REPO)); -} - -void test_reset_soft__cannot_reset_to_a_tag_not_pointing_at_a_commit(void) -{ - /* 53fc32d is the tree of commit e90810b */ - retrieve_target_from_oid(&target, repo, "53fc32d17276939fc79ed05badaef2db09990016"); - - cl_git_fail(git_reset(repo, target, GIT_RESET_SOFT)); - git_object_free(target); - - /* 521d87c is an annotated tag pointing to a blob */ - retrieve_target_from_oid(&target, repo, "521d87c1ec3aef9824daf6d96cc0ae3710766d91"); - cl_git_fail(git_reset(repo, target, GIT_RESET_SOFT)); -} - -void test_reset_soft__resetting_against_an_unborn_head_repo_makes_the_head_no_longer_unborn(void) -{ - git_reference *head; - - retrieve_target_from_oid(&target, repo, KNOWN_COMMIT_IN_BARE_REPO); - - make_head_unborn(repo, NON_EXISTING_HEAD); - - cl_assert_equal_i(true, git_repository_head_unborn(repo)); - - cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT)); - - cl_assert_equal_i(false, git_repository_head_unborn(repo)); - - cl_git_pass(git_reference_lookup(&head, repo, NON_EXISTING_HEAD)); - cl_assert_equal_i(0, git_oid_streq(git_reference_target(head), KNOWN_COMMIT_IN_BARE_REPO)); - - git_reference_free(head); -} - -void test_reset_soft__fails_when_merging(void) -{ - git_buf merge_head_path = GIT_BUF_INIT; - - cl_git_pass(git_repository_detach_head(repo)); - cl_git_pass(git_buf_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD")); - cl_git_mkfile(git_buf_cstr(&merge_head_path), "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef\n"); - - retrieve_target_from_oid(&target, repo, KNOWN_COMMIT_IN_BARE_REPO); - - cl_assert_equal_i(GIT_EUNMERGED, git_reset(repo, target, GIT_RESET_SOFT)); - cl_git_pass(p_unlink(git_buf_cstr(&merge_head_path))); - - git_buf_free(&merge_head_path); -} - -void test_reset_soft__fails_when_index_contains_conflicts_independently_of_MERGE_HEAD_file_existence(void) -{ - git_index *index; - git_reference *head; - git_buf merge_head_path = GIT_BUF_INIT; - - cl_git_sandbox_cleanup(); - - repo = cl_git_sandbox_init("mergedrepo"); - - cl_git_pass(git_buf_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD")); - cl_git_pass(p_unlink(git_buf_cstr(&merge_head_path))); - git_buf_free(&merge_head_path); - - cl_git_pass(git_repository_index(&index, repo)); - cl_assert_equal_i(true, git_index_has_conflicts(index)); - git_index_free(index); - - cl_git_pass(git_repository_head(&head, repo)); - cl_git_pass(git_reference_peel(&target, head, GIT_OBJ_COMMIT)); - git_reference_free(head); - - cl_assert_equal_i(GIT_EUNMERGED, git_reset(repo, target, GIT_RESET_SOFT)); -} diff --git a/tests-clar/resources/.gitattributes b/tests-clar/resources/.gitattributes deleted file mode 100644 index 556f8c827..000000000 --- a/tests-clar/resources/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* binary diff --git a/tests-clar/resources/.gitignore b/tests-clar/resources/.gitignore deleted file mode 100644 index 43a19cc9d..000000000 --- a/tests-clar/resources/.gitignore +++ /dev/null @@ -1 +0,0 @@ -discover.git diff --git a/tests-clar/resources/attr/.gitted/HEAD b/tests-clar/resources/attr/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/attr/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/attr/.gitted/config b/tests-clar/resources/attr/.gitted/config deleted file mode 100644 index af107929f..000000000 --- a/tests-clar/resources/attr/.gitted/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true diff --git a/tests-clar/resources/attr/.gitted/description b/tests-clar/resources/attr/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/attr/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/attr/.gitted/index b/tests-clar/resources/attr/.gitted/index deleted file mode 100644 index 439ffb151..000000000 Binary files a/tests-clar/resources/attr/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/info/attributes b/tests-clar/resources/attr/.gitted/info/attributes deleted file mode 100644 index 5fe62a37a..000000000 --- a/tests-clar/resources/attr/.gitted/info/attributes +++ /dev/null @@ -1,4 +0,0 @@ -* repoattr -a* foo !bar -baz -sub/*.txt reposub -sub/sub/*.txt reposubsub diff --git a/tests-clar/resources/attr/.gitted/info/exclude b/tests-clar/resources/attr/.gitted/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/attr/.gitted/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/attr/.gitted/logs/HEAD b/tests-clar/resources/attr/.gitted/logs/HEAD deleted file mode 100644 index 8ece39f37..000000000 --- a/tests-clar/resources/attr/.gitted/logs/HEAD +++ /dev/null @@ -1,9 +0,0 @@ -0000000000000000000000000000000000000000 6bab5c79cd5140d0f800917f550eb2a3dc32b0da Russell Belfer 1324416995 -0800 commit (initial): initial test data -6bab5c79cd5140d0f800917f550eb2a3dc32b0da 605812ab7fe421fdd325a935d35cb06a9234a7d7 Russell Belfer 1325143098 -0800 commit: latest test updates -605812ab7fe421fdd325a935d35cb06a9234a7d7 a5d76cad53f66f1312bd995909a5bab3c0820770 Russell Belfer 1325281762 -0800 commit: more macro tests -a5d76cad53f66f1312bd995909a5bab3c0820770 370fe9ec224ce33e71f9e5ec2bd1142ce9937a6a Russell Belfer 1327611749 -0800 commit: Updating files so we can do diffs -370fe9ec224ce33e71f9e5ec2bd1142ce9937a6a f5b0af1fb4f5c0cd7aad880711d368a07333c307 Russell Belfer 1327621027 -0800 commit: Updating test data -f5b0af1fb4f5c0cd7aad880711d368a07333c307 a97cc019851d401a4f1d091cb91a15890a0dd1ba Russell Belfer 1328653313 -0800 commit: Some whitespace only changes for testing purposes -a97cc019851d401a4f1d091cb91a15890a0dd1ba 217878ab49e1314388ea2e32dc6fdb58a1b969e0 Russell Belfer 1332734901 -0700 commit: added files in sub/sub -217878ab49e1314388ea2e32dc6fdb58a1b969e0 24fa9a9fc4e202313e24b648087495441dab432b Russell Belfer 1332735555 -0700 commit: adding more files in sub for tree status -24fa9a9fc4e202313e24b648087495441dab432b 8d0b9df9bd30be7910ddda60548d485bc302b911 yorah 1341230701 +0200 commit: Updating test data so we can test inter-hunk-context diff --git a/tests-clar/resources/attr/.gitted/logs/refs/heads/master b/tests-clar/resources/attr/.gitted/logs/refs/heads/master deleted file mode 100644 index 8ece39f37..000000000 --- a/tests-clar/resources/attr/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,9 +0,0 @@ -0000000000000000000000000000000000000000 6bab5c79cd5140d0f800917f550eb2a3dc32b0da Russell Belfer 1324416995 -0800 commit (initial): initial test data -6bab5c79cd5140d0f800917f550eb2a3dc32b0da 605812ab7fe421fdd325a935d35cb06a9234a7d7 Russell Belfer 1325143098 -0800 commit: latest test updates -605812ab7fe421fdd325a935d35cb06a9234a7d7 a5d76cad53f66f1312bd995909a5bab3c0820770 Russell Belfer 1325281762 -0800 commit: more macro tests -a5d76cad53f66f1312bd995909a5bab3c0820770 370fe9ec224ce33e71f9e5ec2bd1142ce9937a6a Russell Belfer 1327611749 -0800 commit: Updating files so we can do diffs -370fe9ec224ce33e71f9e5ec2bd1142ce9937a6a f5b0af1fb4f5c0cd7aad880711d368a07333c307 Russell Belfer 1327621027 -0800 commit: Updating test data -f5b0af1fb4f5c0cd7aad880711d368a07333c307 a97cc019851d401a4f1d091cb91a15890a0dd1ba Russell Belfer 1328653313 -0800 commit: Some whitespace only changes for testing purposes -a97cc019851d401a4f1d091cb91a15890a0dd1ba 217878ab49e1314388ea2e32dc6fdb58a1b969e0 Russell Belfer 1332734901 -0700 commit: added files in sub/sub -217878ab49e1314388ea2e32dc6fdb58a1b969e0 24fa9a9fc4e202313e24b648087495441dab432b Russell Belfer 1332735555 -0700 commit: adding more files in sub for tree status -24fa9a9fc4e202313e24b648087495441dab432b 8d0b9df9bd30be7910ddda60548d485bc302b911 yorah 1341230701 +0200 commit: Updating test data so we can test inter-hunk-context diff --git a/tests-clar/resources/attr/.gitted/objects/10/8bb4e7fd7b16490dc33ff7d972151e73d7166e b/tests-clar/resources/attr/.gitted/objects/10/8bb4e7fd7b16490dc33ff7d972151e73d7166e deleted file mode 100644 index edcf7520c..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/10/8bb4e7fd7b16490dc33ff7d972151e73d7166e and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/16/983da6643656bb44c43965ecb6855c6d574512 b/tests-clar/resources/attr/.gitted/objects/16/983da6643656bb44c43965ecb6855c6d574512 deleted file mode 100644 index e49c94acd..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/16/983da6643656bb44c43965ecb6855c6d574512 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/21/7878ab49e1314388ea2e32dc6fdb58a1b969e0 b/tests-clar/resources/attr/.gitted/objects/21/7878ab49e1314388ea2e32dc6fdb58a1b969e0 deleted file mode 100644 index b537899f2..000000000 --- a/tests-clar/resources/attr/.gitted/objects/21/7878ab49e1314388ea2e32dc6fdb58a1b969e0 +++ /dev/null @@ -1,4 +0,0 @@ -xQ -0D)nD#xmvJ߀7cx0Iۺ -+e"v☝pwcJH1x%HL>Dd xC\ʤzᔶd0Z#mغڰ -y ->{qK \ No newline at end of file diff --git a/tests-clar/resources/attr/.gitted/objects/24/fa9a9fc4e202313e24b648087495441dab432b b/tests-clar/resources/attr/.gitted/objects/24/fa9a9fc4e202313e24b648087495441dab432b deleted file mode 100644 index e7099bbaa..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/24/fa9a9fc4e202313e24b648087495441dab432b and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/29/29de282ce999e95183aedac6451d3384559c4b b/tests-clar/resources/attr/.gitted/objects/29/29de282ce999e95183aedac6451d3384559c4b deleted file mode 100644 index ad84f0854..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/29/29de282ce999e95183aedac6451d3384559c4b and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/2b/40c5aca159b04ea8d20ffe36cdf8b09369b14a b/tests-clar/resources/attr/.gitted/objects/2b/40c5aca159b04ea8d20ffe36cdf8b09369b14a deleted file mode 100644 index 0e2368069..000000000 --- a/tests-clar/resources/attr/.gitted/objects/2b/40c5aca159b04ea8d20ffe36cdf8b09369b14a +++ /dev/null @@ -1 +0,0 @@ -xmPj0=P8ZSc hR6{=ob"afv#3ά=7P%[8 yNlͣ>c;gӐkYX9b|D~Vؗ)vܕ \ No newline at end of file diff --git a/tests-clar/resources/attr/.gitted/objects/2c/66e14f77196ea763fb1e41612c1aa2bc2d8ed2 b/tests-clar/resources/attr/.gitted/objects/2c/66e14f77196ea763fb1e41612c1aa2bc2d8ed2 deleted file mode 100644 index 4b75d50eb..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/2c/66e14f77196ea763fb1e41612c1aa2bc2d8ed2 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/2d/e7dfe3588f3c7e9ad59e7d50ba90e3329df9d9 b/tests-clar/resources/attr/.gitted/objects/2d/e7dfe3588f3c7e9ad59e7d50ba90e3329df9d9 deleted file mode 100644 index e0fd0468e..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/2d/e7dfe3588f3c7e9ad59e7d50ba90e3329df9d9 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/37/0fe9ec224ce33e71f9e5ec2bd1142ce9937a6a b/tests-clar/resources/attr/.gitted/objects/37/0fe9ec224ce33e71f9e5ec2bd1142ce9937a6a deleted file mode 100644 index 9c37c5946..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/37/0fe9ec224ce33e71f9e5ec2bd1142ce9937a6a and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/3a/6df026462ebafe455af9867d27eda20a9e0974 b/tests-clar/resources/attr/.gitted/objects/3a/6df026462ebafe455af9867d27eda20a9e0974 deleted file mode 100644 index c74add826..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/3a/6df026462ebafe455af9867d27eda20a9e0974 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/3b/74db7ab381105dc0d28f8295a77f6a82989292 b/tests-clar/resources/attr/.gitted/objects/3b/74db7ab381105dc0d28f8295a77f6a82989292 deleted file mode 100644 index e5cef35fa..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/3b/74db7ab381105dc0d28f8295a77f6a82989292 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/3e/42ffc54a663f9401cc25843d6c0e71a33e4249 b/tests-clar/resources/attr/.gitted/objects/3e/42ffc54a663f9401cc25843d6c0e71a33e4249 deleted file mode 100644 index 091d79b14..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/3e/42ffc54a663f9401cc25843d6c0e71a33e4249 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/45/141a79a77842c59a63229403220a4e4be74e3d b/tests-clar/resources/attr/.gitted/objects/45/141a79a77842c59a63229403220a4e4be74e3d deleted file mode 100644 index 5b58ef024..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/45/141a79a77842c59a63229403220a4e4be74e3d and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/45/5a314fa848d52ae1f11d254da4f60858fc97f4 b/tests-clar/resources/attr/.gitted/objects/45/5a314fa848d52ae1f11d254da4f60858fc97f4 deleted file mode 100644 index f90f0d79c..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/45/5a314fa848d52ae1f11d254da4f60858fc97f4 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests-clar/resources/attr/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 deleted file mode 100644 index 7ca4ceed5..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/4d/713dc48e6b1bd75b0d61ad078ba9ca3a56745d b/tests-clar/resources/attr/.gitted/objects/4d/713dc48e6b1bd75b0d61ad078ba9ca3a56745d deleted file mode 100644 index eb1e8d0c5..000000000 --- a/tests-clar/resources/attr/.gitted/objects/4d/713dc48e6b1bd75b0d61ad078ba9ca3a56745d +++ /dev/null @@ -1,2 +0,0 @@ -x @WŶ -|k 9n$}g:;51e4\k_]ރ٭hDk'~ \ No newline at end of file diff --git a/tests-clar/resources/attr/.gitted/objects/4e/49ba8c5b6c32ff28cd9dcb60be34df50fcc485 b/tests-clar/resources/attr/.gitted/objects/4e/49ba8c5b6c32ff28cd9dcb60be34df50fcc485 deleted file mode 100644 index 6fcc549b4..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/4e/49ba8c5b6c32ff28cd9dcb60be34df50fcc485 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/55/6f8c827b8e4a02ad5cab77dca2bcb3e226b0b3 b/tests-clar/resources/attr/.gitted/objects/55/6f8c827b8e4a02ad5cab77dca2bcb3e226b0b3 deleted file mode 100644 index 4bcff1faa..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/55/6f8c827b8e4a02ad5cab77dca2bcb3e226b0b3 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/58/19a185d77b03325aaf87cafc771db36f6ddca7 b/tests-clar/resources/attr/.gitted/objects/58/19a185d77b03325aaf87cafc771db36f6ddca7 deleted file mode 100644 index fe34eb63a..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/58/19a185d77b03325aaf87cafc771db36f6ddca7 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/60/5812ab7fe421fdd325a935d35cb06a9234a7d7 b/tests-clar/resources/attr/.gitted/objects/60/5812ab7fe421fdd325a935d35cb06a9234a7d7 deleted file mode 100644 index b0cc51ee6..000000000 --- a/tests-clar/resources/attr/.gitted/objects/60/5812ab7fe421fdd325a935d35cb06a9234a7d7 +++ /dev/null @@ -1,2 +0,0 @@ -xN 0;S˻BU J ?lٖygcáU RbacG;l㠝Dq֠ZʫAH<Ǒ3N=J2d3[0= -}ۤI™jM"x/[TwU&[/k(tJL \ No newline at end of file diff --git a/tests-clar/resources/attr/.gitted/objects/6b/ab5c79cd5140d0f800917f550eb2a3dc32b0da b/tests-clar/resources/attr/.gitted/objects/6b/ab5c79cd5140d0f800917f550eb2a3dc32b0da deleted file mode 100644 index f51e11ccc..000000000 --- a/tests-clar/resources/attr/.gitted/objects/6b/ab5c79cd5140d0f800917f550eb2a3dc32b0da +++ /dev/null @@ -1,3 +0,0 @@ -x 0 E)@d'~@(#tQiQn޷(Pm"Ř2hs L+d{"{Z`u -O4Y[޷;@>MSOmʧh -* <- \ No newline at end of file diff --git a/tests-clar/resources/attr/.gitted/objects/6d/968d62c89c7d9ea23a4c9a7b665d017c3d8ffd b/tests-clar/resources/attr/.gitted/objects/6d/968d62c89c7d9ea23a4c9a7b665d017c3d8ffd deleted file mode 100644 index e832241c9..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/6d/968d62c89c7d9ea23a4c9a7b665d017c3d8ffd and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/71/7fc31f6b84f9d6fc3a4edbca259d7fc92beee2 b/tests-clar/resources/attr/.gitted/objects/71/7fc31f6b84f9d6fc3a4edbca259d7fc92beee2 deleted file mode 100644 index a80265cac..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/71/7fc31f6b84f9d6fc3a4edbca259d7fc92beee2 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/8d/0b9df9bd30be7910ddda60548d485bc302b911 b/tests-clar/resources/attr/.gitted/objects/8d/0b9df9bd30be7910ddda60548d485bc302b911 deleted file mode 100644 index 3dcf088e4..000000000 --- a/tests-clar/resources/attr/.gitted/objects/8d/0b9df9bd30be7910ddda60548d485bc302b911 +++ /dev/null @@ -1 +0,0 @@ -xKj1D)zoli _"hiK2LG!7ȪJ,EPXDS ] /)}/UwR. jp##:?:|;F9܋r=_ )ơN/A[l!q}<Lfx4H\\q֏cjT \ No newline at end of file diff --git a/tests-clar/resources/attr/.gitted/objects/93/61f40bb97239cf55811892e14de2e344168ba1 b/tests-clar/resources/attr/.gitted/objects/93/61f40bb97239cf55811892e14de2e344168ba1 deleted file mode 100644 index 4b57836cd..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/93/61f40bb97239cf55811892e14de2e344168ba1 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/94/da4faa0a6bfb8ee6ccf7153801a69202b31857 b/tests-clar/resources/attr/.gitted/objects/94/da4faa0a6bfb8ee6ccf7153801a69202b31857 deleted file mode 100644 index a9ddf5d20..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/94/da4faa0a6bfb8ee6ccf7153801a69202b31857 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/96/089fd31ce1d3ee2afb0ba09ba063066932f027 b/tests-clar/resources/attr/.gitted/objects/96/089fd31ce1d3ee2afb0ba09ba063066932f027 deleted file mode 100644 index efa62f912..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/96/089fd31ce1d3ee2afb0ba09ba063066932f027 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/99/eae476896f4907224978b88e5ecaa6c5bb67a9 b/tests-clar/resources/attr/.gitted/objects/99/eae476896f4907224978b88e5ecaa6c5bb67a9 deleted file mode 100644 index 8f5acc70a..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/99/eae476896f4907224978b88e5ecaa6c5bb67a9 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/9e/5bdc47d6a80f2be0ea3049ad74231b94609242 b/tests-clar/resources/attr/.gitted/objects/9e/5bdc47d6a80f2be0ea3049ad74231b94609242 deleted file mode 100644 index d6385ec8d..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/9e/5bdc47d6a80f2be0ea3049ad74231b94609242 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/9f/b40b6675dde60b5697afceae91b66d908c02d9 b/tests-clar/resources/attr/.gitted/objects/9f/b40b6675dde60b5697afceae91b66d908c02d9 deleted file mode 100644 index 7663ad0ad..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/9f/b40b6675dde60b5697afceae91b66d908c02d9 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/a0/f7217ae99f5ac3e88534f5cea267febc5fa85b b/tests-clar/resources/attr/.gitted/objects/a0/f7217ae99f5ac3e88534f5cea267febc5fa85b deleted file mode 100644 index 985c2e281..000000000 --- a/tests-clar/resources/attr/.gitted/objects/a0/f7217ae99f5ac3e88534f5cea267febc5fa85b +++ /dev/null @@ -1 +0,0 @@ -x510 E}?΀;S␈Ԯۓv8O'F:2r)( &޷9ZAѹr9l %3Eo.Vi!"ZB;u3Cm {.7Z4avfgBLEeP;NQڬBLAnŲI 5I)M6ZQ[ -h3e: - }u};|)z&pbq?3TJ13JX \ No newline at end of file diff --git a/tests-clar/resources/attr/.gitted/objects/a9/7cc019851d401a4f1d091cb91a15890a0dd1ba b/tests-clar/resources/attr/.gitted/objects/a9/7cc019851d401a4f1d091cb91a15890a0dd1ba deleted file mode 100644 index 1a7ec0c55..000000000 --- a/tests-clar/resources/attr/.gitted/objects/a9/7cc019851d401a4f1d091cb91a15890a0dd1ba +++ /dev/null @@ -1,2 +0,0 @@ -xQj0 DS[hc;PJ( $q޾ޠ_3oIK+BtI|Lgƈ ŐR4'=qFN64 -J1FrzW[rV6-i7.eVW;X, mwl|]ṬMɢdRwC[W9sj~Wy \ No newline at end of file diff --git a/tests-clar/resources/attr/.gitted/objects/b4/35cd5689a0fb54afbeda4ac20368aa480e8f04 b/tests-clar/resources/attr/.gitted/objects/b4/35cd5689a0fb54afbeda4ac20368aa480e8f04 deleted file mode 100644 index ffe3473f4..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/b4/35cd5689a0fb54afbeda4ac20368aa480e8f04 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/c0/091889c0c77142b87a1fa5123a6398a61d33e7 b/tests-clar/resources/attr/.gitted/objects/c0/091889c0c77142b87a1fa5123a6398a61d33e7 deleted file mode 100644 index 11dc63c79..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/c0/091889c0c77142b87a1fa5123a6398a61d33e7 and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/c4/85abe35abd4aa6fd83b076a78bbea9e2e7e06c b/tests-clar/resources/attr/.gitted/objects/c4/85abe35abd4aa6fd83b076a78bbea9e2e7e06c deleted file mode 100644 index 58569ca0e..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/c4/85abe35abd4aa6fd83b076a78bbea9e2e7e06c and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/c7/aadd770d5907a8475c29e9ee21a27b88bf675d b/tests-clar/resources/attr/.gitted/objects/c7/aadd770d5907a8475c29e9ee21a27b88bf675d deleted file mode 100644 index 39aedb7d9..000000000 Binary files a/tests-clar/resources/attr/.gitted/objects/c7/aadd770d5907a8475c29e9ee21a27b88bf675d and /dev/null differ diff --git a/tests-clar/resources/attr/.gitted/objects/c9/6bbb2c2557a8325ae1559e3ba79cdcecb23076 b/tests-clar/resources/attr/.gitted/objects/c9/6bbb2c2557a8325ae1559e3ba79cdcecb23076 deleted file mode 100644 index 589f9ad31..000000000 --- a/tests-clar/resources/attr/.gitted/objects/c9/6bbb2c2557a8325ae1559e3ba79cdcecb23076 +++ /dev/null @@ -1,2 +0,0 @@ -x5A -0D]SεouJ~L0ͯ)xcfp]OOΊcB 6!뢘ó{,U 1335817070 -0700 commit (initial): Initial commit -67c1640e91ccbaf0793591be09bf572cf40c9a53 d441d7d88f52c28c2b23940ce4c33756748425f9 Russell Belfer 1335817296 -0700 commit: Adding some files in subtrees -d441d7d88f52c28c2b23940ce4c33756748425f9 67c1640e91ccbaf0793591be09bf572cf40c9a53 Russell Belfer 1335817353 -0700 HEAD^: updating HEAD -67c1640e91ccbaf0793591be09bf572cf40c9a53 58f7cf825b553ef7c26e5b9f8a23599c1a9ca296 Russell Belfer 1335817372 -0700 commit: Adding subtree data diff --git a/tests-clar/resources/attr_index/.gitted/logs/refs/heads/master b/tests-clar/resources/attr_index/.gitted/logs/refs/heads/master deleted file mode 100644 index ffd298c04..000000000 --- a/tests-clar/resources/attr_index/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,4 +0,0 @@ -0000000000000000000000000000000000000000 67c1640e91ccbaf0793591be09bf572cf40c9a53 Russell Belfer 1335817070 -0700 commit (initial): Initial commit -67c1640e91ccbaf0793591be09bf572cf40c9a53 d441d7d88f52c28c2b23940ce4c33756748425f9 Russell Belfer 1335817296 -0700 commit: Adding some files in subtrees -d441d7d88f52c28c2b23940ce4c33756748425f9 67c1640e91ccbaf0793591be09bf572cf40c9a53 Russell Belfer 1335817353 -0700 HEAD^: updating HEAD -67c1640e91ccbaf0793591be09bf572cf40c9a53 58f7cf825b553ef7c26e5b9f8a23599c1a9ca296 Russell Belfer 1335817372 -0700 commit: Adding subtree data diff --git a/tests-clar/resources/attr_index/.gitted/objects/38/12cfef36615db1788d4e63f90028007e17a348 b/tests-clar/resources/attr_index/.gitted/objects/38/12cfef36615db1788d4e63f90028007e17a348 deleted file mode 100644 index ee2991571..000000000 --- a/tests-clar/resources/attr_index/.gitted/objects/38/12cfef36615db1788d4e63f90028007e17a348 +++ /dev/null @@ -1,3 +0,0 @@ -x[ - E*@PJ -]&`w 'oMKDq45DF#!!=VZD.L:%L}!dCg*qв-LUkz~6閷W}}>g˾{f% G \ No newline at end of file diff --git a/tests-clar/resources/attr_index/.gitted/objects/59/d942b8be2784bc96db9b22202c10815c9a077b b/tests-clar/resources/attr_index/.gitted/objects/59/d942b8be2784bc96db9b22202c10815c9a077b deleted file mode 100644 index ff33737db..000000000 --- a/tests-clar/resources/attr_index/.gitted/objects/59/d942b8be2784bc96db9b22202c10815c9a077b +++ /dev/null @@ -1 +0,0 @@ -x 0 @@kR@]m)49d-#mgwTK@ \ No newline at end of file diff --git a/tests-clar/resources/blametest.git/objects/63/eb57322e363e18d460da5ea8284f3cd2340b36 b/tests-clar/resources/blametest.git/objects/63/eb57322e363e18d460da5ea8284f3cd2340b36 deleted file mode 100644 index c6c285eeb..000000000 Binary files a/tests-clar/resources/blametest.git/objects/63/eb57322e363e18d460da5ea8284f3cd2340b36 and /dev/null differ diff --git a/tests-clar/resources/blametest.git/objects/8b/137891791fe96927ad78e64b0aad7bded08bdc b/tests-clar/resources/blametest.git/objects/8b/137891791fe96927ad78e64b0aad7bded08bdc deleted file mode 100644 index 9d8f60531..000000000 Binary files a/tests-clar/resources/blametest.git/objects/8b/137891791fe96927ad78e64b0aad7bded08bdc and /dev/null differ diff --git a/tests-clar/resources/blametest.git/objects/96/679d59cf9f74d69b3c920f258559b5e8c9a18a b/tests-clar/resources/blametest.git/objects/96/679d59cf9f74d69b3c920f258559b5e8c9a18a deleted file mode 100644 index d716e3b03..000000000 Binary files a/tests-clar/resources/blametest.git/objects/96/679d59cf9f74d69b3c920f258559b5e8c9a18a and /dev/null differ diff --git a/tests-clar/resources/blametest.git/objects/98/89d6e5557761aa8e3607e80c874a6dc51ada7c b/tests-clar/resources/blametest.git/objects/98/89d6e5557761aa8e3607e80c874a6dc51ada7c deleted file mode 100644 index 12407f662..000000000 Binary files a/tests-clar/resources/blametest.git/objects/98/89d6e5557761aa8e3607e80c874a6dc51ada7c and /dev/null differ diff --git a/tests-clar/resources/blametest.git/objects/aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 b/tests-clar/resources/blametest.git/objects/aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 deleted file mode 100644 index bc13badb1..000000000 --- a/tests-clar/resources/blametest.git/objects/aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 +++ /dev/null @@ -1 +0,0 @@ -xK0 DYu6I%P9'ǡ]ޟ"NI#3L vo{R-e1#B0}s9xR6d1SZx#dj&F #AGK?Kg2r \ No newline at end of file diff --git a/tests-clar/resources/blametest.git/objects/bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 b/tests-clar/resources/blametest.git/objects/bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 deleted file mode 100644 index 4e6ad159e..000000000 --- a/tests-clar/resources/blametest.git/objects/bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 +++ /dev/null @@ -1,3 +0,0 @@ -xAn0 {+t))JA3<^Gn@$H\;MoѬƤ \ No newline at end of file diff --git a/tests-clar/resources/blametest.git/objects/da/237394e6132d20d30f175b9b73c8638fddddda b/tests-clar/resources/blametest.git/objects/da/237394e6132d20d30f175b9b73c8638fddddda deleted file mode 100644 index e9e13833f..000000000 --- a/tests-clar/resources/blametest.git/objects/da/237394e6132d20d30f175b9b73c8638fddddda +++ /dev/null @@ -1,4 +0,0 @@ -xK -0@]J|'"$vVbz :Sj)ifёDNS dObs[ޱAb( -Y;f([ -ո%85qK'Y (zF8b@vKc?S \ No newline at end of file diff --git a/tests-clar/resources/blametest.git/objects/e5/b41c1ea533f87388ab69b13baf0b5a562d6243 b/tests-clar/resources/blametest.git/objects/e5/b41c1ea533f87388ab69b13baf0b5a562d6243 deleted file mode 100644 index 7e5586c2b..000000000 Binary files a/tests-clar/resources/blametest.git/objects/e5/b41c1ea533f87388ab69b13baf0b5a562d6243 and /dev/null differ diff --git a/tests-clar/resources/blametest.git/objects/ef/32df4d259143933715c74951f932d9892364d1 b/tests-clar/resources/blametest.git/objects/ef/32df4d259143933715c74951f932d9892364d1 deleted file mode 100644 index d021ccfde..000000000 Binary files a/tests-clar/resources/blametest.git/objects/ef/32df4d259143933715c74951f932d9892364d1 and /dev/null differ diff --git a/tests-clar/resources/blametest.git/refs/heads/master b/tests-clar/resources/blametest.git/refs/heads/master deleted file mode 100644 index b763025d8..000000000 --- a/tests-clar/resources/blametest.git/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -bc7c5ac2bafe828a68e9d1d460343718d6fbe136 diff --git a/tests-clar/resources/config/.gitconfig b/tests-clar/resources/config/.gitconfig deleted file mode 100644 index fa72bddfc..000000000 --- a/tests-clar/resources/config/.gitconfig +++ /dev/null @@ -1,3 +0,0 @@ -[core] - repositoryformatversion = 5 - something = 2 \ No newline at end of file diff --git a/tests-clar/resources/config/config-include b/tests-clar/resources/config/config-include deleted file mode 100644 index 6b5e79de7..000000000 --- a/tests-clar/resources/config/config-include +++ /dev/null @@ -1,2 +0,0 @@ -[include] - path = config-included diff --git a/tests-clar/resources/config/config-included b/tests-clar/resources/config/config-included deleted file mode 100644 index 089ca08a7..000000000 --- a/tests-clar/resources/config/config-included +++ /dev/null @@ -1,2 +0,0 @@ -[foo "bar"] - baz = huzzah diff --git a/tests-clar/resources/config/config0 b/tests-clar/resources/config/config0 deleted file mode 100644 index 85235c501..000000000 --- a/tests-clar/resources/config/config0 +++ /dev/null @@ -1,7 +0,0 @@ -# This is a test -; of different comments -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true \ No newline at end of file diff --git a/tests-clar/resources/config/config1 b/tests-clar/resources/config/config1 deleted file mode 100644 index 211dc9e7d..000000000 --- a/tests-clar/resources/config/config1 +++ /dev/null @@ -1,5 +0,0 @@ -# This one checks for case sensitivity -[this "that"] - other = true -[this "That"] - other = yes diff --git a/tests-clar/resources/config/config10 b/tests-clar/resources/config/config10 deleted file mode 100644 index dde17911b..000000000 --- a/tests-clar/resources/config/config10 +++ /dev/null @@ -1 +0,0 @@ -[empty] diff --git a/tests-clar/resources/config/config11 b/tests-clar/resources/config/config11 deleted file mode 100644 index 1d8a74470..000000000 --- a/tests-clar/resources/config/config11 +++ /dev/null @@ -1,5 +0,0 @@ -[remote "ab"] - url = git://github.com/libgit2/libgit2 - url = git://git.example.com/libgit2 - - diff --git a/tests-clar/resources/config/config12 b/tests-clar/resources/config/config12 deleted file mode 100644 index b57a81b08..000000000 --- a/tests-clar/resources/config/config12 +++ /dev/null @@ -1,7 +0,0 @@ -[some "section"] - test = hi ; comment - other = "hello! \" ; ; ; " ; more test - multi = "hi, this is a ; \ -multiline comment # with ;\n special chars \ -and other stuff !@#" - back = "this is \ba phrase" diff --git a/tests-clar/resources/config/config13 b/tests-clar/resources/config/config13 deleted file mode 100644 index c1e0c5647..000000000 --- a/tests-clar/resources/config/config13 +++ /dev/null @@ -1,2 +0,0 @@ -[core] - editor = \"C:/Program Files/Nonsense/bah.exe\" \"--some option\" diff --git a/tests-clar/resources/config/config14 b/tests-clar/resources/config/config14 deleted file mode 100644 index ef2198c45..000000000 --- a/tests-clar/resources/config/config14 +++ /dev/null @@ -1,4 +0,0 @@ -[a] - b=c -[d] - e = f diff --git a/tests-clar/resources/config/config15 b/tests-clar/resources/config/config15 deleted file mode 100644 index 6d34f817b..000000000 --- a/tests-clar/resources/config/config15 +++ /dev/null @@ -1,3 +0,0 @@ -[core] - dummy2 = 7 - global = 17 diff --git a/tests-clar/resources/config/config16 b/tests-clar/resources/config/config16 deleted file mode 100644 index f25cdb728..000000000 --- a/tests-clar/resources/config/config16 +++ /dev/null @@ -1,3 +0,0 @@ -[core] - dummy2 = 28 - system = 11 diff --git a/tests-clar/resources/config/config17 b/tests-clar/resources/config/config17 deleted file mode 100644 index ca25a86af..000000000 --- a/tests-clar/resources/config/config17 +++ /dev/null @@ -1,3 +0,0 @@ -[core] - dummy2 = 7 - global = 17 \ No newline at end of file diff --git a/tests-clar/resources/config/config18 b/tests-clar/resources/config/config18 deleted file mode 100644 index cb6fd5ebc..000000000 --- a/tests-clar/resources/config/config18 +++ /dev/null @@ -1,5 +0,0 @@ -[core] - int32global = 28 - int64global = 9223372036854775803 - boolglobal = true - stringglobal = I'm a global config value! \ No newline at end of file diff --git a/tests-clar/resources/config/config19 b/tests-clar/resources/config/config19 deleted file mode 100644 index f3ae5a640..000000000 --- a/tests-clar/resources/config/config19 +++ /dev/null @@ -1,5 +0,0 @@ -[core] - int32global = -1 - int64global = -2 - boolglobal = false - stringglobal = don't find me! \ No newline at end of file diff --git a/tests-clar/resources/config/config2 b/tests-clar/resources/config/config2 deleted file mode 100644 index 60a389827..000000000 --- a/tests-clar/resources/config/config2 +++ /dev/null @@ -1,5 +0,0 @@ -; This one tests for multiline values -[this "That"] - and = one one one \ -two two \ -three three \ No newline at end of file diff --git a/tests-clar/resources/config/config20 b/tests-clar/resources/config/config20 deleted file mode 100644 index 8f0f12c4c..000000000 --- a/tests-clar/resources/config/config20 +++ /dev/null @@ -1,11 +0,0 @@ -[valid "[subsection]"] - something = a -; we don't allow anything after closing " -[sec "[subsec]/child"] - parent = grand -[sec2 "[subsec2]/child2"] - type = dvcs -[sec3 "escape\"quote"] - vcs = git -[sec4 "escaping\\slash"] - lib = git2 diff --git a/tests-clar/resources/config/config3 b/tests-clar/resources/config/config3 deleted file mode 100644 index 44a5e50ea..000000000 --- a/tests-clar/resources/config/config3 +++ /dev/null @@ -1,3 +0,0 @@ -# A [section.subsection] header is case-insensitive -[section.SuBsection] - var = hello diff --git a/tests-clar/resources/config/config4 b/tests-clar/resources/config/config4 deleted file mode 100644 index 9dd40419e..000000000 --- a/tests-clar/resources/config/config4 +++ /dev/null @@ -1,5 +0,0 @@ -# A variable name on its own is valid -[some.section] - variable -# A variable and '=' is accepted, but it's not considered true - variableeq = diff --git a/tests-clar/resources/config/config5 b/tests-clar/resources/config/config5 deleted file mode 100644 index 8ab60ccec..000000000 --- a/tests-clar/resources/config/config5 +++ /dev/null @@ -1,9 +0,0 @@ -# Test for number suffixes -[number] - simple = 1 - k = 1k - kk = 1K - m = 1m - mm = 1M - g = 1g - gg = 1G diff --git a/tests-clar/resources/config/config6 b/tests-clar/resources/config/config6 deleted file mode 100644 index 0f8f90ac9..000000000 --- a/tests-clar/resources/config/config6 +++ /dev/null @@ -1,5 +0,0 @@ -[valid "subsection"] - something = true - -[something "else"] - something = false diff --git a/tests-clar/resources/config/config7 b/tests-clar/resources/config/config7 deleted file mode 100644 index 6af6fcf25..000000000 --- a/tests-clar/resources/config/config7 +++ /dev/null @@ -1,5 +0,0 @@ -[valid "subsection"] - something = a -; we don't allow anything after closing " -[sec "subsec"x] - bleh = blah diff --git a/tests-clar/resources/config/config8 b/tests-clar/resources/config/config8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/config/config9 b/tests-clar/resources/config/config9 deleted file mode 100644 index fcaac424e..000000000 --- a/tests-clar/resources/config/config9 +++ /dev/null @@ -1,9 +0,0 @@ -[core] - dummy2 = 42 - verylong = 1 - dummy = 1 - -[remote "ab"] - url = http://example.com/git/ab -[remote "abba"] - url = http://example.com/git/abba diff --git a/tests-clar/resources/crlf/.gitted/HEAD b/tests-clar/resources/crlf/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/crlf/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/crlf/.gitted/config b/tests-clar/resources/crlf/.gitted/config deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/crlf/.gitted/objects/04/de00b358f13389948756732158eaaaefa1448c b/tests-clar/resources/crlf/.gitted/objects/04/de00b358f13389948756732158eaaaefa1448c deleted file mode 100644 index c3b7598c0..000000000 Binary files a/tests-clar/resources/crlf/.gitted/objects/04/de00b358f13389948756732158eaaaefa1448c and /dev/null differ diff --git a/tests-clar/resources/crlf/.gitted/objects/0a/a76e474d259bd7c13eb726a1396c381db55c88 b/tests-clar/resources/crlf/.gitted/objects/0a/a76e474d259bd7c13eb726a1396c381db55c88 deleted file mode 100644 index e118d6656..000000000 Binary files a/tests-clar/resources/crlf/.gitted/objects/0a/a76e474d259bd7c13eb726a1396c381db55c88 and /dev/null differ diff --git a/tests-clar/resources/crlf/.gitted/objects/0d/06894e14df22e066763ae906e0ed3eb79c205f b/tests-clar/resources/crlf/.gitted/objects/0d/06894e14df22e066763ae906e0ed3eb79c205f deleted file mode 100644 index b7a1f3290..000000000 Binary files a/tests-clar/resources/crlf/.gitted/objects/0d/06894e14df22e066763ae906e0ed3eb79c205f and /dev/null differ diff --git a/tests-clar/resources/crlf/.gitted/objects/0f/f5a53f19bfd2b5eea1ba550295c47515678987 b/tests-clar/resources/crlf/.gitted/objects/0f/f5a53f19bfd2b5eea1ba550295c47515678987 deleted file mode 100644 index 5366acd8c..000000000 Binary files a/tests-clar/resources/crlf/.gitted/objects/0f/f5a53f19bfd2b5eea1ba550295c47515678987 and /dev/null differ diff --git a/tests-clar/resources/crlf/.gitted/objects/12/faf3c1ea55f572473cec9052fca468c3584ccb b/tests-clar/resources/crlf/.gitted/objects/12/faf3c1ea55f572473cec9052fca468c3584ccb deleted file mode 100644 index 96d5b2f91..000000000 --- a/tests-clar/resources/crlf/.gitted/objects/12/faf3c1ea55f572473cec9052fca468c3584ccb +++ /dev/null @@ -1 +0,0 @@ -x 1}Nۀ,b6K6`.ؾQoab-A0dXbtnr:0cy(*Y 1347559804 -0700 commit (initial): initial commit -d70d245ed97ed2aa596dd1af6536e4bfdb047b69 7a9e0b02e63179929fed24f0a3e0f19168114d10 Russell Belfer 1347560491 -0700 commit: some changes diff --git a/tests-clar/resources/diff/.gitted/logs/refs/heads/master b/tests-clar/resources/diff/.gitted/logs/refs/heads/master deleted file mode 100644 index 8c6f6fd18..000000000 --- a/tests-clar/resources/diff/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 d70d245ed97ed2aa596dd1af6536e4bfdb047b69 Russell Belfer 1347559804 -0700 commit (initial): initial commit -d70d245ed97ed2aa596dd1af6536e4bfdb047b69 7a9e0b02e63179929fed24f0a3e0f19168114d10 Russell Belfer 1347560491 -0700 commit: some changes diff --git a/tests-clar/resources/diff/.gitted/objects/29/ab7053bb4dde0298e03e2c179e890b7dd465a7 b/tests-clar/resources/diff/.gitted/objects/29/ab7053bb4dde0298e03e2c179e890b7dd465a7 deleted file mode 100644 index 94f9a676d..000000000 Binary files a/tests-clar/resources/diff/.gitted/objects/29/ab7053bb4dde0298e03e2c179e890b7dd465a7 and /dev/null differ diff --git a/tests-clar/resources/diff/.gitted/objects/3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847 b/tests-clar/resources/diff/.gitted/objects/3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847 deleted file mode 100644 index 9fed523dc..000000000 Binary files a/tests-clar/resources/diff/.gitted/objects/3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847 and /dev/null differ diff --git a/tests-clar/resources/diff/.gitted/objects/54/6c735f16a3b44d9784075c2c0dab2ac9bf1989 b/tests-clar/resources/diff/.gitted/objects/54/6c735f16a3b44d9784075c2c0dab2ac9bf1989 deleted file mode 100644 index d7df4d6a1..000000000 Binary files a/tests-clar/resources/diff/.gitted/objects/54/6c735f16a3b44d9784075c2c0dab2ac9bf1989 and /dev/null differ diff --git a/tests-clar/resources/diff/.gitted/objects/7a/9e0b02e63179929fed24f0a3e0f19168114d10 b/tests-clar/resources/diff/.gitted/objects/7a/9e0b02e63179929fed24f0a3e0f19168114d10 deleted file mode 100644 index 9bc25eb34..000000000 Binary files a/tests-clar/resources/diff/.gitted/objects/7a/9e0b02e63179929fed24f0a3e0f19168114d10 and /dev/null differ diff --git a/tests-clar/resources/diff/.gitted/objects/7b/808f723a8ca90df319682c221187235af76693 b/tests-clar/resources/diff/.gitted/objects/7b/808f723a8ca90df319682c221187235af76693 deleted file mode 100644 index 2fd266be6..000000000 Binary files a/tests-clar/resources/diff/.gitted/objects/7b/808f723a8ca90df319682c221187235af76693 and /dev/null differ diff --git a/tests-clar/resources/diff/.gitted/objects/88/789109439c1e1c3cd45224001edee5304ed53c b/tests-clar/resources/diff/.gitted/objects/88/789109439c1e1c3cd45224001edee5304ed53c deleted file mode 100644 index 7598b5914..000000000 --- a/tests-clar/resources/diff/.gitted/objects/88/789109439c1e1c3cd45224001edee5304ed53c +++ /dev/null @@ -1 +0,0 @@ -x+)JMU07g040031QH/H-+(a)[wz {j%;ʊRSrS4W4そN+a \ No newline at end of file diff --git a/tests-clar/resources/diff/.gitted/objects/cb/8294e696339863df760b2ff5d1e275bee72455 b/tests-clar/resources/diff/.gitted/objects/cb/8294e696339863df760b2ff5d1e275bee72455 deleted file mode 100644 index 86ebe04fe..000000000 Binary files a/tests-clar/resources/diff/.gitted/objects/cb/8294e696339863df760b2ff5d1e275bee72455 and /dev/null differ diff --git a/tests-clar/resources/diff/.gitted/objects/d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69 b/tests-clar/resources/diff/.gitted/objects/d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69 deleted file mode 100644 index 99304c4aa..000000000 --- a/tests-clar/resources/diff/.gitted/objects/d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69 +++ /dev/null @@ -1 +0,0 @@ -x !m_RB:XkVpWp 9{ ,^z#7JygԚA i1Y2VyR)𢒨'm[;-lO_#%v8 \ No newline at end of file diff --git a/tests-clar/resources/diff/.gitted/refs/heads/master b/tests-clar/resources/diff/.gitted/refs/heads/master deleted file mode 100644 index a83afc38b..000000000 --- a/tests-clar/resources/diff/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -7a9e0b02e63179929fed24f0a3e0f19168114d10 diff --git a/tests-clar/resources/diff/another.txt b/tests-clar/resources/diff/another.txt deleted file mode 100644 index d0e0bae4d..000000000 --- a/tests-clar/resources/diff/another.txt +++ /dev/null @@ -1,38 +0,0 @@ -Git is fast. With Git, nearly all operations are performed locally, giving -it an huge speed advantage on centralized systems that constantly have to -communicate with a server somewh3r3. - -For testing, large AWS instances were set up in the same availability -zone. Git and SVN were installed on both machines, the Ruby repository was -copied to both Git and SVN servers, and common operations were performed on -both. - -In some cases the commands don't match up exactly. Here, matching on the -lowest common denominator was attempted. For example, the 'commit' tests -also include the time to push for Git, though most of the time you would not -actually be pushing to the server immediately after a commit where the two -commands cannot be separated in SVN. - -Note that this is the best case scenario for SVN - a server with no load -with an 80MB/s bandwidth connection to the client machine. Nearly all of -these times would be even worse for SVN if that connection was slower, while -many of the Git times would not be affected. - -Clearly, in many of these common version control operations, Git is one or -two orders of magnitude faster than SVN, even under ideal conditions for -SVN. - -Let's see how common operations stack up against Subversion, a common -centralized version control system that is similar to CVS or -Perforce. Smaller is faster. - -One place where Git is slower is in the initial clone operation. Here, Git -One place where Git is slower is in the initial clone operation. Here, Git -One place where Git is slower is in the initial clone operation. Here, Git -seen in the above charts, it's not considerably slower for an operation that -is only performed once. - -It's also interesting to note that the size of the data on the client side -is very similar even though Git also has every version of every file for the -entire history of the project. This illustrates how efficient it is at -compressing and storing data on the client side. \ No newline at end of file diff --git a/tests-clar/resources/diff/readme.txt b/tests-clar/resources/diff/readme.txt deleted file mode 100644 index beedf288d..000000000 --- a/tests-clar/resources/diff/readme.txt +++ /dev/null @@ -1,36 +0,0 @@ -The Git feature that r3ally mak3s it stand apart from n3arly 3v3ry other SCM -out there is its branching model. - -Git allows and encourages you to have multiple local branches that can be -entirely independent of each other. The creation, merging, and deletion of -those lines of development takes seconds. - -Git allows and encourages you to have multiple local branches that can be -entirely independent of each other. The creation, merging, and deletion of -those lines of development takes seconds. - -This means that you can do things like: - -Role-Bas3d Codelin3s. Have a branch that always contains only what goes to -production, another that you merge work into for testing, and several -smaller ones for day to day work. - -Feature Based Workflow. Create new branches for each new feature you're -working on so you can seamlessly switch back and forth between them, then -delete each branch when that feature gets merged into your main line. - -Disposable Experimentation. Create a branch to experiment in, realize it's -not going to work, and just delete it - abandoning the work—with nobody else -ever seeing it (even if you've pushed other branches in the meantime). - -Notably, when you push to a remote repository, you do not have to push all -share it with others. - -Git allows and encourages you to have multiple local branches that can be -entirely independent of each other. The creation, merging, and deletion of -those lines of development takes seconds. - -There are ways to accomplish some of this with other systems, but the work -involved is much more difficult and error-prone. Git makes this process -incredibly easy and it changes the way most developers work when they learn -it.! diff --git a/tests-clar/resources/duplicate.git/COMMIT_EDITMSG b/tests-clar/resources/duplicate.git/COMMIT_EDITMSG deleted file mode 100644 index 01f9a2aac..000000000 --- a/tests-clar/resources/duplicate.git/COMMIT_EDITMSG +++ /dev/null @@ -1 +0,0 @@ -commit diff --git a/tests-clar/resources/duplicate.git/HEAD b/tests-clar/resources/duplicate.git/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/duplicate.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/duplicate.git/config b/tests-clar/resources/duplicate.git/config deleted file mode 100644 index a4ef456cb..000000000 --- a/tests-clar/resources/duplicate.git/config +++ /dev/null @@ -1,5 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = true - logallrefupdates = true diff --git a/tests-clar/resources/duplicate.git/description b/tests-clar/resources/duplicate.git/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/duplicate.git/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/duplicate.git/index b/tests-clar/resources/duplicate.git/index deleted file mode 100644 index a61e1c5ca..000000000 Binary files a/tests-clar/resources/duplicate.git/index and /dev/null differ diff --git a/tests-clar/resources/duplicate.git/info/exclude b/tests-clar/resources/duplicate.git/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/duplicate.git/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/duplicate.git/info/refs b/tests-clar/resources/duplicate.git/info/refs deleted file mode 100644 index 3b5bb03be..000000000 --- a/tests-clar/resources/duplicate.git/info/refs +++ /dev/null @@ -1 +0,0 @@ -8d2f05c97ef29a4697b37c30fe81c248ef411a23 refs/heads/master diff --git a/tests-clar/resources/duplicate.git/logs/HEAD b/tests-clar/resources/duplicate.git/logs/HEAD deleted file mode 100644 index be9b4c6cb..000000000 --- a/tests-clar/resources/duplicate.git/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 8d2f05c97ef29a4697b37c30fe81c248ef411a23 Han-Wen Nienhuys 1336844322 -0300 commit (initial): commit diff --git a/tests-clar/resources/duplicate.git/logs/refs/heads/master b/tests-clar/resources/duplicate.git/logs/refs/heads/master deleted file mode 100644 index be9b4c6cb..000000000 --- a/tests-clar/resources/duplicate.git/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 8d2f05c97ef29a4697b37c30fe81c248ef411a23 Han-Wen Nienhuys 1336844322 -0300 commit (initial): commit diff --git a/tests-clar/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea b/tests-clar/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea deleted file mode 100644 index 47c2a631a..000000000 Binary files a/tests-clar/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea and /dev/null differ diff --git a/tests-clar/resources/duplicate.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a b/tests-clar/resources/duplicate.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a deleted file mode 100644 index 6802d4949..000000000 Binary files a/tests-clar/resources/duplicate.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a and /dev/null differ diff --git a/tests-clar/resources/duplicate.git/objects/info/packs b/tests-clar/resources/duplicate.git/objects/info/packs deleted file mode 100644 index d0fdf905e..000000000 --- a/tests-clar/resources/duplicate.git/objects/info/packs +++ /dev/null @@ -1,3 +0,0 @@ -P pack-e87994ad581c9af946de0eb890175c08cd005f38.pack -P pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack - diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx b/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx deleted file mode 100644 index acbed82b6..000000000 Binary files a/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx and /dev/null differ diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack b/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack deleted file mode 100644 index 652b0c91f..000000000 Binary files a/tests-clar/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack and /dev/null differ diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx b/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx deleted file mode 100644 index fff685554..000000000 Binary files a/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx and /dev/null differ diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack b/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack deleted file mode 100644 index e3e5f0e09..000000000 Binary files a/tests-clar/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack and /dev/null differ diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.idx b/tests-clar/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.idx deleted file mode 100644 index fd8abee98..000000000 Binary files a/tests-clar/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.idx and /dev/null differ diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.pack b/tests-clar/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.pack deleted file mode 100644 index 9879e0869..000000000 Binary files a/tests-clar/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.pack and /dev/null differ diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx b/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx deleted file mode 100644 index 9f78f6e0f..000000000 Binary files a/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx and /dev/null differ diff --git a/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack b/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack deleted file mode 100644 index d1dd3b61a..000000000 Binary files a/tests-clar/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack and /dev/null differ diff --git a/tests-clar/resources/duplicate.git/packed-refs b/tests-clar/resources/duplicate.git/packed-refs deleted file mode 100644 index 9f0d4e434..000000000 --- a/tests-clar/resources/duplicate.git/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -8d2f05c97ef29a4697b37c30fe81c248ef411a23 refs/heads/master diff --git a/tests-clar/resources/duplicate.git/refs/heads/dummy-marker.txt b/tests-clar/resources/duplicate.git/refs/heads/dummy-marker.txt deleted file mode 100644 index 421376db9..000000000 --- a/tests-clar/resources/duplicate.git/refs/heads/dummy-marker.txt +++ /dev/null @@ -1 +0,0 @@ -dummy diff --git a/tests-clar/resources/empty_bare.git/HEAD b/tests-clar/resources/empty_bare.git/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/empty_bare.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/empty_bare.git/config b/tests-clar/resources/empty_bare.git/config deleted file mode 100644 index 90e16477b..000000000 --- a/tests-clar/resources/empty_bare.git/config +++ /dev/null @@ -1,7 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = false - bare = true - symlinks = false - ignorecase = true - hideDotFiles = dotGitOnly diff --git a/tests-clar/resources/empty_bare.git/description b/tests-clar/resources/empty_bare.git/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/empty_bare.git/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/empty_bare.git/info/exclude b/tests-clar/resources/empty_bare.git/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/empty_bare.git/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/empty_bare.git/objects/info/dummy-marker.txt b/tests-clar/resources/empty_bare.git/objects/info/dummy-marker.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/empty_bare.git/objects/pack/dummy-marker.txt b/tests-clar/resources/empty_bare.git/objects/pack/dummy-marker.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/empty_bare.git/refs/heads/dummy-marker.txt b/tests-clar/resources/empty_bare.git/refs/heads/dummy-marker.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/empty_bare.git/refs/tags/dummy-marker.txt b/tests-clar/resources/empty_bare.git/refs/tags/dummy-marker.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/empty_standard_repo/.gitted/HEAD b/tests-clar/resources/empty_standard_repo/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/empty_standard_repo/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/empty_standard_repo/.gitted/config b/tests-clar/resources/empty_standard_repo/.gitted/config deleted file mode 100644 index 78387c50b..000000000 --- a/tests-clar/resources/empty_standard_repo/.gitted/config +++ /dev/null @@ -1,8 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = false - bare = false - logallrefupdates = true - symlinks = false - ignorecase = true - hideDotFiles = dotGitOnly diff --git a/tests-clar/resources/empty_standard_repo/.gitted/description b/tests-clar/resources/empty_standard_repo/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/empty_standard_repo/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/empty_standard_repo/.gitted/info/exclude b/tests-clar/resources/empty_standard_repo/.gitted/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/empty_standard_repo/.gitted/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/empty_standard_repo/.gitted/objects/info/dummy-marker.txt b/tests-clar/resources/empty_standard_repo/.gitted/objects/info/dummy-marker.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/empty_standard_repo/.gitted/objects/pack/dummy-marker.txt b/tests-clar/resources/empty_standard_repo/.gitted/objects/pack/dummy-marker.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/empty_standard_repo/.gitted/refs/heads/dummy-marker.txt b/tests-clar/resources/empty_standard_repo/.gitted/refs/heads/dummy-marker.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/empty_standard_repo/.gitted/refs/tags/dummy-marker.txt b/tests-clar/resources/empty_standard_repo/.gitted/refs/tags/dummy-marker.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/filemodes/.gitted/HEAD b/tests-clar/resources/filemodes/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/filemodes/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/filemodes/.gitted/config b/tests-clar/resources/filemodes/.gitted/config deleted file mode 100644 index af107929f..000000000 --- a/tests-clar/resources/filemodes/.gitted/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true diff --git a/tests-clar/resources/filemodes/.gitted/description b/tests-clar/resources/filemodes/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/filemodes/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/filemodes/.gitted/index b/tests-clar/resources/filemodes/.gitted/index deleted file mode 100644 index b1b175a9b..000000000 Binary files a/tests-clar/resources/filemodes/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/filemodes/.gitted/info/exclude b/tests-clar/resources/filemodes/.gitted/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/filemodes/.gitted/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/filemodes/.gitted/logs/HEAD b/tests-clar/resources/filemodes/.gitted/logs/HEAD deleted file mode 100644 index 1cb6a84c1..000000000 --- a/tests-clar/resources/filemodes/.gitted/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 9962c8453ba6f0cf8dac7c5dcc2fa2897fa9964a Russell Belfer 1338847682 -0700 commit (initial): Initial commit of test data diff --git a/tests-clar/resources/filemodes/.gitted/logs/refs/heads/master b/tests-clar/resources/filemodes/.gitted/logs/refs/heads/master deleted file mode 100644 index 1cb6a84c1..000000000 --- a/tests-clar/resources/filemodes/.gitted/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 9962c8453ba6f0cf8dac7c5dcc2fa2897fa9964a Russell Belfer 1338847682 -0700 commit (initial): Initial commit of test data diff --git a/tests-clar/resources/filemodes/.gitted/objects/99/62c8453ba6f0cf8dac7c5dcc2fa2897fa9964a b/tests-clar/resources/filemodes/.gitted/objects/99/62c8453ba6f0cf8dac7c5dcc2fa2897fa9964a deleted file mode 100644 index cbd2b557a..000000000 Binary files a/tests-clar/resources/filemodes/.gitted/objects/99/62c8453ba6f0cf8dac7c5dcc2fa2897fa9964a and /dev/null differ diff --git a/tests-clar/resources/filemodes/.gitted/objects/a5/c5dd0fc6c313159a69b1d19d7f61a9f978e8f1 b/tests-clar/resources/filemodes/.gitted/objects/a5/c5dd0fc6c313159a69b1d19d7f61a9f978e8f1 deleted file mode 100644 index a9eaf2cba..000000000 Binary files a/tests-clar/resources/filemodes/.gitted/objects/a5/c5dd0fc6c313159a69b1d19d7f61a9f978e8f1 and /dev/null differ diff --git a/tests-clar/resources/filemodes/.gitted/objects/e7/48d196331bcb20267eaaee4ff3326cb73b8182 b/tests-clar/resources/filemodes/.gitted/objects/e7/48d196331bcb20267eaaee4ff3326cb73b8182 deleted file mode 100644 index 98066029c..000000000 Binary files a/tests-clar/resources/filemodes/.gitted/objects/e7/48d196331bcb20267eaaee4ff3326cb73b8182 and /dev/null differ diff --git a/tests-clar/resources/filemodes/.gitted/refs/heads/master b/tests-clar/resources/filemodes/.gitted/refs/heads/master deleted file mode 100644 index 9822d2d3f..000000000 --- a/tests-clar/resources/filemodes/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -9962c8453ba6f0cf8dac7c5dcc2fa2897fa9964a diff --git a/tests-clar/resources/filemodes/exec_off b/tests-clar/resources/filemodes/exec_off deleted file mode 100644 index a5c5dd0fc..000000000 --- a/tests-clar/resources/filemodes/exec_off +++ /dev/null @@ -1 +0,0 @@ -Howdy diff --git a/tests-clar/resources/filemodes/exec_off2on_staged b/tests-clar/resources/filemodes/exec_off2on_staged deleted file mode 100755 index a5c5dd0fc..000000000 --- a/tests-clar/resources/filemodes/exec_off2on_staged +++ /dev/null @@ -1 +0,0 @@ -Howdy diff --git a/tests-clar/resources/filemodes/exec_off2on_workdir b/tests-clar/resources/filemodes/exec_off2on_workdir deleted file mode 100755 index a5c5dd0fc..000000000 --- a/tests-clar/resources/filemodes/exec_off2on_workdir +++ /dev/null @@ -1 +0,0 @@ -Howdy diff --git a/tests-clar/resources/filemodes/exec_off_untracked b/tests-clar/resources/filemodes/exec_off_untracked deleted file mode 100644 index a5c5dd0fc..000000000 --- a/tests-clar/resources/filemodes/exec_off_untracked +++ /dev/null @@ -1 +0,0 @@ -Howdy diff --git a/tests-clar/resources/filemodes/exec_on b/tests-clar/resources/filemodes/exec_on deleted file mode 100755 index a5c5dd0fc..000000000 --- a/tests-clar/resources/filemodes/exec_on +++ /dev/null @@ -1 +0,0 @@ -Howdy diff --git a/tests-clar/resources/filemodes/exec_on2off_staged b/tests-clar/resources/filemodes/exec_on2off_staged deleted file mode 100644 index a5c5dd0fc..000000000 --- a/tests-clar/resources/filemodes/exec_on2off_staged +++ /dev/null @@ -1 +0,0 @@ -Howdy diff --git a/tests-clar/resources/filemodes/exec_on2off_workdir b/tests-clar/resources/filemodes/exec_on2off_workdir deleted file mode 100644 index a5c5dd0fc..000000000 --- a/tests-clar/resources/filemodes/exec_on2off_workdir +++ /dev/null @@ -1 +0,0 @@ -Howdy diff --git a/tests-clar/resources/filemodes/exec_on_untracked b/tests-clar/resources/filemodes/exec_on_untracked deleted file mode 100755 index a5c5dd0fc..000000000 --- a/tests-clar/resources/filemodes/exec_on_untracked +++ /dev/null @@ -1 +0,0 @@ -Howdy diff --git a/tests-clar/resources/gitgit.index b/tests-clar/resources/gitgit.index deleted file mode 100644 index 215da649e..000000000 Binary files a/tests-clar/resources/gitgit.index and /dev/null differ diff --git a/tests-clar/resources/icase/.gitted/HEAD b/tests-clar/resources/icase/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/icase/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/icase/.gitted/config b/tests-clar/resources/icase/.gitted/config deleted file mode 100644 index bb4d11c1f..000000000 --- a/tests-clar/resources/icase/.gitted/config +++ /dev/null @@ -1,7 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true - precomposeunicode = false diff --git a/tests-clar/resources/icase/.gitted/description b/tests-clar/resources/icase/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/icase/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/icase/.gitted/index b/tests-clar/resources/icase/.gitted/index deleted file mode 100644 index f8288ec13..000000000 Binary files a/tests-clar/resources/icase/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/icase/.gitted/info/exclude b/tests-clar/resources/icase/.gitted/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/icase/.gitted/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/icase/.gitted/logs/HEAD b/tests-clar/resources/icase/.gitted/logs/HEAD deleted file mode 100644 index 3b16bd163..000000000 --- a/tests-clar/resources/icase/.gitted/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 76d6e1d231b1085fcce151427e9899335de74be6 Russell Belfer 1359157123 -0800 commit (initial): initial commit diff --git a/tests-clar/resources/icase/.gitted/logs/refs/heads/master b/tests-clar/resources/icase/.gitted/logs/refs/heads/master deleted file mode 100644 index 3b16bd163..000000000 --- a/tests-clar/resources/icase/.gitted/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 76d6e1d231b1085fcce151427e9899335de74be6 Russell Belfer 1359157123 -0800 commit (initial): initial commit diff --git a/tests-clar/resources/icase/.gitted/objects/3e/257c57f136a1cb8f2b8e9a2e5bc8ec0258bdce b/tests-clar/resources/icase/.gitted/objects/3e/257c57f136a1cb8f2b8e9a2e5bc8ec0258bdce deleted file mode 100644 index 10691c788..000000000 Binary files a/tests-clar/resources/icase/.gitted/objects/3e/257c57f136a1cb8f2b8e9a2e5bc8ec0258bdce and /dev/null differ diff --git a/tests-clar/resources/icase/.gitted/objects/4d/d6027d083575c7431396dc2a3174afeb393c93 b/tests-clar/resources/icase/.gitted/objects/4d/d6027d083575c7431396dc2a3174afeb393c93 deleted file mode 100644 index 8ca70df17..000000000 Binary files a/tests-clar/resources/icase/.gitted/objects/4d/d6027d083575c7431396dc2a3174afeb393c93 and /dev/null differ diff --git a/tests-clar/resources/icase/.gitted/objects/62/e0af52c199ec731fe4ad230041cd3286192d49 b/tests-clar/resources/icase/.gitted/objects/62/e0af52c199ec731fe4ad230041cd3286192d49 deleted file mode 100644 index e264aeab3..000000000 Binary files a/tests-clar/resources/icase/.gitted/objects/62/e0af52c199ec731fe4ad230041cd3286192d49 and /dev/null differ diff --git a/tests-clar/resources/icase/.gitted/objects/76/d6e1d231b1085fcce151427e9899335de74be6 b/tests-clar/resources/icase/.gitted/objects/76/d6e1d231b1085fcce151427e9899335de74be6 deleted file mode 100644 index 24a4b3ee3..000000000 --- a/tests-clar/resources/icase/.gitted/objects/76/d6e1d231b1085fcce151427e9899335de74be6 +++ /dev/null @@ -1,3 +0,0 @@ -x 1ENӀc XdƉ&/usԛ8}2 SH, -am1ЋEѷ9CJ$ nܷA -bଃjO_SO9%)9 \ No newline at end of file diff --git a/tests-clar/resources/icase/.gitted/objects/d4/4e18fb93b7107b5cd1b95d601591d77869a1b6 b/tests-clar/resources/icase/.gitted/objects/d4/4e18fb93b7107b5cd1b95d601591d77869a1b6 deleted file mode 100644 index 32d8c499f..000000000 Binary files a/tests-clar/resources/icase/.gitted/objects/d4/4e18fb93b7107b5cd1b95d601591d77869a1b6 and /dev/null differ diff --git a/tests-clar/resources/icase/.gitted/refs/heads/master b/tests-clar/resources/icase/.gitted/refs/heads/master deleted file mode 100644 index 37410ec2a..000000000 --- a/tests-clar/resources/icase/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -76d6e1d231b1085fcce151427e9899335de74be6 diff --git a/tests-clar/resources/icase/B b/tests-clar/resources/icase/B deleted file mode 100644 index d44e18fb9..000000000 --- a/tests-clar/resources/icase/B +++ /dev/null @@ -1 +0,0 @@ -start diff --git a/tests-clar/resources/icase/D b/tests-clar/resources/icase/D deleted file mode 100644 index d44e18fb9..000000000 --- a/tests-clar/resources/icase/D +++ /dev/null @@ -1 +0,0 @@ -start diff --git a/tests-clar/resources/icase/F b/tests-clar/resources/icase/F deleted file mode 100644 index d44e18fb9..000000000 --- a/tests-clar/resources/icase/F +++ /dev/null @@ -1 +0,0 @@ -start diff --git a/tests-clar/resources/icase/H b/tests-clar/resources/icase/H deleted file mode 100644 index d44e18fb9..000000000 --- a/tests-clar/resources/icase/H +++ /dev/null @@ -1 +0,0 @@ -start diff --git a/tests-clar/resources/icase/J b/tests-clar/resources/icase/J deleted file mode 100644 index d44e18fb9..000000000 --- a/tests-clar/resources/icase/J +++ /dev/null @@ -1 +0,0 @@ -start diff --git a/tests-clar/resources/icase/L/1 b/tests-clar/resources/icase/L/1 deleted file mode 100644 index 62e0af52c..000000000 --- a/tests-clar/resources/icase/L/1 +++ /dev/null @@ -1 +0,0 @@ -sub diff --git a/tests-clar/resources/icase/L/B b/tests-clar/resources/icase/L/B deleted file mode 100644 index 62e0af52c..000000000 --- a/tests-clar/resources/icase/L/B +++ /dev/null @@ -1 +0,0 @@ -sub diff --git a/tests-clar/resources/icase/L/D b/tests-clar/resources/icase/L/D deleted file mode 100644 index 62e0af52c..000000000 --- a/tests-clar/resources/icase/L/D +++ /dev/null @@ -1 +0,0 @@ -sub diff --git a/tests-clar/resources/icase/L/a b/tests-clar/resources/icase/L/a deleted file mode 100644 index 62e0af52c..000000000 --- a/tests-clar/resources/icase/L/a +++ /dev/null @@ -1 +0,0 @@ -sub diff --git a/tests-clar/resources/icase/L/c b/tests-clar/resources/icase/L/c deleted file mode 100644 index 62e0af52c..000000000 --- a/tests-clar/resources/icase/L/c +++ /dev/null @@ -1 +0,0 @@ -sub diff --git a/tests-clar/resources/icase/a b/tests-clar/resources/icase/a deleted file mode 100644 index d44e18fb9..000000000 --- a/tests-clar/resources/icase/a +++ /dev/null @@ -1 +0,0 @@ -start diff --git a/tests-clar/resources/icase/c b/tests-clar/resources/icase/c deleted file mode 100644 index d44e18fb9..000000000 --- a/tests-clar/resources/icase/c +++ /dev/null @@ -1 +0,0 @@ -start diff --git a/tests-clar/resources/icase/e b/tests-clar/resources/icase/e deleted file mode 100644 index d44e18fb9..000000000 --- a/tests-clar/resources/icase/e +++ /dev/null @@ -1 +0,0 @@ -start diff --git a/tests-clar/resources/icase/g b/tests-clar/resources/icase/g deleted file mode 100644 index d44e18fb9..000000000 --- a/tests-clar/resources/icase/g +++ /dev/null @@ -1 +0,0 @@ -start diff --git a/tests-clar/resources/icase/i b/tests-clar/resources/icase/i deleted file mode 100644 index d44e18fb9..000000000 --- a/tests-clar/resources/icase/i +++ /dev/null @@ -1 +0,0 @@ -start diff --git a/tests-clar/resources/icase/k/1 b/tests-clar/resources/icase/k/1 deleted file mode 100644 index 62e0af52c..000000000 --- a/tests-clar/resources/icase/k/1 +++ /dev/null @@ -1 +0,0 @@ -sub diff --git a/tests-clar/resources/icase/k/B b/tests-clar/resources/icase/k/B deleted file mode 100644 index 62e0af52c..000000000 --- a/tests-clar/resources/icase/k/B +++ /dev/null @@ -1 +0,0 @@ -sub diff --git a/tests-clar/resources/icase/k/D b/tests-clar/resources/icase/k/D deleted file mode 100644 index 62e0af52c..000000000 --- a/tests-clar/resources/icase/k/D +++ /dev/null @@ -1 +0,0 @@ -sub diff --git a/tests-clar/resources/icase/k/a b/tests-clar/resources/icase/k/a deleted file mode 100644 index 62e0af52c..000000000 --- a/tests-clar/resources/icase/k/a +++ /dev/null @@ -1 +0,0 @@ -sub diff --git a/tests-clar/resources/icase/k/c b/tests-clar/resources/icase/k/c deleted file mode 100644 index 62e0af52c..000000000 --- a/tests-clar/resources/icase/k/c +++ /dev/null @@ -1 +0,0 @@ -sub diff --git a/tests-clar/resources/issue_1397/.gitted/HEAD b/tests-clar/resources/issue_1397/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/issue_1397/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/issue_1397/.gitted/config b/tests-clar/resources/issue_1397/.gitted/config deleted file mode 100644 index ba5bbde24..000000000 --- a/tests-clar/resources/issue_1397/.gitted/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - bare = false - repositoryformatversion = 0 - filemode = false - logallrefupdates = true - ignorecase = true diff --git a/tests-clar/resources/issue_1397/.gitted/index b/tests-clar/resources/issue_1397/.gitted/index deleted file mode 100644 index fa0f541d6..000000000 Binary files a/tests-clar/resources/issue_1397/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/issue_1397/.gitted/objects/7f/483a738f867e5b21c8f377d70311f011eb48b5 b/tests-clar/resources/issue_1397/.gitted/objects/7f/483a738f867e5b21c8f377d70311f011eb48b5 deleted file mode 100644 index 63bcb5d76..000000000 --- a/tests-clar/resources/issue_1397/.gitted/objects/7f/483a738f867e5b21c8f377d70311f011eb48b5 +++ /dev/null @@ -1,3 +0,0 @@ -xQN0 as -!'nTBC+e\vӯǾofPPL8FΆ%_ċb4IܗtkULdeId<3/|0j1֣\Gcwe]~ߊS -)GxEqsUڇ8mk~yI \ No newline at end of file diff --git a/tests-clar/resources/issue_1397/.gitted/objects/83/12e0889a9cbab77c732b6bc39b51a683e3a318 b/tests-clar/resources/issue_1397/.gitted/objects/83/12e0889a9cbab77c732b6bc39b51a683e3a318 deleted file mode 100644 index 06b59fede..000000000 Binary files a/tests-clar/resources/issue_1397/.gitted/objects/83/12e0889a9cbab77c732b6bc39b51a683e3a318 and /dev/null differ diff --git a/tests-clar/resources/issue_1397/.gitted/objects/8a/7ef047fc933edb62e84e7977b0612ec3f6f283 b/tests-clar/resources/issue_1397/.gitted/objects/8a/7ef047fc933edb62e84e7977b0612ec3f6f283 deleted file mode 100644 index 19cfbeae2..000000000 Binary files a/tests-clar/resources/issue_1397/.gitted/objects/8a/7ef047fc933edb62e84e7977b0612ec3f6f283 and /dev/null differ diff --git a/tests-clar/resources/issue_1397/.gitted/objects/8e/8f80088a9274fd23584992f587083ca1bcbbac b/tests-clar/resources/issue_1397/.gitted/objects/8e/8f80088a9274fd23584992f587083ca1bcbbac deleted file mode 100644 index f5c776b17..000000000 Binary files a/tests-clar/resources/issue_1397/.gitted/objects/8e/8f80088a9274fd23584992f587083ca1bcbbac and /dev/null differ diff --git a/tests-clar/resources/issue_1397/.gitted/objects/f2/c62dea0372a0578e053697d5c1ba1ac05e774a b/tests-clar/resources/issue_1397/.gitted/objects/f2/c62dea0372a0578e053697d5c1ba1ac05e774a deleted file mode 100644 index f932f3618..000000000 Binary files a/tests-clar/resources/issue_1397/.gitted/objects/f2/c62dea0372a0578e053697d5c1ba1ac05e774a and /dev/null differ diff --git a/tests-clar/resources/issue_1397/.gitted/objects/ff/3578d64d199d5b48d92bbb569e0a273e411741 b/tests-clar/resources/issue_1397/.gitted/objects/ff/3578d64d199d5b48d92bbb569e0a273e411741 deleted file mode 100644 index fbd731727..000000000 Binary files a/tests-clar/resources/issue_1397/.gitted/objects/ff/3578d64d199d5b48d92bbb569e0a273e411741 and /dev/null differ diff --git a/tests-clar/resources/issue_1397/.gitted/refs/heads/master b/tests-clar/resources/issue_1397/.gitted/refs/heads/master deleted file mode 100644 index 285bc08ff..000000000 --- a/tests-clar/resources/issue_1397/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -7f483a738f867e5b21c8f377d70311f011eb48b5 diff --git a/tests-clar/resources/issue_1397/crlf_file.txt b/tests-clar/resources/issue_1397/crlf_file.txt deleted file mode 100644 index 8312e0889..000000000 --- a/tests-clar/resources/issue_1397/crlf_file.txt +++ /dev/null @@ -1,3 +0,0 @@ -first line -second line -both with crlf \ No newline at end of file diff --git a/tests-clar/resources/issue_1397/some_other_crlf_file.txt b/tests-clar/resources/issue_1397/some_other_crlf_file.txt deleted file mode 100644 index 8e8f80088..000000000 --- a/tests-clar/resources/issue_1397/some_other_crlf_file.txt +++ /dev/null @@ -1,3 +0,0 @@ -first line -second line with some change -both with crlf \ No newline at end of file diff --git a/tests-clar/resources/issue_592/.gitted/COMMIT_EDITMSG b/tests-clar/resources/issue_592/.gitted/COMMIT_EDITMSG deleted file mode 100644 index 5852f4463..000000000 --- a/tests-clar/resources/issue_592/.gitted/COMMIT_EDITMSG +++ /dev/null @@ -1 +0,0 @@ -Initial commit diff --git a/tests-clar/resources/issue_592/.gitted/HEAD b/tests-clar/resources/issue_592/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/issue_592/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/issue_592/.gitted/config b/tests-clar/resources/issue_592/.gitted/config deleted file mode 100644 index 78387c50b..000000000 --- a/tests-clar/resources/issue_592/.gitted/config +++ /dev/null @@ -1,8 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = false - bare = false - logallrefupdates = true - symlinks = false - ignorecase = true - hideDotFiles = dotGitOnly diff --git a/tests-clar/resources/issue_592/.gitted/index b/tests-clar/resources/issue_592/.gitted/index deleted file mode 100644 index be7a29d99..000000000 Binary files a/tests-clar/resources/issue_592/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/issue_592/.gitted/info/exclude b/tests-clar/resources/issue_592/.gitted/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/issue_592/.gitted/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/issue_592/.gitted/logs/HEAD b/tests-clar/resources/issue_592/.gitted/logs/HEAD deleted file mode 100644 index f19fe35a6..000000000 --- a/tests-clar/resources/issue_592/.gitted/logs/HEAD +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 4d383e87f0371ba8fa353f3912db6862b2625e85 nulltoken 1331989635 +0100 commit (initial): Initial commit -4d383e87f0371ba8fa353f3912db6862b2625e85 e38fcc7a6060f5eb5b876e836b52ae4769363f21 nulltoken 1332227062 +0100 commit (amend): Initial commit diff --git a/tests-clar/resources/issue_592/.gitted/logs/refs/heads/master b/tests-clar/resources/issue_592/.gitted/logs/refs/heads/master deleted file mode 100644 index f19fe35a6..000000000 --- a/tests-clar/resources/issue_592/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 4d383e87f0371ba8fa353f3912db6862b2625e85 nulltoken 1331989635 +0100 commit (initial): Initial commit -4d383e87f0371ba8fa353f3912db6862b2625e85 e38fcc7a6060f5eb5b876e836b52ae4769363f21 nulltoken 1332227062 +0100 commit (amend): Initial commit diff --git a/tests-clar/resources/issue_592/.gitted/objects/06/07ee9d4ccce8e4c4fa13c2c7d727e7faba4e0e b/tests-clar/resources/issue_592/.gitted/objects/06/07ee9d4ccce8e4c4fa13c2c7d727e7faba4e0e deleted file mode 100644 index 05dec10f7..000000000 Binary files a/tests-clar/resources/issue_592/.gitted/objects/06/07ee9d4ccce8e4c4fa13c2c7d727e7faba4e0e and /dev/null differ diff --git a/tests-clar/resources/issue_592/.gitted/objects/49/363a72a90d9424240258cd3759f23788ecf1d8 b/tests-clar/resources/issue_592/.gitted/objects/49/363a72a90d9424240258cd3759f23788ecf1d8 deleted file mode 100644 index e997e1b49..000000000 Binary files a/tests-clar/resources/issue_592/.gitted/objects/49/363a72a90d9424240258cd3759f23788ecf1d8 and /dev/null differ diff --git a/tests-clar/resources/issue_592/.gitted/objects/4d/383e87f0371ba8fa353f3912db6862b2625e85 b/tests-clar/resources/issue_592/.gitted/objects/4d/383e87f0371ba8fa353f3912db6862b2625e85 deleted file mode 100644 index c49a8be58..000000000 --- a/tests-clar/resources/issue_592/.gitted/objects/4d/383e87f0371ba8fa353f3912db6862b2625e85 +++ /dev/null @@ -1,2 +0,0 @@ -xM -0]o/IDz bz H9v2t =k,p+͏>4U=^(tAF2̟3sL|%cYuZv{=r_G}K> \ No newline at end of file diff --git a/tests-clar/resources/issue_592/.gitted/objects/71/44be264b61825fbff68046fe999bdfe96a1792 b/tests-clar/resources/issue_592/.gitted/objects/71/44be264b61825fbff68046fe999bdfe96a1792 deleted file mode 100644 index 25d44d938..000000000 Binary files a/tests-clar/resources/issue_592/.gitted/objects/71/44be264b61825fbff68046fe999bdfe96a1792 and /dev/null differ diff --git a/tests-clar/resources/issue_592/.gitted/objects/be/de83ee10b5b3f00239660b00acec2d55fd0b84 b/tests-clar/resources/issue_592/.gitted/objects/be/de83ee10b5b3f00239660b00acec2d55fd0b84 deleted file mode 100644 index 1d6e38d37..000000000 Binary files a/tests-clar/resources/issue_592/.gitted/objects/be/de83ee10b5b3f00239660b00acec2d55fd0b84 and /dev/null differ diff --git a/tests-clar/resources/issue_592/.gitted/objects/e3/8fcc7a6060f5eb5b876e836b52ae4769363f21 b/tests-clar/resources/issue_592/.gitted/objects/e3/8fcc7a6060f5eb5b876e836b52ae4769363f21 deleted file mode 100644 index 36c5b9aab..000000000 Binary files a/tests-clar/resources/issue_592/.gitted/objects/e3/8fcc7a6060f5eb5b876e836b52ae4769363f21 and /dev/null differ diff --git a/tests-clar/resources/issue_592/.gitted/objects/f1/adef63cb08891a0942b76fc4b9c50c6c494bc7 b/tests-clar/resources/issue_592/.gitted/objects/f1/adef63cb08891a0942b76fc4b9c50c6c494bc7 deleted file mode 100644 index c08ecd5ed..000000000 Binary files a/tests-clar/resources/issue_592/.gitted/objects/f1/adef63cb08891a0942b76fc4b9c50c6c494bc7 and /dev/null differ diff --git a/tests-clar/resources/issue_592/.gitted/refs/heads/master b/tests-clar/resources/issue_592/.gitted/refs/heads/master deleted file mode 100644 index 1f6669628..000000000 --- a/tests-clar/resources/issue_592/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -e38fcc7a6060f5eb5b876e836b52ae4769363f21 diff --git a/tests-clar/resources/issue_592/a.txt b/tests-clar/resources/issue_592/a.txt deleted file mode 100644 index f1adef63c..000000000 --- a/tests-clar/resources/issue_592/a.txt +++ /dev/null @@ -1 +0,0 @@ -nothing here diff --git a/tests-clar/resources/issue_592/c/a.txt b/tests-clar/resources/issue_592/c/a.txt deleted file mode 100644 index f1adef63c..000000000 --- a/tests-clar/resources/issue_592/c/a.txt +++ /dev/null @@ -1 +0,0 @@ -nothing here diff --git a/tests-clar/resources/issue_592/l.txt b/tests-clar/resources/issue_592/l.txt deleted file mode 100644 index f1adef63c..000000000 --- a/tests-clar/resources/issue_592/l.txt +++ /dev/null @@ -1 +0,0 @@ -nothing here diff --git a/tests-clar/resources/issue_592/t/a.txt b/tests-clar/resources/issue_592/t/a.txt deleted file mode 100644 index f1adef63c..000000000 --- a/tests-clar/resources/issue_592/t/a.txt +++ /dev/null @@ -1 +0,0 @@ -nothing here diff --git a/tests-clar/resources/issue_592/t/b.txt b/tests-clar/resources/issue_592/t/b.txt deleted file mode 100644 index f1adef63c..000000000 --- a/tests-clar/resources/issue_592/t/b.txt +++ /dev/null @@ -1 +0,0 @@ -nothing here diff --git a/tests-clar/resources/issue_592b/.gitted/HEAD b/tests-clar/resources/issue_592b/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/issue_592b/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/issue_592b/.gitted/config b/tests-clar/resources/issue_592b/.gitted/config deleted file mode 100644 index af107929f..000000000 --- a/tests-clar/resources/issue_592b/.gitted/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true diff --git a/tests-clar/resources/issue_592b/.gitted/description b/tests-clar/resources/issue_592b/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/issue_592b/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/issue_592b/.gitted/index b/tests-clar/resources/issue_592b/.gitted/index deleted file mode 100644 index 596438216..000000000 Binary files a/tests-clar/resources/issue_592b/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/issue_592b/.gitted/info/exclude b/tests-clar/resources/issue_592b/.gitted/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/issue_592b/.gitted/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/issue_592b/.gitted/logs/HEAD b/tests-clar/resources/issue_592b/.gitted/logs/HEAD deleted file mode 100644 index 6f3ba90cc..000000000 --- a/tests-clar/resources/issue_592b/.gitted/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 3fbf1852f72fd268e36457b13a18cdd9a4c9ea35 Russell Belfer 1337205933 -0700 commit (initial): Initial commit diff --git a/tests-clar/resources/issue_592b/.gitted/logs/refs/heads/master b/tests-clar/resources/issue_592b/.gitted/logs/refs/heads/master deleted file mode 100644 index 6f3ba90cc..000000000 --- a/tests-clar/resources/issue_592b/.gitted/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 3fbf1852f72fd268e36457b13a18cdd9a4c9ea35 Russell Belfer 1337205933 -0700 commit (initial): Initial commit diff --git a/tests-clar/resources/issue_592b/.gitted/objects/3f/bf1852f72fd268e36457b13a18cdd9a4c9ea35 b/tests-clar/resources/issue_592b/.gitted/objects/3f/bf1852f72fd268e36457b13a18cdd9a4c9ea35 deleted file mode 100644 index 6eaf64b46..000000000 --- a/tests-clar/resources/issue_592b/.gitted/objects/3f/bf1852f72fd268e36457b13a18cdd9a4c9ea35 +++ /dev/null @@ -1,2 +0,0 @@ -xK -1]}%BwnAq xzVƃv ɂc&%9@9xdu.]".=EבO+ۘBEk\N_<>E U%9 \ No newline at end of file diff --git a/tests-clar/resources/issue_592b/.gitted/objects/6f/a891d3e578c83e1c03bdb9e0fdd8e6e934157f b/tests-clar/resources/issue_592b/.gitted/objects/6f/a891d3e578c83e1c03bdb9e0fdd8e6e934157f deleted file mode 100644 index c4becfe2f..000000000 Binary files a/tests-clar/resources/issue_592b/.gitted/objects/6f/a891d3e578c83e1c03bdb9e0fdd8e6e934157f and /dev/null differ diff --git a/tests-clar/resources/issue_592b/.gitted/objects/80/07d41d5794e6ce4d4d2c97e370d5a9aa6d5213 b/tests-clar/resources/issue_592b/.gitted/objects/80/07d41d5794e6ce4d4d2c97e370d5a9aa6d5213 deleted file mode 100644 index aea14f2af..000000000 Binary files a/tests-clar/resources/issue_592b/.gitted/objects/80/07d41d5794e6ce4d4d2c97e370d5a9aa6d5213 and /dev/null differ diff --git a/tests-clar/resources/issue_592b/.gitted/objects/a6/5fb6583a7c425284142f285bc359a2d6565513 b/tests-clar/resources/issue_592b/.gitted/objects/a6/5fb6583a7c425284142f285bc359a2d6565513 deleted file mode 100644 index 9b7407221..000000000 Binary files a/tests-clar/resources/issue_592b/.gitted/objects/a6/5fb6583a7c425284142f285bc359a2d6565513 and /dev/null differ diff --git a/tests-clar/resources/issue_592b/.gitted/objects/ae/be7a55922c7097ef91ca3a7bc327a901d87c2c b/tests-clar/resources/issue_592b/.gitted/objects/ae/be7a55922c7097ef91ca3a7bc327a901d87c2c deleted file mode 100644 index 1494ed822..000000000 Binary files a/tests-clar/resources/issue_592b/.gitted/objects/ae/be7a55922c7097ef91ca3a7bc327a901d87c2c and /dev/null differ diff --git a/tests-clar/resources/issue_592b/.gitted/objects/b3/44b055867fcdc1f01eaa75056a43e868eb4fbc b/tests-clar/resources/issue_592b/.gitted/objects/b3/44b055867fcdc1f01eaa75056a43e868eb4fbc deleted file mode 100644 index 7a6626636..000000000 Binary files a/tests-clar/resources/issue_592b/.gitted/objects/b3/44b055867fcdc1f01eaa75056a43e868eb4fbc and /dev/null differ diff --git a/tests-clar/resources/issue_592b/.gitted/objects/f7/d75fbfad8b1d2e307ced287ea78aad403cdce3 b/tests-clar/resources/issue_592b/.gitted/objects/f7/d75fbfad8b1d2e307ced287ea78aad403cdce3 deleted file mode 100644 index 65a1fd0d0..000000000 Binary files a/tests-clar/resources/issue_592b/.gitted/objects/f7/d75fbfad8b1d2e307ced287ea78aad403cdce3 and /dev/null differ diff --git a/tests-clar/resources/issue_592b/.gitted/refs/heads/master b/tests-clar/resources/issue_592b/.gitted/refs/heads/master deleted file mode 100644 index c0a9ab495..000000000 --- a/tests-clar/resources/issue_592b/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -3fbf1852f72fd268e36457b13a18cdd9a4c9ea35 diff --git a/tests-clar/resources/issue_592b/gitignore b/tests-clar/resources/issue_592b/gitignore deleted file mode 100644 index 8007d41d5..000000000 --- a/tests-clar/resources/issue_592b/gitignore +++ /dev/null @@ -1 +0,0 @@ -ignored/ diff --git a/tests-clar/resources/issue_592b/ignored/contained/ignored3.txt b/tests-clar/resources/issue_592b/ignored/contained/ignored3.txt deleted file mode 100644 index b5dc7b073..000000000 --- a/tests-clar/resources/issue_592b/ignored/contained/ignored3.txt +++ /dev/null @@ -1 +0,0 @@ -I'm ignored diff --git a/tests-clar/resources/issue_592b/ignored/contained/tracked3.txt b/tests-clar/resources/issue_592b/ignored/contained/tracked3.txt deleted file mode 100644 index b344b0558..000000000 --- a/tests-clar/resources/issue_592b/ignored/contained/tracked3.txt +++ /dev/null @@ -1 +0,0 @@ -You added me anyhow diff --git a/tests-clar/resources/issue_592b/ignored/ignored2.txt b/tests-clar/resources/issue_592b/ignored/ignored2.txt deleted file mode 100644 index b5dc7b073..000000000 --- a/tests-clar/resources/issue_592b/ignored/ignored2.txt +++ /dev/null @@ -1 +0,0 @@ -I'm ignored diff --git a/tests-clar/resources/issue_592b/ignored/tracked2.txt b/tests-clar/resources/issue_592b/ignored/tracked2.txt deleted file mode 100644 index 6fa891d3e..000000000 --- a/tests-clar/resources/issue_592b/ignored/tracked2.txt +++ /dev/null @@ -1 +0,0 @@ -You like me diff --git a/tests-clar/resources/issue_592b/ignored1.txt b/tests-clar/resources/issue_592b/ignored1.txt deleted file mode 100644 index b5dc7b073..000000000 --- a/tests-clar/resources/issue_592b/ignored1.txt +++ /dev/null @@ -1 +0,0 @@ -I'm ignored diff --git a/tests-clar/resources/issue_592b/tracked1.txt b/tests-clar/resources/issue_592b/tracked1.txt deleted file mode 100644 index 6fa891d3e..000000000 --- a/tests-clar/resources/issue_592b/tracked1.txt +++ /dev/null @@ -1 +0,0 @@ -You like me diff --git a/tests-clar/resources/merge-resolve/.gitted/COMMIT_EDITMSG b/tests-clar/resources/merge-resolve/.gitted/COMMIT_EDITMSG deleted file mode 100644 index 245b18a2c..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/COMMIT_EDITMSG +++ /dev/null @@ -1 +0,0 @@ -rename conflict theirs diff --git a/tests-clar/resources/merge-resolve/.gitted/HEAD b/tests-clar/resources/merge-resolve/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/merge-resolve/.gitted/ORIG_HEAD b/tests-clar/resources/merge-resolve/.gitted/ORIG_HEAD deleted file mode 100644 index 4092d428f..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/ORIG_HEAD +++ /dev/null @@ -1 +0,0 @@ -2392a2dacc9efb562b8635d6579fb458751c7c5b diff --git a/tests-clar/resources/merge-resolve/.gitted/config b/tests-clar/resources/merge-resolve/.gitted/config deleted file mode 100644 index af107929f..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true diff --git a/tests-clar/resources/merge-resolve/.gitted/description b/tests-clar/resources/merge-resolve/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/merge-resolve/.gitted/index b/tests-clar/resources/merge-resolve/.gitted/index deleted file mode 100644 index 230eba9eb..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/HEAD b/tests-clar/resources/merge-resolve/.gitted/logs/HEAD deleted file mode 100644 index 96cdb337e..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/HEAD +++ /dev/null @@ -1,236 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351563869 -0500 commit (initial): initial -c607fc30883e335def28cd686b51f6cfa02b06ec c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351563886 -0500 checkout: moving from master to branch -c607fc30883e335def28cd686b51f6cfa02b06ec 7cb63eed597130ba4abb87b3e544b85021905520 Edward Thomson 1351563965 -0500 commit: branch -7cb63eed597130ba4abb87b3e544b85021905520 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351563968 -0500 checkout: moving from branch to master -c607fc30883e335def28cd686b51f6cfa02b06ec 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351564033 -0500 commit: master -977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351605785 -0500 checkout: moving from master to ff_branch -977c696519c5a3004c5f1d15d60c89dbeb8f235f 33d500f588fbbe65901d82b4e6b008e549064be0 Edward Thomson 1351605830 -0500 commit: fastforward -33d500f588fbbe65901d82b4e6b008e549064be0 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351605889 -0500 checkout: moving from ff_branch to master -977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874933 -0500 checkout: moving from master to octo1 -977c696519c5a3004c5f1d15d60c89dbeb8f235f 16f825815cfd20a07a75c71554e82d8eede0b061 Edward Thomson 1351874954 -0500 commit: octo1 -16f825815cfd20a07a75c71554e82d8eede0b061 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874957 -0500 checkout: moving from octo1 to master -977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874960 -0500 checkout: moving from master to octo2 -977c696519c5a3004c5f1d15d60c89dbeb8f235f 158dc7bedb202f5b26502bf3574faa7f4238d56c Edward Thomson 1351874974 -0500 commit: octo2 -158dc7bedb202f5b26502bf3574faa7f4238d56c 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874976 -0500 checkout: moving from octo2 to master -977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874980 -0500 checkout: moving from master to octo3 -977c696519c5a3004c5f1d15d60c89dbeb8f235f 50ce7d7d01217679e26c55939eef119e0c93e272 Edward Thomson 1351874998 -0500 commit: octo3 -50ce7d7d01217679e26c55939eef119e0c93e272 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875006 -0500 checkout: moving from octo3 to master -977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875010 -0500 checkout: moving from master to octo4 -977c696519c5a3004c5f1d15d60c89dbeb8f235f 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae Edward Thomson 1351875023 -0500 commit: octo4 -54269b3f6ec3d7d4ede24dd350dd5d605495c3ae 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875031 -0500 checkout: moving from octo4 to master -977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875031 -0500 checkout: moving from master to octo5 -977c696519c5a3004c5f1d15d60c89dbeb8f235f e4f618a2c3ed0669308735727df5ebf2447f022f Edward Thomson 1351875041 -0500 commit: octo5 -e4f618a2c3ed0669308735727df5ebf2447f022f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875046 -0500 checkout: moving from octo5 to master -977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875046 -0500 checkout: moving from master to octo6 -977c696519c5a3004c5f1d15d60c89dbeb8f235f 4ca408a8c88655f7586a1b580be6fad138121e98 Edward Thomson 1351875057 -0500 commit: octo5 -4ca408a8c88655f7586a1b580be6fad138121e98 b6f610aef53bd343e6c96227de874c66f00ee8e8 Edward Thomson 1351875065 -0500 commit (amend): octo6 -b6f610aef53bd343e6c96227de874c66f00ee8e8 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875071 -0500 checkout: moving from octo6 to master -977c696519c5a3004c5f1d15d60c89dbeb8f235f 4e0d9401aee78eb345a8685a859d37c8c3c0bbed Edward Thomson 1351875091 -0500 merge octo1 octo2 octo3 octo4: Merge made by the 'octopus' strategy. -4e0d9401aee78eb345a8685a859d37c8c3c0bbed 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae Edward Thomson 1351875108 -0500 reset: moving to 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae -54269b3f6ec3d7d4ede24dd350dd5d605495c3ae 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875584 -0500 reset: moving to 977c696519c5a3004c5f1d15d60c89dbeb8f235f -bd593285fc7fe4ca18ccdbabf027f5d689101452 33d500f588fbbe65901d82b4e6b008e549064be0 Edward Thomson 1351990193 -0500 checkout: moving from master to ff_branch -33d500f588fbbe65901d82b4e6b008e549064be0 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351990202 -0500 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1351990205 -0500 merge master: Fast-forward -bd593285fc7fe4ca18ccdbabf027f5d689101452 fd89f8cffb663ac89095a0f9764902e93ceaca6a Edward Thomson 1351990229 -0500 commit: fastforward -fd89f8cffb663ac89095a0f9764902e93ceaca6a bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1351990233 -0500 checkout: moving from ff_branch to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352091703 -0600 checkout: moving from master to trivial-2alt -c607fc30883e335def28cd686b51f6cfa02b06ec c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352092411 -0600 checkout: moving from trivial-2alt to trivial-2alt-branch -c607fc30883e335def28cd686b51f6cfa02b06ec c9174cef549ec94ecbc43ef03cdc775b4950becb Edward Thomson 1352092434 -0600 commit: 2alt-branch -c9174cef549ec94ecbc43ef03cdc775b4950becb c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352092440 -0600 checkout: moving from trivial-2alt-branch to trivial-2alt -c607fc30883e335def28cd686b51f6cfa02b06ec 566ab53c220a2eafc1212af1a024513230280ab9 Edward Thomson 1352092452 -0600 commit: 2alt -bd593285fc7fe4ca18ccdbabf027f5d689101452 566ab53c220a2eafc1212af1a024513230280ab9 Edward Thomson 1352094476 -0600 checkout: moving from master to trivial-3alt -566ab53c220a2eafc1212af1a024513230280ab9 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094547 -0600 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 5459c89aa0026d543ce8343bd89871bce543f9c2 Edward Thomson 1352094580 -0600 commit: 3alt -5459c89aa0026d543ce8343bd89871bce543f9c2 4c9fac0707f8d4195037ae5a681aa48626491541 Edward Thomson 1352094610 -0600 commit: 3alt-branch -4c9fac0707f8d4195037ae5a681aa48626491541 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352094620 -0600 checkout: moving from trivial-3alt to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 566ab53c220a2eafc1212af1a024513230280ab9 Edward Thomson 1352094752 -0600 checkout: moving from master to trivial-4 -566ab53c220a2eafc1212af1a024513230280ab9 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094764 -0600 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec cc3e3009134cb88014129fc8858d1101359e5e2f Edward Thomson 1352094815 -0600 commit: trivial-4 -cc3e3009134cb88014129fc8858d1101359e5e2f c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094843 -0600 checkout: moving from trivial-4 to trivial-4-branch -c607fc30883e335def28cd686b51f6cfa02b06ec 183310e30fb1499af8c619108ffea4d300b5e778 Edward Thomson 1352094856 -0600 commit: trivial-4-branch -183310e30fb1499af8c619108ffea4d300b5e778 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352094860 -0600 checkout: moving from trivial-4-branch to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 cc3e3009134cb88014129fc8858d1101359e5e2f Edward Thomson 1352096588 -0600 checkout: moving from master to trivial-4 -cc3e3009134cb88014129fc8858d1101359e5e2f c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096612 -0600 checkout: moving from trivial-4 to trivial-5alt-1 -c607fc30883e335def28cd686b51f6cfa02b06ec 4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 Edward Thomson 1352096643 -0600 commit: 5alt-1 -4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096661 -0600 checkout: moving from trivial-5alt-1 to trivial-5alt-1-branch -c607fc30883e335def28cd686b51f6cfa02b06ec 4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 Edward Thomson 1352096671 -0600 checkout: moving from trivial-5alt-1-branch to trivial-5alt-1 -4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096678 -0600 checkout: moving from trivial-5alt-1 to trivial-5alt-1-branch -c607fc30883e335def28cd686b51f6cfa02b06ec 478172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 Edward Thomson 1352096689 -0600 commit: 5alt-1-branch -478172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 Edward Thomson 1352096701 -0600 checkout: moving from trivial-5alt-1-branch to trivial-5alt-1 -4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096715 -0600 checkout: moving from trivial-5alt-1 to trivial-5alt-2 -c607fc30883e335def28cd686b51f6cfa02b06ec ebc09d0137cfb0c26697aed0109fb943ad906f3f Edward Thomson 1352096764 -0600 commit: existing file -ebc09d0137cfb0c26697aed0109fb943ad906f3f 3b47b031b3e55ae11e14a05260b1c3ffd6838d55 Edward Thomson 1352096815 -0600 commit: 5alt-2 -3b47b031b3e55ae11e14a05260b1c3ffd6838d55 ebc09d0137cfb0c26697aed0109fb943ad906f3f Edward Thomson 1352096840 -0600 checkout: moving from trivial-5alt-2 to trivial-5alt-2-branch -ebc09d0137cfb0c26697aed0109fb943ad906f3f f48097eb340dc5a7cae55aabcf1faf4548aa821f Edward Thomson 1352096855 -0600 commit: 5alt-2-branch -f48097eb340dc5a7cae55aabcf1faf4548aa821f bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352096858 -0600 checkout: moving from trivial-5alt-2-branch to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352097377 -0600 checkout: moving from master to trivial-6 -c607fc30883e335def28cd686b51f6cfa02b06ec f7c332bd4d4d4b777366cae4d24d1687477576bf Edward Thomson 1352097389 -0600 commit: 6 -f7c332bd4d4d4b777366cae4d24d1687477576bf 99b4f7e4f24470fa06b980bc21f1095c2a9425c0 Edward Thomson 1352097404 -0600 commit: trivial-6 -99b4f7e4f24470fa06b980bc21f1095c2a9425c0 f7c332bd4d4d4b777366cae4d24d1687477576bf Edward Thomson 1352097420 -0600 checkout: moving from trivial-6 to trivial-6-branch -f7c332bd4d4d4b777366cae4d24d1687477576bf a43150a738849c59376cf30bb2a68348a83c8f48 Edward Thomson 1352097431 -0600 commit: 6-branch -a43150a738849c59376cf30bb2a68348a83c8f48 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352097442 -0600 checkout: moving from trivial-6-branch to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 99b4f7e4f24470fa06b980bc21f1095c2a9425c0 Edward Thomson 1352098040 -0600 checkout: moving from master to trivial-6 -99b4f7e4f24470fa06b980bc21f1095c2a9425c0 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352098057 -0600 checkout: moving from trivial-6 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 cc3e3009134cb88014129fc8858d1101359e5e2f Edward Thomson 1352098792 -0600 checkout: moving from master to trivial-4 -cc3e3009134cb88014129fc8858d1101359e5e2f c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352098818 -0600 checkout: moving from trivial-4 to trivial-8 -c607fc30883e335def28cd686b51f6cfa02b06ec 75a811bf6bc57694adb3fe604786f3a4efd1cd1b Edward Thomson 1352098884 -0600 commit: trivial-8 -75a811bf6bc57694adb3fe604786f3a4efd1cd1b 75a811bf6bc57694adb3fe604786f3a4efd1cd1b Edward Thomson 1352098947 -0600 checkout: moving from trivial-8 to trivial-8-branch -75a811bf6bc57694adb3fe604786f3a4efd1cd1b 52d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 Edward Thomson 1352098979 -0600 commit: trivial-8-branch -52d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 75a811bf6bc57694adb3fe604786f3a4efd1cd1b Edward Thomson 1352098982 -0600 checkout: moving from trivial-8-branch to trivial-8 -75a811bf6bc57694adb3fe604786f3a4efd1cd1b 3575826c96a975031d2c14368529cc5c4353a8fd Edward Thomson 1352099000 -0600 commit: trivial-8 -3575826c96a975031d2c14368529cc5c4353a8fd bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352099008 -0600 checkout: moving from trivial-8 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352099776 -0600 checkout: moving from master to trivial-7 -c607fc30883e335def28cd686b51f6cfa02b06ec 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099790 -0600 commit: trivial-7 -092ce8682d7f3a2a3a769a6daca58950168ba5c4 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099799 -0600 checkout: moving from trivial-7 to trivial-7-branch -092ce8682d7f3a2a3a769a6daca58950168ba5c4 73cbfdc4fe843169e5b2af8dcad03cbf3acf306c Edward Thomson 1352099812 -0600 commit: trivial-7-branch -73cbfdc4fe843169e5b2af8dcad03cbf3acf306c 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099815 -0600 checkout: moving from trivial-7-branch to trivial-7 -092ce8682d7f3a2a3a769a6daca58950168ba5c4 73cbfdc4fe843169e5b2af8dcad03cbf3acf306c Edward Thomson 1352099838 -0600 checkout: moving from trivial-7 to trivial-7-branch -73cbfdc4fe843169e5b2af8dcad03cbf3acf306c 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099874 -0600 reset: moving to 092ce8682d7f3a2a3a769a6daca58950168ba5c4 -092ce8682d7f3a2a3a769a6daca58950168ba5c4 009b9cab6fdac02915a88ecd078b7a792ed802d8 Edward Thomson 1352099921 -0600 commit: removed in 7 -009b9cab6fdac02915a88ecd078b7a792ed802d8 5195a1b480f66691b667f10a9e41e70115a78351 Edward Thomson 1352099927 -0600 commit (amend): trivial-7-branch -5195a1b480f66691b667f10a9e41e70115a78351 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099937 -0600 checkout: moving from trivial-7-branch to trivial-7 -092ce8682d7f3a2a3a769a6daca58950168ba5c4 d874671ef5b20184836cb983bb273e5280384d0b Edward Thomson 1352099947 -0600 commit: trivial-7 -d874671ef5b20184836cb983bb273e5280384d0b bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352099949 -0600 checkout: moving from trivial-7 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100174 -0600 checkout: moving from master to trivial-10 -c607fc30883e335def28cd686b51f6cfa02b06ec 53825f41ac8d640612f9423a2f03a69f3d96809a Edward Thomson 1352100193 -0600 commit: trivial-10 -53825f41ac8d640612f9423a2f03a69f3d96809a 53825f41ac8d640612f9423a2f03a69f3d96809a Edward Thomson 1352100200 -0600 checkout: moving from trivial-10 to trivial-10-branch -53825f41ac8d640612f9423a2f03a69f3d96809a 11f4f3c08b737f5fd896cbefa1425ee63b21b2fa Edward Thomson 1352100211 -0600 commit: trivial-10-branch -11f4f3c08b737f5fd896cbefa1425ee63b21b2fa 53825f41ac8d640612f9423a2f03a69f3d96809a Edward Thomson 1352100214 -0600 checkout: moving from trivial-10-branch to trivial-10 -53825f41ac8d640612f9423a2f03a69f3d96809a 0ec5f433959cd46177f745903353efb5be08d151 Edward Thomson 1352100223 -0600 commit: trivial-10 -0ec5f433959cd46177f745903353efb5be08d151 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352100225 -0600 checkout: moving from trivial-10 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100270 -0600 checkout: moving from master to trivial-9 -c607fc30883e335def28cd686b51f6cfa02b06ec f0053b8060bb3f0be5cbcc3147a07ece26bf097e Edward Thomson 1352100304 -0600 commit: trivial-9 -f0053b8060bb3f0be5cbcc3147a07ece26bf097e f0053b8060bb3f0be5cbcc3147a07ece26bf097e Edward Thomson 1352100310 -0600 checkout: moving from trivial-9 to trivial-9-branch -f0053b8060bb3f0be5cbcc3147a07ece26bf097e 13d1be4ea52a6ced1d7a1d832f0ee3c399348e5e Edward Thomson 1352100317 -0600 commit: trivial-9-branch -13d1be4ea52a6ced1d7a1d832f0ee3c399348e5e f0053b8060bb3f0be5cbcc3147a07ece26bf097e Edward Thomson 1352100319 -0600 checkout: moving from trivial-9-branch to trivial-9 -f0053b8060bb3f0be5cbcc3147a07ece26bf097e c35dee9bcc0e989f3b0c40f68372a9a51b6c4e6a Edward Thomson 1352100333 -0600 commit: trivial-9 -c35dee9bcc0e989f3b0c40f68372a9a51b6c4e6a bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352100335 -0600 checkout: moving from trivial-9 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100576 -0600 checkout: moving from master to trivial-13 -c607fc30883e335def28cd686b51f6cfa02b06ec 8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa Edward Thomson 1352100589 -0600 commit: trivial-13 -8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa 8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa Edward Thomson 1352100604 -0600 checkout: moving from trivial-13 to trivial-13-branch -8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa 05f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c Edward Thomson 1352100610 -0600 commit: trivial-13-branch -05f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c 8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa Edward Thomson 1352100612 -0600 checkout: moving from trivial-13-branch to trivial-13 -8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa a3fabece9eb8748da810e1e08266fef9b7136ad4 Edward Thomson 1352100625 -0600 commit: trivial-13 -a3fabece9eb8748da810e1e08266fef9b7136ad4 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352100627 -0600 checkout: moving from trivial-13 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100936 -0600 checkout: moving from master to trivial-11 -c607fc30883e335def28cd686b51f6cfa02b06ec 35632e43612c06a3ea924bfbacd48333da874c29 Edward Thomson 1352100958 -0600 commit: trivial-11 -35632e43612c06a3ea924bfbacd48333da874c29 35632e43612c06a3ea924bfbacd48333da874c29 Edward Thomson 1352100964 -0600 checkout: moving from trivial-11 to trivial-11-branch -35632e43612c06a3ea924bfbacd48333da874c29 6718a45909532d1fcf5600d0877f7fe7e78f0b86 Edward Thomson 1352100978 -0600 commit: trivial-11-branch -6718a45909532d1fcf5600d0877f7fe7e78f0b86 35632e43612c06a3ea924bfbacd48333da874c29 Edward Thomson 1352100981 -0600 checkout: moving from trivial-11-branch to trivial-11 -35632e43612c06a3ea924bfbacd48333da874c29 3168dca1a561889b045a6441909f4c56145e666d Edward Thomson 1352100992 -0600 commit: trivial-11 -3168dca1a561889b045a6441909f4c56145e666d bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352100996 -0600 checkout: moving from trivial-11 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352101098 -0600 checkout: moving from master to trivial-14 -c607fc30883e335def28cd686b51f6cfa02b06ec 596803b523203a4851c824c07366906f8353f4ad Edward Thomson 1352101113 -0600 commit: trivial-14 -596803b523203a4851c824c07366906f8353f4ad 596803b523203a4851c824c07366906f8353f4ad Edward Thomson 1352101117 -0600 checkout: moving from trivial-14 to trivial-14-branch -596803b523203a4851c824c07366906f8353f4ad 8187117062b750eed4f93fd7e899f17b52ce554d Edward Thomson 1352101132 -0600 commit: trivial-14-branch -8187117062b750eed4f93fd7e899f17b52ce554d 596803b523203a4851c824c07366906f8353f4ad Edward Thomson 1352101135 -0600 checkout: moving from trivial-14-branch to trivial-14 -596803b523203a4851c824c07366906f8353f4ad 7e2d058d5fedf8329db44db4fac610d6b1a89159 Edward Thomson 1352101141 -0600 commit: trivial-14 -7e2d058d5fedf8329db44db4fac610d6b1a89159 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352101145 -0600 checkout: moving from trivial-14 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1353177749 -0600 checkout: moving from master to renames1 -c607fc30883e335def28cd686b51f6cfa02b06ec 412b32fb66137366147f1801ecc962452757d48a Edward Thomson 1353177886 -0600 commit: renames -412b32fb66137366147f1801ecc962452757d48a bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1353794607 -0600 checkout: moving from renames1 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1353794647 -0600 checkout: moving from master to renames2 -bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1353794677 -0600 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec ab40af3cb8a3ed2e2843e96d9aa7871336b94573 Edward Thomson 1353794852 -0600 commit: renames2 -ab40af3cb8a3ed2e2843e96d9aa7871336b94573 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1353794883 -0600 checkout: moving from renames2 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1354574697 -0600 checkout: moving from master to df_side1 -bd593285fc7fe4ca18ccdbabf027f5d689101452 d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1354574962 -0600 commit: df_ancestor -d4207f77243500bec335ab477f9227fcdb1e271a c94b27e41064c521120627e07e2035cca1d24ffa Edward Thomson 1354575027 -0600 commit: df_side1 -c94b27e41064c521120627e07e2035cca1d24ffa d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1354575070 -0600 checkout: moving from df_side1 to df_side2 -d4207f77243500bec335ab477f9227fcdb1e271a f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 Edward Thomson 1354575206 -0600 commit: df_side2 -f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1354575381 -0600 checkout: moving from df_side2 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 c94b27e41064c521120627e07e2035cca1d24ffa Edward Thomson 1355017614 -0600 checkout: moving from master to df_side1 -c94b27e41064c521120627e07e2035cca1d24ffa a90bc3fb6f15181972a2959a921429efbd81a473 Edward Thomson 1355017650 -0600 commit: df_added -a90bc3fb6f15181972a2959a921429efbd81a473 c94b27e41064c521120627e07e2035cca1d24ffa Edward Thomson 1355017673 -0600 checkout: moving from df_side1 to c94b27e -c94b27e41064c521120627e07e2035cca1d24ffa d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355017673 -0600 rebase -i (squash): updating HEAD -d4207f77243500bec335ab477f9227fcdb1e271a 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355017673 -0600 rebase -i (squash): df_side1 -005b6fcc8fec71d2550bef8462d169b3c26aa14b 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355017676 -0600 rebase -i (finish): returning to refs/heads/df_side1 -005b6fcc8fec71d2550bef8462d169b3c26aa14b f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 Edward Thomson 1355017715 -0600 reset: moving to df_side2 -f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 8c749d9968d4b10dcfb06c9f97d0e5d92d337071 Edward Thomson 1355017744 -0600 commit: df_added -8c749d9968d4b10dcfb06c9f97d0e5d92d337071 f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 Edward Thomson 1355017754 -0600 checkout: moving from df_side1 to f8958bd -f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355017754 -0600 rebase -i (squash): updating HEAD -d4207f77243500bec335ab477f9227fcdb1e271a 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355017754 -0600 rebase -i (squash): df_side2 -0204a84f822acbf6386b36d33f1f6bc68bbbf858 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355017756 -0600 rebase -i (finish): returning to refs/heads/df_side1 -0204a84f822acbf6386b36d33f1f6bc68bbbf858 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355017793 -0600 reset: moving to 005b6fcc8fec71d2550bef8462d169b3c26aa14b -005b6fcc8fec71d2550bef8462d169b3c26aa14b 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355017826 -0600 reset: moving to 0204a84 -0204a84f822acbf6386b36d33f1f6bc68bbbf858 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1355017847 -0600 checkout: moving from df_side1 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355168677 -0600 checkout: moving from master to df_side1 -005b6fcc8fec71d2550bef8462d169b3c26aa14b 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355168829 -0600 checkout: moving from df_side1 to df_side1 -005b6fcc8fec71d2550bef8462d169b3c26aa14b 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355168838 -0600 checkout: moving from df_side1 to df_side1 -005b6fcc8fec71d2550bef8462d169b3c26aa14b e8107f24196736b870a318a0e28f048e29f6feff Edward Thomson 1355169065 -0600 commit: df_side1 -e8107f24196736b870a318a0e28f048e29f6feff 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355169081 -0600 checkout: moving from df_side1 to 005b6fc -005b6fcc8fec71d2550bef8462d169b3c26aa14b d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355169081 -0600 rebase -i (squash): updating HEAD -d4207f77243500bec335ab477f9227fcdb1e271a 80a8fbb3abb1ba423d554e9630b8fc2e5698f86b Edward Thomson 1355169081 -0600 rebase -i (squash): df_side1 -80a8fbb3abb1ba423d554e9630b8fc2e5698f86b 80a8fbb3abb1ba423d554e9630b8fc2e5698f86b Edward Thomson 1355169084 -0600 rebase -i (finish): returning to refs/heads/df_side1 -80a8fbb3abb1ba423d554e9630b8fc2e5698f86b 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355169141 -0600 checkout: moving from df_side1 to df_side2 -0204a84f822acbf6386b36d33f1f6bc68bbbf858 944f5dd1a867cab4c2bbcb896493435cae1dcc1a Edward Thomson 1355169174 -0600 commit: both -944f5dd1a867cab4c2bbcb896493435cae1dcc1a 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355169182 -0600 checkout: moving from df_side2 to 0204a84 -0204a84f822acbf6386b36d33f1f6bc68bbbf858 d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355169182 -0600 rebase -i (squash): updating HEAD -d4207f77243500bec335ab477f9227fcdb1e271a 57079a46233ae2b6df62e9ade71c4948512abefb Edward Thomson 1355169182 -0600 rebase -i (squash): df_side2 -57079a46233ae2b6df62e9ade71c4948512abefb 57079a46233ae2b6df62e9ade71c4948512abefb Edward Thomson 1355169185 -0600 rebase -i (finish): returning to refs/heads/df_side2 -57079a46233ae2b6df62e9ade71c4948512abefb 80a8fbb3abb1ba423d554e9630b8fc2e5698f86b Edward Thomson 1355169241 -0600 checkout: moving from df_side2 to df_side1 -80a8fbb3abb1ba423d554e9630b8fc2e5698f86b e65a9bb2af9f4c2d1c375dd0f8f8a46cf9c68812 Edward Thomson 1355169419 -0600 commit: side1 -e65a9bb2af9f4c2d1c375dd0f8f8a46cf9c68812 80a8fbb3abb1ba423d554e9630b8fc2e5698f86b Edward Thomson 1355169431 -0600 checkout: moving from df_side1 to 80a8fbb -80a8fbb3abb1ba423d554e9630b8fc2e5698f86b d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355169431 -0600 rebase -i (squash): updating HEAD -d4207f77243500bec335ab477f9227fcdb1e271a 5dc1018e90b19654bee986b7a0c268804d39659d Edward Thomson 1355169431 -0600 rebase -i (squash): df_side1 -5dc1018e90b19654bee986b7a0c268804d39659d 5dc1018e90b19654bee986b7a0c268804d39659d Edward Thomson 1355169435 -0600 rebase -i (finish): returning to refs/heads/df_side1 -5dc1018e90b19654bee986b7a0c268804d39659d 57079a46233ae2b6df62e9ade71c4948512abefb Edward Thomson 1355169439 -0600 checkout: moving from df_side1 to df_side2 -57079a46233ae2b6df62e9ade71c4948512abefb 58e853f66699fd02629fd50bde08082bc005933a Edward Thomson 1355169460 -0600 commit: side2 -58e853f66699fd02629fd50bde08082bc005933a 57079a46233ae2b6df62e9ade71c4948512abefb Edward Thomson 1355169469 -0600 checkout: moving from df_side2 to 57079a4 -57079a46233ae2b6df62e9ade71c4948512abefb d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355169469 -0600 rebase -i (squash): updating HEAD -d4207f77243500bec335ab477f9227fcdb1e271a fada9356aa3f74622327a3038ae9c6f92e1c5c1d Edward Thomson 1355169469 -0600 rebase -i (squash): df_side2 -fada9356aa3f74622327a3038ae9c6f92e1c5c1d fada9356aa3f74622327a3038ae9c6f92e1c5c1d Edward Thomson 1355169471 -0600 rebase -i (finish): returning to refs/heads/df_side2 -fada9356aa3f74622327a3038ae9c6f92e1c5c1d 5dc1018e90b19654bee986b7a0c268804d39659d Edward Thomson 1355169494 -0600 checkout: moving from df_side2 to df_side1 -5dc1018e90b19654bee986b7a0c268804d39659d d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355169663 -0600 checkout: moving from df_side1 to d4207f77243500bec335ab477f9227fcdb1e271a -d4207f77243500bec335ab477f9227fcdb1e271a 849619b03ae540acee4d1edec96b86993da6b497 Edward Thomson 1355169683 -0600 commit: both_dirs -849619b03ae540acee4d1edec96b86993da6b497 d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355169691 -0600 checkout: moving from 849619b03ae540acee4d1edec96b86993da6b497 to d4207f7 -d4207f77243500bec335ab477f9227fcdb1e271a bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1355169691 -0600 rebase -i (squash): updating HEAD -bd593285fc7fe4ca18ccdbabf027f5d689101452 a765fb87eb2f7a1920b73b2d5a057f8f8476a42b Edward Thomson 1355169691 -0600 rebase -i (squash): df_ancestor -a765fb87eb2f7a1920b73b2d5a057f8f8476a42b 5dc1018e90b19654bee986b7a0c268804d39659d Edward Thomson 1355169706 -0600 checkout: moving from a765fb87eb2f7a1920b73b2d5a057f8f8476a42b to df_side1 -5dc1018e90b19654bee986b7a0c268804d39659d a765fb87eb2f7a1920b73b2d5a057f8f8476a42b Edward Thomson 1355169715 -0600 checkout: moving from df_side1 to a765fb87eb2f7a1920b73b2d5a057f8f8476a42b^0 -a765fb87eb2f7a1920b73b2d5a057f8f8476a42b bc744705e1d8a019993cf88f62bc4020f1b80919 Edward Thomson 1355169801 -0600 commit: df_side1 -bc744705e1d8a019993cf88f62bc4020f1b80919 bc744705e1d8a019993cf88f62bc4020f1b80919 Edward Thomson 1355169822 -0600 checkout: moving from bc744705e1d8a019993cf88f62bc4020f1b80919 to df_side1 -bc744705e1d8a019993cf88f62bc4020f1b80919 fada9356aa3f74622327a3038ae9c6f92e1c5c1d Edward Thomson 1355169826 -0600 checkout: moving from df_side1 to df_side2 -fada9356aa3f74622327a3038ae9c6f92e1c5c1d a765fb87eb2f7a1920b73b2d5a057f8f8476a42b Edward Thomson 1355169866 -0600 checkout: moving from df_side2 to a765fb87eb2f7a1920b73b2d5a057f8f8476a42b^0 -a765fb87eb2f7a1920b73b2d5a057f8f8476a42b 95646149ab6b6ba6edc83cff678582538b457b2b Edward Thomson 1355169897 -0600 rebase: df_side2 -95646149ab6b6ba6edc83cff678582538b457b2b 95646149ab6b6ba6edc83cff678582538b457b2b Edward Thomson 1355169897 -0600 rebase finished: returning to refs/heads/df_side2 -95646149ab6b6ba6edc83cff678582538b457b2b bc744705e1d8a019993cf88f62bc4020f1b80919 Edward Thomson 1355169949 -0600 checkout: moving from df_side2 to df_side1 -bc744705e1d8a019993cf88f62bc4020f1b80919 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1355170046 -0600 checkout: moving from df_side1 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1355181639 -0600 checkout: moving from master to df_ancestor -bd593285fc7fe4ca18ccdbabf027f5d689101452 2da538570bc1e5b2c3e855bf702f35248ad0735f Edward Thomson 1355181673 -0600 commit: df_ancestor -2da538570bc1e5b2c3e855bf702f35248ad0735f a7dbfcbfc1a60709cb80b5ca24539008456531d0 Edward Thomson 1355181715 -0600 commit: df_side1 -a7dbfcbfc1a60709cb80b5ca24539008456531d0 a7dbfcbfc1a60709cb80b5ca24539008456531d0 Edward Thomson 1355181743 -0600 checkout: moving from df_ancestor to df_ancestor -a7dbfcbfc1a60709cb80b5ca24539008456531d0 9a301fbe6fada7dcb74fcd7c20269b5c743459a7 Edward Thomson 1355181775 -0600 commit: df_side2 -9a301fbe6fada7dcb74fcd7c20269b5c743459a7 a7dbfcbfc1a60709cb80b5ca24539008456531d0 Edward Thomson 1355181793 -0600 checkout: moving from df_ancestor to df_side1 -a7dbfcbfc1a60709cb80b5ca24539008456531d0 9a301fbe6fada7dcb74fcd7c20269b5c743459a7 Edward Thomson 1355181797 -0600 checkout: moving from df_side1 to df_side2 -9a301fbe6fada7dcb74fcd7c20269b5c743459a7 9a301fbe6fada7dcb74fcd7c20269b5c743459a7 Edward Thomson 1355182062 -0600 checkout: moving from df_side2 to df_ancestor -9a301fbe6fada7dcb74fcd7c20269b5c743459a7 2da538570bc1e5b2c3e855bf702f35248ad0735f Edward Thomson 1355182067 -0600 reset: moving to 2da538570bc1e5b2c3e855bf702f35248ad0735f -2da538570bc1e5b2c3e855bf702f35248ad0735f 2da538570bc1e5b2c3e855bf702f35248ad0735f Edward Thomson 1355182087 -0600 checkout: moving from df_ancestor to df_side2 -2da538570bc1e5b2c3e855bf702f35248ad0735f fc90237dc4891fa6c69827fc465632225e391618 Edward Thomson 1355182104 -0600 commit: df_side2 -fc90237dc4891fa6c69827fc465632225e391618 a7dbfcbfc1a60709cb80b5ca24539008456531d0 Edward Thomson 1355182111 -0600 checkout: moving from df_side2 to df_side1 -a7dbfcbfc1a60709cb80b5ca24539008456531d0 fc90237dc4891fa6c69827fc465632225e391618 Edward Thomson 1355182115 -0600 checkout: moving from df_side1 to df_side2 -fc90237dc4891fa6c69827fc465632225e391618 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1355182122 -0600 checkout: moving from df_side2 to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 d6cf6c7741b3316826af1314042550c97ded1d50 Edward Thomson 1358997543 -0600 checkout: moving from master to unrelated -d6cf6c7741b3316826af1314042550c97ded1d50 55b4e4687e7a0d9ca367016ed930f385d4022e6f Edward Thomson 1358997664 -0600 commit: conflicting changes -55b4e4687e7a0d9ca367016ed930f385d4022e6f bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1358997675 -0600 checkout: moving from unrelated to master -bd593285fc7fe4ca18ccdbabf027f5d689101452 88e185910a15cd13bdf44854ad037f4842b03b29 Edward Thomson 1365714471 -0500 checkout: moving from master to rename_conflict_ours -88e185910a15cd13bdf44854ad037f4842b03b29 bef6e37b3ee632ba74159168836f382fed21d77d Edward Thomson 1365714516 -0500 checkout: moving from rename_conflict_ours to bef6e37b3ee632ba74159168836f382fed21d77d -bef6e37b3ee632ba74159168836f382fed21d77d 01f149e1b8f84bd8896aaff6d6b22af88459ded0 Edward Thomson 1365714831 -0500 commit: rename ancestor -0000000000000000000000000000000000000000 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365714958 -0500 commit (initial): rename conflict ancestor -2392a2dacc9efb562b8635d6579fb458751c7c5b 88e185910a15cd13bdf44854ad037f4842b03b29 Edward Thomson 1365714980 -0500 checkout: moving from rename_conflict_ancestor to rename_conflict_ours -88e185910a15cd13bdf44854ad037f4842b03b29 7c2c5228c9e90170d4a35e6558e47163daf092e5 Edward Thomson 1365715250 -0500 commit: rename conflict ours -7c2c5228c9e90170d4a35e6558e47163daf092e5 2f4024ce528d36d8670c289cce5a7963e625bb0c Edward Thomson 1365715274 -0500 checkout: moving from rename_conflict_ours to rename_conflict_theirs -2f4024ce528d36d8670c289cce5a7963e625bb0c 56a638b76b75e068590ac999c2f8621e7f3e264c Edward Thomson 1365715362 -0500 commit: rename conflict theirs -56a638b76b75e068590ac999c2f8621e7f3e264c 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715368 -0500 checkout: moving from rename_conflict_theirs to rename_conflict_ancestor -2392a2dacc9efb562b8635d6579fb458751c7c5b 56a638b76b75e068590ac999c2f8621e7f3e264c Edward Thomson 1365715371 -0500 checkout: moving from rename_conflict_ancestor to rename_conflict_theirs -56a638b76b75e068590ac999c2f8621e7f3e264c 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715404 -0500 checkout: moving from rename_conflict_theirs to rename_conflict_ancestor -2392a2dacc9efb562b8635d6579fb458751c7c5b 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715438 -0500 checkout: moving from rename_conflict_ancestor to rename_conflict_ours -2392a2dacc9efb562b8635d6579fb458751c7c5b 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715480 -0500 checkout: moving from rename_conflict_ours to rename_conflict_ancestor -2392a2dacc9efb562b8635d6579fb458751c7c5b 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715486 -0500 checkout: moving from rename_conflict_ancestor to rename_conflict_ours -2392a2dacc9efb562b8635d6579fb458751c7c5b f3293571dcd708b6a3faf03818cd2844d000e198 Edward Thomson 1365715538 -0500 commit: rename conflict ours -f3293571dcd708b6a3faf03818cd2844d000e198 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715546 -0500 checkout: moving from rename_conflict_ours to rename_conflict_ancestor -2392a2dacc9efb562b8635d6579fb458751c7c5b 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715550 -0500 checkout: moving from rename_conflict_ancestor to rename_conflict_thiers -2392a2dacc9efb562b8635d6579fb458751c7c5b 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715554 -0500 checkout: moving from rename_conflict_thiers to rename_conflict_ancestor -2392a2dacc9efb562b8635d6579fb458751c7c5b 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715557 -0500 checkout: moving from rename_conflict_ancestor to rename_conflict_theirs -2392a2dacc9efb562b8635d6579fb458751c7c5b a802e06f1782a9645b9851bc7202cee74a8a4972 Edward Thomson 1365715572 -0500 commit: rename conflict theirs -a802e06f1782a9645b9851bc7202cee74a8a4972 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1365715620 -0500 checkout: moving from rename_conflict_theirs to master diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/branch deleted file mode 100644 index 8b0acb702..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351563886 -0500 branch: Created from HEAD -c607fc30883e335def28cd686b51f6cfa02b06ec 7cb63eed597130ba4abb87b3e544b85021905520 Edward Thomson 1351563965 -0500 commit: branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/df_ancestor b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/df_ancestor deleted file mode 100644 index df7695a66..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/df_ancestor +++ /dev/null @@ -1,5 +0,0 @@ -0000000000000000000000000000000000000000 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1355181639 -0600 branch: Created from HEAD -bd593285fc7fe4ca18ccdbabf027f5d689101452 2da538570bc1e5b2c3e855bf702f35248ad0735f Edward Thomson 1355181673 -0600 commit: df_ancestor -2da538570bc1e5b2c3e855bf702f35248ad0735f a7dbfcbfc1a60709cb80b5ca24539008456531d0 Edward Thomson 1355181715 -0600 commit: df_side1 -a7dbfcbfc1a60709cb80b5ca24539008456531d0 9a301fbe6fada7dcb74fcd7c20269b5c743459a7 Edward Thomson 1355181775 -0600 commit: df_side2 -9a301fbe6fada7dcb74fcd7c20269b5c743459a7 2da538570bc1e5b2c3e855bf702f35248ad0735f Edward Thomson 1355182067 -0600 reset: moving to 2da538570bc1e5b2c3e855bf702f35248ad0735f diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/df_side1 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/df_side1 deleted file mode 100644 index a504ad610..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/df_side1 +++ /dev/null @@ -1,14 +0,0 @@ -0000000000000000000000000000000000000000 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1354574697 -0600 branch: Created from HEAD -bd593285fc7fe4ca18ccdbabf027f5d689101452 d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1354574962 -0600 commit: df_ancestor -d4207f77243500bec335ab477f9227fcdb1e271a c94b27e41064c521120627e07e2035cca1d24ffa Edward Thomson 1354575027 -0600 commit: df_side1 -c94b27e41064c521120627e07e2035cca1d24ffa a90bc3fb6f15181972a2959a921429efbd81a473 Edward Thomson 1355017650 -0600 commit: df_added -a90bc3fb6f15181972a2959a921429efbd81a473 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355017676 -0600 rebase -i (finish): refs/heads/df_side1 onto c94b27e -005b6fcc8fec71d2550bef8462d169b3c26aa14b f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 Edward Thomson 1355017715 -0600 reset: moving to df_side2 -f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 8c749d9968d4b10dcfb06c9f97d0e5d92d337071 Edward Thomson 1355017744 -0600 commit: df_added -8c749d9968d4b10dcfb06c9f97d0e5d92d337071 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355017756 -0600 rebase -i (finish): refs/heads/df_side1 onto f8958bd -0204a84f822acbf6386b36d33f1f6bc68bbbf858 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355017793 -0600 reset: moving to 005b6fcc8fec71d2550bef8462d169b3c26aa14b -005b6fcc8fec71d2550bef8462d169b3c26aa14b 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355017826 -0600 reset: moving to 0204a84 -005b6fcc8fec71d2550bef8462d169b3c26aa14b e8107f24196736b870a318a0e28f048e29f6feff Edward Thomson 1355169065 -0600 commit: df_side1 -e8107f24196736b870a318a0e28f048e29f6feff 80a8fbb3abb1ba423d554e9630b8fc2e5698f86b Edward Thomson 1355169084 -0600 rebase -i (finish): refs/heads/df_side1 onto 005b6fc -80a8fbb3abb1ba423d554e9630b8fc2e5698f86b e65a9bb2af9f4c2d1c375dd0f8f8a46cf9c68812 Edward Thomson 1355169419 -0600 commit: side1 -e65a9bb2af9f4c2d1c375dd0f8f8a46cf9c68812 5dc1018e90b19654bee986b7a0c268804d39659d Edward Thomson 1355169435 -0600 rebase -i (finish): refs/heads/df_side1 onto 80a8fbb diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/df_side2 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/df_side2 deleted file mode 100644 index 27d833eda..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/df_side2 +++ /dev/null @@ -1,9 +0,0 @@ -0000000000000000000000000000000000000000 d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1354575051 -0600 branch: Created from d4207f77243500bec335ab477f9227fcdb1e271a -d4207f77243500bec335ab477f9227fcdb1e271a f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 Edward Thomson 1354575206 -0600 commit: df_side2 -0204a84f822acbf6386b36d33f1f6bc68bbbf858 944f5dd1a867cab4c2bbcb896493435cae1dcc1a Edward Thomson 1355169174 -0600 commit: both -944f5dd1a867cab4c2bbcb896493435cae1dcc1a 57079a46233ae2b6df62e9ade71c4948512abefb Edward Thomson 1355169185 -0600 rebase -i (finish): refs/heads/df_side2 onto 0204a84 -57079a46233ae2b6df62e9ade71c4948512abefb 58e853f66699fd02629fd50bde08082bc005933a Edward Thomson 1355169460 -0600 commit: side2 -58e853f66699fd02629fd50bde08082bc005933a fada9356aa3f74622327a3038ae9c6f92e1c5c1d Edward Thomson 1355169471 -0600 rebase -i (finish): refs/heads/df_side2 onto 57079a4 -fada9356aa3f74622327a3038ae9c6f92e1c5c1d 95646149ab6b6ba6edc83cff678582538b457b2b Edward Thomson 1355169897 -0600 rebase finished: refs/heads/df_side2 onto a765fb87eb2f7a1920b73b2d5a057f8f8476a42b -0000000000000000000000000000000000000000 2da538570bc1e5b2c3e855bf702f35248ad0735f Edward Thomson 1355182087 -0600 branch: Created from HEAD -2da538570bc1e5b2c3e855bf702f35248ad0735f fc90237dc4891fa6c69827fc465632225e391618 Edward Thomson 1355182104 -0600 commit: df_side2 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/ff_branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/ff_branch deleted file mode 100644 index c4706175d..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/ff_branch +++ /dev/null @@ -1,5 +0,0 @@ -0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351605785 -0500 branch: Created from HEAD -977c696519c5a3004c5f1d15d60c89dbeb8f235f 33d500f588fbbe65901d82b4e6b008e549064be0 Edward Thomson 1351605830 -0500 commit: fastforward -33d500f588fbbe65901d82b4e6b008e549064be0 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351990202 -0500 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1351990205 -0500 merge master: Fast-forward -bd593285fc7fe4ca18ccdbabf027f5d689101452 fd89f8cffb663ac89095a0f9764902e93ceaca6a Edward Thomson 1351990229 -0500 commit: fastforward diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/master b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/master deleted file mode 100644 index 60475992a..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,5 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351563869 -0500 commit (initial): initial -c607fc30883e335def28cd686b51f6cfa02b06ec 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351564033 -0500 commit: master -977c696519c5a3004c5f1d15d60c89dbeb8f235f 4e0d9401aee78eb345a8685a859d37c8c3c0bbed Edward Thomson 1351875091 -0500 merge octo1 octo2 octo3 octo4: Merge made by the 'octopus' strategy. -4e0d9401aee78eb345a8685a859d37c8c3c0bbed 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae Edward Thomson 1351875108 -0500 reset: moving to 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae -54269b3f6ec3d7d4ede24dd350dd5d605495c3ae 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875584 -0500 reset: moving to 977c696519c5a3004c5f1d15d60c89dbeb8f235f diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo1 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo1 deleted file mode 100644 index 0b6c9214a..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo1 +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874933 -0500 branch: Created from HEAD -977c696519c5a3004c5f1d15d60c89dbeb8f235f 16f825815cfd20a07a75c71554e82d8eede0b061 Edward Thomson 1351874954 -0500 commit: octo1 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo2 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo2 deleted file mode 100644 index 5392a4f86..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo2 +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874960 -0500 branch: Created from HEAD -977c696519c5a3004c5f1d15d60c89dbeb8f235f 158dc7bedb202f5b26502bf3574faa7f4238d56c Edward Thomson 1351874974 -0500 commit: octo2 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo3 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo3 deleted file mode 100644 index 7db5617c8..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo3 +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874980 -0500 branch: Created from HEAD -977c696519c5a3004c5f1d15d60c89dbeb8f235f 50ce7d7d01217679e26c55939eef119e0c93e272 Edward Thomson 1351874998 -0500 commit: octo3 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo4 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo4 deleted file mode 100644 index b0f9e42ef..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo4 +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875010 -0500 branch: Created from HEAD -977c696519c5a3004c5f1d15d60c89dbeb8f235f 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae Edward Thomson 1351875023 -0500 commit: octo4 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo5 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo5 deleted file mode 100644 index 614563edf..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo5 +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875031 -0500 branch: Created from HEAD -977c696519c5a3004c5f1d15d60c89dbeb8f235f e4f618a2c3ed0669308735727df5ebf2447f022f Edward Thomson 1351875041 -0500 commit: octo5 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo6 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo6 deleted file mode 100644 index 4c812eacc..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/octo6 +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875046 -0500 branch: Created from HEAD -977c696519c5a3004c5f1d15d60c89dbeb8f235f 4ca408a8c88655f7586a1b580be6fad138121e98 Edward Thomson 1351875057 -0500 commit: octo5 -4ca408a8c88655f7586a1b580be6fad138121e98 b6f610aef53bd343e6c96227de874c66f00ee8e8 Edward Thomson 1351875065 -0500 commit (amend): octo6 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/renames1 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/renames1 deleted file mode 100644 index 58a7e0565..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/renames1 +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1353177745 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 412b32fb66137366147f1801ecc962452757d48a Edward Thomson 1353177886 -0600 commit: renames diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/renames2 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/renames2 deleted file mode 100644 index 5645ecee7..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/renames2 +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1353794647 -0600 branch: Created from HEAD -bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1353794677 -0600 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec ab40af3cb8a3ed2e2843e96d9aa7871336b94573 Edward Thomson 1353794852 -0600 commit: renames2 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10 deleted file mode 100644 index b6bd247e7..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10 +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100171 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 53825f41ac8d640612f9423a2f03a69f3d96809a Edward Thomson 1352100193 -0600 commit: trivial-10 -53825f41ac8d640612f9423a2f03a69f3d96809a 0ec5f433959cd46177f745903353efb5be08d151 Edward Thomson 1352100223 -0600 commit: trivial-10 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10-branch deleted file mode 100644 index 14ce9e545..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10-branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 53825f41ac8d640612f9423a2f03a69f3d96809a Edward Thomson 1352100200 -0600 branch: Created from HEAD -53825f41ac8d640612f9423a2f03a69f3d96809a 11f4f3c08b737f5fd896cbefa1425ee63b21b2fa Edward Thomson 1352100211 -0600 commit: trivial-10-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11 deleted file mode 100644 index 3e6b77437..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11 +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100930 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 35632e43612c06a3ea924bfbacd48333da874c29 Edward Thomson 1352100958 -0600 commit: trivial-11 -35632e43612c06a3ea924bfbacd48333da874c29 3168dca1a561889b045a6441909f4c56145e666d Edward Thomson 1352100992 -0600 commit: trivial-11 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11-branch deleted file mode 100644 index 30d5ec7a3..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11-branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 35632e43612c06a3ea924bfbacd48333da874c29 Edward Thomson 1352100964 -0600 branch: Created from HEAD -35632e43612c06a3ea924bfbacd48333da874c29 6718a45909532d1fcf5600d0877f7fe7e78f0b86 Edward Thomson 1352100978 -0600 commit: trivial-11-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13 deleted file mode 100644 index 3a7302dea..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13 +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100559 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa Edward Thomson 1352100589 -0600 commit: trivial-13 -8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa a3fabece9eb8748da810e1e08266fef9b7136ad4 Edward Thomson 1352100625 -0600 commit: trivial-13 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13-branch deleted file mode 100644 index bb2604244..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13-branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa Edward Thomson 1352100604 -0600 branch: Created from HEAD -8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa 05f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c Edward Thomson 1352100610 -0600 commit: trivial-13-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14 deleted file mode 100644 index 4b70d2898..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14 +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352101083 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 596803b523203a4851c824c07366906f8353f4ad Edward Thomson 1352101113 -0600 commit: trivial-14 -596803b523203a4851c824c07366906f8353f4ad 7e2d058d5fedf8329db44db4fac610d6b1a89159 Edward Thomson 1352101141 -0600 commit: trivial-14 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14-branch deleted file mode 100644 index 8e491ca68..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14-branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 596803b523203a4851c824c07366906f8353f4ad Edward Thomson 1352101117 -0600 branch: Created from HEAD -596803b523203a4851c824c07366906f8353f4ad 8187117062b750eed4f93fd7e899f17b52ce554d Edward Thomson 1352101132 -0600 commit: trivial-14-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt deleted file mode 100644 index a2a28d401..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352091695 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 566ab53c220a2eafc1212af1a024513230280ab9 Edward Thomson 1352092452 -0600 commit: 2alt diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt-branch deleted file mode 100644 index a0a48ae35..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt-branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352092411 -0600 branch: Created from HEAD -c607fc30883e335def28cd686b51f6cfa02b06ec c9174cef549ec94ecbc43ef03cdc775b4950becb Edward Thomson 1352092434 -0600 commit: 2alt-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt deleted file mode 100644 index 4374d3888..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt +++ /dev/null @@ -1,3 +0,0 @@ -566ab53c220a2eafc1212af1a024513230280ab9 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094547 -0600 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 5459c89aa0026d543ce8343bd89871bce543f9c2 Edward Thomson 1352094580 -0600 commit: 3alt -5459c89aa0026d543ce8343bd89871bce543f9c2 4c9fac0707f8d4195037ae5a681aa48626491541 Edward Thomson 1352094610 -0600 commit: 3alt-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt-branch deleted file mode 100644 index 7a2e6f822..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt-branch +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094594 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4 deleted file mode 100644 index 3ee6d2503..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4 +++ /dev/null @@ -1,2 +0,0 @@ -566ab53c220a2eafc1212af1a024513230280ab9 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094764 -0600 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec cc3e3009134cb88014129fc8858d1101359e5e2f Edward Thomson 1352094815 -0600 commit: trivial-4 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4-branch deleted file mode 100644 index 51f8a9290..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4-branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094830 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 183310e30fb1499af8c619108ffea4d300b5e778 Edward Thomson 1352094856 -0600 commit: trivial-4-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1 deleted file mode 100644 index 14497029a..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1 +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096606 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 Edward Thomson 1352096643 -0600 commit: 5alt-1 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1-branch deleted file mode 100644 index 4cff83526..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1-branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096657 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 478172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 Edward Thomson 1352096689 -0600 commit: 5alt-1-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2 deleted file mode 100644 index 3ca077b29..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2 +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096711 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec ebc09d0137cfb0c26697aed0109fb943ad906f3f Edward Thomson 1352096764 -0600 commit: existing file -ebc09d0137cfb0c26697aed0109fb943ad906f3f 3b47b031b3e55ae11e14a05260b1c3ffd6838d55 Edward Thomson 1352096815 -0600 commit: 5alt-2 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2-branch deleted file mode 100644 index e7bb901f2..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2-branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 ebc09d0137cfb0c26697aed0109fb943ad906f3f Edward Thomson 1352096833 -0600 branch: Created from ebc09d0 -ebc09d0137cfb0c26697aed0109fb943ad906f3f f48097eb340dc5a7cae55aabcf1faf4548aa821f Edward Thomson 1352096855 -0600 commit: 5alt-2-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6 deleted file mode 100644 index 7c717a210..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6 +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352097371 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec f7c332bd4d4d4b777366cae4d24d1687477576bf Edward Thomson 1352097389 -0600 commit: 6 -f7c332bd4d4d4b777366cae4d24d1687477576bf 99b4f7e4f24470fa06b980bc21f1095c2a9425c0 Edward Thomson 1352097404 -0600 commit: trivial-6 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6-branch deleted file mode 100644 index 715f3ae1c..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6-branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 f7c332bd4d4d4b777366cae4d24d1687477576bf Edward Thomson 1352097414 -0600 branch: Created from f7c332bd4d4d4b777366cae4d24d1687477576bf -f7c332bd4d4d4b777366cae4d24d1687477576bf a43150a738849c59376cf30bb2a68348a83c8f48 Edward Thomson 1352097431 -0600 commit: 6-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7 deleted file mode 100644 index a014f1722..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7 +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352099765 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099790 -0600 commit: trivial-7 -092ce8682d7f3a2a3a769a6daca58950168ba5c4 d874671ef5b20184836cb983bb273e5280384d0b Edward Thomson 1352099947 -0600 commit: trivial-7 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7-branch deleted file mode 100644 index 22331d78c..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7-branch +++ /dev/null @@ -1,5 +0,0 @@ -0000000000000000000000000000000000000000 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099799 -0600 branch: Created from HEAD -092ce8682d7f3a2a3a769a6daca58950168ba5c4 73cbfdc4fe843169e5b2af8dcad03cbf3acf306c Edward Thomson 1352099812 -0600 commit: trivial-7-branch -73cbfdc4fe843169e5b2af8dcad03cbf3acf306c 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099874 -0600 reset: moving to 092ce8682d7f3a2a3a769a6daca58950168ba5c4 -092ce8682d7f3a2a3a769a6daca58950168ba5c4 009b9cab6fdac02915a88ecd078b7a792ed802d8 Edward Thomson 1352099921 -0600 commit: removed in 7 -009b9cab6fdac02915a88ecd078b7a792ed802d8 5195a1b480f66691b667f10a9e41e70115a78351 Edward Thomson 1352099927 -0600 commit (amend): trivial-7-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8 deleted file mode 100644 index 7670c3506..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8 +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352098816 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec 75a811bf6bc57694adb3fe604786f3a4efd1cd1b Edward Thomson 1352098884 -0600 commit: trivial-8 -75a811bf6bc57694adb3fe604786f3a4efd1cd1b 3575826c96a975031d2c14368529cc5c4353a8fd Edward Thomson 1352099000 -0600 commit: trivial-8 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8-branch deleted file mode 100644 index c4d68edcf..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8-branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 75a811bf6bc57694adb3fe604786f3a4efd1cd1b Edward Thomson 1352098947 -0600 branch: Created from HEAD -75a811bf6bc57694adb3fe604786f3a4efd1cd1b 52d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 Edward Thomson 1352098979 -0600 commit: trivial-8-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9 b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9 deleted file mode 100644 index 09a343bdb..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9 +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100268 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec -c607fc30883e335def28cd686b51f6cfa02b06ec f0053b8060bb3f0be5cbcc3147a07ece26bf097e Edward Thomson 1352100304 -0600 commit: trivial-9 -f0053b8060bb3f0be5cbcc3147a07ece26bf097e c35dee9bcc0e989f3b0c40f68372a9a51b6c4e6a Edward Thomson 1352100333 -0600 commit: trivial-9 diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9-branch b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9-branch deleted file mode 100644 index 1b126fb7b..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9-branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 f0053b8060bb3f0be5cbcc3147a07ece26bf097e Edward Thomson 1352100310 -0600 branch: Created from HEAD -f0053b8060bb3f0be5cbcc3147a07ece26bf097e 13d1be4ea52a6ced1d7a1d832f0ee3c399348e5e Edward Thomson 1352100317 -0600 commit: trivial-9-branch diff --git a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/unrelated b/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/unrelated deleted file mode 100644 index a83ffc26a..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/logs/refs/heads/unrelated +++ /dev/null @@ -1 +0,0 @@ -d6cf6c7741b3316826af1314042550c97ded1d50 55b4e4687e7a0d9ca367016ed930f385d4022e6f Edward Thomson 1358997664 -0600 commit: conflicting changes diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/00/5b6fcc8fec71d2550bef8462d169b3c26aa14b b/tests-clar/resources/merge-resolve/.gitted/objects/00/5b6fcc8fec71d2550bef8462d169b3c26aa14b deleted file mode 100644 index 82a8da597..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/00/5b6fcc8fec71d2550bef8462d169b3c26aa14b and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/00/9b9cab6fdac02915a88ecd078b7a792ed802d8 b/tests-clar/resources/merge-resolve/.gitted/objects/00/9b9cab6fdac02915a88ecd078b7a792ed802d8 deleted file mode 100644 index f663a3c51..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/00/9b9cab6fdac02915a88ecd078b7a792ed802d8 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/00/c7d33f1ffa79d19c2272b370fcaeaadba49c08 b/tests-clar/resources/merge-resolve/.gitted/objects/00/c7d33f1ffa79d19c2272b370fcaeaadba49c08 deleted file mode 100644 index 72698dc3d..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/00/c7d33f1ffa79d19c2272b370fcaeaadba49c08 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/01/f149e1b8f84bd8896aaff6d6b22af88459ded0 b/tests-clar/resources/merge-resolve/.gitted/objects/01/f149e1b8f84bd8896aaff6d6b22af88459ded0 deleted file mode 100644 index aa6336d3f..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/01/f149e1b8f84bd8896aaff6d6b22af88459ded0 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/02/04a84f822acbf6386b36d33f1f6bc68bbbf858 b/tests-clar/resources/merge-resolve/.gitted/objects/02/04a84f822acbf6386b36d33f1f6bc68bbbf858 deleted file mode 100644 index 2f0a0e1bb..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/02/04a84f822acbf6386b36d33f1f6bc68bbbf858 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/02/251f990ca8e92e7ae61d3426163fa821c64001 b/tests-clar/resources/merge-resolve/.gitted/objects/02/251f990ca8e92e7ae61d3426163fa821c64001 deleted file mode 100644 index d623117c5..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/02/251f990ca8e92e7ae61d3426163fa821c64001 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/03/21415405cb906c46869919af56d51dbbe5e85c b/tests-clar/resources/merge-resolve/.gitted/objects/03/21415405cb906c46869919af56d51dbbe5e85c deleted file mode 100644 index 277bdcff5..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/03/21415405cb906c46869919af56d51dbbe5e85c and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/03/2ebc5ab85d9553bb187d3cd40875ff23a63ed0 b/tests-clar/resources/merge-resolve/.gitted/objects/03/2ebc5ab85d9553bb187d3cd40875ff23a63ed0 deleted file mode 100644 index e5404d838..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/03/2ebc5ab85d9553bb187d3cd40875ff23a63ed0 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/03/b87706555accbf874ccd410dbda01e8e70a67f b/tests-clar/resources/merge-resolve/.gitted/objects/03/b87706555accbf874ccd410dbda01e8e70a67f deleted file mode 100644 index 0befcd735..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/03/b87706555accbf874ccd410dbda01e8e70a67f and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/03/dad1005e5d06d418f50b12e0bcd48ff2306a03 b/tests-clar/resources/merge-resolve/.gitted/objects/03/dad1005e5d06d418f50b12e0bcd48ff2306a03 deleted file mode 100644 index 04011a2ce..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/03/dad1005e5d06d418f50b12e0bcd48ff2306a03 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/05/1ffd7901a442faf56b226161649074f15c7c47 b/tests-clar/resources/merge-resolve/.gitted/objects/05/1ffd7901a442faf56b226161649074f15c7c47 deleted file mode 100644 index 65fa6894f..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/05/1ffd7901a442faf56b226161649074f15c7c47 +++ /dev/null @@ -1 +0,0 @@ -x+)JMU06`040031QH,-M-JOMLI+(aH:,:C: o>ZC'g$楧f&%%g5qYeZokM2ԐX\ZDPC~^ZNfrIf^:XZHي1O(_,' jvn~JfZ&5&ؽ +gz43^2 I{| 2mg˾15ӿ,\})TC)0Xvz֛9MՅ'6b# \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/05/8541fc37114bfc1dddf6bd6bffc7fae5c2e6fe b/tests-clar/resources/merge-resolve/.gitted/objects/05/8541fc37114bfc1dddf6bd6bffc7fae5c2e6fe deleted file mode 100644 index d79dc30ba..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/05/8541fc37114bfc1dddf6bd6bffc7fae5c2e6fe and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/05/f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c b/tests-clar/resources/merge-resolve/.gitted/objects/05/f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c deleted file mode 100644 index 7b4b152f3..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/05/f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/07/a759da919f737221791d542f176ab49c88837f b/tests-clar/resources/merge-resolve/.gitted/objects/07/a759da919f737221791d542f176ab49c88837f deleted file mode 100644 index a34b6c235..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/07/a759da919f737221791d542f176ab49c88837f and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/07/c514b04698e068892b31c8d352b85813b99c6e b/tests-clar/resources/merge-resolve/.gitted/objects/07/c514b04698e068892b31c8d352b85813b99c6e deleted file mode 100644 index 23ab92171..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/07/c514b04698e068892b31c8d352b85813b99c6e and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/09/055301463b7f2f8ee5d368f8ed5c0a40ad8515 b/tests-clar/resources/merge-resolve/.gitted/objects/09/055301463b7f2f8ee5d368f8ed5c0a40ad8515 deleted file mode 100644 index bf5b0fcc5..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/09/055301463b7f2f8ee5d368f8ed5c0a40ad8515 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/09/17bb159596aea4d295f4857da77e8f96b3c7dc b/tests-clar/resources/merge-resolve/.gitted/objects/09/17bb159596aea4d295f4857da77e8f96b3c7dc deleted file mode 100644 index 9fb640dd5..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/09/17bb159596aea4d295f4857da77e8f96b3c7dc and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/09/2ce8682d7f3a2a3a769a6daca58950168ba5c4 b/tests-clar/resources/merge-resolve/.gitted/objects/09/2ce8682d7f3a2a3a769a6daca58950168ba5c4 deleted file mode 100644 index b709cf461..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/09/2ce8682d7f3a2a3a769a6daca58950168ba5c4 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/09/3bebf072dd4bbba88833667d6ffe454df199e1 b/tests-clar/resources/merge-resolve/.gitted/objects/09/3bebf072dd4bbba88833667d6ffe454df199e1 deleted file mode 100644 index ae13207d7..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/09/3bebf072dd4bbba88833667d6ffe454df199e1 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/09/768bed22680cdb0859683fa9677ccc8d5a25c1 b/tests-clar/resources/merge-resolve/.gitted/objects/09/768bed22680cdb0859683fa9677ccc8d5a25c1 deleted file mode 100644 index 5f4b4dab1..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/09/768bed22680cdb0859683fa9677ccc8d5a25c1 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/0a/75d9aac1dc84fb5aa51f7325c0ab53242ddef7 b/tests-clar/resources/merge-resolve/.gitted/objects/0a/75d9aac1dc84fb5aa51f7325c0ab53242ddef7 deleted file mode 100644 index d5377341a..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/0a/75d9aac1dc84fb5aa51f7325c0ab53242ddef7 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/0c/fd6c54ef6532d862408f562309dc9c74a401e8 b/tests-clar/resources/merge-resolve/.gitted/objects/0c/fd6c54ef6532d862408f562309dc9c74a401e8 deleted file mode 100644 index 40f628f89..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/0c/fd6c54ef6532d862408f562309dc9c74a401e8 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/0d/52e3a556e189ba0948ae56780918011c1b167d b/tests-clar/resources/merge-resolve/.gitted/objects/0d/52e3a556e189ba0948ae56780918011c1b167d deleted file mode 100644 index 4b633e504..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/0d/52e3a556e189ba0948ae56780918011c1b167d and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/0d/872f8e871a30208305978ecbf9e66d864f1638 b/tests-clar/resources/merge-resolve/.gitted/objects/0d/872f8e871a30208305978ecbf9e66d864f1638 deleted file mode 100644 index 4cbc18e84..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/0d/872f8e871a30208305978ecbf9e66d864f1638 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/0e/c5f433959cd46177f745903353efb5be08d151 b/tests-clar/resources/merge-resolve/.gitted/objects/0e/c5f433959cd46177f745903353efb5be08d151 deleted file mode 100644 index 1bee56c14..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/0e/c5f433959cd46177f745903353efb5be08d151 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/11/deab00b2d3a6f5a3073988ac050c2d7b6655e2 b/tests-clar/resources/merge-resolve/.gitted/objects/11/deab00b2d3a6f5a3073988ac050c2d7b6655e2 deleted file mode 100644 index 857b23686..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/11/deab00b2d3a6f5a3073988ac050c2d7b6655e2 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/11/f4f3c08b737f5fd896cbefa1425ee63b21b2fa b/tests-clar/resources/merge-resolve/.gitted/objects/11/f4f3c08b737f5fd896cbefa1425ee63b21b2fa deleted file mode 100644 index 6555194cb..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/11/f4f3c08b737f5fd896cbefa1425ee63b21b2fa +++ /dev/null @@ -1 +0,0 @@ -xQ D\fw)c^` ۴-Q/ơdb^ץjEDC$u> , z@8qjk<٩G>z2Lva2)Veŏ:%˜{A|Ǽ5K@mg9jY _;n,YyP \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/13/d1be4ea52a6ced1d7a1d832f0ee3c399348e5e b/tests-clar/resources/merge-resolve/.gitted/objects/13/d1be4ea52a6ced1d7a1d832f0ee3c399348e5e deleted file mode 100644 index 4e4e175e8..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/13/d1be4ea52a6ced1d7a1d832f0ee3c399348e5e and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/14/39088f509b79b1535b64193137d3ce4b240734 b/tests-clar/resources/merge-resolve/.gitted/objects/14/39088f509b79b1535b64193137d3ce4b240734 deleted file mode 100644 index 51ddf6dcb..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/14/39088f509b79b1535b64193137d3ce4b240734 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/15/8dc7bedb202f5b26502bf3574faa7f4238d56c b/tests-clar/resources/merge-resolve/.gitted/objects/15/8dc7bedb202f5b26502bf3574faa7f4238d56c deleted file mode 100644 index 064423d0c..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/15/8dc7bedb202f5b26502bf3574faa7f4238d56c +++ /dev/null @@ -1,2 +0,0 @@ -xK!D]sCboi2. bK*Eep73UӾ*NYYIԔ)jL:8<{NޓH6iDC"mqH!9Tm9>R^i.= -G'+~@@j+7أENsFt]7bN) \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/16/f825815cfd20a07a75c71554e82d8eede0b061 b/tests-clar/resources/merge-resolve/.gitted/objects/16/f825815cfd20a07a75c71554e82d8eede0b061 deleted file mode 100644 index 82d65253b..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/16/f825815cfd20a07a75c71554e82d8eede0b061 +++ /dev/null @@ -1 +0,0 @@ -xK!D]sObo hJqo6AJـT1h3'Lՠ.{ec,a`ZJT1#e+هJUi">\+ ץG_X6IvN;^bYgGMM \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/17/8940b450f238a56c0d75b7955cb57b38191982 b/tests-clar/resources/merge-resolve/.gitted/objects/17/8940b450f238a56c0d75b7955cb57b38191982 deleted file mode 100644 index 94e571e65..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/17/8940b450f238a56c0d75b7955cb57b38191982 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/18/3310e30fb1499af8c619108ffea4d300b5e778 b/tests-clar/resources/merge-resolve/.gitted/objects/18/3310e30fb1499af8c619108ffea4d300b5e778 deleted file mode 100644 index 1c4010d04..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/18/3310e30fb1499af8c619108ffea4d300b5e778 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/18/cb316b1cefa0f8a6946f0e201a8e1a6f845ab9 b/tests-clar/resources/merge-resolve/.gitted/objects/18/cb316b1cefa0f8a6946f0e201a8e1a6f845ab9 deleted file mode 100644 index 30f3110f1..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/18/cb316b1cefa0f8a6946f0e201a8e1a6f845ab9 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/19/b7ac485269b672a101060894de3ba9c2a24dd1 b/tests-clar/resources/merge-resolve/.gitted/objects/19/b7ac485269b672a101060894de3ba9c2a24dd1 deleted file mode 100644 index e34ccb855..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/19/b7ac485269b672a101060894de3ba9c2a24dd1 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/1a/010b1c0f081b2e8901d55307a15c29ff30af0e b/tests-clar/resources/merge-resolve/.gitted/objects/1a/010b1c0f081b2e8901d55307a15c29ff30af0e deleted file mode 100644 index 6039df00e..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/1a/010b1c0f081b2e8901d55307a15c29ff30af0e and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/1c/ff9ec6a47a537380dedfdd17c9e76d74259a2b b/tests-clar/resources/merge-resolve/.gitted/objects/1c/ff9ec6a47a537380dedfdd17c9e76d74259a2b deleted file mode 100644 index 30802bcec..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/1c/ff9ec6a47a537380dedfdd17c9e76d74259a2b and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/1e/4ff029aee68d0d69ef9eb6efa6cbf1ec732f99 b/tests-clar/resources/merge-resolve/.gitted/objects/1e/4ff029aee68d0d69ef9eb6efa6cbf1ec732f99 deleted file mode 100644 index 5183b8360..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/1e/4ff029aee68d0d69ef9eb6efa6cbf1ec732f99 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/1f/81433e3161efbf250576c58fede7f6b836f3d3 b/tests-clar/resources/merge-resolve/.gitted/objects/1f/81433e3161efbf250576c58fede7f6b836f3d3 deleted file mode 100644 index 970855675..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/1f/81433e3161efbf250576c58fede7f6b836f3d3 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/20/91d94c8bd3eb0835dc5220de5e8bb310fa1513 b/tests-clar/resources/merge-resolve/.gitted/objects/20/91d94c8bd3eb0835dc5220de5e8bb310fa1513 deleted file mode 100644 index a843890c0..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/20/91d94c8bd3eb0835dc5220de5e8bb310fa1513 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/21/671e290278286fb2ce4c63d01699b67adce331 b/tests-clar/resources/merge-resolve/.gitted/objects/21/671e290278286fb2ce4c63d01699b67adce331 deleted file mode 100644 index b656d0001..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/21/671e290278286fb2ce4c63d01699b67adce331 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/22/7792b52aaa0b238bea00ec7e509b02623f168c b/tests-clar/resources/merge-resolve/.gitted/objects/22/7792b52aaa0b238bea00ec7e509b02623f168c deleted file mode 100644 index 3bb19bb77..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/22/7792b52aaa0b238bea00ec7e509b02623f168c and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/23/3c0919c998ed110a4b6ff36f353aec8b713487 b/tests-clar/resources/merge-resolve/.gitted/objects/23/3c0919c998ed110a4b6ff36f353aec8b713487 deleted file mode 100644 index d0c8c9e1d..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/23/3c0919c998ed110a4b6ff36f353aec8b713487 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/23/92a2dacc9efb562b8635d6579fb458751c7c5b b/tests-clar/resources/merge-resolve/.gitted/objects/23/92a2dacc9efb562b8635d6579fb458751c7c5b deleted file mode 100644 index 86127a344..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/23/92a2dacc9efb562b8635d6579fb458751c7c5b and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/24/1a1005cd9b980732741b74385b891142bcba28 b/tests-clar/resources/merge-resolve/.gitted/objects/24/1a1005cd9b980732741b74385b891142bcba28 deleted file mode 100644 index 9b65f666f..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/24/1a1005cd9b980732741b74385b891142bcba28 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/24/2591eb280ee9eeb2ce63524b9a8b9bc4cb515d b/tests-clar/resources/merge-resolve/.gitted/objects/24/2591eb280ee9eeb2ce63524b9a8b9bc4cb515d deleted file mode 100644 index 74a01373f..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/24/2591eb280ee9eeb2ce63524b9a8b9bc4cb515d and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/24/90b9f1a079420870027deefb49f51d6656cf74 b/tests-clar/resources/merge-resolve/.gitted/objects/24/90b9f1a079420870027deefb49f51d6656cf74 deleted file mode 100644 index 60497caa5..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/24/90b9f1a079420870027deefb49f51d6656cf74 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/25/9d08ca43af9200e9ea9a098e44a5a350ebd9b3 b/tests-clar/resources/merge-resolve/.gitted/objects/25/9d08ca43af9200e9ea9a098e44a5a350ebd9b3 deleted file mode 100644 index 2bae66998..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/25/9d08ca43af9200e9ea9a098e44a5a350ebd9b3 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/25/c40b7660c08c8fb581f770312f41b9b03119d1 b/tests-clar/resources/merge-resolve/.gitted/objects/25/c40b7660c08c8fb581f770312f41b9b03119d1 deleted file mode 100644 index 185214727..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/25/c40b7660c08c8fb581f770312f41b9b03119d1 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/26/153a3ff3649b6c2bb652d3f06878c6e0a172f9 b/tests-clar/resources/merge-resolve/.gitted/objects/26/153a3ff3649b6c2bb652d3f06878c6e0a172f9 deleted file mode 100644 index 4fcaa07e2..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/26/153a3ff3649b6c2bb652d3f06878c6e0a172f9 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/27/133da702ba3c60af2a01e96c2555ff4045d692 b/tests-clar/resources/merge-resolve/.gitted/objects/27/133da702ba3c60af2a01e96c2555ff4045d692 deleted file mode 100644 index 08e61f844..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/27/133da702ba3c60af2a01e96c2555ff4045d692 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/2b/0de5dc27505dcdd83a75c8bf1fcd9462cd7add b/tests-clar/resources/merge-resolve/.gitted/objects/2b/0de5dc27505dcdd83a75c8bf1fcd9462cd7add deleted file mode 100644 index a95f926f8..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/2b/0de5dc27505dcdd83a75c8bf1fcd9462cd7add and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/2b/5f1f181ee3b58ea751f5dd5d8f9b445520a136 b/tests-clar/resources/merge-resolve/.gitted/objects/2b/5f1f181ee3b58ea751f5dd5d8f9b445520a136 deleted file mode 100644 index d24231eda..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/2b/5f1f181ee3b58ea751f5dd5d8f9b445520a136 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/2b/d0a343aeef7a2cf0d158478966a6e587ff3863 b/tests-clar/resources/merge-resolve/.gitted/objects/2b/d0a343aeef7a2cf0d158478966a6e587ff3863 deleted file mode 100644 index d10ca636b..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/2b/d0a343aeef7a2cf0d158478966a6e587ff3863 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/2d/a538570bc1e5b2c3e855bf702f35248ad0735f b/tests-clar/resources/merge-resolve/.gitted/objects/2d/a538570bc1e5b2c3e855bf702f35248ad0735f deleted file mode 100644 index 83253f81c..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/2d/a538570bc1e5b2c3e855bf702f35248ad0735f +++ /dev/null @@ -1,2 +0,0 @@ -xK -1D]N"n{t:L$ UEQ>~7:L D [5ɇ,y2eT@z*.([žunum_|Št@ -apg%haJYծA8թ훠fN4;h[%cOuJWyΏ \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/2f/598248eeccfc27e5ca44d9d96383f6dfea7b16 b/tests-clar/resources/merge-resolve/.gitted/objects/2f/598248eeccfc27e5ca44d9d96383f6dfea7b16 deleted file mode 100644 index 1d9f226e2..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/2f/598248eeccfc27e5ca44d9d96383f6dfea7b16 +++ /dev/null @@ -1 +0,0 @@ -x+)JMU067c040031QH,-M-JOMLI+(aH:,:C: o>ZC'g$楧f&%%g5qYeZokM2ԐX\ZDPC~^ZNfrIf^:XZHي1O(_,' jvQjn~13zדm9Wu]:$I{| 2mg˾15ӿ,\})TC)0Pavz֛9MՅ'6b \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/31/68dca1a561889b045a6441909f4c56145e666d b/tests-clar/resources/merge-resolve/.gitted/objects/31/68dca1a561889b045a6441909f4c56145e666d deleted file mode 100644 index 2de1c5a79..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/31/68dca1a561889b045a6441909f4c56145e666d +++ /dev/null @@ -1,2 +0,0 @@ -xQ -0D)rJMxMHz}xfރaRYipkUD $1fQ2q-=Y3R76ġg9e7 bw GJe*˽ |ůSY"5&Нƨng9Z3_;kdO \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/31/d5472536041a83d986829240bbbdc897c6f8a6 b/tests-clar/resources/merge-resolve/.gitted/objects/31/d5472536041a83d986829240bbbdc897c6f8a6 deleted file mode 100644 index 5ec5acb59..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/31/d5472536041a83d986829240bbbdc897c6f8a6 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/32/21dd512b7e2dc4b5bd03046df6c81b2ab2070b b/tests-clar/resources/merge-resolve/.gitted/objects/32/21dd512b7e2dc4b5bd03046df6c81b2ab2070b deleted file mode 100644 index d36138d79..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/32/21dd512b7e2dc4b5bd03046df6c81b2ab2070b and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/33/46d64325b39e5323733492cd55f808994a2475 b/tests-clar/resources/merge-resolve/.gitted/objects/33/46d64325b39e5323733492cd55f808994a2475 deleted file mode 100644 index 11546cea4..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/33/46d64325b39e5323733492cd55f808994a2475 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/33/d500f588fbbe65901d82b4e6b008e549064be0 b/tests-clar/resources/merge-resolve/.gitted/objects/33/d500f588fbbe65901d82b4e6b008e549064be0 deleted file mode 100644 index 061a031b6..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/33/d500f588fbbe65901d82b4e6b008e549064be0 +++ /dev/null @@ -1,2 +0,0 @@ -xA E]s -.hbo.Z x}[ ~kCA<:km`d̑d,!:𦐳P1P qHccHEO[zsK>y>隿ïm6*Rn>O \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/34/bfafff88eaf118402b44e6f3e2dbbf1a582b05 b/tests-clar/resources/merge-resolve/.gitted/objects/34/bfafff88eaf118402b44e6f3e2dbbf1a582b05 deleted file mode 100644 index c653cec50..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/34/bfafff88eaf118402b44e6f3e2dbbf1a582b05 +++ /dev/null @@ -1 +0,0 @@ -xKj1D) >`7A. $<`Morlm4G&dVd[j2JCъgu_Gu%2:3XزQ'";?wpkm׾&Pf! %QJ%:Cez=6q;iO \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/35/0c6eb3010efc403a6bed682332635314e9ed58 b/tests-clar/resources/merge-resolve/.gitted/objects/35/0c6eb3010efc403a6bed682332635314e9ed58 deleted file mode 100644 index 2eee60233..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/35/0c6eb3010efc403a6bed682332635314e9ed58 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/35/411bfb77cd2cc431f3a03a2b4976ed94b5d241 b/tests-clar/resources/merge-resolve/.gitted/objects/35/411bfb77cd2cc431f3a03a2b4976ed94b5d241 deleted file mode 100644 index ea024ccd9..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/35/411bfb77cd2cc431f3a03a2b4976ed94b5d241 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/35/4704d3613ad4228e4786fc76656b11e98236c4 b/tests-clar/resources/merge-resolve/.gitted/objects/35/4704d3613ad4228e4786fc76656b11e98236c4 deleted file mode 100644 index 1dd13c44a..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/35/4704d3613ad4228e4786fc76656b11e98236c4 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/35/632e43612c06a3ea924bfbacd48333da874c29 b/tests-clar/resources/merge-resolve/.gitted/objects/35/632e43612c06a3ea924bfbacd48333da874c29 deleted file mode 100644 index be7684f19..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/35/632e43612c06a3ea924bfbacd48333da874c29 +++ /dev/null @@ -1 +0,0 @@ -xN !LdMb60^,40;iUFf+)1vB939fG(DIݸʵA$sk]l|L{Ig$m.N5y.\a/]|Ʋ@[g4< Hl?gTsˠzCP \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/35/75826c96a975031d2c14368529cc5c4353a8fd b/tests-clar/resources/merge-resolve/.gitted/objects/35/75826c96a975031d2c14368529cc5c4353a8fd deleted file mode 100644 index 24e33bc41..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/35/75826c96a975031d2c14368529cc5c4353a8fd and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/36/219b49367146cb2e6a1555b5a9ebd4d0328495 b/tests-clar/resources/merge-resolve/.gitted/objects/36/219b49367146cb2e6a1555b5a9ebd4d0328495 deleted file mode 100644 index 7f8044372..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/36/219b49367146cb2e6a1555b5a9ebd4d0328495 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/36/4bbe4ce80c7bd31e6307dce77d46e3e1759fb3 b/tests-clar/resources/merge-resolve/.gitted/objects/36/4bbe4ce80c7bd31e6307dce77d46e3e1759fb3 deleted file mode 100644 index 90fd9651f..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/36/4bbe4ce80c7bd31e6307dce77d46e3e1759fb3 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/37/48859b001c6e627e712a07951aee40afd19b41 b/tests-clar/resources/merge-resolve/.gitted/objects/37/48859b001c6e627e712a07951aee40afd19b41 deleted file mode 100644 index 6a0c389e4..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/37/48859b001c6e627e712a07951aee40afd19b41 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/38/5c8a0f26ddf79e9041e15e17dc352ed2c4cced b/tests-clar/resources/merge-resolve/.gitted/objects/38/5c8a0f26ddf79e9041e15e17dc352ed2c4cced deleted file mode 100644 index e95ff3a88..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/38/5c8a0f26ddf79e9041e15e17dc352ed2c4cced +++ /dev/null @@ -1,2 +0,0 @@ -x-MK -1 uSYRą6C6뛪oknYt Ep iDCddLB+8%qk +e6fHB1J4F1l \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/3b/47b031b3e55ae11e14a05260b1c3ffd6838d55 b/tests-clar/resources/merge-resolve/.gitted/objects/3b/47b031b3e55ae11e14a05260b1c3ffd6838d55 deleted file mode 100644 index 82086466f..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/3b/47b031b3e55ae11e14a05260b1c3ffd6838d55 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/3b/bf0bf59b20df5d5fc58b9fc1dc07be637c301f b/tests-clar/resources/merge-resolve/.gitted/objects/3b/bf0bf59b20df5d5fc58b9fc1dc07be637c301f deleted file mode 100644 index 723a9ae4c..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/3b/bf0bf59b20df5d5fc58b9fc1dc07be637c301f and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/3e/f4d30382ca33fdeba9fda895a99e0891ba37aa b/tests-clar/resources/merge-resolve/.gitted/objects/3e/f4d30382ca33fdeba9fda895a99e0891ba37aa deleted file mode 100644 index 49ee15239..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/3e/f4d30382ca33fdeba9fda895a99e0891ba37aa and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/3e/f9bfe82f9635518ae89152322f3b46fd4ba25b b/tests-clar/resources/merge-resolve/.gitted/objects/3e/f9bfe82f9635518ae89152322f3b46fd4ba25b deleted file mode 100644 index 3b5998ca6..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/3e/f9bfe82f9635518ae89152322f3b46fd4ba25b and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/40/2784a46a4a3982294231594cbeb431f506d22c b/tests-clar/resources/merge-resolve/.gitted/objects/40/2784a46a4a3982294231594cbeb431f506d22c deleted file mode 100644 index a17e05d0f..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/40/2784a46a4a3982294231594cbeb431f506d22c and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/41/2b32fb66137366147f1801ecc962452757d48a b/tests-clar/resources/merge-resolve/.gitted/objects/41/2b32fb66137366147f1801ecc962452757d48a deleted file mode 100644 index b183dd782..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/41/2b32fb66137366147f1801ecc962452757d48a +++ /dev/null @@ -1,2 +0,0 @@ -xK -1D]IO>"nt:x}xwUxjum'뫈.9=y 6$@T8&Lhf4Aܻf0B(.K>9S< +z_f}]Z]eO:wzރP.ިaNU6O \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/43/aafd43bea779ec74317dc361f45ae3f532a505 b/tests-clar/resources/merge-resolve/.gitted/objects/43/aafd43bea779ec74317dc361f45ae3f532a505 deleted file mode 100644 index ac86823b6..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/43/aafd43bea779ec74317dc361f45ae3f532a505 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/43/c338656342227a3a3cd3aa85cbf784061f5425 b/tests-clar/resources/merge-resolve/.gitted/objects/43/c338656342227a3a3cd3aa85cbf784061f5425 deleted file mode 100644 index d9773118b..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/43/c338656342227a3a3cd3aa85cbf784061f5425 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/45/299c1ca5e07bba1fd90843056fb559f96b1f5a b/tests-clar/resources/merge-resolve/.gitted/objects/45/299c1ca5e07bba1fd90843056fb559f96b1f5a deleted file mode 100644 index 2093b4410..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/45/299c1ca5e07bba1fd90843056fb559f96b1f5a and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/46/6daf8552b891e5c22bc58c9d7fc1a2eb8f0289 b/tests-clar/resources/merge-resolve/.gitted/objects/46/6daf8552b891e5c22bc58c9d7fc1a2eb8f0289 deleted file mode 100644 index c39b53aa8..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/46/6daf8552b891e5c22bc58c9d7fc1a2eb8f0289 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/47/6dbb3e207313d1d8aaa120c6ad204bf1295e53 b/tests-clar/resources/merge-resolve/.gitted/objects/47/6dbb3e207313d1d8aaa120c6ad204bf1295e53 deleted file mode 100644 index 3e5f66e55..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/47/6dbb3e207313d1d8aaa120c6ad204bf1295e53 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/47/8172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 b/tests-clar/resources/merge-resolve/.gitted/objects/47/8172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 deleted file mode 100644 index d9e250e66..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/47/8172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/49/130a28ef567af9a6a6104c38773fedfa5f9742 b/tests-clar/resources/merge-resolve/.gitted/objects/49/130a28ef567af9a6a6104c38773fedfa5f9742 deleted file mode 100644 index e2c49f5c4..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/49/130a28ef567af9a6a6104c38773fedfa5f9742 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/49/9df817155e4bdd3c6ee192a72c52f481818230 b/tests-clar/resources/merge-resolve/.gitted/objects/49/9df817155e4bdd3c6ee192a72c52f481818230 deleted file mode 100644 index 9c7e471dd..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/49/9df817155e4bdd3c6ee192a72c52f481818230 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/4a/9550ebcc97ce22b22f45af7b829bb030d003f5 b/tests-clar/resources/merge-resolve/.gitted/objects/4a/9550ebcc97ce22b22f45af7b829bb030d003f5 deleted file mode 100644 index 6ec674adc..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/4a/9550ebcc97ce22b22f45af7b829bb030d003f5 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/4b/253da36a0ae8bfce63aeabd8c5b58429925594 b/tests-clar/resources/merge-resolve/.gitted/objects/4b/253da36a0ae8bfce63aeabd8c5b58429925594 deleted file mode 100644 index 1a4072794..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/4b/253da36a0ae8bfce63aeabd8c5b58429925594 +++ /dev/null @@ -1,2 +0,0 @@ -x A -0 @AAILm l׹vGx#63tW B6%h \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/4b/48deed3a433909bfd6b6ab3d4b91348b6af464 b/tests-clar/resources/merge-resolve/.gitted/objects/4b/48deed3a433909bfd6b6ab3d4b91348b6af464 deleted file mode 100644 index 328c8506e..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/4b/48deed3a433909bfd6b6ab3d4b91348b6af464 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 b/tests-clar/resources/merge-resolve/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 deleted file mode 100644 index adf64119a..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/4c/9fac0707f8d4195037ae5a681aa48626491541 b/tests-clar/resources/merge-resolve/.gitted/objects/4c/9fac0707f8d4195037ae5a681aa48626491541 deleted file mode 100644 index 6b8c85e2b..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/4c/9fac0707f8d4195037ae5a681aa48626491541 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/4c/a408a8c88655f7586a1b580be6fad138121e98 b/tests-clar/resources/merge-resolve/.gitted/objects/4c/a408a8c88655f7586a1b580be6fad138121e98 deleted file mode 100644 index 15cb7f29a..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/4c/a408a8c88655f7586a1b580be6fad138121e98 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/4e/0d9401aee78eb345a8685a859d37c8c3c0bbed b/tests-clar/resources/merge-resolve/.gitted/objects/4e/0d9401aee78eb345a8685a859d37c8c3c0bbed deleted file mode 100644 index 57f7eb68c..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/4e/0d9401aee78eb345a8685a859d37c8c3c0bbed and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/4e/886e602529caa9ab11d71f86634bd1b6e0de10 b/tests-clar/resources/merge-resolve/.gitted/objects/4e/886e602529caa9ab11d71f86634bd1b6e0de10 deleted file mode 100644 index 53168a038..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/4e/886e602529caa9ab11d71f86634bd1b6e0de10 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/4e/b04c9e79e88f6640d01ff5b25ca2a60764f216 b/tests-clar/resources/merge-resolve/.gitted/objects/4e/b04c9e79e88f6640d01ff5b25ca2a60764f216 deleted file mode 100644 index f4ec0efec..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/4e/b04c9e79e88f6640d01ff5b25ca2a60764f216 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/4f/e93c0ec83eb6305cbace3dace88ecee1b63cb6 b/tests-clar/resources/merge-resolve/.gitted/objects/4f/e93c0ec83eb6305cbace3dace88ecee1b63cb6 deleted file mode 100644 index 67dc6842f..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/4f/e93c0ec83eb6305cbace3dace88ecee1b63cb6 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/50/12fd565b1393bdfda1805d4ec38ce6619e1fd1 b/tests-clar/resources/merge-resolve/.gitted/objects/50/12fd565b1393bdfda1805d4ec38ce6619e1fd1 deleted file mode 100644 index d629a23a1..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/50/12fd565b1393bdfda1805d4ec38ce6619e1fd1 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/50/4f75ac95a71ef98051817618576a68505b92f9 b/tests-clar/resources/merge-resolve/.gitted/objects/50/4f75ac95a71ef98051817618576a68505b92f9 deleted file mode 100644 index 1b24c721a..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/50/4f75ac95a71ef98051817618576a68505b92f9 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/50/84fc2a88b6bdba8db93bd3953a8f4fdb470238 b/tests-clar/resources/merge-resolve/.gitted/objects/50/84fc2a88b6bdba8db93bd3953a8f4fdb470238 deleted file mode 100644 index 84c9987ce..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/50/84fc2a88b6bdba8db93bd3953a8f4fdb470238 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/50/ce7d7d01217679e26c55939eef119e0c93e272 b/tests-clar/resources/merge-resolve/.gitted/objects/50/ce7d7d01217679e26c55939eef119e0c93e272 deleted file mode 100644 index e2f9f67fd..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/50/ce7d7d01217679e26c55939eef119e0c93e272 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/51/95a1b480f66691b667f10a9e41e70115a78351 b/tests-clar/resources/merge-resolve/.gitted/objects/51/95a1b480f66691b667f10a9e41e70115a78351 deleted file mode 100644 index 088ee5498..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/51/95a1b480f66691b667f10a9e41e70115a78351 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/52/d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 b/tests-clar/resources/merge-resolve/.gitted/objects/52/d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 deleted file mode 100644 index 6522209bd..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/52/d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 +++ /dev/null @@ -1,3 +0,0 @@ -x] -0})rnD|^`Ђm$FUo3ä,sӽ]" #b"1 9cThS//SYe'+~mrh\cQwFMQϙ]b5M R \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/53/825f41ac8d640612f9423a2f03a69f3d96809a b/tests-clar/resources/merge-resolve/.gitted/objects/53/825f41ac8d640612f9423a2f03a69f3d96809a deleted file mode 100644 index 08cb0b66f..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/53/825f41ac8d640612f9423a2f03a69f3d96809a and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/54/269b3f6ec3d7d4ede24dd350dd5d605495c3ae b/tests-clar/resources/merge-resolve/.gitted/objects/54/269b3f6ec3d7d4ede24dd350dd5d605495c3ae deleted file mode 100644 index 4a2415339..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/54/269b3f6ec3d7d4ede24dd350dd5d605495c3ae +++ /dev/null @@ -1,2 +0,0 @@ -xK -1D]I7 LӌL$FxwUAQj m'؍^v9 d- Ɯ \ ϽC'&`"Ĺ(֡9_sg}]Z}UF?\I&@mt;;ʟ3hzN \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/54/59c89aa0026d543ce8343bd89871bce543f9c2 b/tests-clar/resources/merge-resolve/.gitted/objects/54/59c89aa0026d543ce8343bd89871bce543f9c2 deleted file mode 100644 index 178b833e8..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/54/59c89aa0026d543ce8343bd89871bce543f9c2 +++ /dev/null @@ -1,3 +0,0 @@ -x !D -,,,,9O bl؁3%mY.C[LEtd`\ %aBH%TvB G%Qphq]nCgP3B(H14yS)W;IVsT^܋>myJ?(_kܖ6-$#-Zzvȟ3 -:NqMB \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/54/7607c690372fe81fab8e3bb44c530e129118fd b/tests-clar/resources/merge-resolve/.gitted/objects/54/7607c690372fe81fab8e3bb44c530e129118fd deleted file mode 100644 index dccd22006..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/54/7607c690372fe81fab8e3bb44c530e129118fd and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/55/b4e4687e7a0d9ca367016ed930f385d4022e6f b/tests-clar/resources/merge-resolve/.gitted/objects/55/b4e4687e7a0d9ca367016ed930f385d4022e6f deleted file mode 100644 index fb157a214..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/55/b4e4687e7a0d9ca367016ed930f385d4022e6f +++ /dev/null @@ -1 +0,0 @@ -xQj0DSZvJ \N 7㷱d-{LX' vm*{Z`$U9-TN{,}Kyuۣ78A_Sv.EQgSsxZZX MNRi \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/56/6ab53c220a2eafc1212af1a024513230280ab9 b/tests-clar/resources/merge-resolve/.gitted/objects/56/6ab53c220a2eafc1212af1a024513230280ab9 deleted file mode 100644 index a8855ae67..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/56/6ab53c220a2eafc1212af1a024513230280ab9 +++ /dev/null @@ -1,3 +0,0 @@ -x !D -,˱1؁ ,LD bl؁3%Ihft ١XvY`L2М՝܆NsIbRЧL3Ra$Is,S~qh7~QvՃ6!-Zzvȟ3 -:9M& \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/56/a638b76b75e068590ac999c2f8621e7f3e264c b/tests-clar/resources/merge-resolve/.gitted/objects/56/a638b76b75e068590ac999c2f8621e7f3e264c deleted file mode 100644 index 36289bf7a..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/56/a638b76b75e068590ac999c2f8621e7f3e264c +++ /dev/null @@ -1 +0,0 @@ -xAj!Eu vuWB6s%6qΐ$^Rb[{=coj'|褯UjeKLnn5СPY|2`zzQ{ \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/57/079a46233ae2b6df62e9ade71c4948512abefb b/tests-clar/resources/merge-resolve/.gitted/objects/57/079a46233ae2b6df62e9ade71c4948512abefb deleted file mode 100644 index c7eabc46b..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/57/079a46233ae2b6df62e9ade71c4948512abefb and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/58/43febcb23480df0b5edb22a21c59c772bb8e29 b/tests-clar/resources/merge-resolve/.gitted/objects/58/43febcb23480df0b5edb22a21c59c772bb8e29 deleted file mode 100644 index f6b2a2bfe..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/58/43febcb23480df0b5edb22a21c59c772bb8e29 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/58/e853f66699fd02629fd50bde08082bc005933a b/tests-clar/resources/merge-resolve/.gitted/objects/58/e853f66699fd02629fd50bde08082bc005933a deleted file mode 100644 index cf6db633c..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/58/e853f66699fd02629fd50bde08082bc005933a and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/59/6803b523203a4851c824c07366906f8353f4ad b/tests-clar/resources/merge-resolve/.gitted/objects/59/6803b523203a4851c824c07366906f8353f4ad deleted file mode 100644 index cbc8cbef3..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/59/6803b523203a4851c824c07366906f8353f4ad and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/5c/2411f8075f48a6b2fdb85ebc0d371747c4df15 b/tests-clar/resources/merge-resolve/.gitted/objects/5c/2411f8075f48a6b2fdb85ebc0d371747c4df15 deleted file mode 100644 index 7b41413da..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/5c/2411f8075f48a6b2fdb85ebc0d371747c4df15 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/5c/341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d b/tests-clar/resources/merge-resolve/.gitted/objects/5c/341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d deleted file mode 100644 index 63c86bd33..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/5c/341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/5c/3b68a71fc4fa5d362fd3875e53137c6a5ab7a5 b/tests-clar/resources/merge-resolve/.gitted/objects/5c/3b68a71fc4fa5d362fd3875e53137c6a5ab7a5 deleted file mode 100644 index 541001456..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/5c/3b68a71fc4fa5d362fd3875e53137c6a5ab7a5 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/5d/c1018e90b19654bee986b7a0c268804d39659d b/tests-clar/resources/merge-resolve/.gitted/objects/5d/c1018e90b19654bee986b7a0c268804d39659d deleted file mode 100644 index 7500b9914..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/5d/c1018e90b19654bee986b7a0c268804d39659d and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/5d/dd0fe66f990dc0e5cf9fec6d9b465240e9537f b/tests-clar/resources/merge-resolve/.gitted/objects/5d/dd0fe66f990dc0e5cf9fec6d9b465240e9537f deleted file mode 100644 index 9d8691eb2..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/5d/dd0fe66f990dc0e5cf9fec6d9b465240e9537f and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/5e/b7bb6a146eb3c7fd3990b240a2308eceb1cf8d b/tests-clar/resources/merge-resolve/.gitted/objects/5e/b7bb6a146eb3c7fd3990b240a2308eceb1cf8d deleted file mode 100644 index aca2666cf..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/5e/b7bb6a146eb3c7fd3990b240a2308eceb1cf8d and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/5f/bfbdc04b4eca46f54f4853a3c5a1dce28f5165 b/tests-clar/resources/merge-resolve/.gitted/objects/5f/bfbdc04b4eca46f54f4853a3c5a1dce28f5165 deleted file mode 100644 index aec3867c8..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/5f/bfbdc04b4eca46f54f4853a3c5a1dce28f5165 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/60/91fc2c036a382a69489e3f518ee5aae9a4e567 b/tests-clar/resources/merge-resolve/.gitted/objects/60/91fc2c036a382a69489e3f518ee5aae9a4e567 deleted file mode 100644 index fa63afba1..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/60/91fc2c036a382a69489e3f518ee5aae9a4e567 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/61/340eeed7340fa6a8792def9a5938bb5d4434bb b/tests-clar/resources/merge-resolve/.gitted/objects/61/340eeed7340fa6a8792def9a5938bb5d4434bb deleted file mode 100644 index e830cafe5..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/61/340eeed7340fa6a8792def9a5938bb5d4434bb and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/61/78885b38fe96e825ac0f492c0a941f288b37f6 b/tests-clar/resources/merge-resolve/.gitted/objects/61/78885b38fe96e825ac0f492c0a941f288b37f6 deleted file mode 100644 index bedc5f27e..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/61/78885b38fe96e825ac0f492c0a941f288b37f6 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/62/12c31dab5e482247d7977e4f0dd3601decf13b b/tests-clar/resources/merge-resolve/.gitted/objects/62/12c31dab5e482247d7977e4f0dd3601decf13b deleted file mode 100644 index b6f0607bb..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/62/12c31dab5e482247d7977e4f0dd3601decf13b and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/62/269111c3b02a9355badcb9da8678b1bf41787b b/tests-clar/resources/merge-resolve/.gitted/objects/62/269111c3b02a9355badcb9da8678b1bf41787b deleted file mode 100644 index 0edf65994..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/62/269111c3b02a9355badcb9da8678b1bf41787b and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/62/c4f6533c9a3894191fdcb96a3be935ade63f1a b/tests-clar/resources/merge-resolve/.gitted/objects/62/c4f6533c9a3894191fdcb96a3be935ade63f1a deleted file mode 100644 index c0f822d2c..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/62/c4f6533c9a3894191fdcb96a3be935ade63f1a and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/63/247125386de9ec90a27ad36169307bf8a11a38 b/tests-clar/resources/merge-resolve/.gitted/objects/63/247125386de9ec90a27ad36169307bf8a11a38 deleted file mode 100644 index bc2d7384d..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/63/247125386de9ec90a27ad36169307bf8a11a38 +++ /dev/null @@ -1 +0,0 @@ -xݏ;1 D}AV\8HIVp|?LyOuN7C] ͥlt:iA(xip,O;o7 UYZ Bý]dUmyk[cͥ)!X{Z \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/67/18a45909532d1fcf5600d0877f7fe7e78f0b86 b/tests-clar/resources/merge-resolve/.gitted/objects/67/18a45909532d1fcf5600d0877f7fe7e78f0b86 deleted file mode 100644 index ffda698f0..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/67/18a45909532d1fcf5600d0877f7fe7e78f0b86 +++ /dev/null @@ -1 +0,0 @@ -xM1 DNi`ǹDB~ǧ]ݠY74M8J?$_k[Q,"Zz˟39 LO \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/76/63fce0130db092936b137cabd693ec234eb060 b/tests-clar/resources/merge-resolve/.gitted/objects/76/63fce0130db092936b137cabd693ec234eb060 deleted file mode 100644 index f578a4a68..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/76/63fce0130db092936b137cabd693ec234eb060 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/76/ab0e2868197ec158ddd6c78d8a0d2fd73d38f9 b/tests-clar/resources/merge-resolve/.gitted/objects/76/ab0e2868197ec158ddd6c78d8a0d2fd73d38f9 deleted file mode 100644 index 4d41ad8cd..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/76/ab0e2868197ec158ddd6c78d8a0d2fd73d38f9 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/7a/a3edf2bcfee22398e6b55295aa56366b7aaf76 b/tests-clar/resources/merge-resolve/.gitted/objects/7a/a3edf2bcfee22398e6b55295aa56366b7aaf76 deleted file mode 100644 index 09f1e4d3a..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/7a/a3edf2bcfee22398e6b55295aa56366b7aaf76 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/7c/2c5228c9e90170d4a35e6558e47163daf092e5 b/tests-clar/resources/merge-resolve/.gitted/objects/7c/2c5228c9e90170d4a35e6558e47163daf092e5 deleted file mode 100644 index 52fde92a1..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/7c/2c5228c9e90170d4a35e6558e47163daf092e5 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/7c/b63eed597130ba4abb87b3e544b85021905520 b/tests-clar/resources/merge-resolve/.gitted/objects/7c/b63eed597130ba4abb87b3e544b85021905520 deleted file mode 100644 index 769f29c6e..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/7c/b63eed597130ba4abb87b3e544b85021905520 +++ /dev/null @@ -1,3 +0,0 @@ -xK -1D]t'"nH:L$FxwUAQܖ6f7IT*zJ -1#;@rX]ꞺC3A F'aj#Tf acn]_+s[mG'+~m9i PFCQge"N \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/7e/2d058d5fedf8329db44db4fac610d6b1a89159 b/tests-clar/resources/merge-resolve/.gitted/objects/7e/2d058d5fedf8329db44db4fac610d6b1a89159 deleted file mode 100644 index d12d7b4a7..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/7e/2d058d5fedf8329db44db4fac610d6b1a89159 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/7f/7a2da58126226986d71c6ddfab4afba693280d b/tests-clar/resources/merge-resolve/.gitted/objects/7f/7a2da58126226986d71c6ddfab4afba693280d deleted file mode 100644 index 2f833c292..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/7f/7a2da58126226986d71c6ddfab4afba693280d and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/80/a8fbb3abb1ba423d554e9630b8fc2e5698f86b b/tests-clar/resources/merge-resolve/.gitted/objects/80/a8fbb3abb1ba423d554e9630b8fc2e5698f86b deleted file mode 100644 index 3daf6c3e0..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/80/a8fbb3abb1ba423d554e9630b8fc2e5698f86b and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/81/87117062b750eed4f93fd7e899f17b52ce554d b/tests-clar/resources/merge-resolve/.gitted/objects/81/87117062b750eed4f93fd7e899f17b52ce554d deleted file mode 100644 index 19cac9faf..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/81/87117062b750eed4f93fd7e899f17b52ce554d and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/83/07d93a155903a5c49576583f0ce1f6ff897c0e b/tests-clar/resources/merge-resolve/.gitted/objects/83/07d93a155903a5c49576583f0ce1f6ff897c0e deleted file mode 100644 index 5a96a4e4e..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/83/07d93a155903a5c49576583f0ce1f6ff897c0e and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/83/824a8c6658768e2013905219cc8c64cc3d9a2e b/tests-clar/resources/merge-resolve/.gitted/objects/83/824a8c6658768e2013905219cc8c64cc3d9a2e deleted file mode 100644 index 066190fb8..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/83/824a8c6658768e2013905219cc8c64cc3d9a2e and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/84/9619b03ae540acee4d1edec96b86993da6b497 b/tests-clar/resources/merge-resolve/.gitted/objects/84/9619b03ae540acee4d1edec96b86993da6b497 deleted file mode 100644 index 67271ac50..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/84/9619b03ae540acee4d1edec96b86993da6b497 +++ /dev/null @@ -1,3 +0,0 @@ -xK -1D]v7t3L$ UEVZC'g$楧f&%%g5qYeZokM2ԐX\ZDPC~^ZNfrIf^:XZHي1O(_,' jv^j9!Ɖ9%`<sBާHrS3d Ң2 wI{| 2mg˾15ӿ,\})TC)00avʉz֛9MՅ'6bG \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/8b/095d8fd01594f4d14454d073e3ac57b9ce485f b/tests-clar/resources/merge-resolve/.gitted/objects/8b/095d8fd01594f4d14454d073e3ac57b9ce485f deleted file mode 100644 index 4ec013881..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/8b/095d8fd01594f4d14454d073e3ac57b9ce485f and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/8b/5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a b/tests-clar/resources/merge-resolve/.gitted/objects/8b/5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a deleted file mode 100644 index f4249c23d..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/8b/5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a +++ /dev/null @@ -1 +0,0 @@ -x퐱 0 S{"2d,0^?&SH[8눪E`фrZ*drl, cbF/'gв \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/8b/fb012a6d809e499bd8d3e194a3929bc8995b93 b/tests-clar/resources/merge-resolve/.gitted/objects/8b/fb012a6d809e499bd8d3e194a3929bc8995b93 deleted file mode 100644 index a90ee08ce..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/8b/fb012a6d809e499bd8d3e194a3929bc8995b93 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/8c/749d9968d4b10dcfb06c9f97d0e5d92d337071 b/tests-clar/resources/merge-resolve/.gitted/objects/8c/749d9968d4b10dcfb06c9f97d0e5d92d337071 deleted file mode 100644 index e42393cf7..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/8c/749d9968d4b10dcfb06c9f97d0e5d92d337071 +++ /dev/null @@ -1,2 +0,0 @@ -xAB!C]s -.acxf`|_ bh5m^mzL`}$26#"8`s.`ԝܺ.!bH\< i",K8ٗ_X>MeЏ:7]AC40뭙Q]Q\.,VO \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/8f/4433f8593ddd65b7dd43dd4564d841f4d9c8aa b/tests-clar/resources/merge-resolve/.gitted/objects/8f/4433f8593ddd65b7dd43dd4564d841f4d9c8aa deleted file mode 100644 index d2de777cc..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/8f/4433f8593ddd65b7dd43dd4564d841f4d9c8aa and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/90/a336c7dacbe295159413559b0043b8bdc60d57 b/tests-clar/resources/merge-resolve/.gitted/objects/90/a336c7dacbe295159413559b0043b8bdc60d57 deleted file mode 100644 index 35453ebfd..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/90/a336c7dacbe295159413559b0043b8bdc60d57 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/91/2b2d7819cf9c1029e414883857ed61d597a1a5 b/tests-clar/resources/merge-resolve/.gitted/objects/91/2b2d7819cf9c1029e414883857ed61d597a1a5 deleted file mode 100644 index d5df393e9..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/91/2b2d7819cf9c1029e414883857ed61d597a1a5 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/91/8bb3e09090a9995d48af9a2a6296d7e6088d1c b/tests-clar/resources/merge-resolve/.gitted/objects/91/8bb3e09090a9995d48af9a2a6296d7e6088d1c deleted file mode 100644 index c214ab206..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/91/8bb3e09090a9995d48af9a2a6296d7e6088d1c and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/92/7d4943cdbdc9a667db8e62cfd0a41870235c51 b/tests-clar/resources/merge-resolve/.gitted/objects/92/7d4943cdbdc9a667db8e62cfd0a41870235c51 deleted file mode 100644 index b6b92c842..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/92/7d4943cdbdc9a667db8e62cfd0a41870235c51 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/93/77fccdb210540b8c0520cc6e80eb632c20bd25 b/tests-clar/resources/merge-resolve/.gitted/objects/93/77fccdb210540b8c0520cc6e80eb632c20bd25 deleted file mode 100644 index 4b2d93b07..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/93/77fccdb210540b8c0520cc6e80eb632c20bd25 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/94/4f5dd1a867cab4c2bbcb896493435cae1dcc1a b/tests-clar/resources/merge-resolve/.gitted/objects/94/4f5dd1a867cab4c2bbcb896493435cae1dcc1a deleted file mode 100644 index 143093831..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/94/4f5dd1a867cab4c2bbcb896493435cae1dcc1a +++ /dev/null @@ -1,2 +0,0 @@ -xK!D]s -.z7 |2. bhWKVmH0~7z"P9`:Qi)QLEyq=oC*P6-"4l0StAHZC'g$楧f&%%g5qYeZokM2ԐX\ZDPC~^ZNfrIf^:XZHي1O(_,' jv^jnb^nJfZZjQj^ X#3|>^U:'A2R2 I{| 2mg˾15ӿ,\})TC)0H!vʉz֛9MՅ'6bGx \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/a9/0bc3fb6f15181972a2959a921429efbd81a473 b/tests-clar/resources/merge-resolve/.gitted/objects/a9/0bc3fb6f15181972a2959a921429efbd81a473 deleted file mode 100644 index 91113ee8e..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/a9/0bc3fb6f15181972a2959a921429efbd81a473 +++ /dev/null @@ -1,2 +0,0 @@ -xK -1D]};7d=oo^UQT\;hk6@g 5rѓ]uOMndgz&c圈'} NJ7p?(G\8CآGTg9x$faxN" \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/ab/40af3cb8a3ed2e2843e96d9aa7871336b94573 b/tests-clar/resources/merge-resolve/.gitted/objects/ab/40af3cb8a3ed2e2843e96d9aa7871336b94573 deleted file mode 100644 index 7da1da656..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/ab/40af3cb8a3ed2e2843e96d9aa7871336b94573 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/ab/6c44a2e84492ad4b41bb6bac87353e9d02ac8b b/tests-clar/resources/merge-resolve/.gitted/objects/ab/6c44a2e84492ad4b41bb6bac87353e9d02ac8b deleted file mode 100644 index d840c1a57..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/ab/6c44a2e84492ad4b41bb6bac87353e9d02ac8b and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/ab/929391ac42572f92110f3deeb4f0844a951e22 b/tests-clar/resources/merge-resolve/.gitted/objects/ab/929391ac42572f92110f3deeb4f0844a951e22 deleted file mode 100644 index 8840d00c5..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/ab/929391ac42572f92110f3deeb4f0844a951e22 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/ac/4045f965119e6998f4340ed0f411decfb3ec05 b/tests-clar/resources/merge-resolve/.gitted/objects/ac/4045f965119e6998f4340ed0f411decfb3ec05 deleted file mode 100644 index 4c32d63f8..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/ac/4045f965119e6998f4340ed0f411decfb3ec05 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/ad/a14492498136771f69dd451866cabcb0e9ef9a b/tests-clar/resources/merge-resolve/.gitted/objects/ad/a14492498136771f69dd451866cabcb0e9ef9a deleted file mode 100644 index 71023de39..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/ad/a14492498136771f69dd451866cabcb0e9ef9a and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/ad/a55a45d14527dc3dfc714ea1c65d2e1e6fbe87 b/tests-clar/resources/merge-resolve/.gitted/objects/ad/a55a45d14527dc3dfc714ea1c65d2e1e6fbe87 deleted file mode 100644 index 3091b8f3d..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/ad/a55a45d14527dc3dfc714ea1c65d2e1e6fbe87 +++ /dev/null @@ -1 +0,0 @@ -x+)JMU067d040031QH,-M-JOMLI+(aH:,:C: o>ZC'g$楧f&%%g5qYeZokM2ԐX\ZDPC~^ZNfrIf^:XZHي1O(_,' jvn~JfZ&5`nלU7 V.6t6L/R2 I{| 2mg˾15ӿ,\})TC)0<vʉz֛9MՅ'6bN* \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/b2/d399ae15224e1d58066e3c8df70ce37de7a656 b/tests-clar/resources/merge-resolve/.gitted/objects/b2/d399ae15224e1d58066e3c8df70ce37de7a656 deleted file mode 100644 index 20fa838f2..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/b2/d399ae15224e1d58066e3c8df70ce37de7a656 +++ /dev/null @@ -1,2 +0,0 @@ -xQA1+xċϡ-kI*5f/z af!^/WJcܤ5Lƛ;+B6HZP|`h>\($sX@75}57K -+= ;g @!4!,\$\ \b/Hs#aQ \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/b4/2712cfe99a1a500b2a51fe984e0b8a7702ba11 b/tests-clar/resources/merge-resolve/.gitted/objects/b4/2712cfe99a1a500b2a51fe984e0b8a7702ba11 deleted file mode 100644 index 2820b46cc..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/b4/2712cfe99a1a500b2a51fe984e0b8a7702ba11 +++ /dev/null @@ -1,5 +0,0 @@ -xA - {B{M1 ߯>P3F֎7E02 X0̒,)$;:ܷ(: \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/b6/f610aef53bd343e6c96227de874c66f00ee8e8 b/tests-clar/resources/merge-resolve/.gitted/objects/b6/f610aef53bd343e6c96227de874c66f00ee8e8 deleted file mode 100644 index fb102f15d..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/b6/f610aef53bd343e6c96227de874c66f00ee8e8 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/b7/a2576f9fc20024ac9ef17cb134acbd1ac73127 b/tests-clar/resources/merge-resolve/.gitted/objects/b7/a2576f9fc20024ac9ef17cb134acbd1ac73127 deleted file mode 100644 index 22f2d137d..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/b7/a2576f9fc20024ac9ef17cb134acbd1ac73127 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/b8/a3a806d3950e8c0a03a34f234a92eff0e2c68d b/tests-clar/resources/merge-resolve/.gitted/objects/b8/a3a806d3950e8c0a03a34f234a92eff0e2c68d deleted file mode 100644 index 24f029900..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/b8/a3a806d3950e8c0a03a34f234a92eff0e2c68d and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/ba/cac9b3493509aa15e1730e1545fc0919d1dae0 b/tests-clar/resources/merge-resolve/.gitted/objects/ba/cac9b3493509aa15e1730e1545fc0919d1dae0 deleted file mode 100644 index f35586f7f..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/ba/cac9b3493509aa15e1730e1545fc0919d1dae0 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/bc/744705e1d8a019993cf88f62bc4020f1b80919 b/tests-clar/resources/merge-resolve/.gitted/objects/bc/744705e1d8a019993cf88f62bc4020f1b80919 deleted file mode 100644 index 0d4bdb323..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/bc/744705e1d8a019993cf88f62bc4020f1b80919 +++ /dev/null @@ -1,2 +0,0 @@ -xK -1D]}%%tYH& UJuj7:P(#F̄ģ1+k#vΚS8W|٨%Kpɯ3\Vv#MQg?wH@(c s9t 嶭{kO \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/bc/95c75d59386147d1e79a87c33068d8dbfd71f2 b/tests-clar/resources/merge-resolve/.gitted/objects/bc/95c75d59386147d1e79a87c33068d8dbfd71f2 deleted file mode 100644 index 436d5a076..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/bc/95c75d59386147d1e79a87c33068d8dbfd71f2 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/bd/593285fc7fe4ca18ccdbabf027f5d689101452 b/tests-clar/resources/merge-resolve/.gitted/objects/bd/593285fc7fe4ca18ccdbabf027f5d689101452 deleted file mode 100644 index 75ab1f0f3..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/bd/593285fc7fe4ca18ccdbabf027f5d689101452 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/bd/867fbae2faa80b920b002b80b1c91bcade7784 b/tests-clar/resources/merge-resolve/.gitted/objects/bd/867fbae2faa80b920b002b80b1c91bcade7784 deleted file mode 100644 index 0f7421963..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/bd/867fbae2faa80b920b002b80b1c91bcade7784 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/bd/9cb4cd0a770cb9adcb5fce212142ef40ea1c35 b/tests-clar/resources/merge-resolve/.gitted/objects/bd/9cb4cd0a770cb9adcb5fce212142ef40ea1c35 deleted file mode 100644 index 2aafdc64f..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/bd/9cb4cd0a770cb9adcb5fce212142ef40ea1c35 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/be/f6e37b3ee632ba74159168836f382fed21d77d b/tests-clar/resources/merge-resolve/.gitted/objects/be/f6e37b3ee632ba74159168836f382fed21d77d deleted file mode 100644 index 6c243150d..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/be/f6e37b3ee632ba74159168836f382fed21d77d +++ /dev/null @@ -1,2 +0,0 @@ -xK -1D]}3?Ač7p?$=`Ґx}Gރ`)+0ѮUh.NWޓ!Idlj-f 9UV61:̸ !>Z.P0x hhQ+t`1NZe,X[ =vyI_vJ^2$?I7o4{K>V!~|U= \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/c5/bbe550b9f09444bdddd3ecf3d97c0b42aa786c b/tests-clar/resources/merge-resolve/.gitted/objects/c5/bbe550b9f09444bdddd3ecf3d97c0b42aa786c deleted file mode 100644 index 2f2ada732..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/c5/bbe550b9f09444bdddd3ecf3d97c0b42aa786c and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/c6/07fc30883e335def28cd686b51f6cfa02b06ec b/tests-clar/resources/merge-resolve/.gitted/objects/c6/07fc30883e335def28cd686b51f6cfa02b06ec deleted file mode 100644 index 475b87ef9..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/c6/07fc30883e335def28cd686b51f6cfa02b06ec +++ /dev/null @@ -1,2 +0,0 @@ -xQ -1 D)r%n "x/m[[oo{0k)iכ*`ZavJ>,af<EZȳ5%<'.v,;]=2tws-,w8@ \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/c6/92ecf62007c0ac9fb26e2aa884de2933de15ed b/tests-clar/resources/merge-resolve/.gitted/objects/c6/92ecf62007c0ac9fb26e2aa884de2933de15ed deleted file mode 100644 index ae430bd4a..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/c6/92ecf62007c0ac9fb26e2aa884de2933de15ed and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/c8/f06f2e3bb2964174677e91f0abead0e43c9e5d b/tests-clar/resources/merge-resolve/.gitted/objects/c8/f06f2e3bb2964174677e91f0abead0e43c9e5d deleted file mode 100644 index 5dae4c3ac..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/c8/f06f2e3bb2964174677e91f0abead0e43c9e5d and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/c9/174cef549ec94ecbc43ef03cdc775b4950becb b/tests-clar/resources/merge-resolve/.gitted/objects/c9/174cef549ec94ecbc43ef03cdc775b4950becb deleted file mode 100644 index da8dba244..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/c9/174cef549ec94ecbc43ef03cdc775b4950becb +++ /dev/null @@ -1,2 +0,0 @@ -xQ -0D)rfnSxfCHx}xfc,˵Y kUb8pu`%|@r3GtB;W]!z'%QiӐdT ?\=d/sYe';^r#l`6m Z7U^e6oVO \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/c9/4b27e41064c521120627e07e2035cca1d24ffa b/tests-clar/resources/merge-resolve/.gitted/objects/c9/4b27e41064c521120627e07e2035cca1d24ffa deleted file mode 100644 index fd1ec9fab..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/c9/4b27e41064c521120627e07e2035cca1d24ffa and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/ca/b2cf23998b40f1af2d9d9a756dc9e285a8df4b b/tests-clar/resources/merge-resolve/.gitted/objects/ca/b2cf23998b40f1af2d9d9a756dc9e285a8df4b deleted file mode 100644 index 32ba2aa53..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/ca/b2cf23998b40f1af2d9d9a756dc9e285a8df4b and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/cb/491780d82e46dc88a065b965ab307a038f2bc2 b/tests-clar/resources/merge-resolve/.gitted/objects/cb/491780d82e46dc88a065b965ab307a038f2bc2 deleted file mode 100644 index cf9cd7d39..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/cb/491780d82e46dc88a065b965ab307a038f2bc2 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/cb/6693a788715b82440a54e0eacd19ba9f6ec559 b/tests-clar/resources/merge-resolve/.gitted/objects/cb/6693a788715b82440a54e0eacd19ba9f6ec559 deleted file mode 100644 index e11181a96..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/cb/6693a788715b82440a54e0eacd19ba9f6ec559 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/cc/3e3009134cb88014129fc8858d1101359e5e2f b/tests-clar/resources/merge-resolve/.gitted/objects/cc/3e3009134cb88014129fc8858d1101359e5e2f deleted file mode 100644 index 9a0cb7a0c..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/cc/3e3009134cb88014129fc8858d1101359e5e2f +++ /dev/null @@ -1,2 +0,0 @@ -x] -0})&_H -Fb[6}0L2wPzc*sXb Rt#G$[lvH$kf.ʧLF+ QHD|68Wl.S]uoNOu9Va0^ZF9^# Od \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/ce/8860d49e3bea6fd745874a01b7c3e46da8cbc3 b/tests-clar/resources/merge-resolve/.gitted/objects/ce/8860d49e3bea6fd745874a01b7c3e46da8cbc3 deleted file mode 100644 index 860f9952f..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/ce/8860d49e3bea6fd745874a01b7c3e46da8cbc3 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/ce/e656c392ad0557b3aae0fb411475c206e2926f b/tests-clar/resources/merge-resolve/.gitted/objects/ce/e656c392ad0557b3aae0fb411475c206e2926f deleted file mode 100644 index ff0624ccb..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/ce/e656c392ad0557b3aae0fb411475c206e2926f and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/cf/8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d b/tests-clar/resources/merge-resolve/.gitted/objects/cf/8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d deleted file mode 100644 index 36b0289e6..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/cf/8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d0/7ec190c306ec690bac349e87d01c4358e49bb2 b/tests-clar/resources/merge-resolve/.gitted/objects/d0/7ec190c306ec690bac349e87d01c4358e49bb2 deleted file mode 100644 index d52a56ffe..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/d0/7ec190c306ec690bac349e87d01c4358e49bb2 +++ /dev/null @@ -1,2 +0,0 @@ -xՏ 0 3aOb%ǑS=HT@u:]uYG%LE;u`_?g~0Ҕ. -׋PӜxvXi ӭf! \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d0/d4594e16f2e19107e3fa7ea63e7aaaff305ffb b/tests-clar/resources/merge-resolve/.gitted/objects/d0/d4594e16f2e19107e3fa7ea63e7aaaff305ffb deleted file mode 100644 index 5f7e286ff..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d0/d4594e16f2e19107e3fa7ea63e7aaaff305ffb and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d2/f8637f2eab2507a1e13cbc9df4729ec386627e b/tests-clar/resources/merge-resolve/.gitted/objects/d2/f8637f2eab2507a1e13cbc9df4729ec386627e deleted file mode 100644 index 558a8513f..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d2/f8637f2eab2507a1e13cbc9df4729ec386627e and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d3/719a5ae8e4d92276b5313ce976f6ee5af2b436 b/tests-clar/resources/merge-resolve/.gitted/objects/d3/719a5ae8e4d92276b5313ce976f6ee5af2b436 deleted file mode 100644 index 930bf5a5e..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/d3/719a5ae8e4d92276b5313ce976f6ee5af2b436 +++ /dev/null @@ -1,2 +0,0 @@ -x=10 E}uAHب zRHPT Brh/]?a 48,_MdkуTPF!TZQ? -R֧FN_J͆ h{(kLKV1p+Q A \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d3/7aa3bbfe1c0c49b909781251b956dbabe85f96 b/tests-clar/resources/merge-resolve/.gitted/objects/d3/7aa3bbfe1c0c49b909781251b956dbabe85f96 deleted file mode 100644 index 5902e0f32..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d3/7aa3bbfe1c0c49b909781251b956dbabe85f96 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d3/7ad72a2052685fc6201c2af90103ad42d2079b b/tests-clar/resources/merge-resolve/.gitted/objects/d3/7ad72a2052685fc6201c2af90103ad42d2079b deleted file mode 100644 index b2f39bff4..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d3/7ad72a2052685fc6201c2af90103ad42d2079b and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d4/207f77243500bec335ab477f9227fcdb1e271a b/tests-clar/resources/merge-resolve/.gitted/objects/d4/207f77243500bec335ab477f9227fcdb1e271a deleted file mode 100644 index 862e4e5bc..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/d4/207f77243500bec335ab477f9227fcdb1e271a +++ /dev/null @@ -1,2 +0,0 @@ -xK -1D]O'7t:݌H&z:]oZBBXl(昭+d<"6^% A( J,% %5SSmR^؊Nu^뢏O:Wځ| DcFQEn6#Q \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d4/27e0b2e138501a3d15cc376077a3631e15bd46 b/tests-clar/resources/merge-resolve/.gitted/objects/d4/27e0b2e138501a3d15cc376077a3631e15bd46 deleted file mode 100644 index 0b3611ae4..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d4/27e0b2e138501a3d15cc376077a3631e15bd46 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d5/093787ef302b941b6aab081b99fb4880038bd8 b/tests-clar/resources/merge-resolve/.gitted/objects/d5/093787ef302b941b6aab081b99fb4880038bd8 deleted file mode 100644 index 7d73449eb..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d5/093787ef302b941b6aab081b99fb4880038bd8 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d5/a61b0b4992a4f0caa887fa08b52431e727bb6f b/tests-clar/resources/merge-resolve/.gitted/objects/d5/a61b0b4992a4f0caa887fa08b52431e727bb6f deleted file mode 100644 index a7921de43..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d5/a61b0b4992a4f0caa887fa08b52431e727bb6f and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d5/b6fc965c926a1bfc9ee456042b94088b5c5d21 b/tests-clar/resources/merge-resolve/.gitted/objects/d5/b6fc965c926a1bfc9ee456042b94088b5c5d21 deleted file mode 100644 index 924bdbbb5..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d5/b6fc965c926a1bfc9ee456042b94088b5c5d21 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d5/ec1152fe25e9fec00189eb00b3db71db24c218 b/tests-clar/resources/merge-resolve/.gitted/objects/d5/ec1152fe25e9fec00189eb00b3db71db24c218 deleted file mode 100644 index 0d2534bc9..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d5/ec1152fe25e9fec00189eb00b3db71db24c218 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d6/42b9770c66bba94a08df09b5efb095001f76d7 b/tests-clar/resources/merge-resolve/.gitted/objects/d6/42b9770c66bba94a08df09b5efb095001f76d7 deleted file mode 100644 index 1671f9f2c..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d6/42b9770c66bba94a08df09b5efb095001f76d7 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d6/462fa3f5292857db599c54aea2bf91616230c5 b/tests-clar/resources/merge-resolve/.gitted/objects/d6/462fa3f5292857db599c54aea2bf91616230c5 deleted file mode 100644 index baae3f0e0..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d6/462fa3f5292857db599c54aea2bf91616230c5 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d6/cf6c7741b3316826af1314042550c97ded1d50 b/tests-clar/resources/merge-resolve/.gitted/objects/d6/cf6c7741b3316826af1314042550c97ded1d50 deleted file mode 100644 index 8f9ae1fc6..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/d6/cf6c7741b3316826af1314042550c97ded1d50 +++ /dev/null @@ -1,2 +0,0 @@ -xQ -1 D)r%i@oje[7̤ZʽMSLBNlm B~>-uY8ꠟt֯]Qa͠3f]>bl(A] \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d8/74671ef5b20184836cb983bb273e5280384d0b b/tests-clar/resources/merge-resolve/.gitted/objects/d8/74671ef5b20184836cb983bb273e5280384d0b deleted file mode 100644 index 1d8037895..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d8/74671ef5b20184836cb983bb273e5280384d0b and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d8/fa77b6833082c1ea36b7828a582d4c43882450 b/tests-clar/resources/merge-resolve/.gitted/objects/d8/fa77b6833082c1ea36b7828a582d4c43882450 deleted file mode 100644 index 988145322..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/d8/fa77b6833082c1ea36b7828a582d4c43882450 +++ /dev/null @@ -1 +0,0 @@ -x1 DQkN1&6%lBknaa1kdI(Ur'7LA,+Wm9 I'U͹_ܰN \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/d9/63979c237d08b6ba39062ee7bf64c7d34a27f8 b/tests-clar/resources/merge-resolve/.gitted/objects/d9/63979c237d08b6ba39062ee7bf64c7d34a27f8 deleted file mode 100644 index 5fa10405c..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/d9/63979c237d08b6ba39062ee7bf64c7d34a27f8 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/da/178208145ef585a1bd5ca5f4c9785d738df2cf b/tests-clar/resources/merge-resolve/.gitted/objects/da/178208145ef585a1bd5ca5f4c9785d738df2cf deleted file mode 100644 index 6292118e0..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/da/178208145ef585a1bd5ca5f4c9785d738df2cf and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/db/6261a7c65c7fd678520c9bb6f2c47582ab9ed5 b/tests-clar/resources/merge-resolve/.gitted/objects/db/6261a7c65c7fd678520c9bb6f2c47582ab9ed5 deleted file mode 100644 index b82e7fcaf..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/db/6261a7c65c7fd678520c9bb6f2c47582ab9ed5 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/dd/9a570c3400e6e07bc4d7651d6e20b08926b3d9 b/tests-clar/resources/merge-resolve/.gitted/objects/dd/9a570c3400e6e07bc4d7651d6e20b08926b3d9 deleted file mode 100644 index 8fd60cbe8..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/dd/9a570c3400e6e07bc4d7651d6e20b08926b3d9 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/de/872ee3618b894992e9d1e18ba2ebe256a112f9 b/tests-clar/resources/merge-resolve/.gitted/objects/de/872ee3618b894992e9d1e18ba2ebe256a112f9 deleted file mode 100644 index 04dda4a75..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/de/872ee3618b894992e9d1e18ba2ebe256a112f9 +++ /dev/null @@ -1 +0,0 @@ -x퐱 S3ŏlKAB4Wb T5:8Sc ԻP`KIˆO3Z&ؐ \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/df/e3f22baa1f6fce5447901c3086bae368de6bdd b/tests-clar/resources/merge-resolve/.gitted/objects/df/e3f22baa1f6fce5447901c3086bae368de6bdd deleted file mode 100644 index e13569440..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/df/e3f22baa1f6fce5447901c3086bae368de6bdd and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/e0/67f9361140f19391472df8a82d6610813c73b7 b/tests-clar/resources/merge-resolve/.gitted/objects/e0/67f9361140f19391472df8a82d6610813c73b7 deleted file mode 100644 index 955431dd7..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/e0/67f9361140f19391472df8a82d6610813c73b7 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/e1/129b3cfb5898e0fbd606e0cb80b2755e50d161 b/tests-clar/resources/merge-resolve/.gitted/objects/e1/129b3cfb5898e0fbd606e0cb80b2755e50d161 deleted file mode 100644 index 751f1dd33..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/e1/129b3cfb5898e0fbd606e0cb80b2755e50d161 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/e1/7ace1492648c9dc5701bad5c47af9d1b60c4e9 b/tests-clar/resources/merge-resolve/.gitted/objects/e1/7ace1492648c9dc5701bad5c47af9d1b60c4e9 deleted file mode 100644 index 4a812e5df..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/e1/7ace1492648c9dc5701bad5c47af9d1b60c4e9 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/e2/c6abbd55fed5ac71a5f2751e29b4a34726a595 b/tests-clar/resources/merge-resolve/.gitted/objects/e2/c6abbd55fed5ac71a5f2751e29b4a34726a595 deleted file mode 100644 index 7b84ce966..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/e2/c6abbd55fed5ac71a5f2751e29b4a34726a595 +++ /dev/null @@ -1 +0,0 @@ -x+)JMU067f040031QH,-M-JOMLI+(aH:,:C: o>ZC'g$楧f&%%g5qYeZokM2ԐX\ZDPC~^ZNfrIf^:XZHي1O(_,' jvn~JfZ&5%\N,5[e2 I{| 2mg˾15ӿ,\})TC)0Dvz֛9MՅ'6b \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/e3/1e7ad3ed298f24e383c4950f4671993ec078e4 b/tests-clar/resources/merge-resolve/.gitted/objects/e3/1e7ad3ed298f24e383c4950f4671993ec078e4 deleted file mode 100644 index a28ded3fb..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/e3/1e7ad3ed298f24e383c4950f4671993ec078e4 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/e3/76fbdd06ebf021c92724da9f26f44212734e3e b/tests-clar/resources/merge-resolve/.gitted/objects/e3/76fbdd06ebf021c92724da9f26f44212734e3e deleted file mode 100644 index 8da234114..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/e3/76fbdd06ebf021c92724da9f26f44212734e3e +++ /dev/null @@ -1,3 +0,0 @@ -xA@E]s -`@ uH)M=Scz:ʊ(N+6ޛDFe𭭘Yg$+G&F -pG 4mQ\85#FC~QERu);c6'j \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/e4/9f917b448d1340b31d76e54ba388268fd4c922 b/tests-clar/resources/merge-resolve/.gitted/objects/e4/9f917b448d1340b31d76e54ba388268fd4c922 deleted file mode 100644 index 870c3e732..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/e4/9f917b448d1340b31d76e54ba388268fd4c922 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/e4/f618a2c3ed0669308735727df5ebf2447f022f b/tests-clar/resources/merge-resolve/.gitted/objects/e4/f618a2c3ed0669308735727df5ebf2447f022f deleted file mode 100644 index c7e1ee9d7..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/e4/f618a2c3ed0669308735727df5ebf2447f022f +++ /dev/null @@ -1,2 +0,0 @@ -xK!D]s -.iOboi2. bhJQ6b`7:DN.%4uIQYcm`Q¨ aQYa@>ɗEc9%bhf1x}xwUQv kv@`O;$Kșybh2癈sLA ?R\˷ץ(~Yïb-'Yǎp=Njq˟m[zO+ \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/fa/c03f2c5139618d87d53614c153823bf1f31396 b/tests-clar/resources/merge-resolve/.gitted/objects/fa/c03f2c5139618d87d53614c153823bf1f31396 deleted file mode 100644 index 30e07e5b7..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/fa/c03f2c5139618d87d53614c153823bf1f31396 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/fa/da9356aa3f74622327a3038ae9c6f92e1c5c1d b/tests-clar/resources/merge-resolve/.gitted/objects/fa/da9356aa3f74622327a3038ae9c6f92e1c5c1d deleted file mode 100644 index 16ce49a1b..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/fa/da9356aa3f74622327a3038ae9c6f92e1c5c1d and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/fb/738a106cfd097a4acb96ce132ecb1ad6c46b03 b/tests-clar/resources/merge-resolve/.gitted/objects/fb/738a106cfd097a4acb96ce132ecb1ad6c46b03 deleted file mode 100644 index 4f1e72688..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/fb/738a106cfd097a4acb96ce132ecb1ad6c46b03 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/fc/4c636d6515e9e261f9260dbcf3cc6eca97ea08 b/tests-clar/resources/merge-resolve/.gitted/objects/fc/4c636d6515e9e261f9260dbcf3cc6eca97ea08 deleted file mode 100644 index be8a810cd..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/fc/4c636d6515e9e261f9260dbcf3cc6eca97ea08 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/fc/7d7b805f7a9428574f4f802b2e34cd20ab9d99 b/tests-clar/resources/merge-resolve/.gitted/objects/fc/7d7b805f7a9428574f4f802b2e34cd20ab9d99 deleted file mode 100644 index 20493e68c..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/fc/7d7b805f7a9428574f4f802b2e34cd20ab9d99 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/fc/90237dc4891fa6c69827fc465632225e391618 b/tests-clar/resources/merge-resolve/.gitted/objects/fc/90237dc4891fa6c69827fc465632225e391618 deleted file mode 100644 index 961814bae..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/fc/90237dc4891fa6c69827fc465632225e391618 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/fd/57d2d6770fad8e9959124793a17f441b571e66 b/tests-clar/resources/merge-resolve/.gitted/objects/fd/57d2d6770fad8e9959124793a17f441b571e66 deleted file mode 100644 index 21e6b2c55..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/fd/57d2d6770fad8e9959124793a17f441b571e66 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/fd/89f8cffb663ac89095a0f9764902e93ceaca6a b/tests-clar/resources/merge-resolve/.gitted/objects/fd/89f8cffb663ac89095a0f9764902e93ceaca6a deleted file mode 100644 index 2f9d83b26..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/objects/fd/89f8cffb663ac89095a0f9764902e93ceaca6a +++ /dev/null @@ -1,2 +0,0 @@ -xK!D]s -.{`cx/ɸ`0 oURy|Y`dPA!4C2d=x#e`BgrubLffG@՗-}KԲUy=];)r0 R$(%o=׶OPw \ No newline at end of file diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/fe/5407fc50a53aecb41d1a6e9ea7b612e581af87 b/tests-clar/resources/merge-resolve/.gitted/objects/fe/5407fc50a53aecb41d1a6e9ea7b612e581af87 deleted file mode 100644 index 4ce7d2297..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/fe/5407fc50a53aecb41d1a6e9ea7b612e581af87 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/ff/49d07869831ad761bbdaea026086f8789bcb00 b/tests-clar/resources/merge-resolve/.gitted/objects/ff/49d07869831ad761bbdaea026086f8789bcb00 deleted file mode 100644 index eada39b77..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/ff/49d07869831ad761bbdaea026086f8789bcb00 and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/objects/ff/b312248d607284c290023f9502eea010d34efd b/tests-clar/resources/merge-resolve/.gitted/objects/ff/b312248d607284c290023f9502eea010d34efd deleted file mode 100644 index 7e46c4fe3..000000000 Binary files a/tests-clar/resources/merge-resolve/.gitted/objects/ff/b312248d607284c290023f9502eea010d34efd and /dev/null differ diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/branch deleted file mode 100644 index 03f79a3dc..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/branch +++ /dev/null @@ -1 +0,0 @@ -7cb63eed597130ba4abb87b3e544b85021905520 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/df_ancestor b/tests-clar/resources/merge-resolve/.gitted/refs/heads/df_ancestor deleted file mode 100644 index 4bc37ac60..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/df_ancestor +++ /dev/null @@ -1 +0,0 @@ -2da538570bc1e5b2c3e855bf702f35248ad0735f diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/df_side1 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/df_side1 deleted file mode 100644 index ca6dd679d..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/df_side1 +++ /dev/null @@ -1 +0,0 @@ -a7dbfcbfc1a60709cb80b5ca24539008456531d0 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/df_side2 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/df_side2 deleted file mode 100644 index b8160f80e..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/df_side2 +++ /dev/null @@ -1 +0,0 @@ -fc90237dc4891fa6c69827fc465632225e391618 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/ff_branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/ff_branch deleted file mode 100644 index e9e90512f..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/ff_branch +++ /dev/null @@ -1 +0,0 @@ -fd89f8cffb663ac89095a0f9764902e93ceaca6a diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/master b/tests-clar/resources/merge-resolve/.gitted/refs/heads/master deleted file mode 100644 index 8a329ae5f..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -bd593285fc7fe4ca18ccdbabf027f5d689101452 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo1 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo1 deleted file mode 100644 index 4d2c66902..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo1 +++ /dev/null @@ -1 +0,0 @@ -16f825815cfd20a07a75c71554e82d8eede0b061 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo2 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo2 deleted file mode 100644 index f503977a7..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo2 +++ /dev/null @@ -1 +0,0 @@ -158dc7bedb202f5b26502bf3574faa7f4238d56c diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo3 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo3 deleted file mode 100644 index b92994f10..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo3 +++ /dev/null @@ -1 +0,0 @@ -50ce7d7d01217679e26c55939eef119e0c93e272 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo4 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo4 deleted file mode 100644 index f33d57cbc..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo4 +++ /dev/null @@ -1 +0,0 @@ -54269b3f6ec3d7d4ede24dd350dd5d605495c3ae diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo5 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo5 deleted file mode 100644 index e9f943385..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo5 +++ /dev/null @@ -1 +0,0 @@ -e4f618a2c3ed0669308735727df5ebf2447f022f diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo6 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo6 deleted file mode 100644 index 4c5a98ad9..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/octo6 +++ /dev/null @@ -1 +0,0 @@ -b6f610aef53bd343e6c96227de874c66f00ee8e8 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ancestor b/tests-clar/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ancestor deleted file mode 100644 index 4092d428f..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ancestor +++ /dev/null @@ -1 +0,0 @@ -2392a2dacc9efb562b8635d6579fb458751c7c5b diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ours b/tests-clar/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ours deleted file mode 100644 index a1c50dce8..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ours +++ /dev/null @@ -1 +0,0 @@ -34bfafff88eaf118402b44e6f3e2dbbf1a582b05 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/rename_conflict_theirs b/tests-clar/resources/merge-resolve/.gitted/refs/heads/rename_conflict_theirs deleted file mode 100644 index 130989399..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/rename_conflict_theirs +++ /dev/null @@ -1 +0,0 @@ -a802e06f1782a9645b9851bc7202cee74a8a4972 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/renames1 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/renames1 deleted file mode 100644 index 3d248102c..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/renames1 +++ /dev/null @@ -1 +0,0 @@ -412b32fb66137366147f1801ecc962452757d48a diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/renames2 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/renames2 deleted file mode 100644 index d22621561..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/renames2 +++ /dev/null @@ -1 +0,0 @@ -ab40af3cb8a3ed2e2843e96d9aa7871336b94573 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-10 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-10 deleted file mode 100644 index 5b378cd88..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-10 +++ /dev/null @@ -1 +0,0 @@ -0ec5f433959cd46177f745903353efb5be08d151 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-10-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-10-branch deleted file mode 100644 index b3db6c892..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-10-branch +++ /dev/null @@ -1 +0,0 @@ -11f4f3c08b737f5fd896cbefa1425ee63b21b2fa diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-11 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-11 deleted file mode 100644 index 154de9a64..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-11 +++ /dev/null @@ -1 +0,0 @@ -3168dca1a561889b045a6441909f4c56145e666d diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-11-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-11-branch deleted file mode 100644 index 2e4118029..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-11-branch +++ /dev/null @@ -1 +0,0 @@ -6718a45909532d1fcf5600d0877f7fe7e78f0b86 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-13 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-13 deleted file mode 100644 index 297573a57..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-13 +++ /dev/null @@ -1 +0,0 @@ -a3fabece9eb8748da810e1e08266fef9b7136ad4 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-13-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-13-branch deleted file mode 100644 index 22e429a61..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-13-branch +++ /dev/null @@ -1 +0,0 @@ -05f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-14 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-14 deleted file mode 100644 index 89051853a..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-14 +++ /dev/null @@ -1 +0,0 @@ -7e2d058d5fedf8329db44db4fac610d6b1a89159 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-14-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-14-branch deleted file mode 100644 index 0158f950c..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-14-branch +++ /dev/null @@ -1 +0,0 @@ -8187117062b750eed4f93fd7e899f17b52ce554d diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-2alt b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-2alt deleted file mode 100644 index 474074120..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-2alt +++ /dev/null @@ -1 +0,0 @@ -566ab53c220a2eafc1212af1a024513230280ab9 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-2alt-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-2alt-branch deleted file mode 100644 index 2f5f1a4af..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-2alt-branch +++ /dev/null @@ -1 +0,0 @@ -c9174cef549ec94ecbc43ef03cdc775b4950becb diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-3alt b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-3alt deleted file mode 100644 index 18e50ae12..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-3alt +++ /dev/null @@ -1 +0,0 @@ -4c9fac0707f8d4195037ae5a681aa48626491541 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-3alt-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-3alt-branch deleted file mode 100644 index 7bc1a8d15..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-3alt-branch +++ /dev/null @@ -1 +0,0 @@ -c607fc30883e335def28cd686b51f6cfa02b06ec diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-4 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-4 deleted file mode 100644 index f49bbf956..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-4 +++ /dev/null @@ -1 +0,0 @@ -cc3e3009134cb88014129fc8858d1101359e5e2f diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-4-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-4-branch deleted file mode 100644 index bff519ef1..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-4-branch +++ /dev/null @@ -1 +0,0 @@ -183310e30fb1499af8c619108ffea4d300b5e778 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1 deleted file mode 100644 index 963a7b336..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1 +++ /dev/null @@ -1 +0,0 @@ -4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1-branch deleted file mode 100644 index 4a22138e7..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1-branch +++ /dev/null @@ -1 +0,0 @@ -478172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2 deleted file mode 100644 index aa4ada17e..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2 +++ /dev/null @@ -1 +0,0 @@ -3b47b031b3e55ae11e14a05260b1c3ffd6838d55 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2-branch deleted file mode 100644 index 5553cdba1..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2-branch +++ /dev/null @@ -1 +0,0 @@ -f48097eb340dc5a7cae55aabcf1faf4548aa821f diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-6 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-6 deleted file mode 100644 index fb685bb63..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-6 +++ /dev/null @@ -1 +0,0 @@ -99b4f7e4f24470fa06b980bc21f1095c2a9425c0 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-6-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-6-branch deleted file mode 100644 index efc4c55ac..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-6-branch +++ /dev/null @@ -1 +0,0 @@ -a43150a738849c59376cf30bb2a68348a83c8f48 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-7 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-7 deleted file mode 100644 index 9c9424346..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-7 +++ /dev/null @@ -1 +0,0 @@ -d874671ef5b20184836cb983bb273e5280384d0b diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-7-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-7-branch deleted file mode 100644 index 1762bb5db..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-7-branch +++ /dev/null @@ -1 +0,0 @@ -5195a1b480f66691b667f10a9e41e70115a78351 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-8 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-8 deleted file mode 100644 index 837c4915a..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-8 +++ /dev/null @@ -1 +0,0 @@ -3575826c96a975031d2c14368529cc5c4353a8fd diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-8-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-8-branch deleted file mode 100644 index 874230eff..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-8-branch +++ /dev/null @@ -1 +0,0 @@ -52d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-9 b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-9 deleted file mode 100644 index b968a3efb..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-9 +++ /dev/null @@ -1 +0,0 @@ -c35dee9bcc0e989f3b0c40f68372a9a51b6c4e6a diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-9-branch b/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-9-branch deleted file mode 100644 index 7f3097b69..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/trivial-9-branch +++ /dev/null @@ -1 +0,0 @@ -13d1be4ea52a6ced1d7a1d832f0ee3c399348e5e diff --git a/tests-clar/resources/merge-resolve/.gitted/refs/heads/unrelated b/tests-clar/resources/merge-resolve/.gitted/refs/heads/unrelated deleted file mode 100644 index bb877be2e..000000000 --- a/tests-clar/resources/merge-resolve/.gitted/refs/heads/unrelated +++ /dev/null @@ -1 +0,0 @@ -55b4e4687e7a0d9ca367016ed930f385d4022e6f diff --git a/tests-clar/resources/merge-resolve/added-in-master.txt b/tests-clar/resources/merge-resolve/added-in-master.txt deleted file mode 100644 index 233c0919c..000000000 --- a/tests-clar/resources/merge-resolve/added-in-master.txt +++ /dev/null @@ -1 +0,0 @@ -this file is added in master diff --git a/tests-clar/resources/merge-resolve/automergeable.txt b/tests-clar/resources/merge-resolve/automergeable.txt deleted file mode 100644 index ee3fa1b8c..000000000 --- a/tests-clar/resources/merge-resolve/automergeable.txt +++ /dev/null @@ -1,9 +0,0 @@ -this file is changed in master -this file is automergeable -this file is automergeable -this file is automergeable -this file is automergeable -this file is automergeable -this file is automergeable -this file is automergeable -this file is automergeable diff --git a/tests-clar/resources/merge-resolve/changed-in-branch.txt b/tests-clar/resources/merge-resolve/changed-in-branch.txt deleted file mode 100644 index ab6c44a2e..000000000 --- a/tests-clar/resources/merge-resolve/changed-in-branch.txt +++ /dev/null @@ -1 +0,0 @@ -initial revision diff --git a/tests-clar/resources/merge-resolve/changed-in-master.txt b/tests-clar/resources/merge-resolve/changed-in-master.txt deleted file mode 100644 index 11deab00b..000000000 --- a/tests-clar/resources/merge-resolve/changed-in-master.txt +++ /dev/null @@ -1 +0,0 @@ -changed in master diff --git a/tests-clar/resources/merge-resolve/conflicting.txt b/tests-clar/resources/merge-resolve/conflicting.txt deleted file mode 100644 index 4e886e602..000000000 --- a/tests-clar/resources/merge-resolve/conflicting.txt +++ /dev/null @@ -1 +0,0 @@ -this file is changed in master and branch diff --git a/tests-clar/resources/merge-resolve/removed-in-branch.txt b/tests-clar/resources/merge-resolve/removed-in-branch.txt deleted file mode 100644 index dfe3f22ba..000000000 --- a/tests-clar/resources/merge-resolve/removed-in-branch.txt +++ /dev/null @@ -1 +0,0 @@ -this is removed in branch diff --git a/tests-clar/resources/merge-resolve/unchanged.txt b/tests-clar/resources/merge-resolve/unchanged.txt deleted file mode 100644 index c8f06f2e3..000000000 --- a/tests-clar/resources/merge-resolve/unchanged.txt +++ /dev/null @@ -1 +0,0 @@ -this file is unchanged in both diff --git a/tests-clar/resources/mergedrepo/.gitted/COMMIT_EDITMSG b/tests-clar/resources/mergedrepo/.gitted/COMMIT_EDITMSG deleted file mode 100644 index 1f7391f92..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/COMMIT_EDITMSG +++ /dev/null @@ -1 +0,0 @@ -master diff --git a/tests-clar/resources/mergedrepo/.gitted/HEAD b/tests-clar/resources/mergedrepo/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/mergedrepo/.gitted/MERGE_HEAD b/tests-clar/resources/mergedrepo/.gitted/MERGE_HEAD deleted file mode 100644 index a5bdf6e40..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/MERGE_HEAD +++ /dev/null @@ -1 +0,0 @@ -e2809157a7766f272e4cfe26e61ef2678a5357ff diff --git a/tests-clar/resources/mergedrepo/.gitted/MERGE_MODE b/tests-clar/resources/mergedrepo/.gitted/MERGE_MODE deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/mergedrepo/.gitted/MERGE_MSG b/tests-clar/resources/mergedrepo/.gitted/MERGE_MSG deleted file mode 100644 index 7c4d1f5a9..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/MERGE_MSG +++ /dev/null @@ -1,5 +0,0 @@ -Merge branch 'branch' - -Conflicts: - conflicts-one.txt - conflicts-two.txt diff --git a/tests-clar/resources/mergedrepo/.gitted/ORIG_HEAD b/tests-clar/resources/mergedrepo/.gitted/ORIG_HEAD deleted file mode 100644 index 13d4d6721..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/ORIG_HEAD +++ /dev/null @@ -1 +0,0 @@ -3a34580a35add43a4cf361e8e9a30060a905c876 diff --git a/tests-clar/resources/mergedrepo/.gitted/config b/tests-clar/resources/mergedrepo/.gitted/config deleted file mode 100644 index af107929f..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true diff --git a/tests-clar/resources/mergedrepo/.gitted/description b/tests-clar/resources/mergedrepo/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/mergedrepo/.gitted/index b/tests-clar/resources/mergedrepo/.gitted/index deleted file mode 100644 index 3d29f78e7..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/info/exclude b/tests-clar/resources/mergedrepo/.gitted/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/mergedrepo/.gitted/logs/HEAD b/tests-clar/resources/mergedrepo/.gitted/logs/HEAD deleted file mode 100644 index a385da67b..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/logs/HEAD +++ /dev/null @@ -1,5 +0,0 @@ -0000000000000000000000000000000000000000 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371828 -0500 commit (initial): initial -9a05ccb4e0f948de03128e095f39dae6976751c5 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371835 -0500 checkout: moving from master to branch -9a05ccb4e0f948de03128e095f39dae6976751c5 e2809157a7766f272e4cfe26e61ef2678a5357ff Edward Thomson 1351371872 -0500 commit: branch -e2809157a7766f272e4cfe26e61ef2678a5357ff 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371873 -0500 checkout: moving from branch to master -9a05ccb4e0f948de03128e095f39dae6976751c5 3a34580a35add43a4cf361e8e9a30060a905c876 Edward Thomson 1351372106 -0500 commit: master diff --git a/tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/branch b/tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/branch deleted file mode 100644 index 26a5e8dc5..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/branch +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371835 -0500 branch: Created from HEAD -9a05ccb4e0f948de03128e095f39dae6976751c5 e2809157a7766f272e4cfe26e61ef2678a5357ff Edward Thomson 1351371872 -0500 commit: branch diff --git a/tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/master b/tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/master deleted file mode 100644 index 425f7bd89..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371828 -0500 commit (initial): initial -9a05ccb4e0f948de03128e095f39dae6976751c5 3a34580a35add43a4cf361e8e9a30060a905c876 Edward Thomson 1351372106 -0500 commit: master diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712 b/tests-clar/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712 deleted file mode 100644 index 9232f79d9..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91 b/tests-clar/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91 deleted file mode 100644 index 3e124d9a4..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 b/tests-clar/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 deleted file mode 100644 index 7bb19c873..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211e b/tests-clar/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211e deleted file mode 100644 index 487bcffb1..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211e and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6 b/tests-clar/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6 deleted file mode 100644 index 2eb3954fc..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534 b/tests-clar/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534 deleted file mode 100644 index ebe83ccb2..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/3a/34580a35add43a4cf361e8e9a30060a905c876 b/tests-clar/resources/mergedrepo/.gitted/objects/3a/34580a35add43a4cf361e8e9a30060a905c876 deleted file mode 100644 index 0d4095ffc..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/objects/3a/34580a35add43a4cf361e8e9a30060a905c876 +++ /dev/null @@ -1,2 +0,0 @@ -xK -1D]}Dx/O"F2oo<*ZoљuIhhrl"r YT8'#vm0.¨.:.#+9R^nG~[=VjR"IjD۔7|N` \ No newline at end of file diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8c b/tests-clar/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8c deleted file mode 100644 index 33389c302..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8c and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3 b/tests-clar/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3 deleted file mode 100644 index 5361ea685..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52da b/tests-clar/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52da deleted file mode 100644 index a60da877c..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52da and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46ad b/tests-clar/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46ad deleted file mode 100644 index 85e84d71e..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46ad and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399 b/tests-clar/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399 deleted file mode 100644 index b16b521e6..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 b/tests-clar/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 deleted file mode 100644 index 7c4e85ffb..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 b/tests-clar/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 deleted file mode 100644 index 65173fc4d..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71 b/tests-clar/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71 deleted file mode 100644 index 162fa4455..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038c b/tests-clar/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038c deleted file mode 100644 index 77a519f55..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038c and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda b/tests-clar/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda deleted file mode 100644 index f624cd4f1..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673 b/tests-clar/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673 deleted file mode 100644 index 096474c03..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735a b/tests-clar/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735a deleted file mode 100644 index a413bc6b0..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735a and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2 b/tests-clar/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2 deleted file mode 100644 index 3ac8f6018..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8 b/tests-clar/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8 deleted file mode 100644 index 589a5ae9b..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 b/tests-clar/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 deleted file mode 100644 index 6503985e3..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50 b/tests-clar/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50 deleted file mode 100644 index 2eaa80838..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/9a/05ccb4e0f948de03128e095f39dae6976751c5 b/tests-clar/resources/mergedrepo/.gitted/objects/9a/05ccb4e0f948de03128e095f39dae6976751c5 deleted file mode 100644 index 7373a80d8..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/objects/9a/05ccb4e0f948de03128e095f39dae6976751c5 +++ /dev/null @@ -1 +0,0 @@ -x !Dm@ c6q##Ay/ ܁:#$ltH:闄*DXhV} ˷n[-K_;Z@J GԈbq3"go@I \ No newline at end of file diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092c b/tests-clar/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092c deleted file mode 100644 index c5a651f97..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092c and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d b/tests-clar/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d deleted file mode 100644 index 3e14b5dc8..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51 b/tests-clar/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51 deleted file mode 100644 index a641adc2e..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/e2/809157a7766f272e4cfe26e61ef2678a5357ff b/tests-clar/resources/mergedrepo/.gitted/objects/e2/809157a7766f272e4cfe26e61ef2678a5357ff deleted file mode 100644 index fa86662e0..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/objects/e2/809157a7766f272e4cfe26e61ef2678a5357ff +++ /dev/null @@ -1,3 +0,0 @@ -xK -1D]t> xNq1(]{Pe mٍ.S0[Dcd -ŅbMԝCgd@>glX].$!0*zu})/E_<ڪO:WځrơqѤh@mt;;5uZyVo\M \ No newline at end of file diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478 b/tests-clar/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478 deleted file mode 100644 index c9841c698..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406 b/tests-clar/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406 deleted file mode 100644 index cd587dbec..000000000 Binary files a/tests-clar/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406 and /dev/null differ diff --git a/tests-clar/resources/mergedrepo/.gitted/refs/heads/branch b/tests-clar/resources/mergedrepo/.gitted/refs/heads/branch deleted file mode 100644 index a5bdf6e40..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/refs/heads/branch +++ /dev/null @@ -1 +0,0 @@ -e2809157a7766f272e4cfe26e61ef2678a5357ff diff --git a/tests-clar/resources/mergedrepo/.gitted/refs/heads/master b/tests-clar/resources/mergedrepo/.gitted/refs/heads/master deleted file mode 100644 index 13d4d6721..000000000 --- a/tests-clar/resources/mergedrepo/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -3a34580a35add43a4cf361e8e9a30060a905c876 diff --git a/tests-clar/resources/mergedrepo/conflicts-one.txt b/tests-clar/resources/mergedrepo/conflicts-one.txt deleted file mode 100644 index 8aad34cc8..000000000 --- a/tests-clar/resources/mergedrepo/conflicts-one.txt +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -This is most certainly a conflict! -======= -This is a conflict!!! ->>>>>>> branch diff --git a/tests-clar/resources/mergedrepo/conflicts-two.txt b/tests-clar/resources/mergedrepo/conflicts-two.txt deleted file mode 100644 index e62cac5c8..000000000 --- a/tests-clar/resources/mergedrepo/conflicts-two.txt +++ /dev/null @@ -1,5 +0,0 @@ -<<<<<<< HEAD -This is without question another conflict! -======= -This is another conflict!!! ->>>>>>> branch diff --git a/tests-clar/resources/mergedrepo/one.txt b/tests-clar/resources/mergedrepo/one.txt deleted file mode 100644 index 75938de1e..000000000 --- a/tests-clar/resources/mergedrepo/one.txt +++ /dev/null @@ -1,10 +0,0 @@ -This is file one! -This is file one. -This is file one. -This is file one. -This is file one. -This is file one. -This is file one. -This is file one. -This is file one. -This is file one! diff --git a/tests-clar/resources/mergedrepo/two.txt b/tests-clar/resources/mergedrepo/two.txt deleted file mode 100644 index 7b26923aa..000000000 --- a/tests-clar/resources/mergedrepo/two.txt +++ /dev/null @@ -1,12 +0,0 @@ -This is file two! -This is file two. -This is file two. -This is file two. -This is file two. -This is file two. -This is file two. -This is file two. -This is file two. -This is file two. -This is file two. -This is file two! diff --git a/tests-clar/resources/partial-testrepo/.gitted/HEAD b/tests-clar/resources/partial-testrepo/.gitted/HEAD deleted file mode 100644 index 4bfb9c93f..000000000 --- a/tests-clar/resources/partial-testrepo/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/dir diff --git a/tests-clar/resources/partial-testrepo/.gitted/config b/tests-clar/resources/partial-testrepo/.gitted/config deleted file mode 100644 index 99abaab97..000000000 --- a/tests-clar/resources/partial-testrepo/.gitted/config +++ /dev/null @@ -1,7 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true -[branch "dir"] diff --git a/tests-clar/resources/partial-testrepo/.gitted/index b/tests-clar/resources/partial-testrepo/.gitted/index deleted file mode 100644 index 4f241f914..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 b/tests-clar/resources/partial-testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 deleted file mode 100644 index cedb2a22e..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e b/tests-clar/resources/partial-testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e deleted file mode 100644 index b7d944fa1..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/16/8e4ebd1c667499548ae12403b19b22a5c5e925 b/tests-clar/resources/partial-testrepo/.gitted/objects/16/8e4ebd1c667499548ae12403b19b22a5c5e925 deleted file mode 100644 index d37b93e4f..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/16/8e4ebd1c667499548ae12403b19b22a5c5e925 and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 b/tests-clar/resources/partial-testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 deleted file mode 100644 index 93a16f146..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd b/tests-clar/resources/partial-testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd deleted file mode 100644 index ba0bfb30c..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests-clar/resources/partial-testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 deleted file mode 100644 index 7ca4ceed5..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 b/tests-clar/resources/partial-testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 deleted file mode 100644 index 8953b6cef..000000000 --- a/tests-clar/resources/partial-testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 +++ /dev/null @@ -1,2 +0,0 @@ -xQ -0D)6ͦ "xO-FbEo0 Ǥ,ske[Pn8R,EpD?g}^3 <GhYK8ЖDA);gݧjp4-r;sGA4ۺ=(in7IKFE \ No newline at end of file diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 b/tests-clar/resources/partial-testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 deleted file mode 100644 index e9150214b..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 b/tests-clar/resources/partial-testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 deleted file mode 100644 index c1f22c54f..000000000 --- a/tests-clar/resources/partial-testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 +++ /dev/null @@ -1,2 +0,0 @@ -x 1ENi@k2 "X$YW0YcÅszMD08!s Xgd::@X0Pw"F/RUzmZZV}|/o5I!1z:vUim}/> -F- \ No newline at end of file diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc b/tests-clar/resources/partial-testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc deleted file mode 100644 index b669961d8..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 b/tests-clar/resources/partial-testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 deleted file mode 100644 index 9ff5eb2b5..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests-clar/resources/partial-testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a deleted file mode 100644 index 2ef4faa0f..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests-clar/resources/partial-testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d deleted file mode 100644 index 2f9b6b6e3..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests-clar/resources/partial-testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 deleted file mode 100644 index 5df58dda5..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests-clar/resources/partial-testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a deleted file mode 100644 index a79612435..000000000 --- a/tests-clar/resources/partial-testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a +++ /dev/null @@ -1,3 +0,0 @@ -x[ -0E*fդ "W0-Ft݁pS[Yx^ -Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests-clar/resources/partial-testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f deleted file mode 100644 index f8588696b..000000000 --- a/tests-clar/resources/partial-testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f +++ /dev/null @@ -1,2 +0,0 @@ -x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S - U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd b/tests-clar/resources/partial-testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd deleted file mode 100644 index d0d7e736e..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 b/tests-clar/resources/partial-testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 deleted file mode 100644 index 18a7f61c2..000000000 Binary files a/tests-clar/resources/partial-testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 and /dev/null differ diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd b/tests-clar/resources/partial-testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd deleted file mode 100644 index 75f541f10..000000000 --- a/tests-clar/resources/partial-testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd +++ /dev/null @@ -1,3 +0,0 @@ -xQ -0D)ʦI<'lR+FjEo0 a.txt - git add . - git commit -m 'added a.txt' - - mkdir fold - echo b > fold/b.txt - git add . - git commit -m 'added fold and fold/b.txt' - - git branch b1 #b1 and b2 are the same - git branch b2 - - git checkout -b b3 - echo edit >> a.txt - git add . - git commit -m 'edited a.txt' - - git checkout -b b4 master - echo edit >> fold\b.txt - git add . - git commit -m 'edited fold\b.txt' - - git checkout -b b5 master - git submodule add ../testrepo.git submodule - git commit -m "added submodule named 'submodule' pointing to '../testrepo.git'" - - git checkout master - git merge -m "merge b3, b4, and b5 to master" b3 b4 b5 - - #Log commits to include in testcase - git log --format=oneline --decorate --graph - #*-. 951bbbb90e2259a4c8950db78946784fb53fcbce (HEAD, master) merge b3, b4, and b5 to master - #|\ \ - #| | * fa38b91f199934685819bea316186d8b008c52a2 (b5) added submodule named 'submodule' pointing to '../testrepo.git' - #| * | 27b7ce66243eb1403862d05f958c002312df173d (b4) edited fold\b.txt - #| |/ - #* | d9b63a88223d8367516f50bd131a5f7349b7f3e4 (b3) edited a.txt - #|/ - #* a78705c3b2725f931d3ee05348d83cc26700f247 (b2, b1) added fold and fold/b.txt - #* 5c0bb3d1b9449d1cc69d7519fd05166f01840915 added a.txt - - #fix paths so that we can add repo folders under libgit2 repo - #rename .git to .gitted - find . -name .git -exec mv -i '{}' '{}ted' \; - mv -i .gitmodules gitmodules -popd diff --git a/tests-clar/resources/push_src/.gitted/COMMIT_EDITMSG b/tests-clar/resources/push_src/.gitted/COMMIT_EDITMSG deleted file mode 100644 index b1295084c..000000000 --- a/tests-clar/resources/push_src/.gitted/COMMIT_EDITMSG +++ /dev/null @@ -1 +0,0 @@ -added submodule named 'submodule' pointing to '../testrepo.git' diff --git a/tests-clar/resources/push_src/.gitted/HEAD b/tests-clar/resources/push_src/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/push_src/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/push_src/.gitted/ORIG_HEAD b/tests-clar/resources/push_src/.gitted/ORIG_HEAD deleted file mode 100644 index afadf9d26..000000000 --- a/tests-clar/resources/push_src/.gitted/ORIG_HEAD +++ /dev/null @@ -1 +0,0 @@ -a78705c3b2725f931d3ee05348d83cc26700f247 diff --git a/tests-clar/resources/push_src/.gitted/config b/tests-clar/resources/push_src/.gitted/config deleted file mode 100644 index 51de0311b..000000000 --- a/tests-clar/resources/push_src/.gitted/config +++ /dev/null @@ -1,10 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = false - bare = false - logallrefupdates = true - symlinks = false - ignorecase = true - hideDotFiles = dotGitOnly -[submodule "submodule"] - url = m:/dd/libgit2/tests-clar/resources/testrepo.git diff --git a/tests-clar/resources/push_src/.gitted/description b/tests-clar/resources/push_src/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/push_src/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/push_src/.gitted/index b/tests-clar/resources/push_src/.gitted/index deleted file mode 100644 index 0ef6594b3..000000000 Binary files a/tests-clar/resources/push_src/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/info/exclude b/tests-clar/resources/push_src/.gitted/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/push_src/.gitted/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/push_src/.gitted/logs/HEAD b/tests-clar/resources/push_src/.gitted/logs/HEAD deleted file mode 100644 index 4ef336f84..000000000 --- a/tests-clar/resources/push_src/.gitted/logs/HEAD +++ /dev/null @@ -1,10 +0,0 @@ -0000000000000000000000000000000000000000 5c0bb3d1b9449d1cc69d7519fd05166f01840915 Congyi Wu 1352923200 -0500 commit (initial): added a.txt -5c0bb3d1b9449d1cc69d7519fd05166f01840915 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923200 -0500 commit: added fold and fold/b.txt -a78705c3b2725f931d3ee05348d83cc26700f247 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923201 -0500 checkout: moving from master to b3 -a78705c3b2725f931d3ee05348d83cc26700f247 d9b63a88223d8367516f50bd131a5f7349b7f3e4 Congyi Wu 1352923201 -0500 commit: edited a.txt -d9b63a88223d8367516f50bd131a5f7349b7f3e4 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923201 -0500 checkout: moving from b3 to b4 -a78705c3b2725f931d3ee05348d83cc26700f247 27b7ce66243eb1403862d05f958c002312df173d Congyi Wu 1352923201 -0500 commit: edited fold\b.txt -27b7ce66243eb1403862d05f958c002312df173d a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923201 -0500 checkout: moving from b4 to b5 -a78705c3b2725f931d3ee05348d83cc26700f247 fa38b91f199934685819bea316186d8b008c52a2 Congyi Wu 1352923206 -0500 commit: added submodule named 'submodule' pointing to '../testrepo.git' -fa38b91f199934685819bea316186d8b008c52a2 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923207 -0500 checkout: moving from b5 to master -a78705c3b2725f931d3ee05348d83cc26700f247 951bbbb90e2259a4c8950db78946784fb53fcbce Congyi Wu 1352923207 -0500 merge b3 b4 b5: Merge made by the 'octopus' strategy. diff --git a/tests-clar/resources/push_src/.gitted/logs/refs/heads/b1 b/tests-clar/resources/push_src/.gitted/logs/refs/heads/b1 deleted file mode 100644 index 390a03d5c..000000000 --- a/tests-clar/resources/push_src/.gitted/logs/refs/heads/b1 +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923200 -0500 branch: Created from master diff --git a/tests-clar/resources/push_src/.gitted/logs/refs/heads/b2 b/tests-clar/resources/push_src/.gitted/logs/refs/heads/b2 deleted file mode 100644 index 390a03d5c..000000000 --- a/tests-clar/resources/push_src/.gitted/logs/refs/heads/b2 +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923200 -0500 branch: Created from master diff --git a/tests-clar/resources/push_src/.gitted/logs/refs/heads/b3 b/tests-clar/resources/push_src/.gitted/logs/refs/heads/b3 deleted file mode 100644 index 01e302c44..000000000 --- a/tests-clar/resources/push_src/.gitted/logs/refs/heads/b3 +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923201 -0500 branch: Created from HEAD -a78705c3b2725f931d3ee05348d83cc26700f247 d9b63a88223d8367516f50bd131a5f7349b7f3e4 Congyi Wu 1352923201 -0500 commit: edited a.txt diff --git a/tests-clar/resources/push_src/.gitted/logs/refs/heads/b4 b/tests-clar/resources/push_src/.gitted/logs/refs/heads/b4 deleted file mode 100644 index 7afddc54e..000000000 --- a/tests-clar/resources/push_src/.gitted/logs/refs/heads/b4 +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923201 -0500 branch: Created from master -a78705c3b2725f931d3ee05348d83cc26700f247 27b7ce66243eb1403862d05f958c002312df173d Congyi Wu 1352923201 -0500 commit: edited fold\b.txt diff --git a/tests-clar/resources/push_src/.gitted/logs/refs/heads/b5 b/tests-clar/resources/push_src/.gitted/logs/refs/heads/b5 deleted file mode 100644 index bc22567f7..000000000 --- a/tests-clar/resources/push_src/.gitted/logs/refs/heads/b5 +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923201 -0500 branch: Created from master -a78705c3b2725f931d3ee05348d83cc26700f247 fa38b91f199934685819bea316186d8b008c52a2 Congyi Wu 1352923206 -0500 commit: added submodule named 'submodule' pointing to '../testrepo.git' diff --git a/tests-clar/resources/push_src/.gitted/logs/refs/heads/master b/tests-clar/resources/push_src/.gitted/logs/refs/heads/master deleted file mode 100644 index 8aafa9ca4..000000000 --- a/tests-clar/resources/push_src/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 5c0bb3d1b9449d1cc69d7519fd05166f01840915 Congyi Wu 1352923200 -0500 commit (initial): added a.txt -5c0bb3d1b9449d1cc69d7519fd05166f01840915 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923200 -0500 commit: added fold and fold/b.txt -a78705c3b2725f931d3ee05348d83cc26700f247 951bbbb90e2259a4c8950db78946784fb53fcbce Congyi Wu 1352923207 -0500 merge b3 b4 b5: Merge made by the 'octopus' strategy. diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/HEAD b/tests-clar/resources/push_src/.gitted/modules/submodule/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/config b/tests-clar/resources/push_src/.gitted/modules/submodule/config deleted file mode 100644 index 59810077d..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/config +++ /dev/null @@ -1,15 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = false - bare = false - logallrefupdates = true - worktree = ../../../submodule - symlinks = false - ignorecase = true - hideDotFiles = dotGitOnly -[remote "origin"] - fetch = +refs/heads/*:refs/remotes/origin/* - url = m:/dd/libgit2/tests-clar/resources/testrepo.git -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/description b/tests-clar/resources/push_src/.gitted/modules/submodule/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/index b/tests-clar/resources/push_src/.gitted/modules/submodule/index deleted file mode 100644 index 8e44080f3..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/index and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/info/exclude b/tests-clar/resources/push_src/.gitted/modules/submodule/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/logs/HEAD b/tests-clar/resources/push_src/.gitted/modules/submodule/logs/HEAD deleted file mode 100644 index aedcdf295..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Congyi Wu 1352923205 -0500 clone: from m:/dd/libgit2/tests-clar/resources/testrepo.git diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/logs/refs/heads/master b/tests-clar/resources/push_src/.gitted/modules/submodule/logs/refs/heads/master deleted file mode 100644 index aedcdf295..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Congyi Wu 1352923205 -0500 clone: from m:/dd/libgit2/tests-clar/resources/testrepo.git diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/logs/refs/remotes/origin/HEAD b/tests-clar/resources/push_src/.gitted/modules/submodule/logs/refs/remotes/origin/HEAD deleted file mode 100644 index aedcdf295..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/logs/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Congyi Wu 1352923205 -0500 clone: from m:/dd/libgit2/tests-clar/resources/testrepo.git diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 deleted file mode 100644 index d1c032fce..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 deleted file mode 100644 index cedb2a22e..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 deleted file mode 100644 index 93a16f146..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/18/10dff58d8a660512d4832e740f692884338ccd b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/18/10dff58d8a660512d4832e740f692884338ccd deleted file mode 100644 index ba0bfb30c..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/18/10dff58d8a660512d4832e740f692884338ccd and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd deleted file mode 100644 index 3ec541288..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/1b/8cbad43e867676df601306689fe7c3def5e689 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/1b/8cbad43e867676df601306689fe7c3def5e689 deleted file mode 100644 index 6048d4bad..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/1b/8cbad43e867676df601306689fe7c3def5e689 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b deleted file mode 100644 index 225c45734..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 deleted file mode 100644 index cb1ed5712..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d deleted file mode 100644 index df40d99af..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 deleted file mode 100644 index 0a1500a6f..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 deleted file mode 100644 index 321eaa867..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc deleted file mode 100644 index 9bb5b623b..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 deleted file mode 100644 index 7ca4ceed5..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 deleted file mode 100644 index 8953b6cef..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 +++ /dev/null @@ -1,2 +0,0 @@ -xQ -0D)6ͦ "xO-FbEo0 Ǥ,ske[Pn8R,EpD?g}^3 <GhYK8ЖDA);gݧjp4-r;sGA4ۺ=(in7IKFE \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea deleted file mode 100644 index b4e5aa186..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 deleted file mode 100644 index 351cff823..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 deleted file mode 100644 index c1f22c54f..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 +++ /dev/null @@ -1,2 +0,0 @@ -x 1ENi@k2 "X$YW0YcÅszMD08!s Xgd::@X0Pw"F/RUzmZZV}|/o5I!1z:vUim}/> -F- \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a deleted file mode 100644 index 2ef4faa0f..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af deleted file mode 100644 index 716b0c64b..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af +++ /dev/null @@ -1 +0,0 @@ -xAj!?009o}H6}jUPPZ&Y AԛpFdpz[fYPqLJ.,Z`Ů.`v q $5+9Ot>/DE/龡W*eVdf1>覭ěʙFThk.i^0?PR, \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/7b/4384978d2493e851f9cca7858815fac9b10980 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/7b/4384978d2493e851f9cca7858815fac9b10980 deleted file mode 100644 index 23c462f34..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/7b/4384978d2493e851f9cca7858815fac9b10980 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/81/4889a078c031f61ed08ab5fa863aea9314344d deleted file mode 100644 index 2f9b6b6e3..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/81/4889a078c031f61ed08ab5fa863aea9314344d and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/84/96071c1b46c854b31185ea97743be6a8774479 deleted file mode 100644 index 5df58dda5..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/84/96071c1b46c854b31185ea97743be6a8774479 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe deleted file mode 100644 index 71019a636..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe +++ /dev/null @@ -1,2 +0,0 @@ -xM F]s41x(IKݽ/_P@!8)es - N&FGSƄh{+CZzvF7Z-kx\[P8GK/^ l>.4 \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 deleted file mode 100644 index 4cc3f4dff..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 +++ /dev/null @@ -1 +0,0 @@ -x+)JMU044b040031QrutueXlmmAṃJ}G;UTWRQ`6Kǥ^/-*|W3Py`%E\&g|0{Ӎ1X \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 deleted file mode 100644 index bf7b2bb68..000000000 Binary files a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 deleted file mode 100644 index 7f1cfb23c..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 +++ /dev/null @@ -1,2 +0,0 @@ -xM -0F]d2;XEȎ5R AE &n}ZA \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a deleted file mode 100644 index a79612435..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a +++ /dev/null @@ -1,3 +0,0 @@ -x[ -0E*fդ "W0-Ft݁pS[Yx^ -Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f deleted file mode 100644 index f8588696b..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f +++ /dev/null @@ -1,2 +0,0 @@ -x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S - U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 b/tests-clar/resources/push_src/.gitted/modules/submodule/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 deleted file mode 100644 index 29c8e824d..000000000 --- a/tests-clar/resources/push_src/.gitted/modules/submodule/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 +++ /dev/null @@ -1,3 +0,0 @@ -xQ -!@sBQ" ٱ r{RȞyE - mH&Er7S!*u΄2>#\V8|Gt-ybhFU/J-|M}W+GK \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/objects/28/905c54ea45a4bed8d7b90f51bd8bd81eec8840 b/tests-clar/resources/push_src/.gitted/objects/28/905c54ea45a4bed8d7b90f51bd8bd81eec8840 deleted file mode 100644 index dc10f6831..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/28/905c54ea45a4bed8d7b90f51bd8bd81eec8840 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/36/6226fb970ac0caa9d3f55967ab01334a548f60 b/tests-clar/resources/push_src/.gitted/objects/36/6226fb970ac0caa9d3f55967ab01334a548f60 deleted file mode 100644 index 45c4d9208..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/36/6226fb970ac0caa9d3f55967ab01334a548f60 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 b/tests-clar/resources/push_src/.gitted/objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 deleted file mode 100644 index 0bc57f266..000000000 --- a/tests-clar/resources/push_src/.gitted/objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 +++ /dev/null @@ -1,2 +0,0 @@ -x%] -0S͏B)} @bnf`f`>3(nibC0hQ6BMv2&-M0Q)+ tNsE*;}JϲN픹(th@#B˺C?TÅoyk7 \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/objects/5c/0bb3d1b9449d1cc69d7519fd05166f01840915 b/tests-clar/resources/push_src/.gitted/objects/5c/0bb3d1b9449d1cc69d7519fd05166f01840915 deleted file mode 100644 index 883182138..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/5c/0bb3d1b9449d1cc69d7519fd05166f01840915 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/61/780798228d17af2d34fce4cfbdf35556832472 b/tests-clar/resources/push_src/.gitted/objects/61/780798228d17af2d34fce4cfbdf35556832472 deleted file mode 100644 index 586bf17a4..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/61/780798228d17af2d34fce4cfbdf35556832472 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/64/fd55f9b6390202db5e5666fd1fb339089fba4d b/tests-clar/resources/push_src/.gitted/objects/64/fd55f9b6390202db5e5666fd1fb339089fba4d deleted file mode 100644 index bcaaa91c2..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/64/fd55f9b6390202db5e5666fd1fb339089fba4d and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/78/981922613b2afb6025042ff6bd878ac1994e85 b/tests-clar/resources/push_src/.gitted/objects/78/981922613b2afb6025042ff6bd878ac1994e85 deleted file mode 100644 index e814d07b0..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/78/981922613b2afb6025042ff6bd878ac1994e85 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/80/5c54522e614f29f70d2413a0470247d8b424ac b/tests-clar/resources/push_src/.gitted/objects/80/5c54522e614f29f70d2413a0470247d8b424ac deleted file mode 100644 index 552670c06..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/80/5c54522e614f29f70d2413a0470247d8b424ac and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/95/1bbbb90e2259a4c8950db78946784fb53fcbce b/tests-clar/resources/push_src/.gitted/objects/95/1bbbb90e2259a4c8950db78946784fb53fcbce deleted file mode 100644 index 596cd43de..000000000 --- a/tests-clar/resources/push_src/.gitted/objects/95/1bbbb90e2259a4c8950db78946784fb53fcbce +++ /dev/null @@ -1,2 +0,0 @@ -x[J0}*f2$Eim -\8:DfZ &65^,%lm١~;KJRXT蕄(!{¯DZqPqsPӈB\;EEgs`IeoE(YMFC9uu>|#?i.׻qD90FEENzܶ<\,\a_a.gd \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/objects/a7/8705c3b2725f931d3ee05348d83cc26700f247 b/tests-clar/resources/push_src/.gitted/objects/a7/8705c3b2725f931d3ee05348d83cc26700f247 deleted file mode 100644 index 6ad835e86..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/a7/8705c3b2725f931d3ee05348d83cc26700f247 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498 b/tests-clar/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498 deleted file mode 100644 index 1e0bd3b05..000000000 --- a/tests-clar/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498 +++ /dev/null @@ -1,3 +0,0 @@ -x5K -1D];1i"^'|d`d ooqQEͫ*Pݢ+ - 3$, }%Rw+s9y輨r`+ܦ2p/[mp~u8-Sr=,?Z+g \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/objects/b4/e1f2b375a64c1ccd40c5ff6aa8bc96839ba4fd b/tests-clar/resources/push_src/.gitted/objects/b4/e1f2b375a64c1ccd40c5ff6aa8bc96839ba4fd deleted file mode 100644 index 4e650aaa1..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/b4/e1f2b375a64c1ccd40c5ff6aa8bc96839ba4fd and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/c1/0409136a7a75e025fa502a1b2fd7b62b77d279 b/tests-clar/resources/push_src/.gitted/objects/c1/0409136a7a75e025fa502a1b2fd7b62b77d279 deleted file mode 100644 index fcb2b32f3..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/c1/0409136a7a75e025fa502a1b2fd7b62b77d279 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/cd/881f90f2933db2e4cc26b8c71fe6037ac7fe4c b/tests-clar/resources/push_src/.gitted/objects/cd/881f90f2933db2e4cc26b8c71fe6037ac7fe4c deleted file mode 100644 index ad4272638..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/cd/881f90f2933db2e4cc26b8c71fe6037ac7fe4c and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/d9/b63a88223d8367516f50bd131a5f7349b7f3e4 b/tests-clar/resources/push_src/.gitted/objects/d9/b63a88223d8367516f50bd131a5f7349b7f3e4 deleted file mode 100644 index b471e2155..000000000 --- a/tests-clar/resources/push_src/.gitted/objects/d9/b63a88223d8367516f50bd131a5f7349b7f3e4 +++ /dev/null @@ -1,2 +0,0 @@ -xA -0E]sd$ "xi2ՂmzwSErgj ![͎%wbY(zC/G\tw({r$C`Y[=DCu&V8!s=]8ޛT#|;ltWhfM}UQDM \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/objects/dc/ab83249f6f9d1ed735d651352a80519339b591 b/tests-clar/resources/push_src/.gitted/objects/dc/ab83249f6f9d1ed735d651352a80519339b591 deleted file mode 100644 index 9f6b1502f..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/dc/ab83249f6f9d1ed735d651352a80519339b591 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 b/tests-clar/resources/push_src/.gitted/objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 deleted file mode 100644 index b7b81d5e3..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/f7/8a3106c85fb549c65198b2a2086276c6174928 b/tests-clar/resources/push_src/.gitted/objects/f7/8a3106c85fb549c65198b2a2086276c6174928 deleted file mode 100644 index b9813576d..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/f7/8a3106c85fb549c65198b2a2086276c6174928 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/f8/f7aefc2900a3d737cea9eee45729fd55761e1a b/tests-clar/resources/push_src/.gitted/objects/f8/f7aefc2900a3d737cea9eee45729fd55761e1a deleted file mode 100644 index 888354fc2..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/f8/f7aefc2900a3d737cea9eee45729fd55761e1a and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/fa/38b91f199934685819bea316186d8b008c52a2 b/tests-clar/resources/push_src/.gitted/objects/fa/38b91f199934685819bea316186d8b008c52a2 deleted file mode 100644 index 13d9bca20..000000000 --- a/tests-clar/resources/push_src/.gitted/objects/fa/38b91f199934685819bea316186d8b008c52a2 +++ /dev/null @@ -1,2 +0,0 @@ -xJ15>urrneo {f[)_DmIi7 -7Ĩ8ꔌ.n܃W)_T;x,(li[D\K墓XΓP?>W~|_Wؤxs6IcJNP}~ -מ/󄳭G X \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/objects/ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e b/tests-clar/resources/push_src/.gitted/objects/ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e deleted file mode 100644 index 10f25eb7c..000000000 --- a/tests-clar/resources/push_src/.gitted/objects/ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e +++ /dev/null @@ -1,4 +0,0 @@ -x5M -1 `=E4NA H ooq{/G@5=$+SO) nx[@4y -h1ڄvmSyz' -Wk-ziQc<ޢfS~pv+ \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/objects/ff/fe95c7fd0a37fa2ed702f8f93b56b2196b3925 b/tests-clar/resources/push_src/.gitted/objects/ff/fe95c7fd0a37fa2ed702f8f93b56b2196b3925 deleted file mode 100644 index 1cdc048c0..000000000 Binary files a/tests-clar/resources/push_src/.gitted/objects/ff/fe95c7fd0a37fa2ed702f8f93b56b2196b3925 and /dev/null differ diff --git a/tests-clar/resources/push_src/.gitted/objects/pack/dummy b/tests-clar/resources/push_src/.gitted/objects/pack/dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/push_src/.gitted/refs/heads/b1 b/tests-clar/resources/push_src/.gitted/refs/heads/b1 deleted file mode 100644 index afadf9d26..000000000 --- a/tests-clar/resources/push_src/.gitted/refs/heads/b1 +++ /dev/null @@ -1 +0,0 @@ -a78705c3b2725f931d3ee05348d83cc26700f247 diff --git a/tests-clar/resources/push_src/.gitted/refs/heads/b2 b/tests-clar/resources/push_src/.gitted/refs/heads/b2 deleted file mode 100644 index afadf9d26..000000000 --- a/tests-clar/resources/push_src/.gitted/refs/heads/b2 +++ /dev/null @@ -1 +0,0 @@ -a78705c3b2725f931d3ee05348d83cc26700f247 diff --git a/tests-clar/resources/push_src/.gitted/refs/heads/b3 b/tests-clar/resources/push_src/.gitted/refs/heads/b3 deleted file mode 100644 index 3056bb436..000000000 --- a/tests-clar/resources/push_src/.gitted/refs/heads/b3 +++ /dev/null @@ -1 +0,0 @@ -d9b63a88223d8367516f50bd131a5f7349b7f3e4 diff --git a/tests-clar/resources/push_src/.gitted/refs/heads/b4 b/tests-clar/resources/push_src/.gitted/refs/heads/b4 deleted file mode 100644 index efed6f064..000000000 --- a/tests-clar/resources/push_src/.gitted/refs/heads/b4 +++ /dev/null @@ -1 +0,0 @@ -27b7ce66243eb1403862d05f958c002312df173d diff --git a/tests-clar/resources/push_src/.gitted/refs/heads/b5 b/tests-clar/resources/push_src/.gitted/refs/heads/b5 deleted file mode 100644 index cf313ad05..000000000 --- a/tests-clar/resources/push_src/.gitted/refs/heads/b5 +++ /dev/null @@ -1 +0,0 @@ -fa38b91f199934685819bea316186d8b008c52a2 diff --git a/tests-clar/resources/push_src/.gitted/refs/heads/b6 b/tests-clar/resources/push_src/.gitted/refs/heads/b6 deleted file mode 100644 index 711e466ae..000000000 --- a/tests-clar/resources/push_src/.gitted/refs/heads/b6 +++ /dev/null @@ -1 +0,0 @@ -951bbbb90e2259a4c8950db78946784fb53fcbce diff --git a/tests-clar/resources/push_src/.gitted/refs/tags/tag-blob b/tests-clar/resources/push_src/.gitted/refs/tags/tag-blob deleted file mode 100644 index abfebf22e..000000000 --- a/tests-clar/resources/push_src/.gitted/refs/tags/tag-blob +++ /dev/null @@ -1 +0,0 @@ -b483ae7ba66decee9aee971f501221dea84b1498 diff --git a/tests-clar/resources/push_src/.gitted/refs/tags/tag-commit b/tests-clar/resources/push_src/.gitted/refs/tags/tag-commit deleted file mode 100644 index c023b8452..000000000 --- a/tests-clar/resources/push_src/.gitted/refs/tags/tag-commit +++ /dev/null @@ -1 +0,0 @@ -805c54522e614f29f70d2413a0470247d8b424ac diff --git a/tests-clar/resources/push_src/.gitted/refs/tags/tag-commit-two b/tests-clar/resources/push_src/.gitted/refs/tags/tag-commit-two deleted file mode 100644 index abb365080..000000000 --- a/tests-clar/resources/push_src/.gitted/refs/tags/tag-commit-two +++ /dev/null @@ -1 +0,0 @@ -36f79b2846017d3761e0a02d0bccd573e0f90c57 diff --git a/tests-clar/resources/push_src/.gitted/refs/tags/tag-lightweight b/tests-clar/resources/push_src/.gitted/refs/tags/tag-lightweight deleted file mode 100644 index 711e466ae..000000000 --- a/tests-clar/resources/push_src/.gitted/refs/tags/tag-lightweight +++ /dev/null @@ -1 +0,0 @@ -951bbbb90e2259a4c8950db78946784fb53fcbce diff --git a/tests-clar/resources/push_src/.gitted/refs/tags/tag-tag b/tests-clar/resources/push_src/.gitted/refs/tags/tag-tag deleted file mode 100644 index d6cd74804..000000000 --- a/tests-clar/resources/push_src/.gitted/refs/tags/tag-tag +++ /dev/null @@ -1 +0,0 @@ -eea4f2705eeec2db3813f2430829afce99cd00b5 diff --git a/tests-clar/resources/push_src/.gitted/refs/tags/tag-tree b/tests-clar/resources/push_src/.gitted/refs/tags/tag-tree deleted file mode 100644 index 7a530d381..000000000 --- a/tests-clar/resources/push_src/.gitted/refs/tags/tag-tree +++ /dev/null @@ -1 +0,0 @@ -ff83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e diff --git a/tests-clar/resources/push_src/a.txt b/tests-clar/resources/push_src/a.txt deleted file mode 100644 index f7eac1c51..000000000 --- a/tests-clar/resources/push_src/a.txt +++ /dev/null @@ -1,2 +0,0 @@ -a -edit diff --git a/tests-clar/resources/push_src/fold/b.txt b/tests-clar/resources/push_src/fold/b.txt deleted file mode 100644 index 617807982..000000000 --- a/tests-clar/resources/push_src/fold/b.txt +++ /dev/null @@ -1 +0,0 @@ -b diff --git a/tests-clar/resources/push_src/foldb.txt b/tests-clar/resources/push_src/foldb.txt deleted file mode 100644 index 5b38718be..000000000 --- a/tests-clar/resources/push_src/foldb.txt +++ /dev/null @@ -1 +0,0 @@ -edit diff --git a/tests-clar/resources/push_src/gitmodules b/tests-clar/resources/push_src/gitmodules deleted file mode 100644 index f1734dfc1..000000000 --- a/tests-clar/resources/push_src/gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "submodule"] - path = submodule - url = ../testrepo.git diff --git a/tests-clar/resources/push_src/submodule/.gitted b/tests-clar/resources/push_src/submodule/.gitted deleted file mode 100644 index 3ffcf960a..000000000 --- a/tests-clar/resources/push_src/submodule/.gitted +++ /dev/null @@ -1 +0,0 @@ -gitdir: ../.git/modules/submodule diff --git a/tests-clar/resources/push_src/submodule/README b/tests-clar/resources/push_src/submodule/README deleted file mode 100644 index ca8c64728..000000000 --- a/tests-clar/resources/push_src/submodule/README +++ /dev/null @@ -1 +0,0 @@ -hey there diff --git a/tests-clar/resources/push_src/submodule/branch_file.txt b/tests-clar/resources/push_src/submodule/branch_file.txt deleted file mode 100644 index a26902575..000000000 --- a/tests-clar/resources/push_src/submodule/branch_file.txt +++ /dev/null @@ -1,2 +0,0 @@ -hi -bye! diff --git a/tests-clar/resources/push_src/submodule/new.txt b/tests-clar/resources/push_src/submodule/new.txt deleted file mode 100644 index 8e0884e36..000000000 --- a/tests-clar/resources/push_src/submodule/new.txt +++ /dev/null @@ -1 +0,0 @@ -my new file diff --git a/tests-clar/resources/renames/.gitted/HEAD b/tests-clar/resources/renames/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/renames/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/renames/.gitted/config b/tests-clar/resources/renames/.gitted/config deleted file mode 100644 index bb4d11c1f..000000000 --- a/tests-clar/resources/renames/.gitted/config +++ /dev/null @@ -1,7 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true - precomposeunicode = false diff --git a/tests-clar/resources/renames/.gitted/description b/tests-clar/resources/renames/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/renames/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/renames/.gitted/index b/tests-clar/resources/renames/.gitted/index deleted file mode 100644 index 72363c0f5..000000000 Binary files a/tests-clar/resources/renames/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/renames/.gitted/info/exclude b/tests-clar/resources/renames/.gitted/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/renames/.gitted/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/renames/.gitted/logs/HEAD b/tests-clar/resources/renames/.gitted/logs/HEAD deleted file mode 100644 index e69792263..000000000 --- a/tests-clar/resources/renames/.gitted/logs/HEAD +++ /dev/null @@ -1,4 +0,0 @@ -0000000000000000000000000000000000000000 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 Russell Belfer 1351024687 -0700 commit (initial): Initial commit -31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 2bc7f351d20b53f1c72c16c4b036e491c478c49a Russell Belfer 1351024817 -0700 commit: copy and rename with no change -2bc7f351d20b53f1c72c16c4b036e491c478c49a 1c068dee5790ef1580cfc4cd670915b48d790084 Russell Belfer 1361485758 -0800 commit: rewrites, copies with changes, etc. -1c068dee5790ef1580cfc4cd670915b48d790084 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 Russell Belfer 1361486360 -0800 commit: more renames and smallish modifications diff --git a/tests-clar/resources/renames/.gitted/logs/refs/heads/master b/tests-clar/resources/renames/.gitted/logs/refs/heads/master deleted file mode 100644 index e69792263..000000000 --- a/tests-clar/resources/renames/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,4 +0,0 @@ -0000000000000000000000000000000000000000 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 Russell Belfer 1351024687 -0700 commit (initial): Initial commit -31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 2bc7f351d20b53f1c72c16c4b036e491c478c49a Russell Belfer 1351024817 -0700 commit: copy and rename with no change -2bc7f351d20b53f1c72c16c4b036e491c478c49a 1c068dee5790ef1580cfc4cd670915b48d790084 Russell Belfer 1361485758 -0800 commit: rewrites, copies with changes, etc. -1c068dee5790ef1580cfc4cd670915b48d790084 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 Russell Belfer 1361486360 -0800 commit: more renames and smallish modifications diff --git a/tests-clar/resources/renames/.gitted/objects/03/da7ad872536bd448da8d88eb7165338bf923a7 b/tests-clar/resources/renames/.gitted/objects/03/da7ad872536bd448da8d88eb7165338bf923a7 deleted file mode 100644 index 2ee86444d..000000000 Binary files a/tests-clar/resources/renames/.gitted/objects/03/da7ad872536bd448da8d88eb7165338bf923a7 and /dev/null differ diff --git a/tests-clar/resources/renames/.gitted/objects/17/58bdd7c16a72ff7c17d8de0c957ced3ccad645 b/tests-clar/resources/renames/.gitted/objects/17/58bdd7c16a72ff7c17d8de0c957ced3ccad645 deleted file mode 100644 index 01801ed11..000000000 --- a/tests-clar/resources/renames/.gitted/objects/17/58bdd7c16a72ff7c17d8de0c957ced3ccad645 +++ /dev/null @@ -1,5 +0,0 @@ -xEͱ @QbWq H_&{]yYX`='흶=ZohzF - - - -MhBЄ&4 MhB3ьf4hF3юKx \ No newline at end of file diff --git a/tests-clar/resources/renames/.gitted/objects/19/dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 b/tests-clar/resources/renames/.gitted/objects/19/dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 deleted file mode 100644 index 4be4c6952..000000000 --- a/tests-clar/resources/renames/.gitted/objects/19/dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 +++ /dev/null @@ -1 +0,0 @@ -xM!Ei@3ސc,\X K {Nrbo,xzYC<h[&?=fcvyCWm 䮔~*D \ No newline at end of file diff --git a/tests-clar/resources/renames/.gitted/objects/5e/26abc56a5a84d89790f45416648899cbe13109 b/tests-clar/resources/renames/.gitted/objects/5e/26abc56a5a84d89790f45416648899cbe13109 deleted file mode 100644 index 2acd3d583..000000000 Binary files a/tests-clar/resources/renames/.gitted/objects/5e/26abc56a5a84d89790f45416648899cbe13109 and /dev/null differ diff --git a/tests-clar/resources/renames/.gitted/objects/61/8c6f2f8740bd6049b2fb9eb93fc15726462745 b/tests-clar/resources/renames/.gitted/objects/61/8c6f2f8740bd6049b2fb9eb93fc15726462745 deleted file mode 100644 index 24eac54c5..000000000 Binary files a/tests-clar/resources/renames/.gitted/objects/61/8c6f2f8740bd6049b2fb9eb93fc15726462745 and /dev/null differ diff --git a/tests-clar/resources/renames/.gitted/objects/66/311f5cfbe7836c27510a3ba2f43e282e2c8bba b/tests-clar/resources/renames/.gitted/objects/66/311f5cfbe7836c27510a3ba2f43e282e2c8bba deleted file mode 100644 index 5ee28a76a..000000000 Binary files a/tests-clar/resources/renames/.gitted/objects/66/311f5cfbe7836c27510a3ba2f43e282e2c8bba and /dev/null differ diff --git a/tests-clar/resources/renames/.gitted/objects/93/f538c45a57a87eb4c1e86f91c6ee41d66c7ba7 b/tests-clar/resources/renames/.gitted/objects/93/f538c45a57a87eb4c1e86f91c6ee41d66c7ba7 deleted file mode 100644 index 39105f94d..000000000 Binary files a/tests-clar/resources/renames/.gitted/objects/93/f538c45a57a87eb4c1e86f91c6ee41d66c7ba7 and /dev/null differ diff --git a/tests-clar/resources/renames/.gitted/objects/9a/69d960ae94b060f56c2a8702545e2bb1abb935 b/tests-clar/resources/renames/.gitted/objects/9a/69d960ae94b060f56c2a8702545e2bb1abb935 deleted file mode 100644 index f75178c59..000000000 Binary files a/tests-clar/resources/renames/.gitted/objects/9a/69d960ae94b060f56c2a8702545e2bb1abb935 and /dev/null differ diff --git a/tests-clar/resources/renames/.gitted/objects/ad/0a8e55a104ac54a8a29ed4b84b49e76837a113 b/tests-clar/resources/renames/.gitted/objects/ad/0a8e55a104ac54a8a29ed4b84b49e76837a113 deleted file mode 100644 index 440b7bec3..000000000 Binary files a/tests-clar/resources/renames/.gitted/objects/ad/0a8e55a104ac54a8a29ed4b84b49e76837a113 and /dev/null differ diff --git a/tests-clar/resources/renames/.gitted/objects/b9/25b224cc91f897001a9993fbce169fdaa8858f b/tests-clar/resources/renames/.gitted/objects/b9/25b224cc91f897001a9993fbce169fdaa8858f deleted file mode 100644 index 90e107fa2..000000000 Binary files a/tests-clar/resources/renames/.gitted/objects/b9/25b224cc91f897001a9993fbce169fdaa8858f and /dev/null differ diff --git a/tests-clar/resources/renames/.gitted/objects/d7/9b202de198fa61b02424b9e25e840dc75e1323 b/tests-clar/resources/renames/.gitted/objects/d7/9b202de198fa61b02424b9e25e840dc75e1323 deleted file mode 100644 index daa2b3997..000000000 Binary files a/tests-clar/resources/renames/.gitted/objects/d7/9b202de198fa61b02424b9e25e840dc75e1323 and /dev/null differ diff --git a/tests-clar/resources/renames/.gitted/objects/ea/c43f5195a2cee53b7458d8dad16aedde10711b b/tests-clar/resources/renames/.gitted/objects/ea/c43f5195a2cee53b7458d8dad16aedde10711b deleted file mode 100644 index 2fb025080..000000000 Binary files a/tests-clar/resources/renames/.gitted/objects/ea/c43f5195a2cee53b7458d8dad16aedde10711b and /dev/null differ diff --git a/tests-clar/resources/renames/.gitted/objects/ea/f4a3e3bfe68585e90cada20736ace491cd100b b/tests-clar/resources/renames/.gitted/objects/ea/f4a3e3bfe68585e90cada20736ace491cd100b deleted file mode 100644 index f72df8d82..000000000 --- a/tests-clar/resources/renames/.gitted/objects/ea/f4a3e3bfe68585e90cada20736ace491cd100b +++ /dev/null @@ -1,5 +0,0 @@ -x}R@<_QT.A[ -{t2Cez%L'!aj!x{'+;$)Ξ#yǘ#q#hc QDXmR|aD*O+^ZI~i>3a!,R!-EaI>yo*4戁Rf m&eIA*!;dݬ -Ho -OUDyTVHpwqH7Ʒ.ts6{Z+X\)C5Q9 -%t*&&v;|'4 Du[7he!NK*"C-=`#؎$Ee2T|@NBsslW|/0¬aȥJNv)-ڡiۤ3bbO:uWMNX7T \ No newline at end of file diff --git a/tests-clar/resources/renames/.gitted/objects/f9/0d4fc20ecddf21eebe6a37e9225d244339d2b5 b/tests-clar/resources/renames/.gitted/objects/f9/0d4fc20ecddf21eebe6a37e9225d244339d2b5 deleted file mode 100644 index f6d933be9..000000000 Binary files a/tests-clar/resources/renames/.gitted/objects/f9/0d4fc20ecddf21eebe6a37e9225d244339d2b5 and /dev/null differ diff --git a/tests-clar/resources/renames/.gitted/refs/heads/master b/tests-clar/resources/renames/.gitted/refs/heads/master deleted file mode 100644 index 642c3198d..000000000 --- a/tests-clar/resources/renames/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 diff --git a/tests-clar/resources/renames/.gitted/refs/heads/renames_similar b/tests-clar/resources/renames/.gitted/refs/heads/renames_similar deleted file mode 100644 index 8ffb6d94b..000000000 --- a/tests-clar/resources/renames/.gitted/refs/heads/renames_similar +++ /dev/null @@ -1 +0,0 @@ -444a76ed3e45b183753f49376af30da8c3fe276a diff --git a/tests-clar/resources/renames/.gitted/refs/heads/renames_similar_two b/tests-clar/resources/renames/.gitted/refs/heads/renames_similar_two deleted file mode 100644 index 4ee5d04e1..000000000 --- a/tests-clar/resources/renames/.gitted/refs/heads/renames_similar_two +++ /dev/null @@ -1 +0,0 @@ -50e90273af7d826ff0a95865bcd3ba8412c447d9 diff --git a/tests-clar/resources/renames/ikeepsix.txt b/tests-clar/resources/renames/ikeepsix.txt deleted file mode 100644 index eaf4a3e3b..000000000 --- a/tests-clar/resources/renames/ikeepsix.txt +++ /dev/null @@ -1,27 +0,0 @@ -I Keep Six Honest Serving-Men -============================= - -She sends'em abroad on her own affairs, - From the second she opens her eyes— -One million Hows, two million Wheres, -And seven million Whys! - -I let them rest from nine till five, - For I am busy then, -As well as breakfast, lunch, and tea, - For they are hungry men. -But different folk have different views; -I know a person small— -She keeps ten million serving-men, -Who get no rest at all! - - -- Rudyard Kipling - -I KEEP six honest serving-men - (They taught me all I knew); -Their names are What and Why and When - And How and Where and Who. -I send them over land and sea, - I send them east and west; -But after they have worked for me, - I give them all a rest. diff --git a/tests-clar/resources/renames/sixserving.txt b/tests-clar/resources/renames/sixserving.txt deleted file mode 100644 index f90d4fc20..000000000 --- a/tests-clar/resources/renames/sixserving.txt +++ /dev/null @@ -1,25 +0,0 @@ -I KEEP six honest serving-men - (They taught me all I knew); -Their names are What and Why and When - And How and Where and Who. -I send them over land and sea, - I send them east and west; -But after they have worked for me, - I give them all a rest. - -I let them rest from nine till five, - For I am busy then, -As well as breakfast, lunch, and tea, - For they are hungry men. -But different folk have different views; -I know a person small— -She keeps ten million serving-men, -Who get no rest at all! - -She sends'em abroad on her own affairs, - From the second she opens her eyes— -One million Hows, two million Wheres, -And seven million Whys! - - -- Rudyard Kipling - diff --git a/tests-clar/resources/renames/songof7cities.txt b/tests-clar/resources/renames/songof7cities.txt deleted file mode 100644 index 4210ffd5c..000000000 --- a/tests-clar/resources/renames/songof7cities.txt +++ /dev/null @@ -1,49 +0,0 @@ -The Song of Seven Cities ------------------------- - -I WAS Lord of Cities very sumptuously builded. -Seven roaring Cities paid me tribute from afar. -Ivory their outposts were--the guardrooms of them gilded, -And garrisoned with Amazons invincible in war. - -All the world went softly when it walked before my Cities-- -Neither King nor Army vexed my peoples at their toil, -Never horse nor chariot irked or overbore my Cities, -Never Mob nor Ruler questioned whence they drew their spoil. - -Banded, mailed and arrogant from sunrise unto sunset; -Singing while they sacked it, they possessed the land at large. -Yet when men would rob them, they resisted, they made onset -And pierced the smoke of battle with a thousand-sabred charge. - -So they warred and trafficked only yesterday, my Cities. -To-day there is no mark or mound of where my Cities stood. -For the River rose at midnight and it washed away my Cities. -They are evened with Atlantis and the towns before the Flood. - -Rain on rain-gorged channels raised the water-levels round them, -Freshet backed on freshet swelled and swept their world from sight, -Till the emboldened floods linked arms and, flashing forward, drowned them-- -Drowned my Seven Cities and their peoples in one night! - -Low among the alders lie their derelict foundations, -The beams wherein they trusted and the plinths whereon they built-- -My rulers and their treasure and their unborn populations, -Dead, destroyed, aborted, and defiled with mud and silt! - -The Daughters of the Palace whom they cherished in my Cities, -My silver-tongued Princesses, and the promise of their May-- -Their bridegrooms of the June-tide--all have perished in my Cities, -With the harsh envenomed virgins that can neither love nor play. - -I was Lord of Cities--I will build anew my Cities, -Seven, set on rocks, above the wrath of any flood. -Nor will I rest from search till I have filled anew my Cities -With peoples undefeated of the dark, enduring blood. - -To the sound of trumpets shall their seed restore my Cities -Wealthy and well-weaponed, that once more may I behold -All the world go softly when it walks before my Cities, -And the horses and the chariots fleeing from them as of old! - - -- Rudyard Kipling diff --git a/tests-clar/resources/renames/untimely.txt b/tests-clar/resources/renames/untimely.txt deleted file mode 100644 index 9a69d960a..000000000 --- a/tests-clar/resources/renames/untimely.txt +++ /dev/null @@ -1,24 +0,0 @@ -Untimely -======== - -Nothing in life has been made by man for man's using -But it was shown long since to man in ages -Lost as the name of the maker of it, -Who received oppression and shame for his wages-- -Hate, avoidance, and scorn in his daily dealings-- -Until he perished, wholly confounded - -More to be pitied than he are the wise -Souls which foresaw the evil of loosing -Knowledge or Art before time, and aborted -Noble devices and deep-wrought healings, -Lest offense should arise. - -Heaven delivers on earth the Hour that cannot be - thwarted, -Neither advanced, at the price of a world nor a soul, - and its Prophet -Comes through the blood of the vanguards who - dreamed--too soon--it had sounded. - - -- Rudyard Kipling diff --git a/tests-clar/resources/shallow.git/HEAD b/tests-clar/resources/shallow.git/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/shallow.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/shallow.git/config b/tests-clar/resources/shallow.git/config deleted file mode 100644 index a88b74b69..000000000 --- a/tests-clar/resources/shallow.git/config +++ /dev/null @@ -1,8 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = true - ignorecase = true - precomposeunicode = false -[remote "origin"] - url = file://testrepo.git diff --git a/tests-clar/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.idx b/tests-clar/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.idx deleted file mode 100644 index bfc7d24ff..000000000 Binary files a/tests-clar/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.idx and /dev/null differ diff --git a/tests-clar/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.pack b/tests-clar/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.pack deleted file mode 100644 index ccc6932fc..000000000 Binary files a/tests-clar/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.pack and /dev/null differ diff --git a/tests-clar/resources/shallow.git/packed-refs b/tests-clar/resources/shallow.git/packed-refs deleted file mode 100644 index 97eed743b..000000000 --- a/tests-clar/resources/shallow.git/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -a65fedf39aefe402d3bb6e24df4d4f5fe4547750 refs/heads/master diff --git a/tests-clar/resources/shallow.git/refs/.gitkeep b/tests-clar/resources/shallow.git/refs/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/shallow.git/shallow b/tests-clar/resources/shallow.git/shallow deleted file mode 100644 index 9536ad89c..000000000 --- a/tests-clar/resources/shallow.git/shallow +++ /dev/null @@ -1 +0,0 @@ -be3563ae3f795b2b4353bcce3a527ad0a4f7f644 diff --git a/tests-clar/resources/short_tag.git/HEAD b/tests-clar/resources/short_tag.git/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/short_tag.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/short_tag.git/config b/tests-clar/resources/short_tag.git/config deleted file mode 100644 index a4ef456cb..000000000 --- a/tests-clar/resources/short_tag.git/config +++ /dev/null @@ -1,5 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = true - logallrefupdates = true diff --git a/tests-clar/resources/short_tag.git/index b/tests-clar/resources/short_tag.git/index deleted file mode 100644 index 87fef7847..000000000 Binary files a/tests-clar/resources/short_tag.git/index and /dev/null differ diff --git a/tests-clar/resources/short_tag.git/objects/4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c b/tests-clar/resources/short_tag.git/objects/4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c deleted file mode 100644 index aeb4e4b0b..000000000 Binary files a/tests-clar/resources/short_tag.git/objects/4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c and /dev/null differ diff --git a/tests-clar/resources/short_tag.git/objects/4d/5fcadc293a348e88f777dc0920f11e7d71441c b/tests-clar/resources/short_tag.git/objects/4d/5fcadc293a348e88f777dc0920f11e7d71441c deleted file mode 100644 index 806ce71a5..000000000 Binary files a/tests-clar/resources/short_tag.git/objects/4d/5fcadc293a348e88f777dc0920f11e7d71441c and /dev/null differ diff --git a/tests-clar/resources/short_tag.git/objects/5d/a7760512a953e3c7c4e47e4392c7a4338fb729 b/tests-clar/resources/short_tag.git/objects/5d/a7760512a953e3c7c4e47e4392c7a4338fb729 deleted file mode 100644 index 1192707c9..000000000 --- a/tests-clar/resources/short_tag.git/objects/5d/a7760512a953e3c7c4e47e4392c7a4338fb729 +++ /dev/null @@ -1 +0,0 @@ -xM0@aלb. i%1ƍpc@--6&B E+pVСSƆd/m(RJ% R^vʩ,Giǖ <Ӵ3\ncinRSg u1 \ No newline at end of file diff --git a/tests-clar/resources/short_tag.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/tests-clar/resources/short_tag.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 deleted file mode 100644 index 711223894..000000000 Binary files a/tests-clar/resources/short_tag.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 and /dev/null differ diff --git a/tests-clar/resources/short_tag.git/packed-refs b/tests-clar/resources/short_tag.git/packed-refs deleted file mode 100644 index ca5197e3c..000000000 --- a/tests-clar/resources/short_tag.git/packed-refs +++ /dev/null @@ -1 +0,0 @@ -5da7760512a953e3c7c4e47e4392c7a4338fb729 refs/tags/no_description diff --git a/tests-clar/resources/short_tag.git/refs/heads/master b/tests-clar/resources/short_tag.git/refs/heads/master deleted file mode 100644 index fcefd1ef0..000000000 --- a/tests-clar/resources/short_tag.git/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -4a5ed60bafcf4638b7c8356bd4ce1916bfede93c diff --git a/tests-clar/resources/status/.gitted/COMMIT_EDITMSG b/tests-clar/resources/status/.gitted/COMMIT_EDITMSG deleted file mode 100644 index 1a25cd4a6..000000000 --- a/tests-clar/resources/status/.gitted/COMMIT_EDITMSG +++ /dev/null @@ -1 +0,0 @@ -Add a file which name should appear before the "subdir/" folder while being dealt with by the treewalker diff --git a/tests-clar/resources/status/.gitted/HEAD b/tests-clar/resources/status/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/status/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/status/.gitted/ORIG_HEAD b/tests-clar/resources/status/.gitted/ORIG_HEAD deleted file mode 100644 index b46871fd6..000000000 --- a/tests-clar/resources/status/.gitted/ORIG_HEAD +++ /dev/null @@ -1 +0,0 @@ -735b6a258cd196a8f7c9428419b02c1dca93fd75 diff --git a/tests-clar/resources/status/.gitted/config b/tests-clar/resources/status/.gitted/config deleted file mode 100644 index af107929f..000000000 --- a/tests-clar/resources/status/.gitted/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true diff --git a/tests-clar/resources/status/.gitted/description b/tests-clar/resources/status/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/status/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/status/.gitted/index b/tests-clar/resources/status/.gitted/index deleted file mode 100644 index 2af99a183..000000000 Binary files a/tests-clar/resources/status/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/info/exclude b/tests-clar/resources/status/.gitted/info/exclude deleted file mode 100644 index 0c4042a6a..000000000 --- a/tests-clar/resources/status/.gitted/info/exclude +++ /dev/null @@ -1,8 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ -ignored* - diff --git a/tests-clar/resources/status/.gitted/logs/HEAD b/tests-clar/resources/status/.gitted/logs/HEAD deleted file mode 100644 index 7b95b3cf1..000000000 --- a/tests-clar/resources/status/.gitted/logs/HEAD +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 0017bd4ab1ec30440b17bae1680cff124ab5f1f6 Jason Penny 1308050070 -0400 commit (initial): initial -0017bd4ab1ec30440b17bae1680cff124ab5f1f6 735b6a258cd196a8f7c9428419b02c1dca93fd75 Jason Penny 1308954538 -0400 commit: add subdir -735b6a258cd196a8f7c9428419b02c1dca93fd75 26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f nulltoken 1319911544 +0200 commit: Add a file which name should appear before the "subdir/" folder while being dealt with by the treewalker diff --git a/tests-clar/resources/status/.gitted/logs/refs/heads/master b/tests-clar/resources/status/.gitted/logs/refs/heads/master deleted file mode 100644 index 7b95b3cf1..000000000 --- a/tests-clar/resources/status/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,3 +0,0 @@ -0000000000000000000000000000000000000000 0017bd4ab1ec30440b17bae1680cff124ab5f1f6 Jason Penny 1308050070 -0400 commit (initial): initial -0017bd4ab1ec30440b17bae1680cff124ab5f1f6 735b6a258cd196a8f7c9428419b02c1dca93fd75 Jason Penny 1308954538 -0400 commit: add subdir -735b6a258cd196a8f7c9428419b02c1dca93fd75 26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f nulltoken 1319911544 +0200 commit: Add a file which name should appear before the "subdir/" folder while being dealt with by the treewalker diff --git a/tests-clar/resources/status/.gitted/objects/00/17bd4ab1ec30440b17bae1680cff124ab5f1f6 b/tests-clar/resources/status/.gitted/objects/00/17bd4ab1ec30440b17bae1680cff124ab5f1f6 deleted file mode 100644 index b256d95a3..000000000 --- a/tests-clar/resources/status/.gitted/objects/00/17bd4ab1ec30440b17bae1680cff124ab5f1f6 +++ /dev/null @@ -1,2 +0,0 @@ -xA E]sfh)1] -#STWpK^~9ܡ-"C'؅)Fvbv "wEk{nRί6#sO pD663WxV?9 \ No newline at end of file diff --git a/tests-clar/resources/status/.gitted/objects/06/1d42a44cacde5726057b67558821d95db96f19 b/tests-clar/resources/status/.gitted/objects/06/1d42a44cacde5726057b67558821d95db96f19 deleted file mode 100644 index 82e02cb0e..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/06/1d42a44cacde5726057b67558821d95db96f19 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/18/88c805345ba265b0ee9449b8877b6064592058 b/tests-clar/resources/status/.gitted/objects/18/88c805345ba265b0ee9449b8877b6064592058 deleted file mode 100644 index e3cad2f02..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/18/88c805345ba265b0ee9449b8877b6064592058 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/19/d9cc8584ac2c7dcf57d2680375e80f099dc481 b/tests-clar/resources/status/.gitted/objects/19/d9cc8584ac2c7dcf57d2680375e80f099dc481 deleted file mode 100644 index 2d5e711b9..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/19/d9cc8584ac2c7dcf57d2680375e80f099dc481 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f b/tests-clar/resources/status/.gitted/objects/26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f deleted file mode 100644 index f7dddc4ff..000000000 --- a/tests-clar/resources/status/.gitted/objects/26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f +++ /dev/null @@ -1,2 +0,0 @@ -xMn )V (̀BD޾LЍRȷވ@,9̜tNj6f`M6Z;h Zp ڙY,37/;42x&gϟۉIm|j \ No newline at end of file diff --git a/tests-clar/resources/status/.gitted/objects/32/504b727382542f9f089e24fddac5e78533e96c b/tests-clar/resources/status/.gitted/objects/32/504b727382542f9f089e24fddac5e78533e96c deleted file mode 100644 index 7fca67be8..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/32/504b727382542f9f089e24fddac5e78533e96c and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0 b/tests-clar/resources/status/.gitted/objects/37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0 deleted file mode 100644 index b75481b51..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/45/2e4244b5d083ddf0460acf1ecc74db9dcfa11a b/tests-clar/resources/status/.gitted/objects/45/2e4244b5d083ddf0460acf1ecc74db9dcfa11a deleted file mode 100644 index 5b47461e9..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/45/2e4244b5d083ddf0460acf1ecc74db9dcfa11a and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/52/9a16e8e762d4acb7b9636ff540a00831f9155a b/tests-clar/resources/status/.gitted/objects/52/9a16e8e762d4acb7b9636ff540a00831f9155a deleted file mode 100644 index 615009ad0..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/52/9a16e8e762d4acb7b9636ff540a00831f9155a and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/53/ace0d1cc1145a5f4fe4f78a186a60263190733 b/tests-clar/resources/status/.gitted/objects/53/ace0d1cc1145a5f4fe4f78a186a60263190733 deleted file mode 100644 index cdb7e961a..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/53/ace0d1cc1145a5f4fe4f78a186a60263190733 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/54/52d32f1dd538eb0405e8a83cc185f79e25e80f b/tests-clar/resources/status/.gitted/objects/54/52d32f1dd538eb0405e8a83cc185f79e25e80f deleted file mode 100644 index a72dff646..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/54/52d32f1dd538eb0405e8a83cc185f79e25e80f and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/55/d316c9ba708999f1918e9677d01dfcae69c6b9 b/tests-clar/resources/status/.gitted/objects/55/d316c9ba708999f1918e9677d01dfcae69c6b9 deleted file mode 100644 index 72807f3d0..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/55/d316c9ba708999f1918e9677d01dfcae69c6b9 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/70/bd9443ada07063e7fbf0b3ff5c13f7494d89c2 b/tests-clar/resources/status/.gitted/objects/70/bd9443ada07063e7fbf0b3ff5c13f7494d89c2 deleted file mode 100644 index 3665a8f7c..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/70/bd9443ada07063e7fbf0b3ff5c13f7494d89c2 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/73/5b6a258cd196a8f7c9428419b02c1dca93fd75 b/tests-clar/resources/status/.gitted/objects/73/5b6a258cd196a8f7c9428419b02c1dca93fd75 deleted file mode 100644 index 08e6fd246..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/73/5b6a258cd196a8f7c9428419b02c1dca93fd75 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/75/6e27627e67bfbc048d01ece5819c6de733d7ea b/tests-clar/resources/status/.gitted/objects/75/6e27627e67bfbc048d01ece5819c6de733d7ea deleted file mode 100644 index 8f3fa89e5..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/75/6e27627e67bfbc048d01ece5819c6de733d7ea and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/90/6ee7711f4f4928ddcb2a5f8fbc500deba0d2a8 b/tests-clar/resources/status/.gitted/objects/90/6ee7711f4f4928ddcb2a5f8fbc500deba0d2a8 deleted file mode 100644 index bb732b08e..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/90/6ee7711f4f4928ddcb2a5f8fbc500deba0d2a8 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/90/b8c29d8ba39434d1c63e1b093daaa26e5bd972 b/tests-clar/resources/status/.gitted/objects/90/b8c29d8ba39434d1c63e1b093daaa26e5bd972 deleted file mode 100644 index 7a96618ff..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/90/b8c29d8ba39434d1c63e1b093daaa26e5bd972 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/9c/2e02cdffa8d73e6c189074594477a6baf87960 b/tests-clar/resources/status/.gitted/objects/9c/2e02cdffa8d73e6c189074594477a6baf87960 deleted file mode 100644 index 20a3c497e..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/9c/2e02cdffa8d73e6c189074594477a6baf87960 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/a0/de7e0ac200c489c41c59dfa910154a70264e6e b/tests-clar/resources/status/.gitted/objects/a0/de7e0ac200c489c41c59dfa910154a70264e6e deleted file mode 100644 index a1789c9a6..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/a0/de7e0ac200c489c41c59dfa910154a70264e6e and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/a6/191982709b746d5650e93c2acf34ef74e11504 b/tests-clar/resources/status/.gitted/objects/a6/191982709b746d5650e93c2acf34ef74e11504 deleted file mode 100644 index cc1f377b3..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/a6/191982709b746d5650e93c2acf34ef74e11504 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/a6/be623522ce87a1d862128ac42672604f7b468b b/tests-clar/resources/status/.gitted/objects/a6/be623522ce87a1d862128ac42672604f7b468b deleted file mode 100644 index c47298347..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/a6/be623522ce87a1d862128ac42672604f7b468b and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/aa/27a641456848200fdb7f7c99ba36f8a0952877 b/tests-clar/resources/status/.gitted/objects/aa/27a641456848200fdb7f7c99ba36f8a0952877 deleted file mode 100644 index a4669ccbb..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/aa/27a641456848200fdb7f7c99ba36f8a0952877 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/da/bc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 b/tests-clar/resources/status/.gitted/objects/da/bc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 deleted file mode 100644 index 3e3c03c96..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/da/bc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/e8/ee89e15bbe9b20137715232387b3de5b28972e b/tests-clar/resources/status/.gitted/objects/e8/ee89e15bbe9b20137715232387b3de5b28972e deleted file mode 100644 index cfc2413d5..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/e8/ee89e15bbe9b20137715232387b3de5b28972e and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/e9/b9107f290627c04d097733a10055af941f6bca b/tests-clar/resources/status/.gitted/objects/e9/b9107f290627c04d097733a10055af941f6bca deleted file mode 100644 index 1266d3eac..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/e9/b9107f290627c04d097733a10055af941f6bca and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/objects/ed/062903b8f6f3dccb2fa81117ba6590944ef9bd b/tests-clar/resources/status/.gitted/objects/ed/062903b8f6f3dccb2fa81117ba6590944ef9bd deleted file mode 100644 index 8fa8c1707..000000000 Binary files a/tests-clar/resources/status/.gitted/objects/ed/062903b8f6f3dccb2fa81117ba6590944ef9bd and /dev/null differ diff --git a/tests-clar/resources/status/.gitted/refs/heads/master b/tests-clar/resources/status/.gitted/refs/heads/master deleted file mode 100644 index 3e2e2a07a..000000000 --- a/tests-clar/resources/status/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f diff --git a/tests-clar/resources/status/current_file b/tests-clar/resources/status/current_file deleted file mode 100644 index a0de7e0ac..000000000 --- a/tests-clar/resources/status/current_file +++ /dev/null @@ -1 +0,0 @@ -current_file diff --git a/tests-clar/resources/status/ignored_file b/tests-clar/resources/status/ignored_file deleted file mode 100644 index 6a79f808a..000000000 --- a/tests-clar/resources/status/ignored_file +++ /dev/null @@ -1 +0,0 @@ -ignored_file diff --git a/tests-clar/resources/status/modified_file b/tests-clar/resources/status/modified_file deleted file mode 100644 index 0a5396305..000000000 --- a/tests-clar/resources/status/modified_file +++ /dev/null @@ -1,2 +0,0 @@ -modified_file -modified_file diff --git a/tests-clar/resources/status/new_file b/tests-clar/resources/status/new_file deleted file mode 100644 index d4fa8600b..000000000 --- a/tests-clar/resources/status/new_file +++ /dev/null @@ -1 +0,0 @@ -new_file diff --git a/tests-clar/resources/status/staged_changes b/tests-clar/resources/status/staged_changes deleted file mode 100644 index 55d316c9b..000000000 --- a/tests-clar/resources/status/staged_changes +++ /dev/null @@ -1,2 +0,0 @@ -staged_changes -staged_changes diff --git a/tests-clar/resources/status/staged_changes_modified_file b/tests-clar/resources/status/staged_changes_modified_file deleted file mode 100644 index 011c3440d..000000000 --- a/tests-clar/resources/status/staged_changes_modified_file +++ /dev/null @@ -1,3 +0,0 @@ -staged_changes_modified_file -staged_changes_modified_file -staged_changes_modified_file diff --git a/tests-clar/resources/status/staged_delete_modified_file b/tests-clar/resources/status/staged_delete_modified_file deleted file mode 100644 index dabc8af9b..000000000 --- a/tests-clar/resources/status/staged_delete_modified_file +++ /dev/null @@ -1 +0,0 @@ -staged_delete_modified_file diff --git a/tests-clar/resources/status/staged_new_file b/tests-clar/resources/status/staged_new_file deleted file mode 100644 index 529a16e8e..000000000 --- a/tests-clar/resources/status/staged_new_file +++ /dev/null @@ -1 +0,0 @@ -staged_new_file diff --git a/tests-clar/resources/status/staged_new_file_modified_file b/tests-clar/resources/status/staged_new_file_modified_file deleted file mode 100644 index 8b090c06d..000000000 --- a/tests-clar/resources/status/staged_new_file_modified_file +++ /dev/null @@ -1,2 +0,0 @@ -staged_new_file_modified_file -staged_new_file_modified_file diff --git a/tests-clar/resources/status/subdir.txt b/tests-clar/resources/status/subdir.txt deleted file mode 100644 index e8ee89e15..000000000 --- a/tests-clar/resources/status/subdir.txt +++ /dev/null @@ -1,2 +0,0 @@ -Is it a bird? -Is it a plane? diff --git a/tests-clar/resources/status/subdir/current_file b/tests-clar/resources/status/subdir/current_file deleted file mode 100644 index 53ace0d1c..000000000 --- a/tests-clar/resources/status/subdir/current_file +++ /dev/null @@ -1 +0,0 @@ -subdir/current_file diff --git a/tests-clar/resources/status/subdir/modified_file b/tests-clar/resources/status/subdir/modified_file deleted file mode 100644 index 57274b75e..000000000 --- a/tests-clar/resources/status/subdir/modified_file +++ /dev/null @@ -1,2 +0,0 @@ -subdir/modified_file -subdir/modified_file diff --git a/tests-clar/resources/status/subdir/new_file b/tests-clar/resources/status/subdir/new_file deleted file mode 100644 index 80a86a693..000000000 --- a/tests-clar/resources/status/subdir/new_file +++ /dev/null @@ -1 +0,0 @@ -subdir/new_file diff --git "a/tests-clar/resources/status/\350\277\231" "b/tests-clar/resources/status/\350\277\231" deleted file mode 100644 index f0ff9a197..000000000 --- "a/tests-clar/resources/status/\350\277\231" +++ /dev/null @@ -1 +0,0 @@ -This diff --git a/tests-clar/resources/submod2/.gitted/HEAD b/tests-clar/resources/submod2/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/submod2/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/config b/tests-clar/resources/submod2/.gitted/config deleted file mode 100644 index abc420734..000000000 --- a/tests-clar/resources/submod2/.gitted/config +++ /dev/null @@ -1,20 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true -[submodule "sm_missing_commits"] - url = ../submod2_target -[submodule "sm_unchanged"] - url = ../submod2_target -[submodule "sm_changed_file"] - url = ../submod2_target -[submodule "sm_changed_index"] - url = ../submod2_target -[submodule "sm_changed_head"] - url = ../submod2_target -[submodule "sm_changed_untracked_file"] - url = ../submod2_target -[submodule "sm_added_and_uncommited"] - url = ../submod2_target diff --git a/tests-clar/resources/submod2/.gitted/description b/tests-clar/resources/submod2/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/submod2/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/submod2/.gitted/index b/tests-clar/resources/submod2/.gitted/index deleted file mode 100644 index 0c17e8629..000000000 Binary files a/tests-clar/resources/submod2/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/info/exclude b/tests-clar/resources/submod2/.gitted/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/submod2/.gitted/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/submod2/.gitted/logs/HEAD b/tests-clar/resources/submod2/.gitted/logs/HEAD deleted file mode 100644 index 2cf2ca74d..000000000 --- a/tests-clar/resources/submod2/.gitted/logs/HEAD +++ /dev/null @@ -1,4 +0,0 @@ -0000000000000000000000000000000000000000 14fe9ccf104058df25e0a08361c4494e167ef243 Russell Belfer 1342559771 -0700 commit (initial): Initial commit -14fe9ccf104058df25e0a08361c4494e167ef243 a9104bf89e911387244ef499413960ba472066d9 Russell Belfer 1342559831 -0700 commit: Adding a submodule -a9104bf89e911387244ef499413960ba472066d9 5901da4f1c67756eeadc5121d206bec2431f253b Russell Belfer 1342560036 -0700 commit: Updating submodule -5901da4f1c67756eeadc5121d206bec2431f253b 7484482eb8db738cafa696993664607500a3f2b9 Russell Belfer 1342560288 -0700 commit: Adding a bunch more test content diff --git a/tests-clar/resources/submod2/.gitted/logs/refs/heads/master b/tests-clar/resources/submod2/.gitted/logs/refs/heads/master deleted file mode 100644 index 2cf2ca74d..000000000 --- a/tests-clar/resources/submod2/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,4 +0,0 @@ -0000000000000000000000000000000000000000 14fe9ccf104058df25e0a08361c4494e167ef243 Russell Belfer 1342559771 -0700 commit (initial): Initial commit -14fe9ccf104058df25e0a08361c4494e167ef243 a9104bf89e911387244ef499413960ba472066d9 Russell Belfer 1342559831 -0700 commit: Adding a submodule -a9104bf89e911387244ef499413960ba472066d9 5901da4f1c67756eeadc5121d206bec2431f253b Russell Belfer 1342560036 -0700 commit: Updating submodule -5901da4f1c67756eeadc5121d206bec2431f253b 7484482eb8db738cafa696993664607500a3f2b9 Russell Belfer 1342560288 -0700 commit: Adding a bunch more test content diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/config b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/config deleted file mode 100644 index 2d0583e99..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/config +++ /dev/null @@ -1,13 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - worktree = ../../../sm_added_and_uncommited - ignorecase = true -[remote "origin"] - fetch = +refs/heads/*:refs/remotes/origin/* - url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/description b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/index b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/index deleted file mode 100644 index 65140a510..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/index and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/info/exclude b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/HEAD deleted file mode 100644 index 53753e7dd..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560316 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/heads/master deleted file mode 100644 index 53753e7dd..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560316 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/remotes/origin/HEAD deleted file mode 100644 index 53753e7dd..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560316 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 deleted file mode 100644 index f4b7094c5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 deleted file mode 100644 index 56c845e49..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 deleted file mode 100644 index bd179b5f5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/41/bd4bc3df978de695f67ace64c560913da11653 deleted file mode 100644 index ccf49bd15..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/41/bd4bc3df978de695f67ace64c560913da11653 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 deleted file mode 100644 index 53029069a..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/5e/4963595a9774b90524d35a807169049de8ccad deleted file mode 100644 index 38c791eba..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/5e/4963595a9774b90524d35a807169049de8ccad and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/6b/31c659545507c381e9cd34ec508f16c04e149e deleted file mode 100644 index a26d29993..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/6b/31c659545507c381e9cd34ec508f16c04e149e +++ /dev/null @@ -1,2 +0,0 @@ -xQ -!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/73/ba924a80437097795ae839e66e187c55d3babf deleted file mode 100644 index 83d1ba481..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/73/ba924a80437097795ae839e66e187c55d3babf and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a deleted file mode 100644 index 6d27af8a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a +++ /dev/null @@ -1,2 +0,0 @@ -x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x -uxt(+ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/9efbdadaa4a582778d4584385495559ea0994b deleted file mode 100644 index 17458840b..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/9efbdadaa4a582778d4584385495559ea0994b +++ /dev/null @@ -1,2 +0,0 @@ -x 0 )?= NlOkj8&r -qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e deleted file mode 100644 index 83cc29fb1..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 deleted file mode 100644 index 55bda40ef..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/packed-refs b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/packed-refs deleted file mode 100644 index 5a4ebc47c..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/heads/master deleted file mode 100644 index e12c44d7a..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/remotes/origin/HEAD deleted file mode 100644 index 6efe28fff..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/config b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/config deleted file mode 100644 index 10cc2508e..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/config +++ /dev/null @@ -1,13 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - worktree = ../../../sm_changed_file - ignorecase = true -[remote "origin"] - fetch = +refs/heads/*:refs/remotes/origin/* - url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/description b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/index b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/index deleted file mode 100644 index 6914a3b6e..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/index and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/info/exclude b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/logs/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/logs/HEAD deleted file mode 100644 index e5cb63f8d..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560173 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/heads/master deleted file mode 100644 index e5cb63f8d..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560173 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/remotes/origin/HEAD deleted file mode 100644 index e5cb63f8d..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560173 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 deleted file mode 100644 index f4b7094c5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 deleted file mode 100644 index 56c845e49..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 deleted file mode 100644 index bd179b5f5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 deleted file mode 100644 index ccf49bd15..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 deleted file mode 100644 index 53029069a..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/5e/4963595a9774b90524d35a807169049de8ccad deleted file mode 100644 index 38c791eba..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/5e/4963595a9774b90524d35a807169049de8ccad and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e deleted file mode 100644 index a26d29993..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e +++ /dev/null @@ -1,2 +0,0 @@ -xQ -!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/73/ba924a80437097795ae839e66e187c55d3babf deleted file mode 100644 index 83d1ba481..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/73/ba924a80437097795ae839e66e187c55d3babf and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a deleted file mode 100644 index 6d27af8a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a +++ /dev/null @@ -1,2 +0,0 @@ -x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x -uxt(+ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b deleted file mode 100644 index 17458840b..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b +++ /dev/null @@ -1,2 +0,0 @@ -x 0 )?= NlOkj8&r -qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e deleted file mode 100644 index 83cc29fb1..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 deleted file mode 100644 index 55bda40ef..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/packed-refs b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/packed-refs deleted file mode 100644 index 5a4ebc47c..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/refs/heads/master deleted file mode 100644 index e12c44d7a..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/refs/remotes/origin/HEAD deleted file mode 100644 index 6efe28fff..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_file/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/COMMIT_EDITMSG b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/COMMIT_EDITMSG deleted file mode 100644 index 6b8d1e3fc..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/COMMIT_EDITMSG +++ /dev/null @@ -1 +0,0 @@ -Making a change in a submodule diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/config b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/config deleted file mode 100644 index 7d002536a..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/config +++ /dev/null @@ -1,13 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - worktree = ../../../sm_changed_head - ignorecase = true -[remote "origin"] - fetch = +refs/heads/*:refs/remotes/origin/* - url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/description b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/index b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/index deleted file mode 100644 index 728fa292f..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/index and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/info/exclude b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/logs/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/logs/HEAD deleted file mode 100644 index cabdeb2b5..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/logs/HEAD +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560179 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target -480095882d281ed676fe5b863569520e54a7d5c0 3d9386c507f6b093471a3e324085657a3c2b4247 Russell Belfer 1342560431 -0700 commit: Making a change in a submodule diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/heads/master deleted file mode 100644 index cabdeb2b5..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/heads/master +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560179 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target -480095882d281ed676fe5b863569520e54a7d5c0 3d9386c507f6b093471a3e324085657a3c2b4247 Russell Belfer 1342560431 -0700 commit: Making a change in a submodule diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/remotes/origin/HEAD deleted file mode 100644 index 257ca21d1..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560179 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 deleted file mode 100644 index f4b7094c5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 deleted file mode 100644 index 56c845e49..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 deleted file mode 100644 index bd179b5f5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/3d/9386c507f6b093471a3e324085657a3c2b4247 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/3d/9386c507f6b093471a3e324085657a3c2b4247 deleted file mode 100644 index a2c371642..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/3d/9386c507f6b093471a3e324085657a3c2b4247 +++ /dev/null @@ -1,3 +0,0 @@ -xKj!E3vj#<<@Ouq .)ql osFa#v )g#{':Tl`b40 ;fr4 - -zU-/glm\'LjrhXG_+l ʚE`;=]J \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/41/bd4bc3df978de695f67ace64c560913da11653 deleted file mode 100644 index ccf49bd15..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/41/bd4bc3df978de695f67ace64c560913da11653 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 deleted file mode 100644 index 53029069a..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/5e/4963595a9774b90524d35a807169049de8ccad deleted file mode 100644 index 38c791eba..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/5e/4963595a9774b90524d35a807169049de8ccad and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/6b/31c659545507c381e9cd34ec508f16c04e149e deleted file mode 100644 index a26d29993..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/6b/31c659545507c381e9cd34ec508f16c04e149e +++ /dev/null @@ -1,2 +0,0 @@ -xQ -!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/73/ba924a80437097795ae839e66e187c55d3babf deleted file mode 100644 index 83d1ba481..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/73/ba924a80437097795ae839e66e187c55d3babf and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/77/fb0ed3e58568d6ad362c78de08ab8649d76e29 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/77/fb0ed3e58568d6ad362c78de08ab8649d76e29 deleted file mode 100644 index f8a236f3d..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/77/fb0ed3e58568d6ad362c78de08ab8649d76e29 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a deleted file mode 100644 index 6d27af8a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a +++ /dev/null @@ -1,2 +0,0 @@ -x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x -uxt(+ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/78/9efbdadaa4a582778d4584385495559ea0994b deleted file mode 100644 index 17458840b..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/78/9efbdadaa4a582778d4584385495559ea0994b +++ /dev/null @@ -1,2 +0,0 @@ -x 0 )?= NlOkj8&r -qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e deleted file mode 100644 index 83cc29fb1..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/8e/b1e637ed9fc8e5454fa20d38f809091f9395f4 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/8e/b1e637ed9fc8e5454fa20d38f809091f9395f4 deleted file mode 100644 index 8155b3e87..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/8e/b1e637ed9fc8e5454fa20d38f809091f9395f4 +++ /dev/null @@ -1,2 +0,0 @@ -xMM; -1) ZPr3k lEnl!crz ,e +lEZxuPYx QC*fuLcfR3T0'үj~G^s1b2zVk]5<v'> \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 deleted file mode 100644 index 55bda40ef..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/packed-refs b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/packed-refs deleted file mode 100644 index 5a4ebc47c..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/refs/heads/master deleted file mode 100644 index ae079bd79..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -3d9386c507f6b093471a3e324085657a3c2b4247 diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/refs/remotes/origin/HEAD deleted file mode 100644 index 6efe28fff..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_head/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/config b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/config deleted file mode 100644 index 0274ff7e3..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/config +++ /dev/null @@ -1,13 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - worktree = ../../../sm_changed_index - ignorecase = true -[remote "origin"] - fetch = +refs/heads/*:refs/remotes/origin/* - url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/description b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/index b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/index deleted file mode 100644 index 6fad3b43e..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/index and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/info/exclude b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/logs/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/logs/HEAD deleted file mode 100644 index 80eb54102..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560175 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/heads/master deleted file mode 100644 index 80eb54102..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560175 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/remotes/origin/HEAD deleted file mode 100644 index 80eb54102..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560175 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 deleted file mode 100644 index f4b7094c5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 deleted file mode 100644 index 56c845e49..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 deleted file mode 100644 index bd179b5f5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/41/bd4bc3df978de695f67ace64c560913da11653 deleted file mode 100644 index ccf49bd15..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/41/bd4bc3df978de695f67ace64c560913da11653 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 deleted file mode 100644 index 53029069a..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/5e/4963595a9774b90524d35a807169049de8ccad deleted file mode 100644 index 38c791eba..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/5e/4963595a9774b90524d35a807169049de8ccad and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/6b/31c659545507c381e9cd34ec508f16c04e149e deleted file mode 100644 index a26d29993..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/6b/31c659545507c381e9cd34ec508f16c04e149e +++ /dev/null @@ -1,2 +0,0 @@ -xQ -!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/73/ba924a80437097795ae839e66e187c55d3babf deleted file mode 100644 index 83d1ba481..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/73/ba924a80437097795ae839e66e187c55d3babf and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a deleted file mode 100644 index 6d27af8a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a +++ /dev/null @@ -1,2 +0,0 @@ -x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x -uxt(+ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/78/9efbdadaa4a582778d4584385495559ea0994b deleted file mode 100644 index 17458840b..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/78/9efbdadaa4a582778d4584385495559ea0994b +++ /dev/null @@ -1,2 +0,0 @@ -x 0 )?= NlOkj8&r -qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e deleted file mode 100644 index 83cc29fb1..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/a0/2d31770687965547ab7a04cee199b29ee458d6 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/a0/2d31770687965547ab7a04cee199b29ee458d6 deleted file mode 100644 index cb3f5a002..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/a0/2d31770687965547ab7a04cee199b29ee458d6 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 deleted file mode 100644 index 55bda40ef..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/packed-refs b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/packed-refs deleted file mode 100644 index 5a4ebc47c..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/refs/heads/master deleted file mode 100644 index e12c44d7a..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/refs/remotes/origin/HEAD deleted file mode 100644 index 6efe28fff..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_index/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/config b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/config deleted file mode 100644 index 7f2584476..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/config +++ /dev/null @@ -1,13 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - worktree = ../../../sm_changed_untracked_file - ignorecase = true -[remote "origin"] - fetch = +refs/heads/*:refs/remotes/origin/* - url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/description b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/index b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/index deleted file mode 100644 index 598e30a32..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/index and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/info/exclude b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/HEAD deleted file mode 100644 index d1beafbd6..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560186 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/heads/master deleted file mode 100644 index d1beafbd6..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560186 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/remotes/origin/HEAD deleted file mode 100644 index d1beafbd6..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560186 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 deleted file mode 100644 index f4b7094c5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 deleted file mode 100644 index 56c845e49..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 deleted file mode 100644 index bd179b5f5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 deleted file mode 100644 index ccf49bd15..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 deleted file mode 100644 index 53029069a..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/5e/4963595a9774b90524d35a807169049de8ccad deleted file mode 100644 index 38c791eba..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/5e/4963595a9774b90524d35a807169049de8ccad and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e deleted file mode 100644 index a26d29993..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e +++ /dev/null @@ -1,2 +0,0 @@ -xQ -!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/73/ba924a80437097795ae839e66e187c55d3babf deleted file mode 100644 index 83d1ba481..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/73/ba924a80437097795ae839e66e187c55d3babf and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a deleted file mode 100644 index 6d27af8a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a +++ /dev/null @@ -1,2 +0,0 @@ -x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x -uxt(+ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b deleted file mode 100644 index 17458840b..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b +++ /dev/null @@ -1,2 +0,0 @@ -x 0 )?= NlOkj8&r -qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e deleted file mode 100644 index 83cc29fb1..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 deleted file mode 100644 index 55bda40ef..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/packed-refs b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/packed-refs deleted file mode 100644 index 5a4ebc47c..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/heads/master deleted file mode 100644 index e12c44d7a..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/remotes/origin/HEAD deleted file mode 100644 index 6efe28fff..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/config b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/config deleted file mode 100644 index 45fbb30cf..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/config +++ /dev/null @@ -1,13 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - worktree = ../../../sm_missing_commits - ignorecase = true -[remote "origin"] - fetch = +refs/heads/*:refs/remotes/origin/* - url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/description b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/index b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/index deleted file mode 100644 index 490356524..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/index and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/info/exclude b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/logs/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/logs/HEAD deleted file mode 100644 index ee08c9706..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 5e4963595a9774b90524d35a807169049de8ccad Russell Belfer 1342559796 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/heads/master deleted file mode 100644 index ee08c9706..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 5e4963595a9774b90524d35a807169049de8ccad Russell Belfer 1342559796 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/remotes/origin/HEAD deleted file mode 100644 index ee08c9706..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 5e4963595a9774b90524d35a807169049de8ccad Russell Belfer 1342559796 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 deleted file mode 100644 index f4b7094c5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 deleted file mode 100644 index 56c845e49..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 deleted file mode 100644 index bd179b5f5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/41/bd4bc3df978de695f67ace64c560913da11653 deleted file mode 100644 index ccf49bd15..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/41/bd4bc3df978de695f67ace64c560913da11653 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/5e/4963595a9774b90524d35a807169049de8ccad deleted file mode 100644 index 38c791eba..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/5e/4963595a9774b90524d35a807169049de8ccad and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/6b/31c659545507c381e9cd34ec508f16c04e149e deleted file mode 100644 index a26d29993..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/6b/31c659545507c381e9cd34ec508f16c04e149e +++ /dev/null @@ -1,2 +0,0 @@ -xQ -!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a deleted file mode 100644 index 6d27af8a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a +++ /dev/null @@ -1,2 +0,0 @@ -x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x -uxt(+ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e deleted file mode 100644 index 83cc29fb1..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 deleted file mode 100644 index 55bda40ef..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/packed-refs b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/packed-refs deleted file mode 100644 index 66fbf5daf..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -5e4963595a9774b90524d35a807169049de8ccad refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/refs/heads/master deleted file mode 100644 index 3913aca5d..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -5e4963595a9774b90524d35a807169049de8ccad diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/refs/remotes/origin/HEAD deleted file mode 100644 index 6efe28fff..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_missing_commits/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/config b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/config deleted file mode 100644 index fc706c9dd..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/config +++ /dev/null @@ -1,13 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - worktree = ../../../sm_unchanged - ignorecase = true -[remote "origin"] - fetch = +refs/heads/*:refs/remotes/origin/* - url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/description b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/index b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/index deleted file mode 100644 index 629c849ec..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/index and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/info/exclude b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/logs/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/logs/HEAD deleted file mode 100644 index 72653286a..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560169 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/heads/master deleted file mode 100644 index 72653286a..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560169 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/remotes/origin/HEAD deleted file mode 100644 index 72653286a..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560169 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 deleted file mode 100644 index f4b7094c5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 deleted file mode 100644 index 56c845e49..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 deleted file mode 100644 index bd179b5f5..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/41/bd4bc3df978de695f67ace64c560913da11653 deleted file mode 100644 index ccf49bd15..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/41/bd4bc3df978de695f67ace64c560913da11653 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 deleted file mode 100644 index 53029069a..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/5e/4963595a9774b90524d35a807169049de8ccad deleted file mode 100644 index 38c791eba..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/5e/4963595a9774b90524d35a807169049de8ccad and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/6b/31c659545507c381e9cd34ec508f16c04e149e deleted file mode 100644 index a26d29993..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/6b/31c659545507c381e9cd34ec508f16c04e149e +++ /dev/null @@ -1,2 +0,0 @@ -xQ -!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/73/ba924a80437097795ae839e66e187c55d3babf deleted file mode 100644 index 83d1ba481..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/73/ba924a80437097795ae839e66e187c55d3babf and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a deleted file mode 100644 index 6d27af8a8..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a +++ /dev/null @@ -1,2 +0,0 @@ -x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x -uxt(+ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/78/9efbdadaa4a582778d4584385495559ea0994b deleted file mode 100644 index 17458840b..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/78/9efbdadaa4a582778d4584385495559ea0994b +++ /dev/null @@ -1,2 +0,0 @@ -x 0 )?= NlOkj8&r -qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e deleted file mode 100644 index 83cc29fb1..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 deleted file mode 100644 index 55bda40ef..000000000 Binary files a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/packed-refs b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/packed-refs deleted file mode 100644 index 5a4ebc47c..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/refs/heads/master b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/refs/heads/master deleted file mode 100644 index e12c44d7a..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/refs/remotes/origin/HEAD b/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/refs/remotes/origin/HEAD deleted file mode 100644 index 6efe28fff..000000000 --- a/tests-clar/resources/submod2/.gitted/modules/sm_unchanged/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/remotes/origin/master diff --git a/tests-clar/resources/submod2/.gitted/objects/09/460e5b6cbcb05a3e404593c32a3aa7221eca0e b/tests-clar/resources/submod2/.gitted/objects/09/460e5b6cbcb05a3e404593c32a3aa7221eca0e deleted file mode 100644 index f1ea5f4c8..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/09/460e5b6cbcb05a3e404593c32a3aa7221eca0e and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/14/fe9ccf104058df25e0a08361c4494e167ef243 b/tests-clar/resources/submod2/.gitted/objects/14/fe9ccf104058df25e0a08361c4494e167ef243 deleted file mode 100644 index d3c8582e3..000000000 --- a/tests-clar/resources/submod2/.gitted/objects/14/fe9ccf104058df25e0a08361c4494e167ef243 +++ /dev/null @@ -1 +0,0 @@ -xM F]sfhcc;ހ@I(_O{s%@> ^!F'!諲l_q4E޶RݏS'n>>m^\w^$X_迦xE_.9} \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/objects/22/ce3e0311dda73a5992d54a4a595518d3876ea7 b/tests-clar/resources/submod2/.gitted/objects/22/ce3e0311dda73a5992d54a4a595518d3876ea7 deleted file mode 100644 index fce6a94b5..000000000 --- a/tests-clar/resources/submod2/.gitted/objects/22/ce3e0311dda73a5992d54a4a595518d3876ea7 +++ /dev/null @@ -1,4 +0,0 @@ -x -0Eݶ_Q. -. W"!1 !3 >+.9=3W(n-:;j[" W{ޕQZW,2 iviyh T/={ !@b(bJcSPrŌ -{`|%imp콡=IÿW26B@)|)g \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/objects/25/5546424b0efb847b1bfc91dbf7348b277f8970 b/tests-clar/resources/submod2/.gitted/objects/25/5546424b0efb847b1bfc91dbf7348b277f8970 deleted file mode 100644 index 2965becf6..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/25/5546424b0efb847b1bfc91dbf7348b277f8970 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/2a/30f1e6f94b20917005a21273f65b406d0f8bad b/tests-clar/resources/submod2/.gitted/objects/2a/30f1e6f94b20917005a21273f65b406d0f8bad deleted file mode 100644 index 08faf0fa8..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/2a/30f1e6f94b20917005a21273f65b406d0f8bad and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/42/cfb95cd01bf9225b659b5ee3edcc78e8eeb478 b/tests-clar/resources/submod2/.gitted/objects/42/cfb95cd01bf9225b659b5ee3edcc78e8eeb478 deleted file mode 100644 index ee7848ae6..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/42/cfb95cd01bf9225b659b5ee3edcc78e8eeb478 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/57/958699c2dc394f81cfc76950e9c3ac3025c398 b/tests-clar/resources/submod2/.gitted/objects/57/958699c2dc394f81cfc76950e9c3ac3025c398 deleted file mode 100644 index ca9203a6e..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/57/958699c2dc394f81cfc76950e9c3ac3025c398 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/59/01da4f1c67756eeadc5121d206bec2431f253b b/tests-clar/resources/submod2/.gitted/objects/59/01da4f1c67756eeadc5121d206bec2431f253b deleted file mode 100644 index 9f88f6bdf..000000000 --- a/tests-clar/resources/submod2/.gitted/objects/59/01da4f1c67756eeadc5121d206bec2431f253b +++ /dev/null @@ -1,2 +0,0 @@ -x 1ENӀ2yg@D,A$;YE6m{΁e(/2d#jȚL 2Yd:fʞ =V^DhR $^a+tn {n8xs -Ծ=<@jCŹک[>6#=-g?,F \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/objects/60/7d96653d4d0a4f733107f7890c2e67b55b620d b/tests-clar/resources/submod2/.gitted/objects/60/7d96653d4d0a4f733107f7890c2e67b55b620d deleted file mode 100644 index 30bee40e9..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/60/7d96653d4d0a4f733107f7890c2e67b55b620d and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/74/84482eb8db738cafa696993664607500a3f2b9 b/tests-clar/resources/submod2/.gitted/objects/74/84482eb8db738cafa696993664607500a3f2b9 deleted file mode 100644 index 79018042d..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/74/84482eb8db738cafa696993664607500a3f2b9 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/7b/a4c5c3561daa5ab1a86215cfb0587e96d404d6 b/tests-clar/resources/submod2/.gitted/objects/7b/a4c5c3561daa5ab1a86215cfb0587e96d404d6 deleted file mode 100644 index cde89e5bb..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/7b/a4c5c3561daa5ab1a86215cfb0587e96d404d6 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/87/3585b94bdeabccea991ea5e3ec1a277895b698 b/tests-clar/resources/submod2/.gitted/objects/87/3585b94bdeabccea991ea5e3ec1a277895b698 deleted file mode 100644 index 41af98aa9..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/87/3585b94bdeabccea991ea5e3ec1a277895b698 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/97/4cf7c73de336b0c4e019f918f3cee367d72e84 b/tests-clar/resources/submod2/.gitted/objects/97/4cf7c73de336b0c4e019f918f3cee367d72e84 deleted file mode 100644 index 160f1caf4..000000000 --- a/tests-clar/resources/submod2/.gitted/objects/97/4cf7c73de336b0c4e019f918f3cee367d72e84 +++ /dev/null @@ -1,2 +0,0 @@ -x -0Eݶ_Bqg yi IYUp!΁s|R7=)XCAG:25:<-uU_IY\Ϥ%AF f{G qTPsu(Z{RA #̉0mŲ.8b?{vʌ \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/objects/9d/bc299bc013ea253583b40bf327b5a6e4037b89 b/tests-clar/resources/submod2/.gitted/objects/9d/bc299bc013ea253583b40bf327b5a6e4037b89 deleted file mode 100644 index 1ee52218d..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/9d/bc299bc013ea253583b40bf327b5a6e4037b89 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/a9/104bf89e911387244ef499413960ba472066d9 b/tests-clar/resources/submod2/.gitted/objects/a9/104bf89e911387244ef499413960ba472066d9 deleted file mode 100644 index 2239e14a8..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/a9/104bf89e911387244ef499413960ba472066d9 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/b6/14088620bbdc1d29549d223ceba0f4419fd4cb b/tests-clar/resources/submod2/.gitted/objects/b6/14088620bbdc1d29549d223ceba0f4419fd4cb deleted file mode 100644 index a03ea66e4..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/b6/14088620bbdc1d29549d223ceba0f4419fd4cb and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/d4/07f19e50c1da1ff584beafe0d6dac7237c5d06 b/tests-clar/resources/submod2/.gitted/objects/d4/07f19e50c1da1ff584beafe0d6dac7237c5d06 deleted file mode 100644 index 292303eb9..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/d4/07f19e50c1da1ff584beafe0d6dac7237c5d06 and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/d9/3e95571d92cceb5de28c205f1d5f3cc8b88bc8 b/tests-clar/resources/submod2/.gitted/objects/d9/3e95571d92cceb5de28c205f1d5f3cc8b88bc8 deleted file mode 100644 index b92c7eebd..000000000 --- a/tests-clar/resources/submod2/.gitted/objects/d9/3e95571d92cceb5de28c205f1d5f3cc8b88bc8 +++ /dev/null @@ -1,2 +0,0 @@ -x -!nק} ".zuRCx}Αہt .׫6,is&%9S#IW=aߐf2ABYsНa{c^K3gwM͠Fߥ4s'NI \ No newline at end of file diff --git a/tests-clar/resources/submod2/.gitted/objects/e3/b83bf274ee065eee48734cf8c6dfaf5e81471c b/tests-clar/resources/submod2/.gitted/objects/e3/b83bf274ee065eee48734cf8c6dfaf5e81471c deleted file mode 100644 index 3c7750b12..000000000 Binary files a/tests-clar/resources/submod2/.gitted/objects/e3/b83bf274ee065eee48734cf8c6dfaf5e81471c and /dev/null differ diff --git a/tests-clar/resources/submod2/.gitted/objects/f5/4414c25e6d24fe39f5c3f128d7c8a17bc23833 b/tests-clar/resources/submod2/.gitted/objects/f5/4414c25e6d24fe39f5c3f128d7c8a17bc23833 deleted file mode 100644 index 219620b25..000000000 --- a/tests-clar/resources/submod2/.gitted/objects/f5/4414c25e6d24fe39f5c3f128d7c8a17bc23833 +++ /dev/null @@ -1,2 +0,0 @@ -xe -0aSbOz12 1342560358 -0700 commit (initial): Initial commit diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/logs/refs/heads/master b/tests-clar/resources/submod2/not-submodule/.gitted/logs/refs/heads/master deleted file mode 100644 index 1749e7dff..000000000 --- a/tests-clar/resources/submod2/not-submodule/.gitted/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 68e92c611b80ee1ed8f38314ff9577f0d15b2444 Russell Belfer 1342560358 -0700 commit (initial): Initial commit diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 b/tests-clar/resources/submod2/not-submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 deleted file mode 100644 index 8892531a7..000000000 Binary files a/tests-clar/resources/submod2/not-submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 and /dev/null differ diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 b/tests-clar/resources/submod2/not-submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 deleted file mode 100644 index c4e1a77d7..000000000 Binary files a/tests-clar/resources/submod2/not-submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 and /dev/null differ diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e b/tests-clar/resources/submod2/not-submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e deleted file mode 100644 index e9f1942a9..000000000 Binary files a/tests-clar/resources/submod2/not-submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e and /dev/null differ diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/refs/heads/master b/tests-clar/resources/submod2/not-submodule/.gitted/refs/heads/master deleted file mode 100644 index 0bd8514bd..000000000 --- a/tests-clar/resources/submod2/not-submodule/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -68e92c611b80ee1ed8f38314ff9577f0d15b2444 diff --git a/tests-clar/resources/submod2/not-submodule/README.txt b/tests-clar/resources/submod2/not-submodule/README.txt deleted file mode 100644 index 71ff9927d..000000000 --- a/tests-clar/resources/submod2/not-submodule/README.txt +++ /dev/null @@ -1 +0,0 @@ -This is a git repo but not a submodule diff --git a/tests-clar/resources/submod2/not/.gitted/notempty b/tests-clar/resources/submod2/not/.gitted/notempty deleted file mode 100644 index 9b33ac4e4..000000000 --- a/tests-clar/resources/submod2/not/.gitted/notempty +++ /dev/null @@ -1 +0,0 @@ -fooled you diff --git a/tests-clar/resources/submod2/not/README.txt b/tests-clar/resources/submod2/not/README.txt deleted file mode 100644 index 4f6935b98..000000000 --- a/tests-clar/resources/submod2/not/README.txt +++ /dev/null @@ -1 +0,0 @@ -what am I really diff --git a/tests-clar/resources/submod2/sm_added_and_uncommited/.gitted b/tests-clar/resources/submod2/sm_added_and_uncommited/.gitted deleted file mode 100644 index 2b2a4cf90..000000000 --- a/tests-clar/resources/submod2/sm_added_and_uncommited/.gitted +++ /dev/null @@ -1 +0,0 @@ -gitdir: ../.git/modules/sm_added_and_uncommited diff --git a/tests-clar/resources/submod2/sm_added_and_uncommited/README.txt b/tests-clar/resources/submod2/sm_added_and_uncommited/README.txt deleted file mode 100644 index 780d7397f..000000000 --- a/tests-clar/resources/submod2/sm_added_and_uncommited/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This is the target for submod2 submodule links. -Don't add commits casually because you make break tests. - diff --git a/tests-clar/resources/submod2/sm_added_and_uncommited/file_to_modify b/tests-clar/resources/submod2/sm_added_and_uncommited/file_to_modify deleted file mode 100644 index 789efbdad..000000000 --- a/tests-clar/resources/submod2/sm_added_and_uncommited/file_to_modify +++ /dev/null @@ -1,3 +0,0 @@ -This is a file to modify in submodules -It already has some history. -You can add local changes as needed. diff --git a/tests-clar/resources/submod2/sm_changed_file/.gitted b/tests-clar/resources/submod2/sm_changed_file/.gitted deleted file mode 100644 index dc98b1674..000000000 --- a/tests-clar/resources/submod2/sm_changed_file/.gitted +++ /dev/null @@ -1 +0,0 @@ -gitdir: ../.git/modules/sm_changed_file diff --git a/tests-clar/resources/submod2/sm_changed_file/README.txt b/tests-clar/resources/submod2/sm_changed_file/README.txt deleted file mode 100644 index 780d7397f..000000000 --- a/tests-clar/resources/submod2/sm_changed_file/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This is the target for submod2 submodule links. -Don't add commits casually because you make break tests. - diff --git a/tests-clar/resources/submod2/sm_changed_file/file_to_modify b/tests-clar/resources/submod2/sm_changed_file/file_to_modify deleted file mode 100644 index e5ba67168..000000000 --- a/tests-clar/resources/submod2/sm_changed_file/file_to_modify +++ /dev/null @@ -1,4 +0,0 @@ -This is a file to modify in submodules -It already has some history. -You can add local changes as needed. -In this case, the file is changed in the workdir diff --git a/tests-clar/resources/submod2/sm_changed_head/.gitted b/tests-clar/resources/submod2/sm_changed_head/.gitted deleted file mode 100644 index d5419b62d..000000000 --- a/tests-clar/resources/submod2/sm_changed_head/.gitted +++ /dev/null @@ -1 +0,0 @@ -gitdir: ../.git/modules/sm_changed_head diff --git a/tests-clar/resources/submod2/sm_changed_head/README.txt b/tests-clar/resources/submod2/sm_changed_head/README.txt deleted file mode 100644 index 780d7397f..000000000 --- a/tests-clar/resources/submod2/sm_changed_head/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This is the target for submod2 submodule links. -Don't add commits casually because you make break tests. - diff --git a/tests-clar/resources/submod2/sm_changed_head/file_to_modify b/tests-clar/resources/submod2/sm_changed_head/file_to_modify deleted file mode 100644 index 8eb1e637e..000000000 --- a/tests-clar/resources/submod2/sm_changed_head/file_to_modify +++ /dev/null @@ -1,4 +0,0 @@ -This is a file to modify in submodules -It already has some history. -You can add local changes as needed. -This one has been changed and the change has been committed to HEAD. diff --git a/tests-clar/resources/submod2/sm_changed_index/.gitted b/tests-clar/resources/submod2/sm_changed_index/.gitted deleted file mode 100644 index 2c7a5b271..000000000 --- a/tests-clar/resources/submod2/sm_changed_index/.gitted +++ /dev/null @@ -1 +0,0 @@ -gitdir: ../.git/modules/sm_changed_index diff --git a/tests-clar/resources/submod2/sm_changed_index/README.txt b/tests-clar/resources/submod2/sm_changed_index/README.txt deleted file mode 100644 index 780d7397f..000000000 --- a/tests-clar/resources/submod2/sm_changed_index/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This is the target for submod2 submodule links. -Don't add commits casually because you make break tests. - diff --git a/tests-clar/resources/submod2/sm_changed_index/file_to_modify b/tests-clar/resources/submod2/sm_changed_index/file_to_modify deleted file mode 100644 index a02d31770..000000000 --- a/tests-clar/resources/submod2/sm_changed_index/file_to_modify +++ /dev/null @@ -1,4 +0,0 @@ -This is a file to modify in submodules -It already has some history. -You can add local changes as needed. -Here the file is changed in the index and the workdir diff --git a/tests-clar/resources/submod2/sm_changed_untracked_file/.gitted b/tests-clar/resources/submod2/sm_changed_untracked_file/.gitted deleted file mode 100644 index 9a1070647..000000000 --- a/tests-clar/resources/submod2/sm_changed_untracked_file/.gitted +++ /dev/null @@ -1 +0,0 @@ -gitdir: ../.git/modules/sm_changed_untracked_file diff --git a/tests-clar/resources/submod2/sm_changed_untracked_file/README.txt b/tests-clar/resources/submod2/sm_changed_untracked_file/README.txt deleted file mode 100644 index 780d7397f..000000000 --- a/tests-clar/resources/submod2/sm_changed_untracked_file/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This is the target for submod2 submodule links. -Don't add commits casually because you make break tests. - diff --git a/tests-clar/resources/submod2/sm_changed_untracked_file/file_to_modify b/tests-clar/resources/submod2/sm_changed_untracked_file/file_to_modify deleted file mode 100644 index 789efbdad..000000000 --- a/tests-clar/resources/submod2/sm_changed_untracked_file/file_to_modify +++ /dev/null @@ -1,3 +0,0 @@ -This is a file to modify in submodules -It already has some history. -You can add local changes as needed. diff --git a/tests-clar/resources/submod2/sm_changed_untracked_file/i_am_untracked b/tests-clar/resources/submod2/sm_changed_untracked_file/i_am_untracked deleted file mode 100644 index d2bae6167..000000000 --- a/tests-clar/resources/submod2/sm_changed_untracked_file/i_am_untracked +++ /dev/null @@ -1 +0,0 @@ -This file is untracked, but in a submodule diff --git a/tests-clar/resources/submod2/sm_missing_commits/.gitted b/tests-clar/resources/submod2/sm_missing_commits/.gitted deleted file mode 100644 index 70193be84..000000000 --- a/tests-clar/resources/submod2/sm_missing_commits/.gitted +++ /dev/null @@ -1 +0,0 @@ -gitdir: ../.git/modules/sm_missing_commits diff --git a/tests-clar/resources/submod2/sm_missing_commits/README.txt b/tests-clar/resources/submod2/sm_missing_commits/README.txt deleted file mode 100644 index 780d7397f..000000000 --- a/tests-clar/resources/submod2/sm_missing_commits/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This is the target for submod2 submodule links. -Don't add commits casually because you make break tests. - diff --git a/tests-clar/resources/submod2/sm_missing_commits/file_to_modify b/tests-clar/resources/submod2/sm_missing_commits/file_to_modify deleted file mode 100644 index 8834b635d..000000000 --- a/tests-clar/resources/submod2/sm_missing_commits/file_to_modify +++ /dev/null @@ -1,3 +0,0 @@ -This is a file to modify in submodules -It already has some history. - diff --git a/tests-clar/resources/submod2/sm_unchanged/.gitted b/tests-clar/resources/submod2/sm_unchanged/.gitted deleted file mode 100644 index 51a679c80..000000000 --- a/tests-clar/resources/submod2/sm_unchanged/.gitted +++ /dev/null @@ -1 +0,0 @@ -gitdir: ../.git/modules/sm_unchanged diff --git a/tests-clar/resources/submod2/sm_unchanged/README.txt b/tests-clar/resources/submod2/sm_unchanged/README.txt deleted file mode 100644 index 780d7397f..000000000 --- a/tests-clar/resources/submod2/sm_unchanged/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This is the target for submod2 submodule links. -Don't add commits casually because you make break tests. - diff --git a/tests-clar/resources/submod2/sm_unchanged/file_to_modify b/tests-clar/resources/submod2/sm_unchanged/file_to_modify deleted file mode 100644 index 789efbdad..000000000 --- a/tests-clar/resources/submod2/sm_unchanged/file_to_modify +++ /dev/null @@ -1,3 +0,0 @@ -This is a file to modify in submodules -It already has some history. -You can add local changes as needed. diff --git a/tests-clar/resources/submod2_target/.gitted/HEAD b/tests-clar/resources/submod2_target/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/submod2_target/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/submod2_target/.gitted/config b/tests-clar/resources/submod2_target/.gitted/config deleted file mode 100644 index af107929f..000000000 --- a/tests-clar/resources/submod2_target/.gitted/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true diff --git a/tests-clar/resources/submod2_target/.gitted/description b/tests-clar/resources/submod2_target/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/submod2_target/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/submod2_target/.gitted/index b/tests-clar/resources/submod2_target/.gitted/index deleted file mode 100644 index eb3ff8c10..000000000 Binary files a/tests-clar/resources/submod2_target/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/submod2_target/.gitted/info/exclude b/tests-clar/resources/submod2_target/.gitted/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/submod2_target/.gitted/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/submod2_target/.gitted/logs/HEAD b/tests-clar/resources/submod2_target/.gitted/logs/HEAD deleted file mode 100644 index 0ecd1113f..000000000 --- a/tests-clar/resources/submod2_target/.gitted/logs/HEAD +++ /dev/null @@ -1,4 +0,0 @@ -0000000000000000000000000000000000000000 6b31c659545507c381e9cd34ec508f16c04e149e Russell Belfer 1342559662 -0700 commit (initial): Initial commit -6b31c659545507c381e9cd34ec508f16c04e149e 41bd4bc3df978de695f67ace64c560913da11653 Russell Belfer 1342559709 -0700 commit: Adding test file -41bd4bc3df978de695f67ace64c560913da11653 5e4963595a9774b90524d35a807169049de8ccad Russell Belfer 1342559726 -0700 commit: Updating test file -5e4963595a9774b90524d35a807169049de8ccad 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342559925 -0700 commit: One more update diff --git a/tests-clar/resources/submod2_target/.gitted/logs/refs/heads/master b/tests-clar/resources/submod2_target/.gitted/logs/refs/heads/master deleted file mode 100644 index 0ecd1113f..000000000 --- a/tests-clar/resources/submod2_target/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,4 +0,0 @@ -0000000000000000000000000000000000000000 6b31c659545507c381e9cd34ec508f16c04e149e Russell Belfer 1342559662 -0700 commit (initial): Initial commit -6b31c659545507c381e9cd34ec508f16c04e149e 41bd4bc3df978de695f67ace64c560913da11653 Russell Belfer 1342559709 -0700 commit: Adding test file -41bd4bc3df978de695f67ace64c560913da11653 5e4963595a9774b90524d35a807169049de8ccad Russell Belfer 1342559726 -0700 commit: Updating test file -5e4963595a9774b90524d35a807169049de8ccad 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342559925 -0700 commit: One more update diff --git a/tests-clar/resources/submod2_target/.gitted/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests-clar/resources/submod2_target/.gitted/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 deleted file mode 100644 index f4b7094c5..000000000 Binary files a/tests-clar/resources/submod2_target/.gitted/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 and /dev/null differ diff --git a/tests-clar/resources/submod2_target/.gitted/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests-clar/resources/submod2_target/.gitted/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 deleted file mode 100644 index 56c845e49..000000000 Binary files a/tests-clar/resources/submod2_target/.gitted/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 and /dev/null differ diff --git a/tests-clar/resources/submod2_target/.gitted/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests-clar/resources/submod2_target/.gitted/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 deleted file mode 100644 index bd179b5f5..000000000 Binary files a/tests-clar/resources/submod2_target/.gitted/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 and /dev/null differ diff --git a/tests-clar/resources/submod2_target/.gitted/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests-clar/resources/submod2_target/.gitted/objects/41/bd4bc3df978de695f67ace64c560913da11653 deleted file mode 100644 index ccf49bd15..000000000 Binary files a/tests-clar/resources/submod2_target/.gitted/objects/41/bd4bc3df978de695f67ace64c560913da11653 and /dev/null differ diff --git a/tests-clar/resources/submod2_target/.gitted/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests-clar/resources/submod2_target/.gitted/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 deleted file mode 100644 index 53029069a..000000000 Binary files a/tests-clar/resources/submod2_target/.gitted/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 and /dev/null differ diff --git a/tests-clar/resources/submod2_target/.gitted/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests-clar/resources/submod2_target/.gitted/objects/5e/4963595a9774b90524d35a807169049de8ccad deleted file mode 100644 index 38c791eba..000000000 Binary files a/tests-clar/resources/submod2_target/.gitted/objects/5e/4963595a9774b90524d35a807169049de8ccad and /dev/null differ diff --git a/tests-clar/resources/submod2_target/.gitted/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests-clar/resources/submod2_target/.gitted/objects/6b/31c659545507c381e9cd34ec508f16c04e149e deleted file mode 100644 index a26d29993..000000000 --- a/tests-clar/resources/submod2_target/.gitted/objects/6b/31c659545507c381e9cd34ec508f16c04e149e +++ /dev/null @@ -1,2 +0,0 @@ -xQ -!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests-clar/resources/submod2_target/.gitted/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests-clar/resources/submod2_target/.gitted/objects/73/ba924a80437097795ae839e66e187c55d3babf deleted file mode 100644 index 83d1ba481..000000000 Binary files a/tests-clar/resources/submod2_target/.gitted/objects/73/ba924a80437097795ae839e66e187c55d3babf and /dev/null differ diff --git a/tests-clar/resources/submod2_target/.gitted/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests-clar/resources/submod2_target/.gitted/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a deleted file mode 100644 index 6d27af8a8..000000000 --- a/tests-clar/resources/submod2_target/.gitted/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a +++ /dev/null @@ -1,2 +0,0 @@ -x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x -uxt(+ \ No newline at end of file diff --git a/tests-clar/resources/submod2_target/.gitted/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests-clar/resources/submod2_target/.gitted/objects/78/9efbdadaa4a582778d4584385495559ea0994b deleted file mode 100644 index 17458840b..000000000 --- a/tests-clar/resources/submod2_target/.gitted/objects/78/9efbdadaa4a582778d4584385495559ea0994b +++ /dev/null @@ -1,2 +0,0 @@ -x 0 )?= NlOkj8&r -qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests-clar/resources/submod2_target/.gitted/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests-clar/resources/submod2_target/.gitted/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e deleted file mode 100644 index 83cc29fb1..000000000 Binary files a/tests-clar/resources/submod2_target/.gitted/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e and /dev/null differ diff --git a/tests-clar/resources/submod2_target/.gitted/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests-clar/resources/submod2_target/.gitted/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 deleted file mode 100644 index 55bda40ef..000000000 Binary files a/tests-clar/resources/submod2_target/.gitted/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 and /dev/null differ diff --git a/tests-clar/resources/submod2_target/.gitted/refs/heads/master b/tests-clar/resources/submod2_target/.gitted/refs/heads/master deleted file mode 100644 index e12c44d7a..000000000 --- a/tests-clar/resources/submod2_target/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests-clar/resources/submod2_target/README.txt b/tests-clar/resources/submod2_target/README.txt deleted file mode 100644 index 780d7397f..000000000 --- a/tests-clar/resources/submod2_target/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -This is the target for submod2 submodule links. -Don't add commits casually because you make break tests. - diff --git a/tests-clar/resources/submod2_target/file_to_modify b/tests-clar/resources/submod2_target/file_to_modify deleted file mode 100644 index 789efbdad..000000000 --- a/tests-clar/resources/submod2_target/file_to_modify +++ /dev/null @@ -1,3 +0,0 @@ -This is a file to modify in submodules -It already has some history. -You can add local changes as needed. diff --git a/tests-clar/resources/submodules/.gitted/HEAD b/tests-clar/resources/submodules/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/submodules/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/submodules/.gitted/config b/tests-clar/resources/submodules/.gitted/config deleted file mode 100644 index af107929f..000000000 --- a/tests-clar/resources/submodules/.gitted/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true diff --git a/tests-clar/resources/submodules/.gitted/description b/tests-clar/resources/submodules/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/submodules/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/submodules/.gitted/index b/tests-clar/resources/submodules/.gitted/index deleted file mode 100644 index 97bf8ef51..000000000 Binary files a/tests-clar/resources/submodules/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/submodules/.gitted/info/exclude b/tests-clar/resources/submodules/.gitted/info/exclude deleted file mode 100644 index dfc411579..000000000 --- a/tests-clar/resources/submodules/.gitted/info/exclude +++ /dev/null @@ -1,8 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ -ignored - diff --git a/tests-clar/resources/submodules/.gitted/info/refs b/tests-clar/resources/submodules/.gitted/info/refs deleted file mode 100644 index ba17abdde..000000000 --- a/tests-clar/resources/submodules/.gitted/info/refs +++ /dev/null @@ -1 +0,0 @@ -09176a980273d801a3e37cc45c84af1366501ed9 refs/heads/master diff --git a/tests-clar/resources/submodules/.gitted/logs/HEAD b/tests-clar/resources/submodules/.gitted/logs/HEAD deleted file mode 100644 index 87a7bdafc..000000000 --- a/tests-clar/resources/submodules/.gitted/logs/HEAD +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 09176a980273d801a3e37cc45c84af1366501ed9 Russell Belfer 1332365253 -0700 commit (initial): initial commit -09176a980273d801a3e37cc45c84af1366501ed9 97896810b3210244a62a82458b8e0819ecfc6850 Russell Belfer 1332780781 -0700 commit: Setting up gitmodules diff --git a/tests-clar/resources/submodules/.gitted/logs/refs/heads/master b/tests-clar/resources/submodules/.gitted/logs/refs/heads/master deleted file mode 100644 index 87a7bdafc..000000000 --- a/tests-clar/resources/submodules/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 09176a980273d801a3e37cc45c84af1366501ed9 Russell Belfer 1332365253 -0700 commit (initial): initial commit -09176a980273d801a3e37cc45c84af1366501ed9 97896810b3210244a62a82458b8e0819ecfc6850 Russell Belfer 1332780781 -0700 commit: Setting up gitmodules diff --git a/tests-clar/resources/submodules/.gitted/objects/26/a3b32a9b7d97486c5557f5902e8ac94638145e b/tests-clar/resources/submodules/.gitted/objects/26/a3b32a9b7d97486c5557f5902e8ac94638145e deleted file mode 100644 index 2c3c2cb61..000000000 --- a/tests-clar/resources/submodules/.gitted/objects/26/a3b32a9b7d97486c5557f5902e8ac94638145e +++ /dev/null @@ -1,2 +0,0 @@ -x%= -0 F])0"I*|-t{?2ilV8$mvkk*F DA=(=|=6 DAv=A}&'O$= \ No newline at end of file diff --git a/tests-clar/resources/submodules/.gitted/objects/78/308c9251cf4eee8b25a76c7d2790c73d797357 b/tests-clar/resources/submodules/.gitted/objects/78/308c9251cf4eee8b25a76c7d2790c73d797357 deleted file mode 100644 index c85fb5512..000000000 Binary files a/tests-clar/resources/submodules/.gitted/objects/78/308c9251cf4eee8b25a76c7d2790c73d797357 and /dev/null differ diff --git a/tests-clar/resources/submodules/.gitted/objects/97/896810b3210244a62a82458b8e0819ecfc6850 b/tests-clar/resources/submodules/.gitted/objects/97/896810b3210244a62a82458b8e0819ecfc6850 deleted file mode 100644 index 1c8dbdf9f..000000000 --- a/tests-clar/resources/submodules/.gitted/objects/97/896810b3210244a62a82458b8e0819ecfc6850 +++ /dev/null @@ -1,3 +0,0 @@ -x[ -0E*fʤS K4ݿwׅ9p2MCFP @u..p!OYdiYU'̕8XbPn6 -ħԞ1[q}0qc[W#1fR:SZ+Y+{tdlvOmu_}5i` K \ No newline at end of file diff --git a/tests-clar/resources/submodules/.gitted/objects/b6/0fd986699ba4e9e68bea07cf8e793f323ef888 b/tests-clar/resources/submodules/.gitted/objects/b6/0fd986699ba4e9e68bea07cf8e793f323ef888 deleted file mode 100644 index 3d78bd6be..000000000 Binary files a/tests-clar/resources/submodules/.gitted/objects/b6/0fd986699ba4e9e68bea07cf8e793f323ef888 and /dev/null differ diff --git a/tests-clar/resources/submodules/.gitted/objects/d5/f7fc3f74f7dec08280f370a975b112e8f60818 b/tests-clar/resources/submodules/.gitted/objects/d5/f7fc3f74f7dec08280f370a975b112e8f60818 deleted file mode 100644 index 6e0b49e86..000000000 Binary files a/tests-clar/resources/submodules/.gitted/objects/d5/f7fc3f74f7dec08280f370a975b112e8f60818 and /dev/null differ diff --git a/tests-clar/resources/submodules/.gitted/objects/e3/50052cc767cd1fcb37e84e9a89e701925be4ae b/tests-clar/resources/submodules/.gitted/objects/e3/50052cc767cd1fcb37e84e9a89e701925be4ae deleted file mode 100644 index 082a58941..000000000 Binary files a/tests-clar/resources/submodules/.gitted/objects/e3/50052cc767cd1fcb37e84e9a89e701925be4ae and /dev/null differ diff --git a/tests-clar/resources/submodules/.gitted/objects/info/packs b/tests-clar/resources/submodules/.gitted/objects/info/packs deleted file mode 100644 index 0785ef698..000000000 --- a/tests-clar/resources/submodules/.gitted/objects/info/packs +++ /dev/null @@ -1,2 +0,0 @@ -P pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack - diff --git a/tests-clar/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx b/tests-clar/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx deleted file mode 100644 index 810fc3181..000000000 Binary files a/tests-clar/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx and /dev/null differ diff --git a/tests-clar/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack b/tests-clar/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack deleted file mode 100644 index c25c4a73f..000000000 Binary files a/tests-clar/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack and /dev/null differ diff --git a/tests-clar/resources/submodules/.gitted/packed-refs b/tests-clar/resources/submodules/.gitted/packed-refs deleted file mode 100644 index a6450691e..000000000 --- a/tests-clar/resources/submodules/.gitted/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -09176a980273d801a3e37cc45c84af1366501ed9 refs/heads/master diff --git a/tests-clar/resources/submodules/.gitted/refs/heads/master b/tests-clar/resources/submodules/.gitted/refs/heads/master deleted file mode 100644 index 32b935853..000000000 --- a/tests-clar/resources/submodules/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -97896810b3210244a62a82458b8e0819ecfc6850 diff --git a/tests-clar/resources/submodules/added b/tests-clar/resources/submodules/added deleted file mode 100644 index d5f7fc3f7..000000000 --- a/tests-clar/resources/submodules/added +++ /dev/null @@ -1 +0,0 @@ -added diff --git a/tests-clar/resources/submodules/gitmodules b/tests-clar/resources/submodules/gitmodules deleted file mode 100644 index 2798b696c..000000000 --- a/tests-clar/resources/submodules/gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "testrepo"] - path = testrepo - url = -[submodule ""] - path = testrepo - url = \ No newline at end of file diff --git a/tests-clar/resources/submodules/ignored b/tests-clar/resources/submodules/ignored deleted file mode 100644 index 092bfb9bd..000000000 --- a/tests-clar/resources/submodules/ignored +++ /dev/null @@ -1 +0,0 @@ -yo diff --git a/tests-clar/resources/submodules/modified b/tests-clar/resources/submodules/modified deleted file mode 100644 index 452216e1d..000000000 --- a/tests-clar/resources/submodules/modified +++ /dev/null @@ -1,2 +0,0 @@ -changed - diff --git a/tests-clar/resources/submodules/testrepo/.gitted/HEAD b/tests-clar/resources/submodules/testrepo/.gitted/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/submodules/testrepo/.gitted/config b/tests-clar/resources/submodules/testrepo/.gitted/config deleted file mode 100644 index d6dcad12b..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/config +++ /dev/null @@ -1,12 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - ignorecase = true -[remote "origin"] - fetch = +refs/heads/*:refs/remotes/origin/* - url = /Users/rb/src/libgit2/tests/resources/testrepo.git -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/tests-clar/resources/submodules/testrepo/.gitted/description b/tests-clar/resources/submodules/testrepo/.gitted/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/submodules/testrepo/.gitted/index b/tests-clar/resources/submodules/testrepo/.gitted/index deleted file mode 100644 index 3eb8d84fe..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/index and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/info/exclude b/tests-clar/resources/submodules/testrepo/.gitted/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/logs/HEAD b/tests-clar/resources/submodules/testrepo/.gitted/logs/HEAD deleted file mode 100644 index 147643a30..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/logs/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Russell Belfer 1332366307 -0700 clone: from /Users/rb/src/libgit2/tests/resources/testrepo.git diff --git a/tests-clar/resources/submodules/testrepo/.gitted/logs/refs/heads/master b/tests-clar/resources/submodules/testrepo/.gitted/logs/refs/heads/master deleted file mode 100644 index 147643a30..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Russell Belfer 1332366307 -0700 clone: from /Users/rb/src/libgit2/tests/resources/testrepo.git diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 b/tests-clar/resources/submodules/testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 deleted file mode 100644 index cedb2a22e..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 b/tests-clar/resources/submodules/testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 deleted file mode 100644 index 93a16f146..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd b/tests-clar/resources/submodules/testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd deleted file mode 100644 index ba0bfb30c..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b b/tests-clar/resources/submodules/testrepo/.gitted/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b deleted file mode 100644 index 225c45734..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d b/tests-clar/resources/submodules/testrepo/.gitted/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d deleted file mode 100644 index df40d99af..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 b/tests-clar/resources/submodules/testrepo/.gitted/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 deleted file mode 100644 index 321eaa867..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc b/tests-clar/resources/submodules/testrepo/.gitted/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc deleted file mode 100644 index 9bb5b623b..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests-clar/resources/submodules/testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 deleted file mode 100644 index 7ca4ceed5..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 b/tests-clar/resources/submodules/testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 deleted file mode 100644 index 8953b6cef..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 +++ /dev/null @@ -1,2 +0,0 @@ -xQ -0D)6ͦ "xO-FbEo0 Ǥ,ske[Pn8R,EpD?g}^3 <GhYK8ЖDA);gݧjp4-r;sGA4ۺ=(in7IKFE \ No newline at end of file diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 b/tests-clar/resources/submodules/testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 deleted file mode 100644 index c1f22c54f..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 +++ /dev/null @@ -1,2 +0,0 @@ -x 1ENi@k2 "X$YW0YcÅszMD08!s Xgd::@X0Pw"F/RUzmZZV}|/o5I!1z:vUim}/> -F- \ No newline at end of file diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests-clar/resources/submodules/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a deleted file mode 100644 index 2ef4faa0f..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af b/tests-clar/resources/submodules/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af deleted file mode 100644 index 716b0c64b..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af +++ /dev/null @@ -1 +0,0 @@ -xAj!?009o}H6}jUPPZ&Y AԛpFdpz[fYPqLJ.,Z`Ů.`v q $5+9Ot>/DE/龡W*eVdf1>覭ěʙFThk.i^0?PR, \ No newline at end of file diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 b/tests-clar/resources/submodules/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 deleted file mode 100644 index 23c462f34..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests-clar/resources/submodules/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d deleted file mode 100644 index 2f9b6b6e3..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests-clar/resources/submodules/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 deleted file mode 100644 index 5df58dda5..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 b/tests-clar/resources/submodules/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 deleted file mode 100644 index 4cc3f4dff..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 +++ /dev/null @@ -1 +0,0 @@ -x+)JMU044b040031QrutueXlmmAṃJ}G;UTWRQ`6Kǥ^/-*|W3Py`%E\&g|0{Ӎ1X \ No newline at end of file diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 b/tests-clar/resources/submodules/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 deleted file mode 100644 index bf7b2bb68..000000000 Binary files a/tests-clar/resources/submodules/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 and /dev/null differ diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests-clar/resources/submodules/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a deleted file mode 100644 index a79612435..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a +++ /dev/null @@ -1,3 +0,0 @@ -x[ -0E*fդ "W0-Ft݁pS[Yx^ -Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests-clar/resources/submodules/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f deleted file mode 100644 index f8588696b..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f +++ /dev/null @@ -1,2 +0,0 @@ -x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S - U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests-clar/resources/submodules/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 b/tests-clar/resources/submodules/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 deleted file mode 100644 index 29c8e824d..000000000 --- a/tests-clar/resources/submodules/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 +++ /dev/null @@ -1,3 +0,0 @@ -xQ -!@sBQ" ٱ r{ 1335806563 -0700 clone: from /Users/ben/src/libgit2/tests/resources/testrepo.git -be3563ae3f795b2b4353bcce3a527ad0a4f7f644 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub 1335806603 -0900 commit: -a65fedf39aefe402d3bb6e24df4d4f5fe4547750 5b5b025afb0b4c913b4c338a42934a3863bf3644 Ben Straub 1335806604 -0900 checkout: moving from master to 5b5b025 -5b5b025afb0b4c913b4c338a42934a3863bf3644 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub 1335806605 -0900 checkout: moving from 5b5b025 to master -a65fedf39aefe402d3bb6e24df4d4f5fe4547750 c47800c7266a2be04c571c04d5a6614691ea99bd Ben Straub 1335806608 -0900 checkout: moving from master to br2 -c47800c7266a2be04c571c04d5a6614691ea99bd a4a7dce85cf63874e984719f4fdd239f5145052f Ben Straub 1335806617 -0900 commit: checking in -a4a7dce85cf63874e984719f4fdd239f5145052f a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub 1335806621 -0900 checkout: moving from br2 to master diff --git a/tests-clar/resources/testrepo.git/logs/refs/heads/br2 b/tests-clar/resources/testrepo.git/logs/refs/heads/br2 deleted file mode 100644 index 4e27f6b8d..000000000 --- a/tests-clar/resources/testrepo.git/logs/refs/heads/br2 +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 c47800c7266a2be04c571c04d5a6614691ea99bd Ben Straub 1335806608 -0700 branch: Created from refs/remotes/origin/br2 -a4a7dce85cf63874e984719f4fdd239f5145052f a4a7dce85cf63874e984719f4fdd239f5145052f Ben Straub 1335806617 -0700 commit: checking in diff --git a/tests-clar/resources/testrepo.git/logs/refs/heads/master b/tests-clar/resources/testrepo.git/logs/refs/heads/master deleted file mode 100644 index e1c729a45..000000000 --- a/tests-clar/resources/testrepo.git/logs/refs/heads/master +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 be3563ae3f795b2b4353bcce3a527ad0a4f7f644 Ben Straub 1335806563 -0800 clone: from /Users/ben/src/libgit2/tests/resources/testrepo.git -be3563ae3f795b2b4353bcce3a527ad0a4f7f644 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub 1335806603 -0800 commit: checking in diff --git a/tests-clar/resources/testrepo.git/logs/refs/heads/not-good b/tests-clar/resources/testrepo.git/logs/refs/heads/not-good deleted file mode 100644 index bfbeacb8a..000000000 --- a/tests-clar/resources/testrepo.git/logs/refs/heads/not-good +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub 1336761944 -0700 branch: Created from master diff --git a/tests-clar/resources/testrepo.git/logs/refs/remotes/origin/HEAD b/tests-clar/resources/testrepo.git/logs/refs/remotes/origin/HEAD deleted file mode 100644 index f1aac6d0f..000000000 --- a/tests-clar/resources/testrepo.git/logs/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 be3563ae3f795b2b4353bcce3a527ad0a4f7f644 Ben Straub 1335806563 -0700 clone: from /Users/ben/src/libgit2/tests/resources/testrepo.git diff --git a/tests-clar/resources/testrepo.git/logs/refs/remotes/test/master b/tests-clar/resources/testrepo.git/logs/refs/remotes/test/master deleted file mode 100644 index 8d49ba3e0..000000000 --- a/tests-clar/resources/testrepo.git/logs/refs/remotes/test/master +++ /dev/null @@ -1,2 +0,0 @@ -0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub 1335806565 -0800 update by push -a65fedf39aefe402d3bb6e24df4d4f5fe4547750 be3563ae3f795b2b4353bcce3a527ad0a4f7f644 Ben Straub 1335806688 -0800 update by push diff --git a/tests-clar/resources/testrepo.git/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 b/tests-clar/resources/testrepo.git/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 deleted file mode 100644 index d1c032fce..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 b/tests-clar/resources/testrepo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 deleted file mode 100644 index cedb2a22e..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 b/tests-clar/resources/testrepo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 deleted file mode 100644 index 93a16f146..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd b/tests-clar/resources/testrepo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd deleted file mode 100644 index ba0bfb30c..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd b/tests-clar/resources/testrepo.git/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd deleted file mode 100644 index 3ec541288..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/1b/8cbad43e867676df601306689fe7c3def5e689 b/tests-clar/resources/testrepo.git/objects/1b/8cbad43e867676df601306689fe7c3def5e689 deleted file mode 100644 index 6048d4bad..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/1b/8cbad43e867676df601306689fe7c3def5e689 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b b/tests-clar/resources/testrepo.git/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b deleted file mode 100644 index 225c45734..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 b/tests-clar/resources/testrepo.git/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 deleted file mode 100644 index cb1ed5712..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d b/tests-clar/resources/testrepo.git/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d deleted file mode 100644 index df40d99af..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 b/tests-clar/resources/testrepo.git/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 deleted file mode 100644 index 0a1500a6f..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 b/tests-clar/resources/testrepo.git/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 deleted file mode 100644 index 321eaa867..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc b/tests-clar/resources/testrepo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc deleted file mode 100644 index 9bb5b623b..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests-clar/resources/testrepo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 deleted file mode 100644 index 7ca4ceed5..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 b/tests-clar/resources/testrepo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 deleted file mode 100644 index 8953b6cef..000000000 --- a/tests-clar/resources/testrepo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 +++ /dev/null @@ -1,2 +0,0 @@ -xQ -0D)6ͦ "xO-FbEo0 Ǥ,ske[Pn8R,EpD?g}^3 <GhYK8ЖDA);gݧjp4-r;sGA4ۺ=(in7IKFE \ No newline at end of file diff --git a/tests-clar/resources/testrepo.git/objects/4a/23e2e65ad4e31c4c9db7dc746650bfad082679 b/tests-clar/resources/testrepo.git/objects/4a/23e2e65ad4e31c4c9db7dc746650bfad082679 deleted file mode 100644 index 18e3964b3..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/4a/23e2e65ad4e31c4c9db7dc746650bfad082679 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea b/tests-clar/resources/testrepo.git/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea deleted file mode 100644 index b4e5aa186..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 b/tests-clar/resources/testrepo.git/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 deleted file mode 100644 index 351cff823..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 b/tests-clar/resources/testrepo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 deleted file mode 100644 index c1f22c54f..000000000 --- a/tests-clar/resources/testrepo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 +++ /dev/null @@ -1,2 +0,0 @@ -x 1ENi@k2 "X$YW0YcÅszMD08!s Xgd::@X0Pw"F/RUzmZZV}|/o5I!1z:vUim}/> -F- \ No newline at end of file diff --git a/tests-clar/resources/testrepo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests-clar/resources/testrepo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a deleted file mode 100644 index 2ef4faa0f..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af b/tests-clar/resources/testrepo.git/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af deleted file mode 100644 index 716b0c64b..000000000 --- a/tests-clar/resources/testrepo.git/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af +++ /dev/null @@ -1 +0,0 @@ -xAj!?009o}H6}jUPPZ&Y AԛpFdpz[fYPqLJ.,Z`Ů.`v q $5+9Ot>/DE/龡W*eVdf1>覭ěʙFThk.i^0?PR, \ No newline at end of file diff --git a/tests-clar/resources/testrepo.git/objects/7b/4384978d2493e851f9cca7858815fac9b10980 b/tests-clar/resources/testrepo.git/objects/7b/4384978d2493e851f9cca7858815fac9b10980 deleted file mode 100644 index 23c462f34..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/7b/4384978d2493e851f9cca7858815fac9b10980 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests-clar/resources/testrepo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d deleted file mode 100644 index 2f9b6b6e3..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests-clar/resources/testrepo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 deleted file mode 100644 index 5df58dda5..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe b/tests-clar/resources/testrepo.git/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe deleted file mode 100644 index 71019a636..000000000 --- a/tests-clar/resources/testrepo.git/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe +++ /dev/null @@ -1,2 +0,0 @@ -xM F]s41x(IKݽ/_P@!8)es - N&FGSƄh{+CZzvF7Z-kx\[P8GK/^ l>.4 \ No newline at end of file diff --git a/tests-clar/resources/testrepo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 b/tests-clar/resources/testrepo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 deleted file mode 100644 index 4cc3f4dff..000000000 --- a/tests-clar/resources/testrepo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 +++ /dev/null @@ -1 +0,0 @@ -x+)JMU044b040031QrutueXlmmAṃJ}G;UTWRQ`6Kǥ^/-*|W3Py`%E\&g|0{Ӎ1X \ No newline at end of file diff --git a/tests-clar/resources/testrepo.git/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 b/tests-clar/resources/testrepo.git/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 deleted file mode 100644 index bf7b2bb68..000000000 Binary files a/tests-clar/resources/testrepo.git/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 and /dev/null differ diff --git a/tests-clar/resources/testrepo.git/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 b/tests-clar/resources/testrepo.git/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 deleted file mode 100644 index 7f1cfb23c..000000000 --- a/tests-clar/resources/testrepo.git/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 +++ /dev/null @@ -1,2 +0,0 @@ -xM -0F]d2;XEȎ5R AE &n}ZA \ No newline at end of file diff --git a/tests-clar/resources/testrepo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests-clar/resources/testrepo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a deleted file mode 100644 index a79612435..000000000 --- a/tests-clar/resources/testrepo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a +++ /dev/null @@ -1,3 +0,0 @@ -x[ -0E*fդ "W0-Ft݁pS[Yx^ -Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests-clar/resources/testrepo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests-clar/resources/testrepo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f deleted file mode 100644 index f8588696b..000000000 --- a/tests-clar/resources/testrepo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f +++ /dev/null @@ -1,2 +0,0 @@ -x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S - U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests-clar/resources/testrepo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 b/tests-clar/resources/testrepo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 deleted file mode 100644 index 29c8e824d..000000000 --- a/tests-clar/resources/testrepo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 +++ /dev/null @@ -1,3 +0,0 @@ -xQ -!@sBQ" ٱ r{ -F- \ No newline at end of file diff --git a/tests-clar/resources/testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc b/tests-clar/resources/testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc deleted file mode 100644 index b669961d8..000000000 Binary files a/tests-clar/resources/testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc and /dev/null differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 b/tests-clar/resources/testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 deleted file mode 100644 index 9ff5eb2b5..000000000 Binary files a/tests-clar/resources/testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 and /dev/null differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 b/tests-clar/resources/testrepo/.gitted/objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 deleted file mode 100644 index ee7c78174..000000000 Binary files a/tests-clar/resources/testrepo/.gitted/objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 and /dev/null differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e b/tests-clar/resources/testrepo/.gitted/objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e deleted file mode 100644 index 197685b86..000000000 Binary files a/tests-clar/resources/testrepo/.gitted/objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e and /dev/null differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests-clar/resources/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a deleted file mode 100644 index 2ef4faa0f..000000000 Binary files a/tests-clar/resources/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a and /dev/null differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af b/tests-clar/resources/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af deleted file mode 100644 index 716b0c64b..000000000 --- a/tests-clar/resources/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af +++ /dev/null @@ -1 +0,0 @@ -xAj!?009o}H6}jUPPZ&Y AԛpFdpz[fYPqLJ.,Z`Ů.`v q $5+9Ot>/DE/龡W*eVdf1>覭ěʙFThk.i^0?PR, \ No newline at end of file diff --git a/tests-clar/resources/testrepo/.gitted/objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a b/tests-clar/resources/testrepo/.gitted/objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a deleted file mode 100644 index db778aaae..000000000 Binary files a/tests-clar/resources/testrepo/.gitted/objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a and /dev/null differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 b/tests-clar/resources/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 deleted file mode 100644 index 23c462f34..000000000 Binary files a/tests-clar/resources/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 and /dev/null differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests-clar/resources/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d deleted file mode 100644 index 2f9b6b6e3..000000000 Binary files a/tests-clar/resources/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d and /dev/null differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests-clar/resources/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 deleted file mode 100644 index 5df58dda5..000000000 Binary files a/tests-clar/resources/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 and /dev/null differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/87/380ae84009e9c503506c2f6143a4fc6c60bf80 b/tests-clar/resources/testrepo/.gitted/objects/87/380ae84009e9c503506c2f6143a4fc6c60bf80 deleted file mode 100644 index 3042f5790..000000000 Binary files a/tests-clar/resources/testrepo/.gitted/objects/87/380ae84009e9c503506c2f6143a4fc6c60bf80 and /dev/null differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 b/tests-clar/resources/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 deleted file mode 100644 index 4cc3f4dff..000000000 --- a/tests-clar/resources/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 +++ /dev/null @@ -1 +0,0 @@ -x+)JMU044b040031QrutueXlmmAṃJ}G;UTWRQ`6Kǥ^/-*|W3Py`%E\&g|0{Ӎ1X \ No newline at end of file diff --git a/tests-clar/resources/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 b/tests-clar/resources/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 deleted file mode 100644 index bf7b2bb68..000000000 Binary files a/tests-clar/resources/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 and /dev/null differ diff --git a/tests-clar/resources/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests-clar/resources/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a deleted file mode 100644 index a79612435..000000000 --- a/tests-clar/resources/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a +++ /dev/null @@ -1,3 +0,0 @@ -x[ -0E*fդ "W0-Ft݁pS[Yx^ -Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests-clar/resources/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests-clar/resources/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f deleted file mode 100644 index f8588696b..000000000 --- a/tests-clar/resources/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f +++ /dev/null @@ -1,2 +0,0 @@ -x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S - U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests-clar/resources/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 b/tests-clar/resources/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 deleted file mode 100644 index 29c8e824d..000000000 --- a/tests-clar/resources/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 +++ /dev/null @@ -1,3 +0,0 @@ -xQ -!@sBQ" ٱ r{ 1368278260 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/../../../rugged/test/fixtures/testrepo.git diff --git a/tests-clar/resources/testrepo2/.gitted/logs/refs/heads/master b/tests-clar/resources/testrepo2/.gitted/logs/refs/heads/master deleted file mode 100644 index 4e80c69fa..000000000 --- a/tests-clar/resources/testrepo2/.gitted/logs/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 36060c58702ed4c2a40832c51758d5344201d89a Russell Belfer 1368278260 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/../../../rugged/test/fixtures/testrepo.git diff --git a/tests-clar/resources/testrepo2/.gitted/logs/refs/remotes/origin/HEAD b/tests-clar/resources/testrepo2/.gitted/logs/refs/remotes/origin/HEAD deleted file mode 100644 index 4e80c69fa..000000000 --- a/tests-clar/resources/testrepo2/.gitted/logs/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -0000000000000000000000000000000000000000 36060c58702ed4c2a40832c51758d5344201d89a Russell Belfer 1368278260 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/../../../rugged/test/fixtures/testrepo.git diff --git a/tests-clar/resources/testrepo2/.gitted/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d b/tests-clar/resources/testrepo2/.gitted/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d deleted file mode 100644 index bfe146a5a..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 b/tests-clar/resources/testrepo2/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 deleted file mode 100644 index cedb2a22e..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 b/tests-clar/resources/testrepo2/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 deleted file mode 100644 index 93a16f146..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd b/tests-clar/resources/testrepo2/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd deleted file mode 100644 index ba0bfb30c..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 b/tests-clar/resources/testrepo2/.gitted/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 deleted file mode 100644 index 3cd240db5..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/36/060c58702ed4c2a40832c51758d5344201d89a b/tests-clar/resources/testrepo2/.gitted/objects/36/060c58702ed4c2a40832c51758d5344201d89a deleted file mode 100644 index 0c6246061..000000000 --- a/tests-clar/resources/testrepo2/.gitted/objects/36/060c58702ed4c2a40832c51758d5344201d89a +++ /dev/null @@ -1,2 +0,0 @@ -xQ -0)reݴ $ۭ-F-00𸖲?iL#HSS#q2D據jC|HSL8$)a#2i׹6js?JZftΞUiͶqiZ"_/H6 \ No newline at end of file diff --git a/tests-clar/resources/testrepo2/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests-clar/resources/testrepo2/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 deleted file mode 100644 index 7ca4ceed5..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 b/tests-clar/resources/testrepo2/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 deleted file mode 100644 index 8953b6cef..000000000 --- a/tests-clar/resources/testrepo2/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 +++ /dev/null @@ -1,2 +0,0 @@ -xQ -0D)6ͦ "xO-FbEo0 Ǥ,ske[Pn8R,EpD?g}^3 <GhYK8ЖDA);gݧjp4-r;sGA4ۺ=(in7IKFE \ No newline at end of file diff --git a/tests-clar/resources/testrepo2/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 b/tests-clar/resources/testrepo2/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 deleted file mode 100644 index c1f22c54f..000000000 --- a/tests-clar/resources/testrepo2/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 +++ /dev/null @@ -1,2 +0,0 @@ -x 1ENi@k2 "X$YW0YcÅszMD08!s Xgd::@X0Pw"F/RUzmZZV}|/o5I!1z:vUim}/> -F- \ No newline at end of file diff --git a/tests-clar/resources/testrepo2/.gitted/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 b/tests-clar/resources/testrepo2/.gitted/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 deleted file mode 100644 index 1fd79b477..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests-clar/resources/testrepo2/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a deleted file mode 100644 index 2ef4faa0f..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 b/tests-clar/resources/testrepo2/.gitted/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 deleted file mode 100644 index 3d1016daa..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests-clar/resources/testrepo2/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d deleted file mode 100644 index 2f9b6b6e3..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests-clar/resources/testrepo2/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 deleted file mode 100644 index 5df58dda5..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests-clar/resources/testrepo2/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a deleted file mode 100644 index a79612435..000000000 --- a/tests-clar/resources/testrepo2/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a +++ /dev/null @@ -1,3 +0,0 @@ -x[ -0E*fդ "W0-Ft݁pS[Yx^ -Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests-clar/resources/testrepo2/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests-clar/resources/testrepo2/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f deleted file mode 100644 index f8588696b..000000000 --- a/tests-clar/resources/testrepo2/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f +++ /dev/null @@ -1,2 +0,0 @@ -x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S - U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests-clar/resources/testrepo2/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd b/tests-clar/resources/testrepo2/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd deleted file mode 100644 index d0d7e736e..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 b/tests-clar/resources/testrepo2/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 deleted file mode 100644 index 18a7f61c2..000000000 Binary files a/tests-clar/resources/testrepo2/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 and /dev/null differ diff --git a/tests-clar/resources/testrepo2/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 b/tests-clar/resources/testrepo2/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 deleted file mode 100644 index 0817229bc..000000000 --- a/tests-clar/resources/testrepo2/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 +++ /dev/null @@ -1,3 +0,0 @@ -xKj1D)zUB-0uV9<#+WTKy4`6 ,y9jGJ8b\f5/ ^8v'˜`SƝ%[ -T[[,psL6oK5;n-=D \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/1f/4c0311a24b63f6fc209a59a1e404942d4a5006 b/tests-clar/resources/twowaymerge.git/objects/1f/4c0311a24b63f6fc209a59a1e404942d4a5006 deleted file mode 100644 index 99288fdd7..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/1f/4c0311a24b63f6fc209a59a1e404942d4a5006 +++ /dev/null @@ -1,2 +0,0 @@ -x=0 @aM6BlH m!RqO7[ r5gNXű)Eg]DY2c R8x7 -TRo8~Ӣ[#uj;`7 \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 b/tests-clar/resources/twowaymerge.git/objects/22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 deleted file mode 100644 index 48466ea51..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 +++ /dev/null @@ -1,3 +0,0 @@ -xK -0@]sK& z4HMobY1t[JblɈ4vɡL '՛V`B . -Im 1ZǠxcKh^^+\>?2a.M,tTBp^kucjV_sFh \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/29/6e56023cdc034d2735fee8c0d85a659d1b07f4 b/tests-clar/resources/twowaymerge.git/objects/29/6e56023cdc034d2735fee8c0d85a659d1b07f4 deleted file mode 100644 index aa3fccdf0..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/29/6e56023cdc034d2735fee8c0d85a659d1b07f4 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/31/51880ae2b363f1c262cf98b750c1f169a0d432 b/tests-clar/resources/twowaymerge.git/objects/31/51880ae2b363f1c262cf98b750c1f169a0d432 deleted file mode 100644 index 235d42bff..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/31/51880ae2b363f1c262cf98b750c1f169a0d432 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/3b/287f8730c81d0b763c2d294618a5e32b67b4f8 b/tests-clar/resources/twowaymerge.git/objects/3b/287f8730c81d0b763c2d294618a5e32b67b4f8 deleted file mode 100644 index 56ddac5ee..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/3b/287f8730c81d0b763c2d294618a5e32b67b4f8 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/42/b7311aa626e712891940c1ec5d5cba201946a4 b/tests-clar/resources/twowaymerge.git/objects/42/b7311aa626e712891940c1ec5d5cba201946a4 deleted file mode 100644 index a8e6581f8..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/42/b7311aa626e712891940c1ec5d5cba201946a4 +++ /dev/null @@ -1,3 +0,0 @@ -xν 0@ajOq c"!DDK1 -h_ZʣAC[saȞpI#lBq׼4Z"(yGFd#y[ -X[[J/psL6oAXሂo7ԸEc \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/49/6d6428b9cf92981dc9495211e6e1120fb6f2ba b/tests-clar/resources/twowaymerge.git/objects/49/6d6428b9cf92981dc9495211e6e1120fb6f2ba deleted file mode 100644 index 978bc3448..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/49/6d6428b9cf92981dc9495211e6e1120fb6f2ba and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/59/b0cf7d74659e1cdb13305319d6d4ce2733c118 b/tests-clar/resources/twowaymerge.git/objects/59/b0cf7d74659e1cdb13305319d6d4ce2733c118 deleted file mode 100644 index 30b507c06..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/59/b0cf7d74659e1cdb13305319d6d4ce2733c118 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f b/tests-clar/resources/twowaymerge.git/objects/6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f deleted file mode 100644 index ff6a386ac..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f +++ /dev/null @@ -1 +0,0 @@ -xM0@a=\@2cܙeRܾŗǵRԶ@(i$uO 19Ro" 9x- @cc3;-KvH+9Fe{O{]b +\>oܦ}踖+Hm z(zl7 F- \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 b/tests-clar/resources/twowaymerge.git/objects/6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 deleted file mode 100644 index 9a969a279..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/76/5b32c65d38f04c4f287abda055818ec0f26912 b/tests-clar/resources/twowaymerge.git/objects/76/5b32c65d38f04c4f287abda055818ec0f26912 deleted file mode 100644 index 493bbc076..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/76/5b32c65d38f04c4f287abda055818ec0f26912 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/7b/8c336c45fc6895c1c60827260fe5d798e5d247 b/tests-clar/resources/twowaymerge.git/objects/7b/8c336c45fc6895c1c60827260fe5d798e5d247 deleted file mode 100644 index 19e7ef463..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/7b/8c336c45fc6895c1c60827260fe5d798e5d247 +++ /dev/null @@ -1,3 +0,0 @@ -xA @Qלb.`3 S(1LzB[TzܾϏe -D|kJC3fȵu L>YGMVeMK9Z5H#{EJ: -ϲp:ne>6-sH GծfMS}ZE \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/82/bf9a1a10a4b25c1f14c9607b60970705e92545 b/tests-clar/resources/twowaymerge.git/objects/82/bf9a1a10a4b25c1f14c9607b60970705e92545 deleted file mode 100644 index 89b0b9f9b..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/82/bf9a1a10a4b25c1f14c9607b60970705e92545 +++ /dev/null @@ -1 +0,0 @@ -x 09mh_BܐRןc1-pyPKy4RږDGFJvFE>1#q joimbvSYSbErQ"e{+ޖ=6b+>?/-;3hC#gXyF \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 b/tests-clar/resources/twowaymerge.git/objects/8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 deleted file mode 100644 index 8e9b758ea..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 +++ /dev/null @@ -1,3 +0,0 @@ -xν 0@ajOq 7BtHLp%A8FٟW<= x"ʎ$%1dcDNL:Yv=7yic -l$\b{DbOd9x+ -6T[{ ??yqnӖ:cQZ]͖7H \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/9a/40a2f11c191f180c47e54b11567cb3c1e89b30 b/tests-clar/resources/twowaymerge.git/objects/9a/40a2f11c191f180c47e54b11567cb3c1e89b30 deleted file mode 100644 index 1de1224f7..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/9a/40a2f11c191f180c47e54b11567cb3c1e89b30 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/9b/219343610c88a1187c996d0dc58330b55cee28 b/tests-clar/resources/twowaymerge.git/objects/9b/219343610c88a1187c996d0dc58330b55cee28 deleted file mode 100644 index 8b64b4381..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/9b/219343610c88a1187c996d0dc58330b55cee28 +++ /dev/null @@ -1,2 +0,0 @@ -xKj1ЬFj}Z3 VdFA#?\ zu]FSo"J& ^,9$GEd)7|&[6(FU"&h< Fc4Aƿ>"ZQ;m9\;KP%1b9k93Gkwni[uZ h"RYC[]=0IrKpO: -pʯ _(c \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/9f/e06a50f4d1634d6c6879854d01d80857388706 b/tests-clar/resources/twowaymerge.git/objects/9f/e06a50f4d1634d6c6879854d01d80857388706 deleted file mode 100644 index 055de0158..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/9f/e06a50f4d1634d6c6879854d01d80857388706 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 b/tests-clar/resources/twowaymerge.git/objects/a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 deleted file mode 100644 index cb4d34e77..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 +++ /dev/null @@ -1,3 +0,0 @@ -xν 0@ajOq 7'!DD A$FٟW<=<5Z -8N(CzDž$'2!>[):#Dzǵ, z M d=tNŭ= -wk}9.p9^Ʃ=I@Y =ulD \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 b/tests-clar/resources/twowaymerge.git/objects/a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 deleted file mode 100644 index 8235f1839..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 +++ /dev/null @@ -1 +0,0 @@ -xJ0])nV3$is"ONŶɼ\|8!dz dXG/ޫϹp*CX@Z8|f[V0HDHE]6gI#g*9UEHH!MḦhRuo.{zSײ|үwȾ>14C8;rn8qۿ7kNui~M^ \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c b/tests-clar/resources/twowaymerge.git/objects/a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c deleted file mode 100644 index 4da7e826a..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c +++ /dev/null @@ -1 +0,0 @@ -x+)JMU044c040031QHdx6M9{wk+qIODd6>|X%>9j \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 b/tests-clar/resources/twowaymerge.git/objects/bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 deleted file mode 100644 index b9b60122d..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/c3/7a783c20d92ac92362a78a32860f7eebf938ef b/tests-clar/resources/twowaymerge.git/objects/c3/7a783c20d92ac92362a78a32860f7eebf938ef deleted file mode 100644 index 041e890ab..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/c3/7a783c20d92ac92362a78a32860f7eebf938ef and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/cb/dd40facab1682754eb67f7a43f29e672903cf6 b/tests-clar/resources/twowaymerge.git/objects/cb/dd40facab1682754eb67f7a43f29e672903cf6 deleted file mode 100644 index ccb156d88..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/cb/dd40facab1682754eb67f7a43f29e672903cf6 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 b/tests-clar/resources/twowaymerge.git/objects/cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 deleted file mode 100644 index 0e028dc01..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/d6/f10d549cb335b9e6d38afc1f0088be69b50494 b/tests-clar/resources/twowaymerge.git/objects/d6/f10d549cb335b9e6d38afc1f0088be69b50494 deleted file mode 100644 index b298c520e..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/d6/f10d549cb335b9e6d38afc1f0088be69b50494 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e b/tests-clar/resources/twowaymerge.git/objects/d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e deleted file mode 100644 index de94528a4..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e +++ /dev/null @@ -1 +0,0 @@ -x+)JMU044c040031QHdx6M9{wk+qIODd>4|X%:79U \ No newline at end of file diff --git a/tests-clar/resources/twowaymerge.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/tests-clar/resources/twowaymerge.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 deleted file mode 100644 index 711223894..000000000 Binary files a/tests-clar/resources/twowaymerge.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 and /dev/null differ diff --git a/tests-clar/resources/twowaymerge.git/objects/ef/0488f0b722f0be8bcb90a7730ac7efafd1d694 b/tests-clar/resources/twowaymerge.git/objects/ef/0488f0b722f0be8bcb90a7730ac7efafd1d694 deleted file mode 100644 index 00f7d3615..000000000 --- a/tests-clar/resources/twowaymerge.git/objects/ef/0488f0b722f0be8bcb90a7730ac7efafd1d694 +++ /dev/null @@ -1 +0,0 @@ -xM F]s0_cܙ@H1_ۗ}yh@mK 8Y4Ѩt^'`lPىڠks*? |m“i@mV'`).-1 x -uxt(+ \ No newline at end of file diff --git a/tests-clar/resources/typechanges/.gitted/modules/b/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests-clar/resources/typechanges/.gitted/modules/b/objects/78/9efbdadaa4a582778d4584385495559ea0994b deleted file mode 100644 index 17458840b..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/b/objects/78/9efbdadaa4a582778d4584385495559ea0994b +++ /dev/null @@ -1,2 +0,0 @@ -x 0 )?= NlOkj8&r -qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests-clar/resources/typechanges/.gitted/modules/b/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests-clar/resources/typechanges/.gitted/modules/b/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e deleted file mode 100644 index 83cc29fb1..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/b/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/b/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests-clar/resources/typechanges/.gitted/modules/b/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 deleted file mode 100644 index 55bda40ef..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/b/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/b/packed-refs b/tests-clar/resources/typechanges/.gitted/modules/b/packed-refs deleted file mode 100644 index 5a4ebc47c..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/b/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests-clar/resources/typechanges/.gitted/modules/b/refs/heads/master b/tests-clar/resources/typechanges/.gitted/modules/b/refs/heads/master deleted file mode 100644 index e12c44d7a..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/b/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests-clar/resources/typechanges/.gitted/modules/b/refs/remotes/origin/HEAD b/tests-clar/resources/typechanges/.gitted/modules/b/refs/remotes/origin/HEAD deleted file mode 100644 index 6efe28fff..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/b/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/remotes/origin/master diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/HEAD b/tests-clar/resources/typechanges/.gitted/modules/d/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/d/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/config b/tests-clar/resources/typechanges/.gitted/modules/d/config deleted file mode 100644 index 42e1bddda..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/d/config +++ /dev/null @@ -1,13 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - worktree = ../../../d - ignorecase = true -[remote "origin"] - fetch = +refs/heads/*:refs/remotes/origin/* - url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target/.git -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/description b/tests-clar/resources/typechanges/.gitted/modules/d/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/d/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/index b/tests-clar/resources/typechanges/.gitted/modules/d/index deleted file mode 100644 index 86d0266e8..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/d/index and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/info/exclude b/tests-clar/resources/typechanges/.gitted/modules/d/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/d/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests-clar/resources/typechanges/.gitted/modules/d/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 deleted file mode 100644 index f4b7094c5..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/d/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests-clar/resources/typechanges/.gitted/modules/d/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 deleted file mode 100644 index 56c845e49..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/d/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests-clar/resources/typechanges/.gitted/modules/d/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 deleted file mode 100644 index bd179b5f5..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/d/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests-clar/resources/typechanges/.gitted/modules/d/objects/41/bd4bc3df978de695f67ace64c560913da11653 deleted file mode 100644 index ccf49bd15..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/d/objects/41/bd4bc3df978de695f67ace64c560913da11653 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests-clar/resources/typechanges/.gitted/modules/d/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 deleted file mode 100644 index 53029069a..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/d/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests-clar/resources/typechanges/.gitted/modules/d/objects/5e/4963595a9774b90524d35a807169049de8ccad deleted file mode 100644 index 38c791eba..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/d/objects/5e/4963595a9774b90524d35a807169049de8ccad and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests-clar/resources/typechanges/.gitted/modules/d/objects/6b/31c659545507c381e9cd34ec508f16c04e149e deleted file mode 100644 index a26d29993..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/d/objects/6b/31c659545507c381e9cd34ec508f16c04e149e +++ /dev/null @@ -1,2 +0,0 @@ -xQ -!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests-clar/resources/typechanges/.gitted/modules/d/objects/73/ba924a80437097795ae839e66e187c55d3babf deleted file mode 100644 index 83d1ba481..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/d/objects/73/ba924a80437097795ae839e66e187c55d3babf and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests-clar/resources/typechanges/.gitted/modules/d/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a deleted file mode 100644 index 6d27af8a8..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/d/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a +++ /dev/null @@ -1,2 +0,0 @@ -x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x -uxt(+ \ No newline at end of file diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests-clar/resources/typechanges/.gitted/modules/d/objects/78/9efbdadaa4a582778d4584385495559ea0994b deleted file mode 100644 index 17458840b..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/d/objects/78/9efbdadaa4a582778d4584385495559ea0994b +++ /dev/null @@ -1,2 +0,0 @@ -x 0 )?= NlOkj8&r -qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests-clar/resources/typechanges/.gitted/modules/d/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e deleted file mode 100644 index 83cc29fb1..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/d/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests-clar/resources/typechanges/.gitted/modules/d/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 deleted file mode 100644 index 55bda40ef..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/d/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/packed-refs b/tests-clar/resources/typechanges/.gitted/modules/d/packed-refs deleted file mode 100644 index 5a4ebc47c..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/d/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/refs/heads/master b/tests-clar/resources/typechanges/.gitted/modules/d/refs/heads/master deleted file mode 100644 index e12c44d7a..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/d/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests-clar/resources/typechanges/.gitted/modules/d/refs/remotes/origin/HEAD b/tests-clar/resources/typechanges/.gitted/modules/d/refs/remotes/origin/HEAD deleted file mode 100644 index 6efe28fff..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/d/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/remotes/origin/master diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/HEAD b/tests-clar/resources/typechanges/.gitted/modules/e/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/e/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/config b/tests-clar/resources/typechanges/.gitted/modules/e/config deleted file mode 100644 index 89b3b9b4f..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/e/config +++ /dev/null @@ -1,13 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = false - logallrefupdates = true - worktree = ../../../e - ignorecase = true -[remote "origin"] - fetch = +refs/heads/*:refs/remotes/origin/* - url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target/.git -[branch "master"] - remote = origin - merge = refs/heads/master diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/description b/tests-clar/resources/typechanges/.gitted/modules/e/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/e/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/index b/tests-clar/resources/typechanges/.gitted/modules/e/index deleted file mode 100644 index cd6e2da6c..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/e/index and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/info/exclude b/tests-clar/resources/typechanges/.gitted/modules/e/info/exclude deleted file mode 100644 index a5196d1be..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/e/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests-clar/resources/typechanges/.gitted/modules/e/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 deleted file mode 100644 index f4b7094c5..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/e/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests-clar/resources/typechanges/.gitted/modules/e/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 deleted file mode 100644 index 56c845e49..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/e/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests-clar/resources/typechanges/.gitted/modules/e/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 deleted file mode 100644 index bd179b5f5..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/e/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests-clar/resources/typechanges/.gitted/modules/e/objects/41/bd4bc3df978de695f67ace64c560913da11653 deleted file mode 100644 index ccf49bd15..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/e/objects/41/bd4bc3df978de695f67ace64c560913da11653 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests-clar/resources/typechanges/.gitted/modules/e/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 deleted file mode 100644 index 53029069a..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/e/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests-clar/resources/typechanges/.gitted/modules/e/objects/5e/4963595a9774b90524d35a807169049de8ccad deleted file mode 100644 index 38c791eba..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/e/objects/5e/4963595a9774b90524d35a807169049de8ccad and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests-clar/resources/typechanges/.gitted/modules/e/objects/6b/31c659545507c381e9cd34ec508f16c04e149e deleted file mode 100644 index a26d29993..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/e/objects/6b/31c659545507c381e9cd34ec508f16c04e149e +++ /dev/null @@ -1,2 +0,0 @@ -xQ -!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests-clar/resources/typechanges/.gitted/modules/e/objects/73/ba924a80437097795ae839e66e187c55d3babf deleted file mode 100644 index 83d1ba481..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/e/objects/73/ba924a80437097795ae839e66e187c55d3babf and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests-clar/resources/typechanges/.gitted/modules/e/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a deleted file mode 100644 index 6d27af8a8..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/e/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a +++ /dev/null @@ -1,2 +0,0 @@ -x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x -uxt(+ \ No newline at end of file diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests-clar/resources/typechanges/.gitted/modules/e/objects/78/9efbdadaa4a582778d4584385495559ea0994b deleted file mode 100644 index 17458840b..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/e/objects/78/9efbdadaa4a582778d4584385495559ea0994b +++ /dev/null @@ -1,2 +0,0 @@ -x 0 )?= NlOkj8&r -qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests-clar/resources/typechanges/.gitted/modules/e/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e deleted file mode 100644 index 83cc29fb1..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/e/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests-clar/resources/typechanges/.gitted/modules/e/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 deleted file mode 100644 index 55bda40ef..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/modules/e/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/packed-refs b/tests-clar/resources/typechanges/.gitted/modules/e/packed-refs deleted file mode 100644 index 5a4ebc47c..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/e/packed-refs +++ /dev/null @@ -1,2 +0,0 @@ -# pack-refs with: peeled -480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/refs/heads/master b/tests-clar/resources/typechanges/.gitted/modules/e/refs/heads/master deleted file mode 100644 index e12c44d7a..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/e/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests-clar/resources/typechanges/.gitted/modules/e/refs/remotes/origin/HEAD b/tests-clar/resources/typechanges/.gitted/modules/e/refs/remotes/origin/HEAD deleted file mode 100644 index 6efe28fff..000000000 --- a/tests-clar/resources/typechanges/.gitted/modules/e/refs/remotes/origin/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/remotes/origin/master diff --git a/tests-clar/resources/typechanges/.gitted/objects/0d/78578795b7ca49fd8df6c4b6d27c5c02d991d8 b/tests-clar/resources/typechanges/.gitted/objects/0d/78578795b7ca49fd8df6c4b6d27c5c02d991d8 deleted file mode 100644 index f2d02f4f7..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/0d/78578795b7ca49fd8df6c4b6d27c5c02d991d8 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/0e/7ed140b514b8cae23254cb8656fe1674403aff b/tests-clar/resources/typechanges/.gitted/objects/0e/7ed140b514b8cae23254cb8656fe1674403aff deleted file mode 100644 index 527964c92..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/0e/7ed140b514b8cae23254cb8656fe1674403aff and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/0f/f461da9689266f482d8f6654a4400b4e33c586 b/tests-clar/resources/typechanges/.gitted/objects/0f/f461da9689266f482d8f6654a4400b4e33c586 deleted file mode 100644 index 2694e4fa0..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/0f/f461da9689266f482d8f6654a4400b4e33c586 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/18/aa7e45bbe4c3cc24a0b079696c59d36675af97 b/tests-clar/resources/typechanges/.gitted/objects/18/aa7e45bbe4c3cc24a0b079696c59d36675af97 deleted file mode 100644 index 032a960b4..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/18/aa7e45bbe4c3cc24a0b079696c59d36675af97 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/1b/63caae4a5ca96f78e8dfefc376c6a39a142475 b/tests-clar/resources/typechanges/.gitted/objects/1b/63caae4a5ca96f78e8dfefc376c6a39a142475 deleted file mode 100644 index d32622e67..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/1b/63caae4a5ca96f78e8dfefc376c6a39a142475 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/1e/abe82aa3b2365a394f6108f24435df6e193d02 b/tests-clar/resources/typechanges/.gitted/objects/1e/abe82aa3b2365a394f6108f24435df6e193d02 deleted file mode 100644 index 42d5f92f3..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/1e/abe82aa3b2365a394f6108f24435df6e193d02 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/42/061c01a1c70097d1e4579f29a5adf40abdec95 b/tests-clar/resources/typechanges/.gitted/objects/42/061c01a1c70097d1e4579f29a5adf40abdec95 deleted file mode 100644 index 0a8f32e15..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/42/061c01a1c70097d1e4579f29a5adf40abdec95 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/46/2838cee476a87e7cff32196b66fa18ed756592 b/tests-clar/resources/typechanges/.gitted/objects/46/2838cee476a87e7cff32196b66fa18ed756592 deleted file mode 100644 index 52af51f74..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/46/2838cee476a87e7cff32196b66fa18ed756592 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/63/499e4ea8e096b831515ceb1d5a7593e4d87ae5 b/tests-clar/resources/typechanges/.gitted/objects/63/499e4ea8e096b831515ceb1d5a7593e4d87ae5 deleted file mode 100644 index afafa89f4..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/63/499e4ea8e096b831515ceb1d5a7593e4d87ae5 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/68/1af94e10eaf262f3ab7cb9b8fd5f4158ba4d3e b/tests-clar/resources/typechanges/.gitted/objects/68/1af94e10eaf262f3ab7cb9b8fd5f4158ba4d3e deleted file mode 100644 index 9e518fc28..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/68/1af94e10eaf262f3ab7cb9b8fd5f4158ba4d3e and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/6a/9008602b811e69a9b7a2d83496f39a794fdeeb b/tests-clar/resources/typechanges/.gitted/objects/6a/9008602b811e69a9b7a2d83496f39a794fdeeb deleted file mode 100644 index a245727a1..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/6a/9008602b811e69a9b7a2d83496f39a794fdeeb and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/6e/ae26c90e8ccc4d16208972119c40635489c6f0 b/tests-clar/resources/typechanges/.gitted/objects/6e/ae26c90e8ccc4d16208972119c40635489c6f0 deleted file mode 100644 index ea35cd311..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/6e/ae26c90e8ccc4d16208972119c40635489c6f0 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/6f/39eabbb8a7541515e0d35971078bccb502e7e0 b/tests-clar/resources/typechanges/.gitted/objects/6f/39eabbb8a7541515e0d35971078bccb502e7e0 deleted file mode 100644 index c54817598..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/6f/39eabbb8a7541515e0d35971078bccb502e7e0 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/71/54d3083461536dfc71ad5542f3e65e723a06c4 b/tests-clar/resources/typechanges/.gitted/objects/71/54d3083461536dfc71ad5542f3e65e723a06c4 deleted file mode 100644 index 9fdd8f245..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/71/54d3083461536dfc71ad5542f3e65e723a06c4 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/75/56c1d893a4c0ca85ac8ac51de47ff399758729 b/tests-clar/resources/typechanges/.gitted/objects/75/56c1d893a4c0ca85ac8ac51de47ff399758729 deleted file mode 100644 index d43630f44..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/75/56c1d893a4c0ca85ac8ac51de47ff399758729 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/76/fef844064c26d5e06c2508240dae661e7231b2 b/tests-clar/resources/typechanges/.gitted/objects/76/fef844064c26d5e06c2508240dae661e7231b2 deleted file mode 100644 index 355ce4b5b..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/76/fef844064c26d5e06c2508240dae661e7231b2 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/79/b9f23e85f55ea36a472a902e875bc1121a94cb b/tests-clar/resources/typechanges/.gitted/objects/79/b9f23e85f55ea36a472a902e875bc1121a94cb deleted file mode 100644 index 2b07ad256..000000000 --- a/tests-clar/resources/typechanges/.gitted/objects/79/b9f23e85f55ea36a472a902e875bc1121a94cb +++ /dev/null @@ -1,2 +0,0 @@ -xA E]sfJbq `I@ -yH;ZeBr6LPY%8&v4Jm֢^*qpJµ;Z Ơ3ZD1)"%%38_ \ No newline at end of file diff --git a/tests-clar/resources/typechanges/.gitted/objects/85/28da0ea65eacf1f74f9ed6696adbac547963ad b/tests-clar/resources/typechanges/.gitted/objects/85/28da0ea65eacf1f74f9ed6696adbac547963ad deleted file mode 100644 index 6d2da6c93..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/85/28da0ea65eacf1f74f9ed6696adbac547963ad and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/8b/3726b365824ad5a07c537247f4bc73ed7d37ea b/tests-clar/resources/typechanges/.gitted/objects/8b/3726b365824ad5a07c537247f4bc73ed7d37ea deleted file mode 100644 index 3dc333bc6..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/8b/3726b365824ad5a07c537247f4bc73ed7d37ea and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/93/3e28c1c8a68838a763d250bdf0b2c6068289c3 b/tests-clar/resources/typechanges/.gitted/objects/93/3e28c1c8a68838a763d250bdf0b2c6068289c3 deleted file mode 100644 index 02ad0e97a..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/93/3e28c1c8a68838a763d250bdf0b2c6068289c3 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/96/2710fe5b4e453e9e827945b3487c525968ec4a b/tests-clar/resources/typechanges/.gitted/objects/96/2710fe5b4e453e9e827945b3487c525968ec4a deleted file mode 100644 index d06b06a52..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/96/2710fe5b4e453e9e827945b3487c525968ec4a and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/96/6cf1b3598e195b31b2cde3784f9a19f0728a6f b/tests-clar/resources/typechanges/.gitted/objects/96/6cf1b3598e195b31b2cde3784f9a19f0728a6f deleted file mode 100644 index 5f9ffd4ed..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/96/6cf1b3598e195b31b2cde3784f9a19f0728a6f and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/99/e8bab9ece009f0fba7eb41f850f4c12bedb9b7 b/tests-clar/resources/typechanges/.gitted/objects/99/e8bab9ece009f0fba7eb41f850f4c12bedb9b7 deleted file mode 100644 index ac17defac..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/99/e8bab9ece009f0fba7eb41f850f4c12bedb9b7 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/9b/19edf33a03a0c59cdfc113bfa5c06179bf9b1a b/tests-clar/resources/typechanges/.gitted/objects/9b/19edf33a03a0c59cdfc113bfa5c06179bf9b1a deleted file mode 100644 index 7ab83aefe..000000000 --- a/tests-clar/resources/typechanges/.gitted/objects/9b/19edf33a03a0c59cdfc113bfa5c06179bf9b1a +++ /dev/null @@ -1,5 +0,0 @@ -xI -1E]LT AJЃ7WpyӶ,ZѩUf cXcR C43Y2"NN:HɈo6,sjf#kG -cys -MGm2B -.K)k֑w8CC \ No newline at end of file diff --git a/tests-clar/resources/typechanges/.gitted/objects/9b/db75b73836a99e3dbeea640a81de81031fdc29 b/tests-clar/resources/typechanges/.gitted/objects/9b/db75b73836a99e3dbeea640a81de81031fdc29 deleted file mode 100644 index aed4d8165..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/9b/db75b73836a99e3dbeea640a81de81031fdc29 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/9d/0235c7a7edc0889a18f97a42ee6db9fe688447 b/tests-clar/resources/typechanges/.gitted/objects/9d/0235c7a7edc0889a18f97a42ee6db9fe688447 deleted file mode 100644 index 3e02a41b2..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/9d/0235c7a7edc0889a18f97a42ee6db9fe688447 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/9e/ffc457877f109b2a4319e14bee613a15f2a00d b/tests-clar/resources/typechanges/.gitted/objects/9e/ffc457877f109b2a4319e14bee613a15f2a00d deleted file mode 100644 index fb24100fc..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/9e/ffc457877f109b2a4319e14bee613a15f2a00d and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/a0/a9bad6f6f40325198f938a0e3ae981622d7707 b/tests-clar/resources/typechanges/.gitted/objects/a0/a9bad6f6f40325198f938a0e3ae981622d7707 deleted file mode 100644 index b6b7db785..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/a0/a9bad6f6f40325198f938a0e3ae981622d7707 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/b1/977dc4e573b812d4619754c98138c56999dc0d b/tests-clar/resources/typechanges/.gitted/objects/b1/977dc4e573b812d4619754c98138c56999dc0d deleted file mode 100644 index e1334057c..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/b1/977dc4e573b812d4619754c98138c56999dc0d and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/d7/5992dd02391e128dac332dcc78d649dd9ab095 b/tests-clar/resources/typechanges/.gitted/objects/d7/5992dd02391e128dac332dcc78d649dd9ab095 deleted file mode 100644 index 65f1f530f..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/d7/5992dd02391e128dac332dcc78d649dd9ab095 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/da/e2709d638df52212b1f43ff61797ebfedfcc7c b/tests-clar/resources/typechanges/.gitted/objects/da/e2709d638df52212b1f43ff61797ebfedfcc7c deleted file mode 100644 index 355faa61f..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/da/e2709d638df52212b1f43ff61797ebfedfcc7c and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/e1/152adcb9adf37ec551ada9ba377ab53aec3bad b/tests-clar/resources/typechanges/.gitted/objects/e1/152adcb9adf37ec551ada9ba377ab53aec3bad deleted file mode 100644 index c68fdcfab..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/e1/152adcb9adf37ec551ada9ba377ab53aec3bad and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/e4/ed436a9eb0f198cda722886a5f8d6d6c836b7b b/tests-clar/resources/typechanges/.gitted/objects/e4/ed436a9eb0f198cda722886a5f8d6d6c836b7b deleted file mode 100644 index c9229ba25..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/e4/ed436a9eb0f198cda722886a5f8d6d6c836b7b and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/tests-clar/resources/typechanges/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 deleted file mode 100644 index 711223894..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/f2/0b79342712e0b2315647cd8227a573fd3bc46e b/tests-clar/resources/typechanges/.gitted/objects/f2/0b79342712e0b2315647cd8227a573fd3bc46e deleted file mode 100644 index 3962ba6b4..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/f2/0b79342712e0b2315647cd8227a573fd3bc46e and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/objects/fd/e0147e3b59f381635a3b016e3fe6dacb70779d b/tests-clar/resources/typechanges/.gitted/objects/fd/e0147e3b59f381635a3b016e3fe6dacb70779d deleted file mode 100644 index e3663da9f..000000000 Binary files a/tests-clar/resources/typechanges/.gitted/objects/fd/e0147e3b59f381635a3b016e3fe6dacb70779d and /dev/null differ diff --git a/tests-clar/resources/typechanges/.gitted/refs/heads/master b/tests-clar/resources/typechanges/.gitted/refs/heads/master deleted file mode 100644 index 546481a33..000000000 --- a/tests-clar/resources/typechanges/.gitted/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -6eae26c90e8ccc4d16208972119c40635489c6f0 diff --git a/tests-clar/resources/typechanges/README.md b/tests-clar/resources/typechanges/README.md deleted file mode 100644 index 1f5a95a9f..000000000 --- a/tests-clar/resources/typechanges/README.md +++ /dev/null @@ -1,43 +0,0 @@ -This is a test repo for libgit2 where tree entries have type changes - -Types ------ - -The key types that could be found in tree entries are: - -1. GIT_FILEMODE_NEW = 0000000 (i.e. file does not exist) -2. GIT_FILEMODE_TREE = 0040000 -3. GIT_FILEMODE_BLOB = 0100644 -4. GIT_FILEMODE_BLOB_EXECUTABLE = 0100755 -5. GIT_FILEMODE_LINK = 0120000 -6. GIT_FILEMODE_COMMIT = 0160000 - -I will try to have every type of transition somewhere in the history -of this repo. - -Commits -------- - -* `a(1--1) b(1--1) c(1--1) d(1--1) e(1--1)` - **Initial commit**
- `79b9f23e85f55ea36a472a902e875bc1121a94cb` -* `a(1->2) b(1->3) c(1->4) d(1->5) e(1->6)` - **Create content**
- `9bdb75b73836a99e3dbeea640a81de81031fdc29` -* `a(2->3) b(3->4) c(4->5) d(5->6) e(6->2)` - **Changes #1**
- `0e7ed140b514b8cae23254cb8656fe1674403aff` -* `a(3->5) b(4->6) c(5->2) d(6->3) e(2->4)` - **Changes #2**
- `9d0235c7a7edc0889a18f97a42ee6db9fe688447` -* `a(5->3) b(6->4) c(2->5) d(3->6) e(4->2)` - **Changes #3**
- `9b19edf33a03a0c59cdfc113bfa5c06179bf9b1a` -* `a(3->2) b(4->3) c(5->4) d(6->5) e(2->6)` - **Changes #4**
- `1b63caae4a5ca96f78e8dfefc376c6a39a142475`
- Matches **Changes #1** except README.md -* `a(2->1) b(3->1) c(4->1) d(5->1) e(6->1)` - **Changes #5**
- `6eae26c90e8ccc4d16208972119c40635489c6f0`
- Matches **Initial commit** except README.md and .gitmodules diff --git a/tests-clar/resources/typechanges/gitmodules b/tests-clar/resources/typechanges/gitmodules deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests-clar/resources/unsymlinked.git/HEAD b/tests-clar/resources/unsymlinked.git/HEAD deleted file mode 100644 index cb089cd89..000000000 --- a/tests-clar/resources/unsymlinked.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/tests-clar/resources/unsymlinked.git/config b/tests-clar/resources/unsymlinked.git/config deleted file mode 100644 index f57351fd5..000000000 --- a/tests-clar/resources/unsymlinked.git/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - bare = true - repositoryformatversion = 0 - filemode = false - logallrefupdates = true - ignorecase = true diff --git a/tests-clar/resources/unsymlinked.git/description b/tests-clar/resources/unsymlinked.git/description deleted file mode 100644 index 498b267a8..000000000 --- a/tests-clar/resources/unsymlinked.git/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/unsymlinked.git/info/exclude b/tests-clar/resources/unsymlinked.git/info/exclude deleted file mode 100644 index 6d05881d3..000000000 --- a/tests-clar/resources/unsymlinked.git/info/exclude +++ /dev/null @@ -1,2 +0,0 @@ -# File patterns to ignore; see `git help ignore` for more information. -# Lines that start with '#' are comments. diff --git a/tests-clar/resources/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf b/tests-clar/resources/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf deleted file mode 100644 index 953262fa9..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b b/tests-clar/resources/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b deleted file mode 100644 index 91ec8fa5e..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c b/tests-clar/resources/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c deleted file mode 100644 index 94afd01e8..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 b/tests-clar/resources/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 deleted file mode 100644 index 5b33d027c..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c b/tests-clar/resources/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c deleted file mode 100644 index 67eb14930..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 b/tests-clar/resources/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 deleted file mode 100644 index c1ea0de75..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d b/tests-clar/resources/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d deleted file mode 100644 index 028505563..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 b/tests-clar/resources/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 deleted file mode 100644 index e866a75a6..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 b/tests-clar/resources/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 deleted file mode 100644 index 189ab044d..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 b/tests-clar/resources/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 deleted file mode 100644 index a2ef6be45..000000000 --- a/tests-clar/resources/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 +++ /dev/null @@ -1,2 +0,0 @@ -x[ -0E*_y݀{4ShZ))| N[ks=KߙŚ[Q"4&&M*i/޴!1S*AGt)-'Um7O ccչ=z崵;(PY+*Dq^E!*/0}Z?<P慥Jp \ No newline at end of file diff --git a/tests-clar/resources/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 b/tests-clar/resources/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 deleted file mode 100644 index ec274cb1d..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a b/tests-clar/resources/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a deleted file mode 100644 index c1b6a5101..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 b/tests-clar/resources/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 deleted file mode 100644 index ad751adbe..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 b/tests-clar/resources/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 deleted file mode 100644 index f87cd42fb..000000000 Binary files a/tests-clar/resources/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 and /dev/null differ diff --git a/tests-clar/resources/unsymlinked.git/refs/heads/exe-file b/tests-clar/resources/unsymlinked.git/refs/heads/exe-file deleted file mode 100644 index b96ef46ca..000000000 --- a/tests-clar/resources/unsymlinked.git/refs/heads/exe-file +++ /dev/null @@ -1 +0,0 @@ -a8595ccca04f40818ae0155c8f9c77a230e597b6 diff --git a/tests-clar/resources/unsymlinked.git/refs/heads/master b/tests-clar/resources/unsymlinked.git/refs/heads/master deleted file mode 100644 index 96c17ab17..000000000 --- a/tests-clar/resources/unsymlinked.git/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -7fccd75616ec188b8f1b23d67506a334cc34a49d diff --git a/tests-clar/resources/unsymlinked.git/refs/heads/reg-file b/tests-clar/resources/unsymlinked.git/refs/heads/reg-file deleted file mode 100644 index b428c00d5..000000000 --- a/tests-clar/resources/unsymlinked.git/refs/heads/reg-file +++ /dev/null @@ -1 +0,0 @@ -806999882bf91d24241e4077906b9017605eb1f3 diff --git a/tests-clar/revwalk/basic.c b/tests-clar/revwalk/basic.c deleted file mode 100644 index 6d55aed54..000000000 --- a/tests-clar/revwalk/basic.c +++ /dev/null @@ -1,254 +0,0 @@ -#include "clar_libgit2.h" - -/* - * a4a7dce [0] Merge branch 'master' into br2 - |\ - | * 9fd738e [1] a fourth commit - | * 4a202b3 [2] a third commit - * | c47800c [3] branch commit one - |/ - * 5b5b025 [5] another commit - * 8496071 [4] testing -*/ -static const char *commit_head = "a4a7dce85cf63874e984719f4fdd239f5145052f"; - -static const char *commit_ids[] = { - "a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */ - "9fd738e8f7967c078dceed8190330fc8648ee56a", /* 1 */ - "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", /* 2 */ - "c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */ - "8496071c1b46c854b31185ea97743be6a8774479", /* 4 */ - "5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */ -}; - -/* Careful: there are two possible topological sorts */ -static const int commit_sorting_topo[][6] = { - {0, 1, 2, 3, 5, 4}, {0, 3, 1, 2, 5, 4} -}; - -static const int commit_sorting_time[][6] = { - {0, 3, 1, 2, 5, 4} -}; - -static const int commit_sorting_topo_reverse[][6] = { - {4, 5, 3, 2, 1, 0}, {4, 5, 2, 1, 3, 0} -}; - -static const int commit_sorting_time_reverse[][6] = { - {4, 5, 2, 1, 3, 0} -}; - -static const int commit_sorting_segment[][6] = { - {1, 2, -1, -1, -1, -1} -}; - -#define commit_count 6 -static const int result_bytes = 24; - - -static int get_commit_index(git_oid *raw_oid) -{ - int i; - char oid[40]; - - git_oid_fmt(oid, raw_oid); - - for (i = 0; i < commit_count; ++i) - if (memcmp(oid, commit_ids[i], 40) == 0) - return i; - - return -1; -} - -static int test_walk_only(git_revwalk *walk, - const int possible_results[][commit_count], int results_count) -{ - git_oid oid; - int i; - int result_array[commit_count]; - - for (i = 0; i < commit_count; ++i) - result_array[i] = -1; - - i = 0; - while (git_revwalk_next(&oid, walk) == 0) { - result_array[i++] = get_commit_index(&oid); - /*{ - char str[41]; - git_oid_fmt(str, &oid); - str[40] = 0; - printf(" %d) %s\n", i, str); - }*/ - } - - for (i = 0; i < results_count; ++i) - if (memcmp(possible_results[i], - result_array, result_bytes) == 0) - return 0; - - return GIT_ERROR; -} - -static int test_walk(git_revwalk *walk, const git_oid *root, - int flags, const int possible_results[][6], int results_count) -{ - git_revwalk_sorting(walk, flags); - git_revwalk_push(walk, root); - - return test_walk_only(walk, possible_results, results_count); -} - -static git_repository *_repo = NULL; -static git_revwalk *_walk = NULL; -static const char *_fixture = NULL; - -void test_revwalk_basic__initialize(void) -{ -} - -void test_revwalk_basic__cleanup(void) -{ - git_revwalk_free(_walk); - - if (_fixture) - cl_git_sandbox_cleanup(); - else - git_repository_free(_repo); - - _fixture = NULL; - _repo = NULL; - _walk = NULL; -} - -static void revwalk_basic_setup_walk(const char *fixture) -{ - if (fixture) { - _fixture = fixture; - _repo = cl_git_sandbox_init(fixture); - } else { - cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); - } - - cl_git_pass(git_revwalk_new(&_walk, _repo)); -} - -void test_revwalk_basic__sorting_modes(void) -{ - git_oid id; - - revwalk_basic_setup_walk(NULL); - - git_oid_fromstr(&id, commit_head); - - cl_git_pass(test_walk(_walk, &id, GIT_SORT_TIME, commit_sorting_time, 1)); - cl_git_pass(test_walk(_walk, &id, GIT_SORT_TOPOLOGICAL, commit_sorting_topo, 2)); - cl_git_pass(test_walk(_walk, &id, GIT_SORT_TIME | GIT_SORT_REVERSE, commit_sorting_time_reverse, 1)); - cl_git_pass(test_walk(_walk, &id, GIT_SORT_TOPOLOGICAL | GIT_SORT_REVERSE, commit_sorting_topo_reverse, 2)); -} - -void test_revwalk_basic__glob_heads(void) -{ - int i = 0; - git_oid oid; - - revwalk_basic_setup_walk(NULL); - - cl_git_pass(git_revwalk_push_glob(_walk, "heads")); - - while (git_revwalk_next(&oid, _walk) == 0) { - i++; - } - - /* git log --branches --oneline | wc -l => 14 */ - cl_assert(i == 14); -} - -void test_revwalk_basic__glob_heads_with_invalid(void) -{ - int i; - git_oid oid; - - revwalk_basic_setup_walk("testrepo"); - - cl_git_mkfile("testrepo/.git/refs/heads/garbage", "not-a-ref"); - cl_git_pass(git_revwalk_push_glob(_walk, "heads")); - - for (i = 0; !git_revwalk_next(&oid, _walk); ++i) - /* walking */; - - /* git log --branches --oneline | wc -l => 16 */ - cl_assert_equal_i(17, i); -} - -void test_revwalk_basic__push_head(void) -{ - int i = 0; - git_oid oid; - - revwalk_basic_setup_walk(NULL); - - cl_git_pass(git_revwalk_push_head(_walk)); - - while (git_revwalk_next(&oid, _walk) == 0) { - i++; - } - - /* git log HEAD --oneline | wc -l => 7 */ - cl_assert(i == 7); -} - -void test_revwalk_basic__push_head_hide_ref(void) -{ - int i = 0; - git_oid oid; - - revwalk_basic_setup_walk(NULL); - - cl_git_pass(git_revwalk_push_head(_walk)); - cl_git_pass(git_revwalk_hide_ref(_walk, "refs/heads/packed-test")); - - while (git_revwalk_next(&oid, _walk) == 0) { - i++; - } - - /* git log HEAD --oneline --not refs/heads/packed-test | wc -l => 4 */ - cl_assert(i == 4); -} - -void test_revwalk_basic__push_head_hide_ref_nobase(void) -{ - int i = 0; - git_oid oid; - - revwalk_basic_setup_walk(NULL); - - cl_git_pass(git_revwalk_push_head(_walk)); - cl_git_pass(git_revwalk_hide_ref(_walk, "refs/heads/packed")); - - while (git_revwalk_next(&oid, _walk) == 0) { - i++; - } - - /* git log HEAD --oneline --not refs/heads/packed | wc -l => 7 */ - cl_assert(i == 7); -} - -void test_revwalk_basic__disallow_non_commit(void) -{ - git_oid oid; - - revwalk_basic_setup_walk(NULL); - - cl_git_pass(git_oid_fromstr(&oid, "521d87c1ec3aef9824daf6d96cc0ae3710766d91")); - cl_git_fail(git_revwalk_push(_walk, &oid)); -} - -void test_revwalk_basic__push_range(void) -{ - revwalk_basic_setup_walk(NULL); - - git_revwalk_reset(_walk); - git_revwalk_sorting(_walk, 0); - cl_git_pass(git_revwalk_push_range(_walk, "9fd738e~2..9fd738e")); - cl_git_pass(test_walk_only(_walk, commit_sorting_segment, 1)); -} diff --git a/tests-clar/revwalk/mergebase.c b/tests-clar/revwalk/mergebase.c deleted file mode 100644 index 2d01647fd..000000000 --- a/tests-clar/revwalk/mergebase.c +++ /dev/null @@ -1,392 +0,0 @@ -#include "clar_libgit2.h" -#include "vector.h" -#include - -static git_repository *_repo; -static git_repository *_repo2; - -void test_revwalk_mergebase__initialize(void) -{ - cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_repository_open(&_repo2, cl_fixture("twowaymerge.git"))); -} - -void test_revwalk_mergebase__cleanup(void) -{ - git_repository_free(_repo); - _repo = NULL; - - git_repository_free(_repo2); - _repo2 = NULL; -} - -void test_revwalk_mergebase__single1(void) -{ - git_oid result, one, two, expected; - size_t ahead, behind; - - cl_git_pass(git_oid_fromstr(&one, "c47800c7266a2be04c571c04d5a6614691ea99bd ")); - cl_git_pass(git_oid_fromstr(&two, "9fd738e8f7967c078dceed8190330fc8648ee56a")); - cl_git_pass(git_oid_fromstr(&expected, "5b5b025afb0b4c913b4c338a42934a3863bf3644")); - - cl_git_pass(git_merge_base(&result, _repo, &one, &two)); - cl_assert(git_oid_cmp(&result, &expected) == 0); - - cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); - cl_assert_equal_sz(ahead, 2); - cl_assert_equal_sz(behind, 1); - - cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &two, &one)); - cl_assert_equal_sz(ahead, 1); - cl_assert_equal_sz(behind, 2); -} - -void test_revwalk_mergebase__single2(void) -{ - git_oid result, one, two, expected; - size_t ahead, behind; - - cl_git_pass(git_oid_fromstr(&one, "763d71aadf09a7951596c9746c024e7eece7c7af")); - cl_git_pass(git_oid_fromstr(&two, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750")); - cl_git_pass(git_oid_fromstr(&expected, "c47800c7266a2be04c571c04d5a6614691ea99bd")); - - cl_git_pass(git_merge_base(&result, _repo, &one, &two)); - cl_assert(git_oid_cmp(&result, &expected) == 0); - - cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &one, &two)); - cl_assert_equal_sz(ahead, 4); - cl_assert_equal_sz(behind, 1); - - cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &two, &one)); - cl_assert_equal_sz(ahead, 1); - cl_assert_equal_sz(behind, 4); -} - -void test_revwalk_mergebase__merged_branch(void) -{ - git_oid result, one, two, expected; - size_t ahead, behind; - - cl_git_pass(git_oid_fromstr(&one, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750")); - cl_git_pass(git_oid_fromstr(&two, "9fd738e8f7967c078dceed8190330fc8648ee56a")); - cl_git_pass(git_oid_fromstr(&expected, "9fd738e8f7967c078dceed8190330fc8648ee56a")); - - cl_git_pass(git_merge_base(&result, _repo, &one, &two)); - cl_assert(git_oid_cmp(&result, &expected) == 0); - - cl_git_pass(git_merge_base(&result, _repo, &two, &one)); - cl_assert(git_oid_cmp(&result, &expected) == 0); - - cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); - cl_assert_equal_sz(ahead, 0); - cl_assert_equal_sz(behind, 3); - - cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &two, &one)); - cl_assert_equal_sz(ahead, 3); - cl_assert_equal_sz(behind, 0); -} - -void test_revwalk_mergebase__two_way_merge(void) -{ - git_oid one, two; - size_t ahead, behind; - - cl_git_pass(git_oid_fromstr(&one, "9b219343610c88a1187c996d0dc58330b55cee28")); - cl_git_pass(git_oid_fromstr(&two, "a953a018c5b10b20c86e69fef55ebc8ad4c5a417")); - cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo2, &one, &two)); - - cl_assert_equal_sz(ahead, 2); - cl_assert_equal_sz(behind, 8); - - cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo2, &two, &one)); - - cl_assert_equal_sz(ahead, 8); - cl_assert_equal_sz(behind, 2); -} - -void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void) -{ - git_oid result, one, two; - size_t ahead, behind; - int error; - - cl_git_pass(git_oid_fromstr(&one, "763d71aadf09a7951596c9746c024e7eece7c7af")); - cl_git_pass(git_oid_fromstr(&two, "e90810b8df3e80c413d903f631643c716887138d")); - - error = git_merge_base(&result, _repo, &one, &two); - cl_git_fail(error); - - cl_assert_equal_i(GIT_ENOTFOUND, error); - - cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); - cl_assert_equal_sz(2, ahead); - cl_assert_equal_sz(4, behind); -} - -void test_revwalk_mergebase__prefer_youngest_merge_base(void) -{ - git_oid result, one, two, expected; - - cl_git_pass(git_oid_fromstr(&one, "a4a7dce85cf63874e984719f4fdd239f5145052f ")); - cl_git_pass(git_oid_fromstr(&two, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); - cl_git_pass(git_oid_fromstr(&expected, "c47800c7266a2be04c571c04d5a6614691ea99bd")); - - cl_git_pass(git_merge_base(&result, _repo, &one, &two)); - cl_assert(git_oid_cmp(&result, &expected) == 0); -} - -void test_revwalk_mergebase__no_off_by_one_missing(void) -{ - git_oid result, one, two; - - cl_git_pass(git_oid_fromstr(&one, "1a443023183e3f2bfbef8ac923cd81c1018a18fd")); - cl_git_pass(git_oid_fromstr(&two, "9f13f7d0a9402c681f91dc590cf7b5470e6a77d2")); - cl_git_pass(git_merge_base(&result, _repo, &one, &two)); -} - -static void assert_mergebase_many(const char *expected_sha, int count, ...) -{ - va_list ap; - int i; - git_oid *oids; - git_oid oid, expected; - char *partial_oid; - git_object *object; - - oids = git__malloc(count * sizeof(git_oid)); - cl_assert(oids != NULL); - - memset(oids, 0x0, count * sizeof(git_oid)); - - va_start(ap, count); - - for (i = 0; i < count; ++i) { - partial_oid = va_arg(ap, char *); - cl_git_pass(git_oid_fromstrn(&oid, partial_oid, strlen(partial_oid))); - - cl_git_pass(git_object_lookup_prefix(&object, _repo, &oid, strlen(partial_oid), GIT_OBJ_COMMIT)); - git_oid_cpy(&oids[i], git_object_id(object)); - git_object_free(object); - } - - va_end(ap); - - if (expected_sha == NULL) - cl_assert_equal_i(GIT_ENOTFOUND, git_merge_base_many(&oid, _repo, count, oids)); - else { - cl_git_pass(git_merge_base_many(&oid, _repo, count, oids)); - cl_git_pass(git_oid_fromstr(&expected, expected_sha)); - - cl_assert(git_oid_cmp(&expected, &oid) == 0); - } - - git__free(oids); -} - -void test_revwalk_mergebase__many_no_common_ancestor_returns_ENOTFOUND(void) -{ - assert_mergebase_many(NULL, 3, "41bc8c", "e90810", "a65fed"); - assert_mergebase_many(NULL, 3, "e90810", "41bc8c", "a65fed"); - assert_mergebase_many(NULL, 3, "e90810", "a65fed", "41bc8c"); - assert_mergebase_many(NULL, 3, "a65fed", "e90810", "41bc8c"); - assert_mergebase_many(NULL, 3, "a65fed", "e90810", "41bc8c"); - assert_mergebase_many(NULL, 3, "a65fed", "41bc8c", "e90810"); - - assert_mergebase_many(NULL, 3, "e90810", "763d71", "a65fed"); -} - -void test_revwalk_mergebase__many_merge_branch(void) -{ - assert_mergebase_many("c47800c7266a2be04c571c04d5a6614691ea99bd", 3, "a65fed", "763d71", "849607"); - - assert_mergebase_many("c47800c7266a2be04c571c04d5a6614691ea99bd", 3, "763d71", "e90810", "a65fed"); - assert_mergebase_many("c47800c7266a2be04c571c04d5a6614691ea99bd", 3, "763d71", "a65fed", "e90810"); - - assert_mergebase_many("c47800c7266a2be04c571c04d5a6614691ea99bd", 3, "a65fed", "763d71", "849607"); - assert_mergebase_many("c47800c7266a2be04c571c04d5a6614691ea99bd", 3, "a65fed", "849607", "763d71"); - assert_mergebase_many("8496071c1b46c854b31185ea97743be6a8774479", 3, "849607", "a65fed", "763d71"); - - assert_mergebase_many("5b5b025afb0b4c913b4c338a42934a3863bf3644", 5, "5b5b02", "763d71", "a4a7dc", "a65fed", "41bc8c"); -} - -/* - * testrepo.git $ git log --graph --all - * * commit 763d71aadf09a7951596c9746c024e7eece7c7af - * | Author: nulltoken - * | Date: Sun Oct 9 12:54:47 2011 +0200 - * | - * | Add some files into subdirectories - * | - * | * commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750 - * | | Author: Scott Chacon - * | | Date: Tue Aug 9 19:33:46 2011 -0700 - * | | - * | * commit be3563ae3f795b2b4353bcce3a527ad0a4f7f644 - * | |\ Merge: 9fd738e c47800c - * | |/ Author: Scott Chacon - * |/| Date: Tue May 25 11:58:27 2010 -0700 - * | | - * | | Merge branch 'br2' - * | | - * | | * commit e90810b8df3e80c413d903f631643c716887138d - * | | | Author: Vicent Marti - * | | | Date: Thu Aug 5 18:42:20 2010 +0200 - * | | | - * | | | Test commit 2 - * | | | - * | | * commit 6dcf9bf7541ee10456529833502442f385010c3d - * | | Author: Vicent Marti - * | | Date: Thu Aug 5 18:41:33 2010 +0200 - * | | - * | | Test commit 1 - * | | - * | | * commit a4a7dce85cf63874e984719f4fdd239f5145052f - * | | |\ Merge: c47800c 9fd738e - * | |/ / Author: Scott Chacon - * |/| / Date: Tue May 25 12:00:23 2010 -0700 - * | |/ - * | | Merge branch 'master' into br2 - * | | - * | * commit 9fd738e8f7967c078dceed8190330fc8648ee56a - * | | Author: Scott Chacon - * | | Date: Mon May 24 10:19:19 2010 -0700 - * | | - * | | a fourth commit - * | | - * | * commit 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 - * | | Author: Scott Chacon - * | | Date: Mon May 24 10:19:04 2010 -0700 - * | | - * | | a third commit - * | | - * * | commit c47800c7266a2be04c571c04d5a6614691ea99bd - * |/ Author: Scott Chacon - * | Date: Tue May 25 11:58:14 2010 -0700 - * | - * | branch commit one - * | - * * commit 5b5b025afb0b4c913b4c338a42934a3863bf3644 - * | Author: Scott Chacon - * | Date: Tue May 11 13:38:42 2010 -0700 - * | - * | another commit - * | - * * commit 8496071c1b46c854b31185ea97743be6a8774479 - * Author: Scott Chacon - * Date: Sat May 8 16:13:06 2010 -0700 - * - * testing - * - * * commit 41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9 - * | Author: Scott Chacon - * | Date: Tue May 11 13:40:41 2010 -0700 - * | - * | packed commit two - * | - * * commit 5001298e0c09ad9c34e4249bc5801c75e9754fa5 - * Author: Scott Chacon - * Date: Tue May 11 13:40:23 2010 -0700 - * - * packed commit one - */ - -/* - * twowaymerge.git $ git log --graph --all - * * commit 9b219343610c88a1187c996d0dc58330b55cee28 - * |\ Merge: c37a783 2224e19 - * | | Author: Scott J. Goldman - * | | Date: Tue Nov 27 20:31:04 2012 -0800 - * | | - * | | Merge branch 'first-branch' into second-branch - * | | - * | * commit 2224e191514cb4bd8c566d80dac22dfcb1e9bb83 - * | | Author: Scott J. Goldman - * | | Date: Tue Nov 27 20:28:51 2012 -0800 - * | | - * | | j - * | | - * | * commit a41a49f8f5cd9b6cb14a076bf8394881ed0b4d19 - * | | Author: Scott J. Goldman - * | | Date: Tue Nov 27 20:28:39 2012 -0800 - * | | - * | | i - * | | - * | * commit 82bf9a1a10a4b25c1f14c9607b60970705e92545 - * | | Author: Scott J. Goldman - * | | Date: Tue Nov 27 20:28:28 2012 -0800 - * | | - * | | h - * | | - * * | commit c37a783c20d92ac92362a78a32860f7eebf938ef - * | | Author: Scott J. Goldman - * | | Date: Tue Nov 27 20:30:57 2012 -0800 - * | | - * | | n - * | | - * * | commit 8b82fb1794cb1c8c7f172ec730a4c2db0ae3e650 - * | | Author: Scott J. Goldman - * | | Date: Tue Nov 27 20:30:43 2012 -0800 - * | | - * | | m - * | | - * * | commit 6ab5d28acbf3c3bdff276f7ccfdf29c1520e542f - * | | Author: Scott J. Goldman - * | | Date: Tue Nov 27 20:30:38 2012 -0800 - * | | - * | | l - * | | - * * | commit 7b8c336c45fc6895c1c60827260fe5d798e5d247 - * | | Author: Scott J. Goldman - * | | Date: Tue Nov 27 20:30:24 2012 -0800 - * | | - * | | k - * | | - * | | * commit 1c30b88f5f3ee66d78df6520a7de9e89b890818b - * | | | Author: Scott J. Goldman - * | | | Date: Tue Nov 27 20:28:10 2012 -0800 - * | | | - * | | | e - * | | | - * | | * commit 42b7311aa626e712891940c1ec5d5cba201946a4 - * | | | Author: Scott J. Goldman - * | | | Date: Tue Nov 27 20:28:06 2012 -0800 - * | | | - * | | | d - * | | | - * | | * commit a953a018c5b10b20c86e69fef55ebc8ad4c5a417 - * | | |\ Merge: bd1732c cdf97fd - * | | |/ Author: Scott J. Goldman - * | |/| Date: Tue Nov 27 20:26:43 2012 -0800 - * | | | - * | | | Merge branch 'first-branch' - * | | | - * | * | commit cdf97fd3bb48eb3827638bb33d208f5fd32d0aa6 - * | | | Author: Scott J. Goldman - * | | | Date: Tue Nov 27 20:24:46 2012 -0800 - * | | | - * | | | g - * | | | - * | * | commit ef0488f0b722f0be8bcb90a7730ac7efafd1d694 - * | | | Author: Scott J. Goldman - * | | | Date: Tue Nov 27 20:24:39 2012 -0800 - * | | | - * | | | f - * | | | - * | | * commit bd1732c43c68d712ad09e1d872b9be6d4b9efdc4 - * | |/ Author: Scott J. Goldman - * | | Date: Tue Nov 27 17:43:58 2012 -0800 - * | | - * | | c - * | | - * | * commit 0c8a3f1f3d5f421cf83048c7c73ee3b55a5e0f29 - * |/ Author: Scott J. Goldman - * | Date: Tue Nov 27 17:43:48 2012 -0800 - * | - * | b - * | - * * commit 1f4c0311a24b63f6fc209a59a1e404942d4a5006 - * Author: Scott J. Goldman - * Date: Tue Nov 27 17:43:41 2012 -0800 - * - * a - */ diff --git a/tests-clar/revwalk/signatureparsing.c b/tests-clar/revwalk/signatureparsing.c deleted file mode 100644 index 5c7d8813d..000000000 --- a/tests-clar/revwalk/signatureparsing.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "clar_libgit2.h" - -static git_repository *_repo; -static git_revwalk *_walk; - -void test_revwalk_signatureparsing__initialize(void) -{ - cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_revwalk_new(&_walk, _repo)); -} - -void test_revwalk_signatureparsing__cleanup(void) -{ - git_revwalk_free(_walk); - _walk = NULL; - - git_repository_free(_repo); - _repo = NULL; -} - -void test_revwalk_signatureparsing__do_not_choke_when_name_contains_angle_brackets(void) -{ - git_reference *ref; - git_oid commit_oid; - git_commit *commit; - const git_signature *signature; - - /* - * The branch below points at a commit with angle brackets in the committer/author name - * committer 1323847743 +0100 - */ - cl_git_pass(git_reference_lookup(&ref, _repo, "refs/heads/haacked")); - - git_revwalk_push(_walk, git_reference_target(ref)); - cl_git_pass(git_revwalk_next(&commit_oid, _walk)); - - cl_git_pass(git_commit_lookup(&commit, _repo, git_reference_target(ref))); - - signature = git_commit_committer(commit); - cl_assert_equal_s("foo@example.com", signature->email); - cl_assert_equal_s("", signature->name); - cl_assert_equal_i(1323847743, (int)signature->when.time); - cl_assert_equal_i(60, signature->when.offset); - - git_commit_free(commit); - git_reference_free(ref); -} diff --git a/tests-clar/revwalk/simplify.c b/tests-clar/revwalk/simplify.c deleted file mode 100644 index 81c19d366..000000000 --- a/tests-clar/revwalk/simplify.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "clar_libgit2.h" - -void test_revwalk_simplify__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -/* - * a4a7dce [0] Merge branch 'master' into br2 - |\ - | * 9fd738e [1] a fourth commit - | * 4a202b3 [2] a third commit - * | c47800c [3] branch commit one - |/ - * 5b5b025 [5] another commit - * 8496071 [4] testing -*/ -static const char *commit_head = "a4a7dce85cf63874e984719f4fdd239f5145052f"; - -static const char *expected_str[] = { - "a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */ - "c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */ - "8496071c1b46c854b31185ea97743be6a8774479", /* 4 */ - "5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */ -}; - -void test_revwalk_simplify__first_parent(void) -{ - git_repository *repo; - git_revwalk *walk; - git_oid id, expected[4]; - int i, error; - - for (i = 0; i < 4; i++) { - git_oid_fromstr(&expected[i], expected_str[i]); - } - - repo = cl_git_sandbox_init("testrepo.git"); - cl_git_pass(git_revwalk_new(&walk, repo)); - - git_oid_fromstr(&id, commit_head); - cl_git_pass(git_revwalk_push(walk, &id)); - git_revwalk_simplify_first_parent(walk); - - i = 0; - while ((error = git_revwalk_next(&id, walk)) == 0) { - git_oid_cmp(&id, &expected[i]); - i++; - } - - cl_assert_equal_i(i, 4); - cl_assert_equal_i(error, GIT_ITEROVER); - - git_revwalk_free(walk); -} diff --git a/tests-clar/stash/drop.c b/tests-clar/stash/drop.c deleted file mode 100644 index 63ff0377c..000000000 --- a/tests-clar/stash/drop.c +++ /dev/null @@ -1,174 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "stash_helpers.h" -#include "refs.h" - -static git_repository *repo; -static git_signature *signature; - -void test_stash_drop__initialize(void) -{ - cl_git_pass(git_repository_init(&repo, "stash", 0)); - cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ -} - -void test_stash_drop__cleanup(void) -{ - git_signature_free(signature); - signature = NULL; - - git_repository_free(repo); - repo = NULL; - - cl_git_pass(git_futils_rmdir_r("stash", NULL, GIT_RMDIR_REMOVE_FILES)); -} - -void test_stash_drop__cannot_drop_from_an_empty_stash(void) -{ - cl_git_fail_with(git_stash_drop(repo, 0), GIT_ENOTFOUND); -} - -static void push_three_states(void) -{ - git_oid oid; - git_index *index; - - cl_git_mkfile("stash/zero.txt", "content\n"); - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add_bypath(index, "zero.txt")); - cl_repo_commit_from_index(NULL, repo, signature, 0, "Initial commit"); - cl_assert(git_path_exists("stash/zero.txt")); - git_index_free(index); - - cl_git_mkfile("stash/one.txt", "content\n"); - cl_git_pass(git_stash_save( - &oid, repo, signature, "First", GIT_STASH_INCLUDE_UNTRACKED)); - cl_assert(!git_path_exists("stash/one.txt")); - cl_assert(git_path_exists("stash/zero.txt")); - - cl_git_mkfile("stash/two.txt", "content\n"); - cl_git_pass(git_stash_save( - &oid, repo, signature, "Second", GIT_STASH_INCLUDE_UNTRACKED)); - cl_assert(!git_path_exists("stash/two.txt")); - cl_assert(git_path_exists("stash/zero.txt")); - - cl_git_mkfile("stash/three.txt", "content\n"); - cl_git_pass(git_stash_save( - &oid, repo, signature, "Third", GIT_STASH_INCLUDE_UNTRACKED)); - cl_assert(!git_path_exists("stash/three.txt")); - cl_assert(git_path_exists("stash/zero.txt")); -} - -void test_stash_drop__cannot_drop_a_non_existing_stashed_state(void) -{ - push_three_states(); - - cl_git_fail_with(git_stash_drop(repo, 666), GIT_ENOTFOUND); - cl_git_fail_with(git_stash_drop(repo, 42), GIT_ENOTFOUND); - cl_git_fail_with(git_stash_drop(repo, 3), GIT_ENOTFOUND); -} - -void test_stash_drop__can_purge_the_stash_from_the_top(void) -{ - push_three_states(); - - cl_git_pass(git_stash_drop(repo, 0)); - cl_git_pass(git_stash_drop(repo, 0)); - cl_git_pass(git_stash_drop(repo, 0)); - - cl_git_fail_with(git_stash_drop(repo, 0), GIT_ENOTFOUND); -} - -void test_stash_drop__can_purge_the_stash_from_the_bottom(void) -{ - push_three_states(); - - cl_git_pass(git_stash_drop(repo, 2)); - cl_git_pass(git_stash_drop(repo, 1)); - cl_git_pass(git_stash_drop(repo, 0)); - - cl_git_fail_with(git_stash_drop(repo, 0), GIT_ENOTFOUND); -} - -void test_stash_drop__dropping_an_entry_rewrites_reflog_history(void) -{ - git_reference *stash; - git_reflog *reflog; - const git_reflog_entry *entry; - git_oid oid; - size_t count; - - push_three_states(); - - cl_git_pass(git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE)); - - cl_git_pass(git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)); - entry = git_reflog_entry_byindex(reflog, 1); - - git_oid_cpy(&oid, git_reflog_entry_id_old(entry)); - count = git_reflog_entrycount(reflog); - - git_reflog_free(reflog); - - cl_git_pass(git_stash_drop(repo, 1)); - - cl_git_pass(git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)); - entry = git_reflog_entry_byindex(reflog, 0); - - cl_assert_equal_i(0, git_oid_cmp(&oid, git_reflog_entry_id_old(entry))); - cl_assert_equal_sz(count - 1, git_reflog_entrycount(reflog)); - - git_reflog_free(reflog); - - git_reference_free(stash); -} - -void test_stash_drop__dropping_the_last_entry_removes_the_stash(void) -{ - git_reference *stash; - - push_three_states(); - - cl_git_pass(git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE)); - git_reference_free(stash); - - cl_git_pass(git_stash_drop(repo, 0)); - cl_git_pass(git_stash_drop(repo, 0)); - cl_git_pass(git_stash_drop(repo, 0)); - - cl_git_fail_with( - git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE), GIT_ENOTFOUND); -} - -void retrieve_top_stash_id(git_oid *out) -{ - git_object *top_stash; - - cl_git_pass(git_revparse_single(&top_stash, repo, "stash@{0}")); - cl_git_pass(git_reference_name_to_id(out, repo, GIT_REFS_STASH_FILE)); - - cl_assert_equal_i(true, git_oid_cmp(out, git_object_id(top_stash)) == 0); - - git_object_free(top_stash); -} - -void test_stash_drop__dropping_the_top_stash_updates_the_stash_reference(void) -{ - git_object *next_top_stash; - git_oid oid; - - push_three_states(); - - retrieve_top_stash_id(&oid); - - cl_git_pass(git_revparse_single(&next_top_stash, repo, "stash@{1}")); - cl_assert(git_oid_cmp(&oid, git_object_id(next_top_stash)) != 0); - - cl_git_pass(git_stash_drop(repo, 0)); - - retrieve_top_stash_id(&oid); - - cl_git_pass(git_oid_cmp(&oid, git_object_id(next_top_stash))); - - git_object_free(next_top_stash); -} diff --git a/tests-clar/stash/foreach.c b/tests-clar/stash/foreach.c deleted file mode 100644 index f1983625f..000000000 --- a/tests-clar/stash/foreach.c +++ /dev/null @@ -1,124 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "stash_helpers.h" - -struct callback_data -{ - char **oids; - int invokes; -}; - -static git_repository *repo; -static git_signature *signature; -static git_oid stash_tip_oid; -struct callback_data data; - -#define REPO_NAME "stash" - -void test_stash_foreach__initialize(void) -{ - cl_git_pass(git_signature_new( - &signature, - "nulltoken", - "emeric.fermas@gmail.com", - 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ - - memset(&data, 0, sizeof(struct callback_data)); -} - -void test_stash_foreach__cleanup(void) -{ - git_signature_free(signature); - signature = NULL; - - git_repository_free(repo); - repo = NULL; - - cl_git_pass(git_futils_rmdir_r(REPO_NAME, NULL, GIT_RMDIR_REMOVE_FILES)); -} - -static int callback_cb( - size_t index, - const char* message, - const git_oid *stash_oid, - void *payload) -{ - struct callback_data *data = (struct callback_data *)payload; - - GIT_UNUSED(index); - GIT_UNUSED(message); - - cl_assert_equal_i(0, git_oid_streq(stash_oid, data->oids[data->invokes++])); - - return 0; -} - -void test_stash_foreach__enumerating_a_empty_repository_doesnt_fail(void) -{ - char *oids[] = { NULL }; - - data.oids = oids; - - cl_git_pass(git_repository_init(&repo, REPO_NAME, 0)); - - cl_git_pass(git_stash_foreach(repo, callback_cb, &data)); - - cl_assert_equal_i(0, data.invokes); -} - -void test_stash_foreach__can_enumerate_a_repository(void) -{ - char *oids_default[] = { - "1d91c842a7cdfc25872b3a763e5c31add8816c25", NULL }; - - char *oids_untracked[] = { - "7f89a8b15c878809c5c54d1ff8f8c9674154017b", - "1d91c842a7cdfc25872b3a763e5c31add8816c25", NULL }; - - char *oids_ignored[] = { - "c95599a8fef20a7e57582c6727b1a0d02e0a5828", - "7f89a8b15c878809c5c54d1ff8f8c9674154017b", - "1d91c842a7cdfc25872b3a763e5c31add8816c25", NULL }; - - cl_git_pass(git_repository_init(&repo, REPO_NAME, 0)); - - setup_stash(repo, signature); - - cl_git_pass(git_stash_save( - &stash_tip_oid, - repo, - signature, - NULL, - GIT_STASH_DEFAULT)); - - data.oids = oids_default; - - cl_git_pass(git_stash_foreach(repo, callback_cb, &data)); - cl_assert_equal_i(1, data.invokes); - - data.oids = oids_untracked; - data.invokes = 0; - - cl_git_pass(git_stash_save( - &stash_tip_oid, - repo, - signature, - NULL, - GIT_STASH_INCLUDE_UNTRACKED)); - - cl_git_pass(git_stash_foreach(repo, callback_cb, &data)); - cl_assert_equal_i(2, data.invokes); - - data.oids = oids_ignored; - data.invokes = 0; - - cl_git_pass(git_stash_save( - &stash_tip_oid, - repo, - signature, - NULL, - GIT_STASH_INCLUDE_IGNORED)); - - cl_git_pass(git_stash_foreach(repo, callback_cb, &data)); - cl_assert_equal_i(3, data.invokes); -} diff --git a/tests-clar/stash/save.c b/tests-clar/stash/save.c deleted file mode 100644 index 3d92b26bd..000000000 --- a/tests-clar/stash/save.c +++ /dev/null @@ -1,354 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "stash_helpers.h" - -static git_repository *repo; -static git_signature *signature; -static git_oid stash_tip_oid; - -/* - * Friendly reminder, in order to ease the reading of the following tests: - * - * "stash" points to the worktree commit - * "stash^1" points to the base commit (HEAD when the stash was created) - * "stash^2" points to the index commit - * "stash^3" points to the untracked commit - */ - -void test_stash_save__initialize(void) -{ - cl_git_pass(git_repository_init(&repo, "stash", 0)); - cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ - - setup_stash(repo, signature); -} - -void test_stash_save__cleanup(void) -{ - git_signature_free(signature); - signature = NULL; - - git_repository_free(repo); - repo = NULL; - - cl_git_pass(git_futils_rmdir_r("stash", NULL, GIT_RMDIR_REMOVE_FILES)); - cl_fixture_cleanup("sorry-it-is-a-non-bare-only-party"); -} - -static void assert_object_oid(const char* revision, const char* expected_oid, git_otype type) -{ - int result; - git_object *obj; - - result = git_revparse_single(&obj, repo, revision); - - if (!expected_oid) { - cl_assert_equal_i(GIT_ENOTFOUND, result); - return; - } else - cl_assert_equal_i(0, result); - - cl_git_pass(git_oid_streq(git_object_id(obj), expected_oid)); - cl_assert_equal_i(type, git_object_type(obj)); - git_object_free(obj); -} - -static void assert_blob_oid(const char* revision, const char* expected_oid) -{ - assert_object_oid(revision, expected_oid, GIT_OBJ_BLOB); -} - -void test_stash_save__does_not_keep_index_by_default(void) -{ -/* -$ git stash - -$ git show refs/stash:what -see you later - -$ git show refs/stash:how -not so small and - -$ git show refs/stash:who -funky world - -$ git show refs/stash:when -fatal: Path 'when' exists on disk, but not in 'stash'. - -$ git show refs/stash^2:what -goodbye - -$ git show refs/stash^2:how -not so small and - -$ git show refs/stash^2:who -world - -$ git show refs/stash^2:when -fatal: Path 'when' exists on disk, but not in 'stash^2'. - -$ git status --short -?? when - -*/ - unsigned int status; - - cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); - cl_git_pass(git_status_file(&status, repo, "when")); - - assert_blob_oid("refs/stash:what", "bc99dc98b3eba0e9157e94769cd4d49cb49de449"); /* see you later */ - assert_blob_oid("refs/stash:how", "e6d64adb2c7f3eb8feb493b556cc8070dca379a3"); /* not so small and */ - assert_blob_oid("refs/stash:who", "a0400d4954659306a976567af43125a0b1aa8595"); /* funky world */ - assert_blob_oid("refs/stash:when", NULL); - assert_blob_oid("refs/stash:just.ignore", NULL); - - assert_blob_oid("refs/stash^2:what", "dd7e1c6f0fefe118f0b63d9f10908c460aa317a6"); /* goodbye */ - assert_blob_oid("refs/stash^2:how", "e6d64adb2c7f3eb8feb493b556cc8070dca379a3"); /* not so small and */ - assert_blob_oid("refs/stash^2:who", "cc628ccd10742baea8241c5924df992b5c019f71"); /* world */ - assert_blob_oid("refs/stash^2:when", NULL); - assert_blob_oid("refs/stash^2:just.ignore", NULL); - - assert_blob_oid("refs/stash^3", NULL); - - cl_assert_equal_i(GIT_STATUS_WT_NEW, status); -} - -void test_stash_save__can_keep_index(void) -{ - cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_KEEP_INDEX)); - - assert_status(repo, "what", GIT_STATUS_INDEX_MODIFIED); - assert_status(repo, "how", GIT_STATUS_INDEX_MODIFIED); - assert_status(repo, "who", GIT_STATUS_CURRENT); - assert_status(repo, "when", GIT_STATUS_WT_NEW); - assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); -} - -static void assert_commit_message_contains(const char *revision, const char *fragment) -{ - git_commit *commit; - - cl_git_pass(git_revparse_single((git_object**)&commit, repo, revision)); - - cl_assert(strstr(git_commit_message(commit), fragment) != NULL); - - git_commit_free(commit); -} - -void test_stash_save__can_include_untracked_files(void) -{ - cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); - - assert_commit_message_contains("refs/stash^3", "untracked files on master: "); - - assert_blob_oid("refs/stash^3:what", NULL); - assert_blob_oid("refs/stash^3:how", NULL); - assert_blob_oid("refs/stash^3:who", NULL); - assert_blob_oid("refs/stash^3:when", "b6ed15e81e2593d7bb6265eb4a991d29dc3e628b"); - assert_blob_oid("refs/stash^3:just.ignore", NULL); -} - -void test_stash_save__can_include_untracked_and_ignored_files(void) -{ - cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED | GIT_STASH_INCLUDE_IGNORED)); - - assert_commit_message_contains("refs/stash^3", "untracked files on master: "); - - assert_blob_oid("refs/stash^3:what", NULL); - assert_blob_oid("refs/stash^3:how", NULL); - assert_blob_oid("refs/stash^3:who", NULL); - assert_blob_oid("refs/stash^3:when", "b6ed15e81e2593d7bb6265eb4a991d29dc3e628b"); - assert_blob_oid("refs/stash^3:just.ignore", "78925fb1236b98b37a35e9723033e627f97aa88b"); -} - -#define MESSAGE "Look Ma! I'm on TV!" -void test_stash_save__can_accept_a_message(void) -{ - cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, MESSAGE, GIT_STASH_DEFAULT)); - - assert_commit_message_contains("refs/stash^2", "index on master: "); - assert_commit_message_contains("refs/stash", "On master: " MESSAGE); -} - -void test_stash_save__cannot_stash_against_an_unborn_branch(void) -{ - git_reference *head; - - cl_git_pass(git_reference_symbolic_create(&head, repo, "HEAD", "refs/heads/unborn", 1)); - - cl_assert_equal_i(GIT_EUNBORNBRANCH, - git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); - - git_reference_free(head); -} - -void test_stash_save__cannot_stash_against_a_bare_repository(void) -{ - git_repository *local; - - cl_git_pass(git_repository_init(&local, "sorry-it-is-a-non-bare-only-party", 1)); - - cl_assert_equal_i(GIT_EBAREREPO, - git_stash_save(&stash_tip_oid, local, signature, NULL, GIT_STASH_DEFAULT)); - - git_repository_free(local); -} - -void test_stash_save__can_stash_against_a_detached_head(void) -{ - git_repository_detach_head(repo); - - cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); - - assert_commit_message_contains("refs/stash^2", "index on (no branch): "); - assert_commit_message_contains("refs/stash", "WIP on (no branch): "); -} - -void test_stash_save__stashing_updates_the_reflog(void) -{ - char *sha; - - assert_object_oid("refs/stash@{0}", NULL, GIT_OBJ_COMMIT); - - cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); - - sha = git_oid_allocfmt(&stash_tip_oid); - - assert_object_oid("refs/stash@{0}", sha, GIT_OBJ_COMMIT); - assert_object_oid("refs/stash@{1}", NULL, GIT_OBJ_COMMIT); - - git__free(sha); -} - -void test_stash_save__cannot_stash_when_there_are_no_local_change(void) -{ - git_index *index; - git_oid stash_tip_oid; - - cl_git_pass(git_repository_index(&index, repo)); - - /* - * 'what' and 'who' are being committed. - * 'when' remain untracked. - */ - cl_git_pass(git_index_add_bypath(index, "what")); - cl_git_pass(git_index_add_bypath(index, "who")); - cl_repo_commit_from_index(NULL, repo, signature, 0, "Initial commit"); - git_index_free(index); - - cl_assert_equal_i(GIT_ENOTFOUND, - git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); - - p_unlink("stash/when"); - cl_assert_equal_i(GIT_ENOTFOUND, - git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); -} - -void test_stash_save__can_stage_normal_then_stage_untracked(void) -{ - /* - * $ git ls-tree stash@{1}^0 - * 100644 blob ac4d88de61733173d9959e4b77c69b9f17a00980 .gitignore - * 100644 blob e6d64adb2c7f3eb8feb493b556cc8070dca379a3 how - * 100644 blob bc99dc98b3eba0e9157e94769cd4d49cb49de449 what - * 100644 blob a0400d4954659306a976567af43125a0b1aa8595 who - * - * $ git ls-tree stash@{1}^1 - * 100644 blob ac4d88de61733173d9959e4b77c69b9f17a00980 .gitignore - * 100644 blob ac790413e2d7a26c3767e78c57bb28716686eebc how - * 100644 blob ce013625030ba8dba906f756967f9e9ca394464a what - * 100644 blob cc628ccd10742baea8241c5924df992b5c019f71 who - * - * $ git ls-tree stash@{1}^2 - * 100644 blob ac4d88de61733173d9959e4b77c69b9f17a00980 .gitignore - * 100644 blob e6d64adb2c7f3eb8feb493b556cc8070dca379a3 how - * 100644 blob dd7e1c6f0fefe118f0b63d9f10908c460aa317a6 what - * 100644 blob cc628ccd10742baea8241c5924df992b5c019f71 who - * - * $ git ls-tree stash@{1}^3 - * fatal: Not a valid object name stash@{1}^3 - * - * $ git ls-tree stash@{0}^0 - * 100644 blob ac4d88de61733173d9959e4b77c69b9f17a00980 .gitignore - * 100644 blob ac790413e2d7a26c3767e78c57bb28716686eebc how - * 100644 blob ce013625030ba8dba906f756967f9e9ca394464a what - * 100644 blob cc628ccd10742baea8241c5924df992b5c019f71 who - * - * $ git ls-tree stash@{0}^1 - * 100644 blob ac4d88de61733173d9959e4b77c69b9f17a00980 .gitignore - * 100644 blob ac790413e2d7a26c3767e78c57bb28716686eebc how - * 100644 blob ce013625030ba8dba906f756967f9e9ca394464a what - * 100644 blob cc628ccd10742baea8241c5924df992b5c019f71 who - * - * $ git ls-tree stash@{0}^2 - * 100644 blob ac4d88de61733173d9959e4b77c69b9f17a00980 .gitignore - * 100644 blob ac790413e2d7a26c3767e78c57bb28716686eebc how - * 100644 blob ce013625030ba8dba906f756967f9e9ca394464a what - * 100644 blob cc628ccd10742baea8241c5924df992b5c019f71 who - * - * $ git ls-tree stash@{0}^3 - * 100644 blob b6ed15e81e2593d7bb6265eb4a991d29dc3e628b when - */ - - assert_status(repo, "what", GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED); - assert_status(repo, "how", GIT_STATUS_INDEX_MODIFIED); - assert_status(repo, "who", GIT_STATUS_WT_MODIFIED); - assert_status(repo, "when", GIT_STATUS_WT_NEW); - assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); - - cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); - assert_status(repo, "what", GIT_STATUS_CURRENT); - assert_status(repo, "how", GIT_STATUS_CURRENT); - assert_status(repo, "who", GIT_STATUS_CURRENT); - assert_status(repo, "when", GIT_STATUS_WT_NEW); - assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); - - cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); - assert_status(repo, "what", GIT_STATUS_CURRENT); - assert_status(repo, "how", GIT_STATUS_CURRENT); - assert_status(repo, "who", GIT_STATUS_CURRENT); - assert_status(repo, "when", GIT_ENOTFOUND); - assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); - - - assert_blob_oid("stash@{1}^0:what", "bc99dc98b3eba0e9157e94769cd4d49cb49de449"); /* see you later */ - assert_blob_oid("stash@{1}^0:how", "e6d64adb2c7f3eb8feb493b556cc8070dca379a3"); /* not so small and */ - assert_blob_oid("stash@{1}^0:who", "a0400d4954659306a976567af43125a0b1aa8595"); /* funky world */ - assert_blob_oid("stash@{1}^0:when", NULL); - - assert_blob_oid("stash@{1}^2:what", "dd7e1c6f0fefe118f0b63d9f10908c460aa317a6"); /* goodbye */ - assert_blob_oid("stash@{1}^2:how", "e6d64adb2c7f3eb8feb493b556cc8070dca379a3"); /* not so small and */ - assert_blob_oid("stash@{1}^2:who", "cc628ccd10742baea8241c5924df992b5c019f71"); /* world */ - assert_blob_oid("stash@{1}^2:when", NULL); - - assert_object_oid("stash@{1}^3", NULL, GIT_OBJ_COMMIT); - - assert_blob_oid("stash@{0}^0:what", "ce013625030ba8dba906f756967f9e9ca394464a"); /* hello */ - assert_blob_oid("stash@{0}^0:how", "ac790413e2d7a26c3767e78c57bb28716686eebc"); /* small */ - assert_blob_oid("stash@{0}^0:who", "cc628ccd10742baea8241c5924df992b5c019f71"); /* world */ - assert_blob_oid("stash@{0}^0:when", NULL); - - assert_blob_oid("stash@{0}^2:what", "ce013625030ba8dba906f756967f9e9ca394464a"); /* hello */ - assert_blob_oid("stash@{0}^2:how", "ac790413e2d7a26c3767e78c57bb28716686eebc"); /* small */ - assert_blob_oid("stash@{0}^2:who", "cc628ccd10742baea8241c5924df992b5c019f71"); /* world */ - assert_blob_oid("stash@{0}^2:when", NULL); - - assert_blob_oid("stash@{0}^3:when", "b6ed15e81e2593d7bb6265eb4a991d29dc3e628b"); /* now */ -} - -#define EMPTY_TREE "4b825dc642cb6eb9a060e54bf8d69288fbee4904" - -void test_stash_save__including_untracked_without_any_untracked_file_creates_an_empty_tree(void) -{ - cl_git_pass(p_unlink("stash/when")); - - assert_status(repo, "what", GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED); - assert_status(repo, "how", GIT_STATUS_INDEX_MODIFIED); - assert_status(repo, "who", GIT_STATUS_WT_MODIFIED); - assert_status(repo, "when", GIT_ENOTFOUND); - assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); - - cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); - - assert_object_oid("stash^3^{tree}", EMPTY_TREE, GIT_OBJ_TREE); -} diff --git a/tests-clar/stash/stash_helpers.c b/tests-clar/stash/stash_helpers.c deleted file mode 100644 index 8b7d685f8..000000000 --- a/tests-clar/stash/stash_helpers.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "stash_helpers.h" - -void setup_stash(git_repository *repo, git_signature *signature) -{ - git_index *index; - - cl_git_pass(git_repository_index(&index, repo)); - - cl_git_mkfile("stash/what", "hello\n"); /* ce013625030ba8dba906f756967f9e9ca394464a */ - cl_git_mkfile("stash/how", "small\n"); /* ac790413e2d7a26c3767e78c57bb28716686eebc */ - cl_git_mkfile("stash/who", "world\n"); /* cc628ccd10742baea8241c5924df992b5c019f71 */ - cl_git_mkfile("stash/when", "now\n"); /* b6ed15e81e2593d7bb6265eb4a991d29dc3e628b */ - cl_git_mkfile("stash/just.ignore", "me\n"); /* 78925fb1236b98b37a35e9723033e627f97aa88b */ - - cl_git_mkfile("stash/.gitignore", "*.ignore\n"); - - cl_git_pass(git_index_add_bypath(index, "what")); - cl_git_pass(git_index_add_bypath(index, "how")); - cl_git_pass(git_index_add_bypath(index, "who")); - cl_git_pass(git_index_add_bypath(index, ".gitignore")); - - cl_repo_commit_from_index(NULL, repo, signature, 0, "Initial commit"); - - cl_git_rewritefile("stash/what", "goodbye\n"); /* dd7e1c6f0fefe118f0b63d9f10908c460aa317a6 */ - cl_git_rewritefile("stash/how", "not so small and\n"); /* e6d64adb2c7f3eb8feb493b556cc8070dca379a3 */ - cl_git_rewritefile("stash/who", "funky world\n"); /* a0400d4954659306a976567af43125a0b1aa8595 */ - - cl_git_pass(git_index_add_bypath(index, "what")); - cl_git_pass(git_index_add_bypath(index, "how")); - cl_git_pass(git_index_write(index)); - - cl_git_rewritefile("stash/what", "see you later\n"); /* bc99dc98b3eba0e9157e94769cd4d49cb49de449 */ - - git_index_free(index); -} - -void assert_status( - git_repository *repo, - const char *path, - int status_flags) -{ - unsigned int status; - int error; - - error = git_status_file(&status, repo, path); - - if (status_flags < 0) { - cl_assert_equal_i(status_flags, error); - return; - } - - cl_assert_equal_i(0, error); - cl_assert_equal_i((unsigned int)status_flags, status); -} diff --git a/tests-clar/stash/stash_helpers.h b/tests-clar/stash/stash_helpers.h deleted file mode 100644 index 66d758fe2..000000000 --- a/tests-clar/stash/stash_helpers.h +++ /dev/null @@ -1,8 +0,0 @@ -void setup_stash( - git_repository *repo, - git_signature *signature); - -void assert_status( - git_repository *repo, - const char *path, - int status_flags); diff --git a/tests-clar/stash/submodules.c b/tests-clar/stash/submodules.c deleted file mode 100644 index 137c4408c..000000000 --- a/tests-clar/stash/submodules.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "clar_libgit2.h" -#include "stash_helpers.h" -#include "../submodule/submodule_helpers.h" - -static git_repository *repo; -static git_signature *signature; -static git_oid stash_tip_oid; - -static git_submodule *sm; - -void test_stash_submodules__initialize(void) -{ - cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ - - repo = setup_fixture_submodules(); - - cl_git_pass(git_submodule_lookup(&sm, repo, "testrepo")); -} - -void test_stash_submodules__cleanup(void) -{ - git_signature_free(signature); - signature = NULL; -} - -void test_stash_submodules__does_not_stash_modified_submodules(void) -{ - static git_index *smindex; - static git_repository *smrepo; - - assert_status(repo, "modified", GIT_STATUS_WT_MODIFIED); - - /* modify file in submodule */ - cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); - assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); - - /* add file to index in submodule */ - cl_git_pass(git_submodule_open(&smrepo, sm)); - cl_git_pass(git_repository_index(&smindex, smrepo)); - cl_git_pass(git_index_add_bypath(smindex, "README")); - - /* commit changed index of submodule */ - cl_repo_commit_from_index(NULL, smrepo, NULL, 1372350000, "Modify it"); - assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); - - cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); - - assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); - assert_status(repo, "modified", GIT_STATUS_CURRENT); - - git_index_free(smindex); - git_repository_free(smrepo); -} - -void test_stash_submodules__stash_is_empty_with_modified_submodules(void) -{ - static git_index *smindex; - static git_repository *smrepo; - - cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); - assert_status(repo, "modified", GIT_STATUS_CURRENT); - - /* modify file in submodule */ - cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); - assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); - - /* add file to index in submodule */ - cl_git_pass(git_submodule_open(&smrepo, sm)); - cl_git_pass(git_repository_index(&smindex, smrepo)); - cl_git_pass(git_index_add_bypath(smindex, "README")); - - /* commit changed index of submodule */ - cl_repo_commit_from_index(NULL, smrepo, NULL, 1372350000, "Modify it"); - assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); - - cl_git_fail_with(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT), GIT_ENOTFOUND); - - git_index_free(smindex); - git_repository_free(smrepo); -} diff --git a/tests-clar/status/ignore.c b/tests-clar/status/ignore.c deleted file mode 100644 index acdc8fb58..000000000 --- a/tests-clar/status/ignore.c +++ /dev/null @@ -1,582 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "git2/attr.h" -#include "ignore.h" -#include "attr.h" -#include "status_helpers.h" - -static git_repository *g_repo = NULL; - -void test_status_ignore__initialize(void) -{ -} - -void test_status_ignore__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -void test_status_ignore__0(void) -{ - struct { - const char *path; - int expected; - } test_cases[] = { - /* pattern "ign" from .gitignore */ - { "file", 0 }, - { "ign", 1 }, - { "sub", 0 }, - { "sub/file", 0 }, - { "sub/ign", 1 }, - { "sub/ign/file", 1 }, - { "sub/ign/sub", 1 }, - { "sub/ign/sub/file", 1 }, - { "sub/sub", 0 }, - { "sub/sub/file", 0 }, - { "sub/sub/ign", 1 }, - { "sub/sub/sub", 0 }, - /* pattern "dir/" from .gitignore */ - { "dir", 1 }, - { "dir/", 1 }, - { "sub/dir", 1 }, - { "sub/dir/", 1 }, - { "sub/dir/file", 1 }, /* contained in ignored parent */ - { "sub/sub/dir", 0 }, /* dir is not actually a dir, but a file */ - { NULL, 0 } - }, *one_test; - - g_repo = cl_git_sandbox_init("attr"); - - for (one_test = test_cases; one_test->path != NULL; one_test++) { - int ignored; - cl_git_pass(git_status_should_ignore(&ignored, g_repo, one_test->path)); - cl_assert_(ignored == one_test->expected, one_test->path); - } - - /* confirm that ignore files were cached */ - cl_assert(git_attr_cache__is_cached(g_repo, 0, ".git/info/exclude")); - cl_assert(git_attr_cache__is_cached(g_repo, 0, ".gitignore")); -} - - -void test_status_ignore__1(void) -{ - int ignored; - - g_repo = cl_git_sandbox_init("attr"); - - cl_git_rewritefile("attr/.gitignore", "/*.txt\n/dir/\n"); - git_attr_cache_flush(g_repo); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "root_test4.txt")); - cl_assert(ignored); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "sub/subdir_test2.txt")); - cl_assert(!ignored); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "dir")); - cl_assert(ignored); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "dir/")); - cl_assert(ignored); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "sub/dir")); - cl_assert(!ignored); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "sub/dir/")); - cl_assert(!ignored); -} - - -void test_status_ignore__empty_repo_with_gitignore_rewrite(void) -{ - status_entry_single st; - int ignored; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_mkfile( - "empty_standard_repo/look-ma.txt", "I'm going to be ignored!"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); - cl_assert(st.count == 1); - cl_assert(st.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); - cl_assert(st.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "look-ma.txt")); - cl_assert(!ignored); - - cl_git_rewritefile("empty_standard_repo/.gitignore", "*.nomatch\n"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); - cl_assert(st.count == 2); - cl_assert(st.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); - cl_assert(st.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "look-ma.txt")); - cl_assert(!ignored); - - cl_git_rewritefile("empty_standard_repo/.gitignore", "*.txt\n"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); - cl_assert(st.count == 2); - cl_assert(st.status == GIT_STATUS_IGNORED); - - cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); - cl_assert(st.status == GIT_STATUS_IGNORED); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "look-ma.txt")); - cl_assert(ignored); -} - -void test_status_ignore__ignore_pattern_contains_space(void) -{ - unsigned int flags; - const mode_t mode = 0777; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - cl_git_rewritefile("empty_standard_repo/.gitignore", "foo bar.txt\n"); - - cl_git_mkfile( - "empty_standard_repo/foo bar.txt", "I'm going to be ignored!"); - - cl_git_pass(git_status_file(&flags, g_repo, "foo bar.txt")); - cl_assert(flags == GIT_STATUS_IGNORED); - - cl_git_pass(git_futils_mkdir_r("empty_standard_repo/foo", NULL, mode)); - cl_git_mkfile("empty_standard_repo/foo/look-ma.txt", "I'm not going to be ignored!"); - - cl_git_pass(git_status_file(&flags, g_repo, "foo/look-ma.txt")); - cl_assert(flags == GIT_STATUS_WT_NEW); -} - -void test_status_ignore__ignore_pattern_ignorecase(void) -{ - unsigned int flags; - bool ignore_case; - git_index *index; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - cl_git_rewritefile("empty_standard_repo/.gitignore", "a.txt\n"); - - cl_git_mkfile("empty_standard_repo/A.txt", "Differs in case"); - - cl_git_pass(git_repository_index(&index, g_repo)); - ignore_case = (git_index_caps(index) & GIT_INDEXCAP_IGNORE_CASE) != 0; - git_index_free(index); - - cl_git_pass(git_status_file(&flags, g_repo, "A.txt")); - cl_assert(flags == ignore_case ? GIT_STATUS_IGNORED : GIT_STATUS_WT_NEW); -} - -void test_status_ignore__subdirectories(void) -{ - status_entry_single st; - int ignored; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_mkfile( - "empty_standard_repo/ignore_me", "I'm going to be ignored!"); - - cl_git_rewritefile("empty_standard_repo/.gitignore", "ignore_me\n"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); - cl_assert_equal_i(2, st.count); - cl_assert(st.status == GIT_STATUS_IGNORED); - - cl_git_pass(git_status_file(&st.status, g_repo, "ignore_me")); - cl_assert(st.status == GIT_STATUS_IGNORED); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "ignore_me")); - cl_assert(ignored); - - /* I've changed libgit2 so that the behavior here now differs from - * core git but seems to make more sense. In core git, the following - * items are skipped completed, even if --ignored is passed to status. - * It you mirror these steps and run "git status -uall --ignored" then - * you will not see "test/ignore_me/" in the results. - * - * However, we had a couple reports of this as a bug, plus there is a - * similar circumstance where we were differing for core git when you - * used a rooted path for an ignore, so I changed this behavior. - */ - cl_git_pass(git_futils_mkdir_r( - "empty_standard_repo/test/ignore_me", NULL, 0775)); - cl_git_mkfile( - "empty_standard_repo/test/ignore_me/file", "I'm going to be ignored!"); - cl_git_mkfile( - "empty_standard_repo/test/ignore_me/file2", "Me, too!"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); - cl_assert_equal_i(3, st.count); - - cl_git_pass(git_status_file(&st.status, g_repo, "test/ignore_me/file")); - cl_assert(st.status == GIT_STATUS_IGNORED); - - cl_git_pass( - git_status_should_ignore(&ignored, g_repo, "test/ignore_me/file")); - cl_assert(ignored); -} - -void test_status_ignore__subdirectories_recursion(void) -{ - /* Let's try again with recursing into ignored dirs turned on */ - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - status_entry_counts counts; - static const char *paths_r[] = { - ".gitignore", - "ignore_also/file", - "ignore_me", - "test/ignore_me/and_me/file", - "test/ignore_me/file", - "test/ignore_me/file2", - }; - static const unsigned int statuses_r[] = { - GIT_STATUS_WT_NEW, - GIT_STATUS_IGNORED, - GIT_STATUS_IGNORED, - GIT_STATUS_IGNORED, - GIT_STATUS_IGNORED, - GIT_STATUS_IGNORED, - }; - static const char *paths_nr[] = { - ".gitignore", - "ignore_also/", - "ignore_me", - "test/ignore_me/", - }; - static const unsigned int statuses_nr[] = { - GIT_STATUS_WT_NEW, - GIT_STATUS_IGNORED, - GIT_STATUS_IGNORED, - GIT_STATUS_IGNORED, - }; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_rewritefile("empty_standard_repo/.gitignore", "ignore_me\n/ignore_also\n"); - - cl_git_mkfile( - "empty_standard_repo/ignore_me", "I'm going to be ignored!"); - cl_git_pass(git_futils_mkdir_r( - "empty_standard_repo/test/ignore_me", NULL, 0775)); - cl_git_mkfile( - "empty_standard_repo/test/ignore_me/file", "I'm going to be ignored!"); - cl_git_mkfile( - "empty_standard_repo/test/ignore_me/file2", "Me, too!"); - cl_git_pass(git_futils_mkdir_r( - "empty_standard_repo/test/ignore_me/and_me", NULL, 0775)); - cl_git_mkfile( - "empty_standard_repo/test/ignore_me/and_me/file", "Deeply ignored"); - cl_git_pass(git_futils_mkdir_r( - "empty_standard_repo/ignore_also", NULL, 0775)); - cl_git_mkfile( - "empty_standard_repo/ignore_also/file", "I'm going to be ignored!"); - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = 6; - counts.expected_paths = paths_r; - counts.expected_statuses = statuses_r; - - opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; - - cl_git_pass(git_status_foreach_ext( - g_repo, &opts, cb_status__normal, &counts)); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); - - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = 4; - counts.expected_paths = paths_nr; - counts.expected_statuses = statuses_nr; - - opts.flags = GIT_STATUS_OPT_DEFAULTS; - - cl_git_pass(git_status_foreach_ext( - g_repo, &opts, cb_status__normal, &counts)); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - -void test_status_ignore__adding_internal_ignores(void) -{ - int ignored; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.txt")); - cl_assert(!ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); - cl_assert(!ignored); - - cl_git_pass(git_ignore_add_rule(g_repo, "*.nomatch\n")); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.txt")); - cl_assert(!ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); - cl_assert(!ignored); - - cl_git_pass(git_ignore_add_rule(g_repo, "*.txt\n")); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.txt")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); - cl_assert(!ignored); - - cl_git_pass(git_ignore_add_rule(g_repo, "*.bar\n")); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.txt")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); - cl_assert(ignored); - - cl_git_pass(git_ignore_clear_internal_rules(g_repo)); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.txt")); - cl_assert(!ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); - cl_assert(!ignored); - - cl_git_pass(git_ignore_add_rule( - g_repo, "multiple\n*.rules\n# comment line\n*.bar\n")); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.txt")); - cl_assert(!ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); - cl_assert(ignored); -} - -void test_status_ignore__add_internal_as_first_thing(void) -{ - int ignored; - const char *add_me = "\n#################\n## Eclipse\n#################\n\n*.pydevproject\n.project\n.metadata\nbin/\ntmp/\n*.tmp\n\n"; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_pass(git_ignore_add_rule(g_repo, add_me)); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.tmp")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); - cl_assert(!ignored); -} - -void test_status_ignore__internal_ignores_inside_deep_paths(void) -{ - int ignored; - const char *add_me = "Debug\nthis/is/deep\npatterned*/dir\n"; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_pass(git_ignore_add_rule(g_repo, add_me)); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "Debug")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "and/Debug")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "really/Debug/this/file")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "Debug/what/I/say")); - cl_assert(ignored); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "and/NoDebug")); - cl_assert(!ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "NoDebug/this")); - cl_assert(!ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "please/NoDebug/this")); - cl_assert(!ignored); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/is/deep")); - cl_assert(ignored); - /* pattern containing slash gets FNM_PATHNAME so all slashes must match */ - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "and/this/is/deep")); - cl_assert(!ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/is/deep/too")); - cl_assert(ignored); - /* pattern containing slash gets FNM_PATHNAME so all slashes must match */ - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "but/this/is/deep/and/ignored")); - cl_assert(!ignored); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/is/not/deep")); - cl_assert(!ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "is/this/not/as/deep")); - cl_assert(!ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/is/deepish")); - cl_assert(!ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "xthis/is/deep")); - cl_assert(!ignored); -} - -void test_status_ignore__automatically_ignore_bad_files(void) -{ - int ignored; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, ".git")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/file/.")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/../funky")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/whatever.c")); - cl_assert(!ignored); - - cl_git_pass(git_ignore_add_rule(g_repo, "*.c\n")); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, ".git")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/file/.")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/../funky")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/whatever.c")); - cl_assert(ignored); - - cl_git_pass(git_ignore_clear_internal_rules(g_repo)); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, ".git")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/file/.")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/../funky")); - cl_assert(ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/whatever.c")); - cl_assert(!ignored); -} - -void test_status_ignore__filenames_with_special_prefixes_do_not_interfere_with_status_retrieval(void) -{ - status_entry_single st; - char *test_cases[] = { - "!file", - "#blah", - "[blah]", - "[attr]", - "[attr]blah", - NULL - }; - int i; - - for (i = 0; *(test_cases + i) != NULL; i++) { - git_buf file = GIT_BUF_INIT; - char *file_name = *(test_cases + i); - git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_pass(git_buf_joinpath(&file, "empty_standard_repo", file_name)); - cl_git_mkfile(git_buf_cstr(&file), "Please don't ignore me!"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); - cl_assert(st.count == 1); - cl_assert(st.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&st.status, repo, file_name)); - cl_assert(st.status == GIT_STATUS_WT_NEW); - - cl_git_sandbox_cleanup(); - git_buf_free(&file); - } -} - -void test_status_ignore__issue_1766_negated_ignores(void) -{ - int ignored = 0; - unsigned int status; - - g_repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_pass(git_futils_mkdir_r( - "empty_standard_repo/a", NULL, 0775)); - cl_git_mkfile( - "empty_standard_repo/a/.gitignore", "*\n!.gitignore\n"); - cl_git_mkfile( - "empty_standard_repo/a/ignoreme", "I should be ignored\n"); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "a/.gitignore")); - cl_assert(!ignored); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "a/ignoreme")); - cl_assert(ignored); - - cl_git_pass(git_futils_mkdir_r( - "empty_standard_repo/b", NULL, 0775)); - cl_git_mkfile( - "empty_standard_repo/b/.gitignore", "*\n!.gitignore\n"); - cl_git_mkfile( - "empty_standard_repo/b/ignoreme", "I should be ignored\n"); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "b/.gitignore")); - cl_assert(!ignored); - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "b/ignoreme")); - cl_assert(ignored); - - /* shouldn't have changed results from first couple either */ - - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "a/.gitignore")); - cl_assert(!ignored); - cl_git_pass(git_status_should_ignore(&ignored, g_repo, "a/ignoreme")); - cl_assert(ignored); - - /* status should find the two ignore files and nothing else */ - - cl_git_pass(git_status_file(&status, g_repo, "a/.gitignore")); - cl_assert_equal_i(GIT_STATUS_WT_NEW, (int)status); - - cl_git_pass(git_status_file(&status, g_repo, "a/ignoreme")); - cl_assert_equal_i(GIT_STATUS_IGNORED, (int)status); - - cl_git_pass(git_status_file(&status, g_repo, "b/.gitignore")); - cl_assert_equal_i(GIT_STATUS_WT_NEW, (int)status); - - cl_git_pass(git_status_file(&status, g_repo, "b/ignoreme")); - cl_assert_equal_i(GIT_STATUS_IGNORED, (int)status); - - { - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - status_entry_counts counts; - static const char *paths[] = { - "a/.gitignore", - "a/ignoreme", - "b/.gitignore", - "b/ignoreme", - }; - static const unsigned int statuses[] = { - GIT_STATUS_WT_NEW, - GIT_STATUS_IGNORED, - GIT_STATUS_WT_NEW, - GIT_STATUS_IGNORED, - }; - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = 4; - counts.expected_paths = paths; - counts.expected_statuses = statuses; - - opts.flags = GIT_STATUS_OPT_DEFAULTS; - - cl_git_pass(git_status_foreach_ext( - g_repo, &opts, cb_status__normal, &counts)); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); - } -} - diff --git a/tests-clar/status/renames.c b/tests-clar/status/renames.c deleted file mode 100644 index 16fd02676..000000000 --- a/tests-clar/status/renames.c +++ /dev/null @@ -1,557 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "path.h" -#include "posix.h" -#include "status_helpers.h" -#include "util.h" -#include "status.h" - -static git_repository *g_repo = NULL; - -void test_status_renames__initialize(void) -{ - g_repo = cl_git_sandbox_init("renames"); - - cl_repo_set_bool(g_repo, "core.autocrlf", false); -} - -void test_status_renames__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -static void rename_file(git_repository *repo, const char *oldname, const char *newname) -{ - git_buf oldpath = GIT_BUF_INIT, newpath = GIT_BUF_INIT; - - git_buf_joinpath(&oldpath, git_repository_workdir(repo), oldname); - git_buf_joinpath(&newpath, git_repository_workdir(repo), newname); - - cl_git_pass(p_rename(oldpath.ptr, newpath.ptr)); - - git_buf_free(&oldpath); - git_buf_free(&newpath); -} - -static void rename_and_edit_file(git_repository *repo, const char *oldname, const char *newname) -{ - git_buf oldpath = GIT_BUF_INIT, newpath = GIT_BUF_INIT; - - git_buf_joinpath(&oldpath, git_repository_workdir(repo), oldname); - git_buf_joinpath(&newpath, git_repository_workdir(repo), newname); - - cl_git_pass(p_rename(oldpath.ptr, newpath.ptr)); - cl_git_append2file(newpath.ptr, "Added at the end to keep similarity!"); - - git_buf_free(&oldpath); - git_buf_free(&newpath); -} - -struct status_entry { - git_status_t status; - const char *oldname; - const char *newname; -}; - -static void test_status( - git_status_list *status_list, - struct status_entry *expected_list, - size_t expected_len) -{ - const git_status_entry *actual; - const struct status_entry *expected; - const char *oldname, *newname; - size_t i; - - cl_assert_equal_sz(expected_len, git_status_list_entrycount(status_list)); - - for (i = 0; i < expected_len; i++) { - actual = git_status_byindex(status_list, i); - expected = &expected_list[i]; - - oldname = actual->head_to_index ? actual->head_to_index->old_file.path : - actual->index_to_workdir ? actual->index_to_workdir->old_file.path : NULL; - - newname = actual->index_to_workdir ? actual->index_to_workdir->new_file.path : - actual->head_to_index ? actual->head_to_index->new_file.path : NULL; - - cl_assert_equal_i_fmt(expected->status, actual->status, "%04x"); - - if (oldname) - cl_assert(git__strcmp(oldname, expected->oldname) == 0); - else - cl_assert(expected->oldname == NULL); - - if (newname) - cl_assert(git__strcmp(newname, expected->newname) == 0); - else - cl_assert(expected->newname == NULL); - } -} - -void test_status_renames__head2index_one(void) -{ - git_index *index; - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - struct status_entry expected[] = { - { GIT_STATUS_INDEX_RENAMED, "ikeepsix.txt", "newname.txt" }, - }; - - opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; - - cl_git_pass(git_repository_index(&index, g_repo)); - - rename_file(g_repo, "ikeepsix.txt", "newname.txt"); - - cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_add_bypath(index, "newname.txt")); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 1); - git_status_list_free(statuslist); - - git_index_free(index); -} - -void test_status_renames__head2index_two(void) -{ - git_index *index; - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - struct status_entry expected[] = { - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED, - "sixserving.txt", "aaa.txt" }, - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED, - "untimely.txt", "bbb.txt" }, - { GIT_STATUS_INDEX_RENAMED, "songof7cities.txt", "ccc.txt" }, - { GIT_STATUS_INDEX_RENAMED, "ikeepsix.txt", "ddd.txt" }, - }; - - opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; - - cl_git_pass(git_repository_index(&index, g_repo)); - - rename_file(g_repo, "ikeepsix.txt", "ddd.txt"); - rename_and_edit_file(g_repo, "sixserving.txt", "aaa.txt"); - rename_file(g_repo, "songof7cities.txt", "ccc.txt"); - rename_and_edit_file(g_repo, "untimely.txt", "bbb.txt"); - - cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_remove_bypath(index, "sixserving.txt")); - cl_git_pass(git_index_remove_bypath(index, "songof7cities.txt")); - cl_git_pass(git_index_remove_bypath(index, "untimely.txt")); - cl_git_pass(git_index_add_bypath(index, "ddd.txt")); - cl_git_pass(git_index_add_bypath(index, "aaa.txt")); - cl_git_pass(git_index_add_bypath(index, "ccc.txt")); - cl_git_pass(git_index_add_bypath(index, "bbb.txt")); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 4); - git_status_list_free(statuslist); - - git_index_free(index); -} - -void test_status_renames__head2index_no_rename_from_rewrite(void) -{ - git_index *index; - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - struct status_entry expected[] = { - { GIT_STATUS_INDEX_MODIFIED, "ikeepsix.txt", "ikeepsix.txt" }, - { GIT_STATUS_INDEX_MODIFIED, "sixserving.txt", "sixserving.txt" }, - }; - - opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; - - cl_git_pass(git_repository_index(&index, g_repo)); - - rename_file(g_repo, "ikeepsix.txt", "_temp_.txt"); - rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); - rename_file(g_repo, "_temp_.txt", "sixserving.txt"); - - cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_add_bypath(index, "sixserving.txt")); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 2); - git_status_list_free(statuslist); - - git_index_free(index); -} - -void test_status_renames__head2index_rename_from_rewrite(void) -{ - git_index *index; - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - struct status_entry expected[] = { - { GIT_STATUS_INDEX_RENAMED, "sixserving.txt", "ikeepsix.txt" }, - { GIT_STATUS_INDEX_RENAMED, "ikeepsix.txt", "sixserving.txt" }, - }; - - opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; - opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES; - - cl_git_pass(git_repository_index(&index, g_repo)); - - rename_file(g_repo, "ikeepsix.txt", "_temp_.txt"); - rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); - rename_file(g_repo, "_temp_.txt", "sixserving.txt"); - - cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_add_bypath(index, "sixserving.txt")); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 2); - git_status_list_free(statuslist); - - git_index_free(index); -} - -void test_status_renames__index2workdir_one(void) -{ - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - struct status_entry expected[] = { - { GIT_STATUS_WT_RENAMED, "ikeepsix.txt", "newname.txt" }, - }; - - opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; - opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; - - rename_file(g_repo, "ikeepsix.txt", "newname.txt"); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 1); - git_status_list_free(statuslist); -} - -void test_status_renames__index2workdir_two(void) -{ - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - struct status_entry expected[] = { - { GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, - "sixserving.txt", "aaa.txt" }, - { GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, - "untimely.txt", "bbb.txt" }, - { GIT_STATUS_WT_RENAMED, "songof7cities.txt", "ccc.txt" }, - { GIT_STATUS_WT_RENAMED, "ikeepsix.txt", "ddd.txt" }, - }; - - opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; - opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; - - rename_file(g_repo, "ikeepsix.txt", "ddd.txt"); - rename_and_edit_file(g_repo, "sixserving.txt", "aaa.txt"); - rename_file(g_repo, "songof7cities.txt", "ccc.txt"); - rename_and_edit_file(g_repo, "untimely.txt", "bbb.txt"); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 4); - git_status_list_free(statuslist); -} - -void test_status_renames__index2workdir_rename_from_rewrite(void) -{ - git_index *index; - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - struct status_entry expected[] = { - { GIT_STATUS_WT_RENAMED, "sixserving.txt", "ikeepsix.txt" }, - { GIT_STATUS_WT_RENAMED, "ikeepsix.txt", "sixserving.txt" }, - }; - - opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; - opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES; - - cl_git_pass(git_repository_index(&index, g_repo)); - - rename_file(g_repo, "ikeepsix.txt", "_temp_.txt"); - rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); - rename_file(g_repo, "_temp_.txt", "sixserving.txt"); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 2); - git_status_list_free(statuslist); - - git_index_free(index); -} - -void test_status_renames__both_one(void) -{ - git_index *index; - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - struct status_entry expected[] = { - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, - "ikeepsix.txt", "newname-workdir.txt" }, - }; - - opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; - opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; - opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; - - cl_git_pass(git_repository_index(&index, g_repo)); - - rename_file(g_repo, "ikeepsix.txt", "newname-index.txt"); - - cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_add_bypath(index, "newname-index.txt")); - cl_git_pass(git_index_write(index)); - - rename_file(g_repo, "newname-index.txt", "newname-workdir.txt"); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 1); - git_status_list_free(statuslist); - - git_index_free(index); -} - -void test_status_renames__both_two(void) -{ - git_index *index; - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - struct status_entry expected[] = { - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED | - GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, - "ikeepsix.txt", "ikeepsix-both.txt" }, - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED, - "sixserving.txt", "sixserving-index.txt" }, - { GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, - "songof7cities.txt", "songof7cities-workdir.txt" }, - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, - "untimely.txt", "untimely-both.txt" }, - }; - - opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; - opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; - opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; - - cl_git_pass(git_repository_index(&index, g_repo)); - - rename_and_edit_file(g_repo, "ikeepsix.txt", "ikeepsix-index.txt"); - rename_and_edit_file(g_repo, "sixserving.txt", "sixserving-index.txt"); - rename_file(g_repo, "untimely.txt", "untimely-index.txt"); - - cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_remove_bypath(index, "sixserving.txt")); - cl_git_pass(git_index_remove_bypath(index, "untimely.txt")); - cl_git_pass(git_index_add_bypath(index, "ikeepsix-index.txt")); - cl_git_pass(git_index_add_bypath(index, "sixserving-index.txt")); - cl_git_pass(git_index_add_bypath(index, "untimely-index.txt")); - cl_git_pass(git_index_write(index)); - - rename_and_edit_file(g_repo, "ikeepsix-index.txt", "ikeepsix-both.txt"); - rename_and_edit_file(g_repo, "songof7cities.txt", "songof7cities-workdir.txt"); - rename_file(g_repo, "untimely-index.txt", "untimely-both.txt"); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 4); - git_status_list_free(statuslist); - - git_index_free(index); -} - - -void test_status_renames__both_rename_from_rewrite(void) -{ - git_index *index; - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - struct status_entry expected[] = { - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, - "songof7cities.txt", "ikeepsix.txt" }, - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, - "ikeepsix.txt", "sixserving.txt" }, - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, - "sixserving.txt", "songof7cities.txt" }, - }; - - opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; - opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; - opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; - opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES; - - cl_git_pass(git_repository_index(&index, g_repo)); - - rename_file(g_repo, "ikeepsix.txt", "_temp_.txt"); - rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); - rename_file(g_repo, "songof7cities.txt", "sixserving.txt"); - rename_file(g_repo, "_temp_.txt", "songof7cities.txt"); - - cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_add_bypath(index, "sixserving.txt")); - cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); - cl_git_pass(git_index_write(index)); - - rename_file(g_repo, "songof7cities.txt", "_temp_.txt"); - rename_file(g_repo, "ikeepsix.txt", "songof7cities.txt"); - rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); - rename_file(g_repo, "_temp_.txt", "sixserving.txt"); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 3); - git_status_list_free(statuslist); - - git_index_free(index); -} - -void test_status_renames__rewrites_only_for_renames(void) -{ - git_index *index; - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - struct status_entry expected[] = { - { GIT_STATUS_WT_MODIFIED, "ikeepsix.txt", "ikeepsix.txt" }, - }; - - opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; - opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; - opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; - opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES; - - cl_git_pass(git_repository_index(&index, g_repo)); - - cl_git_rewritefile("renames/ikeepsix.txt", - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n" \ - "This is enough content for the file to be rewritten.\n"); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 1); - git_status_list_free(statuslist); - - git_index_free(index); -} - -void test_status_renames__both_casechange_one(void) -{ - git_index *index; - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - int index_caps; - struct status_entry expected_icase[] = { - { GIT_STATUS_INDEX_RENAMED, - "ikeepsix.txt", "IKeepSix.txt" }, - }; - struct status_entry expected_case[] = { - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, - "ikeepsix.txt", "IKEEPSIX.txt" }, - }; - - opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; - opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; - opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; - - cl_git_pass(git_repository_index(&index, g_repo)); - index_caps = git_index_caps(index); - - rename_file(g_repo, "ikeepsix.txt", "IKeepSix.txt"); - - cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_add_bypath(index, "IKeepSix.txt")); - cl_git_pass(git_index_write(index)); - - /* on a case-insensitive file system, this change won't matter. - * on a case-sensitive one, it will. - */ - rename_file(g_repo, "IKeepSix.txt", "IKEEPSIX.txt"); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - - test_status(statuslist, (index_caps & GIT_INDEXCAP_IGNORE_CASE) ? - expected_icase : expected_case, 1); - - git_status_list_free(statuslist); - - git_index_free(index); -} - -void test_status_renames__both_casechange_two(void) -{ - git_index *index; - git_status_list *statuslist; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - int index_caps; - struct status_entry expected_icase[] = { - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED | - GIT_STATUS_WT_MODIFIED, - "ikeepsix.txt", "IKeepSix.txt" }, - { GIT_STATUS_INDEX_MODIFIED, - "sixserving.txt", "sixserving.txt" }, - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_MODIFIED, - "songof7cities.txt", "songof7.txt" }, - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, - "untimely.txt", "untimeliest.txt" } - }; - struct status_entry expected_case[] = { - { GIT_STATUS_INDEX_RENAMED | - GIT_STATUS_WT_MODIFIED | GIT_STATUS_WT_RENAMED, - "songof7cities.txt", "SONGOF7.txt" }, - { GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_RENAMED, - "sixserving.txt", "SixServing.txt" }, - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED | - GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, - "ikeepsix.txt", "ikeepsix.txt" }, - { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, - "untimely.txt", "untimeliest.txt" } - }; - - opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; - opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; - opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; - - cl_git_pass(git_repository_index(&index, g_repo)); - index_caps = git_index_caps(index); - - rename_and_edit_file(g_repo, "ikeepsix.txt", "IKeepSix.txt"); - rename_and_edit_file(g_repo, "sixserving.txt", "sixserving.txt"); - rename_file(g_repo, "songof7cities.txt", "songof7.txt"); - rename_file(g_repo, "untimely.txt", "untimelier.txt"); - - cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_remove_bypath(index, "sixserving.txt")); - cl_git_pass(git_index_remove_bypath(index, "songof7cities.txt")); - cl_git_pass(git_index_remove_bypath(index, "untimely.txt")); - cl_git_pass(git_index_add_bypath(index, "IKeepSix.txt")); - cl_git_pass(git_index_add_bypath(index, "sixserving.txt")); - cl_git_pass(git_index_add_bypath(index, "songof7.txt")); - cl_git_pass(git_index_add_bypath(index, "untimelier.txt")); - cl_git_pass(git_index_write(index)); - - rename_and_edit_file(g_repo, "IKeepSix.txt", "ikeepsix.txt"); - rename_file(g_repo, "sixserving.txt", "SixServing.txt"); - rename_and_edit_file(g_repo, "songof7.txt", "SONGOF7.txt"); - rename_file(g_repo, "untimelier.txt", "untimeliest.txt"); - - cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - - test_status(statuslist, (index_caps & GIT_INDEXCAP_IGNORE_CASE) ? - expected_icase : expected_case, 4); - - git_status_list_free(statuslist); - - git_index_free(index); -} diff --git a/tests-clar/status/single.c b/tests-clar/status/single.c deleted file mode 100644 index 292c9120a..000000000 --- a/tests-clar/status/single.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" - -static void -cleanup__remove_file(void *_file) -{ - cl_must_pass(p_unlink((char *)_file)); -} - -/* test retrieving OID from a file apart from the ODB */ -void test_status_single__hash_single_file(void) -{ - static const char file_name[] = "new_file"; - static const char file_contents[] = "new_file\n"; - static const char file_hash[] = "d4fa8600b4f37d7516bef4816ae2c64dbf029e3a"; - - git_oid expected_id, actual_id; - - /* initialization */ - git_oid_fromstr(&expected_id, file_hash); - cl_git_mkfile(file_name, file_contents); - cl_set_cleanup(&cleanup__remove_file, (void *)file_name); - - cl_git_pass(git_odb_hashfile(&actual_id, file_name, GIT_OBJ_BLOB)); - cl_assert(git_oid_cmp(&expected_id, &actual_id) == 0); -} - -/* test retrieving OID from an empty file apart from the ODB */ -void test_status_single__hash_single_empty_file(void) -{ - static const char file_name[] = "new_empty_file"; - static const char file_contents[] = ""; - static const char file_hash[] = "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"; - - git_oid expected_id, actual_id; - - /* initialization */ - git_oid_fromstr(&expected_id, file_hash); - cl_git_mkfile(file_name, file_contents); - cl_set_cleanup(&cleanup__remove_file, (void *)file_name); - - cl_git_pass(git_odb_hashfile(&actual_id, file_name, GIT_OBJ_BLOB)); - cl_assert(git_oid_cmp(&expected_id, &actual_id) == 0); -} - diff --git a/tests-clar/status/status_data.h b/tests-clar/status/status_data.h deleted file mode 100644 index 8ad4235fd..000000000 --- a/tests-clar/status/status_data.h +++ /dev/null @@ -1,326 +0,0 @@ -#include "status_helpers.h" - -// A utf-8 string with 83 characters, but 249 bytes. -static const char *longname = "\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97"; - - -/* entries for a plain copy of tests/resources/status */ - -static const char *entry_paths0[] = { - "file_deleted", - "ignored_file", - "modified_file", - "new_file", - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_file_deleted", - "staged_delete_modified_file", - "staged_new_file", - "staged_new_file_deleted_file", - "staged_new_file_modified_file", - - "subdir/deleted_file", - "subdir/modified_file", - "subdir/new_file", - - "\xe8\xbf\x99", -}; - -static const unsigned int entry_statuses0[] = { - GIT_STATUS_WT_DELETED, - GIT_STATUS_IGNORED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW, - GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_DELETED, - GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_MODIFIED, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_DELETED, - GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_MODIFIED, - - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW, - - GIT_STATUS_WT_NEW, -}; - -static const int entry_count0 = 16; - -/* entries for a copy of tests/resources/status with all content - * deleted from the working directory - */ - -static const char *entry_paths2[] = { - "current_file", - "file_deleted", - "modified_file", - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_file_deleted", - "staged_delete_modified_file", - "staged_new_file", - "staged_new_file_deleted_file", - "staged_new_file_modified_file", - "subdir.txt", - "subdir/current_file", - "subdir/deleted_file", - "subdir/modified_file", -}; - -static const unsigned int entry_statuses2[] = { - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED, -}; - -static const int entry_count2 = 15; - -/* entries for a copy of tests/resources/status with some mods */ - -static const char *entry_paths3_icase[] = { - ".HEADER", - "42-is-not-prime.sigh", - "current_file", - "current_file/", - "file_deleted", - "ignored_file", - "modified_file", - "new_file", - "README.md", - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_file_deleted", - "staged_delete_modified_file", - "staged_new_file", - "staged_new_file_deleted_file", - "staged_new_file_modified_file", - "subdir", - "subdir/current_file", - "subdir/deleted_file", - "subdir/modified_file", - "\xe8\xbf\x99", -}; - -static const unsigned int entry_statuses3_icase[] = { - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_IGNORED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, - GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_WT_NEW | GIT_STATUS_INDEX_DELETED, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_NEW, -}; - -static const char *entry_paths3[] = { - ".HEADER", - "42-is-not-prime.sigh", - "README.md", - "current_file", - "current_file/", - "file_deleted", - "ignored_file", - "modified_file", - "new_file", - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_file_deleted", - "staged_delete_modified_file", - "staged_new_file", - "staged_new_file_deleted_file", - "staged_new_file_modified_file", - "subdir", - "subdir/current_file", - "subdir/deleted_file", - "subdir/modified_file", - "\xe8\xbf\x99", -}; - -static const unsigned int entry_statuses3[] = { - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_IGNORED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW, - GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_WT_NEW | GIT_STATUS_INDEX_DELETED, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_NEW, -}; - -static const int entry_count3 = 22; - - -/* entries for a copy of tests/resources/status with some mods - * and different options to the status call - */ - -static const char *entry_paths4[] = { - ".new_file", - "current_file", - "current_file/current_file", - "current_file/modified_file", - "current_file/new_file", - "file_deleted", - "modified_file", - "new_file", - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_file_deleted", - "staged_delete_modified_file", - "staged_new_file", - "staged_new_file_deleted_file", - "staged_new_file_modified_file", - "subdir", - "subdir/current_file", - "subdir/deleted_file", - "subdir/modified_file", - "zzz_new_dir/new_file", - "zzz_new_file", - "\xe8\xbf\x99", -}; - -static const unsigned int entry_statuses4[] = { - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW, - GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_WT_NEW | GIT_STATUS_INDEX_DELETED, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_NEW, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, -}; - -static const int entry_count4 = 23; - - -/* entries for a copy of tests/resources/status with options - * passed to the status call in order to only get the differences - * between the HEAD and the index (changes to be committed) - */ - -static const char *entry_paths5[] = { - "staged_changes", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_file_deleted", - "staged_delete_modified_file", - "staged_new_file", - "staged_new_file_deleted_file", - "staged_new_file_modified_file", -}; - -static const unsigned int entry_statuses5[] = { - GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_INDEX_NEW, -}; - -static const int entry_count5 = 8; - - -/* entries for a copy of tests/resources/status with options - * passed to the status call in order to only get the differences - * between the workdir and the index (changes not staged, untracked files) - */ - -static const char *entry_paths6[] = { - "file_deleted", - "ignored_file", - "modified_file", - "new_file", - "staged_changes_file_deleted", - "staged_changes_modified_file", - "staged_delete_modified_file", - "staged_new_file_deleted_file", - "staged_new_file_modified_file", - "subdir/deleted_file", - "subdir/modified_file", - "subdir/new_file", - "\xe8\xbf\x99", -}; - -static const unsigned int entry_statuses6[] = { - GIT_STATUS_WT_DELETED, - GIT_STATUS_IGNORED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW, - GIT_STATUS_WT_NEW, -}; - -static const int entry_count6 = 13; diff --git a/tests-clar/status/status_helpers.c b/tests-clar/status/status_helpers.c deleted file mode 100644 index 902b65c4f..000000000 --- a/tests-clar/status/status_helpers.c +++ /dev/null @@ -1,101 +0,0 @@ -#include "clar_libgit2.h" -#include "status_helpers.h" - -int cb_status__normal( - const char *path, unsigned int status_flags, void *payload) -{ - status_entry_counts *counts = payload; - - if (counts->debug) - cb_status__print(path, status_flags, NULL); - - if (counts->entry_count >= counts->expected_entry_count) { - counts->wrong_status_flags_count++; - goto exit; - } - - if (strcmp(path, counts->expected_paths[counts->entry_count])) { - counts->wrong_sorted_path++; - goto exit; - } - - if (status_flags != counts->expected_statuses[counts->entry_count]) - counts->wrong_status_flags_count++; - -exit: - counts->entry_count++; - return 0; -} - -int cb_status__count(const char *p, unsigned int s, void *payload) -{ - volatile int *count = (int *)payload; - - GIT_UNUSED(p); - GIT_UNUSED(s); - - (*count)++; - - return 0; -} - -int cb_status__single(const char *p, unsigned int s, void *payload) -{ - status_entry_single *data = (status_entry_single *)payload; - - if (data->debug) - fprintf(stderr, "%02d: %s (%04x)\n", data->count, p, s); - - data->count++; - data->status = s; - - return 0; -} - -int cb_status__print( - const char *path, unsigned int status_flags, void *payload) -{ - char istatus = ' ', wstatus = ' '; - int icount = 0, wcount = 0; - - if (status_flags & GIT_STATUS_INDEX_NEW) { - istatus = 'A'; icount++; - } - if (status_flags & GIT_STATUS_INDEX_MODIFIED) { - istatus = 'M'; icount++; - } - if (status_flags & GIT_STATUS_INDEX_DELETED) { - istatus = 'D'; icount++; - } - if (status_flags & GIT_STATUS_INDEX_RENAMED) { - istatus = 'R'; icount++; - } - if (status_flags & GIT_STATUS_INDEX_TYPECHANGE) { - istatus = 'T'; icount++; - } - - if (status_flags & GIT_STATUS_WT_NEW) { - wstatus = 'A'; wcount++; - } - if (status_flags & GIT_STATUS_WT_MODIFIED) { - wstatus = 'M'; wcount++; - } - if (status_flags & GIT_STATUS_WT_DELETED) { - wstatus = 'D'; wcount++; - } - if (status_flags & GIT_STATUS_WT_TYPECHANGE) { - wstatus = 'T'; wcount++; - } - if (status_flags & GIT_STATUS_IGNORED) { - wstatus = 'I'; wcount++; - } - - fprintf(stderr, "%c%c %s (%d/%d%s)\n", - istatus, wstatus, path, icount, wcount, - (icount > 1 || wcount > 1) ? " INVALID COMBO" : ""); - - if (payload) - *((int *)payload) += 1; - - return 0; -} diff --git a/tests-clar/status/status_helpers.h b/tests-clar/status/status_helpers.h deleted file mode 100644 index f1f009e02..000000000 --- a/tests-clar/status/status_helpers.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef INCLUDE_cl_status_helpers_h__ -#define INCLUDE_cl_status_helpers_h__ - -typedef struct { - int wrong_status_flags_count; - int wrong_sorted_path; - int entry_count; - const unsigned int* expected_statuses; - const char** expected_paths; - int expected_entry_count; - bool debug; -} status_entry_counts; - -/* cb_status__normal takes payload of "status_entry_counts *" */ - -extern int cb_status__normal( - const char *path, unsigned int status_flags, void *payload); - - -/* cb_status__count takes payload of "int *" */ - -extern int cb_status__count(const char *p, unsigned int s, void *payload); - - -typedef struct { - int count; - unsigned int status; - bool debug; -} status_entry_single; - -/* cb_status__single takes payload of "status_entry_single *" */ - -extern int cb_status__single(const char *p, unsigned int s, void *payload); - -/* cb_status__print takes optional payload of "int *" */ - -extern int cb_status__print(const char *p, unsigned int s, void *payload); - -#endif diff --git a/tests-clar/status/submodules.c b/tests-clar/status/submodules.c deleted file mode 100644 index ef2888f7d..000000000 --- a/tests-clar/status/submodules.c +++ /dev/null @@ -1,223 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "path.h" -#include "posix.h" -#include "status_helpers.h" -#include "../submodule/submodule_helpers.h" - -static git_repository *g_repo = NULL; - -void test_status_submodules__initialize(void) -{ -} - -void test_status_submodules__cleanup(void) -{ -} - -void test_status_submodules__api(void) -{ - git_submodule *sm; - - g_repo = setup_fixture_submodules(); - - cl_assert(git_submodule_lookup(NULL, g_repo, "nonexistent") == GIT_ENOTFOUND); - - cl_assert(git_submodule_lookup(NULL, g_repo, "modified") == GIT_ENOTFOUND); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo")); - cl_assert(sm != NULL); - cl_assert_equal_s("testrepo", git_submodule_name(sm)); - cl_assert_equal_s("testrepo", git_submodule_path(sm)); -} - -void test_status_submodules__0(void) -{ - int counts = 0; - - g_repo = setup_fixture_submodules(); - - cl_assert(git_path_isdir("submodules/.git")); - cl_assert(git_path_isdir("submodules/testrepo/.git")); - cl_assert(git_path_isfile("submodules/.gitmodules")); - - cl_git_pass( - git_status_foreach(g_repo, cb_status__count, &counts) - ); - - cl_assert_equal_i(6, counts); -} - -static const char *expected_files[] = { - ".gitmodules", - "added", - "deleted", - "ignored", - "modified", - "untracked" -}; - -static unsigned int expected_status[] = { - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_IGNORED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW -}; - -static int cb_status__match(const char *p, unsigned int s, void *payload) -{ - status_entry_counts *counts = payload; - int idx = counts->entry_count++; - - cl_assert_equal_s(counts->expected_paths[idx], p); - cl_assert(counts->expected_statuses[idx] == s); - - return 0; -} - -void test_status_submodules__1(void) -{ - status_entry_counts counts; - - g_repo = setup_fixture_submodules(); - - cl_assert(git_path_isdir("submodules/.git")); - cl_assert(git_path_isdir("submodules/testrepo/.git")); - cl_assert(git_path_isfile("submodules/.gitmodules")); - - memset(&counts, 0, sizeof(counts)); - counts.expected_paths = expected_files; - counts.expected_statuses = expected_status; - - cl_git_pass( - git_status_foreach(g_repo, cb_status__match, &counts) - ); - - cl_assert_equal_i(6, counts.entry_count); -} - -void test_status_submodules__single_file(void) -{ - unsigned int status = 0; - g_repo = setup_fixture_submodules(); - cl_git_pass( git_status_file(&status, g_repo, "testrepo") ); - cl_assert(!status); -} - -void test_status_submodules__moved_head(void) -{ - git_submodule *sm; - git_repository *smrepo; - git_oid oid; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - status_entry_counts counts; - static const char *expected_files_with_sub[] = { - ".gitmodules", - "added", - "deleted", - "ignored", - "modified", - "testrepo", - "untracked" - }; - static unsigned int expected_status_with_sub[] = { - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_IGNORED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW - }; - - g_repo = setup_fixture_submodules(); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo")); - cl_git_pass(git_submodule_open(&smrepo, sm)); - - /* move submodule HEAD to c47800c7266a2be04c571c04d5a6614691ea99bd */ - cl_git_pass( - git_oid_fromstr(&oid, "c47800c7266a2be04c571c04d5a6614691ea99bd")); - cl_git_pass(git_repository_set_head_detached(smrepo, &oid)); - - /* first do a normal status, which should now include the submodule */ - - memset(&counts, 0, sizeof(counts)); - counts.expected_paths = expected_files_with_sub; - counts.expected_statuses = expected_status_with_sub; - - opts.flags = GIT_STATUS_OPT_DEFAULTS; - - cl_git_pass( - git_status_foreach_ext(g_repo, &opts, cb_status__match, &counts)); - cl_assert_equal_i(7, counts.entry_count); - - /* try again with EXCLUDE_SUBMODULES which should skip it */ - - memset(&counts, 0, sizeof(counts)); - counts.expected_paths = expected_files; - counts.expected_statuses = expected_status; - - opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_EXCLUDE_SUBMODULES; - - cl_git_pass( - git_status_foreach_ext(g_repo, &opts, cb_status__match, &counts)); - cl_assert_equal_i(6, counts.entry_count); - - git_repository_free(smrepo); -} - -void test_status_submodules__dirty_workdir_only(void) -{ - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - status_entry_counts counts; - static const char *expected_files_with_sub[] = { - ".gitmodules", - "added", - "deleted", - "ignored", - "modified", - "testrepo", - "untracked" - }; - static unsigned int expected_status_with_sub[] = { - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_INDEX_NEW, - GIT_STATUS_INDEX_DELETED, - GIT_STATUS_IGNORED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW - }; - - g_repo = setup_fixture_submodules(); - - cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); - cl_git_mkfile("submodules/testrepo/all_new.txt", "never seen before"); - - /* first do a normal status, which should now include the submodule */ - - memset(&counts, 0, sizeof(counts)); - counts.expected_paths = expected_files_with_sub; - counts.expected_statuses = expected_status_with_sub; - - opts.flags = GIT_STATUS_OPT_DEFAULTS; - - cl_git_pass( - git_status_foreach_ext(g_repo, &opts, cb_status__match, &counts)); - cl_assert_equal_i(7, counts.entry_count); - - /* try again with EXCLUDE_SUBMODULES which should skip it */ - - memset(&counts, 0, sizeof(counts)); - counts.expected_paths = expected_files; - counts.expected_statuses = expected_status; - - opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_EXCLUDE_SUBMODULES; - - cl_git_pass( - git_status_foreach_ext(g_repo, &opts, cb_status__match, &counts)); - cl_assert_equal_i(6, counts.entry_count); -} diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c deleted file mode 100644 index 34be6d34c..000000000 --- a/tests-clar/status/worktree.c +++ /dev/null @@ -1,875 +0,0 @@ -#include "clar_libgit2.h" -#include "fileops.h" -#include "ignore.h" -#include "status_data.h" -#include "posix.h" -#include "util.h" -#include "path.h" - -/** - * Cleanup - * - * This will be called once after each test finishes, even - * if the test failed - */ -void test_status_worktree__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -/** - * Tests - Status determination on a working tree - */ -/* this test is equivalent to t18-status.c:statuscb0 */ -void test_status_worktree__whole_repository(void) -{ - status_entry_counts counts; - git_repository *repo = cl_git_sandbox_init("status"); - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = entry_count0; - counts.expected_paths = entry_paths0; - counts.expected_statuses = entry_statuses0; - - cl_git_pass( - git_status_foreach(repo, cb_status__normal, &counts) - ); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - -void assert_show(const int entry_counts, const char *entry_paths[], - const unsigned int entry_statuses[], git_status_show_t show) -{ - status_entry_counts counts; - git_repository *repo = cl_git_sandbox_init("status"); - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = entry_counts; - counts.expected_paths = entry_paths; - counts.expected_statuses = entry_statuses; - - opts.flags = GIT_STATUS_OPT_DEFAULTS; - opts.show = show; - - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) - ); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - -void test_status_worktree__show_index_and_workdir(void) -{ - assert_show(entry_count0, entry_paths0, entry_statuses0, - GIT_STATUS_SHOW_INDEX_AND_WORKDIR); -} - -void test_status_worktree__show_index_only(void) -{ - assert_show(entry_count5, entry_paths5, entry_statuses5, - GIT_STATUS_SHOW_INDEX_ONLY); -} - -void test_status_worktree__show_workdir_only(void) -{ - assert_show(entry_count6, entry_paths6, entry_statuses6, - GIT_STATUS_SHOW_WORKDIR_ONLY); -} - -/* this test is equivalent to t18-status.c:statuscb1 */ -void test_status_worktree__empty_repository(void) -{ - int count = 0; - git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_pass(git_status_foreach(repo, cb_status__count, &count)); - - cl_assert_equal_i(0, count); -} - -static int remove_file_cb(void *data, git_buf *file) -{ - const char *filename = git_buf_cstr(file); - - GIT_UNUSED(data); - - if (git__suffixcmp(filename, ".git") == 0) - return 0; - - if (git_path_isdir(filename)) - cl_git_pass(git_futils_rmdir_r(filename, NULL, GIT_RMDIR_REMOVE_FILES)); - else - cl_git_pass(p_unlink(git_buf_cstr(file))); - - return 0; -} - -/* this test is equivalent to t18-status.c:statuscb2 */ -void test_status_worktree__purged_worktree(void) -{ - status_entry_counts counts; - git_repository *repo = cl_git_sandbox_init("status"); - git_buf workdir = GIT_BUF_INIT; - - /* first purge the contents of the worktree */ - cl_git_pass(git_buf_sets(&workdir, git_repository_workdir(repo))); - cl_git_pass(git_path_direach(&workdir, 0, remove_file_cb, NULL)); - git_buf_free(&workdir); - - /* now get status */ - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = entry_count2; - counts.expected_paths = entry_paths2; - counts.expected_statuses = entry_statuses2; - - cl_git_pass( - git_status_foreach(repo, cb_status__normal, &counts) - ); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - -/* this test is similar to t18-status.c:statuscb3 */ -void test_status_worktree__swap_subdir_and_file(void) -{ - status_entry_counts counts; - git_repository *repo = cl_git_sandbox_init("status"); - git_index *index; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - bool ignore_case; - - cl_git_pass(git_repository_index(&index, repo)); - ignore_case = (git_index_caps(index) & GIT_INDEXCAP_IGNORE_CASE) != 0; - git_index_free(index); - - /* first alter the contents of the worktree */ - cl_git_pass(p_rename("status/current_file", "status/swap")); - cl_git_pass(p_rename("status/subdir", "status/current_file")); - cl_git_pass(p_rename("status/swap", "status/subdir")); - - cl_git_mkfile("status/.HEADER", "dummy"); - cl_git_mkfile("status/42-is-not-prime.sigh", "dummy"); - cl_git_mkfile("status/README.md", "dummy"); - - /* now get status */ - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = entry_count3; - counts.expected_paths = ignore_case ? entry_paths3_icase : entry_paths3; - counts.expected_statuses = ignore_case ? entry_statuses3_icase : entry_statuses3; - - opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | - GIT_STATUS_OPT_INCLUDE_IGNORED; - - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) - ); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - -void test_status_worktree__swap_subdir_with_recurse_and_pathspec(void) -{ - status_entry_counts counts; - git_repository *repo = cl_git_sandbox_init("status"); - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - - /* first alter the contents of the worktree */ - cl_git_pass(p_rename("status/current_file", "status/swap")); - cl_git_pass(p_rename("status/subdir", "status/current_file")); - cl_git_pass(p_rename("status/swap", "status/subdir")); - cl_git_mkfile("status/.new_file", "dummy"); - cl_git_pass(git_futils_mkdir_r("status/zzz_new_dir", NULL, 0777)); - cl_git_mkfile("status/zzz_new_dir/new_file", "dummy"); - cl_git_mkfile("status/zzz_new_file", "dummy"); - - /* now get status */ - memset(&counts, 0x0, sizeof(status_entry_counts)); - counts.expected_entry_count = entry_count4; - counts.expected_paths = entry_paths4; - counts.expected_statuses = entry_statuses4; - - opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | - GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; - /* TODO: set pathspec to "current_file" eventually */ - - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) - ); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - -/* this test is equivalent to t18-status.c:singlestatus0 */ -void test_status_worktree__single_file(void) -{ - int i; - unsigned int status_flags; - git_repository *repo = cl_git_sandbox_init("status"); - - for (i = 0; i < (int)entry_count0; i++) { - cl_git_pass( - git_status_file(&status_flags, repo, entry_paths0[i]) - ); - cl_assert(entry_statuses0[i] == status_flags); - } -} - -/* this test is equivalent to t18-status.c:singlestatus1 */ -void test_status_worktree__single_nonexistent_file(void) -{ - int error; - unsigned int status_flags; - git_repository *repo = cl_git_sandbox_init("status"); - - error = git_status_file(&status_flags, repo, "nonexistent"); - cl_git_fail(error); - cl_assert(error == GIT_ENOTFOUND); -} - -/* this test is equivalent to t18-status.c:singlestatus2 */ -void test_status_worktree__single_nonexistent_file_empty_repo(void) -{ - int error; - unsigned int status_flags; - git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); - - error = git_status_file(&status_flags, repo, "nonexistent"); - cl_git_fail(error); - cl_assert(error == GIT_ENOTFOUND); -} - -/* this test is equivalent to t18-status.c:singlestatus3 */ -void test_status_worktree__single_file_empty_repo(void) -{ - unsigned int status_flags; - git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); - - cl_git_mkfile("empty_standard_repo/new_file", "new_file\n"); - - cl_git_pass(git_status_file(&status_flags, repo, "new_file")); - cl_assert(status_flags == GIT_STATUS_WT_NEW); -} - -/* this test is equivalent to t18-status.c:singlestatus4 */ -void test_status_worktree__single_folder(void) -{ - int error; - unsigned int status_flags; - git_repository *repo = cl_git_sandbox_init("status"); - - error = git_status_file(&status_flags, repo, "subdir"); - cl_git_fail(error); - cl_assert(error != GIT_ENOTFOUND); -} - - -void test_status_worktree__ignores(void) -{ - int i, ignored; - git_repository *repo = cl_git_sandbox_init("status"); - - for (i = 0; i < (int)entry_count0; i++) { - cl_git_pass( - git_status_should_ignore(&ignored, repo, entry_paths0[i]) - ); - cl_assert(ignored == (entry_statuses0[i] == GIT_STATUS_IGNORED)); - } - - cl_git_pass( - git_status_should_ignore(&ignored, repo, "nonexistent_file") - ); - cl_assert(!ignored); - - cl_git_pass( - git_status_should_ignore(&ignored, repo, "ignored_nonexistent_file") - ); - cl_assert(ignored); -} - -static int cb_status__check_592(const char *p, unsigned int s, void *payload) -{ - if (s != GIT_STATUS_WT_DELETED || - (payload != NULL && strcmp(p, (const char *)payload) != 0)) - return -1; - - return 0; -} - -void test_status_worktree__issue_592(void) -{ - git_repository *repo; - git_buf path = GIT_BUF_INIT; - - repo = cl_git_sandbox_init("issue_592"); - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "l.txt")); - cl_git_pass(p_unlink(git_buf_cstr(&path))); - cl_assert(!git_path_exists("issue_592/l.txt")); - - cl_git_pass(git_status_foreach(repo, cb_status__check_592, "l.txt")); - - git_buf_free(&path); -} - -void test_status_worktree__issue_592_2(void) -{ - git_repository *repo; - git_buf path = GIT_BUF_INIT; - - repo = cl_git_sandbox_init("issue_592"); - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "c/a.txt")); - cl_git_pass(p_unlink(git_buf_cstr(&path))); - cl_assert(!git_path_exists("issue_592/c/a.txt")); - - cl_git_pass(git_status_foreach(repo, cb_status__check_592, "c/a.txt")); - - git_buf_free(&path); -} - -void test_status_worktree__issue_592_3(void) -{ - git_repository *repo; - git_buf path = GIT_BUF_INIT; - - repo = cl_git_sandbox_init("issue_592"); - - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "c")); - cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); - cl_assert(!git_path_exists("issue_592/c/a.txt")); - - cl_git_pass(git_status_foreach(repo, cb_status__check_592, "c/a.txt")); - - git_buf_free(&path); -} - -void test_status_worktree__issue_592_4(void) -{ - git_repository *repo; - git_buf path = GIT_BUF_INIT; - - repo = cl_git_sandbox_init("issue_592"); - - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "t/b.txt")); - cl_git_pass(p_unlink(git_buf_cstr(&path))); - - cl_git_pass(git_status_foreach(repo, cb_status__check_592, "t/b.txt")); - - git_buf_free(&path); -} - -void test_status_worktree__issue_592_5(void) -{ - git_repository *repo; - git_buf path = GIT_BUF_INIT; - - repo = cl_git_sandbox_init("issue_592"); - - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "t")); - cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); - cl_git_pass(p_mkdir(git_buf_cstr(&path), 0777)); - - cl_git_pass(git_status_foreach(repo, cb_status__check_592, NULL)); - - git_buf_free(&path); -} - -void test_status_worktree__issue_592_ignores_0(void) -{ - int count = 0; - status_entry_single st; - git_repository *repo = cl_git_sandbox_init("issue_592"); - - cl_git_pass(git_status_foreach(repo, cb_status__count, &count)); - cl_assert_equal_i(0, count); - - cl_git_rewritefile("issue_592/.gitignore", - ".gitignore\n*.txt\nc/\n[tT]*/\n"); - - cl_git_pass(git_status_foreach(repo, cb_status__count, &count)); - cl_assert_equal_i(1, count); - - /* This is a situation where the behavior of libgit2 is - * different from core git. Core git will show ignored.txt - * in the list of ignored files, even though the directory - * "t" is ignored and the file is untracked because we have - * the explicit "*.txt" ignore rule. Libgit2 just excludes - * all untracked files that are contained within ignored - * directories without explicitly listing them. - */ - cl_git_rewritefile("issue_592/t/ignored.txt", "ping"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); - cl_assert_equal_i(1, st.count); - cl_assert(st.status == GIT_STATUS_IGNORED); - - cl_git_rewritefile("issue_592/c/ignored_by_dir", "ping"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); - cl_assert_equal_i(1, st.count); - cl_assert(st.status == GIT_STATUS_IGNORED); - - cl_git_rewritefile("issue_592/t/ignored_by_dir_pattern", "ping"); - - memset(&st, 0, sizeof(st)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); - cl_assert_equal_i(1, st.count); - cl_assert(st.status == GIT_STATUS_IGNORED); -} - -void test_status_worktree__issue_592_ignored_dirs_with_tracked_content(void) -{ - int count = 0; - git_repository *repo = cl_git_sandbox_init("issue_592b"); - - cl_git_pass(git_status_foreach(repo, cb_status__count, &count)); - cl_assert_equal_i(1, count); - - /* if we are really mimicking core git, then only ignored1.txt - * at the top level will show up in the ignores list here. - * everything else will be unmodified or skipped completely. - */ -} - -void test_status_worktree__conflict_with_diff3(void) -{ - git_repository *repo = cl_git_sandbox_init("status"); - git_index *index; - unsigned int status; - git_index_entry ancestor_entry, our_entry, their_entry; - - memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); - memset(&our_entry, 0x0, sizeof(git_index_entry)); - memset(&their_entry, 0x0, sizeof(git_index_entry)); - - ancestor_entry.path = "modified_file"; - git_oid_fromstr(&ancestor_entry.oid, - "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); - - our_entry.path = "modified_file"; - git_oid_fromstr(&our_entry.oid, - "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); - - their_entry.path = "modified_file"; - git_oid_fromstr(&their_entry.oid, - "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); - - cl_git_pass(git_status_file(&status, repo, "modified_file")); - cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_remove(index, "modified_file", 0)); - cl_git_pass(git_index_conflict_add( - index, &ancestor_entry, &our_entry, &their_entry)); - cl_git_pass(git_index_write(index)); - git_index_free(index); - - cl_git_pass(git_status_file(&status, repo, "modified_file")); - - cl_assert_equal_i(GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW, status); -} - -static const char *filemode_paths[] = { - "exec_off", - "exec_off2on_staged", - "exec_off2on_workdir", - "exec_off_untracked", - "exec_on", - "exec_on2off_staged", - "exec_on2off_workdir", - "exec_on_untracked", -}; - -static unsigned int filemode_statuses[] = { - GIT_STATUS_CURRENT, - GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW, - GIT_STATUS_CURRENT, - GIT_STATUS_INDEX_MODIFIED, - GIT_STATUS_WT_MODIFIED, - GIT_STATUS_WT_NEW -}; - -static const int filemode_count = 8; - -void test_status_worktree__filemode_changes(void) -{ - git_repository *repo = cl_git_sandbox_init("filemodes"); - status_entry_counts counts; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - - /* overwrite stored filemode with platform appropriate value */ - if (cl_is_chmod_supported()) - cl_repo_set_bool(repo, "core.filemode", true); - else { - int i; - - cl_repo_set_bool(repo, "core.filemode", false); - - /* won't trust filesystem mode diffs, so these will appear unchanged */ - for (i = 0; i < filemode_count; ++i) - if (filemode_statuses[i] == GIT_STATUS_WT_MODIFIED) - filemode_statuses[i] = GIT_STATUS_CURRENT; - } - - opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | - GIT_STATUS_OPT_INCLUDE_IGNORED | - GIT_STATUS_OPT_INCLUDE_UNMODIFIED; - - memset(&counts, 0, sizeof(counts)); - counts.expected_entry_count = filemode_count; - counts.expected_paths = filemode_paths; - counts.expected_statuses = filemode_statuses; - - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) - ); - - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - -static int cb_status__interrupt(const char *p, unsigned int s, void *payload) -{ - volatile int *count = (int *)payload; - - GIT_UNUSED(p); - GIT_UNUSED(s); - - (*count)++; - - return (*count == 8); -} - -void test_status_worktree__interruptable_foreach(void) -{ - int count = 0; - git_repository *repo = cl_git_sandbox_init("status"); - - cl_assert_equal_i( - GIT_EUSER, git_status_foreach(repo, cb_status__interrupt, &count) - ); - - cl_assert_equal_i(8, count); -} - -void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf(void) -{ - git_repository *repo = cl_git_sandbox_init("status"); - unsigned int status; - - cl_repo_set_bool(repo, "core.autocrlf", true); - - cl_git_rewritefile("status/current_file", "current_file\r\n"); - - cl_git_pass(git_status_file(&status, repo, "current_file")); - - cl_assert_equal_i(GIT_STATUS_CURRENT, status); -} - -void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf_issue_1397(void) -{ - git_repository *repo = cl_git_sandbox_init("issue_1397"); - unsigned int status; - - cl_repo_set_bool(repo, "core.autocrlf", true); - - cl_git_pass(git_status_file(&status, repo, "crlf_file.txt")); - - cl_assert_equal_i(GIT_STATUS_CURRENT, status); -} - -void test_status_worktree__conflicted_item(void) -{ - git_repository *repo = cl_git_sandbox_init("status"); - git_index *index; - unsigned int status; - git_index_entry ancestor_entry, our_entry, their_entry; - - memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); - memset(&our_entry, 0x0, sizeof(git_index_entry)); - memset(&their_entry, 0x0, sizeof(git_index_entry)); - - ancestor_entry.path = "modified_file"; - git_oid_fromstr(&ancestor_entry.oid, - "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); - - our_entry.path = "modified_file"; - git_oid_fromstr(&our_entry.oid, - "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); - - their_entry.path = "modified_file"; - git_oid_fromstr(&their_entry.oid, - "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); - - cl_git_pass(git_status_file(&status, repo, "modified_file")); - cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_conflict_add(index, &ancestor_entry, - &our_entry, &their_entry)); - - cl_git_pass(git_status_file(&status, repo, "modified_file")); - cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); - - git_index_free(index); -} - -static void stage_and_commit(git_repository *repo, const char *path) -{ - git_index *index; - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add_bypath(index, path)); - cl_repo_commit_from_index(NULL, repo, NULL, 1323847743, "Initial commit\n"); - git_index_free(index); -} - -static void assert_ignore_case( - bool should_ignore_case, - int expected_lower_cased_file_status, - int expected_camel_cased_file_status) -{ - unsigned int status; - git_buf lower_case_path = GIT_BUF_INIT, camel_case_path = GIT_BUF_INIT; - git_repository *repo, *repo2; - - repo = cl_git_sandbox_init("empty_standard_repo"); - cl_git_remove_placeholders(git_repository_path(repo), "dummy-marker.txt"); - - cl_repo_set_bool(repo, "core.ignorecase", should_ignore_case); - - cl_git_pass(git_buf_joinpath(&lower_case_path, - git_repository_workdir(repo), "plop")); - - cl_git_mkfile(git_buf_cstr(&lower_case_path), ""); - - stage_and_commit(repo, "plop"); - - cl_git_pass(git_repository_open(&repo2, "./empty_standard_repo")); - - cl_git_pass(git_status_file(&status, repo2, "plop")); - cl_assert_equal_i(GIT_STATUS_CURRENT, status); - - cl_git_pass(git_buf_joinpath(&camel_case_path, - git_repository_workdir(repo), "Plop")); - - cl_git_pass(p_rename(git_buf_cstr(&lower_case_path), git_buf_cstr(&camel_case_path))); - - cl_git_pass(git_status_file(&status, repo2, "plop")); - cl_assert_equal_i(expected_lower_cased_file_status, status); - - cl_git_pass(git_status_file(&status, repo2, "Plop")); - cl_assert_equal_i(expected_camel_cased_file_status, status); - - git_repository_free(repo2); - git_buf_free(&lower_case_path); - git_buf_free(&camel_case_path); -} - -void test_status_worktree__file_status_honors_core_ignorecase_true(void) -{ - assert_ignore_case(true, GIT_STATUS_CURRENT, GIT_STATUS_CURRENT); -} - -void test_status_worktree__file_status_honors_core_ignorecase_false(void) -{ - assert_ignore_case(false, GIT_STATUS_WT_DELETED, GIT_STATUS_WT_NEW); -} - -void test_status_worktree__file_status_honors_case_ignorecase_regarding_untracked_files(void) -{ - git_repository *repo = cl_git_sandbox_init("status"); - unsigned int status; - git_index *index; - - cl_repo_set_bool(repo, "core.ignorecase", false); - - repo = cl_git_sandbox_reopen(); - - /* Actually returns GIT_STATUS_IGNORED on Windows */ - cl_git_fail_with(git_status_file(&status, repo, "NEW_FILE"), GIT_ENOTFOUND); - - cl_git_pass(git_repository_index(&index, repo)); - - cl_git_pass(git_index_add_bypath(index, "new_file")); - cl_git_pass(git_index_write(index)); - git_index_free(index); - - /* Actually returns GIT_STATUS_IGNORED on Windows */ - cl_git_fail_with(git_status_file(&status, repo, "NEW_FILE"), GIT_ENOTFOUND); -} - -void test_status_worktree__simple_delete(void) -{ - git_repository *repo = cl_git_sandbox_init("renames"); - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - int count; - - opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | - GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH | - GIT_STATUS_OPT_EXCLUDE_SUBMODULES | - GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; - - count = 0; - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__count, &count) ); - cl_assert_equal_i(0, count); - - cl_must_pass(p_unlink("renames/untimely.txt")); - - count = 0; - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__count, &count) ); - cl_assert_equal_i(1, count); -} - -void test_status_worktree__simple_delete_indexed(void) -{ - git_repository *repo = cl_git_sandbox_init("renames"); - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - git_status_list *status; - - opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | - GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH | - GIT_STATUS_OPT_EXCLUDE_SUBMODULES | - GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; - - cl_git_pass(git_status_list_new(&status, repo, &opts)); - cl_assert_equal_sz(0, git_status_list_entrycount(status)); - git_status_list_free(status); - - cl_must_pass(p_unlink("renames/untimely.txt")); - - cl_git_pass(git_status_list_new(&status, repo, &opts)); - cl_assert_equal_sz(1, git_status_list_entrycount(status)); - cl_assert_equal_i( - GIT_STATUS_WT_DELETED, git_status_byindex(status, 0)->status); - git_status_list_free(status); -} - -static const char *icase_paths[] = { "B", "c", "g", "H" }; -static unsigned int icase_statuses[] = { - GIT_STATUS_WT_MODIFIED, GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_MODIFIED, GIT_STATUS_WT_DELETED, -}; - -static const char *case_paths[] = { "B", "H", "c", "g" }; -static unsigned int case_statuses[] = { - GIT_STATUS_WT_MODIFIED, GIT_STATUS_WT_DELETED, - GIT_STATUS_WT_DELETED, GIT_STATUS_WT_MODIFIED, -}; - -void test_status_worktree__sorting_by_case(void) -{ - git_repository *repo = cl_git_sandbox_init("icase"); - git_index *index; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - bool native_ignore_case; - status_entry_counts counts; - - cl_git_pass(git_repository_index(&index, repo)); - native_ignore_case = - (git_index_caps(index) & GIT_INDEXCAP_IGNORE_CASE) != 0; - git_index_free(index); - - memset(&counts, 0, sizeof(counts)); - counts.expected_entry_count = 0; - counts.expected_paths = NULL; - counts.expected_statuses = NULL; - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__normal, &counts)); - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); - - cl_git_rewritefile("icase/B", "new stuff"); - cl_must_pass(p_unlink("icase/c")); - cl_git_rewritefile("icase/g", "new stuff"); - cl_must_pass(p_unlink("icase/H")); - - memset(&counts, 0, sizeof(counts)); - counts.expected_entry_count = 4; - if (native_ignore_case) { - counts.expected_paths = icase_paths; - counts.expected_statuses = icase_statuses; - } else { - counts.expected_paths = case_paths; - counts.expected_statuses = case_statuses; - } - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__normal, &counts)); - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); - - opts.flags = GIT_STATUS_OPT_SORT_CASE_SENSITIVELY; - - memset(&counts, 0, sizeof(counts)); - counts.expected_entry_count = 4; - counts.expected_paths = case_paths; - counts.expected_statuses = case_statuses; - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__normal, &counts)); - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); - - opts.flags = GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY; - - memset(&counts, 0, sizeof(counts)); - counts.expected_entry_count = 4; - counts.expected_paths = icase_paths; - counts.expected_statuses = icase_statuses; - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__normal, &counts)); - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - -void test_status_worktree__long_filenames(void) -{ - char path[260*4+1]; - const char *expected_paths[] = {path}; - const unsigned int expected_statuses[] = {GIT_STATUS_WT_NEW}; - - git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - status_entry_counts counts = {0}; - - // Create directory with amazingly long filename - sprintf(path, "empty_standard_repo/%s", longname); - cl_git_pass(git_futils_mkdir_r(path, NULL, 0777)); - sprintf(path, "empty_standard_repo/%s/foo", longname); - cl_git_mkfile(path, "dummy"); - - sprintf(path, "%s/foo", longname); - counts.expected_entry_count = 1; - counts.expected_paths = expected_paths; - counts.expected_statuses = expected_statuses; - - opts.show = GIT_STATUS_SHOW_WORKDIR_ONLY; - opts.flags = GIT_STATUS_OPT_DEFAULTS; - - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) ); - cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); - cl_assert_equal_i(0, counts.wrong_status_flags_count); - cl_assert_equal_i(0, counts.wrong_sorted_path); -} - diff --git a/tests-clar/status/worktree_init.c b/tests-clar/status/worktree_init.c deleted file mode 100644 index 296c27c86..000000000 --- a/tests-clar/status/worktree_init.c +++ /dev/null @@ -1,341 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/sys/repository.h" - -#include "fileops.h" -#include "ignore.h" -#include "status_helpers.h" -#include "posix.h" -#include "util.h" -#include "path.h" - -static void cleanup_new_repo(void *path) -{ - cl_fixture_cleanup((char *)path); -} - -void test_status_worktree_init__cannot_retrieve_the_status_of_a_bare_repository(void) -{ - git_repository *repo; - unsigned int status = 0; - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - cl_assert_equal_i(GIT_EBAREREPO, git_status_file(&status, repo, "dummy")); - git_repository_free(repo); -} - -void test_status_worktree_init__first_commit_in_progress(void) -{ - git_repository *repo; - git_index *index; - status_entry_single result; - - cl_set_cleanup(&cleanup_new_repo, "getting_started"); - - cl_git_pass(git_repository_init(&repo, "getting_started", 0)); - cl_git_mkfile("getting_started/testfile.txt", "content\n"); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(1, result.count); - cl_assert(result.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add_bypath(index, "testfile.txt")); - cl_git_pass(git_index_write(index)); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(1, result.count); - cl_assert(result.status == GIT_STATUS_INDEX_NEW); - - git_index_free(index); - git_repository_free(repo); -} - - - -void test_status_worktree_init__status_file_without_index_or_workdir(void) -{ - git_repository *repo; - unsigned int status = 0; - git_index *index; - - cl_git_pass(p_mkdir("wd", 0777)); - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_repository_set_workdir(repo, "wd", false)); - - cl_git_pass(git_index_open(&index, "empty-index")); - cl_assert_equal_i(0, (int)git_index_entrycount(index)); - git_repository_set_index(repo, index); - - cl_git_pass(git_status_file(&status, repo, "branch_file.txt")); - - cl_assert_equal_i(GIT_STATUS_INDEX_DELETED, status); - - git_repository_free(repo); - git_index_free(index); - cl_git_pass(p_rmdir("wd")); -} - -static void fill_index_wth_head_entries(git_repository *repo, git_index *index) -{ - git_oid oid; - git_commit *commit; - git_tree *tree; - - cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_commit_tree(&tree, commit)); - - cl_git_pass(git_index_read_tree(index, tree)); - cl_git_pass(git_index_write(index)); - - git_tree_free(tree); - git_commit_free(commit); -} - -void test_status_worktree_init__status_file_with_clean_index_and_empty_workdir(void) -{ - git_repository *repo; - unsigned int status = 0; - git_index *index; - - cl_git_pass(p_mkdir("wd", 0777)); - - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - cl_git_pass(git_repository_set_workdir(repo, "wd", false)); - - cl_git_pass(git_index_open(&index, "my-index")); - fill_index_wth_head_entries(repo, index); - - git_repository_set_index(repo, index); - - cl_git_pass(git_status_file(&status, repo, "branch_file.txt")); - - cl_assert_equal_i(GIT_STATUS_WT_DELETED, status); - - git_repository_free(repo); - git_index_free(index); - cl_git_pass(p_rmdir("wd")); - cl_git_pass(p_unlink("my-index")); -} - -void test_status_worktree_init__bracket_in_filename(void) -{ - git_repository *repo; - git_index *index; - status_entry_single result; - unsigned int status_flags; - int error; - - #define FILE_WITH_BRACKET "LICENSE[1].md" - #define FILE_WITHOUT_BRACKET "LICENSE1.md" - - cl_set_cleanup(&cleanup_new_repo, "with_bracket"); - - cl_git_pass(git_repository_init(&repo, "with_bracket", 0)); - cl_git_mkfile("with_bracket/" FILE_WITH_BRACKET, "I have a bracket in my name\n"); - - /* file is new to working directory */ - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(1, result.count); - cl_assert(result.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); - cl_assert(status_flags == GIT_STATUS_WT_NEW); - - /* ignore the file */ - - cl_git_rewritefile("with_bracket/.gitignore", "*.md\n.gitignore\n"); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(2, result.count); - cl_assert(result.status == GIT_STATUS_IGNORED); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); - cl_assert(status_flags == GIT_STATUS_IGNORED); - - /* don't ignore the file */ - - cl_git_rewritefile("with_bracket/.gitignore", ".gitignore\n"); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(2, result.count); - cl_assert(result.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); - cl_assert(status_flags == GIT_STATUS_WT_NEW); - - /* add the file to the index */ - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add_bypath(index, FILE_WITH_BRACKET)); - cl_git_pass(git_index_write(index)); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(2, result.count); - cl_assert(result.status == GIT_STATUS_INDEX_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); - cl_assert(status_flags == GIT_STATUS_INDEX_NEW); - - /* Create file without bracket */ - - cl_git_mkfile("with_bracket/" FILE_WITHOUT_BRACKET, "I have no bracket in my name!\n"); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITHOUT_BRACKET)); - cl_assert(status_flags == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, "LICENSE\\[1\\].md")); - cl_assert(status_flags == GIT_STATUS_INDEX_NEW); - - error = git_status_file(&status_flags, repo, FILE_WITH_BRACKET); - cl_git_fail(error); - cl_assert_equal_i(GIT_EAMBIGUOUS, error); - - git_index_free(index); - git_repository_free(repo); -} - -void test_status_worktree_init__space_in_filename(void) -{ - git_repository *repo; - git_index *index; - status_entry_single result; - unsigned int status_flags; - -#define FILE_WITH_SPACE "LICENSE - copy.md" - - cl_set_cleanup(&cleanup_new_repo, "with_space"); - cl_git_pass(git_repository_init(&repo, "with_space", 0)); - cl_git_mkfile("with_space/" FILE_WITH_SPACE, "I have a space in my name\n"); - - /* file is new to working directory */ - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(1, result.count); - cl_assert(result.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); - cl_assert(status_flags == GIT_STATUS_WT_NEW); - - /* ignore the file */ - - cl_git_rewritefile("with_space/.gitignore", "*.md\n.gitignore\n"); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(2, result.count); - cl_assert(result.status == GIT_STATUS_IGNORED); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); - cl_assert(status_flags == GIT_STATUS_IGNORED); - - /* don't ignore the file */ - - cl_git_rewritefile("with_space/.gitignore", ".gitignore\n"); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(2, result.count); - cl_assert(result.status == GIT_STATUS_WT_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); - cl_assert(status_flags == GIT_STATUS_WT_NEW); - - /* add the file to the index */ - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add_bypath(index, FILE_WITH_SPACE)); - cl_git_pass(git_index_write(index)); - - memset(&result, 0, sizeof(result)); - cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); - cl_assert_equal_i(2, result.count); - cl_assert(result.status == GIT_STATUS_INDEX_NEW); - - cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); - cl_assert(status_flags == GIT_STATUS_INDEX_NEW); - - git_index_free(index); - git_repository_free(repo); -} - -static int cb_status__expected_path(const char *p, unsigned int s, void *payload) -{ - const char *expected_path = (const char *)payload; - - GIT_UNUSED(s); - - if (payload == NULL) - cl_fail("Unexpected path"); - - cl_assert_equal_s(expected_path, p); - - return 0; -} - -void test_status_worktree_init__disable_pathspec_match(void) -{ - git_repository *repo; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - char *file_with_bracket = "LICENSE[1].md", - *imaginary_file_with_bracket = "LICENSE[1-2].md"; - - cl_set_cleanup(&cleanup_new_repo, "pathspec"); - cl_git_pass(git_repository_init(&repo, "pathspec", 0)); - cl_git_mkfile("pathspec/LICENSE[1].md", "screaming bracket\n"); - cl_git_mkfile("pathspec/LICENSE1.md", "no bracket\n"); - - opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | - GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH; - opts.pathspec.count = 1; - opts.pathspec.strings = &file_with_bracket; - - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__expected_path, - file_with_bracket) - ); - - /* Test passing a pathspec matching files in the workdir. */ - /* Must not match because pathspecs are disabled. */ - opts.pathspec.strings = &imaginary_file_with_bracket; - cl_git_pass( - git_status_foreach_ext(repo, &opts, cb_status__expected_path, NULL) - ); - - git_repository_free(repo); -} - -void test_status_worktree_init__new_staged_file_must_handle_crlf(void) -{ - git_repository *repo; - git_index *index; - unsigned int status; - - cl_set_cleanup(&cleanup_new_repo, "getting_started"); - cl_git_pass(git_repository_init(&repo, "getting_started", 0)); - - /* Ensure that repo has core.autocrlf=true */ - cl_repo_set_bool(repo, "core.autocrlf", true); - - cl_git_mkfile("getting_started/testfile.txt", "content\r\n"); /* Content with CRLF */ - - cl_git_pass(git_repository_index(&index, repo)); - cl_git_pass(git_index_add_bypath(index, "testfile.txt")); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_status_file(&status, repo, "testfile.txt")); - cl_assert_equal_i(GIT_STATUS_INDEX_NEW, status); - - git_index_free(index); - git_repository_free(repo); -} - diff --git a/tests-clar/stress/diff.c b/tests-clar/stress/diff.c deleted file mode 100644 index 3d2092614..000000000 --- a/tests-clar/stress/diff.c +++ /dev/null @@ -1,146 +0,0 @@ -#include "clar_libgit2.h" -#include "../diff/diff_helpers.h" - -static git_repository *g_repo = NULL; - -void test_stress_diff__initialize(void) -{ -} - -void test_stress_diff__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - -#define ANOTHER_POEM \ -"OH, glorious are the guarded heights\nWhere guardian souls abide—\nSelf-exiled from our gross delights—\nAbove, beyond, outside:\nAn ampler arc their spirit swings—\nCommands a juster view—\nWe have their word for all these things,\nNo doubt their words are true.\n\nYet we, the bond slaves of our day,\nWhom dirt and danger press—\nCo-heirs of insolence, delay,\nAnd leagued unfaithfulness—\nSuch is our need must seek indeed\nAnd, having found, engage\nThe men who merely do the work\nFor which they draw the wage.\n\nFrom forge and farm and mine and bench,\nDeck, altar, outpost lone—\nMill, school, battalion, counter, trench,\nRail, senate, sheepfold, throne—\nCreation's cry goes up on high\nFrom age to cheated age:\n\"Send us the men who do the work\n\"For which they draw the wage!\"\n" - -static void test_with_many(int expected_new) -{ - git_index *index; - git_tree *tree, *new_tree; - git_diff *diff = NULL; - diff_expects exp; - git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; - git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass( - git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); - - cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/ikeepsix2.txt")); - cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); - cl_git_pass(git_index_add_bypath(index, "ikeepsix2.txt")); - cl_git_pass(git_index_write(index)); - - cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &exp)); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(expected_new + 2, exp.files); - - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &exp)); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(expected_new + 1, exp.files); - - git_diff_free(diff); - - cl_repo_commit_from_index(NULL, g_repo, NULL, 1372350000, "yoyoyo"); - cl_git_pass(git_revparse_single( - (git_object **)&new_tree, g_repo, "HEAD^{tree}")); - - cl_git_pass(git_diff_tree_to_tree( - &diff, g_repo, tree, new_tree, &diffopts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &exp)); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); - cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(expected_new + 2, exp.files); - - opts.flags = GIT_DIFF_FIND_ALL; - cl_git_pass(git_diff_find_similar(diff, &opts)); - - memset(&exp, 0, sizeof(exp)); - cl_git_pass(git_diff_foreach( - diff, diff_file_cb, NULL, NULL, &exp)); - cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); - cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); - cl_assert_equal_i(expected_new + 1, exp.files); - - git_diff_free(diff); - - git_tree_free(new_tree); - git_tree_free(tree); - git_index_free(index); -} - -void test_stress_diff__rename_big_files(void) -{ - git_index *index; - char tmp[64]; - int i, j; - git_buf b = GIT_BUF_INIT; - - g_repo = cl_git_sandbox_init("renames"); - - cl_git_pass(git_repository_index(&index, g_repo)); - - for (i = 0; i < 100; i += 1) { - snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); - for (j = i * 256; j > 0; --j) - git_buf_printf(&b, "more content %d\n", i); - cl_git_mkfile(tmp, b.ptr); - } - - for (i = 0; i < 100; i += 1) { - snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); - cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/"))); - } - - git_buf_free(&b); - git_index_free(index); - - test_with_many(100); -} - -void test_stress_diff__rename_many_files(void) -{ - git_index *index; - char tmp[64]; - int i; - git_buf b = GIT_BUF_INIT; - - g_repo = cl_git_sandbox_init("renames"); - - cl_git_pass(git_repository_index(&index, g_repo)); - - git_buf_printf(&b, "%08d\n" ANOTHER_POEM "%08d\n" ANOTHER_POEM ANOTHER_POEM, 0, 0); - - for (i = 0; i < 2500; i += 1) { - snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); - snprintf(b.ptr, 9, "%08d", i); - b.ptr[8] = '\n'; - cl_git_mkfile(tmp, b.ptr); - } - git_buf_free(&b); - - for (i = 0; i < 2500; i += 1) { - snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); - cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/"))); - } - - git_index_free(index); - - test_with_many(2500); -} diff --git a/tests-clar/submodule/lookup.c b/tests-clar/submodule/lookup.c deleted file mode 100644 index 5f320e702..000000000 --- a/tests-clar/submodule/lookup.c +++ /dev/null @@ -1,172 +0,0 @@ -#include "clar_libgit2.h" -#include "submodule_helpers.h" -#include "posix.h" -#include "git2/sys/repository.h" - -static git_repository *g_repo = NULL; - -void test_submodule_lookup__initialize(void) -{ - g_repo = setup_fixture_submod2(); -} - -void test_submodule_lookup__simple_lookup(void) -{ - git_submodule *sm; - - /* lookup existing */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_assert(sm); - - /* lookup pending change in .gitmodules that is not in HEAD */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_assert(sm); - - /* lookup pending change in .gitmodules that is neither in HEAD nor index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); - cl_assert(sm); - - /* lookup git repo subdir that is not added as submodule */ - cl_assert(git_submodule_lookup(&sm, g_repo, "not-submodule") == GIT_EEXISTS); - - /* lookup existing directory that is not a submodule */ - cl_assert(git_submodule_lookup(&sm, g_repo, "just_a_dir") == GIT_ENOTFOUND); - - /* lookup existing file that is not a submodule */ - cl_assert(git_submodule_lookup(&sm, g_repo, "just_a_file") == GIT_ENOTFOUND); - - /* lookup non-existent item */ - cl_assert(git_submodule_lookup(&sm, g_repo, "no_such_file") == GIT_ENOTFOUND); -} - -void test_submodule_lookup__accessors(void) -{ - git_submodule *sm; - const char *oid = "480095882d281ed676fe5b863569520e54a7d5c0"; - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_assert(git_submodule_owner(sm) == g_repo); - cl_assert_equal_s("sm_unchanged", git_submodule_name(sm)); - cl_assert(git__suffixcmp(git_submodule_path(sm), "sm_unchanged") == 0); - cl_assert(git__suffixcmp(git_submodule_url(sm), "/submod2_target") == 0); - - cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0); - cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0); - cl_assert(git_oid_streq(git_submodule_wd_id(sm), oid) == 0); - - cl_assert(git_submodule_ignore(sm) == GIT_SUBMODULE_IGNORE_NONE); - cl_assert(git_submodule_update(sm) == GIT_SUBMODULE_UPDATE_CHECKOUT); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_assert_equal_s("sm_changed_head", git_submodule_name(sm)); - - cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0); - cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0); - cl_assert(git_oid_streq(git_submodule_wd_id(sm), - "3d9386c507f6b093471a3e324085657a3c2b4247") == 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_assert_equal_s("sm_added_and_uncommited", git_submodule_name(sm)); - - cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0); - cl_assert(git_submodule_head_id(sm) == NULL); - cl_assert(git_oid_streq(git_submodule_wd_id(sm), oid) == 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); - cl_assert_equal_s("sm_missing_commits", git_submodule_name(sm)); - - cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0); - cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0); - cl_assert(git_oid_streq(git_submodule_wd_id(sm), - "5e4963595a9774b90524d35a807169049de8ccad") == 0); -} - -typedef struct { - int count; -} sm_lookup_data; - -static int sm_lookup_cb(git_submodule *sm, const char *name, void *payload) -{ - sm_lookup_data *data = payload; - data->count += 1; - cl_assert_equal_s(git_submodule_name(sm), name); - return 0; -} - -void test_submodule_lookup__foreach(void) -{ - sm_lookup_data data; - memset(&data, 0, sizeof(data)); - cl_git_pass(git_submodule_foreach(g_repo, sm_lookup_cb, &data)); - cl_assert_equal_i(8, data.count); -} - -void test_submodule_lookup__lookup_even_with_unborn_head(void) -{ - git_reference *head; - git_submodule *sm; - - /* put us on an unborn branch */ - cl_git_pass(git_reference_symbolic_create( - &head, g_repo, "HEAD", "refs/heads/garbage", 1)); - git_reference_free(head); - - /* lookup existing */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_assert(sm); - - /* lookup pending change in .gitmodules that is not in HEAD */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_assert(sm); - - /* lookup pending change in .gitmodules that is neither in HEAD nor index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); - cl_assert(sm); - - /* lookup git repo subdir that is not added as submodule */ - cl_assert_equal_i(GIT_EEXISTS, git_submodule_lookup(&sm, g_repo, "not-submodule")); - - /* lookup existing directory that is not a submodule */ - cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_dir")); - - /* lookup existing file that is not a submodule */ - cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_file")); - - /* lookup non-existent item */ - cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "no_such_file")); -} - -void test_submodule_lookup__lookup_even_with_missing_index(void) -{ - git_index *idx; - git_submodule *sm; - - /* give the repo an empty index */ - cl_git_pass(git_index_new(&idx)); - git_repository_set_index(g_repo, idx); - git_index_free(idx); - - /* lookup existing */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_assert(sm); - - /* lookup pending change in .gitmodules that is not in HEAD */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_assert(sm); - - /* lookup pending change in .gitmodules that is neither in HEAD nor index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); - cl_assert(sm); - - /* lookup git repo subdir that is not added as submodule */ - cl_assert_equal_i(GIT_EEXISTS, git_submodule_lookup(&sm, g_repo, "not-submodule")); - - /* lookup existing directory that is not a submodule */ - cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_dir")); - - /* lookup existing file that is not a submodule */ - cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_file")); - - /* lookup non-existent item */ - cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "no_such_file")); -} diff --git a/tests-clar/submodule/modify.c b/tests-clar/submodule/modify.c deleted file mode 100644 index e326287a6..000000000 --- a/tests-clar/submodule/modify.c +++ /dev/null @@ -1,253 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" -#include "path.h" -#include "submodule_helpers.h" - -static git_repository *g_repo = NULL; - -#define SM_LIBGIT2_URL "https://github.com/libgit2/libgit2.git" -#define SM_LIBGIT2 "sm_libgit2" -#define SM_LIBGIT2B "sm_libgit2b" - -void test_submodule_modify__initialize(void) -{ - g_repo = setup_fixture_submod2(); -} - -void test_submodule_modify__add(void) -{ - git_submodule *sm; - git_config *cfg; - const char *s; - - /* re-add existing submodule */ - cl_assert( - git_submodule_add_setup(NULL, g_repo, "whatever", "sm_unchanged", 1) == - GIT_EEXISTS ); - - /* add a submodule using a gitlink */ - - cl_git_pass( - git_submodule_add_setup(&sm, g_repo, SM_LIBGIT2_URL, SM_LIBGIT2, 1) - ); - - cl_assert(git_path_isfile("submod2/" SM_LIBGIT2 "/.git")); - - cl_assert(git_path_isdir("submod2/.git/modules")); - cl_assert(git_path_isdir("submod2/.git/modules/" SM_LIBGIT2)); - cl_assert(git_path_isfile("submod2/.git/modules/" SM_LIBGIT2 "/HEAD")); - - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass( - git_config_get_string(&s, cfg, "submodule." SM_LIBGIT2 ".url")); - cl_assert_equal_s(s, SM_LIBGIT2_URL); - git_config_free(cfg); - - /* add a submodule not using a gitlink */ - - cl_git_pass( - git_submodule_add_setup(&sm, g_repo, SM_LIBGIT2_URL, SM_LIBGIT2B, 0) - ); - - cl_assert(git_path_isdir("submod2/" SM_LIBGIT2B "/.git")); - cl_assert(git_path_isfile("submod2/" SM_LIBGIT2B "/.git/HEAD")); - cl_assert(!git_path_exists("submod2/.git/modules/" SM_LIBGIT2B)); - - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass( - git_config_get_string(&s, cfg, "submodule." SM_LIBGIT2B ".url")); - cl_assert_equal_s(s, SM_LIBGIT2_URL); - git_config_free(cfg); -} - -static int delete_one_config(const git_config_entry *entry, void *payload) -{ - git_config *cfg = payload; - return git_config_delete_entry(cfg, entry->name); -} - -static int init_one_submodule( - git_submodule *sm, const char *name, void *payload) -{ - GIT_UNUSED(name); - GIT_UNUSED(payload); - return git_submodule_init(sm, false); -} - -void test_submodule_modify__init(void) -{ - git_config *cfg; - const char *str; - - /* erase submodule data from .git/config */ - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass( - git_config_foreach_match(cfg, "submodule\\..*", delete_one_config, cfg)); - git_config_free(cfg); - - /* confirm no submodule data in config */ - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_fail(git_config_get_string(&str, cfg, "submodule.sm_unchanged.url")); - cl_git_fail(git_config_get_string(&str, cfg, "submodule.sm_changed_head.url")); - cl_git_fail(git_config_get_string(&str, cfg, "submodule.sm_added_and_uncommited.url")); - git_config_free(cfg); - - /* call init and see that settings are copied */ - cl_git_pass(git_submodule_foreach(g_repo, init_one_submodule, NULL)); - - git_submodule_reload_all(g_repo); - - /* confirm submodule data in config */ - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_get_string(&str, cfg, "submodule.sm_unchanged.url")); - cl_assert(git__suffixcmp(str, "/submod2_target") == 0); - cl_git_pass(git_config_get_string(&str, cfg, "submodule.sm_changed_head.url")); - cl_assert(git__suffixcmp(str, "/submod2_target") == 0); - cl_git_pass(git_config_get_string(&str, cfg, "submodule.sm_added_and_uncommited.url")); - cl_assert(git__suffixcmp(str, "/submod2_target") == 0); - git_config_free(cfg); -} - -static int sync_one_submodule( - git_submodule *sm, const char *name, void *payload) -{ - GIT_UNUSED(name); - GIT_UNUSED(payload); - return git_submodule_sync(sm); -} - -void test_submodule_modify__sync(void) -{ - git_submodule *sm1, *sm2, *sm3; - git_config *cfg; - const char *str; - -#define SM1 "sm_unchanged" -#define SM2 "sm_changed_head" -#define SM3 "sm_added_and_uncommited" - - /* look up some submodules */ - cl_git_pass(git_submodule_lookup(&sm1, g_repo, SM1)); - cl_git_pass(git_submodule_lookup(&sm2, g_repo, SM2)); - cl_git_pass(git_submodule_lookup(&sm3, g_repo, SM3)); - - /* At this point, the .git/config URLs for the submodules have - * not be rewritten with the absolute paths (although the - * .gitmodules have. Let's confirm that they DO NOT match - * yet, then we can do a sync to make them match... - */ - - /* check submodule info does not match before sync */ - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM1".url")); - cl_assert(strcmp(git_submodule_url(sm1), str) != 0); - cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM2".url")); - cl_assert(strcmp(git_submodule_url(sm2), str) != 0); - cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM3".url")); - cl_assert(strcmp(git_submodule_url(sm3), str) != 0); - git_config_free(cfg); - - /* sync all the submodules */ - cl_git_pass(git_submodule_foreach(g_repo, sync_one_submodule, NULL)); - - /* check that submodule config is updated */ - cl_git_pass(git_repository_config(&cfg, g_repo)); - cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM1".url")); - cl_assert_equal_s(git_submodule_url(sm1), str); - cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM2".url")); - cl_assert_equal_s(git_submodule_url(sm2), str); - cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM3".url")); - cl_assert_equal_s(git_submodule_url(sm3), str); - git_config_free(cfg); -} - -void test_submodule_modify__edit_and_save(void) -{ - git_submodule *sm1, *sm2; - char *old_url; - git_submodule_ignore_t old_ignore; - git_submodule_update_t old_update; - git_repository *r2; - int old_fetchrecurse; - - cl_git_pass(git_submodule_lookup(&sm1, g_repo, "sm_changed_head")); - - old_url = git__strdup(git_submodule_url(sm1)); - - /* modify properties of submodule */ - cl_git_pass(git_submodule_set_url(sm1, SM_LIBGIT2_URL)); - old_ignore = git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_UNTRACKED); - old_update = git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_REBASE); - old_fetchrecurse = git_submodule_set_fetch_recurse_submodules(sm1, 1); - - cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm1)); - cl_assert_equal_i( - (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm1)); - cl_assert_equal_i( - (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm1)); - cl_assert_equal_i(1, git_submodule_fetch_recurse_submodules(sm1)); - - /* revert without saving (and confirm setters return old value) */ - cl_git_pass(git_submodule_set_url(sm1, old_url)); - cl_assert_equal_i( - (int)GIT_SUBMODULE_IGNORE_UNTRACKED, - (int)git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_RESET)); - cl_assert_equal_i( - (int)GIT_SUBMODULE_UPDATE_REBASE, - (int)git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_RESET)); - cl_assert_equal_i( - 1, git_submodule_set_fetch_recurse_submodules(sm1, old_fetchrecurse)); - - /* check that revert was successful */ - cl_assert_equal_s(old_url, git_submodule_url(sm1)); - cl_assert_equal_i((int)old_ignore, (int)git_submodule_ignore(sm1)); - cl_assert_equal_i((int)old_update, (int)git_submodule_update(sm1)); - cl_assert_equal_i( - old_fetchrecurse, git_submodule_fetch_recurse_submodules(sm1)); - - /* modify properties of submodule (again) */ - cl_git_pass(git_submodule_set_url(sm1, SM_LIBGIT2_URL)); - git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_UNTRACKED); - git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_REBASE); - git_submodule_set_fetch_recurse_submodules(sm1, 1); - - /* call save */ - cl_git_pass(git_submodule_save(sm1)); - - /* attempt to "revert" values */ - git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_RESET); - git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_RESET); - - /* but ignore and update should NOT revert because the RESET - * should now be the newly saved value... - */ - cl_assert_equal_i( - (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm1)); - cl_assert_equal_i( - (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm1)); - cl_assert_equal_i(1, git_submodule_fetch_recurse_submodules(sm1)); - - /* call reload and check that the new values are loaded */ - cl_git_pass(git_submodule_reload(sm1)); - - cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm1)); - cl_assert_equal_i( - (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm1)); - cl_assert_equal_i( - (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm1)); - cl_assert_equal_i(1, git_submodule_fetch_recurse_submodules(sm1)); - - /* open a second copy of the repo and compare submodule */ - cl_git_pass(git_repository_open(&r2, "submod2")); - cl_git_pass(git_submodule_lookup(&sm2, r2, "sm_changed_head")); - - cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm2)); - cl_assert_equal_i( - (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm2)); - cl_assert_equal_i( - (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm2)); - cl_assert_equal_i(1, git_submodule_fetch_recurse_submodules(sm2)); - - git_repository_free(r2); - git__free(old_url); -} diff --git a/tests-clar/submodule/status.c b/tests-clar/submodule/status.c deleted file mode 100644 index f5111c84f..000000000 --- a/tests-clar/submodule/status.c +++ /dev/null @@ -1,425 +0,0 @@ -#include "clar_libgit2.h" -#include "posix.h" -#include "path.h" -#include "submodule_helpers.h" -#include "fileops.h" -#include "iterator.h" - -static git_repository *g_repo = NULL; - -void test_submodule_status__initialize(void) -{ - g_repo = setup_fixture_submod2(); -} - -void test_submodule_status__cleanup(void) -{ -} - -void test_submodule_status__unchanged(void) -{ - unsigned int status, expected; - git_submodule *sm; - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - expected = GIT_SUBMODULE_STATUS_IN_HEAD | - GIT_SUBMODULE_STATUS_IN_INDEX | - GIT_SUBMODULE_STATUS_IN_CONFIG | - GIT_SUBMODULE_STATUS_IN_WD; - - cl_assert(status == expected); -} - -/* 4 values of GIT_SUBMODULE_IGNORE to check */ - -void test_submodule_status__ignore_none(void) -{ - unsigned int status; - git_submodule *sm; - git_buf path = GIT_BUF_INIT; - - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged")); - cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); - - cl_assert_equal_i(GIT_ENOTFOUND, - git_submodule_lookup(&sm, g_repo, "just_a_dir")); - cl_assert_equal_i(GIT_EEXISTS, - git_submodule_lookup(&sm, g_repo, "not-submodule")); - cl_assert_equal_i(GIT_EEXISTS, - git_submodule_lookup(&sm, g_repo, "not")); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) != 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) != 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNTRACKED) != 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0); - - /* removed sm_unchanged for deleted workdir */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0); - - /* now mkdir sm_unchanged to test uninitialized */ - cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_reload(sm)); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0); - - /* update sm_changed_head in index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_add_to_index(sm, true)); - /* reload is not needed because add_to_index updates the submodule data */ - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0); - - /* remove sm_changed_head from index */ - { - git_index *index; - size_t pos; - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_assert(!git_index_find(&pos, index, "sm_changed_head")); - cl_git_pass(git_index_remove(index, "sm_changed_head", 0)); - cl_git_pass(git_index_write(index)); - - git_index_free(index); - } - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_reload(sm)); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_DELETED) != 0); - - git_buf_free(&path); -} - -static int set_sm_ignore(git_submodule *sm, const char *name, void *payload) -{ - git_submodule_ignore_t ignore = *(git_submodule_ignore_t *)payload; - GIT_UNUSED(name); - git_submodule_set_ignore(sm, ignore); - return 0; -} - -void test_submodule_status__ignore_untracked(void) -{ - unsigned int status; - git_submodule *sm; - git_buf path = GIT_BUF_INIT; - git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_UNTRACKED; - - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged")); - cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); - - cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign)); - - cl_git_fail(git_submodule_lookup(&sm, g_repo, "not-submodule")); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) != 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) != 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0); - - /* removed sm_unchanged for deleted workdir */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0); - - /* now mkdir sm_unchanged to test uninitialized */ - cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_reload(sm)); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0); - - /* update sm_changed_head in index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_add_to_index(sm, true)); - /* reload is not needed because add_to_index updates the submodule data */ - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0); - - git_buf_free(&path); -} - -void test_submodule_status__ignore_dirty(void) -{ - unsigned int status; - git_submodule *sm; - git_buf path = GIT_BUF_INIT; - git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_DIRTY; - - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged")); - cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); - - cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign)); - - cl_assert_equal_i(GIT_ENOTFOUND, - git_submodule_lookup(&sm, g_repo, "just_a_dir")); - cl_assert_equal_i(GIT_EEXISTS, - git_submodule_lookup(&sm, g_repo, "not-submodule")); - cl_assert_equal_i(GIT_EEXISTS, - git_submodule_lookup(&sm, g_repo, "not")); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0); - - /* removed sm_unchanged for deleted workdir */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0); - - /* now mkdir sm_unchanged to test uninitialized */ - cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_reload(sm)); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0); - - /* update sm_changed_head in index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_add_to_index(sm, true)); - /* reload is not needed because add_to_index updates the submodule data */ - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0); - - git_buf_free(&path); -} - -void test_submodule_status__ignore_all(void) -{ - unsigned int status; - git_submodule *sm; - git_buf path = GIT_BUF_INIT; - git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_ALL; - - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged")); - cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); - - cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign)); - - cl_assert_equal_i(GIT_ENOTFOUND, - git_submodule_lookup(&sm, g_repo, "just_a_dir")); - cl_assert_equal_i(GIT_EEXISTS, - git_submodule_lookup(&sm, g_repo, "not-submodule")); - cl_assert_equal_i(GIT_EEXISTS, - git_submodule_lookup(&sm, g_repo, "not")); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - /* removed sm_unchanged for deleted workdir */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - /* now mkdir sm_unchanged to test uninitialized */ - cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_reload(sm)); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - /* update sm_changed_head in index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_add_to_index(sm, true)); - /* reload is not needed because add_to_index updates the submodule data */ - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - git_buf_free(&path); -} - -typedef struct { - size_t counter; - const char **paths; - int *statuses; -} submodule_expectations; - -static int confirm_submodule_status( - const char *path, unsigned int status_flags, void *payload) -{ - submodule_expectations *exp = payload; - - while (git__suffixcmp(exp->paths[exp->counter], "/") == 0) - exp->counter++; - - cl_assert_equal_i(exp->statuses[exp->counter], (int)status_flags); - cl_assert_equal_s(exp->paths[exp->counter++], path); - - GIT_UNUSED(status_flags); - - return 0; -} - -void test_submodule_status__iterator(void) -{ - git_iterator *iter; - const git_index_entry *entry; - size_t i; - static const char *expected[] = { - ".gitmodules", - "just_a_dir/", - "just_a_dir/contents", - "just_a_file", - "not", - "not-submodule", - "README.txt", - "sm_added_and_uncommited", - "sm_changed_file", - "sm_changed_head", - "sm_changed_index", - "sm_changed_untracked_file", - "sm_missing_commits", - "sm_unchanged", - NULL - }; - static int expected_flags[] = { - GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_MODIFIED, /* ".gitmodules" */ - 0, /* "just_a_dir/" will be skipped */ - GIT_STATUS_CURRENT, /* "just_a_dir/contents" */ - GIT_STATUS_CURRENT, /* "just_a_file" */ - GIT_STATUS_IGNORED, /* "not" (contains .git) */ - GIT_STATUS_IGNORED, /* "not-submodule" (contains .git) */ - GIT_STATUS_CURRENT, /* "README.txt */ - GIT_STATUS_INDEX_NEW, /* "sm_added_and_uncommited" */ - GIT_STATUS_WT_MODIFIED, /* "sm_changed_file" */ - GIT_STATUS_WT_MODIFIED, /* "sm_changed_head" */ - GIT_STATUS_WT_MODIFIED, /* "sm_changed_index" */ - GIT_STATUS_WT_MODIFIED, /* "sm_changed_untracked_file" */ - GIT_STATUS_WT_MODIFIED, /* "sm_missing_commits" */ - GIT_STATUS_CURRENT, /* "sm_unchanged" */ - 0 - }; - submodule_expectations exp = { 0, expected, expected_flags }; - git_status_options opts = GIT_STATUS_OPTIONS_INIT; - - cl_git_pass(git_iterator_for_workdir(&iter, g_repo, - GIT_ITERATOR_IGNORE_CASE | GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); - - for (i = 0; !git_iterator_advance(&entry, iter); ++i) - cl_assert_equal_s(expected[i], entry->path); - - git_iterator_free(iter); - - opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | - GIT_STATUS_OPT_INCLUDE_UNMODIFIED | - GIT_STATUS_OPT_INCLUDE_IGNORED | - GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS | - GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY; - - cl_git_pass(git_status_foreach_ext( - g_repo, &opts, confirm_submodule_status, &exp)); -} - -void test_submodule_status__untracked_dirs_containing_ignored_files(void) -{ - git_buf path = GIT_BUF_INIT; - unsigned int status, expected; - git_submodule *sm; - - cl_git_pass(git_buf_joinpath(&path, git_repository_path(g_repo), "modules/sm_unchanged/info/exclude")); - cl_git_append2file(git_buf_cstr(&path), "\n*.ignored\n"); - - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged/directory")); - cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); - cl_git_pass(git_buf_joinpath(&path, git_buf_cstr(&path), "i_am.ignored")); - cl_git_mkfile(git_buf_cstr(&path), "ignored this file, please\n"); - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_status(&status, sm)); - - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - expected = GIT_SUBMODULE_STATUS_IN_HEAD | - GIT_SUBMODULE_STATUS_IN_INDEX | - GIT_SUBMODULE_STATUS_IN_CONFIG | - GIT_SUBMODULE_STATUS_IN_WD; - - cl_assert(status == expected); - - git_buf_free(&path); -} diff --git a/tests-clar/submodule/submodule_helpers.c b/tests-clar/submodule/submodule_helpers.c deleted file mode 100644 index d5750675c..000000000 --- a/tests-clar/submodule/submodule_helpers.c +++ /dev/null @@ -1,127 +0,0 @@ -#include "clar_libgit2.h" -#include "buffer.h" -#include "path.h" -#include "util.h" -#include "posix.h" -#include "submodule_helpers.h" -#include "git2/sys/repository.h" - -/* rewrite gitmodules -> .gitmodules - * rewrite the empty or relative urls inside each module - * rename the .gitted directory inside any submodule to .git - */ -void rewrite_gitmodules(const char *workdir) -{ - git_buf in_f = GIT_BUF_INIT, out_f = GIT_BUF_INIT, path = GIT_BUF_INIT; - FILE *in, *out; - char line[256]; - - cl_git_pass(git_buf_joinpath(&in_f, workdir, "gitmodules")); - cl_git_pass(git_buf_joinpath(&out_f, workdir, ".gitmodules")); - - cl_assert((in = fopen(in_f.ptr, "r")) != NULL); - cl_assert((out = fopen(out_f.ptr, "w")) != NULL); - - while (fgets(line, sizeof(line), in) != NULL) { - char *scan = line; - - while (*scan == ' ' || *scan == '\t') scan++; - - /* rename .gitted -> .git in submodule directories */ - if (git__prefixcmp(scan, "path =") == 0) { - scan += strlen("path ="); - while (*scan == ' ') scan++; - - git_buf_joinpath(&path, workdir, scan); - git_buf_rtrim(&path); - git_buf_joinpath(&path, path.ptr, ".gitted"); - - if (!git_buf_oom(&path) && p_access(path.ptr, F_OK) == 0) { - git_buf_joinpath(&out_f, workdir, scan); - git_buf_rtrim(&out_f); - git_buf_joinpath(&out_f, out_f.ptr, ".git"); - - if (!git_buf_oom(&out_f)) - p_rename(path.ptr, out_f.ptr); - } - } - - /* copy non-"url =" lines verbatim */ - if (git__prefixcmp(scan, "url =") != 0) { - fputs(line, out); - continue; - } - - /* convert relative URLs in "url =" lines */ - scan += strlen("url ="); - while (*scan == ' ') scan++; - - if (*scan == '.') { - git_buf_joinpath(&path, workdir, scan); - git_buf_rtrim(&path); - } else if (!*scan || *scan == '\n') { - git_buf_joinpath(&path, workdir, "../testrepo.git"); - } else { - fputs(line, out); - continue; - } - - git_path_prettify(&path, path.ptr, NULL); - git_buf_putc(&path, '\n'); - cl_assert(!git_buf_oom(&path)); - - fwrite(line, scan - line, sizeof(char), out); - fputs(path.ptr, out); - } - - fclose(in); - fclose(out); - - cl_must_pass(p_unlink(in_f.ptr)); - - git_buf_free(&in_f); - git_buf_free(&out_f); - git_buf_free(&path); -} - -static void cleanup_fixture_submodules(void *payload) -{ - cl_git_sandbox_cleanup(); /* either "submodules" or "submod2" */ - - if (payload) - cl_fixture_cleanup(payload); -} - -git_repository *setup_fixture_submodules(void) -{ - git_repository *repo = cl_git_sandbox_init("submodules"); - - cl_fixture_sandbox("testrepo.git"); - - rewrite_gitmodules(git_repository_workdir(repo)); - p_rename("submodules/testrepo/.gitted", "submodules/testrepo/.git"); - - cl_set_cleanup(cleanup_fixture_submodules, "testrepo.git"); - - cl_git_pass(git_repository_reinit_filesystem(repo, 1)); - - return repo; -} - -git_repository *setup_fixture_submod2(void) -{ - git_repository *repo = cl_git_sandbox_init("submod2"); - - cl_fixture_sandbox("submod2_target"); - p_rename("submod2_target/.gitted", "submod2_target/.git"); - - rewrite_gitmodules(git_repository_workdir(repo)); - p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git"); - p_rename("submod2/not/.gitted", "submod2/not/.git"); - - cl_set_cleanup(cleanup_fixture_submodules, "submod2_target"); - - cl_git_pass(git_repository_reinit_filesystem(repo, 1)); - - return repo; -} diff --git a/tests-clar/submodule/submodule_helpers.h b/tests-clar/submodule/submodule_helpers.h deleted file mode 100644 index 610c40720..000000000 --- a/tests-clar/submodule/submodule_helpers.h +++ /dev/null @@ -1,5 +0,0 @@ -extern void rewrite_gitmodules(const char *workdir); - -/* these will automatically set a cleanup callback */ -extern git_repository *setup_fixture_submodules(void); -extern git_repository *setup_fixture_submod2(void); diff --git a/tests-clar/threads/basic.c b/tests-clar/threads/basic.c deleted file mode 100644 index a329ee7f9..000000000 --- a/tests-clar/threads/basic.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "clar_libgit2.h" - -#include "cache.h" - - -static git_repository *g_repo; - -void test_threads_basic__initialize(void) -{ - g_repo = cl_git_sandbox_init("testrepo"); -} - -void test_threads_basic__cleanup(void) -{ - cl_git_sandbox_cleanup(); -} - - -void test_threads_basic__cache(void) -{ - // run several threads polling the cache at the same time - cl_assert(1 == 1); -} - -void test_threads_basic__multiple_init(void) -{ - git_repository *nested_repo; - - git_threads_init(); - cl_git_pass(git_repository_open(&nested_repo, cl_fixture("testrepo.git"))); - git_repository_free(nested_repo); - - git_threads_shutdown(); - cl_git_pass(git_repository_open(&nested_repo, cl_fixture("testrepo.git"))); - git_repository_free(nested_repo); -} diff --git a/tests-clar/threads/refdb.c b/tests-clar/threads/refdb.c deleted file mode 100644 index 3c651e341..000000000 --- a/tests-clar/threads/refdb.c +++ /dev/null @@ -1,213 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/refdb.h" -#include "refdb.h" - -static git_repository *g_repo; -static int g_expected = 0; - -void test_threads_refdb__initialize(void) -{ - g_repo = NULL; -} - -void test_threads_refdb__cleanup(void) -{ - cl_git_sandbox_cleanup(); - g_repo = NULL; -} - -#define REPEAT 20 -#define THREADS 20 - -static void *iterate_refs(void *arg) -{ - git_reference_iterator *i; - git_reference *ref; - int count = 0; - - cl_git_pass(git_reference_iterator_new(&i, g_repo)); - - for (count = 0; !git_reference_next(&ref, i); ++count) { - cl_assert(ref != NULL); - git_reference_free(ref); - } - - if (g_expected > 0) - cl_assert_equal_i(g_expected, count); - - git_reference_iterator_free(i); - - return arg; -} - -void test_threads_refdb__iterator(void) -{ - int r, t; - git_thread th[THREADS]; - int id[THREADS]; - git_oid head; - git_reference *ref; - char name[128]; - git_refdb *refdb; - - g_repo = cl_git_sandbox_init("testrepo2"); - - cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); - - /* make a bunch of references */ - - for (r = 0; r < 200; ++r) { - snprintf(name, sizeof(name), "refs/heads/direct-%03d", r); - cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0)); - git_reference_free(ref); - } - - cl_git_pass(git_repository_refdb(&refdb, g_repo)); - cl_git_pass(git_refdb_compress(refdb)); - git_refdb_free(refdb); - - g_expected = 206; - - for (r = 0; r < REPEAT; ++r) { - g_repo = cl_git_sandbox_reopen(); /* reopen to flush caches */ - - for (t = 0; t < THREADS; ++t) { - id[t] = t; -#ifdef GIT_THREADS - cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t])); -#else - th[t] = t; - iterate_refs(&id[t]); -#endif - } - -#ifdef GIT_THREADS - for (t = 0; t < THREADS; ++t) { - cl_git_pass(git_thread_join(th[t], NULL)); - } -#endif - - memset(th, 0, sizeof(th)); - } -} - -static void *create_refs(void *arg) -{ - int *id = arg, i; - git_oid head; - char name[128]; - git_reference *ref[10]; - - cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); - - for (i = 0; i < 10; ++i) { - snprintf(name, sizeof(name), "refs/heads/thread-%03d-%02d", *id, i); - cl_git_pass(git_reference_create(&ref[i], g_repo, name, &head, 0)); - - if (i == 5) { - git_refdb *refdb; - cl_git_pass(git_repository_refdb(&refdb, g_repo)); - cl_git_pass(git_refdb_compress(refdb)); - git_refdb_free(refdb); - } - } - - for (i = 0; i < 10; ++i) - git_reference_free(ref[i]); - - return arg; -} - -static void *delete_refs(void *arg) -{ - int *id = arg, i; - git_reference *ref; - char name[128]; - - for (i = 0; i < 10; ++i) { - snprintf( - name, sizeof(name), "refs/heads/thread-%03d-%02d", (*id) & ~0x3, i); - - if (!git_reference_lookup(&ref, g_repo, name)) { - cl_git_pass(git_reference_delete(ref)); - git_reference_free(ref); - } - - if (i == 5) { - git_refdb *refdb; - cl_git_pass(git_repository_refdb(&refdb, g_repo)); - cl_git_pass(git_refdb_compress(refdb)); - git_refdb_free(refdb); - } - } - - return arg; -} - -void test_threads_refdb__edit_while_iterate(void) -{ - int r, t; - int id[THREADS]; - git_oid head; - git_reference *ref; - char name[128]; - git_refdb *refdb; - -#ifdef GIT_THREADS - git_thread th[THREADS]; -#endif - - g_repo = cl_git_sandbox_init("testrepo2"); - - cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); - - /* make a bunch of references */ - - for (r = 0; r < 50; ++r) { - snprintf(name, sizeof(name), "refs/heads/starter-%03d", r); - cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0)); - git_reference_free(ref); - } - - cl_git_pass(git_repository_refdb(&refdb, g_repo)); - cl_git_pass(git_refdb_compress(refdb)); - git_refdb_free(refdb); - - g_expected = -1; - - g_repo = cl_git_sandbox_reopen(); /* reopen to flush caches */ - - for (t = 0; t < THREADS; ++t) { - void *(*fn)(void *arg); - - switch (t & 0x3) { - case 0: fn = create_refs; break; - case 1: fn = delete_refs; break; - default: fn = iterate_refs; break; - } - - id[t] = t; -#ifdef GIT_THREADS - cl_git_pass(git_thread_create(&th[t], NULL, fn, &id[t])); -#else - fn(&id[t]); -#endif - } - -#ifdef GIT_THREADS - for (t = 0; t < THREADS; ++t) { - cl_git_pass(git_thread_join(th[t], NULL)); - } - - memset(th, 0, sizeof(th)); - - for (t = 0; t < THREADS; ++t) { - id[t] = t; - cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t])); - } - - for (t = 0; t < THREADS; ++t) { - cl_git_pass(git_thread_join(th[t], NULL)); - } -#endif -} diff --git a/tests-clar/trace/trace.c b/tests-clar/trace/trace.c deleted file mode 100644 index 87b325378..000000000 --- a/tests-clar/trace/trace.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "clar_libgit2.h" -#include "trace.h" - -static int written = 0; - -static void trace_callback(git_trace_level_t level, const char *message) -{ - GIT_UNUSED(level); - - cl_assert(strcmp(message, "Hello world!") == 0); - - written = 1; -} - -void test_trace_trace__initialize(void) -{ - git_trace_set(GIT_TRACE_INFO, trace_callback); - written = 0; -} - -void test_trace_trace__cleanup(void) -{ - git_trace_set(GIT_TRACE_NONE, NULL); -} - -void test_trace_trace__sets(void) -{ -#ifdef GIT_TRACE - cl_assert(git_trace_level() == GIT_TRACE_INFO); -#endif -} - -void test_trace_trace__can_reset(void) -{ -#ifdef GIT_TRACE - cl_assert(git_trace_level() == GIT_TRACE_INFO); - cl_git_pass(git_trace_set(GIT_TRACE_ERROR, trace_callback)); - - cl_assert(written == 0); - git_trace(GIT_TRACE_INFO, "Hello %s!", "world"); - cl_assert(written == 0); - - git_trace(GIT_TRACE_ERROR, "Hello %s!", "world"); - cl_assert(written == 1); -#endif -} - -void test_trace_trace__can_unset(void) -{ -#ifdef GIT_TRACE - cl_assert(git_trace_level() == GIT_TRACE_INFO); - cl_git_pass(git_trace_set(GIT_TRACE_NONE, NULL)); - - cl_assert(git_trace_level() == GIT_TRACE_NONE); - - cl_assert(written == 0); - git_trace(GIT_TRACE_FATAL, "Hello %s!", "world"); - cl_assert(written == 0); -#endif -} - -void test_trace_trace__skips_higher_level(void) -{ -#ifdef GIT_TRACE - cl_assert(written == 0); - git_trace(GIT_TRACE_DEBUG, "Hello %s!", "world"); - cl_assert(written == 0); -#endif -} - -void test_trace_trace__writes(void) -{ -#ifdef GIT_TRACE - cl_assert(written == 0); - git_trace(GIT_TRACE_INFO, "Hello %s!", "world"); - cl_assert(written == 1); -#endif -} - -void test_trace_trace__writes_lower_level(void) -{ -#ifdef GIT_TRACE - cl_assert(written == 0); - git_trace(GIT_TRACE_ERROR, "Hello %s!", "world"); - cl_assert(written == 1); -#endif -} diff --git a/tests-clar/valgrind-supp-mac.txt b/tests-clar/valgrind-supp-mac.txt deleted file mode 100644 index 99833d091..000000000 --- a/tests-clar/valgrind-supp-mac.txt +++ /dev/null @@ -1,184 +0,0 @@ -{ - libgit2-giterr-set-buffer - Memcheck:Leak - ... - fun:git__realloc - fun:git_buf_try_grow - fun:git_buf_grow - fun:git_buf_vprintf - fun:giterr_set -} -{ - mac-setenv-leak-1 - Memcheck:Leak - fun:malloc_zone_malloc - fun:__setenv - fun:setenv -} -{ - mac-setenv-leak-2 - Memcheck:Leak - fun:malloc_zone_malloc - fun:malloc_set_zone_name - ... - fun:init__zone0 - fun:setenv -} -{ - mac-dyld-initializer-leak - Memcheck:Leak - fun:malloc - ... - fun:dyld_register_image_state_change_handler - fun:_dyld_initializer -} -{ - mac-tz-leak-1 - Memcheck:Leak - ... - fun:token_table_add - fun:notify_register_check - fun:notify_register_tz -} -{ - mac-tz-leak-2 - Memcheck:Leak - fun:malloc - fun:tzload -} -{ - mac-tz-leak-3 - Memcheck:Leak - fun:malloc - fun:tzsetwall_basic -} -{ - mac-tz-leak-4 - Memcheck:Leak - fun:malloc - fun:gmtsub -} -{ - mac-system-init-leak-1 - Memcheck:Leak - ... - fun:_libxpc_initializer - fun:libSystem_initializer -} -{ - mac-system-init-leak-2 - Memcheck:Leak - ... - fun:__keymgr_initializer - fun:libSystem_initializer -} -{ - mac-puts-leak - Memcheck:Leak - fun:malloc - fun:__smakebuf - ... - fun:puts -} -{ - mac-ssl-uninitialized-1 - Memcheck:Cond - obj:/usr/lib/libcrypto.0.9.8.dylib - ... - fun:ssl23_connect -} -{ - mac-ssl-uninitialized-2 - Memcheck:Cond - ... - obj:/usr/lib/libssl.0.9.8.dylib - ... - fun:ssl23_connect -} -{ - mac-ssl-uninitialized-3 - Memcheck:Value8 - obj:/usr/lib/libcrypto.0.9.8.dylib - ... - fun:ssl23_connect -} -{ - mac-ssl-uninitialized-4 - Memcheck:Param - ... - obj:/usr/lib/libcrypto.0.9.8.dylib - ... - fun:ssl23_connect -} -{ - mac-ssl-leak-1 - Memcheck:Leak - ... - fun:ERR_load_strings -} -{ - mac-ssl-leak-2 - Memcheck:Leak - ... - fun:SSL_library_init -} -{ - mac-ssl-leak-3 - Memcheck:Leak - ... - fun:si_module_with_name - fun:getaddrinfo -} -{ - mac-ssl-leak-4 - Memcheck:Leak - fun:malloc - fun:CRYPTO_malloc - ... - fun:ssl3_get_server_certificate -} -{ - mac-ssl-leak-5 - Memcheck:Leak - fun:malloc - fun:CRYPTO_malloc - ... - fun:ERR_put_error -} -{ - clar-printf-buf - Memcheck:Leak - fun:malloc - fun:__smakebuf - ... - fun:printf - fun:clar_print_init -} -{ - molo-1 - Memcheck:Leak - fun:malloc_zone_malloc - ... - fun:_objc_init -} -{ - molo-2 - Memcheck:Leak - fun:malloc_zone_calloc - ... - fun:_objc_init -} -{ - molo-3 - Memcheck:Leak - fun:malloc - ... - fun:_objc_init -} -{ - molo-4 - Memcheck:Leak - fun:malloc - ... - fun:dyld_register_image_state_change_handler -} diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 000000000..3aeaaf464 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,22 @@ +Writing Clar tests for libgit2 +============================== + +For information on the Clar testing framework and a detailed introduction +please visit: + +https://github.com/vmg/clar + + +* Write your modules and tests. Use good, meaningful names. + +* Make sure you actually build the tests by setting: + + cmake -DBUILD_CLAR=ON build/ + +* Test: + + ./build/libgit2_clar + +* Make sure everything is fine. + +* Send your pull request. That's it. diff --git a/tests/attr/attr_expect.h b/tests/attr/attr_expect.h new file mode 100644 index 000000000..70f1ab4f5 --- /dev/null +++ b/tests/attr/attr_expect.h @@ -0,0 +1,43 @@ +#ifndef __CLAR_TEST_ATTR_EXPECT__ +#define __CLAR_TEST_ATTR_EXPECT__ + +enum attr_expect_t { + EXPECT_FALSE, + EXPECT_TRUE, + EXPECT_UNDEFINED, + EXPECT_STRING +}; + +struct attr_expected { + const char *path; + const char *attr; + enum attr_expect_t expected; + const char *expected_str; +}; + +GIT_INLINE(void) attr_check_expected( + enum attr_expect_t expected, + const char *expected_str, + const char *name, + const char *value) +{ + switch (expected) { + case EXPECT_TRUE: + cl_assert_(GIT_ATTR_TRUE(value), name); + break; + + case EXPECT_FALSE: + cl_assert_(GIT_ATTR_FALSE(value), name); + break; + + case EXPECT_UNDEFINED: + cl_assert_(GIT_ATTR_UNSPECIFIED(value), name); + break; + + case EXPECT_STRING: + cl_assert_equal_s(expected_str, value); + break; + } +} + +#endif diff --git a/tests/attr/file.c b/tests/attr/file.c new file mode 100644 index 000000000..4eb1d22fe --- /dev/null +++ b/tests/attr/file.c @@ -0,0 +1,224 @@ +#include "clar_libgit2.h" +#include "attr_file.h" +#include "attr_expect.h" + +#define get_rule(X) ((git_attr_rule *)git_vector_get(&file->rules,(X))) +#define get_assign(R,Y) ((git_attr_assignment *)git_vector_get(&(R)->assigns,(Y))) + +void test_attr_file__simple_read(void) +{ + git_attr_file *file; + git_attr_assignment *assign; + git_attr_rule *rule; + + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr0"))); + + cl_assert_equal_s(cl_fixture("attr/attr0"), file->key + 2); + cl_assert(file->rules.length == 1); + + rule = get_rule(0); + cl_assert(rule != NULL); + cl_assert_equal_s("*", rule->match.pattern); + cl_assert(rule->match.length == 1); + cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_HASWILD) != 0); + + cl_assert(rule->assigns.length == 1); + assign = get_assign(rule, 0); + cl_assert(assign != NULL); + cl_assert_equal_s("binary", assign->name); + cl_assert(GIT_ATTR_TRUE(assign->value)); + + git_attr_file__free(file); +} + +void test_attr_file__match_variants(void) +{ + git_attr_file *file; + git_attr_rule *rule; + git_attr_assignment *assign; + + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr1"))); + + cl_assert_equal_s(cl_fixture("attr/attr1"), file->key + 2); + cl_assert(file->rules.length == 10); + + /* let's do a thorough check of this rule, then just verify + * the things that are unique for the later rules + */ + rule = get_rule(0); + cl_assert(rule); + cl_assert_equal_s("pat0", rule->match.pattern); + cl_assert(rule->match.length == strlen("pat0")); + cl_assert(rule->assigns.length == 1); + assign = get_assign(rule,0); + cl_assert_equal_s("attr0", assign->name); + cl_assert(assign->name_hash == git_attr_file__name_hash(assign->name)); + cl_assert(GIT_ATTR_TRUE(assign->value)); + + rule = get_rule(1); + cl_assert_equal_s("pat1", rule->match.pattern); + cl_assert(rule->match.length == strlen("pat1")); + cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_NEGATIVE) != 0); + + rule = get_rule(2); + cl_assert_equal_s("pat2", rule->match.pattern); + cl_assert(rule->match.length == strlen("pat2")); + cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_DIRECTORY) != 0); + + rule = get_rule(3); + cl_assert_equal_s("pat3dir/pat3file", rule->match.pattern); + cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_FULLPATH) != 0); + + rule = get_rule(4); + cl_assert_equal_s("pat4.*", rule->match.pattern); + cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_HASWILD) != 0); + + rule = get_rule(5); + cl_assert_equal_s("*.pat5", rule->match.pattern); + cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_HASWILD) != 0); + + rule = get_rule(7); + cl_assert_equal_s("pat7[a-e]??[xyz]", rule->match.pattern); + cl_assert(rule->assigns.length == 1); + cl_assert((rule->match.flags & GIT_ATTR_FNMATCH_HASWILD) != 0); + assign = get_assign(rule,0); + cl_assert_equal_s("attr7", assign->name); + cl_assert(GIT_ATTR_TRUE(assign->value)); + + rule = get_rule(8); + cl_assert_equal_s("pat8 with spaces", rule->match.pattern); + cl_assert(rule->match.length == strlen("pat8 with spaces")); + + rule = get_rule(9); + cl_assert_equal_s("pat9", rule->match.pattern); + + git_attr_file__free(file); +} + +static void check_one_assign( + git_attr_file *file, + int rule_idx, + int assign_idx, + const char *pattern, + const char *name, + enum attr_expect_t expected, + const char *expected_str) +{ + git_attr_rule *rule = get_rule(rule_idx); + git_attr_assignment *assign = get_assign(rule, assign_idx); + + cl_assert_equal_s(pattern, rule->match.pattern); + cl_assert(rule->assigns.length == 1); + cl_assert_equal_s(name, assign->name); + cl_assert(assign->name_hash == git_attr_file__name_hash(assign->name)); + + attr_check_expected(expected, expected_str, assign->name, assign->value); +} + +void test_attr_file__assign_variants(void) +{ + git_attr_file *file; + git_attr_rule *rule; + git_attr_assignment *assign; + + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr2"))); + + cl_assert_equal_s(cl_fixture("attr/attr2"), file->key + 2); + cl_assert(file->rules.length == 11); + + check_one_assign(file, 0, 0, "pat0", "simple", EXPECT_TRUE, NULL); + check_one_assign(file, 1, 0, "pat1", "neg", EXPECT_FALSE, NULL); + check_one_assign(file, 2, 0, "*", "notundef", EXPECT_TRUE, NULL); + check_one_assign(file, 3, 0, "pat2", "notundef", EXPECT_UNDEFINED, NULL); + check_one_assign(file, 4, 0, "pat3", "assigned", EXPECT_STRING, "test-value"); + check_one_assign(file, 5, 0, "pat4", "rule-with-more-chars", EXPECT_STRING, "value-with-more-chars"); + check_one_assign(file, 6, 0, "pat5", "empty", EXPECT_TRUE, NULL); + check_one_assign(file, 7, 0, "pat6", "negempty", EXPECT_FALSE, NULL); + + rule = get_rule(8); + cl_assert_equal_s("pat7", rule->match.pattern); + cl_assert(rule->assigns.length == 5); + /* assignments will be sorted by hash value, so we have to do + * lookups by search instead of by position + */ + assign = git_attr_rule__lookup_assignment(rule, "multiple"); + cl_assert(assign); + cl_assert_equal_s("multiple", assign->name); + cl_assert(GIT_ATTR_TRUE(assign->value)); + assign = git_attr_rule__lookup_assignment(rule, "single"); + cl_assert(assign); + cl_assert_equal_s("single", assign->name); + cl_assert(GIT_ATTR_FALSE(assign->value)); + assign = git_attr_rule__lookup_assignment(rule, "values"); + cl_assert(assign); + cl_assert_equal_s("values", assign->name); + cl_assert_equal_s("1", assign->value); + assign = git_attr_rule__lookup_assignment(rule, "also"); + cl_assert(assign); + cl_assert_equal_s("also", assign->name); + cl_assert_equal_s("a-really-long-value/*", assign->value); + assign = git_attr_rule__lookup_assignment(rule, "happy"); + cl_assert(assign); + cl_assert_equal_s("happy", assign->name); + cl_assert_equal_s("yes!", assign->value); + assign = git_attr_rule__lookup_assignment(rule, "other"); + cl_assert(!assign); + + rule = get_rule(9); + cl_assert_equal_s("pat8", rule->match.pattern); + cl_assert(rule->assigns.length == 2); + assign = git_attr_rule__lookup_assignment(rule, "again"); + cl_assert(assign); + cl_assert_equal_s("again", assign->name); + cl_assert(GIT_ATTR_TRUE(assign->value)); + assign = git_attr_rule__lookup_assignment(rule, "another"); + cl_assert(assign); + cl_assert_equal_s("another", assign->name); + cl_assert_equal_s("12321", assign->value); + + check_one_assign(file, 10, 0, "pat9", "at-eof", EXPECT_FALSE, NULL); + + git_attr_file__free(file); +} + +void test_attr_file__check_attr_examples(void) +{ + git_attr_file *file; + git_attr_rule *rule; + git_attr_assignment *assign; + + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr3"))); + cl_assert_equal_s(cl_fixture("attr/attr3"), file->key + 2); + cl_assert(file->rules.length == 3); + + rule = get_rule(0); + cl_assert_equal_s("*.java", rule->match.pattern); + cl_assert(rule->assigns.length == 3); + assign = git_attr_rule__lookup_assignment(rule, "diff"); + cl_assert_equal_s("diff", assign->name); + cl_assert_equal_s("java", assign->value); + assign = git_attr_rule__lookup_assignment(rule, "crlf"); + cl_assert_equal_s("crlf", assign->name); + cl_assert(GIT_ATTR_FALSE(assign->value)); + assign = git_attr_rule__lookup_assignment(rule, "myAttr"); + cl_assert_equal_s("myAttr", assign->name); + cl_assert(GIT_ATTR_TRUE(assign->value)); + assign = git_attr_rule__lookup_assignment(rule, "missing"); + cl_assert(assign == NULL); + + rule = get_rule(1); + cl_assert_equal_s("NoMyAttr.java", rule->match.pattern); + cl_assert(rule->assigns.length == 1); + assign = get_assign(rule, 0); + cl_assert_equal_s("myAttr", assign->name); + cl_assert(GIT_ATTR_UNSPECIFIED(assign->value)); + + rule = get_rule(2); + cl_assert_equal_s("README", rule->match.pattern); + cl_assert(rule->assigns.length == 1); + assign = get_assign(rule, 0); + cl_assert_equal_s("caveat", assign->name); + cl_assert_equal_s("unspecified", assign->value); + + git_attr_file__free(file); +} diff --git a/tests/attr/flags.c b/tests/attr/flags.c new file mode 100644 index 000000000..80c6e1171 --- /dev/null +++ b/tests/attr/flags.c @@ -0,0 +1,108 @@ +#include "clar_libgit2.h" +#include "git2/attr.h" + +void test_attr_flags__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_attr_flags__bare(void) +{ + git_repository *repo = cl_git_sandbox_init("testrepo.git"); + const char *value; + + cl_assert(git_repository_is_bare(repo)); + + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM, "README.md", "diff")); + cl_assert(GIT_ATTR_UNSPECIFIED(value)); +} + +void test_attr_flags__index_vs_workdir(void) +{ + git_repository *repo = cl_git_sandbox_init("attr_index"); + const char *value; + + cl_assert(!git_repository_is_bare(repo)); + + /* wd then index */ + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "README.md", "bar")); + cl_assert(GIT_ATTR_FALSE(value)); + + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "README.md", "blargh")); + cl_assert_equal_s(value, "goop"); + + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "README.txt", "foo")); + cl_assert(GIT_ATTR_FALSE(value)); + + /* index then wd */ + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "README.md", "bar")); + cl_assert(GIT_ATTR_TRUE(value)); + + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "README.md", "blargh")); + cl_assert_equal_s(value, "garble"); + + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "README.txt", "foo")); + cl_assert(GIT_ATTR_TRUE(value)); +} + +void test_attr_flags__subdir(void) +{ + git_repository *repo = cl_git_sandbox_init("attr_index"); + const char *value; + + /* wd then index */ + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "sub/sub/README.md", "bar")); + cl_assert_equal_s(value, "1234"); + + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "sub/sub/README.txt", "another")); + cl_assert_equal_s(value, "one"); + + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "sub/sub/README.txt", "again")); + cl_assert(GIT_ATTR_TRUE(value)); + + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "sub/sub/README.txt", "beep")); + cl_assert_equal_s(value, "10"); + + /* index then wd */ + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "sub/sub/README.md", "bar")); + cl_assert_equal_s(value, "1337"); + + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "sub/sub/README.txt", "another")); + cl_assert_equal_s(value, "one"); + + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "sub/sub/README.txt", "again")); + cl_assert(GIT_ATTR_TRUE(value)); + + cl_git_pass(git_attr_get( + &value, repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "sub/sub/README.txt", "beep")); + cl_assert_equal_s(value, "5"); +} + diff --git a/tests/attr/ignore.c b/tests/attr/ignore.c new file mode 100644 index 000000000..0f945ebf6 --- /dev/null +++ b/tests/attr/ignore.c @@ -0,0 +1,102 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "path.h" +#include "fileops.h" + +static git_repository *g_repo = NULL; + +void test_attr_ignore__initialize(void) +{ + g_repo = cl_git_sandbox_init("attr"); +} + +void test_attr_ignore__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +void assert_is_ignored(bool expected, const char *filepath) +{ + int is_ignored; + + cl_git_pass(git_ignore_path_is_ignored(&is_ignored, g_repo, filepath)); + cl_assert_equal_b(expected, is_ignored); +} + +void test_attr_ignore__honor_temporary_rules(void) +{ + cl_git_rewritefile("attr/.gitignore", "/NewFolder\n/NewFolder/NewFolder"); + + assert_is_ignored(false, "File.txt"); + assert_is_ignored(true, "NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); +} + +void test_attr_ignore__allow_root(void) +{ + cl_git_rewritefile("attr/.gitignore", "/"); + + assert_is_ignored(false, "File.txt"); + assert_is_ignored(false, "NewFolder"); + assert_is_ignored(false, "NewFolder/NewFolder"); + assert_is_ignored(false, "NewFolder/NewFolder/File.txt"); +} + +void test_attr_ignore__ignore_root(void) +{ + cl_git_rewritefile("attr/.gitignore", "/\n\n/NewFolder\n/NewFolder/NewFolder"); + + assert_is_ignored(false, "File.txt"); + assert_is_ignored(true, "NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); +} + + +void test_attr_ignore__skip_gitignore_directory(void) +{ + cl_git_rewritefile("attr/.git/info/exclude", "/NewFolder\n/NewFolder/NewFolder"); + p_unlink("attr/.gitignore"); + cl_assert(!git_path_exists("attr/.gitignore")); + p_mkdir("attr/.gitignore", 0777); + cl_git_mkfile("attr/.gitignore/garbage.txt", "new_file\n"); + + assert_is_ignored(false, "File.txt"); + assert_is_ignored(true, "NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder"); + assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); +} + +void test_attr_ignore__expand_tilde_to_homedir(void) +{ + git_buf path = GIT_BUF_INIT; + git_config *cfg; + + assert_is_ignored(false, "example.global_with_tilde"); + + /* construct fake home with fake global excludes */ + + cl_must_pass(p_mkdir("home", 0777)); + cl_git_pass(git_path_prettify(&path, "home", NULL)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); + + cl_git_mkfile("home/globalexcludes", "# found me\n*.global_with_tilde\n"); + + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_string(cfg, "core.excludesfile", "~/globalexcludes")); + git_config_free(cfg); + + git_attr_cache_flush(g_repo); /* must reset to pick up change */ + + assert_is_ignored(true, "example.global_with_tilde"); + + cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES)); + + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, NULL)); + + git_buf_free(&path); +} diff --git a/tests/attr/lookup.c b/tests/attr/lookup.c new file mode 100644 index 000000000..200bdd2c7 --- /dev/null +++ b/tests/attr/lookup.c @@ -0,0 +1,262 @@ +#include "clar_libgit2.h" +#include "attr_file.h" + +#include "attr_expect.h" + +void test_attr_lookup__simple(void) +{ + git_attr_file *file; + git_attr_path path; + const char *value = NULL; + + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr0"))); + cl_assert_equal_s(cl_fixture("attr/attr0"), file->key + 2); + cl_assert(file->rules.length == 1); + + cl_git_pass(git_attr_path__init(&path, "test", NULL)); + cl_assert_equal_s("test", path.path); + cl_assert_equal_s("test", path.basename); + cl_assert(!path.is_dir); + + cl_git_pass(git_attr_file__lookup_one(file,&path,"binary",&value)); + cl_assert(GIT_ATTR_TRUE(value)); + + cl_git_pass(git_attr_file__lookup_one(file,&path,"missing",&value)); + cl_assert(!value); + + git_attr_path__free(&path); + git_attr_file__free(file); +} + +static void run_test_cases(git_attr_file *file, struct attr_expected *cases, int force_dir) +{ + git_attr_path path; + const char *value = NULL; + struct attr_expected *c; + int error; + + for (c = cases; c->path != NULL; c++) { + cl_git_pass(git_attr_path__init(&path, c->path, NULL)); + + if (force_dir) + path.is_dir = 1; + + error = git_attr_file__lookup_one(file,&path,c->attr,&value); + cl_git_pass(error); + + attr_check_expected(c->expected, c->expected_str, c->attr, value); + + git_attr_path__free(&path); + } +} + +void test_attr_lookup__match_variants(void) +{ + git_attr_file *file; + git_attr_path path; + + struct attr_expected dir_cases[] = { + { "pat2", "attr2", EXPECT_TRUE, NULL }, + { "/testing/for/pat2", "attr2", EXPECT_TRUE, NULL }, + { "/not/pat2/yousee", "attr2", EXPECT_UNDEFINED, NULL }, + { "/fun/fun/fun/pat4.dir", "attr4", EXPECT_TRUE, NULL }, + { "foo.pat5", "attr5", EXPECT_TRUE, NULL }, + { NULL, NULL, 0, NULL } + }; + + struct attr_expected cases[] = { + /* pat0 -> simple match */ + { "pat0", "attr0", EXPECT_TRUE, NULL }, + { "/testing/for/pat0", "attr0", EXPECT_TRUE, NULL }, + { "relative/to/pat0", "attr0", EXPECT_TRUE, NULL }, + { "this-contains-pat0-inside", "attr0", EXPECT_UNDEFINED, NULL }, + { "this-aint-right", "attr0", EXPECT_UNDEFINED, NULL }, + { "/this/pat0/dont/match", "attr0", EXPECT_UNDEFINED, NULL }, + /* negative match */ + { "pat0", "attr1", EXPECT_TRUE, NULL }, + { "pat1", "attr1", EXPECT_UNDEFINED, NULL }, + { "/testing/for/pat1", "attr1", EXPECT_UNDEFINED, NULL }, + { "/testing/for/pat0", "attr1", EXPECT_TRUE, NULL }, + { "/testing/for/pat1/inside", "attr1", EXPECT_TRUE, NULL }, + { "misc", "attr1", EXPECT_TRUE, NULL }, + /* dir match */ + { "pat2", "attr2", EXPECT_UNDEFINED, NULL }, + { "/testing/for/pat2", "attr2", EXPECT_UNDEFINED, NULL }, + { "/not/pat2/yousee", "attr2", EXPECT_UNDEFINED, NULL }, + /* path match */ + { "pat3file", "attr3", EXPECT_UNDEFINED, NULL }, + { "/pat3dir/pat3file", "attr3", EXPECT_TRUE, NULL }, + { "pat3dir/pat3file", "attr3", EXPECT_TRUE, NULL }, + /* pattern* match */ + { "pat4.txt", "attr4", EXPECT_TRUE, NULL }, + { "/fun/fun/fun/pat4.c", "attr4", EXPECT_TRUE, NULL }, + { "pat4.", "attr4", EXPECT_TRUE, NULL }, + { "pat4", "attr4", EXPECT_UNDEFINED, NULL }, + /* *pattern match */ + { "foo.pat5", "attr5", EXPECT_TRUE, NULL }, + { "/this/is/ok.pat5", "attr5", EXPECT_TRUE, NULL }, + { "/this/is/bad.pat5/yousee.txt", "attr5", EXPECT_UNDEFINED, NULL }, + { "foo.pat5", "attr100", EXPECT_UNDEFINED, NULL }, + /* glob match with slashes */ + { "foo.pat6", "attr6", EXPECT_UNDEFINED, NULL }, + { "pat6/pat6/foobar.pat6", "attr6", EXPECT_TRUE, NULL }, + { "pat6/pat6/.pat6", "attr6", EXPECT_TRUE, NULL }, + { "pat6/pat6/extra/foobar.pat6", "attr6", EXPECT_UNDEFINED, NULL }, + { "/prefix/pat6/pat6/foobar.pat6", "attr6", EXPECT_UNDEFINED, NULL }, + { "/pat6/pat6/foobar.pat6", "attr6", EXPECT_TRUE, NULL }, + /* complex pattern */ + { "pat7a12z", "attr7", EXPECT_TRUE, NULL }, + { "pat7e__x", "attr7", EXPECT_TRUE, NULL }, + { "pat7b/1y", "attr7", EXPECT_UNDEFINED, NULL }, /* ? does not match / */ + { "pat7e_x", "attr7", EXPECT_UNDEFINED, NULL }, + { "pat7aaaa", "attr7", EXPECT_UNDEFINED, NULL }, + { "pat7zzzz", "attr7", EXPECT_UNDEFINED, NULL }, + { "/this/can/be/anything/pat7a12z", "attr7", EXPECT_TRUE, NULL }, + { "but/it/still/must/match/pat7aaaa", "attr7", EXPECT_UNDEFINED, NULL }, + { "pat7aaay.fail", "attr7", EXPECT_UNDEFINED, NULL }, + /* pattern with spaces */ + { "pat8 with spaces", "attr8", EXPECT_TRUE, NULL }, + { "/gotta love/pat8 with spaces", "attr8", EXPECT_TRUE, NULL }, + { "failing pat8 with spaces", "attr8", EXPECT_UNDEFINED, NULL }, + { "spaces", "attr8", EXPECT_UNDEFINED, NULL }, + /* pattern at eof */ + { "pat9", "attr9", EXPECT_TRUE, NULL }, + { "/eof/pat9", "attr9", EXPECT_TRUE, NULL }, + { "pat", "attr9", EXPECT_UNDEFINED, NULL }, + { "at9", "attr9", EXPECT_UNDEFINED, NULL }, + { "pat9.fail", "attr9", EXPECT_UNDEFINED, NULL }, + /* sentinel at end */ + { NULL, NULL, 0, NULL } + }; + + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr1"))); + cl_assert_equal_s(cl_fixture("attr/attr1"), file->key + 2); + cl_assert(file->rules.length == 10); + + cl_git_pass(git_attr_path__init(&path, "/testing/for/pat0", NULL)); + cl_assert_equal_s("pat0", path.basename); + + run_test_cases(file, cases, 0); + run_test_cases(file, dir_cases, 1); + + git_attr_file__free(file); + git_attr_path__free(&path); +} + +void test_attr_lookup__assign_variants(void) +{ + git_attr_file *file; + + struct attr_expected cases[] = { + /* pat0 -> simple assign */ + { "pat0", "simple", EXPECT_TRUE, NULL }, + { "/testing/pat0", "simple", EXPECT_TRUE, NULL }, + { "pat0", "fail", EXPECT_UNDEFINED, NULL }, + { "/testing/pat0", "fail", EXPECT_UNDEFINED, NULL }, + /* negative assign */ + { "pat1", "neg", EXPECT_FALSE, NULL }, + { "/testing/pat1", "neg", EXPECT_FALSE, NULL }, + { "pat1", "fail", EXPECT_UNDEFINED, NULL }, + { "/testing/pat1", "fail", EXPECT_UNDEFINED, NULL }, + /* forced undef */ + { "pat1", "notundef", EXPECT_TRUE, NULL }, + { "pat2", "notundef", EXPECT_UNDEFINED, NULL }, + { "/lead/in/pat1", "notundef", EXPECT_TRUE, NULL }, + { "/lead/in/pat2", "notundef", EXPECT_UNDEFINED, NULL }, + /* assign value */ + { "pat3", "assigned", EXPECT_STRING, "test-value" }, + { "pat3", "notassigned", EXPECT_UNDEFINED, NULL }, + /* assign value */ + { "pat4", "rule-with-more-chars", EXPECT_STRING, "value-with-more-chars" }, + { "pat4", "notassigned-rule-with-more-chars", EXPECT_UNDEFINED, NULL }, + /* empty assignments */ + { "pat5", "empty", EXPECT_TRUE, NULL }, + { "pat6", "negempty", EXPECT_FALSE, NULL }, + /* multiple assignment */ + { "pat7", "multiple", EXPECT_TRUE, NULL }, + { "pat7", "single", EXPECT_FALSE, NULL }, + { "pat7", "values", EXPECT_STRING, "1" }, + { "pat7", "also", EXPECT_STRING, "a-really-long-value/*" }, + { "pat7", "happy", EXPECT_STRING, "yes!" }, + { "pat8", "again", EXPECT_TRUE, NULL }, + { "pat8", "another", EXPECT_STRING, "12321" }, + /* bad assignment */ + { "patbad0", "simple", EXPECT_UNDEFINED, NULL }, + { "patbad0", "notundef", EXPECT_TRUE, NULL }, + { "patbad1", "simple", EXPECT_UNDEFINED, NULL }, + /* eof assignment */ + { "pat9", "at-eof", EXPECT_FALSE, NULL }, + /* sentinel at end */ + { NULL, NULL, 0, NULL } + }; + + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr2"))); + cl_assert(file->rules.length == 11); + + run_test_cases(file, cases, 0); + + git_attr_file__free(file); +} + +void test_attr_lookup__check_attr_examples(void) +{ + git_attr_file *file; + + struct attr_expected cases[] = { + { "foo.java", "diff", EXPECT_STRING, "java" }, + { "foo.java", "crlf", EXPECT_FALSE, NULL }, + { "foo.java", "myAttr", EXPECT_TRUE, NULL }, + { "foo.java", "other", EXPECT_UNDEFINED, NULL }, + { "/prefix/dir/foo.java", "diff", EXPECT_STRING, "java" }, + { "/prefix/dir/foo.java", "crlf", EXPECT_FALSE, NULL }, + { "/prefix/dir/foo.java", "myAttr", EXPECT_TRUE, NULL }, + { "/prefix/dir/foo.java", "other", EXPECT_UNDEFINED, NULL }, + { "NoMyAttr.java", "crlf", EXPECT_FALSE, NULL }, + { "NoMyAttr.java", "myAttr", EXPECT_UNDEFINED, NULL }, + { "NoMyAttr.java", "other", EXPECT_UNDEFINED, NULL }, + { "/prefix/dir/NoMyAttr.java", "crlf", EXPECT_FALSE, NULL }, + { "/prefix/dir/NoMyAttr.java", "myAttr", EXPECT_UNDEFINED, NULL }, + { "/prefix/dir/NoMyAttr.java", "other", EXPECT_UNDEFINED, NULL }, + { "README", "caveat", EXPECT_STRING, "unspecified" }, + { "/specific/path/README", "caveat", EXPECT_STRING, "unspecified" }, + { "README", "missing", EXPECT_UNDEFINED, NULL }, + { "/specific/path/README", "missing", EXPECT_UNDEFINED, NULL }, + /* sentinel at end */ + { NULL, NULL, 0, NULL } + }; + + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr3"))); + cl_assert(file->rules.length == 3); + + run_test_cases(file, cases, 0); + + git_attr_file__free(file); +} + +void test_attr_lookup__from_buffer(void) +{ + git_attr_file *file; + + struct attr_expected cases[] = { + { "abc", "foo", EXPECT_TRUE, NULL }, + { "abc", "bar", EXPECT_TRUE, NULL }, + { "abc", "baz", EXPECT_TRUE, NULL }, + { "aaa", "foo", EXPECT_TRUE, NULL }, + { "aaa", "bar", EXPECT_UNDEFINED, NULL }, + { "aaa", "baz", EXPECT_TRUE, NULL }, + { "qqq", "foo", EXPECT_UNDEFINED, NULL }, + { "qqq", "bar", EXPECT_UNDEFINED, NULL }, + { "qqq", "baz", EXPECT_TRUE, NULL }, + { NULL, NULL, 0, NULL } + }; + + cl_git_pass(git_attr_file__new(&file, 0, NULL, NULL)); + + cl_git_pass(git_attr_file__parse_buffer(NULL, NULL, "a* foo\nabc bar\n* baz", file)); + + cl_assert(file->rules.length == 3); + + run_test_cases(file, cases, 0); + + git_attr_file__free(file); +} diff --git a/tests/attr/repo.c b/tests/attr/repo.c new file mode 100644 index 000000000..ef2ad5ce9 --- /dev/null +++ b/tests/attr/repo.c @@ -0,0 +1,310 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "git2/attr.h" +#include "attr.h" + +#include "attr_expect.h" + +static git_repository *g_repo = NULL; + +void test_attr_repo__initialize(void) +{ + /* Before each test, instantiate the attr repo from the fixtures and + * rename the .gitted to .git so it is a repo with a working dir. + * Also rename gitattributes to .gitattributes, because it contains + * macro definitions which are only allowed in the root. + */ + g_repo = cl_git_sandbox_init("attr"); +} + +void test_attr_repo__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +void test_attr_repo__get_one(void) +{ + struct attr_expected test_cases[] = { + { "root_test1", "repoattr", EXPECT_TRUE, NULL }, + { "root_test1", "rootattr", EXPECT_TRUE, NULL }, + { "root_test1", "missingattr", EXPECT_UNDEFINED, NULL }, + { "root_test1", "subattr", EXPECT_UNDEFINED, NULL }, + { "root_test1", "negattr", EXPECT_UNDEFINED, NULL }, + { "root_test2", "repoattr", EXPECT_TRUE, NULL }, + { "root_test2", "rootattr", EXPECT_FALSE, NULL }, + { "root_test2", "missingattr", EXPECT_UNDEFINED, NULL }, + { "root_test2", "multiattr", EXPECT_FALSE, NULL }, + { "root_test3", "repoattr", EXPECT_TRUE, NULL }, + { "root_test3", "rootattr", EXPECT_UNDEFINED, NULL }, + { "root_test3", "multiattr", EXPECT_STRING, "3" }, + { "root_test3", "multi2", EXPECT_UNDEFINED, NULL }, + { "sub/subdir_test1", "repoattr", EXPECT_TRUE, NULL }, + { "sub/subdir_test1", "rootattr", EXPECT_TRUE, NULL }, + { "sub/subdir_test1", "missingattr", EXPECT_UNDEFINED, NULL }, + { "sub/subdir_test1", "subattr", EXPECT_STRING, "yes" }, + { "sub/subdir_test1", "negattr", EXPECT_FALSE, NULL }, + { "sub/subdir_test1", "another", EXPECT_UNDEFINED, NULL }, + { "sub/subdir_test2.txt", "repoattr", EXPECT_TRUE, NULL }, + { "sub/subdir_test2.txt", "rootattr", EXPECT_TRUE, NULL }, + { "sub/subdir_test2.txt", "missingattr", EXPECT_UNDEFINED, NULL }, + { "sub/subdir_test2.txt", "subattr", EXPECT_STRING, "yes" }, + { "sub/subdir_test2.txt", "negattr", EXPECT_FALSE, NULL }, + { "sub/subdir_test2.txt", "another", EXPECT_STRING, "zero" }, + { "sub/subdir_test2.txt", "reposub", EXPECT_TRUE, NULL }, + { "sub/sub/subdir.txt", "another", EXPECT_STRING, "one" }, + { "sub/sub/subdir.txt", "reposubsub", EXPECT_TRUE, NULL }, + { "sub/sub/subdir.txt", "reposub", EXPECT_UNDEFINED, NULL }, + { "does-not-exist", "foo", EXPECT_STRING, "yes" }, + { "sub/deep/file", "deepdeep", EXPECT_TRUE, NULL }, + { "sub/sub/d/no", "test", EXPECT_STRING, "a/b/d/*" }, + { "sub/sub/d/yes", "test", EXPECT_UNDEFINED, NULL }, + { NULL, NULL, 0, NULL } + }, *scan; + + for (scan = test_cases; scan->path != NULL; scan++) { + const char *value; + cl_git_pass(git_attr_get(&value, g_repo, 0, scan->path, scan->attr)); + attr_check_expected(scan->expected, scan->expected_str, scan->attr, value); + } + + cl_assert(git_attr_cache__is_cached(g_repo, 0, ".git/info/attributes")); + cl_assert(git_attr_cache__is_cached(g_repo, 0, ".gitattributes")); + cl_assert(git_attr_cache__is_cached(g_repo, 0, "sub/.gitattributes")); +} + +void test_attr_repo__get_many(void) +{ + const char *names[4] = { "repoattr", "rootattr", "missingattr", "subattr" }; + const char *values[4]; + + cl_git_pass(git_attr_get_many(values, g_repo, 0, "root_test1", 4, names)); + + cl_assert(GIT_ATTR_TRUE(values[0])); + cl_assert(GIT_ATTR_TRUE(values[1])); + cl_assert(GIT_ATTR_UNSPECIFIED(values[2])); + cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); + + cl_git_pass(git_attr_get_many(values, g_repo, 0, "root_test2", 4, names)); + + cl_assert(GIT_ATTR_TRUE(values[0])); + cl_assert(GIT_ATTR_FALSE(values[1])); + cl_assert(GIT_ATTR_UNSPECIFIED(values[2])); + cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); + + cl_git_pass(git_attr_get_many(values, g_repo, 0, "sub/subdir_test1", 4, names)); + + cl_assert(GIT_ATTR_TRUE(values[0])); + cl_assert(GIT_ATTR_TRUE(values[1])); + cl_assert(GIT_ATTR_UNSPECIFIED(values[2])); + cl_assert_equal_s("yes", values[3]); +} + +void test_attr_repo__get_many_in_place(void) +{ + const char *vals[4] = { "repoattr", "rootattr", "missingattr", "subattr" }; + + /* it should be legal to look up values into the same array that has + * the attribute names, overwriting each name as the value is found. + */ + + cl_git_pass(git_attr_get_many(vals, g_repo, 0, "sub/subdir_test1", 4, vals)); + + cl_assert(GIT_ATTR_TRUE(vals[0])); + cl_assert(GIT_ATTR_TRUE(vals[1])); + cl_assert(GIT_ATTR_UNSPECIFIED(vals[2])); + cl_assert_equal_s("yes", vals[3]); +} + +static int count_attrs( + const char *name, + const char *value, + void *payload) +{ + GIT_UNUSED(name); + GIT_UNUSED(value); + + *((int *)payload) += 1; + + return 0; +} + +static int cancel_iteration( + const char *name, + const char *value, + void *payload) +{ + GIT_UNUSED(name); + GIT_UNUSED(value); + + *((int *)payload) -= 1; + + if (*((int *)payload) < 0) + return -1; + + return 0; +} + +void test_attr_repo__foreach(void) +{ + int count; + + count = 0; + cl_git_pass(git_attr_foreach( + g_repo, 0, "root_test1", &count_attrs, &count)); + cl_assert(count == 2); + + count = 0; + cl_git_pass(git_attr_foreach(g_repo, 0, "sub/subdir_test1", + &count_attrs, &count)); + cl_assert(count == 4); /* repoattr, rootattr, subattr, negattr */ + + count = 0; + cl_git_pass(git_attr_foreach(g_repo, 0, "sub/subdir_test2.txt", + &count_attrs, &count)); + cl_assert(count == 6); /* repoattr, rootattr, subattr, reposub, negattr, another */ + + count = 2; + cl_assert_equal_i( + GIT_EUSER, git_attr_foreach( + g_repo, 0, "sub/subdir_test1", &cancel_iteration, &count) + ); +} + +void test_attr_repo__manpage_example(void) +{ + const char *value; + + cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "foo")); + cl_assert(GIT_ATTR_TRUE(value)); + + cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "bar")); + cl_assert(GIT_ATTR_UNSPECIFIED(value)); + + cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "baz")); + cl_assert(GIT_ATTR_FALSE(value)); + + cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "merge")); + cl_assert_equal_s("filfre", value); + + cl_git_pass(git_attr_get(&value, g_repo, 0, "sub/abc", "frotz")); + cl_assert(GIT_ATTR_UNSPECIFIED(value)); +} + +void test_attr_repo__macros(void) +{ + const char *names[5] = { "rootattr", "binary", "diff", "crlf", "frotz" }; + const char *names2[5] = { "mymacro", "positive", "negative", "rootattr", "another" }; + const char *names3[3] = { "macro2", "multi2", "multi3" }; + const char *values[5]; + + cl_git_pass(git_attr_get_many(values, g_repo, 0, "binfile", 5, names)); + + cl_assert(GIT_ATTR_TRUE(values[0])); + cl_assert(GIT_ATTR_TRUE(values[1])); + cl_assert(GIT_ATTR_FALSE(values[2])); + cl_assert(GIT_ATTR_FALSE(values[3])); + cl_assert(GIT_ATTR_UNSPECIFIED(values[4])); + + cl_git_pass(git_attr_get_many(values, g_repo, 0, "macro_test", 5, names2)); + + cl_assert(GIT_ATTR_TRUE(values[0])); + cl_assert(GIT_ATTR_TRUE(values[1])); + cl_assert(GIT_ATTR_FALSE(values[2])); + cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); + cl_assert_equal_s("77", values[4]); + + cl_git_pass(git_attr_get_many(values, g_repo, 0, "macro_test", 3, names3)); + + cl_assert(GIT_ATTR_TRUE(values[0])); + cl_assert(GIT_ATTR_FALSE(values[1])); + cl_assert_equal_s("answer", values[2]); +} + +void test_attr_repo__bad_macros(void) +{ + const char *names[6] = { "rootattr", "positive", "negative", + "firstmacro", "secondmacro", "thirdmacro" }; + const char *values[6]; + + cl_git_pass(git_attr_get_many(values, g_repo, 0, "macro_bad", 6, names)); + + /* these three just confirm that the "mymacro" rule ran */ + cl_assert(GIT_ATTR_UNSPECIFIED(values[0])); + cl_assert(GIT_ATTR_TRUE(values[1])); + cl_assert(GIT_ATTR_FALSE(values[2])); + + /* file contains: + * # let's try some malicious macro defs + * [attr]firstmacro -thirdmacro -secondmacro + * [attr]secondmacro firstmacro -firstmacro + * [attr]thirdmacro secondmacro=hahaha -firstmacro + * macro_bad firstmacro secondmacro thirdmacro + * + * firstmacro assignment list ends up with: + * -thirdmacro -secondmacro + * secondmacro assignment list expands "firstmacro" and ends up with: + * -thirdmacro -secondmacro -firstmacro + * thirdmacro assignment don't expand so list ends up with: + * secondmacro="hahaha" + * + * macro_bad assignment list ends up with: + * -thirdmacro -secondmacro firstmacro && + * -thirdmacro -secondmacro -firstmacro secondmacro && + * secondmacro="hahaha" thirdmacro + * + * so summary results should be: + * -firstmacro secondmacro="hahaha" thirdmacro + */ + cl_assert(GIT_ATTR_FALSE(values[3])); + cl_assert_equal_s("hahaha", values[4]); + cl_assert(GIT_ATTR_TRUE(values[5])); +} + +#define CONTENT "I'm going to be dynamically processed\r\n" \ + "And my line endings...\r\n" \ + "...are going to be\n" \ + "normalized!\r\n" + +#define GITATTR "* text=auto\n" \ + "*.txt text\n" \ + "*.data binary\n" + +static void add_to_workdir(const char *filename, const char *content) +{ + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&buf, "attr", filename)); + cl_git_rewritefile(git_buf_cstr(&buf), content); + + git_buf_free(&buf); +} + +static void assert_proper_normalization(git_index *index, const char *filename, const char *expected_sha) +{ + size_t index_pos; + const git_index_entry *entry; + + add_to_workdir(filename, CONTENT); + cl_git_pass(git_index_add_bypath(index, filename)); + + cl_assert(!git_index_find(&index_pos, index, filename)); + + entry = git_index_get_byindex(index, index_pos); + cl_assert_equal_i(0, git_oid_streq(&entry->oid, expected_sha)); +} + +void test_attr_repo__staging_properly_normalizes_line_endings_according_to_gitattributes_directives(void) +{ + git_index* index; + + cl_git_pass(git_repository_index(&index, g_repo)); + + add_to_workdir(".gitattributes", GITATTR); + + assert_proper_normalization(index, "text.txt", "22c74203bace3c2e950278c7ab08da0fca9f4e9b"); + assert_proper_normalization(index, "huh.dunno", "22c74203bace3c2e950278c7ab08da0fca9f4e9b"); + assert_proper_normalization(index, "binary.data", "66eeff1fcbacf589e6d70aa70edd3fce5be2b37c"); + + git_index_free(index); +} diff --git a/tests/blame/blame_helpers.c b/tests/blame/blame_helpers.c new file mode 100644 index 000000000..d64bb5c4c --- /dev/null +++ b/tests/blame/blame_helpers.c @@ -0,0 +1,64 @@ +#include "blame_helpers.h" + +void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...) +{ + va_list arglist; + + printf("Hunk %zd (line %d +%d): ", idx, + hunk->final_start_line_number, hunk->lines_in_hunk-1); + + va_start(arglist, fmt); + vprintf(fmt, arglist); + va_end(arglist); + + printf("\n"); +} + +void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx, + int start_line, int len, char boundary, const char *commit_id, const char *orig_path) +{ + char expected[41] = {0}, actual[41] = {0}; + const git_blame_hunk *hunk = git_blame_get_hunk_byindex(blame, idx); + cl_assert(hunk); + + if (!strncmp(commit_id, "0000", 4)) { + strcpy(expected, "0000000000000000000000000000000000000000"); + } else { + git_object *obj; + cl_git_pass(git_revparse_single(&obj, repo, commit_id)); + git_oid_fmt(expected, git_object_id(obj)); + git_object_free(obj); + } + + if (hunk->final_start_line_number != start_line) { + hunk_message(idx, hunk, "mismatched start line number: expected %d, got %d", + start_line, hunk->final_start_line_number); + } + cl_assert_equal_i(hunk->final_start_line_number, start_line); + + if (hunk->lines_in_hunk != len) { + hunk_message(idx, hunk, "mismatched line count: expected %d, got %d", + len, hunk->lines_in_hunk); + } + cl_assert_equal_i(hunk->lines_in_hunk, len); + + git_oid_fmt(actual, &hunk->final_commit_id); + if (strcmp(expected, actual)) { + hunk_message(idx, hunk, "has mismatched original id (got %s, expected %s)\n", + actual, expected); + } + cl_assert_equal_s(actual, expected); + if (strcmp(hunk->orig_path, orig_path)) { + hunk_message(idx, hunk, "has mismatched original path (got '%s', expected '%s')\n", + hunk->orig_path, orig_path); + } + cl_assert_equal_s(hunk->orig_path, orig_path); + + if (hunk->boundary != boundary) { + hunk_message(idx, hunk, "doesn't match boundary flag (got %d, expected %d)\n", + hunk->boundary, boundary); + } + cl_assert_equal_i(boundary, hunk->boundary); +} + + diff --git a/tests/blame/blame_helpers.h b/tests/blame/blame_helpers.h new file mode 100644 index 000000000..94321a5b5 --- /dev/null +++ b/tests/blame/blame_helpers.h @@ -0,0 +1,16 @@ +#include "clar_libgit2.h" +#include "blame.h" + +void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...); + +void check_blame_hunk_index( + git_repository *repo, + git_blame *blame, + int idx, + int start_line, + int len, + char boundary, + const char *commit_id, + const char *orig_path); + + diff --git a/tests/blame/buffer.c b/tests/blame/buffer.c new file mode 100644 index 000000000..912ee9846 --- /dev/null +++ b/tests/blame/buffer.c @@ -0,0 +1,166 @@ +#include "blame_helpers.h" + +git_repository *g_repo; +git_blame *g_fileblame, *g_bufferblame; + +void test_blame_buffer__initialize(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); + cl_git_pass(git_blame_file(&g_fileblame, g_repo, "b.txt", NULL)); + g_bufferblame = NULL; +} + +void test_blame_buffer__cleanup(void) +{ + git_blame_free(g_fileblame); + git_blame_free(g_bufferblame); + git_repository_free(g_repo); +} + +void test_blame_buffer__added_line(void) +{ + const git_blame_hunk *hunk; + + const char *buffer = "\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +\n\ +abcdefg\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; + + cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); + cl_assert_equal_i(5, git_blame_get_hunk_count(g_bufferblame)); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "000000", "b.txt"); + + hunk = git_blame_get_hunk_byline(g_bufferblame, 16); + cl_assert(hunk); + cl_assert_equal_s("Ben Straub", hunk->final_signature->name); +} + +void test_blame_buffer__deleted_line(void) +{ + const char *buffer = "\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; + + cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 3, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 9, 1, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 4, 10, 5, 0, "aa06ecca", "b.txt"); +} + +void test_blame_buffer__add_splits_hunk(void) +{ + const char *buffer = "\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +abc\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; + + cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 2, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 8, 1, 0, "00000000", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 4, 9, 3, 0, "63d671eb", "b.txt"); +} + +void test_blame_buffer__delete_crosses_hunk_boundary(void) +{ + const char *buffer = "\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; + + cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 2, 0, "aa06ecca", "b.txt"); +} + +void test_blame_buffer__replace_line(void) +{ + const char *buffer = "\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +abc\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; + + cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 1, 0, "00000000", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 4, 8, 3, 0, "63d671eb", "b.txt"); +} + +void test_blame_buffer__add_lines_at_end(void) +{ + const char *buffer = "\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\ +\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\ +\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\ +\n\ +abc\n\ +def\n"; + cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); + + cl_assert_equal_i(5, git_blame_get_hunk_count(g_bufferblame)); + check_blame_hunk_index(g_repo, g_bufferblame, 0, 1, 4, 0, "da237394", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 5, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 3, 11, 5, 0, "aa06ecca", "b.txt"); + check_blame_hunk_index(g_repo, g_bufferblame, 4, 16, 2, 0, "00000000", "b.txt"); +} diff --git a/tests/blame/getters.c b/tests/blame/getters.c new file mode 100644 index 000000000..66eaeecf9 --- /dev/null +++ b/tests/blame/getters.c @@ -0,0 +1,56 @@ +#include "clar_libgit2.h" + +#include "blame.h" + +git_blame *g_blame; + +void test_blame_getters__initialize(void) +{ + size_t i; + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + git_blame_hunk hunks[] = { + { 3, {{0}}, 1, NULL, {{0}}, "a", 0}, + { 3, {{0}}, 4, NULL, {{0}}, "b", 0}, + { 3, {{0}}, 7, NULL, {{0}}, "c", 0}, + { 3, {{0}}, 10, NULL, {{0}}, "d", 0}, + { 3, {{0}}, 13, NULL, {{0}}, "e", 0}, + }; + + g_blame = git_blame__alloc(NULL, opts, ""); + + for (i=0; i<5; i++) { + git_blame_hunk *h = git__calloc(1, sizeof(git_blame_hunk)); + h->final_start_line_number = hunks[i].final_start_line_number; + h->orig_path = git__strdup(hunks[i].orig_path); + h->lines_in_hunk = hunks[i].lines_in_hunk; + + git_vector_insert(&g_blame->hunks, h); + } +} + +void test_blame_getters__cleanup(void) +{ + git_blame_free(g_blame); +} + + +void test_blame_getters__byindex(void) +{ + const git_blame_hunk *h = git_blame_get_hunk_byindex(g_blame, 2); + cl_assert(h); + cl_assert_equal_s(h->orig_path, "c"); + + h = git_blame_get_hunk_byindex(g_blame, 95); + cl_assert_equal_p(h, NULL); +} + +void test_blame_getters__byline(void) +{ + const git_blame_hunk *h = git_blame_get_hunk_byline(g_blame, 5); + cl_assert(h); + cl_assert_equal_s(h->orig_path, "b"); + + h = git_blame_get_hunk_byline(g_blame, 95); + cl_assert_equal_p(h, NULL); +} diff --git a/tests/blame/harder.c b/tests/blame/harder.c new file mode 100644 index 000000000..7c4dd4f74 --- /dev/null +++ b/tests/blame/harder.c @@ -0,0 +1,71 @@ +#include "clar_libgit2.h" + +#include "blame.h" + + +/** + * The test repo has a history that looks like this: + * + * * (A) bc7c5ac + * |\ + * | * (B) aa06ecc + * * | (C) 63d671e + * |/ + * * (D) da23739 + * * (E) b99f7ac + * + */ + +static git_repository *g_repo = NULL; + +void test_blame_harder__initialize(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); +} + +void test_blame_harder__cleanup(void) +{ + git_repository_free(g_repo); + g_repo = NULL; +} + + + +void test_blame_harder__m(void) +{ + /* TODO */ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + opts.flags = GIT_BLAME_TRACK_COPIES_SAME_FILE; +} + + +void test_blame_harder__c(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + /* Attribute the first hunk in b.txt to (E), since it was cut/pasted from + * a.txt in (D). + */ + opts.flags = GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; +} + +void test_blame_harder__cc(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + /* Attribute the second hunk in b.txt to (E), since it was copy/pasted from + * a.txt in (C). + */ + opts.flags = GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; +} + +void test_blame_harder__ccc(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + /* Attribute the third hunk in b.txt to (E). This hunk was deleted from + * a.txt in (D), but reintroduced in (B). + */ + opts.flags = GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES; +} diff --git a/tests/blame/simple.c b/tests/blame/simple.c new file mode 100644 index 000000000..79bd56b83 --- /dev/null +++ b/tests/blame/simple.c @@ -0,0 +1,305 @@ +#include "blame_helpers.h" + +static git_repository *g_repo; +static git_blame *g_blame; + +void test_blame_simple__initialize(void) +{ + g_repo = NULL; + g_blame = NULL; +} + +void test_blame_simple__cleanup(void) +{ + git_blame_free(g_blame); + git_repository_free(g_repo); +} + +/* + * $ git blame -s branch_file.txt + * orig line no final line no + * commit V author timestamp V + * c47800c7 1 (Scott Chacon 2010-05-25 11:58:14 -0700 1 + * a65fedf3 2 (Scott Chacon 2011-08-09 19:33:46 -0700 2 + */ +void test_blame_simple__trivial_testrepo(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo/.gitted"))); + cl_git_pass(git_blame_file(&g_blame, g_repo, "branch_file.txt", NULL)); + + cl_assert_equal_i(2, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, 0, "c47800c7", "branch_file.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, 0, "a65fedf3", "branch_file.txt"); +} + +/* + * $ git blame -n b.txt + * orig line no final line no + * commit V author timestamp V + * da237394 1 (Ben Straub 2013-02-12 15:11:30 -0800 1 + * da237394 2 (Ben Straub 2013-02-12 15:11:30 -0800 2 + * da237394 3 (Ben Straub 2013-02-12 15:11:30 -0800 3 + * da237394 4 (Ben Straub 2013-02-12 15:11:30 -0800 4 + * ^b99f7ac 1 (Ben Straub 2013-02-12 15:10:12 -0800 5 + * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 + * 63d671eb 7 (Ben Straub 2013-02-12 15:13:04 -0800 7 + * 63d671eb 8 (Ben Straub 2013-02-12 15:13:04 -0800 8 + * 63d671eb 9 (Ben Straub 2013-02-12 15:13:04 -0800 9 + * 63d671eb 10 (Ben Straub 2013-02-12 15:13:04 -0800 10 + * aa06ecca 6 (Ben Straub 2013-02-12 15:14:46 -0800 11 + * aa06ecca 7 (Ben Straub 2013-02-12 15:14:46 -0800 12 + * aa06ecca 8 (Ben Straub 2013-02-12 15:14:46 -0800 13 + * aa06ecca 9 (Ben Straub 2013-02-12 15:14:46 -0800 14 + * aa06ecca 10 (Ben Straub 2013-02-12 15:14:46 -0800 15 + */ +void test_blame_simple__trivial_blamerepo(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); + cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", NULL)); + + cl_assert_equal_i(4, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, 0, "da237394", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 2, 6, 5, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 3, 11, 5, 0, "aa06ecca", "b.txt"); +} + + +/* + * $ git blame -n 359fc2d -- include/git2.h + * orig line no final line no + * commit orig path V author timestamp V + * d12299fe src/git.h 1 (Vicent Martí 2010-12-03 22:22:10 +0200 1 + * 359fc2d2 include/git2.h 2 (Edward Thomson 2013-01-08 17:07:25 -0600 2 + * d12299fe src/git.h 5 (Vicent Martí 2010-12-03 22:22:10 +0200 3 + * bb742ede include/git2.h 4 (Vicent Martí 2011-09-19 01:54:32 +0300 4 + * bb742ede include/git2.h 5 (Vicent Martí 2011-09-19 01:54:32 +0300 5 + * d12299fe src/git.h 24 (Vicent Martí 2010-12-03 22:22:10 +0200 6 + * d12299fe src/git.h 25 (Vicent Martí 2010-12-03 22:22:10 +0200 7 + * d12299fe src/git.h 26 (Vicent Martí 2010-12-03 22:22:10 +0200 8 + * d12299fe src/git.h 27 (Vicent Martí 2010-12-03 22:22:10 +0200 9 + * d12299fe src/git.h 28 (Vicent Martí 2010-12-03 22:22:10 +0200 10 + * 96fab093 include/git2.h 11 (Sven Strickroth 2011-10-09 18:37:41 +0200 11 + * 9d1dcca2 src/git2.h 33 (Vicent Martí 2011-02-07 10:35:58 +0200 12 + * 44908fe7 src/git2.h 29 (Vicent Martí 2010-12-06 23:03:16 +0200 13 + * a15c550d include/git2.h 14 (Vicent Martí 2011-11-16 14:09:44 +0100 14 + * 44908fe7 src/git2.h 30 (Vicent Martí 2010-12-06 23:03:16 +0200 15 + * d12299fe src/git.h 32 (Vicent Martí 2010-12-03 22:22:10 +0200 16 + * 44908fe7 src/git2.h 33 (Vicent Martí 2010-12-06 23:03:16 +0200 17 + * d12299fe src/git.h 34 (Vicent Martí 2010-12-03 22:22:10 +0200 18 + * 44908fe7 src/git2.h 35 (Vicent Martí 2010-12-06 23:03:16 +0200 19 + * 638c2ca4 src/git2.h 36 (Vicent Martí 2010-12-18 02:10:25 +0200 20 + * 44908fe7 src/git2.h 36 (Vicent Martí 2010-12-06 23:03:16 +0200 21 + * d12299fe src/git.h 37 (Vicent Martí 2010-12-03 22:22:10 +0200 22 + * 44908fe7 src/git2.h 38 (Vicent Martí 2010-12-06 23:03:16 +0200 23 + * 44908fe7 src/git2.h 39 (Vicent Martí 2010-12-06 23:03:16 +0200 24 + * bf787bd8 include/git2.h 25 (Carlos Martín Nieto 2012-04-08 18:56:50 +0200 25 + * 0984c876 include/git2.h 26 (Scott J. Goldman 2012-11-28 18:27:43 -0800 26 + * 2f8a8ab2 src/git2.h 41 (Vicent Martí 2011-01-29 01:56:25 +0200 27 + * 27df4275 include/git2.h 47 (Michael Schubert 2011-06-28 14:13:12 +0200 28 + * a346992f include/git2.h 28 (Ben Straub 2012-05-10 09:47:14 -0700 29 + * d12299fe src/git.h 40 (Vicent Martí 2010-12-03 22:22:10 +0200 30 + * 44908fe7 src/git2.h 41 (Vicent Martí 2010-12-06 23:03:16 +0200 31 + * 44908fe7 src/git2.h 42 (Vicent Martí 2010-12-06 23:03:16 +0200 32 + * 44908fe7 src/git2.h 43 (Vicent Martí 2010-12-06 23:03:16 +0200 33 + * 44908fe7 src/git2.h 44 (Vicent Martí 2010-12-06 23:03:16 +0200 34 + * 44908fe7 src/git2.h 45 (Vicent Martí 2010-12-06 23:03:16 +0200 35 + * 65b09b1d include/git2.h 33 (Russell Belfer 2012-02-02 18:03:43 -0800 36 + * d12299fe src/git.h 46 (Vicent Martí 2010-12-03 22:22:10 +0200 37 + * 44908fe7 src/git2.h 47 (Vicent Martí 2010-12-06 23:03:16 +0200 38 + * 5d4cd003 include/git2.h 55 (Carlos Martín Nieto 2011-03-28 17:02:45 +0200 39 + * 41fb1ca0 include/git2.h 39 (Philip Kelley 2012-10-29 13:41:14 -0400 40 + * 2dc31040 include/git2.h 56 (Carlos Martín Nieto 2011-06-20 18:58:57 +0200 41 + * 764df57e include/git2.h 40 (Ben Straub 2012-06-15 13:14:43 -0700 42 + * 5280f4e6 include/git2.h 41 (Ben Straub 2012-07-31 19:39:06 -0700 43 + * 613d5eb9 include/git2.h 43 (Philip Kelley 2012-11-28 11:42:37 -0500 44 + * d12299fe src/git.h 48 (Vicent Martí 2010-12-03 22:22:10 +0200 45 + * 111ee3fe include/git2.h 41 (Vicent Martí 2012-07-11 14:37:26 +0200 46 + * f004c4a8 include/git2.h 44 (Russell Belfer 2012-08-21 17:26:39 -0700 47 + * 111ee3fe include/git2.h 42 (Vicent Martí 2012-07-11 14:37:26 +0200 48 + * 9c82357b include/git2.h 58 (Carlos Martín Nieto 2011-06-17 18:13:14 +0200 49 + * d6258deb include/git2.h 61 (Carlos Martín Nieto 2011-06-25 15:10:09 +0200 50 + * b311e313 include/git2.h 63 (Julien Miotte 2011-07-27 18:31:13 +0200 51 + * 3412391d include/git2.h 63 (Carlos Martín Nieto 2011-07-07 11:47:31 +0200 52 + * bfc9ca59 include/git2.h 43 (Russell Belfer 2012-03-28 16:45:36 -0700 53 + * bf477ed4 include/git2.h 44 (Michael Schubert 2012-02-15 00:33:38 +0100 54 + * edebceff include/git2.h 46 (nulltoken 2012-05-01 13:57:45 +0200 55 + * 743a4b3b include/git2.h 48 (nulltoken 2012-06-15 22:24:59 +0200 56 + * 0a32dca5 include/git2.h 54 (Michael Schubert 2012-08-19 22:26:32 +0200 57 + * 590fb68b include/git2.h 55 (nulltoken 2012-10-04 13:47:45 +0200 58 + * bf477ed4 include/git2.h 45 (Michael Schubert 2012-02-15 00:33:38 +0100 59 + * d12299fe src/git.h 49 (Vicent Martí 2010-12-03 22:22:10 +0200 60 + */ +void test_blame_simple__trivial_libgit2(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + git_object *obj; + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("../.."))); + + /* This test can't work on a shallow clone */ + if (git_repository_is_shallow(g_repo)) + return; + + cl_git_pass(git_revparse_single(&obj, g_repo, "359fc2d")); + git_oid_cpy(&opts.newest_commit, git_object_id(obj)); + git_object_free(obj); + + cl_git_pass(git_blame_file(&g_blame, g_repo, "include/git2.h", &opts)); + + check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, 0, "359fc2d2", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 2, 3, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 3, 4, 2, 0, "bb742ede", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 4, 6, 5, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 5, 11, 1, 0, "96fab093", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 6, 12, 1, 0, "9d1dcca2", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 7, 13, 1, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 8, 14, 1, 0, "a15c550d", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 9, 15, 1, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 10, 16, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 11, 17, 1, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 12, 18, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 13, 19, 1, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 14, 20, 1, 0, "638c2ca4", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 15, 21, 1, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 16, 22, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 17, 23, 2, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 18, 25, 1, 0, "bf787bd8", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 19, 26, 1, 0, "0984c876", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 20, 27, 1, 0, "2f8a8ab2", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 21, 28, 1, 0, "27df4275", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 22, 29, 1, 0, "a346992f", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 23, 30, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 24, 31, 5, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 25, 36, 1, 0, "65b09b1d", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 26, 37, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 27, 38, 1, 0, "44908fe7", "src/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 28, 39, 1, 0, "5d4cd003", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 29, 40, 1, 0, "41fb1ca0", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 30, 41, 1, 0, "2dc31040", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 31, 42, 1, 0, "764df57e", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 32, 43, 1, 0, "5280f4e6", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 33, 44, 1, 0, "613d5eb9", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 34, 45, 1, 0, "d12299fe", "src/git.h"); + check_blame_hunk_index(g_repo, g_blame, 35, 46, 1, 0, "111ee3fe", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 36, 47, 1, 0, "f004c4a8", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 37, 48, 1, 0, "111ee3fe", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 38, 49, 1, 0, "9c82357b", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 39, 50, 1, 0, "d6258deb", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 40, 51, 1, 0, "b311e313", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 41, 52, 1, 0, "3412391d", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 42, 53, 1, 0, "bfc9ca59", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 43, 54, 1, 0, "bf477ed4", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 44, 55, 1, 0, "edebceff", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 45, 56, 1, 0, "743a4b3b", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 46, 57, 1, 0, "0a32dca5", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 47, 58, 1, 0, "590fb68b", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 48, 59, 1, 0, "bf477ed4", "include/git2.h"); + check_blame_hunk_index(g_repo, g_blame, 49, 60, 1, 0, "d12299fe", "src/git.h"); +} + + +/* + * $ git blame -n b.txt -L 8 + * orig line no final line no + * commit V author timestamp V + * 63d671eb 8 (Ben Straub 2013-02-12 15:13:04 -0800 8 + * 63d671eb 9 (Ben Straub 2013-02-12 15:13:04 -0800 9 + * 63d671eb 10 (Ben Straub 2013-02-12 15:13:04 -0800 10 + * aa06ecca 6 (Ben Straub 2013-02-12 15:14:46 -0800 11 + * aa06ecca 7 (Ben Straub 2013-02-12 15:14:46 -0800 12 + * aa06ecca 8 (Ben Straub 2013-02-12 15:14:46 -0800 13 + * aa06ecca 9 (Ben Straub 2013-02-12 15:14:46 -0800 14 + * aa06ecca 10 (Ben Straub 2013-02-12 15:14:46 -0800 15 + */ +void test_blame_simple__can_restrict_lines_min(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); + + opts.min_line = 8; + cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); + cl_assert_equal_i(2, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 8, 3, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 11, 5, 0, "aa06ecca", "b.txt"); +} + +/* + * $ git blame -n b.txt -L ,6 + * orig line no final line no + * commit V author timestamp V + * da237394 1 (Ben Straub 2013-02-12 15:11:30 -0800 1 + * da237394 2 (Ben Straub 2013-02-12 15:11:30 -0800 2 + * da237394 3 (Ben Straub 2013-02-12 15:11:30 -0800 3 + * da237394 4 (Ben Straub 2013-02-12 15:11:30 -0800 4 + * ^b99f7ac 1 (Ben Straub 2013-02-12 15:10:12 -0800 5 + * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 + */ +void test_blame_simple__can_restrict_lines_max(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); + + opts.max_line = 6; + cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); + cl_assert_equal_i(3, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, 0, "da237394", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 2, 6, 1, 0, "63d671eb", "b.txt"); +} + +/* + * $ git blame -n b.txt -L 2,7 + * orig line no final line no + * commit V author timestamp V + * da237394 2 (Ben Straub 2013-02-12 15:11:30 -0800 2 + * da237394 3 (Ben Straub 2013-02-12 15:11:30 -0800 3 + * da237394 4 (Ben Straub 2013-02-12 15:11:30 -0800 4 + * ^b99f7ac 1 (Ben Straub 2013-02-12 15:10:12 -0800 5 + * 63d671eb 6 (Ben Straub 2013-02-12 15:13:04 -0800 6 + * 63d671eb 7 (Ben Straub 2013-02-12 15:13:04 -0800 7 + */ +void test_blame_simple__can_restrict_lines_both(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); + + opts.min_line = 2; + opts.max_line = 7; + cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); + cl_assert_equal_i(3, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 2, 3, 0, "da237394", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 2, 6, 2, 0, "63d671eb", "b.txt"); +} + +/* + * $ git blame -n branch_file.txt be3563a..HEAD + * orig line no final line no + * commit V author timestamp V + * ^be3563a 1 (Scott Chacon 2010-05-25 11:58:27 -0700 1) hi + * a65fedf3 2 (Scott Chacon 2011-08-09 19:33:46 -0700 2) bye! + */ +void test_blame_simple__can_restrict_to_newish_commits(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); + + { + git_object *obj; + cl_git_pass(git_revparse_single(&obj, g_repo, "be3563a")); + git_oid_cpy(&opts.oldest_commit, git_object_id(obj)); + git_object_free(obj); + } + + cl_git_pass(git_blame_file(&g_blame, g_repo, "branch_file.txt", &opts)); + + cl_assert_equal_i(2, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, 1, "be3563a", "branch_file.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, 0, "a65fedf", "branch_file.txt"); +} diff --git a/tests/buf/basic.c b/tests/buf/basic.c new file mode 100644 index 000000000..d558757a9 --- /dev/null +++ b/tests/buf/basic.c @@ -0,0 +1,29 @@ +#include "clar_libgit2.h" +#include "buffer.h" + +static const char *test_string = "Have you seen that? Have you seeeen that??"; + +void test_buf_basic__resize(void) +{ + git_buf buf1 = GIT_BUF_INIT; + git_buf_puts(&buf1, test_string); + cl_assert(git_buf_oom(&buf1) == 0); + cl_assert_equal_s(git_buf_cstr(&buf1), test_string); + + git_buf_puts(&buf1, test_string); + cl_assert(strlen(git_buf_cstr(&buf1)) == strlen(test_string) * 2); + git_buf_free(&buf1); +} + +void test_buf_basic__printf(void) +{ + git_buf buf2 = GIT_BUF_INIT; + git_buf_printf(&buf2, "%s %s %d ", "shoop", "da", 23); + cl_assert(git_buf_oom(&buf2) == 0); + cl_assert_equal_s(git_buf_cstr(&buf2), "shoop da 23 "); + + git_buf_printf(&buf2, "%s %d", "woop", 42); + cl_assert(git_buf_oom(&buf2) == 0); + cl_assert_equal_s(git_buf_cstr(&buf2), "shoop da 23 woop 42"); + git_buf_free(&buf2); +} diff --git a/tests/buf/splice.c b/tests/buf/splice.c new file mode 100644 index 000000000..e80c93105 --- /dev/null +++ b/tests/buf/splice.c @@ -0,0 +1,93 @@ +#include "clar_libgit2.h" +#include "buffer.h" + +static git_buf _buf; + +void test_buf_splice__initialize(void) { + git_buf_init(&_buf, 16); +} + +void test_buf_splice__cleanup(void) { + git_buf_free(&_buf); +} + +void test_buf_splice__preprend(void) +{ + git_buf_sets(&_buf, "world!"); + + cl_git_pass(git_buf_splice(&_buf, 0, 0, "Hello Dolly", strlen("Hello "))); + + cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); +} + +void test_buf_splice__append(void) +{ + git_buf_sets(&_buf, "Hello"); + + cl_git_pass(git_buf_splice(&_buf, git_buf_len(&_buf), 0, " world!", strlen(" world!"))); + + cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); +} + +void test_buf_splice__insert_at(void) +{ + git_buf_sets(&_buf, "Hell world!"); + + cl_git_pass(git_buf_splice(&_buf, strlen("Hell"), 0, "o", strlen("o"))); + + cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); +} + +void test_buf_splice__remove_at(void) +{ + git_buf_sets(&_buf, "Hello world of warcraft!"); + + cl_git_pass(git_buf_splice(&_buf, strlen("Hello world"), strlen(" of warcraft"), "", 0)); + + cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); +} + +void test_buf_splice__replace(void) +{ + git_buf_sets(&_buf, "Hell0 w0rld!"); + + cl_git_pass(git_buf_splice(&_buf, strlen("Hell"), strlen("0 w0"), "o wo", strlen("o wo"))); + + cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); +} + +void test_buf_splice__replace_with_longer(void) +{ + git_buf_sets(&_buf, "Hello you!"); + + cl_git_pass(git_buf_splice(&_buf, strlen("Hello "), strlen("you"), "world", strlen("world"))); + + cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); +} + +void test_buf_splice__replace_with_shorter(void) +{ + git_buf_sets(&_buf, "Brave new world!"); + + cl_git_pass(git_buf_splice(&_buf, 0, strlen("Brave new"), "Hello", strlen("Hello"))); + + cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); +} + +void test_buf_splice__truncate(void) +{ + git_buf_sets(&_buf, "Hello world!!"); + + cl_git_pass(git_buf_splice(&_buf, strlen("Hello world!"), strlen("!"), "", 0)); + + cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); +} + +void test_buf_splice__dont_do_anything(void) +{ + git_buf_sets(&_buf, "Hello world!"); + + cl_git_pass(git_buf_splice(&_buf, 3, 0, "Hello", 0)); + + cl_assert_equal_s("Hello world!", git_buf_cstr(&_buf)); +} diff --git a/tests/checkout/binaryunicode.c b/tests/checkout/binaryunicode.c new file mode 100644 index 000000000..14ab9fdfa --- /dev/null +++ b/tests/checkout/binaryunicode.c @@ -0,0 +1,58 @@ +#include "clar_libgit2.h" +#include "refs.h" +#include "repo/repo_helpers.h" +#include "path.h" +#include "fileops.h" + +static git_repository *g_repo; + +void test_checkout_binaryunicode__initialize(void) +{ + g_repo = cl_git_sandbox_init("binaryunicode"); +} + +void test_checkout_binaryunicode__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void execute_test(void) +{ + git_oid oid, check; + git_commit *commit; + git_tree *tree; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/branch1")); + cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); + cl_git_pass(git_commit_tree(&tree, commit)); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_checkout_tree(g_repo, (git_object *)tree, &opts)); + + git_tree_free(tree); + git_commit_free(commit); + + /* Verify that the lenna.jpg file was checked out correctly */ + cl_git_pass(git_oid_fromstr(&check, "8ab005d890fe53f65eda14b23672f60d9f4ec5a1")); + cl_git_pass(git_odb_hashfile(&oid, "binaryunicode/lenna.jpg", GIT_OBJ_BLOB)); + cl_assert(git_oid_equal(&oid, &check)); + + /* Verify that the text file was checked out correctly */ + cl_git_pass(git_oid_fromstr(&check, "965b223880dd4249e2c66a0cc0b4cffe1dc40f5a")); + cl_git_pass(git_odb_hashfile(&oid, "binaryunicode/utf16_withbom_noeol_crlf.txt", GIT_OBJ_BLOB)); + cl_assert(git_oid_equal(&oid, &check)); +} + +void test_checkout_binaryunicode__noautocrlf(void) +{ + cl_repo_set_bool(g_repo, "core.autocrlf", false); + execute_test(); +} + +void test_checkout_binaryunicode__autocrlf(void) +{ + cl_repo_set_bool(g_repo, "core.autocrlf", true); + execute_test(); +} diff --git a/tests/checkout/checkout_helpers.c b/tests/checkout/checkout_helpers.c new file mode 100644 index 000000000..06b4e0682 --- /dev/null +++ b/tests/checkout/checkout_helpers.c @@ -0,0 +1,130 @@ +#include "clar_libgit2.h" +#include "checkout_helpers.h" +#include "refs.h" +#include "fileops.h" + +void assert_on_branch(git_repository *repo, const char *branch) +{ + git_reference *head; + git_buf bname = GIT_BUF_INIT; + + cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE)); + cl_assert_(git_reference_type(head) == GIT_REF_SYMBOLIC, branch); + + cl_git_pass(git_buf_joinpath(&bname, "refs/heads", branch)); + cl_assert_equal_s(bname.ptr, git_reference_symbolic_target(head)); + + git_reference_free(head); + git_buf_free(&bname); +} + +void reset_index_to_treeish(git_object *treeish) +{ + git_object *tree; + git_index *index; + git_repository *repo = git_object_owner(treeish); + + cl_git_pass(git_object_peel(&tree, treeish, GIT_OBJ_TREE)); + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_read_tree(index, (git_tree *)tree)); + cl_git_pass(git_index_write(index)); + + git_object_free(tree); + git_index_free(index); +} + +int checkout_count_callback( + git_checkout_notify_t why, + const char *path, + const git_diff_file *baseline, + const git_diff_file *target, + const git_diff_file *workdir, + void *payload) +{ + checkout_counts *ct = payload; + + GIT_UNUSED(baseline); GIT_UNUSED(target); GIT_UNUSED(workdir); + + if (why & GIT_CHECKOUT_NOTIFY_CONFLICT) { + ct->n_conflicts++; + + if (ct->debug) { + if (workdir) { + if (baseline) { + if (target) + fprintf(stderr, "M %s (conflicts with M %s)\n", + workdir->path, target->path); + else + fprintf(stderr, "M %s (conflicts with D %s)\n", + workdir->path, baseline->path); + } else { + if (target) + fprintf(stderr, "Existing %s (conflicts with A %s)\n", + workdir->path, target->path); + else + fprintf(stderr, "How can an untracked file be a conflict (%s)\n", workdir->path); + } + } else { + if (baseline) { + if (target) + fprintf(stderr, "D %s (conflicts with M %s)\n", + target->path, baseline->path); + else + fprintf(stderr, "D %s (conflicts with D %s)\n", + baseline->path, baseline->path); + } else { + if (target) + fprintf(stderr, "How can an added file with no workdir be a conflict (%s)\n", target->path); + else + fprintf(stderr, "How can a nonexistent file be a conflict (%s)\n", path); + } + } + } + } + + if (why & GIT_CHECKOUT_NOTIFY_DIRTY) { + ct->n_dirty++; + + if (ct->debug) { + if (workdir) + fprintf(stderr, "M %s\n", workdir->path); + else + fprintf(stderr, "D %s\n", baseline->path); + } + } + + if (why & GIT_CHECKOUT_NOTIFY_UPDATED) { + ct->n_updates++; + + if (ct->debug) { + if (baseline) { + if (target) + fprintf(stderr, "update: M %s\n", path); + else + fprintf(stderr, "update: D %s\n", path); + } else { + if (target) + fprintf(stderr, "update: A %s\n", path); + else + fprintf(stderr, "update: this makes no sense %s\n", path); + } + } + } + + if (why & GIT_CHECKOUT_NOTIFY_UNTRACKED) { + ct->n_untracked++; + + if (ct->debug) + fprintf(stderr, "? %s\n", path); + } + + if (why & GIT_CHECKOUT_NOTIFY_IGNORED) { + ct->n_ignored++; + + if (ct->debug) + fprintf(stderr, "I %s\n", path); + } + + return 0; +} diff --git a/tests/checkout/checkout_helpers.h b/tests/checkout/checkout_helpers.h new file mode 100644 index 000000000..705ee903d --- /dev/null +++ b/tests/checkout/checkout_helpers.h @@ -0,0 +1,29 @@ +#include "buffer.h" +#include "git2/object.h" +#include "git2/repository.h" + +extern void assert_on_branch(git_repository *repo, const char *branch); +extern void reset_index_to_treeish(git_object *treeish); + +#define check_file_contents(PATH,EXP) \ + cl_assert_equal_file(EXP,0,PATH) + +#define check_file_contents_nocr(PATH,EXP) \ + cl_assert_equal_file_ignore_cr(EXP,0,PATH) + +typedef struct { + int n_conflicts; + int n_dirty; + int n_updates; + int n_untracked; + int n_ignored; + int debug; +} checkout_counts; + +extern int checkout_count_callback( + git_checkout_notify_t why, + const char *path, + const git_diff_file *baseline, + const git_diff_file *target, + const git_diff_file *workdir, + void *payload); diff --git a/tests/checkout/conflict.c b/tests/checkout/conflict.c new file mode 100644 index 000000000..66965a89b --- /dev/null +++ b/tests/checkout/conflict.c @@ -0,0 +1,1127 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/sys/index.h" +#include "fileops.h" + +static git_repository *g_repo; +static git_index *g_index; + +#define TEST_REPO_PATH "merge-resolve" + +#define CONFLICTING_ANCESTOR_OID "d427e0b2e138501a3d15cc376077a3631e15bd46" +#define CONFLICTING_OURS_OID "4e886e602529caa9ab11d71f86634bd1b6e0de10" +#define CONFLICTING_THEIRS_OID "2bd0a343aeef7a2cf0d158478966a6e587ff3863" + +#define AUTOMERGEABLE_ANCESTOR_OID "6212c31dab5e482247d7977e4f0dd3601decf13b" +#define AUTOMERGEABLE_OURS_OID "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf" +#define AUTOMERGEABLE_THEIRS_OID "058541fc37114bfc1dddf6bd6bffc7fae5c2e6fe" + +#define LINK_ANCESTOR_OID "1a010b1c0f081b2e8901d55307a15c29ff30af0e" +#define LINK_OURS_OID "72ea499e108df5ff0a4a913e7655bbeeb1fb69f2" +#define LINK_THEIRS_OID "8bfb012a6d809e499bd8d3e194a3929bc8995b93" + +#define LINK_ANCESTOR_TARGET "file" +#define LINK_OURS_TARGET "other-file" +#define LINK_THEIRS_TARGET "still-another-file" + +#define CONFLICTING_OURS_FILE \ + "this file is changed in master and branch\n" +#define CONFLICTING_THEIRS_FILE \ + "this file is changed in branch and master\n" +#define CONFLICTING_DIFF3_FILE \ + "<<<<<<< ours\n" \ + "this file is changed in master and branch\n" \ + "=======\n" \ + "this file is changed in branch and master\n" \ + ">>>>>>> theirs\n" + +#define AUTOMERGEABLE_MERGED_FILE \ + "this file is changed in master\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is changed in branch\n" + +struct checkout_index_entry { + uint16_t mode; + char oid_str[41]; + int stage; + char path[128]; +}; + +struct checkout_name_entry { + char ancestor[64]; + char ours[64]; + char theirs[64]; +}; + +void test_checkout_conflict__initialize(void) +{ + g_repo = cl_git_sandbox_init(TEST_REPO_PATH); + git_repository_index(&g_index, g_repo); + + cl_git_rewritefile( + TEST_REPO_PATH "/.gitattributes", + "* text eol=lf\n"); +} + +void test_checkout_conflict__cleanup(void) +{ + git_index_free(g_index); + cl_git_sandbox_cleanup(); +} + +static void create_index(struct checkout_index_entry *entries, size_t entries_len) +{ + git_buf path = GIT_BUF_INIT; + size_t i; + + for (i = 0; i < entries_len; i++) { + git_buf_joinpath(&path, TEST_REPO_PATH, entries[i].path); + + if (entries[i].stage == 3 && (i == 0 || strcmp(entries[i-1].path, entries[i].path) != 0 || entries[i-1].stage != 2)) + p_unlink(git_buf_cstr(&path)); + + git_index_remove_bypath(g_index, entries[i].path); + } + + for (i = 0; i < entries_len; i++) { + git_index_entry entry; + + memset(&entry, 0x0, sizeof(git_index_entry)); + + entry.mode = entries[i].mode; + entry.flags = entries[i].stage << GIT_IDXENTRY_STAGESHIFT; + git_oid_fromstr(&entry.oid, entries[i].oid_str); + entry.path = entries[i].path; + + cl_git_pass(git_index_add(g_index, &entry)); + } + + git_buf_free(&path); +} + +static void create_index_names(struct checkout_name_entry *entries, size_t entries_len) +{ + size_t i; + + for (i = 0; i < entries_len; i++) { + cl_git_pass(git_index_name_add(g_index, + strlen(entries[i].ancestor) == 0 ? NULL : entries[i].ancestor, + strlen(entries[i].ours) == 0 ? NULL : entries[i].ours, + strlen(entries[i].theirs) == 0 ? NULL : entries[i].theirs)); + } +} + +static void create_conflicting_index(void) +{ + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting.txt" }, + { 0100644, CONFLICTING_OURS_OID, 2, "conflicting.txt" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting.txt" }, + }; + + create_index(checkout_index_entries, 3); + git_index_write(g_index); +} + +static void ensure_workdir_contents(const char *path, const char *contents) +{ + git_buf fullpath = GIT_BUF_INIT, data_buf = GIT_BUF_INIT; + + cl_git_pass( + git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); + + cl_git_pass(git_futils_readbuffer(&data_buf, git_buf_cstr(&fullpath))); + cl_assert(strcmp(git_buf_cstr(&data_buf), contents) == 0); + + git_buf_free(&fullpath); + git_buf_free(&data_buf); +} + +static void ensure_workdir_oid(const char *path, const char *oid_str) +{ + git_oid expected, actual; + + cl_git_pass(git_oid_fromstr(&expected, oid_str)); + cl_git_pass(git_repository_hashfile(&actual, g_repo, path, GIT_OBJ_BLOB, NULL)); + cl_assert(git_oid_cmp(&expected, &actual) == 0); +} + +static void ensure_workdir_mode(const char *path, int mode) +{ +#ifndef GIT_WIN32 + git_buf fullpath = GIT_BUF_INIT; + struct stat st; + + cl_git_pass( + git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); + + cl_git_pass(p_stat(git_buf_cstr(&fullpath), &st)); + cl_assert_equal_i(mode, st.st_mode); + + git_buf_free(&fullpath); +#endif +} + +static void ensure_workdir(const char *path, int mode, const char *oid_str) +{ + ensure_workdir_mode(path, mode); + ensure_workdir_oid(path, oid_str); +} + +static void ensure_workdir_link(const char *path, const char *target) +{ +#ifdef GIT_WIN32 + ensure_workdir_contents(path, target); +#else + git_buf fullpath = GIT_BUF_INIT; + char actual[1024]; + struct stat st; + int len; + + cl_git_pass( + git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); + + cl_git_pass(p_lstat(git_buf_cstr(&fullpath), &st)); + cl_assert(S_ISLNK(st.st_mode)); + + cl_assert((len = p_readlink(git_buf_cstr(&fullpath), actual, 1024)) > 0); + actual[len] = '\0'; + cl_assert(strcmp(actual, target) == 0); + + git_buf_free(&fullpath); +#endif +} + +void test_checkout_conflict__ignored(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy |= GIT_CHECKOUT_SKIP_UNMERGED; + + create_conflicting_index(); + cl_git_pass(p_unlink(TEST_REPO_PATH "/conflicting.txt")); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + cl_assert(!git_path_exists(TEST_REPO_PATH "/conflicting.txt")); +} + +void test_checkout_conflict__ours(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy |= GIT_CHECKOUT_USE_OURS; + + create_conflicting_index(); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_contents("conflicting.txt", CONFLICTING_OURS_FILE); +} + +void test_checkout_conflict__theirs(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy |= GIT_CHECKOUT_USE_THEIRS; + + create_conflicting_index(); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_contents("conflicting.txt", CONFLICTING_THEIRS_FILE); + +} + +void test_checkout_conflict__diff3(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + create_conflicting_index(); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_contents("conflicting.txt", CONFLICTING_DIFF3_FILE); +} + +void test_checkout_conflict__automerge(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "automergeable.txt" }, + { 0100644, AUTOMERGEABLE_OURS_OID, 2, "automergeable.txt" }, + { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "automergeable.txt" }, + }; + + create_index(checkout_index_entries, 3); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_contents("automergeable.txt", AUTOMERGEABLE_MERGED_FILE); +} + +void test_checkout_conflict__directory_file(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-1" }, + { 0100644, CONFLICTING_OURS_OID, 2, "df-1" }, + { 0100644, CONFLICTING_THEIRS_OID, 0, "df-1/file" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-2" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "df-2" }, + { 0100644, CONFLICTING_OURS_OID, 0, "df-2/file" }, + + { 0100644, CONFLICTING_THEIRS_OID, 3, "df-3" }, + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-3/file" }, + { 0100644, CONFLICTING_OURS_OID, 2, "df-3/file" }, + + { 0100644, CONFLICTING_OURS_OID, 2, "df-4" }, + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-4/file" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "df-4/file" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 12); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_oid("df-1/file", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("df-1~ours", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-2/file", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-2~theirs", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("df-3/file", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-3~theirs", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("df-4~ours", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-4/file", CONFLICTING_THEIRS_OID); +} + +void test_checkout_conflict__directory_file_with_custom_labels(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-1" }, + { 0100644, CONFLICTING_OURS_OID, 2, "df-1" }, + { 0100644, CONFLICTING_THEIRS_OID, 0, "df-1/file" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-2" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "df-2" }, + { 0100644, CONFLICTING_OURS_OID, 0, "df-2/file" }, + + { 0100644, CONFLICTING_THEIRS_OID, 3, "df-3" }, + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-3/file" }, + { 0100644, CONFLICTING_OURS_OID, 2, "df-3/file" }, + + { 0100644, CONFLICTING_OURS_OID, 2, "df-4" }, + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "df-4/file" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "df-4/file" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + opts.our_label = "HEAD"; + opts.their_label = "branch"; + + create_index(checkout_index_entries, 12); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_oid("df-1/file", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("df-1~HEAD", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-2/file", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-2~branch", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("df-3/file", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-3~branch", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("df-4~HEAD", CONFLICTING_OURS_OID); + ensure_workdir_oid("df-4/file", CONFLICTING_THEIRS_OID); +} + +void test_checkout_conflict__link_file(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "link-1" }, + { 0100644, CONFLICTING_OURS_OID, 2, "link-1" }, + { 0120000, LINK_THEIRS_OID, 3, "link-1" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "link-2" }, + { 0120000, LINK_OURS_OID, 2, "link-2" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "link-2" }, + + { 0120000, LINK_ANCESTOR_OID, 1, "link-3" }, + { 0100644, CONFLICTING_OURS_OID, 2, "link-3" }, + { 0120000, LINK_THEIRS_OID, 3, "link-3" }, + + { 0120000, LINK_ANCESTOR_OID, 1, "link-4" }, + { 0120000, LINK_OURS_OID, 2, "link-4" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "link-4" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 12); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + /* Typechange conflicts always keep the file in the workdir */ + ensure_workdir_oid("link-1", CONFLICTING_OURS_OID); + ensure_workdir_oid("link-2", CONFLICTING_THEIRS_OID); + ensure_workdir_oid("link-3", CONFLICTING_OURS_OID); + ensure_workdir_oid("link-4", CONFLICTING_THEIRS_OID); +} + +void test_checkout_conflict__links(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0120000, LINK_ANCESTOR_OID, 1, "link-1" }, + { 0120000, LINK_OURS_OID, 2, "link-1" }, + { 0120000, LINK_THEIRS_OID, 3, "link-1" }, + + { 0120000, LINK_OURS_OID, 2, "link-2" }, + { 0120000, LINK_THEIRS_OID, 3, "link-2" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 5); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + /* Conflicts with links always keep the ours side (even with -Xtheirs) */ + ensure_workdir_link("link-1", LINK_OURS_TARGET); + ensure_workdir_link("link-2", LINK_OURS_TARGET); +} + +void test_checkout_conflict__add_add(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_OURS_OID, 2, "conflicting.txt" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting.txt" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 2); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + /* Add/add writes diff3 files */ + ensure_workdir_contents("conflicting.txt", CONFLICTING_DIFF3_FILE); +} + +void test_checkout_conflict__mode_change(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "executable-1" }, + { 0100755, CONFLICTING_ANCESTOR_OID, 2, "executable-1" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "executable-1" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "executable-2" }, + { 0100644, CONFLICTING_OURS_OID, 2, "executable-2" }, + { 0100755, CONFLICTING_ANCESTOR_OID, 3, "executable-2" }, + + { 0100755, CONFLICTING_ANCESTOR_OID, 1, "executable-3" }, + { 0100644, CONFLICTING_ANCESTOR_OID, 2, "executable-3" }, + { 0100755, CONFLICTING_THEIRS_OID, 3, "executable-3" }, + + { 0100755, CONFLICTING_ANCESTOR_OID, 1, "executable-4" }, + { 0100755, CONFLICTING_OURS_OID, 2, "executable-4" }, + { 0100644, CONFLICTING_ANCESTOR_OID, 3, "executable-4" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "executable-5" }, + { 0100755, CONFLICTING_OURS_OID, 2, "executable-5" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "executable-5" }, + + { 0100755, CONFLICTING_ANCESTOR_OID, 1, "executable-6" }, + { 0100644, CONFLICTING_OURS_OID, 2, "executable-6" }, + { 0100755, CONFLICTING_THEIRS_OID, 3, "executable-6" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 18); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + /* Keep the modified mode */ + ensure_workdir_oid("executable-1", CONFLICTING_THEIRS_OID); + ensure_workdir_mode("executable-1", 0100755); + + ensure_workdir_oid("executable-2", CONFLICTING_OURS_OID); + ensure_workdir_mode("executable-2", 0100755); + + ensure_workdir_oid("executable-3", CONFLICTING_THEIRS_OID); + ensure_workdir_mode("executable-3", 0100644); + + ensure_workdir_oid("executable-4", CONFLICTING_OURS_OID); + ensure_workdir_mode("executable-4", 0100644); + + ensure_workdir_contents("executable-5", CONFLICTING_DIFF3_FILE); + ensure_workdir_mode("executable-5", 0100755); + + ensure_workdir_contents("executable-6", CONFLICTING_DIFF3_FILE); + ensure_workdir_mode("executable-6", 0100644); +} + +void test_checkout_conflict__renames(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 1, "0b-rewritten-in-ours.txt" }, + { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 2, "0b-rewritten-in-ours.txt" }, + { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 3, "0b-rewritten-in-ours.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 1, "0c-rewritten-in-theirs.txt" }, + { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 2, "0c-rewritten-in-theirs.txt" }, + { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 3, "0c-rewritten-in-theirs.txt" }, + { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, + { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, + { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, + { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, + { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 2, "3a-newname-in-ours-deleted-in-theirs.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 1, "3a-renamed-in-ours-deleted-in-theirs.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 3, "3b-newname-in-theirs-deleted-in-ours.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 1, "3b-renamed-in-theirs-deleted-in-ours.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 2, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 3, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 1, "4a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 2, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 3, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 1, "4b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 2, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 3, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 1, "5a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 3, "5a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 2, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 3, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 1, "5b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 2, "5b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 2, "6-both-renamed-1-to-2-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 3, "6-both-renamed-1-to-2-theirs.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 1, "6-both-renamed-1-to-2.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "7-both-renamed-side-1.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "7-both-renamed-side-1.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "7-both-renamed-side-2.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "7-both-renamed-side-2.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" } + }; + + struct checkout_name_entry checkout_name_entries[] = { + { + "3a-renamed-in-ours-deleted-in-theirs.txt", + "3a-newname-in-ours-deleted-in-theirs.txt", + "" + }, + + { + "3b-renamed-in-theirs-deleted-in-ours.txt", + "", + "3b-newname-in-theirs-deleted-in-ours.txt" + }, + + { + "4a-renamed-in-ours-added-in-theirs.txt", + "4a-newname-in-ours-added-in-theirs.txt", + "" + }, + + { + "4b-renamed-in-theirs-added-in-ours.txt", + "", + "4b-newname-in-theirs-added-in-ours.txt" + }, + + { + "5a-renamed-in-ours-added-in-theirs.txt", + "5a-newname-in-ours-added-in-theirs.txt", + "5a-renamed-in-ours-added-in-theirs.txt" + }, + + { + "5b-renamed-in-theirs-added-in-ours.txt", + "5b-renamed-in-theirs-added-in-ours.txt", + "5b-newname-in-theirs-added-in-ours.txt" + }, + + { + "6-both-renamed-1-to-2.txt", + "6-both-renamed-1-to-2-ours.txt", + "6-both-renamed-1-to-2-theirs.txt" + }, + + { + "7-both-renamed-side-1.txt", + "7-both-renamed.txt", + "7-both-renamed-side-1.txt" + }, + + { + "7-both-renamed-side-2.txt", + "7-both-renamed-side-2.txt", + "7-both-renamed.txt" + } + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 41); + create_index_names(checkout_name_entries, 9); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir("0a-no-change.txt", + 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"); + + ensure_workdir("0b-duplicated-in-ours.txt", + 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6"); + + ensure_workdir("0b-rewritten-in-ours.txt", + 0100644, "4c7e515d6d52d820496858f2f059ece69e99e2e3"); + + ensure_workdir("0c-duplicated-in-theirs.txt", + 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31"); + + ensure_workdir("0c-rewritten-in-theirs.txt", + 0100644, "4648d658682d1155c2a3db5b0c53305e26884ea5"); + + ensure_workdir("1a-newname-in-ours-edited-in-theirs.txt", + 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638"); + + ensure_workdir("1a-newname-in-ours.txt", + 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"); + + ensure_workdir("1b-newname-in-theirs-edited-in-ours.txt", + 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a"); + + ensure_workdir("1b-newname-in-theirs.txt", + 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"); + + ensure_workdir("2-newname-in-both.txt", + 0100644, "178940b450f238a56c0d75b7955cb57b38191982"); + + ensure_workdir("3a-newname-in-ours-deleted-in-theirs.txt", + 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"); + + ensure_workdir("3b-newname-in-theirs-deleted-in-ours.txt", + 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495"); + + ensure_workdir("4a-newname-in-ours-added-in-theirs.txt~ours", + 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c"); + + ensure_workdir("4a-newname-in-ours-added-in-theirs.txt~theirs", + 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a"); + + ensure_workdir("4b-newname-in-theirs-added-in-ours.txt~ours", + 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9"); + + ensure_workdir("4b-newname-in-theirs-added-in-ours.txt~theirs", + 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db"); + + ensure_workdir("5a-newname-in-ours-added-in-theirs.txt~ours", + 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436"); + + ensure_workdir("5a-newname-in-ours-added-in-theirs.txt~theirs", + 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714"); + + ensure_workdir("5b-newname-in-theirs-added-in-ours.txt~ours", + 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced"); + + ensure_workdir("5b-newname-in-theirs-added-in-ours.txt~theirs", + 0100644, "63247125386de9ec90a27ad36169307bf8a11a38"); + + ensure_workdir("6-both-renamed-1-to-2-ours.txt", + 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450"); + + ensure_workdir("6-both-renamed-1-to-2-theirs.txt", + 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450"); + + ensure_workdir("7-both-renamed.txt~ours", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); + + ensure_workdir("7-both-renamed.txt~theirs", + 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); +} + +void test_checkout_conflict__rename_keep_ours(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 1, "0b-rewritten-in-ours.txt" }, + { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 2, "0b-rewritten-in-ours.txt" }, + { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 3, "0b-rewritten-in-ours.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 1, "0c-rewritten-in-theirs.txt" }, + { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 2, "0c-rewritten-in-theirs.txt" }, + { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 3, "0c-rewritten-in-theirs.txt" }, + { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, + { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, + { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, + { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, + { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 2, "3a-newname-in-ours-deleted-in-theirs.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 1, "3a-renamed-in-ours-deleted-in-theirs.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 3, "3b-newname-in-theirs-deleted-in-ours.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 1, "3b-renamed-in-theirs-deleted-in-ours.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 2, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 3, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 1, "4a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 2, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 3, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 1, "4b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 2, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 3, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 1, "5a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 3, "5a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 2, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 3, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 1, "5b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 2, "5b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 2, "6-both-renamed-1-to-2-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 3, "6-both-renamed-1-to-2-theirs.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 1, "6-both-renamed-1-to-2.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "7-both-renamed-side-1.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "7-both-renamed-side-1.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "7-both-renamed-side-2.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "7-both-renamed-side-2.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" } + }; + + struct checkout_name_entry checkout_name_entries[] = { + { + "3a-renamed-in-ours-deleted-in-theirs.txt", + "3a-newname-in-ours-deleted-in-theirs.txt", + "" + }, + + { + "3b-renamed-in-theirs-deleted-in-ours.txt", + "", + "3b-newname-in-theirs-deleted-in-ours.txt" + }, + + { + "4a-renamed-in-ours-added-in-theirs.txt", + "4a-newname-in-ours-added-in-theirs.txt", + "" + }, + + { + "4b-renamed-in-theirs-added-in-ours.txt", + "", + "4b-newname-in-theirs-added-in-ours.txt" + }, + + { + "5a-renamed-in-ours-added-in-theirs.txt", + "5a-newname-in-ours-added-in-theirs.txt", + "5a-renamed-in-ours-added-in-theirs.txt" + }, + + { + "5b-renamed-in-theirs-added-in-ours.txt", + "5b-renamed-in-theirs-added-in-ours.txt", + "5b-newname-in-theirs-added-in-ours.txt" + }, + + { + "6-both-renamed-1-to-2.txt", + "6-both-renamed-1-to-2-ours.txt", + "6-both-renamed-1-to-2-theirs.txt" + }, + + { + "7-both-renamed-side-1.txt", + "7-both-renamed.txt", + "7-both-renamed-side-1.txt" + }, + + { + "7-both-renamed-side-2.txt", + "7-both-renamed-side-2.txt", + "7-both-renamed.txt" + } + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS; + + create_index(checkout_index_entries, 41); + create_index_names(checkout_name_entries, 9); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir("0a-no-change.txt", + 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"); + + ensure_workdir("0b-duplicated-in-ours.txt", + 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6"); + + ensure_workdir("0b-rewritten-in-ours.txt", + 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e"); + + ensure_workdir("0c-duplicated-in-theirs.txt", + 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31"); + + ensure_workdir("0c-rewritten-in-theirs.txt", + 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09"); + + ensure_workdir("1a-newname-in-ours-edited-in-theirs.txt", + 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638"); + + ensure_workdir("1a-newname-in-ours.txt", + 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"); + + ensure_workdir("1b-newname-in-theirs-edited-in-ours.txt", + 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a"); + + ensure_workdir("1b-newname-in-theirs.txt", + 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"); + + ensure_workdir("2-newname-in-both.txt", + 0100644, "178940b450f238a56c0d75b7955cb57b38191982"); + + ensure_workdir("3a-newname-in-ours-deleted-in-theirs.txt", + 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"); + + ensure_workdir("3b-newname-in-theirs-deleted-in-ours.txt", + 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495"); + + ensure_workdir("4a-newname-in-ours-added-in-theirs.txt", + 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c"); + + ensure_workdir("4b-newname-in-theirs-added-in-ours.txt", + 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9"); + + ensure_workdir("5a-newname-in-ours-added-in-theirs.txt", + 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436"); + + ensure_workdir("5b-newname-in-theirs-added-in-ours.txt", + 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced"); + + ensure_workdir("6-both-renamed-1-to-2-ours.txt", + 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450"); + + ensure_workdir("7-both-renamed.txt", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); +} + +void test_checkout_conflict__name_mangled_file_exists_in_workdir(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "test-one-side-one.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "test-one-side-one.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "test-one-side-two.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "test-one-side-two.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "test-one.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "test-one.txt" }, + + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "test-two-side-one.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "test-two-side-one.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "test-two-side-two.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "test-two-side-two.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "test-two.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "test-two.txt" }, + + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "test-three-side-one.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "test-three-side-one.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "test-three-side-two.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "test-three-side-two.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "test-three.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "test-three.txt" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-one" }, + { 0100644, CONFLICTING_OURS_OID, 2, "directory_file-one" }, + { 0100644, CONFLICTING_THEIRS_OID, 0, "directory_file-one/file" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-two" }, + { 0100644, CONFLICTING_OURS_OID, 0, "directory_file-two/file" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "directory_file-two" }, + }; + + struct checkout_name_entry checkout_name_entries[] = { + { + "test-one-side-one.txt", + "test-one.txt", + "test-one-side-one.txt" + }, + { + "test-one-side-two.txt", + "test-one-side-two.txt", + "test-one.txt" + }, + + { + "test-two-side-one.txt", + "test-two.txt", + "test-two-side-one.txt" + }, + { + "test-two-side-two.txt", + "test-two-side-two.txt", + "test-two.txt" + }, + + { + "test-three-side-one.txt", + "test-three.txt", + "test-three-side-one.txt" + }, + { + "test-three-side-two.txt", + "test-three-side-two.txt", + "test-three.txt" + } + }; + + opts.checkout_strategy |= GIT_CHECKOUT_SAFE; + + create_index(checkout_index_entries, 24); + create_index_names(checkout_name_entries, 6); + git_index_write(g_index); + + /* Add some files on disk that conflict with the names that would be chosen + * for the files written for each side. */ + + cl_git_rewritefile("merge-resolve/test-one.txt~ours", + "Expect index contents to be written to ~ours_0"); + cl_git_rewritefile("merge-resolve/test-one.txt~theirs", + "Expect index contents to be written to ~theirs_0"); + + cl_git_rewritefile("merge-resolve/test-two.txt~ours", + "Expect index contents to be written to ~ours_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~theirs", + "Expect index contents to be written to ~theirs_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~ours_0", + "Expect index contents to be written to ~ours_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~theirs_0", + "Expect index contents to be written to ~theirs_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~ours_1", + "Expect index contents to be written to ~ours_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~theirs_1", + "Expect index contents to be written to ~theirs_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~ours_2", + "Expect index contents to be written to ~ours_3"); + cl_git_rewritefile("merge-resolve/test-two.txt~theirs_2", + "Expect index contents to be written to ~theirs_3"); + + cl_git_rewritefile("merge-resolve/test-three.txt~Ours", + "Expect case insensitive filesystems to create ~ours_0"); + cl_git_rewritefile("merge-resolve/test-three.txt~THEIRS", + "Expect case insensitive filesystems to create ~theirs_0"); + + cl_git_rewritefile("merge-resolve/directory_file-one~ours", + "Index contents written to ~ours_0 in this D/F conflict"); + cl_git_rewritefile("merge-resolve/directory_file-two~theirs", + "Index contents written to ~theirs_0 in this D/F conflict"); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir("test-one.txt~ours_0", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); + ensure_workdir("test-one.txt~theirs_0", + 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); + + ensure_workdir("test-two.txt~ours_3", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); + ensure_workdir("test-two.txt~theirs_3", + 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); + + /* Name is mangled on case insensitive only */ +#if defined(GIT_WIN32) || defined(__APPLE__) + ensure_workdir("test-three.txt~ours_0", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); + ensure_workdir("test-three.txt~theirs_0", + 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); +#else + ensure_workdir("test-three.txt~ours", + 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); + ensure_workdir("test-three.txt~theirs", + 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07"); +#endif + + ensure_workdir("directory_file-one~ours_0", 0100644, CONFLICTING_OURS_OID); + ensure_workdir("directory_file-two~theirs_0", 0100644, CONFLICTING_THEIRS_OID); +} + +void test_checkout_conflict__update_only(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "automergeable.txt" }, + { 0100644, AUTOMERGEABLE_OURS_OID, 2, "automergeable.txt" }, + { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "automergeable.txt" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "modify-delete" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "modify-delete" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-one" }, + { 0100644, CONFLICTING_OURS_OID, 2, "directory_file-one" }, + { 0100644, CONFLICTING_THEIRS_OID, 0, "directory_file-one/file" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "directory_file-two" }, + { 0100644, CONFLICTING_OURS_OID, 0, "directory_file-two/file" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "directory_file-two" }, + }; + + opts.checkout_strategy |= GIT_CHECKOUT_UPDATE_ONLY; + + create_index(checkout_index_entries, 3); + git_index_write(g_index); + + cl_git_pass(p_mkdir("merge-resolve/directory_file-two", 0777)); + cl_git_rewritefile("merge-resolve/directory_file-two/file", CONFLICTING_OURS_FILE); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_contents("automergeable.txt", AUTOMERGEABLE_MERGED_FILE); + ensure_workdir("directory_file-two/file", 0100644, CONFLICTING_OURS_OID); + + cl_assert(!git_path_exists("merge-resolve/modify-delete")); + cl_assert(!git_path_exists("merge-resolve/test-one.txt")); + cl_assert(!git_path_exists("merge-resolve/test-one-side-one.txt")); + cl_assert(!git_path_exists("merge-resolve/test-one-side-two.txt")); + cl_assert(!git_path_exists("merge-resolve/test-one.txt~ours")); + cl_assert(!git_path_exists("merge-resolve/test-one.txt~theirs")); + cl_assert(!git_path_exists("merge-resolve/directory_file-one/file")); + cl_assert(!git_path_exists("merge-resolve/directory_file-one~ours")); + cl_assert(!git_path_exists("merge-resolve/directory_file-two~theirs")); +} + +void test_checkout_conflict__path_filters(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + char *paths[] = { "conflicting-1.txt", "conflicting-3.txt" }; + git_strarray patharray = {0}; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-1.txt" }, + { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-1.txt" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-1.txt" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-2.txt" }, + { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-2.txt" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-2.txt" }, + + { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-3.txt" }, + { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-3.txt" }, + { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-3.txt" }, + + { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-4.txt" }, + { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-4.txt" }, + { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-4.txt" }, + }; + + patharray.count = 2; + patharray.strings = paths; + + opts.paths = patharray; + + create_index(checkout_index_entries, 12); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + ensure_workdir_contents("conflicting-1.txt", CONFLICTING_DIFF3_FILE); + cl_assert(!git_path_exists("merge-resolve/conflicting-2.txt")); + ensure_workdir_contents("conflicting-3.txt", AUTOMERGEABLE_MERGED_FILE); + cl_assert(!git_path_exists("merge-resolve/conflicting-4.txt")); +} + +static void collect_progress( + const char *path, + size_t completed_steps, + size_t total_steps, + void *payload) +{ + git_vector *paths = payload; + + (void)completed_steps; + (void)total_steps; + + if (path == NULL) + return; + + git_vector_insert(paths, strdup(path)); +} + +void test_checkout_conflict__report_progress(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_vector paths = GIT_VECTOR_INIT; + char *path; + size_t i; + + struct checkout_index_entry checkout_index_entries[] = { + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-1.txt" }, + { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-1.txt" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-1.txt" }, + + { 0100644, CONFLICTING_ANCESTOR_OID, 1, "conflicting-2.txt" }, + { 0100644, CONFLICTING_OURS_OID, 2, "conflicting-2.txt" }, + { 0100644, CONFLICTING_THEIRS_OID, 3, "conflicting-2.txt" }, + + { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-3.txt" }, + { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-3.txt" }, + { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-3.txt" }, + + { 0100644, AUTOMERGEABLE_ANCESTOR_OID, 1, "conflicting-4.txt" }, + { 0100644, AUTOMERGEABLE_OURS_OID, 2, "conflicting-4.txt" }, + { 0100644, AUTOMERGEABLE_THEIRS_OID, 3, "conflicting-4.txt" }, + }; + + opts.progress_cb = collect_progress; + opts.progress_payload = &paths; + + + create_index(checkout_index_entries, 12); + git_index_write(g_index); + + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); + + cl_assert_equal_i(4, git_vector_length(&paths)); + cl_assert_equal_s("conflicting-1.txt", git_vector_get(&paths, 0)); + cl_assert_equal_s("conflicting-2.txt", git_vector_get(&paths, 1)); + cl_assert_equal_s("conflicting-3.txt", git_vector_get(&paths, 2)); + cl_assert_equal_s("conflicting-4.txt", git_vector_get(&paths, 3)); + + git_vector_foreach(&paths, i, path) + git__free(path); + + git_vector_free(&paths); +} diff --git a/tests/checkout/crlf.c b/tests/checkout/crlf.c new file mode 100644 index 000000000..9a4cbd313 --- /dev/null +++ b/tests/checkout/crlf.c @@ -0,0 +1,231 @@ +#include "clar_libgit2.h" +#include "checkout_helpers.h" +#include "../filter/crlf.h" + +#include "git2/checkout.h" +#include "repository.h" +#include "posix.h" + +static git_repository *g_repo; + +void test_checkout_crlf__initialize(void) +{ + g_repo = cl_git_sandbox_init("crlf"); +} + +void test_checkout_crlf__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_checkout_crlf__detect_crlf_autocrlf_false(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_repo_set_bool(g_repo, "core.autocrlf", false); + + git_checkout_head(g_repo, &opts); + + check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW); + check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW); +} + +void test_checkout_crlf__autocrlf_false_index_size_is_unfiltered_size(void) +{ + git_index *index; + const git_index_entry *entry; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_repo_set_bool(g_repo, "core.autocrlf", false); + + git_checkout_head(g_repo, &opts); + + git_repository_index(&index, g_repo); + + cl_assert((entry = git_index_get_bypath(index, "all-lf", 0)) != NULL); + cl_assert(entry->file_size == strlen(ALL_LF_TEXT_RAW)); + + cl_assert((entry = git_index_get_bypath(index, "all-crlf", 0)) != NULL); + cl_assert(entry->file_size == strlen(ALL_CRLF_TEXT_RAW)); + + git_index_free(index); +} + +void test_checkout_crlf__detect_crlf_autocrlf_true(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + git_checkout_head(g_repo, &opts); + + if (GIT_EOL_NATIVE == GIT_EOL_LF) + check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW); + else + check_file_contents("./crlf/all-lf", ALL_LF_TEXT_AS_CRLF); + + check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW); +} + +void test_checkout_crlf__more_lf_autocrlf_true(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + git_checkout_head(g_repo, &opts); + + if (GIT_EOL_NATIVE == GIT_EOL_LF) + check_file_contents("./crlf/more-lf", MORE_LF_TEXT_RAW); + else + check_file_contents("./crlf/more-lf", MORE_LF_TEXT_AS_CRLF); +} + +void test_checkout_crlf__more_crlf_autocrlf_true(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + git_checkout_head(g_repo, &opts); + + if (GIT_EOL_NATIVE == GIT_EOL_LF) + check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_RAW); + else + check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_AS_CRLF); +} + +void test_checkout_crlf__all_crlf_autocrlf_true(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + git_checkout_head(g_repo, &opts); + + check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW); +} + +void test_checkout_crlf__autocrlf_true_index_size_is_filtered_size(void) +{ + git_index *index; + const git_index_entry *entry; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + git_checkout_head(g_repo, &opts); + + git_repository_index(&index, g_repo); + + cl_assert((entry = git_index_get_bypath(index, "all-lf", 0)) != NULL); + + if (GIT_EOL_NATIVE == GIT_EOL_LF) + cl_assert_equal_sz(strlen(ALL_LF_TEXT_RAW), entry->file_size); + else + cl_assert_equal_sz(strlen(ALL_LF_TEXT_AS_CRLF), entry->file_size); + + cl_assert((entry = git_index_get_bypath(index, "all-crlf", 0)) != NULL); + cl_assert_equal_sz(strlen(ALL_CRLF_TEXT_RAW), entry->file_size); + + git_index_free(index); +} + +void test_checkout_crlf__with_ident(void) +{ + git_index *index; + git_blob *blob; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_git_mkfile("crlf/.gitattributes", + "*.txt text\n*.bin binary\n" + "*.crlf text eol=crlf\n" + "*.lf text eol=lf\n" + "*.ident text ident\n" + "*.identcrlf ident text eol=crlf\n" + "*.identlf ident text eol=lf\n"); + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + /* add files with $Id$ */ + + cl_git_mkfile("crlf/lf.ident", ALL_LF_TEXT_RAW "\n$Id: initial content$\n"); + cl_git_mkfile("crlf/crlf.ident", ALL_CRLF_TEXT_RAW "\r\n$Id$\r\n\r\n"); + cl_git_mkfile("crlf/more1.identlf", "$Id$\n" MORE_LF_TEXT_RAW); + cl_git_mkfile("crlf/more2.identcrlf", "\r\n$Id: $\r\n" MORE_CRLF_TEXT_RAW); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_add_bypath(index, "lf.ident")); + cl_git_pass(git_index_add_bypath(index, "crlf.ident")); + cl_git_pass(git_index_add_bypath(index, "more1.identlf")); + cl_git_pass(git_index_add_bypath(index, "more2.identcrlf")); + cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "Some ident files\n"); + + git_checkout_head(g_repo, &opts); + + /* check that blobs have $Id$ */ + + cl_git_pass(git_blob_lookup(&blob, g_repo, + & git_index_get_bypath(index, "lf.ident", 0)->oid)); + cl_assert_equal_s( + ALL_LF_TEXT_RAW "\n$Id$\n", git_blob_rawcontent(blob)); + git_blob_free(blob); + + cl_git_pass(git_blob_lookup(&blob, g_repo, + & git_index_get_bypath(index, "more2.identcrlf", 0)->oid)); + cl_assert_equal_s( + "\n$Id$\n" MORE_CRLF_TEXT_AS_LF, git_blob_rawcontent(blob)); + git_blob_free(blob); + + /* check that filesystem is initially untouched - matching core Git */ + + cl_assert_equal_file( + ALL_LF_TEXT_RAW "\n$Id: initial content$\n", 0, "crlf/lf.ident"); + + /* check that forced checkout rewrites correctly */ + + p_unlink("crlf/lf.ident"); + p_unlink("crlf/crlf.ident"); + p_unlink("crlf/more1.identlf"); + p_unlink("crlf/more2.identcrlf"); + + git_checkout_head(g_repo, &opts); + + if (GIT_EOL_NATIVE == GIT_EOL_LF) { + cl_assert_equal_file( + ALL_LF_TEXT_RAW + "\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467$\n", + 0, "crlf/lf.ident"); + cl_assert_equal_file( + ALL_CRLF_TEXT_AS_LF + "\n$Id: f2c66ad9b2b5a734d9bf00d5000cc10a62b8a857$\n\n", + 0, "crlf/crlf.ident"); + } else { + cl_assert_equal_file( + ALL_LF_TEXT_AS_CRLF + "\r\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467$\r\n", + 0, "crlf/lf.ident"); + cl_assert_equal_file( + ALL_CRLF_TEXT_RAW + "\r\n$Id: f2c66ad9b2b5a734d9bf00d5000cc10a62b8a857$\r\n\r\n", + 0, "crlf/crlf.ident"); + } + + cl_assert_equal_file( + "$Id: f7830382dac1f1583422be5530fdfbd26289431b$\n" + MORE_LF_TEXT_AS_LF, 0, "crlf/more1.identlf"); + + cl_assert_equal_file( + "\r\n$Id: 74677a68413012ce8d7e7cfc3f12603df3a3eac4$\r\n" + MORE_CRLF_TEXT_AS_CRLF, 0, "crlf/more2.identcrlf"); + + git_index_free(index); +} diff --git a/tests/checkout/head.c b/tests/checkout/head.c new file mode 100644 index 000000000..a7a7e9071 --- /dev/null +++ b/tests/checkout/head.c @@ -0,0 +1,62 @@ +#include "clar_libgit2.h" +#include "refs.h" +#include "repo/repo_helpers.h" +#include "path.h" +#include "fileops.h" + +static git_repository *g_repo; + +void test_checkout_head__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_checkout_head__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_checkout_head__unborn_head_returns_GIT_EUNBORNBRANCH(void) +{ + make_head_unborn(g_repo, NON_EXISTING_HEAD); + + cl_assert_equal_i(GIT_EUNBORNBRANCH, git_checkout_head(g_repo, NULL)); +} + +void test_checkout_head__with_index_only_tree(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_index *index; + + /* let's start by getting things into a known state */ + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + cl_git_pass(git_checkout_head(g_repo, &opts)); + + /* now let's stage some new stuff including a new directory */ + + cl_git_pass(git_repository_index(&index, g_repo)); + + p_mkdir("testrepo/newdir", 0777); + cl_git_mkfile("testrepo/newdir/newfile.txt", "new file\n"); + + cl_git_pass(git_index_add_bypath(index, "newdir/newfile.txt")); + cl_git_pass(git_index_write(index)); + + cl_assert(git_path_isfile("testrepo/newdir/newfile.txt")); + cl_assert(git_index_get_bypath(index, "newdir/newfile.txt", 0) != NULL); + + git_index_free(index); + + /* okay, so now we have staged this new file; let's see if we can remove */ + + opts.checkout_strategy = GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED; + cl_git_pass(git_checkout_head(g_repo, &opts)); + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_assert(!git_path_isfile("testrepo/newdir/newfile.txt")); + cl_assert(git_index_get_bypath(index, "newdir/newfile.txt", 0) == NULL); + + git_index_free(index); +} diff --git a/tests/checkout/index.c b/tests/checkout/index.c new file mode 100644 index 000000000..48d6d79f9 --- /dev/null +++ b/tests/checkout/index.c @@ -0,0 +1,620 @@ +#include "clar_libgit2.h" +#include "checkout_helpers.h" + +#include "git2/checkout.h" +#include "fileops.h" +#include "repository.h" + +static git_repository *g_repo; + +void test_checkout_index__initialize(void) +{ + git_tree *tree; + + g_repo = cl_git_sandbox_init("testrepo"); + + cl_git_pass(git_repository_head_tree(&tree, g_repo)); + + reset_index_to_treeish((git_object *)tree); + git_tree_free(tree); + + cl_git_rewritefile( + "./testrepo/.gitattributes", + "* text eol=lf\n"); +} + +void test_checkout_index__cleanup(void) +{ + cl_git_sandbox_cleanup(); + + /* try to remove alternative dir */ + if (git_path_isdir("alternative")) + git_futils_rmdir_r("alternative", NULL, GIT_RMDIR_REMOVE_FILES); +} + +void test_checkout_index__cannot_checkout_a_bare_repository(void) +{ + test_checkout_index__cleanup(); + + g_repo = cl_git_sandbox_init("testrepo.git"); + + cl_git_fail(git_checkout_index(g_repo, NULL, NULL)); +} + +void test_checkout_index__can_create_missing_files(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + cl_assert_equal_i(false, git_path_isfile("./testrepo/README")); + cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt")); + cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt")); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + check_file_contents("./testrepo/README", "hey there\n"); + check_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n"); + check_file_contents("./testrepo/new.txt", "my new file\n"); +} + +void test_checkout_index__can_remove_untracked_files(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + git_futils_mkdir("./testrepo/dir/subdir/subsubdir", NULL, 0755, GIT_MKDIR_PATH); + cl_git_mkfile("./testrepo/dir/one", "one\n"); + cl_git_mkfile("./testrepo/dir/subdir/two", "two\n"); + + cl_assert_equal_i(true, git_path_isdir("./testrepo/dir/subdir/subsubdir")); + + opts.checkout_strategy = + GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_REMOVE_UNTRACKED; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + cl_assert_equal_i(false, git_path_isdir("./testrepo/dir")); +} + +void test_checkout_index__honor_the_specified_pathspecs(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + char *entries[] = { "*.txt" }; + + opts.paths.strings = entries; + opts.paths.count = 1; + + cl_assert_equal_i(false, git_path_isfile("./testrepo/README")); + cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt")); + cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt")); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + cl_assert_equal_i(false, git_path_isfile("./testrepo/README")); + check_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n"); + check_file_contents("./testrepo/new.txt", "my new file\n"); +} + +void test_checkout_index__honor_the_gitattributes_directives(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + const char *attributes = + "branch_file.txt text eol=crlf\n" + "new.txt text eol=lf\n"; + + cl_git_mkfile("./testrepo/.gitattributes", attributes); + cl_repo_set_bool(g_repo, "core.autocrlf", false); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + check_file_contents("./testrepo/README", "hey there\n"); + check_file_contents("./testrepo/new.txt", "my new file\n"); + check_file_contents("./testrepo/branch_file.txt", "hi\r\nbye!\r\n"); +} + +void test_checkout_index__honor_coreautocrlf_setting_set_to_true(void) +{ +#ifdef GIT_WIN32 + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + const char *expected_readme_text = "hey there\r\n"; + + cl_git_pass(p_unlink("./testrepo/.gitattributes")); + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + check_file_contents("./testrepo/README", expected_readme_text); +#endif +} + +void test_checkout_index__honor_coresymlinks_setting_set_to_true(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + cl_repo_set_bool(g_repo, "core.symlinks", true); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + +#ifdef GIT_WIN32 + check_file_contents("./testrepo/link_to_new.txt", "new.txt"); +#else + { + char link_data[1024]; + size_t link_size = 1024; + + link_size = p_readlink("./testrepo/link_to_new.txt", link_data, link_size); + link_data[link_size] = '\0'; + cl_assert_equal_i(link_size, strlen("new.txt")); + cl_assert_equal_s(link_data, "new.txt"); + check_file_contents("./testrepo/link_to_new.txt", "my new file\n"); + } +#endif +} + +void test_checkout_index__honor_coresymlinks_setting_set_to_false(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + cl_repo_set_bool(g_repo, "core.symlinks", false); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + check_file_contents("./testrepo/link_to_new.txt", "new.txt"); +} + +void test_checkout_index__donot_overwrite_modified_file_by_default(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!"); + + /* set this up to not return an error code on conflicts, but it + * still will not have permission to overwrite anything... + */ + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + check_file_contents("./testrepo/new.txt", "This isn't what's stored!"); +} + +void test_checkout_index__can_overwrite_modified_file(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!"); + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + check_file_contents("./testrepo/new.txt", "my new file\n"); +} + +void test_checkout_index__options_disable_filters(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + cl_git_mkfile("./testrepo/.gitattributes", "*.txt text eol=crlf\n"); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + opts.disable_filters = false; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + check_file_contents("./testrepo/new.txt", "my new file\r\n"); + + p_unlink("./testrepo/new.txt"); + + opts.disable_filters = true; + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + check_file_contents("./testrepo/new.txt", "my new file\n"); +} + +void test_checkout_index__options_dir_modes(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + struct stat st; + git_oid oid; + git_commit *commit; + mode_t um; + + if (!cl_is_chmod_supported()) + return; + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); + cl_git_pass(git_commit_lookup(&commit, g_repo, &oid)); + + reset_index_to_treeish((git_object *)commit); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + opts.dir_mode = 0701; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + /* umask will influence actual directory creation mode */ + (void)p_umask(um = p_umask(022)); + + cl_git_pass(p_stat("./testrepo/a", &st)); + cl_assert_equal_i_fmt(st.st_mode, (GIT_FILEMODE_TREE | 0701) & ~um, "%07o"); + + /* File-mode test, since we're on the 'dir' branch */ + cl_git_pass(p_stat("./testrepo/a/b.txt", &st)); + cl_assert_equal_i_fmt(st.st_mode, GIT_FILEMODE_BLOB_EXECUTABLE, "%07o"); + + git_commit_free(commit); +} + +void test_checkout_index__options_override_file_modes(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + struct stat st; + + if (!cl_is_chmod_supported()) + return; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + opts.file_mode = 0700; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + cl_git_pass(p_stat("./testrepo/new.txt", &st)); + cl_assert_equal_i_fmt(st.st_mode & GIT_MODE_PERMS_MASK, 0700, "%07o"); +} + +void test_checkout_index__options_open_flags(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + cl_git_mkfile("./testrepo/new.txt", "hi\n"); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + opts.file_open_flags = O_CREAT | O_RDWR | O_APPEND; + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + check_file_contents("./testrepo/new.txt", "hi\nmy new file\n"); +} + +struct notify_data { + const char *file; + const char *sha; +}; + +static int test_checkout_notify_cb( + git_checkout_notify_t why, + const char *path, + const git_diff_file *baseline, + const git_diff_file *target, + const git_diff_file *workdir, + void *payload) +{ + struct notify_data *expectations = (struct notify_data *)payload; + + GIT_UNUSED(workdir); + + cl_assert_equal_i(GIT_CHECKOUT_NOTIFY_CONFLICT, why); + cl_assert_equal_s(expectations->file, path); + cl_assert_equal_i(0, git_oid_streq(&baseline->oid, expectations->sha)); + cl_assert_equal_i(0, git_oid_streq(&target->oid, expectations->sha)); + + return 0; +} + +void test_checkout_index__can_notify_of_skipped_files(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + struct notify_data data; + + cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!"); + + /* + * $ git ls-tree HEAD + * 100644 blob a8233120f6ad708f843d861ce2b7228ec4e3dec6 README + * 100644 blob 3697d64be941a53d4ae8f6a271e4e3fa56b022cc branch_file.txt + * 100644 blob a71586c1dfe8a71c6cbf6c129f404c5642ff31bd new.txt + */ + data.file = "new.txt"; + data.sha = "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd"; + + opts.checkout_strategy = + GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS; + opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT; + opts.notify_cb = test_checkout_notify_cb; + opts.notify_payload = &data; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); +} + +static int dont_notify_cb( + git_checkout_notify_t why, + const char *path, + const git_diff_file *baseline, + const git_diff_file *target, + const git_diff_file *workdir, + void *payload) +{ + GIT_UNUSED(why); + GIT_UNUSED(path); + GIT_UNUSED(baseline); + GIT_UNUSED(target); + GIT_UNUSED(workdir); + GIT_UNUSED(payload); + + cl_assert(false); + + return 0; +} + +void test_checkout_index__wont_notify_of_expected_line_ending_changes(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + cl_git_pass(p_unlink("./testrepo/.gitattributes")); + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + cl_git_mkfile("./testrepo/new.txt", "my new file\r\n"); + + opts.checkout_strategy = + GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS; + opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT; + opts.notify_cb = dont_notify_cb; + opts.notify_payload = NULL; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); +} + +static void checkout_progress_counter( + const char *path, size_t cur, size_t tot, void *payload) +{ + GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot); + (*(int *)payload)++; +} + +void test_checkout_index__calls_progress_callback(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + int calls = 0; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + opts.progress_cb = checkout_progress_counter; + opts.progress_payload = &calls; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + cl_assert(calls > 0); +} + +void test_checkout_index__can_overcome_name_clashes(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_index *index; + + cl_git_pass(git_repository_index(&index, g_repo)); + git_index_clear(index); + + cl_git_mkfile("./testrepo/path0", "content\r\n"); + cl_git_pass(p_mkdir("./testrepo/path1", 0777)); + cl_git_mkfile("./testrepo/path1/file1", "content\r\n"); + + cl_git_pass(git_index_add_bypath(index, "path0")); + cl_git_pass(git_index_add_bypath(index, "path1/file1")); + + cl_git_pass(p_unlink("./testrepo/path0")); + cl_git_pass(git_futils_rmdir_r( + "./testrepo/path1", NULL, GIT_RMDIR_REMOVE_FILES)); + + cl_git_mkfile("./testrepo/path1", "content\r\n"); + cl_git_pass(p_mkdir("./testrepo/path0", 0777)); + cl_git_mkfile("./testrepo/path0/file0", "content\r\n"); + + cl_assert(git_path_isfile("./testrepo/path1")); + cl_assert(git_path_isfile("./testrepo/path0/file0")); + + opts.checkout_strategy = + GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS; + cl_git_pass(git_checkout_index(g_repo, index, &opts)); + + cl_assert(git_path_isfile("./testrepo/path1")); + cl_assert(git_path_isfile("./testrepo/path0/file0")); + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + cl_git_pass(git_checkout_index(g_repo, index, &opts)); + + cl_assert(git_path_isfile("./testrepo/path0")); + cl_assert(git_path_isfile("./testrepo/path1/file1")); + + git_index_free(index); +} + +void test_checkout_index__validates_struct_version(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + const git_error *err; + + opts.version = 1024; + cl_git_fail(git_checkout_index(g_repo, NULL, &opts)); + + err = giterr_last(); + cl_assert_equal_i(err->klass, GITERR_INVALID); + + opts.version = 0; + giterr_clear(); + cl_git_fail(git_checkout_index(g_repo, NULL, &opts)); + + err = giterr_last(); + cl_assert_equal_i(err->klass, GITERR_INVALID); +} + +void test_checkout_index__can_update_prefixed_files(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + cl_assert_equal_i(false, git_path_isfile("./testrepo/README")); + cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt")); + cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt")); + + cl_git_mkfile("./testrepo/READ", "content\n"); + cl_git_mkfile("./testrepo/README.after", "content\n"); + cl_git_pass(p_mkdir("./testrepo/branch_file", 0777)); + cl_git_pass(p_mkdir("./testrepo/branch_file/contained_dir", 0777)); + cl_git_mkfile("./testrepo/branch_file/contained_file", "content\n"); + cl_git_pass(p_mkdir("./testrepo/branch_file.txt.after", 0777)); + + opts.checkout_strategy = + GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_REMOVE_UNTRACKED; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + /* remove untracked will remove the .gitattributes file before the blobs + * were created, so they will have had crlf filtering applied on Windows + */ + check_file_contents_nocr("./testrepo/README", "hey there\n"); + check_file_contents_nocr("./testrepo/branch_file.txt", "hi\nbye!\n"); + check_file_contents_nocr("./testrepo/new.txt", "my new file\n"); + + cl_assert(!git_path_exists("testrepo/READ")); + cl_assert(!git_path_exists("testrepo/README.after")); + cl_assert(!git_path_exists("testrepo/branch_file")); + cl_assert(!git_path_exists("testrepo/branch_file.txt.after")); +} + +void test_checkout_index__can_checkout_a_newly_initialized_repository(void) +{ + test_checkout_index__cleanup(); + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_remove_placeholders(git_repository_path(g_repo), "dummy-marker.txt"); + + cl_git_pass(git_checkout_index(g_repo, NULL, NULL)); +} + +void test_checkout_index__issue_1397(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + test_checkout_index__cleanup(); + + g_repo = cl_git_sandbox_init("issue_1397"); + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + check_file_contents("./issue_1397/crlf_file.txt", "first line\r\nsecond line\r\nboth with crlf"); +} + +void test_checkout_index__target_directory(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + checkout_counts cts; + memset(&cts, 0, sizeof(cts)); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + opts.target_directory = "alternative"; + cl_assert(!git_path_isdir("alternative")); + + opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL; + opts.notify_cb = checkout_count_callback; + opts.notify_payload = &cts; + + /* create some files that *would* conflict if we were using the wd */ + cl_git_mkfile("testrepo/README", "I'm in the way!\n"); + cl_git_mkfile("testrepo/new.txt", "my new file\n"); + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + cl_assert_equal_i(0, cts.n_untracked); + cl_assert_equal_i(0, cts.n_ignored); + cl_assert_equal_i(4, cts.n_updates); + + check_file_contents("./alternative/README", "hey there\n"); + check_file_contents("./alternative/branch_file.txt", "hi\nbye!\n"); + check_file_contents("./alternative/new.txt", "my new file\n"); + + cl_git_pass(git_futils_rmdir_r( + "alternative", NULL, GIT_RMDIR_REMOVE_FILES)); +} + +void test_checkout_index__target_directory_from_bare(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_index *index; + git_object *head = NULL; + checkout_counts cts; + memset(&cts, 0, sizeof(cts)); + + test_checkout_index__cleanup(); + + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_assert(git_repository_is_bare(g_repo)); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_revparse_single(&head, g_repo, "HEAD^{tree}")); + cl_git_pass(git_index_read_tree(index, (const git_tree *)head)); + cl_git_pass(git_index_write(index)); + git_index_free(index); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL; + opts.notify_cb = checkout_count_callback; + opts.notify_payload = &cts; + + /* fail to checkout a bare repo */ + cl_git_fail(git_checkout_index(g_repo, NULL, &opts)); + + opts.target_directory = "alternative"; + cl_assert(!git_path_isdir("alternative")); + + cl_git_pass(git_checkout_index(g_repo, NULL, &opts)); + + cl_assert_equal_i(0, cts.n_untracked); + cl_assert_equal_i(0, cts.n_ignored); + cl_assert_equal_i(3, cts.n_updates); + + /* files will have been filtered if needed, so strip CR */ + check_file_contents_nocr("./alternative/README", "hey there\n"); + check_file_contents_nocr("./alternative/branch_file.txt", "hi\nbye!\n"); + check_file_contents_nocr("./alternative/new.txt", "my new file\n"); + + cl_git_pass(git_futils_rmdir_r( + "alternative", NULL, GIT_RMDIR_REMOVE_FILES)); + + git_object_free(head); +} + +void test_checkout_index__can_get_repo_from_index(void) +{ + git_index *index; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + cl_assert_equal_i(false, git_path_isfile("./testrepo/README")); + cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt")); + cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt")); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_pass(git_checkout_index(NULL, index, &opts)); + + check_file_contents("./testrepo/README", "hey there\n"); + check_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n"); + check_file_contents("./testrepo/new.txt", "my new file\n"); + + git_index_free(index); +} diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c new file mode 100644 index 000000000..66b01bc7f --- /dev/null +++ b/tests/checkout/tree.c @@ -0,0 +1,742 @@ +#include "clar_libgit2.h" +#include "checkout_helpers.h" + +#include "git2/checkout.h" +#include "repository.h" +#include "buffer.h" +#include "fileops.h" + +static git_repository *g_repo; +static git_checkout_opts g_opts; +static git_object *g_object; + +void test_checkout_tree__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); + + GIT_INIT_STRUCTURE(&g_opts, GIT_CHECKOUT_OPTS_VERSION); + g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; +} + +void test_checkout_tree__cleanup(void) +{ + git_object_free(g_object); + g_object = NULL; + + cl_git_sandbox_cleanup(); + + if (git_path_isdir("alternative")) + git_futils_rmdir_r("alternative", NULL, GIT_RMDIR_REMOVE_FILES); +} + +void test_checkout_tree__cannot_checkout_a_non_treeish(void) +{ + /* blob */ + cl_git_pass(git_revparse_single(&g_object, g_repo, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd")); + cl_git_fail(git_checkout_tree(g_repo, g_object, NULL)); +} + +void test_checkout_tree__can_checkout_a_subdirectory_from_a_commit(void) +{ + char *entries[] = { "ab/de/" }; + + g_opts.paths.strings = entries; + g_opts.paths.count = 1; + + cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees")); + + cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/")); + + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + + cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/2.txt")); + cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/fgh/1.txt")); +} + +void test_checkout_tree__can_checkout_and_remove_directory(void) +{ + cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/")); + + /* Checkout brach "subtrees" and update HEAD, so that HEAD matches the + * current working tree + */ + cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees")); + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + + cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees")); + + cl_assert_equal_i(true, git_path_isdir("./testrepo/ab/")); + cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/2.txt")); + cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/fgh/1.txt")); + + git_object_free(g_object); + g_object = NULL; + + /* Checkout brach "master" and update HEAD, so that HEAD matches the + * current working tree + */ + cl_git_pass(git_revparse_single(&g_object, g_repo, "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")); + + /* This directory should no longer exist */ + cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/")); +} + +void test_checkout_tree__can_checkout_a_subdirectory_from_a_subtree(void) +{ + char *entries[] = { "de/" }; + + g_opts.paths.strings = entries; + g_opts.paths.count = 1; + + cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees:ab")); + + cl_assert_equal_i(false, git_path_isdir("./testrepo/de/")); + + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + + cl_assert_equal_i(true, git_path_isfile("./testrepo/de/2.txt")); + cl_assert_equal_i(true, git_path_isfile("./testrepo/de/fgh/1.txt")); +} + +static void progress(const char *path, size_t cur, size_t tot, void *payload) +{ + bool *was_called = (bool*)payload; + GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot); + *was_called = true; +} + +void test_checkout_tree__calls_progress_callback(void) +{ + bool was_called = 0; + + g_opts.progress_cb = progress; + g_opts.progress_payload = &was_called; + + cl_git_pass(git_revparse_single(&g_object, g_repo, "master")); + + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + + cl_assert_equal_i(was_called, true); +} + +void test_checkout_tree__doesnt_write_unrequested_files_to_worktree(void) +{ + git_oid master_oid; + git_oid chomped_oid; + git_commit* p_master_commit; + git_commit* p_chomped_commit; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + git_oid_fromstr(&master_oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + git_oid_fromstr(&chomped_oid, "e90810b8df3e80c413d903f631643c716887138d"); + cl_git_pass(git_commit_lookup(&p_master_commit, g_repo, &master_oid)); + cl_git_pass(git_commit_lookup(&p_chomped_commit, g_repo, &chomped_oid)); + + /* GIT_CHECKOUT_NONE should not add any file to the working tree from the + * index as it is supposed to be a dry run. + */ + opts.checkout_strategy = GIT_CHECKOUT_NONE; + git_checkout_tree(g_repo, (git_object*)p_chomped_commit, &opts); + cl_assert_equal_i(false, git_path_isfile("testrepo/readme.txt")); + + git_commit_free(p_master_commit); + git_commit_free(p_chomped_commit); +} + +void test_checkout_tree__can_switch_branches(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_oid oid; + git_object *obj = NULL; + + assert_on_branch(g_repo, "master"); + + /* do first checkout with FORCE because we don't know if testrepo + * base data is clean for a checkout or not + */ + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + + cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); + cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir")); + + cl_assert(git_path_isfile("testrepo/README")); + cl_assert(git_path_isfile("testrepo/branch_file.txt")); + cl_assert(git_path_isfile("testrepo/new.txt")); + cl_assert(git_path_isfile("testrepo/a/b.txt")); + + cl_assert(!git_path_isdir("testrepo/ab")); + + assert_on_branch(g_repo, "dir"); + + git_object_free(obj); + + /* do second checkout safe because we should be clean after first */ + opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/subtrees")); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + + cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); + cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees")); + + cl_assert(git_path_isfile("testrepo/README")); + cl_assert(git_path_isfile("testrepo/branch_file.txt")); + cl_assert(git_path_isfile("testrepo/new.txt")); + cl_assert(git_path_isfile("testrepo/ab/4.txt")); + cl_assert(git_path_isfile("testrepo/ab/c/3.txt")); + cl_assert(git_path_isfile("testrepo/ab/de/2.txt")); + cl_assert(git_path_isfile("testrepo/ab/de/fgh/1.txt")); + + cl_assert(!git_path_isdir("testrepo/a")); + + assert_on_branch(g_repo, "subtrees"); + + git_object_free(obj); +} + +void test_checkout_tree__can_remove_untracked(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_REMOVE_UNTRACKED; + + cl_git_mkfile("testrepo/untracked_file", "as you wish"); + cl_assert(git_path_isfile("testrepo/untracked_file")); + + cl_git_pass(git_checkout_head(g_repo, &opts)); + + cl_assert(!git_path_isfile("testrepo/untracked_file")); +} + +void test_checkout_tree__can_remove_ignored(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + int ignored = 0; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_REMOVE_IGNORED; + + cl_git_mkfile("testrepo/ignored_file", "as you wish"); + + cl_git_pass(git_ignore_add_rule(g_repo, "ignored_file\n")); + + cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "ignored_file")); + cl_assert_equal_i(1, ignored); + + cl_assert(git_path_isfile("testrepo/ignored_file")); + + cl_git_pass(git_checkout_head(g_repo, &opts)); + + cl_assert(!git_path_isfile("testrepo/ignored_file")); +} + +void test_checkout_tree__can_update_only(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_oid oid; + git_object *obj = NULL; + + /* first let's get things into a known state - by checkout out the HEAD */ + + assert_on_branch(g_repo, "master"); + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + cl_git_pass(git_checkout_head(g_repo, &opts)); + + cl_assert(!git_path_isdir("testrepo/a")); + + check_file_contents_nocr("testrepo/branch_file.txt", "hi\nbye!\n"); + + /* now checkout branch but with update only */ + + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + + cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); + cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir")); + + assert_on_branch(g_repo, "dir"); + + /* this normally would have been created (which was tested separately in + * the test_checkout_tree__can_switch_branches test), but with + * UPDATE_ONLY it will not have been created. + */ + cl_assert(!git_path_isdir("testrepo/a")); + + /* but this file still should have been updated */ + check_file_contents_nocr("testrepo/branch_file.txt", "hi\n"); + + git_object_free(obj); +} + +void test_checkout_tree__can_checkout_with_pattern(void) +{ + char *entries[] = { "[l-z]*.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, "8496071c1b46c854b31185ea97743be6a8774479")); + + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + cl_git_pass( + git_repository_set_head_detached(g_repo, git_object_id(g_object))); + + git_object_free(g_object); + g_object = NULL; + + 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")); + + /* now to a narrow patterned checkout */ + + g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + g_opts.paths.strings = entries; + g_opts.paths.count = 1; + + 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_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")); +} + +void test_checkout_tree__can_disable_pattern_match(void) +{ + char *entries[] = { "b*.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, "8496071c1b46c854b31185ea97743be6a8774479")); + + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + cl_git_pass( + git_repository_set_head_detached(g_repo, git_object_id(g_object))); + + git_object_free(g_object); + g_object = NULL; + + cl_assert(!git_path_isfile("testrepo/branch_file.txt")); + + /* now to a narrow patterned checkout, but disable pattern */ + + g_opts.checkout_strategy = + GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH; + g_opts.paths.strings = entries; + g_opts.paths.count = 1; + + 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_assert(!git_path_isfile("testrepo/branch_file.txt")); + + /* let's try that again, but allow the pattern match */ + + g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + + cl_assert(git_path_isfile("testrepo/branch_file.txt")); +} + +void assert_conflict( + const char *entry_path, + const char *new_content, + const char *parent_sha, + const char *commit_sha) +{ + git_index *index; + git_object *hack_tree; + git_reference *branch, *head; + git_buf file_path = GIT_BUF_INIT; + + cl_git_pass(git_repository_index(&index, g_repo)); + + /* Create a branch pointing at the parent */ + cl_git_pass(git_revparse_single(&g_object, g_repo, parent_sha)); + cl_git_pass(git_branch_create(&branch, g_repo, + "potential_conflict", (git_commit *)g_object, 0)); + + /* Make HEAD point to this branch */ + cl_git_pass(git_reference_symbolic_create( + &head, g_repo, "HEAD", git_reference_name(branch), 1)); + git_reference_free(head); + git_reference_free(branch); + + /* Checkout the parent */ + g_opts.checkout_strategy = GIT_CHECKOUT_FORCE; + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + + /* Hack-ishy workaound to ensure *all* the index entries + * match the content of the tree + */ + cl_git_pass(git_object_peel(&hack_tree, g_object, GIT_OBJ_TREE)); + cl_git_pass(git_index_read_tree(index, (git_tree *)hack_tree)); + git_object_free(hack_tree); + git_object_free(g_object); + g_object = NULL; + + /* Create a conflicting file */ + cl_git_pass(git_buf_joinpath(&file_path, "./testrepo", entry_path)); + cl_git_mkfile(git_buf_cstr(&file_path), new_content); + git_buf_free(&file_path); + + /* Trying to checkout the original commit */ + cl_git_pass(git_revparse_single(&g_object, g_repo, commit_sha)); + + g_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + cl_assert_equal_i( + GIT_EMERGECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts)); + + /* Stage the conflicting change */ + cl_git_pass(git_index_add_bypath(index, entry_path)); + cl_git_pass(git_index_write(index)); + git_index_free(index); + + cl_assert_equal_i( + GIT_EMERGECONFLICT, git_checkout_tree(g_repo, g_object, &g_opts)); +} + +void test_checkout_tree__checking_out_a_conflicting_type_change_returns_EMERGECONFLICT(void) +{ + /* + * 099faba adds a symlink named 'link_to_new.txt' + * a65fedf is the parent of 099faba + */ + + assert_conflict("link_to_new.txt", "old.txt", "a65fedf", "099faba"); +} + +void test_checkout_tree__checking_out_a_conflicting_type_change_returns_EMERGECONFLICT_2(void) +{ + /* + * cf80f8d adds a directory named 'a/' + * a4a7dce is the parent of cf80f8d + */ + + assert_conflict("a", "hello\n", "a4a7dce", "cf80f8d"); +} + +void test_checkout_tree__checking_out_a_conflicting_content_change_returns_EMERGECONFLICT(void) +{ + /* + * c47800c adds a symlink named 'branch_file.txt' + * 5b5b025 is the parent of 763d71a + */ + + assert_conflict("branch_file.txt", "hello\n", "5b5b025", "c47800c"); +} + +void test_checkout_tree__donot_update_deleted_file_by_default(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_oid old_id, new_id; + git_commit *old_commit = NULL, *new_commit = NULL; + git_index *index = NULL; + checkout_counts ct; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + memset(&ct, 0, sizeof(ct)); + opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL; + opts.notify_cb = checkout_count_callback; + opts.notify_payload = &ct; + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_pass(git_oid_fromstr(&old_id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); + cl_git_pass(git_commit_lookup(&old_commit, g_repo, &old_id)); + cl_git_pass(git_reset(g_repo, (git_object *)old_commit, GIT_RESET_HARD)); + + cl_git_pass(p_unlink("testrepo/branch_file.txt")); + cl_git_pass(git_index_remove_bypath(index ,"branch_file.txt")); + cl_git_pass(git_index_write(index)); + + cl_assert(!git_path_exists("testrepo/branch_file.txt")); + + cl_git_pass(git_oid_fromstr(&new_id, "099fabac3a9ea935598528c27f866e34089c2eff")); + cl_git_pass(git_commit_lookup(&new_commit, g_repo, &new_id)); + + + cl_git_fail(git_checkout_tree(g_repo, (git_object *)new_commit, &opts)); + + cl_assert_equal_i(1, ct.n_conflicts); + cl_assert_equal_i(1, ct.n_updates); + + git_commit_free(old_commit); + git_commit_free(new_commit); + git_index_free(index); +} + +void test_checkout_tree__can_checkout_with_last_workdir_item_missing(void) +{ + git_index *index = NULL; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_oid tree_id, commit_id; + git_tree *tree = NULL; + git_commit *commit = NULL; + + git_repository_index(&index, g_repo); + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_reference_name_to_id(&commit_id, g_repo, "refs/heads/master")); + cl_git_pass(git_commit_lookup(&commit, g_repo, &commit_id)); + + cl_git_pass(git_checkout_tree(g_repo, (git_object *)commit, &opts)); + cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master")); + + cl_git_pass(p_mkdir("./testrepo/this-is-dir", 0777)); + cl_git_mkfile("./testrepo/this-is-dir/contained_file", "content\n"); + + cl_git_pass(git_index_add_bypath(index, "this-is-dir/contained_file")); + git_index_write_tree(&tree_id, index); + cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); + + cl_git_pass(p_unlink("./testrepo/this-is-dir/contained_file")); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + opts.checkout_strategy = 1; + git_checkout_tree(g_repo, (git_object *)tree, &opts); + + git_tree_free(tree); + git_commit_free(commit); + git_index_free(index); +} + +void test_checkout_tree__issue_1397(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + const char *partial_oid = "8a7ef04"; + git_object *tree = NULL; + + test_checkout_tree__cleanup(); /* cleanup default checkout */ + + g_repo = cl_git_sandbox_init("issue_1397"); + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + cl_git_pass(git_revparse_single(&tree, g_repo, partial_oid)); + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_checkout_tree(g_repo, tree, &opts)); + + check_file_contents("./issue_1397/crlf_file.txt", "first line\r\nsecond line\r\nboth with crlf"); + + git_object_free(tree); +} + +void test_checkout_tree__can_write_to_empty_dirs(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_oid oid; + git_object *obj = NULL; + + assert_on_branch(g_repo, "master"); + + cl_git_pass(p_mkdir("testrepo/a", 0777)); + + /* do first checkout with FORCE because we don't know if testrepo + * base data is clean for a checkout or not + */ + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + + cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); + + cl_assert(git_path_isfile("testrepo/a/b.txt")); + + git_object_free(obj); +} + +void test_checkout_tree__fails_when_dir_in_use(void) +{ +#ifdef GIT_WIN32 + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_oid oid; + git_object *obj = NULL; + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + + cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); + + cl_assert(git_path_isfile("testrepo/a/b.txt")); + + git_object_free(obj); + + cl_git_pass(p_chdir("testrepo/a")); + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/master")); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + + cl_git_fail(git_checkout_tree(g_repo, obj, &opts)); + + cl_git_pass(p_chdir("../..")); + + cl_assert(git_path_is_empty_dir("testrepo/a")); + + git_object_free(obj); +#endif +} + +void test_checkout_tree__can_continue_when_dir_in_use(void) +{ +#ifdef GIT_WIN32 + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_oid oid; + git_object *obj = NULL; + + opts.checkout_strategy = GIT_CHECKOUT_FORCE | + GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES; + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir")); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + + cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); + + cl_assert(git_path_isfile("testrepo/a/b.txt")); + + git_object_free(obj); + + cl_git_pass(p_chdir("testrepo/a")); + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/master")); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + + cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); + + cl_git_pass(p_chdir("../..")); + + cl_assert(git_path_is_empty_dir("testrepo/a")); + + git_object_free(obj); +#endif +} + +void test_checkout_tree__target_directory_from_bare(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_oid oid; + checkout_counts cts; + memset(&cts, 0, sizeof(cts)); + + test_checkout_tree__cleanup(); /* cleanup default checkout */ + + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_assert(git_repository_is_bare(g_repo)); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + + opts.notify_flags = GIT_CHECKOUT_NOTIFY_ALL; + opts.notify_cb = checkout_count_callback; + opts.notify_payload = &cts; + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "HEAD")); + cl_git_pass(git_object_lookup(&g_object, g_repo, &oid, GIT_OBJ_ANY)); + + cl_git_fail(git_checkout_tree(g_repo, g_object, &opts)); + + opts.target_directory = "alternative"; + cl_assert(!git_path_isdir("alternative")); + + cl_git_pass(git_checkout_tree(g_repo, g_object, &opts)); + + cl_assert_equal_i(0, cts.n_untracked); + cl_assert_equal_i(0, cts.n_ignored); + cl_assert_equal_i(3, cts.n_updates); + + check_file_contents_nocr("./alternative/README", "hey there\n"); + check_file_contents_nocr("./alternative/branch_file.txt", "hi\nbye!\n"); + check_file_contents_nocr("./alternative/new.txt", "my new file\n"); + + cl_git_pass(git_futils_rmdir_r( + "alternative", NULL, GIT_RMDIR_REMOVE_FILES)); +} + +void test_checkout_tree__extremely_long_file_name(void) +{ + // A utf-8 string with 83 characters, but 249 bytes. + const char *longname = "\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97"; + char path[1024]; + + g_opts.checkout_strategy = GIT_CHECKOUT_FORCE; + cl_git_pass(git_revparse_single(&g_object, g_repo, "long-file-name")); + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + + sprintf(path, "testrepo/%s.txt", longname); + cl_assert(git_path_exists(path)); + + git_object_free(g_object); + cl_git_pass(git_revparse_single(&g_object, g_repo, "master")); + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + cl_assert(!git_path_exists(path)); +} + +static void create_conflict(void) +{ + git_index *index; + git_index_entry entry; + + cl_git_pass(git_repository_index(&index, g_repo)); + + memset(&entry, 0x0, sizeof(git_index_entry)); + entry.mode = 0100644; + entry.flags = 1 << GIT_IDXENTRY_STAGESHIFT; + git_oid_fromstr(&entry.oid, "d427e0b2e138501a3d15cc376077a3631e15bd46"); + entry.path = "conflicts.txt"; + cl_git_pass(git_index_add(index, &entry)); + + entry.flags = 2 << GIT_IDXENTRY_STAGESHIFT; + git_oid_fromstr(&entry.oid, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf"); + cl_git_pass(git_index_add(index, &entry)); + + entry.flags = 3 << GIT_IDXENTRY_STAGESHIFT; + git_oid_fromstr(&entry.oid, "2bd0a343aeef7a2cf0d158478966a6e587ff3863"); + cl_git_pass(git_index_add(index, &entry)); + + git_index_write(index); + git_index_free(index); +} + +void test_checkout_tree__fails_when_conflicts_exist_in_index(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_oid oid; + git_object *obj = NULL; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE; + + cl_git_pass(git_reference_name_to_id(&oid, g_repo, "HEAD")); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + + create_conflict(); + + cl_git_fail(git_checkout_tree(g_repo, obj, &opts)); + + git_object_free(obj); +} diff --git a/tests/checkout/typechange.c b/tests/checkout/typechange.c new file mode 100644 index 000000000..6cf99ac15 --- /dev/null +++ b/tests/checkout/typechange.c @@ -0,0 +1,240 @@ +#include "clar_libgit2.h" +#include "git2/checkout.h" +#include "path.h" +#include "posix.h" +#include "fileops.h" + +static git_repository *g_repo = NULL; + +static const char *g_typechange_oids[] = { + "79b9f23e85f55ea36a472a902e875bc1121a94cb", + "9bdb75b73836a99e3dbeea640a81de81031fdc29", + "0e7ed140b514b8cae23254cb8656fe1674403aff", + "9d0235c7a7edc0889a18f97a42ee6db9fe688447", + "9b19edf33a03a0c59cdfc113bfa5c06179bf9b1a", + "1b63caae4a5ca96f78e8dfefc376c6a39a142475", + "6eae26c90e8ccc4d16208972119c40635489c6f0", + NULL +}; + +static bool g_typechange_empty[] = { + true, false, false, false, false, false, true, true +}; + +void test_checkout_typechange__initialize(void) +{ + g_repo = cl_git_sandbox_init("typechanges"); + + cl_fixture_sandbox("submod2_target"); + p_rename("submod2_target/.gitted", "submod2_target/.git"); +} + +void test_checkout_typechange__cleanup(void) +{ + cl_git_sandbox_cleanup(); + cl_fixture_cleanup("submod2_target"); +} + +static void assert_file_exists(const char *path) +{ + cl_assert_(git_path_isfile(path), path); +} + +static void assert_dir_exists(const char *path) +{ + cl_assert_(git_path_isdir(path), path); +} + +static void assert_workdir_matches_tree( + git_repository *repo, const git_oid *id, const char *root, bool recurse) +{ + git_object *obj; + git_tree *tree; + size_t i, max_i; + git_buf path = GIT_BUF_INIT; + + if (!root) + root = git_repository_workdir(repo); + cl_assert(root); + + cl_git_pass(git_object_lookup(&obj, repo, id, GIT_OBJ_ANY)); + cl_git_pass(git_object_peel((git_object **)&tree, obj, GIT_OBJ_TREE)); + git_object_free(obj); + + max_i = git_tree_entrycount(tree); + + for (i = 0; i < max_i; ++i) { + const git_tree_entry *te = git_tree_entry_byindex(tree, i); + cl_assert(te); + + cl_git_pass(git_buf_joinpath(&path, root, git_tree_entry_name(te))); + + switch (git_tree_entry_type(te)) { + case GIT_OBJ_COMMIT: + assert_dir_exists(path.ptr); + break; + case GIT_OBJ_TREE: + assert_dir_exists(path.ptr); + if (recurse) + assert_workdir_matches_tree( + repo, git_tree_entry_id(te), path.ptr, true); + break; + case GIT_OBJ_BLOB: + switch (git_tree_entry_filemode(te)) { + case GIT_FILEMODE_BLOB: + case GIT_FILEMODE_BLOB_EXECUTABLE: + assert_file_exists(path.ptr); + /* because of cross-platform, don't confirm exec bit yet */ + break; + case GIT_FILEMODE_LINK: + cl_assert_(git_path_exists(path.ptr), path.ptr); + /* because of cross-platform, don't confirm link yet */ + break; + default: + cl_assert(false); /* really?! */ + } + break; + default: + cl_assert(false); /* really?!! */ + } + } + + git_tree_free(tree); + git_buf_free(&path); +} + +void test_checkout_typechange__checkout_typechanges_safe(void) +{ + int i; + git_object *obj; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + for (i = 0; g_typechange_oids[i] != NULL; ++i) { + cl_git_pass(git_revparse_single(&obj, g_repo, g_typechange_oids[i])); + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + /* There are bugs in some submodule->tree changes that prevent + * SAFE from passing here, even though the following should work: + */ + /* !i ? GIT_CHECKOUT_FORCE : GIT_CHECKOUT_SAFE; */ + + cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); + + cl_git_pass( + git_repository_set_head_detached(g_repo, git_object_id(obj))); + + assert_workdir_matches_tree(g_repo, git_object_id(obj), NULL, true); + + git_object_free(obj); + + if (!g_typechange_empty[i]) { + cl_assert(git_path_isdir("typechanges")); + cl_assert(git_path_exists("typechanges/a")); + cl_assert(git_path_exists("typechanges/b")); + cl_assert(git_path_exists("typechanges/c")); + cl_assert(git_path_exists("typechanges/d")); + cl_assert(git_path_exists("typechanges/e")); + } else { + cl_assert(git_path_isdir("typechanges")); + cl_assert(!git_path_exists("typechanges/a")); + cl_assert(!git_path_exists("typechanges/b")); + cl_assert(!git_path_exists("typechanges/c")); + cl_assert(!git_path_exists("typechanges/d")); + cl_assert(!git_path_exists("typechanges/e")); + } + } +} + +typedef struct { + int conflicts; + int dirty; + int updates; + int untracked; + int ignored; +} notify_counts; + +static int notify_counter( + git_checkout_notify_t why, + const char *path, + const git_diff_file *baseline, + const git_diff_file *target, + const git_diff_file *workdir, + void *payload) +{ + notify_counts *cts = payload; + + GIT_UNUSED(path); + GIT_UNUSED(baseline); + GIT_UNUSED(target); + GIT_UNUSED(workdir); + + switch (why) { + case GIT_CHECKOUT_NOTIFY_CONFLICT: cts->conflicts++; break; + case GIT_CHECKOUT_NOTIFY_DIRTY: cts->dirty++; break; + case GIT_CHECKOUT_NOTIFY_UPDATED: cts->updates++; break; + case GIT_CHECKOUT_NOTIFY_UNTRACKED: cts->untracked++; break; + case GIT_CHECKOUT_NOTIFY_IGNORED: cts->ignored++; break; + default: break; + } + + return 0; +} + +static void force_create_file(const char *file) +{ + int error = git_futils_rmdir_r(file, NULL, + GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS); + cl_assert(!error || error == GIT_ENOTFOUND); + cl_git_pass(git_futils_mkpath2file(file, 0777)); + cl_git_rewritefile(file, "yowza!!"); +} + +void test_checkout_typechange__checkout_with_conflicts(void) +{ + int i; + git_object *obj; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + notify_counts cts = {0}; + + opts.notify_flags = + GIT_CHECKOUT_NOTIFY_CONFLICT | GIT_CHECKOUT_NOTIFY_UNTRACKED; + opts.notify_cb = notify_counter; + opts.notify_payload = &cts; + + for (i = 0; g_typechange_oids[i] != NULL; ++i) { + cl_git_pass(git_revparse_single(&obj, g_repo, g_typechange_oids[i])); + + force_create_file("typechanges/a/blocker"); + force_create_file("typechanges/b"); + force_create_file("typechanges/c/sub/sub/file"); + git_futils_rmdir_r("typechanges/d", NULL, GIT_RMDIR_REMOVE_FILES); + p_mkdir("typechanges/d", 0777); /* intentionally empty dir */ + force_create_file("typechanges/untracked"); + + opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + memset(&cts, 0, sizeof(cts)); + + cl_git_fail(git_checkout_tree(g_repo, obj, &opts)); + cl_assert(cts.conflicts > 0); + cl_assert(cts.untracked > 0); + + opts.checkout_strategy = + GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED; + memset(&cts, 0, sizeof(cts)); + + cl_assert(git_path_exists("typechanges/untracked")); + + cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); + cl_assert_equal_i(0, cts.conflicts); + + cl_assert(!git_path_exists("typechanges/untracked")); + + cl_git_pass( + git_repository_set_head_detached(g_repo, git_object_id(obj))); + + assert_workdir_matches_tree(g_repo, git_object_id(obj), NULL, true); + + git_object_free(obj); + } +} diff --git a/tests/clar.c b/tests/clar.c new file mode 100644 index 000000000..6c7399a54 --- /dev/null +++ b/tests/clar.c @@ -0,0 +1,511 @@ +/* + * Copyright (c) Vicent Marti. All rights reserved. + * + * This file is part of clar, distributed under the ISC license. + * For full terms see the included COPYING file. + */ +#include +#include +#include +#include +#include +#include +#include + +/* required for sandboxing */ +#include +#include + +#ifdef _WIN32 +# include +# include +# include +# include + +# define _MAIN_CC __cdecl + +# ifndef stat +# define stat(path, st) _stat(path, st) +# endif +# ifndef mkdir +# define mkdir(path, mode) _mkdir(path) +# endif +# ifndef chdir +# define chdir(path) _chdir(path) +# endif +# ifndef access +# define access(path, mode) _access(path, mode) +# endif +# ifndef strdup +# define strdup(str) _strdup(str) +# endif +# ifndef strcasecmp +# define strcasecmp(a,b) _stricmp(a,b) +# endif + +# ifndef __MINGW32__ +# pragma comment(lib, "shell32") +# ifndef strncpy +# define strncpy(to, from, to_size) strncpy_s(to, to_size, from, _TRUNCATE) +# endif +# ifndef W_OK +# define W_OK 02 +# endif +# ifndef S_ISDIR +# define S_ISDIR(x) ((x & _S_IFDIR) != 0) +# endif +# define p_snprintf(buf,sz,fmt,...) _snprintf_s(buf,sz,_TRUNCATE,fmt,__VA_ARGS__) +# else +# define p_snprintf snprintf +# endif + +# ifndef PRIuZ +# define PRIuZ "Iu" +# endif +# ifndef PRIxZ +# define PRIxZ "Ix" +# endif + typedef struct _stat STAT_T; +#else +# include /* waitpid(2) */ +# include +# define _MAIN_CC +# define p_snprintf snprintf +# ifndef PRIuZ +# define PRIuZ "zu" +# endif +# ifndef PRIxZ +# define PRIxZ "zx" +# endif + typedef struct stat STAT_T; +#endif + +#include "clar.h" + +static void fs_rm(const char *_source); +static void fs_copy(const char *_source, const char *dest); + +static const char * +fixture_path(const char *base, const char *fixture_name); + +struct clar_error { + const char *test; + int test_number; + const char *suite; + const char *file; + int line_number; + const char *error_msg; + char *description; + + struct clar_error *next; +}; + +static struct { + const char *active_test; + const char *active_suite; + + int suite_errors; + int total_errors; + + int tests_ran; + int suites_ran; + + int report_errors_only; + int exit_on_error; + int report_suite_names; + + struct clar_error *errors; + struct clar_error *last_error; + + void (*local_cleanup)(void *); + void *local_cleanup_payload; + + jmp_buf trampoline; + int trampoline_enabled; +} _clar; + +struct clar_func { + const char *name; + void (*ptr)(void); +}; + +struct clar_suite { + const char *name; + struct clar_func initialize; + struct clar_func cleanup; + const struct clar_func *tests; + size_t test_count; + int enabled; +}; + +/* From clar_print_*.c */ +static void clar_print_init(int test_count, int suite_count, const char *suite_names); +static void clar_print_shutdown(int test_count, int suite_count, int error_count); +static void clar_print_error(int num, const struct clar_error *error); +static void clar_print_ontest(const char *test_name, int test_number, int failed); +static void clar_print_onsuite(const char *suite_name, int suite_index); +static void clar_print_onabort(const char *msg, ...); + +/* From clar_sandbox.c */ +static void clar_unsandbox(void); +static int clar_sandbox(void); + +/* Load the declarations for the test suite */ +#include "clar.suite" + +/* Core test functions */ +static void +clar_report_errors(void) +{ + int i = 1; + struct clar_error *error, *next; + + error = _clar.errors; + while (error != NULL) { + next = error->next; + clar_print_error(i++, error); + free(error->description); + free(error); + error = next; + } + + _clar.errors = _clar.last_error = NULL; +} + +static void +clar_run_test( + const struct clar_func *test, + const struct clar_func *initialize, + const struct clar_func *cleanup) +{ + int error_st = _clar.suite_errors; + + _clar.trampoline_enabled = 1; + + if (setjmp(_clar.trampoline) == 0) { + if (initialize->ptr != NULL) + initialize->ptr(); + + test->ptr(); + } + + _clar.trampoline_enabled = 0; + + if (_clar.local_cleanup != NULL) + _clar.local_cleanup(_clar.local_cleanup_payload); + + if (cleanup->ptr != NULL) + cleanup->ptr(); + + _clar.tests_ran++; + + /* remove any local-set cleanup methods */ + _clar.local_cleanup = NULL; + _clar.local_cleanup_payload = NULL; + + if (_clar.report_errors_only) + clar_report_errors(); + else + clar_print_ontest( + test->name, + _clar.tests_ran, + (_clar.suite_errors > error_st) + ); +} + +static void +clar_run_suite(const struct clar_suite *suite, const char *filter) +{ + const struct clar_func *test = suite->tests; + size_t i, matchlen; + + if (!suite->enabled) + return; + + if (_clar.exit_on_error && _clar.total_errors) + return; + + if (!_clar.report_errors_only) + clar_print_onsuite(suite->name, ++_clar.suites_ran); + + _clar.active_suite = suite->name; + _clar.suite_errors = 0; + + if (filter) { + size_t suitelen = strlen(suite->name); + matchlen = strlen(filter); + if (matchlen <= suitelen) { + filter = NULL; + } else { + filter += suitelen; + while (*filter == ':') + ++filter; + matchlen = strlen(filter); + } + } + + for (i = 0; i < suite->test_count; ++i) { + if (filter && strncmp(test[i].name, filter, matchlen)) + continue; + + _clar.active_test = test[i].name; + clar_run_test(&test[i], &suite->initialize, &suite->cleanup); + + if (_clar.exit_on_error && _clar.total_errors) + return; + } +} + +static void +clar_usage(const char *arg) +{ + printf("Usage: %s [options]\n\n", arg); + printf("Options:\n"); + printf(" -sname\tRun only the suite with `name` (can go to individual test name)\n"); + printf(" -iname\tInclude the suite with `name`\n"); + printf(" -xname\tExclude the suite with `name`\n"); + printf(" -q \tOnly report tests that had an error\n"); + printf(" -Q \tQuit as soon as a test fails\n"); + printf(" -l \tPrint suite names\n"); + exit(-1); +} + +static void +clar_parse_args(int argc, char **argv) +{ + int i; + + for (i = 1; i < argc; ++i) { + char *argument = argv[i]; + + if (argument[0] != '-') + clar_usage(argv[0]); + + switch (argument[1]) { + case 's': + case 'i': + case 'x': { /* given suite name */ + int offset = (argument[2] == '=') ? 3 : 2, found = 0; + char action = argument[1]; + size_t j, arglen, suitelen, cmplen; + + argument += offset; + arglen = strlen(argument); + + if (arglen == 0) + clar_usage(argv[0]); + + for (j = 0; j < _clar_suite_count; ++j) { + suitelen = strlen(_clar_suites[j].name); + cmplen = (arglen < suitelen) ? arglen : suitelen; + + if (strncmp(argument, _clar_suites[j].name, cmplen) == 0) { + int exact = (arglen >= suitelen); + + ++found; + + if (!exact) + _clar.report_suite_names = 1; + + switch (action) { + case 's': clar_run_suite(&_clar_suites[j], argument); break; + case 'i': _clar_suites[j].enabled = 1; break; + case 'x': _clar_suites[j].enabled = 0; break; + } + + if (exact) + break; + } + } + + if (!found) { + clar_print_onabort("No suite matching '%s' found.\n", argument); + exit(-1); + } + break; + } + + case 'q': + _clar.report_errors_only = 1; + break; + + case 'Q': + _clar.exit_on_error = 1; + break; + + case 'l': { + size_t j; + printf("Test suites (use -s to run just one):\n"); + for (j = 0; j < _clar_suite_count; ++j) + printf(" %3d: %s\n", (int)j, _clar_suites[j].name); + + exit(0); + } + + default: + clar_usage(argv[0]); + } + } +} + +int +clar_test(int argc, char **argv) +{ + clar_print_init( + (int)_clar_callback_count, + (int)_clar_suite_count, + "" + ); + + if (clar_sandbox() < 0) { + clar_print_onabort("Failed to sandbox the test runner.\n"); + exit(-1); + } + + if (argc > 1) + clar_parse_args(argc, argv); + + if (!_clar.suites_ran) { + size_t i; + for (i = 0; i < _clar_suite_count; ++i) + clar_run_suite(&_clar_suites[i], NULL); + } + + clar_print_shutdown( + _clar.tests_ran, + (int)_clar_suite_count, + _clar.total_errors + ); + + clar_unsandbox(); + return _clar.total_errors; +} + +void clar__fail( + const char *file, + int line, + const char *error_msg, + const char *description, + int should_abort) +{ + struct clar_error *error = calloc(1, sizeof(struct clar_error)); + + if (_clar.errors == NULL) + _clar.errors = error; + + if (_clar.last_error != NULL) + _clar.last_error->next = error; + + _clar.last_error = error; + + error->test = _clar.active_test; + error->test_number = _clar.tests_ran; + error->suite = _clar.active_suite; + error->file = file; + error->line_number = line; + error->error_msg = error_msg; + + if (description != NULL) + error->description = strdup(description); + + _clar.suite_errors++; + _clar.total_errors++; + + if (should_abort) { + if (!_clar.trampoline_enabled) { + clar_print_onabort( + "Fatal error: a cleanup method raised an exception."); + clar_report_errors(); + exit(-1); + } + + longjmp(_clar.trampoline, -1); + } +} + +void clar__assert( + int condition, + const char *file, + int line, + const char *error_msg, + const char *description, + int should_abort) +{ + if (condition) + return; + + clar__fail(file, line, error_msg, description, should_abort); +} + +void clar__assert_equal( + const char *file, + int line, + const char *err, + int should_abort, + const char *fmt, + ...) +{ + va_list args; + char buf[4096]; + int is_equal = 1; + + va_start(args, fmt); + + if (!strcmp("%s", fmt)) { + const char *s1 = va_arg(args, const char *); + const char *s2 = va_arg(args, const char *); + is_equal = (!s1 || !s2) ? (s1 == s2) : !strcmp(s1, s2); + + if (!is_equal) { + if (s1 && s2) { + int pos; + for (pos = 0; s1[pos] == s2[pos] && s1[pos] && s2[pos]; ++pos) + /* find differing byte offset */; + p_snprintf(buf, sizeof(buf), "'%s' != '%s' (at byte %d)", + s1, s2, pos); + } else { + p_snprintf(buf, sizeof(buf), "'%s' != '%s'", s1, s2); + } + } + } + else if (!strcmp("%"PRIuZ, fmt) || !strcmp("%"PRIxZ, fmt)) { + size_t sz1 = va_arg(args, size_t), sz2 = va_arg(args, size_t); + is_equal = (sz1 == sz2); + if (!is_equal) { + int offset = p_snprintf(buf, sizeof(buf), fmt, sz1); + strncat(buf, " != ", sizeof(buf) - offset); + p_snprintf(buf + offset + 4, sizeof(buf) - offset - 4, fmt, sz2); + } + } + else if (!strcmp("%p", fmt)) { + void *p1 = va_arg(args, void *), *p2 = va_arg(args, void *); + is_equal = (p1 == p2); + if (!is_equal) + p_snprintf(buf, sizeof(buf), "%p != %p", p1, p2); + } + else { + int i1 = va_arg(args, int), i2 = va_arg(args, int); + is_equal = (i1 == i2); + if (!is_equal) { + int offset = p_snprintf(buf, sizeof(buf), fmt, i1); + strncat(buf, " != ", sizeof(buf) - offset); + p_snprintf(buf + offset + 4, sizeof(buf) - offset - 4, fmt, i2); + } + } + + va_end(args); + + if (!is_equal) + clar__fail(file, line, err, buf, should_abort); +} + +void cl_set_cleanup(void (*cleanup)(void *), void *opaque) +{ + _clar.local_cleanup = cleanup; + _clar.local_cleanup_payload = opaque; +} + +#include "clar/sandbox.h" +#include "clar/fixtures.h" +#include "clar/fs.h" +#include "clar/print.h" diff --git a/tests/clar.h b/tests/clar.h new file mode 100644 index 000000000..e1f244eba --- /dev/null +++ b/tests/clar.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) Vicent Marti. All rights reserved. + * + * This file is part of clar, distributed under the ISC license. + * For full terms see the included COPYING file. + */ +#ifndef __CLAR_TEST_H__ +#define __CLAR_TEST_H__ + +#include + +int clar_test(int argc, char *argv[]); + +void cl_set_cleanup(void (*cleanup)(void *), void *opaque); +void cl_fs_cleanup(void); + +#ifdef CLAR_FIXTURE_PATH +const char *cl_fixture(const char *fixture_name); +void cl_fixture_sandbox(const char *fixture_name); +void cl_fixture_cleanup(const char *fixture_name); +#endif + +/** + * Assertion macros with explicit error message + */ +#define cl_must_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __LINE__, "Function call failed: " #expr, desc, 1) +#define cl_must_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __LINE__, "Expected function call to fail: " #expr, desc, 1) +#define cl_assert_(expr, desc) clar__assert((expr) != 0, __FILE__, __LINE__, "Expression is not true: " #expr, desc, 1) + +/** + * Check macros with explicit error message + */ +#define cl_check_pass_(expr, desc) clar__assert((expr) >= 0, __FILE__, __LINE__, "Function call failed: " #expr, desc, 0) +#define cl_check_fail_(expr, desc) clar__assert((expr) < 0, __FILE__, __LINE__, "Expected function call to fail: " #expr, desc, 0) +#define cl_check_(expr, desc) clar__assert((expr) != 0, __FILE__, __LINE__, "Expression is not true: " #expr, desc, 0) + +/** + * Assertion macros with no error message + */ +#define cl_must_pass(expr) cl_must_pass_(expr, NULL) +#define cl_must_fail(expr) cl_must_fail_(expr, NULL) +#define cl_assert(expr) cl_assert_(expr, NULL) + +/** + * Check macros with no error message + */ +#define cl_check_pass(expr) cl_check_pass_(expr, NULL) +#define cl_check_fail(expr) cl_check_fail_(expr, NULL) +#define cl_check(expr) cl_check_(expr, NULL) + +/** + * Forced failure/warning + */ +#define cl_fail(desc) clar__fail(__FILE__, __LINE__, "Test failed.", desc, 1) +#define cl_warning(desc) clar__fail(__FILE__, __LINE__, "Warning during test execution:", desc, 0) + +/** + * Typed assertion macros + */ +#define cl_assert_equal_s(s1,s2) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2, 1, "%s", (s1), (s2)) +#define cl_assert_equal_s_(s1,s2,note) clar__assert_equal(__FILE__,__LINE__,"String mismatch: " #s1 " != " #s2 " (" #note ")", 1, "%s", (s1), (s2)) + +#define cl_assert_equal_i(i1,i2) clar__assert_equal(__FILE__,__LINE__,#i1 " != " #i2, 1, "%d", (int)(i1), (int)(i2)) +#define cl_assert_equal_i_(i1,i2,note) clar__assert_equal(__FILE__,__LINE__,#i1 " != " #i2 " (" #note ")", 1, "%d", (i1), (i2)) +#define cl_assert_equal_i_fmt(i1,i2,fmt) clar__assert_equal(__FILE__,__LINE__,#i1 " != " #i2, 1, (fmt), (int)(i1), (int)(i2)) + +#define cl_assert_equal_b(b1,b2) clar__assert_equal(__FILE__,__LINE__,#b1 " != " #b2, 1, "%d", (int)((b1) != 0),(int)((b2) != 0)) + +#define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2)) + + +void clar__fail( + const char *file, + int line, + const char *error, + const char *description, + int should_abort); + +void clar__assert( + int condition, + const char *file, + int line, + const char *error, + const char *description, + int should_abort); + +void clar__assert_equal( + const char *file, + int line, + const char *err, + int should_abort, + const char *fmt, + ...); + +#endif diff --git a/tests/clar/fixtures.h b/tests/clar/fixtures.h new file mode 100644 index 000000000..264cd7f4f --- /dev/null +++ b/tests/clar/fixtures.h @@ -0,0 +1,38 @@ +static const char * +fixture_path(const char *base, const char *fixture_name) +{ + static char _path[4096]; + size_t root_len; + + root_len = strlen(base); + strncpy(_path, base, sizeof(_path)); + + if (_path[root_len - 1] != '/') + _path[root_len++] = '/'; + + if (fixture_name[0] == '/') + fixture_name++; + + strncpy(_path + root_len, + fixture_name, + sizeof(_path) - root_len); + + return _path; +} + +#ifdef CLAR_FIXTURE_PATH +const char *cl_fixture(const char *fixture_name) +{ + return fixture_path(CLAR_FIXTURE_PATH, fixture_name); +} + +void cl_fixture_sandbox(const char *fixture_name) +{ + fs_copy(cl_fixture(fixture_name), _clar_path); +} + +void cl_fixture_cleanup(const char *fixture_name) +{ + fs_rm(fixture_path(_clar_path, fixture_name)); +} +#endif diff --git a/tests/clar/fs.h b/tests/clar/fs.h new file mode 100644 index 000000000..b7a1ff9d2 --- /dev/null +++ b/tests/clar/fs.h @@ -0,0 +1,325 @@ +#ifdef _WIN32 + +#define RM_RETRY_COUNT 5 +#define RM_RETRY_DELAY 10 + +#ifdef __MINGW32__ + +/* These security-enhanced functions are not available + * in MinGW, so just use the vanilla ones */ +#define wcscpy_s(a, b, c) wcscpy((a), (c)) +#define wcscat_s(a, b, c) wcscat((a), (c)) + +#endif /* __MINGW32__ */ + +static int +fs__dotordotdot(WCHAR *_tocheck) +{ + return _tocheck[0] == '.' && + (_tocheck[1] == '\0' || + (_tocheck[1] == '.' && _tocheck[2] == '\0')); +} + +static int +fs_rmdir_rmdir(WCHAR *_wpath) +{ + unsigned retries = 1; + + while (!RemoveDirectoryW(_wpath)) { + /* Only retry when we have retries remaining, and the + * error was ERROR_DIR_NOT_EMPTY. */ + if (retries++ > RM_RETRY_COUNT || + ERROR_DIR_NOT_EMPTY != GetLastError()) + return -1; + + /* Give whatever has a handle to a child item some time + * to release it before trying again */ + Sleep(RM_RETRY_DELAY * retries * retries); + } + + return 0; +} + +static void +fs_rmdir_helper(WCHAR *_wsource) +{ + WCHAR buffer[MAX_PATH]; + HANDLE find_handle; + WIN32_FIND_DATAW find_data; + size_t buffer_prefix_len; + + /* Set up the buffer and capture the length */ + wcscpy_s(buffer, MAX_PATH, _wsource); + wcscat_s(buffer, MAX_PATH, L"\\"); + buffer_prefix_len = wcslen(buffer); + + /* FindFirstFile needs a wildcard to match multiple items */ + wcscat_s(buffer, MAX_PATH, L"*"); + find_handle = FindFirstFileW(buffer, &find_data); + cl_assert(INVALID_HANDLE_VALUE != find_handle); + + do { + /* FindFirstFile/FindNextFile gives back . and .. + * entries at the beginning */ + if (fs__dotordotdot(find_data.cFileName)) + continue; + + wcscpy_s(buffer + buffer_prefix_len, MAX_PATH - buffer_prefix_len, find_data.cFileName); + + if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes) + fs_rmdir_helper(buffer); + else { + /* If set, the +R bit must be cleared before deleting */ + if (FILE_ATTRIBUTE_READONLY & find_data.dwFileAttributes) + cl_assert(SetFileAttributesW(buffer, find_data.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)); + + cl_assert(DeleteFileW(buffer)); + } + } + while (FindNextFileW(find_handle, &find_data)); + + /* Ensure that we successfully completed the enumeration */ + cl_assert(ERROR_NO_MORE_FILES == GetLastError()); + + /* Close the find handle */ + FindClose(find_handle); + + /* Now that the directory is empty, remove it */ + cl_assert(0 == fs_rmdir_rmdir(_wsource)); +} + +static int +fs_rm_wait(WCHAR *_wpath) +{ + unsigned retries = 1; + DWORD last_error; + + do { + if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(_wpath)) + last_error = GetLastError(); + else + last_error = ERROR_SUCCESS; + + /* Is the item gone? */ + if (ERROR_FILE_NOT_FOUND == last_error || + ERROR_PATH_NOT_FOUND == last_error) + return 0; + + Sleep(RM_RETRY_DELAY * retries * retries); + } + while (retries++ <= RM_RETRY_COUNT); + + return -1; +} + +static void +fs_rm(const char *_source) +{ + WCHAR wsource[MAX_PATH]; + DWORD attrs; + + /* The input path is UTF-8. Convert it to wide characters + * for use with the Windows API */ + cl_assert(MultiByteToWideChar(CP_UTF8, + MB_ERR_INVALID_CHARS, + _source, + -1, /* Indicates NULL termination */ + wsource, + MAX_PATH)); + + /* Does the item exist? If not, we have no work to do */ + attrs = GetFileAttributesW(wsource); + + if (INVALID_FILE_ATTRIBUTES == attrs) + return; + + if (FILE_ATTRIBUTE_DIRECTORY & attrs) + fs_rmdir_helper(wsource); + else { + /* The item is a file. Strip the +R bit */ + if (FILE_ATTRIBUTE_READONLY & attrs) + cl_assert(SetFileAttributesW(wsource, attrs & ~FILE_ATTRIBUTE_READONLY)); + + cl_assert(DeleteFileW(wsource)); + } + + /* Wait for the DeleteFile or RemoveDirectory call to complete */ + cl_assert(0 == fs_rm_wait(wsource)); +} + +static void +fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest) +{ + WCHAR buf_source[MAX_PATH], buf_dest[MAX_PATH]; + HANDLE find_handle; + WIN32_FIND_DATAW find_data; + size_t buf_source_prefix_len, buf_dest_prefix_len; + + wcscpy_s(buf_source, MAX_PATH, _wsource); + wcscat_s(buf_source, MAX_PATH, L"\\"); + buf_source_prefix_len = wcslen(buf_source); + + wcscpy_s(buf_dest, MAX_PATH, _wdest); + wcscat_s(buf_dest, MAX_PATH, L"\\"); + buf_dest_prefix_len = wcslen(buf_dest); + + /* Get an enumerator for the items in the source. */ + wcscat_s(buf_source, MAX_PATH, L"*"); + find_handle = FindFirstFileW(buf_source, &find_data); + cl_assert(INVALID_HANDLE_VALUE != find_handle); + + /* Create the target directory. */ + cl_assert(CreateDirectoryW(_wdest, NULL)); + + do { + /* FindFirstFile/FindNextFile gives back . and .. + * entries at the beginning */ + if (fs__dotordotdot(find_data.cFileName)) + continue; + + wcscpy_s(buf_source + buf_source_prefix_len, MAX_PATH - buf_source_prefix_len, find_data.cFileName); + wcscpy_s(buf_dest + buf_dest_prefix_len, MAX_PATH - buf_dest_prefix_len, find_data.cFileName); + + if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes) + fs_copydir_helper(buf_source, buf_dest); + else + cl_assert(CopyFileW(buf_source, buf_dest, TRUE)); + } + while (FindNextFileW(find_handle, &find_data)); + + /* Ensure that we successfully completed the enumeration */ + cl_assert(ERROR_NO_MORE_FILES == GetLastError()); + + /* Close the find handle */ + FindClose(find_handle); +} + +static void +fs_copy(const char *_source, const char *_dest) +{ + WCHAR wsource[MAX_PATH], wdest[MAX_PATH]; + DWORD source_attrs, dest_attrs; + HANDLE find_handle; + WIN32_FIND_DATAW find_data; + + /* The input paths are UTF-8. Convert them to wide characters + * for use with the Windows API. */ + cl_assert(MultiByteToWideChar(CP_UTF8, + MB_ERR_INVALID_CHARS, + _source, + -1, + wsource, + MAX_PATH)); + + cl_assert(MultiByteToWideChar(CP_UTF8, + MB_ERR_INVALID_CHARS, + _dest, + -1, + wdest, + MAX_PATH)); + + /* Check the source for existence */ + source_attrs = GetFileAttributesW(wsource); + cl_assert(INVALID_FILE_ATTRIBUTES != source_attrs); + + /* Check the target for existence */ + dest_attrs = GetFileAttributesW(wdest); + + if (INVALID_FILE_ATTRIBUTES != dest_attrs) { + /* Target exists; append last path part of source to target. + * Use FindFirstFile to parse the path */ + find_handle = FindFirstFileW(wsource, &find_data); + cl_assert(INVALID_HANDLE_VALUE != find_handle); + wcscat_s(wdest, MAX_PATH, L"\\"); + wcscat_s(wdest, MAX_PATH, find_data.cFileName); + FindClose(find_handle); + + /* Check the new target for existence */ + cl_assert(INVALID_FILE_ATTRIBUTES == GetFileAttributesW(wdest)); + } + + if (FILE_ATTRIBUTE_DIRECTORY & source_attrs) + fs_copydir_helper(wsource, wdest); + else + cl_assert(CopyFileW(wsource, wdest, TRUE)); +} + +void +cl_fs_cleanup(void) +{ + fs_rm(fixture_path(_clar_path, "*")); +} + +#else +static int +shell_out(char * const argv[]) +{ + int status; + pid_t pid; + + pid = fork(); + + if (pid < 0) { + fprintf(stderr, + "System error: `fork()` call failed.\n"); + exit(-1); + } + + if (pid == 0) { + execv(argv[0], argv); + } + + waitpid(pid, &status, 0); + return WEXITSTATUS(status); +} + +static void +fs_copy(const char *_source, const char *dest) +{ + char *argv[5]; + char *source; + size_t source_len; + + source = strdup(_source); + source_len = strlen(source); + + if (source[source_len - 1] == '/') + source[source_len - 1] = 0; + + argv[0] = "/bin/cp"; + argv[1] = "-R"; + argv[2] = source; + argv[3] = (char *)dest; + argv[4] = NULL; + + cl_must_pass_( + shell_out(argv), + "Failed to copy test fixtures to sandbox" + ); + + free(source); +} + +static void +fs_rm(const char *source) +{ + char *argv[4]; + + argv[0] = "/bin/rm"; + argv[1] = "-Rf"; + argv[2] = (char *)source; + argv[3] = NULL; + + cl_must_pass_( + shell_out(argv), + "Failed to cleanup the sandbox" + ); +} + +void +cl_fs_cleanup(void) +{ + clar_unsandbox(); + clar_sandbox(); +} +#endif diff --git a/tests/clar/print.h b/tests/clar/print.h new file mode 100644 index 000000000..368016f2f --- /dev/null +++ b/tests/clar/print.h @@ -0,0 +1,60 @@ + +static void clar_print_init(int test_count, int suite_count, const char *suite_names) +{ + (void)test_count; + printf("Loaded %d suites: %s\n", (int)suite_count, suite_names); + printf("Started\n"); +} + +static void clar_print_shutdown(int test_count, int suite_count, int error_count) +{ + (void)test_count; + (void)suite_count; + (void)error_count; + + printf("\n\n"); + clar_report_errors(); +} + +static void clar_print_error(int num, const struct clar_error *error) +{ + printf(" %d) Failure:\n", num); + + printf("%s::%s [%s:%d]\n", + error->suite, + error->test, + error->file, + error->line_number); + + printf(" %s\n", error->error_msg); + + if (error->description != NULL) + printf(" %s\n", error->description); + + printf("\n"); + fflush(stdout); +} + +static void clar_print_ontest(const char *test_name, int test_number, int failed) +{ + (void)test_name; + (void)test_number; + printf("%c", failed ? 'F' : '.'); + fflush(stdout); +} + +static void clar_print_onsuite(const char *suite_name, int suite_index) +{ + if (_clar.report_suite_names) + printf("\n%s", suite_name); + + (void)suite_index; +} + +static void clar_print_onabort(const char *msg, ...) +{ + va_list argp; + va_start(argp, msg); + vfprintf(stderr, msg, argp); + va_end(argp); +} diff --git a/tests/clar/sandbox.h b/tests/clar/sandbox.h new file mode 100644 index 000000000..ee7564148 --- /dev/null +++ b/tests/clar/sandbox.h @@ -0,0 +1,129 @@ +static char _clar_path[4096]; + +static int +is_valid_tmp_path(const char *path) +{ + STAT_T st; + + if (stat(path, &st) != 0) + return 0; + + if (!S_ISDIR(st.st_mode)) + return 0; + + return (access(path, W_OK) == 0); +} + +static int +find_tmp_path(char *buffer, size_t length) +{ +#ifndef _WIN32 + static const size_t var_count = 5; + static const char *env_vars[] = { + "CLAR_TMP", "TMPDIR", "TMP", "TEMP", "USERPROFILE" + }; + + size_t i; + + for (i = 0; i < var_count; ++i) { + const char *env = getenv(env_vars[i]); + if (!env) + continue; + + if (is_valid_tmp_path(env)) { + strncpy(buffer, env, length); + return 0; + } + } + + /* If the environment doesn't say anything, try to use /tmp */ + if (is_valid_tmp_path("/tmp")) { + strncpy(buffer, "/tmp", length); + return 0; + } + +#else + DWORD env_len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length); + if (env_len > 0 && env_len < (DWORD)length) + return 0; + + if (GetTempPath((DWORD)length, buffer)) + return 0; +#endif + + /* This system doesn't like us, try to use the current directory */ + if (is_valid_tmp_path(".")) { + strncpy(buffer, ".", length); + return 0; + } + + return -1; +} + +static void clar_unsandbox(void) +{ + if (_clar_path[0] == '\0') + return; + + chdir(".."); + + fs_rm(_clar_path); +} + +static int build_sandbox_path(void) +{ + const char path_tail[] = "clar_tmp_XXXXXX"; + size_t len; + + if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0) + return -1; + + len = strlen(_clar_path); + +#ifdef _WIN32 + { /* normalize path to POSIX forward slashes */ + size_t i; + for (i = 0; i < len; ++i) { + if (_clar_path[i] == '\\') + _clar_path[i] = '/'; + } + } +#endif + + if (_clar_path[len - 1] != '/') { + _clar_path[len++] = '/'; + } + + strncpy(_clar_path + len, path_tail, sizeof(_clar_path) - len); + +#if defined(__MINGW32__) + if (_mktemp(_clar_path) == NULL) + return -1; + + if (mkdir(_clar_path, 0700) != 0) + return -1; +#elif defined(_WIN32) + if (_mktemp_s(_clar_path, sizeof(_clar_path)) != 0) + return -1; + + if (mkdir(_clar_path, 0700) != 0) + return -1; +#else + if (mkdtemp(_clar_path) == NULL) + return -1; +#endif + + return 0; +} + +static int clar_sandbox(void) +{ + if (_clar_path[0] == '\0' && build_sandbox_path() < 0) + return -1; + + if (chdir(_clar_path) != 0) + return -1; + + return 0; +} + diff --git a/tests/clar_libgit2.c b/tests/clar_libgit2.c new file mode 100644 index 000000000..50762cdb8 --- /dev/null +++ b/tests/clar_libgit2.c @@ -0,0 +1,483 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "path.h" +#include "git2/sys/repository.h" + +void cl_git_report_failure( + int error, 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 : ""); + clar__assert(0, file, line, fncall, msg, 1); +} + +void cl_git_mkfile(const char *filename, const char *content) +{ + int fd; + + fd = p_creat(filename, 0666); + cl_assert(fd != 0); + + if (content) { + cl_must_pass(p_write(fd, content, strlen(content))); + } else { + cl_must_pass(p_write(fd, filename, strlen(filename))); + cl_must_pass(p_write(fd, "\n", 1)); + } + + cl_must_pass(p_close(fd)); +} + +void cl_git_write2file( + const char *path, const char *content, size_t content_len, + int flags, unsigned int mode) +{ + int fd; + cl_assert(path && content); + cl_assert((fd = p_open(path, flags, mode)) >= 0); + if (!content_len) + content_len = strlen(content); + cl_must_pass(p_write(fd, content, content_len)); + cl_must_pass(p_close(fd)); +} + +void cl_git_append2file(const char *path, const char *content) +{ + cl_git_write2file(path, content, 0, O_WRONLY | O_CREAT | O_APPEND, 0644); +} + +void cl_git_rewritefile(const char *path, const char *content) +{ + cl_git_write2file(path, content, 0, O_WRONLY | O_CREAT | O_TRUNC, 0644); +} + +#ifdef GIT_WIN32 + +#include "win32/utf-conv.h" + +char *cl_getenv(const char *name) +{ + git_win32_path name_utf16; + DWORD alloc_len; + wchar_t *value_utf16; + char *value_utf8; + + git_win32_path_from_c(name_utf16, name); + alloc_len = GetEnvironmentVariableW(name_utf16, NULL, 0); + if (alloc_len <= 0) + return NULL; + + cl_assert(value_utf16 = git__calloc(alloc_len, sizeof(wchar_t))); + + GetEnvironmentVariableW(name_utf16, value_utf16, alloc_len); + + alloc_len = alloc_len * 4 + 1; /* worst case UTF16->UTF8 growth */ + cl_assert(value_utf8 = git__calloc(alloc_len, 1)); + + git__utf16_to_8(value_utf8, alloc_len, value_utf16); + + git__free(value_utf16); + + return value_utf8; +} + +int cl_setenv(const char *name, const char *value) +{ + git_win32_path name_utf16; + git_win32_path value_utf16; + + git_win32_path_from_c(name_utf16, name); + + if (value) { + git_win32_path_from_c(value_utf16, value); + cl_assert(SetEnvironmentVariableW(name_utf16, value_utf16)); + } else { + /* Windows XP returns 0 (failed) when passing NULL for lpValue when + * lpName does not exist in the environment block. This behavior + * seems to have changed in later versions. Don't check return value + * of SetEnvironmentVariable when passing NULL for lpValue. + */ + SetEnvironmentVariableW(name_utf16, NULL); + } + + return 0; +} + +/* This function performs retries on calls to MoveFile in order + * to provide enhanced reliability in the face of antivirus + * agents that may be scanning the source (or in the case that + * the source is a directory, a child of the source). */ +int cl_rename(const char *source, const char *dest) +{ + git_win32_path source_utf16; + git_win32_path dest_utf16; + unsigned retries = 1; + + git_win32_path_from_c(source_utf16, source); + git_win32_path_from_c(dest_utf16, dest); + + while (!MoveFileW(source_utf16, dest_utf16)) { + /* Only retry if the error is ERROR_ACCESS_DENIED; + * this may indicate that an antivirus agent is + * preventing the rename from source to target */ + if (retries > 5 || + ERROR_ACCESS_DENIED != GetLastError()) + return -1; + + /* With 5 retries and a coefficient of 10ms, the maximum + * delay here is 550 ms */ + Sleep(10 * retries * retries); + retries++; + } + + return 0; +} + +#else + +#include +char *cl_getenv(const char *name) +{ + return getenv(name); +} + +int cl_setenv(const char *name, const char *value) +{ + return (value == NULL) ? unsetenv(name) : setenv(name, value, 1); +} + +int cl_rename(const char *source, const char *dest) +{ + return p_rename(source, dest); +} + +#endif + +static const char *_cl_sandbox = NULL; +static git_repository *_cl_repo = NULL; + +git_repository *cl_git_sandbox_init(const char *sandbox) +{ + /* Copy the whole sandbox folder from our fixtures to our test sandbox + * area. After this it can be accessed with `./sandbox` + */ + cl_fixture_sandbox(sandbox); + _cl_sandbox = sandbox; + + cl_git_pass(p_chdir(sandbox)); + + /* If this is not a bare repo, then rename `sandbox/.gitted` to + * `sandbox/.git` which must be done since we cannot store a folder + * named `.git` inside the fixtures folder of our libgit2 repo. + */ + if (p_access(".gitted", F_OK) == 0) + cl_git_pass(cl_rename(".gitted", ".git")); + + /* If we have `gitattributes`, rename to `.gitattributes`. This may + * be necessary if we don't want the attributes to be applied in the + * libgit2 repo, but just during testing. + */ + if (p_access("gitattributes", F_OK) == 0) + cl_git_pass(cl_rename("gitattributes", ".gitattributes")); + + /* As with `gitattributes`, we may need `gitignore` just for testing. */ + if (p_access("gitignore", F_OK) == 0) + cl_git_pass(cl_rename("gitignore", ".gitignore")); + + cl_git_pass(p_chdir("..")); + + /* Now open the sandbox repository and make it available for tests */ + cl_git_pass(git_repository_open(&_cl_repo, sandbox)); + + /* Adjust configs after copying to new filesystem */ + cl_git_pass(git_repository_reinit_filesystem(_cl_repo, 0)); + + return _cl_repo; +} + +git_repository *cl_git_sandbox_reopen(void) +{ + if (_cl_repo) { + git_repository_free(_cl_repo); + _cl_repo = NULL; + + cl_git_pass(git_repository_open(&_cl_repo, _cl_sandbox)); + } + + return _cl_repo; +} + +void cl_git_sandbox_cleanup(void) +{ + if (_cl_repo) { + git_repository_free(_cl_repo); + _cl_repo = NULL; + } + if (_cl_sandbox) { + cl_fixture_cleanup(_cl_sandbox); + _cl_sandbox = NULL; + } +} + +bool cl_toggle_filemode(const char *filename) +{ + struct stat st1, st2; + + cl_must_pass(p_stat(filename, &st1)); + cl_must_pass(p_chmod(filename, st1.st_mode ^ 0100)); + cl_must_pass(p_stat(filename, &st2)); + + return (st1.st_mode != st2.st_mode); +} + +bool cl_is_chmod_supported(void) +{ + static int _is_supported = -1; + + if (_is_supported < 0) { + cl_git_mkfile("filemode.t", "Test if filemode can be modified"); + _is_supported = cl_toggle_filemode("filemode.t"); + cl_must_pass(p_unlink("filemode.t")); + } + + return _is_supported; +} + +const char* cl_git_fixture_url(const char *fixturename) +{ + return cl_git_path_url(cl_fixture(fixturename)); +} + +const char* cl_git_path_url(const char *path) +{ + static char url[4096]; + + const char *in_buf; + git_buf path_buf = GIT_BUF_INIT; + git_buf url_buf = GIT_BUF_INIT; + + cl_git_pass(git_path_prettify_dir(&path_buf, path, NULL)); + cl_git_pass(git_buf_puts(&url_buf, "file://")); + +#ifdef GIT_WIN32 + /* + * A FILE uri matches the following format: file://[host]/path + * where "host" can be empty and "path" is an absolute path to the resource. + * + * In this test, no hostname is used, but we have to ensure the leading triple slashes: + * + * *nix: file:///usr/home/... + * Windows: file:///C:/Users/... + */ + cl_git_pass(git_buf_putc(&url_buf, '/')); +#endif + + in_buf = git_buf_cstr(&path_buf); + + /* + * A very hacky Url encoding that only takes care of escaping the spaces + */ + while (*in_buf) { + if (*in_buf == ' ') + cl_git_pass(git_buf_puts(&url_buf, "%20")); + else + cl_git_pass(git_buf_putc(&url_buf, *in_buf)); + + in_buf++; + } + + strncpy(url, git_buf_cstr(&url_buf), 4096); + git_buf_free(&url_buf); + git_buf_free(&path_buf); + return url; +} + +typedef struct { + const char *filename; + size_t filename_len; +} remove_data; + +static int remove_placeholders_recurs(void *_data, git_buf *path) +{ + remove_data *data = (remove_data *)_data; + size_t pathlen; + + if (git_path_isdir(path->ptr) == true) + return git_path_direach(path, 0, remove_placeholders_recurs, data); + + pathlen = path->size; + + if (pathlen < data->filename_len) + return 0; + + /* if path ends in '/'+filename (or equals filename) */ + if (!strcmp(data->filename, path->ptr + pathlen - data->filename_len) && + (pathlen == data->filename_len || + path->ptr[pathlen - data->filename_len - 1] == '/')) + return p_unlink(path->ptr); + + return 0; +} + +int cl_git_remove_placeholders(const char *directory_path, const char *filename) +{ + int error; + remove_data data; + git_buf buffer = GIT_BUF_INIT; + + if (git_path_isdir(directory_path) == false) + return -1; + + if (git_buf_sets(&buffer, directory_path) < 0) + return -1; + + data.filename = filename; + data.filename_len = strlen(filename); + + error = remove_placeholders_recurs(&data, &buffer); + + git_buf_free(&buffer); + + return error; +} + +#define CL_COMMIT_NAME "Libgit2 Tester" +#define CL_COMMIT_EMAIL "libgit2-test@github.com" +#define CL_COMMIT_MSG "Test commit of tree " + +void cl_repo_commit_from_index( + git_oid *out, + git_repository *repo, + git_signature *sig, + git_time_t time, + const char *msg) +{ + git_index *index; + git_oid commit_id, tree_id; + git_object *parent = NULL; + git_reference *ref = NULL; + git_tree *tree = NULL; + char buf[128]; + int free_sig = (sig == NULL); + + /* it is fine if looking up HEAD fails - we make this the first commit */ + git_revparse_ext(&parent, &ref, repo, "HEAD"); + + /* write the index content as a tree */ + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_write_tree(&tree_id, index)); + cl_git_pass(git_index_write(index)); + git_index_free(index); + + cl_git_pass(git_tree_lookup(&tree, repo, &tree_id)); + + if (sig) + cl_assert(sig->name && sig->email); + else if (!time) + cl_git_pass(git_signature_now(&sig, CL_COMMIT_NAME, CL_COMMIT_EMAIL)); + else + cl_git_pass(git_signature_new( + &sig, CL_COMMIT_NAME, CL_COMMIT_EMAIL, time, 0)); + + if (!msg) { + strcpy(buf, CL_COMMIT_MSG); + git_oid_tostr(buf + strlen(CL_COMMIT_MSG), + sizeof(buf) - strlen(CL_COMMIT_MSG), &tree_id); + msg = buf; + } + + cl_git_pass(git_commit_create_v( + &commit_id, repo, ref ? git_reference_name(ref) : "HEAD", + sig, sig, NULL, msg, tree, parent ? 1 : 0, parent)); + + if (out) + git_oid_cpy(out, &commit_id); + + git_object_free(parent); + git_reference_free(ref); + if (free_sig) + git_signature_free(sig); + git_tree_free(tree); +} + +void cl_repo_set_bool(git_repository *repo, const char *cfg, int value) +{ + git_config *config; + cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_config_set_bool(config, cfg, value != 0)); + git_config_free(config); +} + +int cl_repo_get_bool(git_repository *repo, const char *cfg) +{ + int val = 0; + git_config *config; + cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_config_get_bool(&val, config, cfg));; + git_config_free(config); + return val; +} + +/* this is essentially the code from git__unescape modified slightly */ +static size_t strip_cr_from_buf(char *start, size_t len) +{ + char *scan, *trail, *end = start + len; + + for (scan = trail = start; scan < end; trail++, scan++) { + while (*scan == '\r') + scan++; /* skip '\r' */ + + if (trail != scan) + *trail = *scan; + } + + *trail = '\0'; + + return (trail - start); +} + +void clar__assert_equal_file( + const char *expected_data, + size_t expected_bytes, + int ignore_cr, + const char *path, + const char *file, + int line) +{ + char buf[4000]; + ssize_t bytes, total_bytes = 0; + int fd = p_open(path, O_RDONLY | O_BINARY); + cl_assert(fd >= 0); + + if (expected_data && !expected_bytes) + expected_bytes = strlen(expected_data); + + while ((bytes = p_read(fd, buf, sizeof(buf))) != 0) { + clar__assert( + bytes > 0, file, line, "error reading from file", path, 1); + + if (ignore_cr) + bytes = strip_cr_from_buf(buf, bytes); + + if (memcmp(expected_data, buf, bytes) != 0) { + int pos; + for (pos = 0; pos < bytes && expected_data[pos] == buf[pos]; ++pos) + /* find differing byte offset */; + p_snprintf( + buf, sizeof(buf), "file content mismatch at byte %d", + (int)(total_bytes + pos)); + clar__fail(file, line, buf, path, 1); + } + + expected_data += bytes; + total_bytes += bytes; + } + + p_close(fd); + + clar__assert(!bytes, file, line, "error reading from file", path, 1); + clar__assert_equal(file, line, "mismatched file length", 1, "%"PRIuZ, + (size_t)expected_bytes, (size_t)total_bytes); +} diff --git a/tests/clar_libgit2.h b/tests/clar_libgit2.h new file mode 100644 index 000000000..b9ef5627e --- /dev/null +++ b/tests/clar_libgit2.h @@ -0,0 +1,119 @@ +#ifndef __CLAR_LIBGIT2__ +#define __CLAR_LIBGIT2__ + +#include "clar.h" +#include +#include "common.h" + +/** + * Replace for `clar_must_pass` that passes the last library error as the + * test failure message. + * + * Use this wrapper around all `git_` library calls that return error codes! + */ +#define cl_git_pass(expr) do { \ + int _lg2_error; \ + giterr_clear(); \ + if ((_lg2_error = (expr)) != 0) \ + cl_git_report_failure(_lg2_error, __FILE__, __LINE__, "Function call failed: " #expr); \ + } while (0) + +/** + * Wrapper for `clar_must_fail` -- this one is + * 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) + +void cl_git_report_failure(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) + +GIT_INLINE(void) clar__assert_in_range( + int lo, int val, int hi, + const char *file, int line, const char *err, int should_abort) +{ + if (lo > val || hi < val) { + char buf[128]; + snprintf(buf, sizeof(buf), "%d not in [%d,%d]", val, lo, hi); + clar__fail(file, line, err, buf, should_abort); + } +} + +#define cl_assert_equal_sz(sz1,sz2) do { \ + size_t __sz1 = (size_t)(sz1), __sz2 = (size_t)(sz2); \ + clar__assert_equal(__FILE__,__LINE__,#sz1 " != " #sz2, 1, "%"PRIuZ, __sz1, __sz2); \ +} while (0) + +#define cl_assert_in_range(L,V,H) \ + clar__assert_in_range((L),(V),(H),__FILE__,__LINE__,"Range check: " #V " in [" #L "," #H "]", 1) + +#define cl_assert_equal_file(DATA,SIZE,PATH) \ + clar__assert_equal_file(DATA,SIZE,0,PATH,__FILE__,(int)__LINE__) + +#define cl_assert_equal_file_ignore_cr(DATA,SIZE,PATH) \ + clar__assert_equal_file(DATA,SIZE,1,PATH,__FILE__,(int)__LINE__) + +void clar__assert_equal_file( + const char *expected_data, + size_t expected_size, + int ignore_cr, + const char *path, + const char *file, + int line); + +/* + * Some utility macros for building long strings + */ +#define REP4(STR) STR STR STR STR +#define REP15(STR) REP4(STR) REP4(STR) REP4(STR) STR STR STR +#define REP16(STR) REP4(REP4(STR)) +#define REP256(STR) REP16(REP16(STR)) +#define REP1024(STR) REP4(REP256(STR)) + +/* Write the contents of a buffer to disk */ +void cl_git_mkfile(const char *filename, const char *content); +void cl_git_append2file(const char *filename, const char *new_content); +void cl_git_rewritefile(const char *filename, const char *new_content); +void cl_git_write2file(const char *path, const char *data, + size_t datalen, int flags, unsigned int mode); + +bool cl_toggle_filemode(const char *filename); +bool cl_is_chmod_supported(void); + +/* Environment wrappers */ +char *cl_getenv(const char *name); +int cl_setenv(const char *name, const char *value); + +/* Reliable rename */ +int cl_rename(const char *source, const char *dest); + +/* Git sandbox setup helpers */ + +git_repository *cl_git_sandbox_init(const char *sandbox); +void cl_git_sandbox_cleanup(void); +git_repository *cl_git_sandbox_reopen(void); + +/* Local-repo url helpers */ +const char* cl_git_fixture_url(const char *fixturename); +const char* cl_git_path_url(const char *path); + +/* Test repository cleaner */ +int cl_git_remove_placeholders(const char *directory_path, const char *filename); + +/* commit creation helpers */ +void cl_repo_commit_from_index( + git_oid *out, + git_repository *repo, + git_signature *sig, + git_time_t time, + const char *msg); + +/* config setting helpers */ +void cl_repo_set_bool(git_repository *repo, const char *cfg, int value); +int cl_repo_get_bool(git_repository *repo, const char *cfg); + +#endif diff --git a/tests/clone/empty.c b/tests/clone/empty.c new file mode 100644 index 000000000..6d19244cc --- /dev/null +++ b/tests/clone/empty.c @@ -0,0 +1,85 @@ +#include "clar_libgit2.h" + +#include "git2/clone.h" +#include "repository.h" + +static git_clone_options g_options; +static git_repository *g_repo; +static git_repository *g_repo_cloned; + +void test_clone_empty__initialize(void) +{ + git_repository *sandbox = cl_git_sandbox_init("empty_bare.git"); + git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; + cl_git_remove_placeholders(git_repository_path(sandbox), "dummy-marker.txt"); + + g_repo = NULL; + + memset(&g_options, 0, sizeof(git_clone_options)); + g_options.version = GIT_CLONE_OPTIONS_VERSION; + g_options.remote_callbacks = dummy_callbacks; +} + +void test_clone_empty__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void cleanup_repository(void *path) +{ + cl_fixture_cleanup((const char *)path); + + git_repository_free(g_repo_cloned); + g_repo_cloned = NULL; +} + +void test_clone_empty__can_clone_an_empty_local_repo_barely(void) +{ + char *local_name = "refs/heads/master"; + const char *expected_tracked_branch_name = "refs/remotes/origin/master"; + const char *expected_remote_name = "origin"; + char buffer[1024]; + git_reference *ref; + + cl_set_cleanup(&cleanup_repository, "./empty"); + + g_options.bare = true; + cl_git_pass(git_clone(&g_repo_cloned, "./empty_bare.git", "./empty", &g_options)); + + /* Although the HEAD is unborn... */ + cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo_cloned, local_name)); + + /* ...one can still retrieve the name of the remote tracking reference */ + cl_assert_equal_i((int)strlen(expected_tracked_branch_name) + 1, + git_branch_upstream_name(buffer, 1024, g_repo_cloned, local_name)); + + cl_assert_equal_s(expected_tracked_branch_name, buffer); + + /* ...and the name of the remote... */ + cl_assert_equal_i((int)strlen(expected_remote_name) + 1, + git_branch_remote_name(buffer, 1024, g_repo_cloned, expected_tracked_branch_name)); + + cl_assert_equal_s(expected_remote_name, buffer); + + /* ...even when the remote HEAD is unborn as well */ + cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&ref, g_repo_cloned, + expected_tracked_branch_name)); +} + +void test_clone_empty__can_clone_an_empty_local_repo(void) +{ + cl_set_cleanup(&cleanup_repository, "./empty"); + + cl_git_pass(git_clone(&g_repo_cloned, "./empty_bare.git", "./empty", &g_options)); +} + +void test_clone_empty__can_clone_an_empty_standard_repo(void) +{ + cl_git_sandbox_cleanup(); + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_remove_placeholders(git_repository_path(g_repo), "dummy-marker.txt"); + + cl_set_cleanup(&cleanup_repository, "./empty"); + + cl_git_pass(git_clone(&g_repo_cloned, "./empty_standard_repo", "./empty", &g_options)); +} diff --git a/tests/clone/nonetwork.c b/tests/clone/nonetwork.c new file mode 100644 index 000000000..a286e2a8f --- /dev/null +++ b/tests/clone/nonetwork.c @@ -0,0 +1,179 @@ +#include "clar_libgit2.h" + +#include "git2/clone.h" +#include "remote.h" +#include "fileops.h" +#include "repository.h" + +#define LIVE_REPO_URL "git://github.com/libgit2/TestGitRepository" + +static git_clone_options g_options; +static git_repository *g_repo; +static git_reference* g_ref; +static git_remote* g_remote; + +void test_clone_nonetwork__initialize(void) +{ + git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT; + git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; + + g_repo = NULL; + + memset(&g_options, 0, sizeof(git_clone_options)); + g_options.version = GIT_CLONE_OPTIONS_VERSION; + g_options.checkout_opts = dummy_opts; + g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + g_options.remote_callbacks = dummy_callbacks; +} + +void test_clone_nonetwork__cleanup(void) +{ + if (g_repo) { + git_repository_free(g_repo); + g_repo = NULL; + } + + if (g_ref) { + git_reference_free(g_ref); + g_ref = NULL; + } + + if (g_remote) { + git_remote_free(g_remote); + g_remote = NULL; + } + + cl_fixture_cleanup("./foo"); +} + +void test_clone_nonetwork__bad_urls(void) +{ + /* Clone should clean up the mess if the URL isn't a git repository */ + cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); + cl_assert(!git_path_exists("./foo")); + g_options.bare = true; + cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); + cl_assert(!git_path_exists("./foo")); + + cl_git_fail(git_clone(&g_repo, "git://example.com:asdf", "./foo", &g_options)); + cl_git_fail(git_clone(&g_repo, "https://example.com:asdf/foo", "./foo", &g_options)); + cl_git_fail(git_clone(&g_repo, "git://github.com/git://github.com/foo/bar.git.git", + "./foo", &g_options)); + cl_git_fail(git_clone(&g_repo, "arrbee:my/bad:password@github.com:1111/strange:words.git", + "./foo", &g_options)); +} + +void test_clone_nonetwork__do_not_clean_existing_directory(void) +{ + /* Clone should not remove the directory if it already exists, but + * Should clean up entries it creates. */ + p_mkdir("./foo", GIT_DIR_MODE); + cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); + cl_assert(git_path_is_empty_dir("./foo")); + + /* Try again with a bare repository. */ + g_options.bare = true; + cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", &g_options)); + cl_assert(git_path_is_empty_dir("./foo")); +} + +void test_clone_nonetwork__local(void) +{ + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); +} + +void test_clone_nonetwork__local_absolute_path(void) +{ + const char *local_src; + local_src = cl_fixture("testrepo.git"); + cl_git_pass(git_clone(&g_repo, local_src, "./foo", &g_options)); +} + +void test_clone_nonetwork__local_bare(void) +{ + g_options.bare = true; + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); +} + +void test_clone_nonetwork__fail_when_the_target_is_a_file(void) +{ + cl_git_mkfile("./foo", "Bar!"); + cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); +} + +void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(void) +{ + p_mkdir("./foo", GIT_DIR_MODE); + cl_git_mkfile("./foo/bar", "Baz!"); + cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); +} + +void test_clone_nonetwork__custom_origin_name(void) +{ + g_options.remote_name = "my_origin"; + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); + + cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin")); +} + +void test_clone_nonetwork__defaults(void) +{ + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", NULL)); + cl_assert(g_repo); + cl_git_pass(git_remote_load(&g_remote, g_repo, "origin")); +} + +void test_clone_nonetwork__cope_with_already_existing_directory(void) +{ + p_mkdir("./foo", GIT_DIR_MODE); + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); +} + +void test_clone_nonetwork__can_prevent_the_checkout_of_a_standard_repo(void) +{ + git_buf path = GIT_BUF_INIT; + + g_options.checkout_opts.checkout_strategy = 0; + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); + cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&path))); + + git_buf_free(&path); +} + +void test_clone_nonetwork__can_checkout_given_branch(void) +{ + g_options.checkout_branch = "test"; + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); + + cl_assert_equal_i(0, git_repository_head_unborn(g_repo)); + + cl_git_pass(git_repository_head(&g_ref, g_repo)); + cl_assert_equal_s(git_reference_name(g_ref), "refs/heads/test"); +} + +void test_clone_nonetwork__can_detached_head(void) +{ + git_object *obj; + git_repository *cloned; + git_reference *cloned_head; + + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); + + cl_git_pass(git_revparse_single(&obj, g_repo, "master~1")); + cl_git_pass(git_repository_set_head_detached(g_repo, git_object_id(obj))); + + cl_git_pass(git_clone(&cloned, "./foo", "./foo1", &g_options)); + + cl_assert(git_repository_head_detached(cloned)); + + cl_git_pass(git_repository_head(&cloned_head, cloned)); + cl_assert(!git_oid_cmp(git_object_id(obj), git_reference_target(cloned_head))); + + git_object_free(obj); + git_reference_free(cloned_head); + git_repository_free(cloned); + + cl_fixture_cleanup("./foo1"); +} diff --git a/tests/commit/commit.c b/tests/commit/commit.c new file mode 100644 index 000000000..8f071ff94 --- /dev/null +++ b/tests/commit/commit.c @@ -0,0 +1,46 @@ +#include "clar_libgit2.h" + +static git_repository *_repo; + +void test_commit_commit__initialize(void) +{ + cl_fixture_sandbox("testrepo.git"); + cl_git_pass(git_repository_open(&_repo, "testrepo.git")); +} + +void test_commit_commit__cleanup(void) +{ + git_repository_free(_repo); + _repo = NULL; + + cl_fixture_cleanup("testrepo.git"); +} + +void test_commit_commit__create_unexisting_update_ref(void) +{ + git_oid oid; + git_tree *tree; + git_commit *commit; + git_signature *s; + git_reference *ref; + + git_oid_fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + cl_git_pass(git_commit_lookup(&commit, _repo, &oid)); + + git_oid_fromstr(&oid, "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"); + cl_git_pass(git_tree_lookup(&tree, _repo, &oid)); + + cl_git_pass(git_signature_now(&s, "alice", "alice@example.com")); + + cl_git_fail(git_reference_lookup(&ref, _repo, "refs/heads/foo/bar")); + cl_git_pass(git_commit_create(&oid, _repo, "refs/heads/foo/bar", s, s, + NULL, "some msg", tree, 1, (const git_commit **) &commit)); + + cl_git_pass(git_reference_lookup(&ref, _repo, "refs/heads/foo/bar")); + cl_assert(!git_oid_cmp(&oid, git_reference_target(ref))); + + git_tree_free(tree); + git_commit_free(commit); + git_signature_free(s); + git_reference_free(ref); +} diff --git a/tests/commit/parent.c b/tests/commit/parent.c new file mode 100644 index 000000000..18ce0bba6 --- /dev/null +++ b/tests/commit/parent.c @@ -0,0 +1,60 @@ +#include "clar_libgit2.h" + +static git_repository *_repo; +static git_commit *commit; + +void test_commit_parent__initialize(void) +{ + git_oid oid; + + cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); + + git_oid_fromstr(&oid, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + cl_git_pass(git_commit_lookup(&commit, _repo, &oid)); +} + +void test_commit_parent__cleanup(void) +{ + git_commit_free(commit); + commit = NULL; + + git_repository_free(_repo); + _repo = NULL; +} + +static void assert_nth_gen_parent(unsigned int gen, const char *expected_oid) +{ + git_commit *parent = NULL; + int error; + + error = git_commit_nth_gen_ancestor(&parent, commit, gen); + + if (expected_oid != NULL) { + cl_assert_equal_i(0, error); + cl_assert_equal_i(0, git_oid_streq(git_commit_id(parent), expected_oid)); + } else + cl_assert_equal_i(GIT_ENOTFOUND, error); + + git_commit_free(parent); +} + +/* + * $ git show be35~0 + * commit be3563ae3f795b2b4353bcce3a527ad0a4f7f644 + * + * $ git show be35~1 + * commit 9fd738e8f7967c078dceed8190330fc8648ee56a + * + * $ git show be35~3 + * commit 5b5b025afb0b4c913b4c338a42934a3863bf3644 + * + * $ git show be35~42 + * fatal: ambiguous argument 'be35~42': unknown revision or path not in the working tree. + */ +void test_commit_parent__can_retrieve_nth_generation_parent(void) +{ + assert_nth_gen_parent(0, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + assert_nth_gen_parent(1, "9fd738e8f7967c078dceed8190330fc8648ee56a"); + assert_nth_gen_parent(3, "5b5b025afb0b4c913b4c338a42934a3863bf3644"); + assert_nth_gen_parent(42, NULL); +} diff --git a/tests/commit/parse.c b/tests/commit/parse.c new file mode 100644 index 000000000..41e162440 --- /dev/null +++ b/tests/commit/parse.c @@ -0,0 +1,413 @@ +#include "clar_libgit2.h" +#include +#include "commit.h" +#include "signature.h" + +// Fixture setup +static git_repository *g_repo; +void test_commit_parse__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} +void test_commit_parse__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + + +// Header parsing +typedef struct { + const char *line; + const char *header; +} parse_test_case; + +static parse_test_case passing_header_cases[] = { + { "parent 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "parent " }, + { "tree 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree " }, + { "random_heading 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "random_heading " }, + { "stuck_heading05452d6349abcd67aa396dfb28660d765d8b2a36\n", "stuck_heading" }, + { "tree 5F4BEFFC0759261D015AA63A3A85613FF2F235DE\n", "tree " }, + { "tree 1A669B8AB81B5EB7D9DB69562D34952A38A9B504\n", "tree " }, + { "tree 5B20DCC6110FCC75D31C6CEDEBD7F43ECA65B503\n", "tree " }, + { "tree 173E7BF00EA5C33447E99E6C1255954A13026BE4\n", "tree " }, + { NULL, NULL } +}; + +static parse_test_case failing_header_cases[] = { + { "parent 05452d6349abcd67aa396dfb28660d765d8b2a36", "parent " }, + { "05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree " }, + { "parent05452d6349abcd67aa396dfb28660d765d8b2a6a\n", "parent " }, + { "parent 05452d6349abcd67aa396dfb280d765d8b2a6\n", "parent " }, + { "tree 05452d6349abcd67aa396dfb28660d765d8b2a36\n", "tree " }, + { "parent 0545xd6349abcd67aa396dfb28660d765d8b2a36\n", "parent " }, + { "parent 0545xd6349abcd67aa396dfb28660d765d8b2a36FF\n", "parent " }, + { "", "tree " }, + { "", "" }, + { NULL, NULL } +}; + +void test_commit_parse__header(void) +{ + git_oid oid; + + parse_test_case *testcase; + for (testcase = passing_header_cases; testcase->line != NULL; testcase++) + { + const char *line = testcase->line; + const char *line_end = line + strlen(line); + + cl_git_pass(git_oid__parse(&oid, &line, line_end, testcase->header)); + cl_assert(line == line_end); + } + + for (testcase = failing_header_cases; testcase->line != NULL; testcase++) + { + const char *line = testcase->line; + const char *line_end = line + strlen(line); + + cl_git_fail(git_oid__parse(&oid, &line, line_end, testcase->header)); + } +} + + +// Signature parsing +typedef struct { + const char *string; + const char *header; + const char *name; + const char *email; + git_time_t time; + int offset; +} passing_signature_test_case; + +passing_signature_test_case passing_signature_cases[] = { + {"author Vicent Marti 12345 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 12345, 0}, + {"author Vicent Marti <> 12345 \n", "author ", "Vicent Marti", "", 12345, 0}, + {"author Vicent Marti 231301 +1020\n", "author ", "Vicent Marti", "tanoku@gmail.com", 231301, 620}, + {"author Vicent Marti with an outrageously long name which will probably overflow the buffer 12345 \n", "author ", "Vicent Marti with an outrageously long name which will probably overflow the buffer", "tanoku@gmail.com", 12345, 0}, + {"author Vicent Marti 12345 \n", "author ", "Vicent Marti", "tanokuwithaveryveryverylongemailwhichwillprobablyvoverflowtheemailbuffer@gmail.com", 12345, 0}, + {"committer Vicent Marti 123456 +0000 \n", "committer ", "Vicent Marti", "tanoku@gmail.com", 123456, 0}, + {"committer Vicent Marti 123456 +0100 \n", "committer ", "Vicent Marti", "tanoku@gmail.com", 123456, 60}, + {"committer Vicent Marti 123456 -0100 \n", "committer ", "Vicent Marti", "tanoku@gmail.com", 123456, -60}, + // Parse a signature without an author field + {"committer 123456 -0100 \n", "committer ", "", "tanoku@gmail.com", 123456, -60}, + // Parse a signature without an author field + {"committer 123456 -0100 \n", "committer ", "", "tanoku@gmail.com", 123456, -60}, + // Parse a signature with an empty author field + {"committer 123456 -0100 \n", "committer ", "", "tanoku@gmail.com", 123456, -60}, + // Parse a signature with an empty email field + {"committer Vicent Marti <> 123456 -0100 \n", "committer ", "Vicent Marti", "", 123456, -60}, + // Parse a signature with an empty email field + {"committer Vicent Marti < > 123456 -0100 \n", "committer ", "Vicent Marti", "", 123456, -60}, + // Parse a signature with empty name and email + {"committer <> 123456 -0100 \n", "committer ", "", "", 123456, -60}, + // Parse a signature with empty name and email + {"committer <> 123456 -0100 \n", "committer ", "", "", 123456, -60}, + // Parse a signature with empty name and email + {"committer < > 123456 -0100 \n", "committer ", "", "", 123456, -60}, + // Parse an obviously invalid signature + {"committer foo<@bar> 123456 -0100 \n", "committer ", "foo", "@bar", 123456, -60}, + // Parse an obviously invalid signature + {"committer foo<@bar> 123456 -0100 \n", "committer ", "foo", "@bar", 123456, -60}, + // Parse an obviously invalid signature + {"committer <>\n", "committer ", "", "", 0, 0}, + {"committer Vicent Marti 123456 -1500 \n", "committer ", "Vicent Marti", "tanoku@gmail.com", 123456, 0}, + {"committer Vicent Marti 123456 +0163 \n", "committer ", "Vicent Marti", "tanoku@gmail.com", 123456, 0}, + {"author Vicent Marti \n", "author ", "Vicent Marti", "tanoku@gmail.com", 0, 0}, + /* a variety of dates */ + {"author Vicent Marti 0 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 0, 0}, + {"author Vicent Marti 1234567890 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 1234567890, 0}, + {"author Vicent Marti 2147483647 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 0x7fffffff, 0}, + {"author Vicent Marti 4294967295 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 0xffffffff, 0}, + {"author Vicent Marti 4294967296 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 4294967296, 0}, + {"author Vicent Marti 8589934592 \n", "author ", "Vicent Marti", "tanoku@gmail.com", 8589934592, 0}, + + {NULL,NULL,NULL,NULL,0,0} +}; + +typedef struct { + const char *string; + const char *header; +} failing_signature_test_case; + +failing_signature_test_case failing_signature_cases[] = { + {"committer Vicent Marti tanoku@gmail.com> 123456 -0100 \n", "committer "}, + {"author Vicent Marti 12345 \n", "author "}, + {"author Vicent Marti 12345 \n", "committer "}, + {"author Vicent Marti 12345 \n", "author "}, + {"author Vicent Marti <\n", "committer "}, + {"author ", "author "}, + {NULL, NULL,} +}; + +void test_commit_parse__signature(void) +{ + passing_signature_test_case *passcase; + failing_signature_test_case *failcase; + + for (passcase = passing_signature_cases; passcase->string != NULL; passcase++) + { + const char *str = passcase->string; + size_t len = strlen(passcase->string); + struct git_signature person = {0}; + + cl_git_pass(git_signature__parse(&person, &str, str + len, passcase->header, '\n')); + cl_assert_equal_s(passcase->name, person.name); + cl_assert_equal_s(passcase->email, person.email); + cl_assert_equal_i((int)passcase->time, (int)person.when.time); + cl_assert_equal_i(passcase->offset, person.when.offset); + git__free(person.name); git__free(person.email); + } + + for (failcase = failing_signature_cases; failcase->string != NULL; failcase++) + { + const char *str = failcase->string; + size_t len = strlen(failcase->string); + git_signature person = {0}; + cl_git_fail(git_signature__parse(&person, &str, str + len, failcase->header, '\n')); + git__free(person.name); git__free(person.email); + } +} + + + +static char *failing_commit_cases[] = { +// empty commit +"", +// random garbage +"asd97sa9du902e9a0jdsuusad09as9du098709aweu8987sd\n", +// broken endlines 1 +"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\r\n\ +parent 05452d6349abcd67aa396dfb28660d765d8b2a36\r\n\ +author Vicent Marti 1273848544 +0200\r\n\ +committer Vicent Marti 1273848544 +0200\r\n\ +\r\n\ +a test commit with broken endlines\r\n", +// broken endlines 2 +"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\ +parent 05452d6349abcd67aa396dfb28660d765d8b2a36\ +author Vicent Marti 1273848544 +0200\ +committer Vicent Marti 1273848544 +0200\ +\ +another test commit with broken endlines", +// starting endlines +"\ntree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\ +parent 05452d6349abcd67aa396dfb28660d765d8b2a36\n\ +author Vicent Marti 1273848544 +0200\n\ +committer Vicent Marti 1273848544 +0200\n\ +\n\ +a test commit with a starting endline\n", +// corrupted commit 1 +"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\ +parent 05452d6349abcd67aa396df", +// corrupted commit 2 +"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\ +parent ", +// corrupted commit 3 +"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\ +parent ", +// corrupted commit 4 +"tree f6c0dad3c7b3481caa9d73db21f91964894a945b\n\ +par", +}; + + +static char *passing_commit_cases[] = { +// simple commit with no message +"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ +author Vicent Marti 1273848544 +0200\n\ +committer Vicent Marti 1273848544 +0200\n\ +\n", +// simple commit, no parent +"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ +author Vicent Marti 1273848544 +0200\n\ +committer Vicent Marti 1273848544 +0200\n\ +\n\ +a simple commit which works\n", +// simple commit, no parent, no newline in message +"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ +author Vicent Marti 1273848544 +0200\n\ +committer Vicent Marti 1273848544 +0200\n\ +\n\ +a simple commit which works", +// simple commit, 1 parent +"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ +parent e90810b8df3e80c413d903f631643c716887138d\n\ +author Vicent Marti 1273848544 +0200\n\ +committer Vicent Marti 1273848544 +0200\n\ +\n\ +a simple commit which works\n", +/* simple commit with GPG signature */ +"tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\ +parent 34734e478d6cf50c27c9d69026d93974d052c454\n\ +author Ben Burkert 1358451456 -0800\n\ +committer Ben Burkert 1358451456 -0800\n\ +gpgsig -----BEGIN PGP SIGNATURE-----\n\ + Version: GnuPG v1.4.12 (Darwin)\n\ + \n\ + iQIcBAABAgAGBQJQ+FMIAAoJEH+LfPdZDSs1e3EQAJMjhqjWF+WkGLHju7pTw2al\n\ + o6IoMAhv0Z/LHlWhzBd9e7JeCnanRt12bAU7yvYp9+Z+z+dbwqLwDoFp8LVuigl8\n\ + JGLcnwiUW3rSvhjdCp9irdb4+bhKUnKUzSdsR2CK4/hC0N2i/HOvMYX+BRsvqweq\n\ + AsAkA6dAWh+gAfedrBUkCTGhlNYoetjdakWqlGL1TiKAefEZrtA1TpPkGn92vbLq\n\ + SphFRUY9hVn1ZBWrT3hEpvAIcZag3rTOiRVT1X1flj8B2vGCEr3RrcwOIZikpdaW\n\ + who/X3xh/DGbI2RbuxmmJpxxP/8dsVchRJJzBwG+yhwU/iN3MlV2c5D69tls/Dok\n\ + 6VbyU4lm/ae0y3yR83D9dUlkycOnmmlBAHKIZ9qUts9X7mWJf0+yy2QxJVpjaTGG\n\ + cmnQKKPeNIhGJk2ENnnnzjEve7L7YJQF6itbx5VCOcsGh3Ocb3YR7DMdWjt7f8pu\n\ + c6j+q1rP7EpE2afUN/geSlp5i3x8aXZPDj67jImbVCE/Q1X9voCtyzGJH7MXR0N9\n\ + ZpRF8yzveRfMH8bwAJjSOGAFF5XkcR/RNY95o+J+QcgBLdX48h+ZdNmUf6jqlu3J\n\ + 7KmTXXQcOVpN6dD3CmRFsbjq+x6RHwa8u1iGn+oIkX908r97ckfB/kHKH7ZdXIJc\n\ + cpxtDQQMGYFpXK/71stq\n\ + =ozeK\n\ + -----END PGP SIGNATURE-----\n\ +\n\ +a simple commit which works\n", +}; + +static int parse_commit(git_commit **out, const char *buffer) +{ + git_commit *commit; + git_odb_object fake_odb_object; + int error; + + commit = (git_commit*)git__malloc(sizeof(git_commit)); + memset(commit, 0x0, sizeof(git_commit)); + commit->object.repo = g_repo; + + memset(&fake_odb_object, 0x0, sizeof(git_odb_object)); + fake_odb_object.buffer = (char *)buffer; + fake_odb_object.cached.size = strlen(fake_odb_object.buffer); + + error = git_commit__parse(commit, &fake_odb_object); + + *out = commit; + return error; +} + +void test_commit_parse__entire_commit(void) +{ + const int failing_commit_count = ARRAY_SIZE(failing_commit_cases); + const int passing_commit_count = ARRAY_SIZE(passing_commit_cases); + int i; + git_commit *commit; + + for (i = 0; i < failing_commit_count; ++i) { + cl_git_fail(parse_commit(&commit, failing_commit_cases[i])); + git_commit__free(commit); + } + + for (i = 0; i < passing_commit_count; ++i) { + cl_git_pass(parse_commit(&commit, passing_commit_cases[i])); + + if (!i) + cl_assert_equal_s("", git_commit_message(commit)); + else + cl_assert(git__prefixcmp( + git_commit_message(commit), "a simple commit which works") == 0); + + git_commit__free(commit); + } +} + + +// query the details on a parsed commit +void test_commit_parse__details0(void) { + static const char *commit_ids[] = { + "a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */ + "9fd738e8f7967c078dceed8190330fc8648ee56a", /* 1 */ + "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", /* 2 */ + "c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */ + "8496071c1b46c854b31185ea97743be6a8774479", /* 4 */ + "5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */ + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", /* 6 */ + }; + const size_t commit_count = sizeof(commit_ids) / sizeof(const char *); + unsigned int i; + + for (i = 0; i < commit_count; ++i) { + git_oid id; + git_commit *commit; + + const git_signature *author, *committer; + const char *message; + git_time_t commit_time; + unsigned int parents, p; + git_commit *parent = NULL, *old_parent = NULL; + + git_oid_fromstr(&id, commit_ids[i]); + + cl_git_pass(git_commit_lookup(&commit, g_repo, &id)); + + message = git_commit_message(commit); + author = git_commit_author(commit); + committer = git_commit_committer(commit); + commit_time = git_commit_time(commit); + parents = git_commit_parentcount(commit); + + cl_assert_equal_s("Scott Chacon", author->name); + cl_assert_equal_s("schacon@gmail.com", author->email); + cl_assert_equal_s("Scott Chacon", committer->name); + cl_assert_equal_s("schacon@gmail.com", committer->email); + cl_assert(message != NULL); + cl_assert(commit_time > 0); + cl_assert(parents <= 2); + for (p = 0;p < parents;p++) { + if (old_parent != NULL) + git_commit_free(old_parent); + + old_parent = parent; + cl_git_pass(git_commit_parent(&parent, commit, p)); + cl_assert(parent != NULL); + cl_assert(git_commit_author(parent) != NULL); // is it really a commit? + } + git_commit_free(old_parent); + git_commit_free(parent); + + cl_git_fail(git_commit_parent(&parent, commit, parents)); + git_commit_free(commit); + } +} + +void test_commit_parse__leading_lf(void) +{ + git_commit *commit; + const char *buffer = +"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ +parent e90810b8df3e80c413d903f631643c716887138d\n\ +author Vicent Marti 1273848544 +0200\n\ +committer Vicent Marti 1273848544 +0200\n\ +\n\ +\n\ +\n\ +This commit has a few LF at the start of the commit message"; + const char *message = +"This commit has a few LF at the start of the commit message"; + const char *raw_message = +"\n\ +\n\ +This commit has a few LF at the start of the commit message"; + cl_git_pass(parse_commit(&commit, buffer)); + cl_assert_equal_s(message, git_commit_message(commit)); + cl_assert_equal_s(raw_message, git_commit_message_raw(commit)); + git_commit__free(commit); +} + +void test_commit_parse__only_lf(void) +{ + git_commit *commit; + const char *buffer = +"tree 1810dff58d8a660512d4832e740f692884338ccd\n\ +parent e90810b8df3e80c413d903f631643c716887138d\n\ +author Vicent Marti 1273848544 +0200\n\ +committer Vicent Marti 1273848544 +0200\n\ +\n\ +\n\ +\n"; + const char *message = ""; + const char *raw_message = "\n\n"; + + cl_git_pass(parse_commit(&commit, buffer)); + cl_assert_equal_s(message, git_commit_message(commit)); + cl_assert_equal_s(raw_message, git_commit_message_raw(commit)); + git_commit__free(commit); +} diff --git a/tests/commit/signature.c b/tests/commit/signature.c new file mode 100644 index 000000000..e9dcfab41 --- /dev/null +++ b/tests/commit/signature.c @@ -0,0 +1,81 @@ +#include "clar_libgit2.h" + +static int try_build_signature(const char *name, const char *email, git_time_t time, int offset) +{ + git_signature *sign; + int error = 0; + + if ((error = git_signature_new(&sign, name, email, time, offset)) < 0) + return error; + + git_signature_free((git_signature *)sign); + + return error; +} + +static void assert_name_and_email( + const char *expected_name, + const char *expected_email, + const char *name, + const char *email) +{ + git_signature *sign; + + cl_git_pass(git_signature_new(&sign, name, email, 1234567890, 60)); + cl_assert_equal_s(expected_name, sign->name); + cl_assert_equal_s(expected_email, sign->email); + + git_signature_free(sign); +} + +void test_commit_signature__leading_and_trailing_spaces_are_trimmed(void) +{ + assert_name_and_email("nulltoken", "emeric.fermas@gmail.com", " nulltoken ", " emeric.fermas@gmail.com "); + assert_name_and_email("nulltoken", "emeric.fermas@gmail.com", " nulltoken ", " emeric.fermas@gmail.com \n"); + assert_name_and_email("nulltoken", "emeric.fermas@gmail.com", " \t nulltoken \n", " \n emeric.fermas@gmail.com \n"); +} + +void test_commit_signature__angle_brackets_in_names_are_not_supported(void) +{ + cl_git_fail(try_build_signature("Haack", "phil@haack", 1234567890, 60)); + cl_git_fail(try_build_signature("", "phil@haack", 1234567890, 60)); +} + +void test_commit_signature__angle_brackets_in_email_are_not_supported(void) +{ + cl_git_fail(try_build_signature("Phil Haack", ">phil@haack", 1234567890, 60)); + cl_git_fail(try_build_signature("Phil Haack", "phil@>haack", 1234567890, 60)); + cl_git_fail(try_build_signature("Phil Haack", "", 1234567890, 60)); +} + +void test_commit_signature__create_empties(void) +{ + // can not create a signature with empty name or email + cl_git_pass(try_build_signature("nulltoken", "emeric.fermas@gmail.com", 1234567890, 60)); + + cl_git_fail(try_build_signature("", "emeric.fermas@gmail.com", 1234567890, 60)); + cl_git_fail(try_build_signature(" ", "emeric.fermas@gmail.com", 1234567890, 60)); + cl_git_pass(try_build_signature("nulltoken", "", 1234567890, 60)); + cl_git_pass(try_build_signature("nulltoken", " ", 1234567890, 60)); +} + +void test_commit_signature__create_one_char(void) +{ + // creating a one character signature + assert_name_and_email("x", "foo@bar.baz", "x", "foo@bar.baz"); +} + +void test_commit_signature__create_two_char(void) +{ + // creating a two character signature + assert_name_and_email("xx", "foo@bar.baz", "xx", "foo@bar.baz"); +} + +void test_commit_signature__create_zero_char(void) +{ + // creating a zero character signature + git_signature *sign; + cl_git_fail(git_signature_new(&sign, "", "x@y.z", 1234567890, 60)); + cl_assert(sign == NULL); +} diff --git a/tests/commit/write.c b/tests/commit/write.c new file mode 100644 index 000000000..73436b74b --- /dev/null +++ b/tests/commit/write.c @@ -0,0 +1,147 @@ +#include "clar_libgit2.h" + +static const char *committer_name = "Vicent Marti"; +static const char *committer_email = "vicent@github.com"; +static const char *commit_message = "This commit has been created in memory\n\ + This is a commit created in memory and it will be written back to disk\n"; +static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd"; +static const char *root_commit_message = "This is a root commit\n\ + This is a root commit and should be the only one in this branch\n"; +static char *head_old; +static git_reference *head, *branch; +static git_commit *commit; + +// Fixture setup +static git_repository *g_repo; +void test_commit_write__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_commit_write__cleanup(void) +{ + git_reference_free(head); + head = NULL; + + git_reference_free(branch); + branch = NULL; + + git_commit_free(commit); + commit = NULL; + + git__free(head_old); + head_old = NULL; + + cl_git_sandbox_cleanup(); +} + + +// write a new commit object from memory to disk +void test_commit_write__from_memory(void) +{ + git_oid tree_id, parent_id, commit_id; + git_signature *author, *committer; + const git_signature *author1, *committer1; + git_commit *parent; + git_tree *tree; + const char *commit_id_str = "8496071c1b46c854b31185ea97743be6a8774479"; + + git_oid_fromstr(&tree_id, tree_oid); + cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); + + git_oid_fromstr(&parent_id, commit_id_str); + cl_git_pass(git_commit_lookup(&parent, g_repo, &parent_id)); + + /* create signatures */ + cl_git_pass(git_signature_new(&committer, committer_name, committer_email, 123456789, 60)); + cl_git_pass(git_signature_new(&author, committer_name, committer_email, 987654321, 90)); + + cl_git_pass(git_commit_create_v( + &commit_id, /* out id */ + g_repo, + NULL, /* do not update the HEAD */ + author, + committer, + NULL, + commit_message, + tree, + 1, parent)); + + git_object_free((git_object *)parent); + git_object_free((git_object *)tree); + + git_signature_free(committer); + git_signature_free(author); + + cl_git_pass(git_commit_lookup(&commit, g_repo, &commit_id)); + + /* Check attributes were set correctly */ + author1 = git_commit_author(commit); + cl_assert(author1 != NULL); + cl_assert_equal_s(committer_name, author1->name); + cl_assert_equal_s(committer_email, author1->email); + cl_assert(author1->when.time == 987654321); + cl_assert(author1->when.offset == 90); + + committer1 = git_commit_committer(commit); + cl_assert(committer1 != NULL); + cl_assert_equal_s(committer_name, committer1->name); + cl_assert_equal_s(committer_email, committer1->email); + cl_assert(committer1->when.time == 123456789); + cl_assert(committer1->when.offset == 60); + + cl_assert_equal_s(commit_message, git_commit_message(commit)); +} + +// create a root commit +void test_commit_write__root(void) +{ + git_oid tree_id, commit_id; + const git_oid *branch_oid; + git_signature *author, *committer; + const char *branch_name = "refs/heads/root-commit-branch"; + git_tree *tree; + + git_oid_fromstr(&tree_id, tree_oid); + cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); + + /* create signatures */ + cl_git_pass(git_signature_new(&committer, committer_name, committer_email, 123456789, 60)); + cl_git_pass(git_signature_new(&author, committer_name, committer_email, 987654321, 90)); + + /* First we need to update HEAD so it points to our non-existant branch */ + cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); + cl_assert(git_reference_type(head) == GIT_REF_SYMBOLIC); + head_old = git__strdup(git_reference_symbolic_target(head)); + cl_assert(head_old != NULL); + git_reference_free(head); + + cl_git_pass(git_reference_symbolic_create(&head, g_repo, "HEAD", branch_name, 1)); + + cl_git_pass(git_commit_create_v( + &commit_id, /* out id */ + g_repo, + "HEAD", + author, + committer, + NULL, + root_commit_message, + tree, + 0)); + + git_object_free((git_object *)tree); + git_signature_free(committer); + git_signature_free(author); + + /* + * The fact that creating a commit works has already been + * tested. Here we just make sure it's our commit and that it was + * written as a root commit. + */ + cl_git_pass(git_commit_lookup(&commit, g_repo, &commit_id)); + cl_assert(git_commit_parentcount(commit) == 0); + cl_git_pass(git_reference_lookup(&branch, g_repo, branch_name)); + branch_oid = git_reference_target(branch); + cl_git_pass(git_oid_cmp(branch_oid, &commit_id)); + cl_assert_equal_s(root_commit_message, git_commit_message(commit)); +} diff --git a/tests/config/add.c b/tests/config/add.c new file mode 100644 index 000000000..405f1e2c9 --- /dev/null +++ b/tests/config/add.c @@ -0,0 +1,37 @@ +#include "clar_libgit2.h" + +void test_config_add__initialize(void) +{ + cl_fixture_sandbox("config/config10"); +} + +void test_config_add__cleanup(void) +{ + cl_fixture_cleanup("config10"); +} + +void test_config_add__to_existing_section(void) +{ + git_config *cfg; + int32_t i; + + cl_git_pass(git_config_open_ondisk(&cfg, "config10")); + cl_git_pass(git_config_set_int32(cfg, "empty.tmp", 5)); + cl_git_pass(git_config_get_int32(&i, cfg, "empty.tmp")); + cl_assert(i == 5); + cl_git_pass(git_config_delete_entry(cfg, "empty.tmp")); + git_config_free(cfg); +} + +void test_config_add__to_new_section(void) +{ + git_config *cfg; + int32_t i; + + cl_git_pass(git_config_open_ondisk(&cfg, "config10")); + cl_git_pass(git_config_set_int32(cfg, "section.tmp", 5)); + cl_git_pass(git_config_get_int32(&i, cfg, "section.tmp")); + cl_assert(i == 5); + cl_git_pass(git_config_delete_entry(cfg, "section.tmp")); + git_config_free(cfg); +} diff --git a/tests/config/backend.c b/tests/config/backend.c new file mode 100644 index 000000000..3fd6eb114 --- /dev/null +++ b/tests/config/backend.c @@ -0,0 +1,24 @@ +#include "clar_libgit2.h" +#include "git2/sys/config.h" + +void test_config_backend__checks_version(void) +{ + git_config *cfg; + git_config_backend backend = GIT_CONFIG_BACKEND_INIT; + const git_error *err; + + backend.version = 1024; + + cl_git_pass(git_config_new(&cfg)); + cl_git_fail(git_config_add_backend(cfg, &backend, 0, false)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); + + giterr_clear(); + backend.version = 1024; + cl_git_fail(git_config_add_backend(cfg, &backend, 0, false)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); + + git_config_free(cfg); +} diff --git a/tests/config/config_helpers.c b/tests/config/config_helpers.c new file mode 100644 index 000000000..53bd945a0 --- /dev/null +++ b/tests/config/config_helpers.c @@ -0,0 +1,37 @@ +#include "clar_libgit2.h" +#include "config_helpers.h" +#include "repository.h" + +void assert_config_entry_existence( + git_repository *repo, + const char *name, + bool is_supposed_to_exist) +{ + git_config *config; + const char *out; + int result; + + cl_git_pass(git_repository_config__weakptr(&config, repo)); + + result = git_config_get_string(&out, config, name); + + if (is_supposed_to_exist) + cl_git_pass(result); + else + cl_assert_equal_i(GIT_ENOTFOUND, result); +} + +void assert_config_entry_value( + git_repository *repo, + const char *name, + const char *expected_value) +{ + git_config *config; + const char *out; + + cl_git_pass(git_repository_config__weakptr(&config, repo)); + + cl_git_pass(git_config_get_string(&out, config, name)); + + cl_assert_equal_s(expected_value, out); +} diff --git a/tests/config/config_helpers.h b/tests/config/config_helpers.h new file mode 100644 index 000000000..b887b3d38 --- /dev/null +++ b/tests/config/config_helpers.h @@ -0,0 +1,9 @@ +extern void assert_config_entry_existence( + git_repository *repo, + const char *name, + bool is_supposed_to_exist); + +extern void assert_config_entry_value( + git_repository *repo, + const char *name, + const char *expected_value); diff --git a/tests/config/configlevel.c b/tests/config/configlevel.c new file mode 100644 index 000000000..1c22e8d9f --- /dev/null +++ b/tests/config/configlevel.c @@ -0,0 +1,71 @@ +#include "clar_libgit2.h" + +void test_config_configlevel__adding_the_same_level_twice_returns_EEXISTS(void) +{ + int error; + git_config *cfg; + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), + GIT_CONFIG_LEVEL_LOCAL, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), + GIT_CONFIG_LEVEL_GLOBAL, 0)); + error = git_config_add_file_ondisk(cfg, cl_fixture("config/config16"), + GIT_CONFIG_LEVEL_GLOBAL, 0); + + cl_git_fail(error); + cl_assert_equal_i(GIT_EEXISTS, error); + + git_config_free(cfg); +} + +void test_config_configlevel__can_replace_a_config_file_at_an_existing_level(void) +{ + git_config *cfg; + const char *s; + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"), + GIT_CONFIG_LEVEL_LOCAL, 1)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"), + GIT_CONFIG_LEVEL_LOCAL, 1)); + + cl_git_pass(git_config_get_string(&s, cfg, "core.stringglobal")); + cl_assert_equal_s("don't find me!", s); + + git_config_free(cfg); +} + +void test_config_configlevel__can_read_from_a_single_level_focused_file_after_parent_config_has_been_freed(void) +{ + git_config *cfg; + git_config *single_level_cfg; + const char *s; + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"), + GIT_CONFIG_LEVEL_GLOBAL, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"), + GIT_CONFIG_LEVEL_LOCAL, 0)); + + cl_git_pass(git_config_open_level(&single_level_cfg, cfg, GIT_CONFIG_LEVEL_LOCAL)); + + git_config_free(cfg); + + cl_git_pass(git_config_get_string(&s, single_level_cfg, "core.stringglobal")); + cl_assert_equal_s("don't find me!", s); + + git_config_free(single_level_cfg); +} + +void test_config_configlevel__fetching_a_level_from_an_empty_compound_config_returns_ENOTFOUND(void) +{ + git_config *cfg; + git_config *local_cfg; + + cl_git_pass(git_config_new(&cfg)); + + cl_assert_equal_i(GIT_ENOTFOUND, git_config_open_level(&local_cfg, cfg, GIT_CONFIG_LEVEL_LOCAL)); + + git_config_free(cfg); +} diff --git a/tests/config/global.c b/tests/config/global.c new file mode 100644 index 000000000..d5f95f504 --- /dev/null +++ b/tests/config/global.c @@ -0,0 +1,72 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "fileops.h" + +void test_config_global__initialize(void) +{ + git_buf path = GIT_BUF_INIT; + + cl_assert_equal_i(0, p_mkdir("home", 0777)); + cl_git_pass(git_path_prettify(&path, "home", NULL)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); + + cl_assert_equal_i(0, p_mkdir("xdg", 0777)); + cl_assert_equal_i(0, p_mkdir("xdg/git", 0777)); + cl_git_pass(git_path_prettify(&path, "xdg/git", NULL)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); + + cl_assert_equal_i(0, p_mkdir("etc", 0777)); + cl_git_pass(git_path_prettify(&path, "etc", NULL)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); + + git_buf_free(&path); +} + +void test_config_global__cleanup(void) +{ + cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES)); + cl_git_pass(git_futils_rmdir_r("xdg", NULL, GIT_RMDIR_REMOVE_FILES)); + cl_git_pass(git_futils_rmdir_r("etc", NULL, GIT_RMDIR_REMOVE_FILES)); + + git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, NULL); + git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, NULL); + git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, NULL); +} + +void test_config_global__open_global(void) +{ + git_config *cfg, *global, *selected, *dummy; + + cl_git_pass(git_config_open_default(&cfg)); + cl_git_pass(git_config_open_level(&global, cfg, GIT_CONFIG_LEVEL_GLOBAL)); + cl_git_fail(git_config_open_level(&dummy, cfg, GIT_CONFIG_LEVEL_XDG)); + cl_git_pass(git_config_open_global(&selected, cfg)); + + git_config_free(selected); + git_config_free(global); + git_config_free(cfg); +} + +void test_config_global__open_xdg(void) +{ + git_config *cfg, *xdg, *selected; + const char *val, *str = "teststring"; + const char *key = "this.variable"; + + cl_git_mkfile("xdg/git/config", "# XDG config\n[core]\n test = 1\n"); + + cl_git_pass(git_config_open_default(&cfg)); + cl_git_pass(git_config_open_level(&xdg, cfg, GIT_CONFIG_LEVEL_XDG)); + cl_git_pass(git_config_open_global(&selected, cfg)); + + cl_git_pass(git_config_set_string(xdg, key, str)); + cl_git_pass(git_config_get_string(&val, selected, key)); + cl_assert_equal_s(str, val); + + git_config_free(selected); + git_config_free(xdg); + git_config_free(cfg); +} diff --git a/tests/config/include.c b/tests/config/include.c new file mode 100644 index 000000000..535573808 --- /dev/null +++ b/tests/config/include.c @@ -0,0 +1,109 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "fileops.h" + +void test_config_include__relative(void) +{ + git_config *cfg; + const char *str; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config-include"))); + + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); + cl_assert_equal_s(str, "huzzah"); + + git_config_free(cfg); +} + +void test_config_include__absolute(void) +{ + git_config *cfg; + const char *str; + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_buf_printf(&buf, "[include]\npath = %s/config-included", cl_fixture("config"))); + + cl_git_mkfile("config-include-absolute", git_buf_cstr(&buf)); + git_buf_free(&buf); + cl_git_pass(git_config_open_ondisk(&cfg, "config-include-absolute")); + + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); + cl_assert_equal_s(str, "huzzah"); + + git_config_free(cfg); +} + +void test_config_include__homedir(void) +{ + git_config *cfg; + const char *str; + + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, cl_fixture("config"))); + cl_git_mkfile("config-include-homedir", "[include]\npath = ~/config-included"); + + cl_git_pass(git_config_open_ondisk(&cfg, "config-include-homedir")); + + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); + cl_assert_equal_s(str, "huzzah"); + + git_config_free(cfg); +} + +void test_config_include__refresh(void) +{ + git_config *cfg; + const char *str; + + cl_fixture_sandbox("config"); + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config-include")); + + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); + cl_assert_equal_s(str, "huzzah"); + + /* Change the included file and see if we refresh */ + cl_git_mkfile("config/config-included", "[foo \"bar\"]\nbaz = hurrah"); + cl_git_pass(git_config_refresh(cfg)); + + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); + cl_assert_equal_s(str, "hurrah"); + + git_config_free(cfg); + cl_fixture_cleanup("config"); +} + +/* We need to pretend that the variables were defined where the file was included */ +void test_config_include__ordering(void) +{ + git_config *cfg; + const char *str; + + cl_git_mkfile("included", "[foo \"bar\"]\nbaz = hurrah\nfrotz = hiya"); + cl_git_mkfile("including", + "[foo \"bar\"]\nfrotz = hello\n" + "[include]\npath = included\n" + "[foo \"bar\"]\nbaz = huzzah\n"); + + cl_git_pass(git_config_open_ondisk(&cfg, "including")); + + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.frotz")); + cl_assert_equal_s(str, "hiya"); + cl_git_pass(git_config_get_string(&str, cfg, "foo.bar.baz")); + cl_assert_equal_s(str, "huzzah"); + + git_config_free(cfg); +} + +/* We need to pretend that the variables were defined where the file was included */ +void test_config_include__depth(void) +{ + git_config *cfg; + + cl_git_mkfile("a", "[include]\npath = b"); + cl_git_mkfile("b", "[include]\npath = a"); + + cl_git_fail(git_config_open_ondisk(&cfg, "a")); + + unlink("a"); + unlink("b"); +} diff --git a/tests/config/multivar.c b/tests/config/multivar.c new file mode 100644 index 000000000..afdb1e5f4 --- /dev/null +++ b/tests/config/multivar.c @@ -0,0 +1,288 @@ +#include "clar_libgit2.h" + +static const char *_name = "remote.ab.url"; + +void test_config_multivar__initialize(void) +{ + cl_fixture_sandbox("config"); +} + +void test_config_multivar__cleanup(void) +{ + cl_fixture_cleanup("config"); +} + +static int mv_read_cb(const git_config_entry *entry, void *data) +{ + int *n = (int *) data; + + if (!strcmp(entry->name, _name)) + (*n)++; + + return 0; +} + +void test_config_multivar__foreach(void) +{ + git_config *cfg; + int n = 0; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config11"))); + + cl_git_pass(git_config_foreach(cfg, mv_read_cb, &n)); + cl_assert(n == 2); + + git_config_free(cfg); +} + +static int cb(const git_config_entry *entry, void *data) +{ + int *n = (int *) data; + + GIT_UNUSED(entry); + + (*n)++; + + return 0; +} + +static void check_get_multivar_foreach( + git_config *cfg, int expected, int expected_patterned) +{ + int n = 0; + + if (expected > 0) { + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert_equal_i(expected, n); + } else { + cl_assert_equal_i(GIT_ENOTFOUND, + git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + } + + n = 0; + + if (expected_patterned > 0) { + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "example", cb, &n)); + cl_assert_equal_i(expected_patterned, n); + } else { + cl_assert_equal_i(GIT_ENOTFOUND, + git_config_get_multivar_foreach(cfg, _name, "example", cb, &n)); + } +} + +static void check_get_multivar(git_config *cfg, int expected) +{ + git_config_iterator *iter; + git_config_entry *entry; + int n = 0; + + cl_git_pass(git_config_multivar_iterator_new(&iter, cfg, _name, NULL)); + + while (git_config_next(&entry, iter) == 0) + n++; + + cl_assert_equal_i(expected, n); + git_config_iterator_free(iter); + +} + +void test_config_multivar__get(void) +{ + git_config *cfg; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + check_get_multivar_foreach(cfg, 2, 1); + + /* add another that has the _name entry */ + cl_git_pass(git_config_add_file_ondisk(cfg, "config/config9", GIT_CONFIG_LEVEL_SYSTEM, 1)); + check_get_multivar_foreach(cfg, 3, 2); + + /* add another that does not have the _name entry */ + cl_git_pass(git_config_add_file_ondisk(cfg, "config/config0", GIT_CONFIG_LEVEL_GLOBAL, 1)); + check_get_multivar_foreach(cfg, 3, 2); + + /* add another that does not have the _name entry at the end */ + cl_git_pass(git_config_add_file_ondisk(cfg, "config/config1", GIT_CONFIG_LEVEL_APP, 1)); + check_get_multivar_foreach(cfg, 3, 2); + + /* drop original file */ + cl_git_pass(git_config_add_file_ondisk(cfg, "config/config2", GIT_CONFIG_LEVEL_LOCAL, 1)); + check_get_multivar_foreach(cfg, 1, 1); + + /* drop other file with match */ + cl_git_pass(git_config_add_file_ondisk(cfg, "config/config3", GIT_CONFIG_LEVEL_SYSTEM, 1)); + check_get_multivar_foreach(cfg, 0, 0); + + /* reload original file (add different place in order) */ + cl_git_pass(git_config_add_file_ondisk(cfg, "config/config11", GIT_CONFIG_LEVEL_SYSTEM, 1)); + check_get_multivar_foreach(cfg, 2, 1); + + check_get_multivar(cfg, 2); + + git_config_free(cfg); +} + +void test_config_multivar__add(void) +{ + git_config *cfg; + int n; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + cl_git_pass(git_config_set_multivar(cfg, _name, "nonexistant", "git://git.otherplace.org/libgit2")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert_equal_i(n, 3); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); + cl_assert_equal_i(n, 1); + + git_config_free(cfg); + + /* We know it works in memory, let's see if the file is written correctly */ + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert_equal_i(n, 3); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); + cl_assert_equal_i(n, 1); + + git_config_free(cfg); +} + +void test_config_multivar__add_new(void) +{ + const char *var = "a.brand.new"; + git_config *cfg; + int n; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + cl_git_pass(git_config_set_multivar(cfg, var, "", "variable")); + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, var, NULL, cb, &n)); + cl_assert_equal_i(n, 1); + + git_config_free(cfg); +} + +void test_config_multivar__replace(void) +{ + git_config *cfg; + int n; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 2); + + cl_git_pass(git_config_set_multivar(cfg, _name, "github", "git://git.otherplace.org/libgit2")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 2); + + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 2); + + git_config_free(cfg); +} + +void test_config_multivar__replace_multiple(void) +{ + git_config *cfg; + int n; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + cl_git_pass(git_config_set_multivar(cfg, _name, "git://", "git://git.otherplace.org/libgit2")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); + cl_assert_equal_i(n, 2); + + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, "otherplace", cb, &n)); + cl_assert_equal_i(n, 2); + + git_config_free(cfg); +} + +void test_config_multivar__delete(void) +{ + git_config *cfg; + int n; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 2); + + cl_git_pass(git_config_delete_multivar(cfg, _name, "github")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 1); + + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 1); + + git_config_free(cfg); +} + +void test_config_multivar__delete_multiple(void) +{ + git_config *cfg; + int n; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_pass(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n)); + cl_assert(n == 2); + + cl_git_pass(git_config_delete_multivar(cfg, _name, "git")); + + n = 0; + cl_git_fail_with(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n), GIT_ENOTFOUND); + + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + n = 0; + cl_git_fail_with(git_config_get_multivar_foreach(cfg, _name, NULL, cb, &n), GIT_ENOTFOUND); + + git_config_free(cfg); +} + +void test_config_multivar__delete_notfound(void) +{ + git_config *cfg; + + cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); + + cl_git_fail_with(git_config_delete_multivar(cfg, "remote.ab.noturl", "git"), GIT_ENOTFOUND); + + git_config_free(cfg); +} diff --git a/tests/config/new.c b/tests/config/new.c new file mode 100644 index 000000000..dd6dbca9e --- /dev/null +++ b/tests/config/new.c @@ -0,0 +1,32 @@ +#include "clar_libgit2.h" + +#include "filebuf.h" +#include "fileops.h" +#include "posix.h" + +#define TEST_CONFIG "git-new-config" + +void test_config_new__write_new_config(void) +{ + const char *out; + git_config *config; + + cl_git_mkfile(TEST_CONFIG, ""); + cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); + + cl_git_pass(git_config_set_string(config, "color.ui", "auto")); + cl_git_pass(git_config_set_string(config, "core.editor", "ed")); + + git_config_free(config); + + cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); + + cl_git_pass(git_config_get_string(&out, config, "color.ui")); + cl_assert_equal_s(out, "auto"); + cl_git_pass(git_config_get_string(&out, config, "core.editor")); + cl_assert_equal_s(out, "ed"); + + git_config_free(config); + + p_unlink(TEST_CONFIG); +} diff --git a/tests/config/read.c b/tests/config/read.c new file mode 100644 index 000000000..abc088d59 --- /dev/null +++ b/tests/config/read.c @@ -0,0 +1,569 @@ +#include "clar_libgit2.h" + +void test_config_read__simple_read(void) +{ + git_config *cfg; + int32_t i; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config0"))); + + cl_git_pass(git_config_get_int32(&i, cfg, "core.repositoryformatversion")); + cl_assert(i == 0); + cl_git_pass(git_config_get_bool(&i, cfg, "core.filemode")); + cl_assert(i == 1); + cl_git_pass(git_config_get_bool(&i, cfg, "core.bare")); + cl_assert(i == 0); + cl_git_pass(git_config_get_bool(&i, cfg, "core.logallrefupdates")); + cl_assert(i == 1); + + git_config_free(cfg); +} + +void test_config_read__case_sensitive(void) +{ + git_config *cfg; + int i; + const char *str; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config1"))); + + cl_git_pass(git_config_get_string(&str, cfg, "this.that.other")); + cl_assert_equal_s(str, "true"); + cl_git_pass(git_config_get_string(&str, cfg, "this.That.other")); + cl_assert_equal_s(str, "yes"); + + cl_git_pass(git_config_get_bool(&i, cfg, "this.that.other")); + cl_assert(i == 1); + cl_git_pass(git_config_get_bool(&i, cfg, "this.That.other")); + cl_assert(i == 1); + + /* This one doesn't exist */ + cl_must_fail(git_config_get_bool(&i, cfg, "this.thaT.other")); + + git_config_free(cfg); +} + +/* + * If \ is the last non-space character on the line, we read the next + * one, separating each line with SP. + */ +void test_config_read__multiline_value(void) +{ + git_config *cfg; + const char *str; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config2"))); + + cl_git_pass(git_config_get_string(&str, cfg, "this.That.and")); + cl_assert_equal_s(str, "one one one two two three three"); + + git_config_free(cfg); +} + +/* + * This kind of subsection declaration is case-insensitive + */ +void test_config_read__subsection_header(void) +{ + git_config *cfg; + const char *str; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config3"))); + + cl_git_pass(git_config_get_string(&str, cfg, "section.subsection.var")); + cl_assert_equal_s(str, "hello"); + + /* The subsection is transformed to lower-case */ + cl_must_fail(git_config_get_string(&str, cfg, "section.subSectIon.var")); + + git_config_free(cfg); +} + +void test_config_read__lone_variable(void) +{ + git_config *cfg; + const char *str; + int i; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config4"))); + + cl_git_fail(git_config_get_int32(&i, cfg, "some.section.variable")); + + cl_git_pass(git_config_get_string(&str, cfg, "some.section.variable")); + cl_assert_equal_s(str, ""); + + cl_git_pass(git_config_get_bool(&i, cfg, "some.section.variable")); + cl_assert(i == 1); + + cl_git_pass(git_config_get_string(&str, cfg, "some.section.variableeq")); + cl_assert_equal_s(str, ""); + + cl_git_pass(git_config_get_bool(&i, cfg, "some.section.variableeq")); + cl_assert(i == 0); + + git_config_free(cfg); +} + +void test_config_read__number_suffixes(void) +{ + git_config *cfg; + int64_t i; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config5"))); + + cl_git_pass(git_config_get_int64(&i, cfg, "number.simple")); + cl_assert(i == 1); + + cl_git_pass(git_config_get_int64(&i, cfg, "number.k")); + cl_assert(i == 1 * 1024); + + cl_git_pass(git_config_get_int64(&i, cfg, "number.kk")); + cl_assert(i == 1 * 1024); + + cl_git_pass(git_config_get_int64(&i, cfg, "number.m")); + cl_assert(i == 1 * 1024 * 1024); + + cl_git_pass(git_config_get_int64(&i, cfg, "number.mm")); + cl_assert(i == 1 * 1024 * 1024); + + cl_git_pass(git_config_get_int64(&i, cfg, "number.g")); + cl_assert(i == 1 * 1024 * 1024 * 1024); + + cl_git_pass(git_config_get_int64(&i, cfg, "number.gg")); + cl_assert(i == 1 * 1024 * 1024 * 1024); + + git_config_free(cfg); +} + +void test_config_read__blank_lines(void) +{ + git_config *cfg; + int i; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config6"))); + + cl_git_pass(git_config_get_bool(&i, cfg, "valid.subsection.something")); + cl_assert(i == 1); + + cl_git_pass(git_config_get_bool(&i, cfg, "something.else.something")); + cl_assert(i == 0); + + git_config_free(cfg); +} + +void test_config_read__invalid_ext_headers(void) +{ + git_config *cfg; + cl_must_fail(git_config_open_ondisk(&cfg, cl_fixture("config/config7"))); +} + +void test_config_read__empty_files(void) +{ + git_config *cfg; + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config8"))); + git_config_free(cfg); +} + +void test_config_read__symbol_headers(void) +{ + git_config *cfg; + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config20"))); + git_config_free(cfg); +} + +void test_config_read__header_in_last_line(void) +{ + git_config *cfg; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config10"))); + git_config_free(cfg); +} + +void test_config_read__prefixes(void) +{ + git_config *cfg; + const char *str; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9"))); + cl_git_pass(git_config_get_string(&str, cfg, "remote.ab.url")); + cl_assert_equal_s(str, "http://example.com/git/ab"); + + cl_git_pass(git_config_get_string(&str, cfg, "remote.abba.url")); + cl_assert_equal_s(str, "http://example.com/git/abba"); + + git_config_free(cfg); +} + +void test_config_read__escaping_quotes(void) +{ + git_config *cfg; + const char *str; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config13"))); + cl_git_pass(git_config_get_string(&str, cfg, "core.editor")); + cl_assert_equal_s("\"C:/Program Files/Nonsense/bah.exe\" \"--some option\"", str); + + git_config_free(cfg); +} + +static int count_cfg_entries_and_compare_levels( + const git_config_entry *entry, void *payload) +{ + int *count = payload; + + if (!strcmp(entry->value, "7") || !strcmp(entry->value, "17")) + cl_assert(entry->level == GIT_CONFIG_LEVEL_GLOBAL); + else + cl_assert(entry->level == GIT_CONFIG_LEVEL_SYSTEM); + + (*count)++; + return 0; +} + +static int cfg_callback_countdown(const git_config_entry *entry, void *payload) +{ + int *count = payload; + GIT_UNUSED(entry); + (*count)--; + if (*count == 0) + return -100; + return 0; +} + +void test_config_read__foreach(void) +{ + git_config *cfg; + int count, ret; + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), + GIT_CONFIG_LEVEL_SYSTEM, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), + GIT_CONFIG_LEVEL_GLOBAL, 0)); + + count = 0; + cl_git_pass(git_config_foreach(cfg, count_cfg_entries_and_compare_levels, &count)); + cl_assert_equal_i(7, count); + + count = 3; + cl_git_fail(ret = git_config_foreach(cfg, cfg_callback_countdown, &count)); + cl_assert_equal_i(GIT_EUSER, ret); + + git_config_free(cfg); +} + +void test_config_read__iterator(void) +{ + git_config *cfg; + git_config_iterator *iter; + git_config_entry *entry; + int count, ret; + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), + GIT_CONFIG_LEVEL_SYSTEM, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), + GIT_CONFIG_LEVEL_GLOBAL, 0)); + + count = 0; + cl_git_pass(git_config_iterator_new(&iter, cfg)); + + while ((ret = git_config_next(&entry, iter)) == 0) { + count++; + } + + git_config_iterator_free(iter); + cl_assert_equal_i(GIT_ITEROVER, ret); + cl_assert_equal_i(7, count); + + count = 3; + cl_git_pass(git_config_iterator_new(&iter, cfg)); + + git_config_iterator_free(iter); + git_config_free(cfg); +} + +static int count_cfg_entries(const git_config_entry *entry, void *payload) +{ + int *count = payload; + GIT_UNUSED(entry); + (*count)++; + return 0; +} + +void test_config_read__foreach_match(void) +{ + git_config *cfg; + int count; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9"))); + + count = 0; + cl_git_pass( + git_config_foreach_match(cfg, "core.*", count_cfg_entries, &count)); + cl_assert_equal_i(3, count); + + count = 0; + cl_git_pass( + git_config_foreach_match(cfg, "remote\\.ab.*", count_cfg_entries, &count)); + cl_assert_equal_i(2, count); + + count = 0; + cl_git_pass( + git_config_foreach_match(cfg, ".*url$", count_cfg_entries, &count)); + cl_assert_equal_i(2, count); + + count = 0; + cl_git_pass( + git_config_foreach_match(cfg, ".*dummy.*", count_cfg_entries, &count)); + cl_assert_equal_i(2, count); + + count = 0; + cl_git_pass( + git_config_foreach_match(cfg, ".*nomatch.*", count_cfg_entries, &count)); + cl_assert_equal_i(0, count); + + git_config_free(cfg); +} + +static void check_glob_iter(git_config *cfg, const char *regexp, int expected) +{ + git_config_iterator *iter; + git_config_entry *entry; + int count, error; + + cl_git_pass(git_config_iterator_glob_new(&iter, cfg, regexp)); + + count = 0; + while ((error = git_config_next(&entry, iter)) == 0) + count++; + + cl_assert_equal_i(GIT_ITEROVER, error); + cl_assert_equal_i(expected, count); + git_config_iterator_free(iter); +} + +void test_config_read__iterator_glob(void) +{ + git_config *cfg; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9"))); + + check_glob_iter(cfg, "core.*", 3); + check_glob_iter(cfg, "remote\\.ab.*", 2); + check_glob_iter(cfg, ".*url$", 2); + check_glob_iter(cfg, ".*dummy.*", 2); + check_glob_iter(cfg, ".*nomatch.*", 0); + + git_config_free(cfg); +} + +void test_config_read__whitespace_not_required_around_assignment(void) +{ + git_config *cfg; + const char *str; + + cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config14"))); + + cl_git_pass(git_config_get_string(&str, cfg, "a.b")); + cl_assert_equal_s(str, "c"); + + cl_git_pass(git_config_get_string(&str, cfg, "d.e")); + cl_assert_equal_s(str, "f"); + + git_config_free(cfg); +} + +void test_config_read__read_git_config_entry(void) +{ + git_config *cfg; + const git_config_entry *entry; + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), + GIT_CONFIG_LEVEL_SYSTEM, 0)); + + cl_git_pass(git_config_get_entry(&entry, cfg, "core.dummy2")); + cl_assert_equal_s("core.dummy2", entry->name); + cl_assert_equal_s("42", entry->value); + cl_assert_equal_i(GIT_CONFIG_LEVEL_SYSTEM, entry->level); + + git_config_free(cfg); +} + +/* + * At the beginning of the test: + * - config9 has: core.dummy2=42 + * - config15 has: core.dummy2=7 + * - config16 has: core.dummy2=28 + */ +void test_config_read__local_config_overrides_global_config_overrides_system_config(void) +{ + git_config *cfg; + int32_t i; + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), + GIT_CONFIG_LEVEL_SYSTEM, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), + GIT_CONFIG_LEVEL_GLOBAL, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config16"), + GIT_CONFIG_LEVEL_LOCAL, 0)); + + cl_git_pass(git_config_get_int32(&i, cfg, "core.dummy2")); + cl_assert_equal_i(28, i); + + git_config_free(cfg); + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), + GIT_CONFIG_LEVEL_SYSTEM, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), + GIT_CONFIG_LEVEL_GLOBAL, 0)); + + cl_git_pass(git_config_get_int32(&i, cfg, "core.dummy2")); + cl_assert_equal_i(7, i); + + git_config_free(cfg); +} + +/* + * At the beginning of the test: + * - config9 has: core.global does not exist + * - config15 has: core.global=17 + * - config16 has: core.global=29 + * + * And also: + * - config9 has: core.system does not exist + * - config15 has: core.system does not exist + * - config16 has: core.system=11 + */ +void test_config_read__fallback_from_local_to_global_and_from_global_to_system(void) +{ + git_config *cfg; + int32_t i; + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"), + GIT_CONFIG_LEVEL_SYSTEM, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"), + GIT_CONFIG_LEVEL_GLOBAL, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config16"), + GIT_CONFIG_LEVEL_LOCAL, 0)); + + cl_git_pass(git_config_get_int32(&i, cfg, "core.global")); + cl_assert_equal_i(17, i); + cl_git_pass(git_config_get_int32(&i, cfg, "core.system")); + cl_assert_equal_i(11, i); + + git_config_free(cfg); +} + +/* + * At the beginning of the test, config18 has: + * int32global = 28 + * int64global = 9223372036854775803 + * boolglobal = true + * stringglobal = I'm a global config value! + * + * And config19 has: + * int32global = -1 + * int64global = -2 + * boolglobal = false + * stringglobal = don't find me! + * + */ +void test_config_read__simple_read_from_specific_level(void) +{ + git_config *cfg, *cfg_specific; + int i; + int64_t l, expected = +9223372036854775803; + const char *s; + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"), + GIT_CONFIG_LEVEL_GLOBAL, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"), + GIT_CONFIG_LEVEL_SYSTEM, 0)); + + cl_git_pass(git_config_open_level(&cfg_specific, cfg, GIT_CONFIG_LEVEL_GLOBAL)); + + cl_git_pass(git_config_get_int32(&i, cfg_specific, "core.int32global")); + cl_assert_equal_i(28, i); + cl_git_pass(git_config_get_int64(&l, cfg_specific, "core.int64global")); + cl_assert(l == expected); + cl_git_pass(git_config_get_bool(&i, cfg_specific, "core.boolglobal")); + cl_assert_equal_b(true, i); + cl_git_pass(git_config_get_string(&s, cfg_specific, "core.stringglobal")); + cl_assert_equal_s("I'm a global config value!", s); + + git_config_free(cfg_specific); + git_config_free(cfg); +} + +static void clean_test_config(void *unused) +{ + GIT_UNUSED(unused); + cl_fixture_cleanup("./testconfig"); +} + +void test_config_read__can_load_and_parse_an_empty_config_file(void) +{ + git_config *cfg; + int i; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", ""); + cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig")); + cl_assert_equal_i(GIT_ENOTFOUND, git_config_get_int32(&i, cfg, "nope.neither")); + + git_config_free(cfg); +} + +void test_config_read__corrupt_header(void) +{ + git_config *cfg; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "[sneaky ] \"quoted closing quote mark\\\""); + cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); + + git_config_free(cfg); +} + +void test_config_read__corrupt_header2(void) +{ + git_config *cfg; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "[unclosed \"bracket\"\n lib = git2\n"); + cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); + + git_config_free(cfg); +} + +void test_config_read__corrupt_header3(void) +{ + git_config *cfg; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "[unclosed \"slash\\\"]\n lib = git2\n"); + cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); + + git_config_free(cfg); +} + +void test_config_read__override_variable(void) +{ + git_config *cfg; + const char *str; + + cl_set_cleanup(&clean_test_config, NULL); + cl_git_mkfile("./testconfig", "[some] var = one\nvar = two"); + cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig")); + + cl_git_pass(git_config_get_string(&str, cfg, "some.var")); + cl_assert_equal_s(str, "two"); + + git_config_free(cfg); +} diff --git a/tests/config/refresh.c b/tests/config/refresh.c new file mode 100644 index 000000000..99d677f0e --- /dev/null +++ b/tests/config/refresh.c @@ -0,0 +1,67 @@ +#include "clar_libgit2.h" + +#define TEST_FILE "config.refresh" + +void test_config_refresh__initialize(void) +{ +} + +void test_config_refresh__cleanup(void) +{ + cl_fixture_cleanup(TEST_FILE); +} + +void test_config_refresh__update_value(void) +{ + git_config *cfg; + int32_t v; + + cl_git_mkfile(TEST_FILE, "[section]\n\tvalue = 1\n\n"); + + /* By freeing the config, we make sure we flush the values */ + cl_git_pass(git_config_open_ondisk(&cfg, TEST_FILE)); + + cl_git_pass(git_config_get_int32(&v, cfg, "section.value")); + cl_assert_equal_i(1, v); + + cl_git_rewritefile(TEST_FILE, "[section]\n\tvalue = 10\n\n"); + + cl_git_pass(git_config_get_int32(&v, cfg, "section.value")); + cl_assert_equal_i(1, v); + + cl_git_pass(git_config_refresh(cfg)); + + cl_git_pass(git_config_get_int32(&v, cfg, "section.value")); + cl_assert_equal_i(10, v); + + git_config_free(cfg); +} + +void test_config_refresh__delete_value(void) +{ + git_config *cfg; + int32_t v; + + cl_git_mkfile(TEST_FILE, "[section]\n\tvalue = 1\n\n"); + + /* By freeing the config, we make sure we flush the values */ + cl_git_pass(git_config_open_ondisk(&cfg, TEST_FILE)); + + cl_git_pass(git_config_get_int32(&v, cfg, "section.value")); + cl_assert_equal_i(1, v); + cl_git_fail(git_config_get_int32(&v, cfg, "section.newval")); + + cl_git_rewritefile(TEST_FILE, "[section]\n\tnewval = 10\n\n"); + + cl_git_pass(git_config_get_int32(&v, cfg, "section.value")); + cl_assert_equal_i(1, v); + cl_git_fail(git_config_get_int32(&v, cfg, "section.newval")); + + cl_git_pass(git_config_refresh(cfg)); + + cl_git_fail(git_config_get_int32(&v, cfg, "section.value")); + cl_git_pass(git_config_get_int32(&v, cfg, "section.newval")); + cl_assert_equal_i(10, v); + + git_config_free(cfg); +} diff --git a/tests/config/stress.c b/tests/config/stress.c new file mode 100644 index 000000000..eeca54ff4 --- /dev/null +++ b/tests/config/stress.c @@ -0,0 +1,92 @@ +#include "clar_libgit2.h" + +#include "filebuf.h" +#include "fileops.h" +#include "posix.h" + +#define TEST_CONFIG "git-test-config" + +void test_config_stress__initialize(void) +{ + git_filebuf file = GIT_FILEBUF_INIT; + + cl_git_pass(git_filebuf_open(&file, TEST_CONFIG, 0, 0666)); + + git_filebuf_printf(&file, "[color]\n\tui = auto\n"); + git_filebuf_printf(&file, "[core]\n\teditor = \n"); + + cl_git_pass(git_filebuf_commit(&file)); +} + +void test_config_stress__cleanup(void) +{ + p_unlink(TEST_CONFIG); +} + +void test_config_stress__dont_break_on_invalid_input(void) +{ + const char *editor, *color; + git_config *config; + + cl_assert(git_path_exists(TEST_CONFIG)); + cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); + + cl_git_pass(git_config_get_string(&color, config, "color.ui")); + cl_git_pass(git_config_get_string(&editor, config, "core.editor")); + + git_config_free(config); +} + +void test_config_stress__comments(void) +{ + git_config *config; + const char *str; + + cl_git_pass(git_config_open_ondisk(&config, cl_fixture("config/config12"))); + + cl_git_pass(git_config_get_string(&str, config, "some.section.other")); + cl_assert_equal_s("hello! \" ; ; ; ", str); + + cl_git_pass(git_config_get_string(&str, config, "some.section.multi")); + cl_assert_equal_s("hi, this is a ; multiline comment # with ;\n special chars and other stuff !@#", str); + + cl_git_pass(git_config_get_string(&str, config, "some.section.back")); + cl_assert_equal_s("this is \ba phrase", str); + + git_config_free(config); +} + +void test_config_stress__escape_subsection_names(void) +{ + git_config *config; + const char *str; + + cl_assert(git_path_exists("git-test-config")); + cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); + + cl_git_pass(git_config_set_string(config, "some.sec\\tion.other", "foo")); + git_config_free(config); + + cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); + + cl_git_pass(git_config_get_string(&str, config, "some.sec\\tion.other")); + cl_assert_equal_s("foo", str); + git_config_free(config); +} + +void test_config_stress__trailing_backslash(void) +{ + git_config *config; + const char *str; + const char *path = "C:\\iam\\some\\windows\\path\\"; + + cl_assert(git_path_exists("git-test-config")); + cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); + cl_git_pass(git_config_set_string(config, "windows.path", path)); + git_config_free(config); + + cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); + cl_git_pass(git_config_get_string(&str, config, "windows.path")); + cl_assert_equal_s(path, str); + git_config_free(config); +} diff --git a/tests/config/validkeyname.c b/tests/config/validkeyname.c new file mode 100644 index 000000000..33699737b --- /dev/null +++ b/tests/config/validkeyname.c @@ -0,0 +1,68 @@ +#include "clar_libgit2.h" + +#include "config.h" + +static git_config *cfg; +static const char *value; + +void test_config_validkeyname__initialize(void) +{ + cl_fixture_sandbox("config/config10"); + + cl_git_pass(git_config_open_ondisk(&cfg, "config10")); +} + +void test_config_validkeyname__cleanup(void) +{ + git_config_free(cfg); + cfg = NULL; + + cl_fixture_cleanup("config10"); +} + +static void assert_invalid_config_key_name(const char *name) +{ + cl_git_fail_with(git_config_get_string(&value, cfg, name), + GIT_EINVALIDSPEC); + cl_git_fail_with(git_config_set_string(cfg, name, "42"), + GIT_EINVALIDSPEC); + cl_git_fail_with(git_config_delete_entry(cfg, name), + GIT_EINVALIDSPEC); + cl_git_fail_with(git_config_get_multivar_foreach(cfg, name, "*", NULL, NULL), + GIT_EINVALIDSPEC); + cl_git_fail_with(git_config_set_multivar(cfg, name, "*", "42"), + GIT_EINVALIDSPEC); +} + +void test_config_validkeyname__accessing_requires_a_valid_name(void) +{ + assert_invalid_config_key_name(""); + assert_invalid_config_key_name("."); + assert_invalid_config_key_name(".."); + assert_invalid_config_key_name("core."); + assert_invalid_config_key_name("d#ff.dirstat.lines"); + assert_invalid_config_key_name("diff.dirstat.lines#"); + assert_invalid_config_key_name("dif\nf.dirstat.lines"); + assert_invalid_config_key_name("dif.dir\nstat.lines"); + assert_invalid_config_key_name("dif.dirstat.li\nes"); +} + +static void assert_invalid_config_section_name(git_repository *repo, const char *name) +{ + cl_git_fail_with(git_config_rename_section(repo, "branch.remoteless", name), GIT_EINVALIDSPEC); +} + +void test_config_validkeyname__renaming_a_section_requires_a_valid_name(void) +{ + git_repository *repo; + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + + assert_invalid_config_section_name(repo, ""); + assert_invalid_config_section_name(repo, "bra\nch"); + assert_invalid_config_section_name(repo, "branc#"); + assert_invalid_config_section_name(repo, "bra\nch.duh"); + assert_invalid_config_section_name(repo, "branc#.duh"); + + git_repository_free(repo); +} diff --git a/tests/config/write.c b/tests/config/write.c new file mode 100644 index 000000000..15f750dc0 --- /dev/null +++ b/tests/config/write.c @@ -0,0 +1,305 @@ +#include "clar_libgit2.h" + +void test_config_write__initialize(void) +{ + cl_fixture_sandbox("config/config9"); + cl_fixture_sandbox("config/config15"); + cl_fixture_sandbox("config/config17"); +} + +void test_config_write__cleanup(void) +{ + cl_fixture_cleanup("config9"); + cl_fixture_cleanup("config15"); + cl_fixture_cleanup("config17"); +} + +void test_config_write__replace_value(void) +{ + git_config *cfg; + int i; + int64_t l, expected = +9223372036854775803; + + /* By freeing the config, we make sure we flush the values */ + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_set_int32(cfg, "core.dummy", 5)); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_get_int32(&i, cfg, "core.dummy")); + cl_assert(i == 5); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_set_int32(cfg, "core.dummy", 1)); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_set_int64(cfg, "core.verylong", expected)); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_get_int64(&l, cfg, "core.verylong")); + cl_assert(l == expected); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_must_fail(git_config_get_int32(&i, cfg, "core.verylong")); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_set_int64(cfg, "core.verylong", 1)); + git_config_free(cfg); +} + +void test_config_write__delete_value(void) +{ + git_config *cfg; + int32_t i; + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_set_int32(cfg, "core.dummy", 5)); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_delete_entry(cfg, "core.dummy")); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_assert(git_config_get_int32(&i, cfg, "core.dummy") == GIT_ENOTFOUND); + cl_git_pass(git_config_set_int32(cfg, "core.dummy", 1)); + git_config_free(cfg); +} + +/* + * At the beginning of the test: + * - config9 has: core.dummy2=42 + * - config15 has: core.dummy2=7 + */ +void test_config_write__delete_value_at_specific_level(void) +{ + git_config *cfg, *cfg_specific; + int32_t i; + + cl_git_pass(git_config_open_ondisk(&cfg, "config15")); + cl_git_pass(git_config_get_int32(&i, cfg, "core.dummy2")); + cl_assert(i == 7); + git_config_free(cfg); + + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, "config9", + GIT_CONFIG_LEVEL_LOCAL, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, "config15", + GIT_CONFIG_LEVEL_GLOBAL, 0)); + + cl_git_pass(git_config_open_level(&cfg_specific, cfg, GIT_CONFIG_LEVEL_GLOBAL)); + + cl_git_pass(git_config_delete_entry(cfg_specific, "core.dummy2")); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config15")); + cl_assert(git_config_get_int32(&i, cfg, "core.dummy2") == GIT_ENOTFOUND); + cl_git_pass(git_config_set_int32(cfg, "core.dummy2", 7)); + + git_config_free(cfg_specific); + git_config_free(cfg); +} + +void test_config_write__write_subsection(void) +{ + git_config *cfg; + const char *str; + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_set_string(cfg, "my.own.var", "works")); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_get_string(&str, cfg, "my.own.var")); + cl_assert_equal_s("works", str); + git_config_free(cfg); +} + +void test_config_write__delete_inexistent(void) +{ + git_config *cfg; + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_assert(git_config_delete_entry(cfg, "core.imaginary") == GIT_ENOTFOUND); + git_config_free(cfg); +} + +void test_config_write__value_containing_quotes(void) +{ + git_config *cfg; + const char* str; + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_set_string(cfg, "core.somevar", "this \"has\" quotes")); + cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); + cl_assert_equal_s(str, "this \"has\" quotes"); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); + cl_assert_equal_s(str, "this \"has\" quotes"); + git_config_free(cfg); + + /* The code path for values that already exist is different, check that one as well */ + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_set_string(cfg, "core.somevar", "this also \"has\" quotes")); + cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); + cl_assert_equal_s(str, "this also \"has\" quotes"); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); + cl_assert_equal_s(str, "this also \"has\" quotes"); + git_config_free(cfg); +} + +void test_config_write__escape_value(void) +{ + git_config *cfg; + const char* str; + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_set_string(cfg, "core.somevar", "this \"has\" quotes and \t")); + cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); + cl_assert_equal_s(str, "this \"has\" quotes and \t"); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + cl_git_pass(git_config_get_string(&str, cfg, "core.somevar")); + cl_assert_equal_s(str, "this \"has\" quotes and \t"); + git_config_free(cfg); +} + +void test_config_write__add_value_at_specific_level(void) +{ + git_config *cfg, *cfg_specific; + int i; + int64_t l, expected = +9223372036854775803; + const char *s; + + // open config15 as global level config file + cl_git_pass(git_config_new(&cfg)); + cl_git_pass(git_config_add_file_ondisk(cfg, "config9", + GIT_CONFIG_LEVEL_LOCAL, 0)); + cl_git_pass(git_config_add_file_ondisk(cfg, "config15", + GIT_CONFIG_LEVEL_GLOBAL, 0)); + + cl_git_pass(git_config_open_level(&cfg_specific, cfg, GIT_CONFIG_LEVEL_GLOBAL)); + + cl_git_pass(git_config_set_int32(cfg_specific, "core.int32global", 28)); + cl_git_pass(git_config_set_int64(cfg_specific, "core.int64global", expected)); + cl_git_pass(git_config_set_bool(cfg_specific, "core.boolglobal", true)); + cl_git_pass(git_config_set_string(cfg_specific, "core.stringglobal", "I'm a global config value!")); + git_config_free(cfg_specific); + git_config_free(cfg); + + // open config15 as local level config file + cl_git_pass(git_config_open_ondisk(&cfg, "config15")); + + cl_git_pass(git_config_get_int32(&i, cfg, "core.int32global")); + cl_assert_equal_i(28, i); + cl_git_pass(git_config_get_int64(&l, cfg, "core.int64global")); + cl_assert(l == expected); + cl_git_pass(git_config_get_bool(&i, cfg, "core.boolglobal")); + cl_assert_equal_b(true, i); + cl_git_pass(git_config_get_string(&s, cfg, "core.stringglobal")); + cl_assert_equal_s("I'm a global config value!", s); + + git_config_free(cfg); +} + +void test_config_write__add_value_at_file_with_no_clrf_at_the_end(void) +{ + git_config *cfg; + int i; + + cl_git_pass(git_config_open_ondisk(&cfg, "config17")); + cl_git_pass(git_config_set_int32(cfg, "core.newline", 7)); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config17")); + cl_git_pass(git_config_get_int32(&i, cfg, "core.newline")); + cl_assert_equal_i(7, i); + + git_config_free(cfg); +} + +void test_config_write__add_value_which_needs_quotes(void) +{ + git_config *cfg; + const char* str1; + const char* str2; + const char* str3; + const char* str4; + const char* str5; + + cl_git_pass(git_config_open_ondisk(&cfg, "config17")); + cl_git_pass(git_config_set_string(cfg, "core.startwithspace", " Something")); + cl_git_pass(git_config_set_string(cfg, "core.endwithspace", "Something ")); + cl_git_pass(git_config_set_string(cfg, "core.containscommentchar1", "some#thing")); + cl_git_pass(git_config_set_string(cfg, "core.containscommentchar2", "some;thing")); + cl_git_pass(git_config_set_string(cfg, "core.startwhithsapceandcontainsdoublequote", " some\"thing")); + git_config_free(cfg); + + cl_git_pass(git_config_open_ondisk(&cfg, "config17")); + cl_git_pass(git_config_get_string(&str1, cfg, "core.startwithspace")); + cl_assert_equal_s(" Something", str1); + cl_git_pass(git_config_get_string(&str2, cfg, "core.endwithspace")); + cl_assert_equal_s("Something ", str2); + cl_git_pass(git_config_get_string(&str3, cfg, "core.containscommentchar1")); + cl_assert_equal_s("some#thing", str3); + cl_git_pass(git_config_get_string(&str4, cfg, "core.containscommentchar2")); + cl_assert_equal_s("some;thing", str4); + cl_git_pass(git_config_get_string(&str5, cfg, "core.startwhithsapceandcontainsdoublequote")); + cl_assert_equal_s(" some\"thing", str5); + git_config_free(cfg); +} + +void test_config_write__can_set_a_value_to_NULL(void) +{ + git_repository *repository; + git_config *config; + + repository = cl_git_sandbox_init("testrepo.git"); + + cl_git_pass(git_repository_config(&config, repository)); + cl_git_fail(git_config_set_string(config, "a.b.c", NULL)); + git_config_free(config); + + cl_git_sandbox_cleanup(); +} + +void test_config_write__can_set_an_empty_value(void) +{ + git_repository *repository; + git_config *config; + const char * str; + + repository = cl_git_sandbox_init("testrepo.git"); + cl_git_pass(git_repository_config(&config, repository)); + + cl_git_pass(git_config_set_string(config, "core.somevar", "")); + cl_git_pass(git_config_get_string(&str, config, "core.somevar")); + cl_assert_equal_s(str, ""); + + git_config_free(config); + cl_git_sandbox_cleanup(); +} + +void test_config_write__updating_a_locked_config_file_returns_ELOCKED(void) +{ + git_config *cfg; + + cl_git_pass(git_config_open_ondisk(&cfg, "config9")); + + cl_git_mkfile("config9.lock", "[core]\n"); + + cl_git_fail_with(git_config_set_string(cfg, "core.dump", "boom"), GIT_ELOCKED); + + git_config_free(cfg); +} diff --git a/tests/core/bitvec.c b/tests/core/bitvec.c new file mode 100644 index 000000000..48d7b99f0 --- /dev/null +++ b/tests/core/bitvec.c @@ -0,0 +1,64 @@ +#include "clar_libgit2.h" +#include "bitvec.h" + +#if 0 +static void print_bitvec(git_bitvec *bv) +{ + int b; + + if (!bv->length) { + for (b = 63; b >= 0; --b) + fprintf(stderr, "%d", (bv->u.bits & (1ul << b)) ? 1 : 0); + } else { + for (b = bv->length * 8; b >= 0; --b) + fprintf(stderr, "%d", (bv->u.ptr[b >> 3] & (b & 0x0ff)) ? 1 : 0); + } + fprintf(stderr, "\n"); +} +#endif + +static void set_some_bits(git_bitvec *bv, size_t length) +{ + size_t i; + + for (i = 0; i < length; ++i) { + if (i % 3 == 0 || i % 7 == 0) + git_bitvec_set(bv, i, true); + } +} + +static void check_some_bits(git_bitvec *bv, size_t length) +{ + size_t i; + + for (i = 0; i < length; ++i) + cl_assert_equal_b(i % 3 == 0 || i % 7 == 0, git_bitvec_get(bv, i)); +} + +void test_core_bitvec__0(void) +{ + git_bitvec bv; + + cl_git_pass(git_bitvec_init(&bv, 32)); + set_some_bits(&bv, 16); + check_some_bits(&bv, 16); + git_bitvec_clear(&bv); + set_some_bits(&bv, 32); + check_some_bits(&bv, 32); + git_bitvec_clear(&bv); + set_some_bits(&bv, 64); + check_some_bits(&bv, 64); + git_bitvec_free(&bv); + + cl_git_pass(git_bitvec_init(&bv, 128)); + set_some_bits(&bv, 32); + check_some_bits(&bv, 32); + set_some_bits(&bv, 128); + check_some_bits(&bv, 128); + git_bitvec_free(&bv); + + cl_git_pass(git_bitvec_init(&bv, 4000)); + set_some_bits(&bv, 4000); + check_some_bits(&bv, 4000); + git_bitvec_free(&bv); +} diff --git a/tests/core/buffer.c b/tests/core/buffer.c new file mode 100644 index 000000000..11d173d49 --- /dev/null +++ b/tests/core/buffer.c @@ -0,0 +1,1039 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "buf_text.h" +#include "hashsig.h" +#include "fileops.h" + +#define TESTSTR "Have you seen that? Have you seeeen that??" +const char *test_string = TESTSTR; +const char *test_string_x2 = TESTSTR TESTSTR; + +#define TESTSTR_4096 REP1024("1234") +#define TESTSTR_8192 REP1024("12341234") +const char *test_4096 = TESTSTR_4096; +const char *test_8192 = TESTSTR_8192; + +/* test basic data concatenation */ +void test_core_buffer__0(void) +{ + git_buf buf = GIT_BUF_INIT; + + cl_assert(buf.size == 0); + + git_buf_puts(&buf, test_string); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(test_string, git_buf_cstr(&buf)); + + git_buf_puts(&buf, test_string); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(test_string_x2, git_buf_cstr(&buf)); + + git_buf_free(&buf); +} + +/* test git_buf_printf */ +void test_core_buffer__1(void) +{ + git_buf buf = GIT_BUF_INIT; + + git_buf_printf(&buf, "%s %s %d ", "shoop", "da", 23); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s("shoop da 23 ", git_buf_cstr(&buf)); + + git_buf_printf(&buf, "%s %d", "woop", 42); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s("shoop da 23 woop 42", git_buf_cstr(&buf)); + + git_buf_free(&buf); +} + +/* more thorough test of concatenation options */ +void test_core_buffer__2(void) +{ + git_buf buf = GIT_BUF_INIT; + int i; + char data[128]; + + cl_assert(buf.size == 0); + + /* this must be safe to do */ + git_buf_free(&buf); + cl_assert(buf.size == 0); + cl_assert(buf.asize == 0); + + /* empty buffer should be empty string */ + cl_assert_equal_s("", git_buf_cstr(&buf)); + cl_assert(buf.size == 0); + /* cl_assert(buf.asize == 0); -- should not assume what git_buf does */ + + /* free should set us back to the beginning */ + git_buf_free(&buf); + cl_assert(buf.size == 0); + cl_assert(buf.asize == 0); + + /* add letter */ + git_buf_putc(&buf, '+'); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s("+", git_buf_cstr(&buf)); + + /* add letter again */ + git_buf_putc(&buf, '+'); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s("++", git_buf_cstr(&buf)); + + /* let's try that a few times */ + for (i = 0; i < 16; ++i) { + git_buf_putc(&buf, '+'); + cl_assert(git_buf_oom(&buf) == 0); + } + cl_assert_equal_s("++++++++++++++++++", git_buf_cstr(&buf)); + + git_buf_free(&buf); + + /* add data */ + git_buf_put(&buf, "xo", 2); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s("xo", git_buf_cstr(&buf)); + + /* add letter again */ + git_buf_put(&buf, "xo", 2); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s("xoxo", git_buf_cstr(&buf)); + + /* let's try that a few times */ + for (i = 0; i < 16; ++i) { + git_buf_put(&buf, "xo", 2); + cl_assert(git_buf_oom(&buf) == 0); + } + cl_assert_equal_s("xoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxo", + git_buf_cstr(&buf)); + + git_buf_free(&buf); + + /* set to string */ + git_buf_sets(&buf, test_string); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(test_string, git_buf_cstr(&buf)); + + /* append string */ + git_buf_puts(&buf, test_string); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(test_string_x2, git_buf_cstr(&buf)); + + /* set to string again (should overwrite - not append) */ + git_buf_sets(&buf, test_string); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(test_string, git_buf_cstr(&buf)); + + /* test clear */ + git_buf_clear(&buf); + cl_assert_equal_s("", git_buf_cstr(&buf)); + + git_buf_free(&buf); + + /* test extracting data into buffer */ + git_buf_puts(&buf, REP4("0123456789")); + cl_assert(git_buf_oom(&buf) == 0); + + git_buf_copy_cstr(data, sizeof(data), &buf); + cl_assert_equal_s(REP4("0123456789"), data); + git_buf_copy_cstr(data, 11, &buf); + cl_assert_equal_s("0123456789", data); + git_buf_copy_cstr(data, 3, &buf); + cl_assert_equal_s("01", data); + git_buf_copy_cstr(data, 1, &buf); + cl_assert_equal_s("", data); + + git_buf_copy_cstr(data, sizeof(data), &buf); + cl_assert_equal_s(REP4("0123456789"), data); + + git_buf_sets(&buf, REP256("x")); + git_buf_copy_cstr(data, sizeof(data), &buf); + /* since sizeof(data) == 128, only 127 bytes should be copied */ + cl_assert_equal_s(REP4(REP16("x")) REP16("x") REP16("x") + REP16("x") "xxxxxxxxxxxxxxx", data); + + git_buf_free(&buf); + + git_buf_copy_cstr(data, sizeof(data), &buf); + cl_assert_equal_s("", data); +} + +/* let's do some tests with larger buffers to push our limits */ +void test_core_buffer__3(void) +{ + git_buf buf = GIT_BUF_INIT; + + /* set to string */ + git_buf_set(&buf, test_4096, 4096); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(test_4096, git_buf_cstr(&buf)); + + /* append string */ + git_buf_puts(&buf, test_4096); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(test_8192, git_buf_cstr(&buf)); + + /* set to string again (should overwrite - not append) */ + git_buf_set(&buf, test_4096, 4096); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(test_4096, git_buf_cstr(&buf)); + + git_buf_free(&buf); +} + +/* let's try some producer/consumer tests */ +void test_core_buffer__4(void) +{ + git_buf buf = GIT_BUF_INIT; + int i; + + for (i = 0; i < 10; ++i) { + git_buf_puts(&buf, "1234"); /* add 4 */ + cl_assert(git_buf_oom(&buf) == 0); + git_buf_consume(&buf, buf.ptr + 2); /* eat the first two */ + cl_assert(strlen(git_buf_cstr(&buf)) == (size_t)((i + 1) * 2)); + } + /* we have appended 1234 10x and removed the first 20 letters */ + cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf)); + + git_buf_consume(&buf, NULL); + cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf)); + + git_buf_consume(&buf, "invalid pointer"); + cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf)); + + git_buf_consume(&buf, buf.ptr); + cl_assert_equal_s("12341234123412341234", git_buf_cstr(&buf)); + + git_buf_consume(&buf, buf.ptr + 1); + cl_assert_equal_s("2341234123412341234", git_buf_cstr(&buf)); + + git_buf_consume(&buf, buf.ptr + buf.size); + cl_assert_equal_s("", git_buf_cstr(&buf)); + + git_buf_free(&buf); +} + + +static void +check_buf_append( + const char* data_a, + const char* data_b, + const char* expected_data, + size_t expected_size, + size_t expected_asize) +{ + git_buf tgt = GIT_BUF_INIT; + + git_buf_sets(&tgt, data_a); + cl_assert(git_buf_oom(&tgt) == 0); + git_buf_puts(&tgt, data_b); + cl_assert(git_buf_oom(&tgt) == 0); + cl_assert_equal_s(expected_data, git_buf_cstr(&tgt)); + cl_assert(tgt.size == expected_size); + if (expected_asize > 0) + cl_assert(tgt.asize == expected_asize); + + git_buf_free(&tgt); +} + +static void +check_buf_append_abc( + const char* buf_a, + const char* buf_b, + const char* buf_c, + const char* expected_ab, + const char* expected_abc, + const char* expected_abca, + const char* expected_abcab, + const char* expected_abcabc) +{ + git_buf buf = GIT_BUF_INIT; + + git_buf_sets(&buf, buf_a); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(buf_a, git_buf_cstr(&buf)); + + git_buf_puts(&buf, buf_b); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(expected_ab, git_buf_cstr(&buf)); + + git_buf_puts(&buf, buf_c); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(expected_abc, git_buf_cstr(&buf)); + + git_buf_puts(&buf, buf_a); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(expected_abca, git_buf_cstr(&buf)); + + git_buf_puts(&buf, buf_b); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(expected_abcab, git_buf_cstr(&buf)); + + git_buf_puts(&buf, buf_c); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(expected_abcabc, git_buf_cstr(&buf)); + + git_buf_free(&buf); +} + +/* more variations on append tests */ +void test_core_buffer__5(void) +{ + check_buf_append("", "", "", 0, 8); + check_buf_append("a", "", "a", 1, 8); + check_buf_append("", "a", "a", 1, 8); + check_buf_append("", "a", "a", 1, 8); + check_buf_append("a", "", "a", 1, 8); + check_buf_append("a", "b", "ab", 2, 8); + check_buf_append("", "abcdefgh", "abcdefgh", 8, 16); + check_buf_append("abcdefgh", "", "abcdefgh", 8, 16); + + /* buffer with starting asize will grow to: + * 1 -> 2, 2 -> 3, 3 -> 5, 4 -> 6, 5 -> 8, 6 -> 9, + * 7 -> 11, 8 -> 12, 9 -> 14, 10 -> 15, 11 -> 17, 12 -> 18, + * 13 -> 20, 14 -> 21, 15 -> 23, 16 -> 24, 17 -> 26, 18 -> 27, + * 19 -> 29, 20 -> 30, 21 -> 32, 22 -> 33, 23 -> 35, 24 -> 36, + * ... + * follow sequence until value > target size, + * then round up to nearest multiple of 8. + */ + + check_buf_append("abcdefgh", "/", "abcdefgh/", 9, 16); + check_buf_append("abcdefgh", "ijklmno", "abcdefghijklmno", 15, 16); + check_buf_append("abcdefgh", "ijklmnop", "abcdefghijklmnop", 16, 24); + check_buf_append("0123456789", "0123456789", + "01234567890123456789", 20, 24); + check_buf_append(REP16("x"), REP16("o"), + REP16("x") REP16("o"), 32, 40); + + check_buf_append(test_4096, "", test_4096, 4096, 4104); + check_buf_append(test_4096, test_4096, test_8192, 8192, 9240); + + /* check sequences of appends */ + check_buf_append_abc("a", "b", "c", + "ab", "abc", "abca", "abcab", "abcabc"); + check_buf_append_abc("a1", "b2", "c3", + "a1b2", "a1b2c3", "a1b2c3a1", + "a1b2c3a1b2", "a1b2c3a1b2c3"); + check_buf_append_abc("a1/", "b2/", "c3/", + "a1/b2/", "a1/b2/c3/", "a1/b2/c3/a1/", + "a1/b2/c3/a1/b2/", "a1/b2/c3/a1/b2/c3/"); +} + +/* test swap */ +void test_core_buffer__6(void) +{ + git_buf a = GIT_BUF_INIT; + git_buf b = GIT_BUF_INIT; + + git_buf_sets(&a, "foo"); + cl_assert(git_buf_oom(&a) == 0); + git_buf_sets(&b, "bar"); + cl_assert(git_buf_oom(&b) == 0); + + cl_assert_equal_s("foo", git_buf_cstr(&a)); + cl_assert_equal_s("bar", git_buf_cstr(&b)); + + git_buf_swap(&a, &b); + + cl_assert_equal_s("bar", git_buf_cstr(&a)); + cl_assert_equal_s("foo", git_buf_cstr(&b)); + + git_buf_free(&a); + git_buf_free(&b); +} + + +/* test detach/attach data */ +void test_core_buffer__7(void) +{ + const char *fun = "This is fun"; + git_buf a = GIT_BUF_INIT; + char *b = NULL; + + git_buf_sets(&a, "foo"); + cl_assert(git_buf_oom(&a) == 0); + cl_assert_equal_s("foo", git_buf_cstr(&a)); + + b = git_buf_detach(&a); + + cl_assert_equal_s("foo", b); + cl_assert_equal_s("", a.ptr); + git__free(b); + + b = git_buf_detach(&a); + + cl_assert_equal_s(NULL, b); + cl_assert_equal_s("", a.ptr); + + git_buf_free(&a); + + b = git__strdup(fun); + git_buf_attach(&a, b, 0); + + cl_assert_equal_s(fun, a.ptr); + cl_assert(a.size == strlen(fun)); + cl_assert(a.asize == strlen(fun) + 1); + + git_buf_free(&a); + + b = git__strdup(fun); + git_buf_attach(&a, b, strlen(fun) + 1); + + cl_assert_equal_s(fun, a.ptr); + cl_assert(a.size == strlen(fun)); + cl_assert(a.asize == strlen(fun) + 1); + + git_buf_free(&a); +} + + +static void +check_joinbuf_2( + const char *a, + const char *b, + const char *expected) +{ + char sep = '/'; + git_buf buf = GIT_BUF_INIT; + + git_buf_join(&buf, sep, a, b); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(expected, git_buf_cstr(&buf)); + git_buf_free(&buf); +} + +static void +check_joinbuf_n_2( + const char *a, + const char *b, + const char *expected) +{ + char sep = '/'; + git_buf buf = GIT_BUF_INIT; + + git_buf_sets(&buf, a); + cl_assert(git_buf_oom(&buf) == 0); + + git_buf_join_n(&buf, sep, 1, b); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(expected, git_buf_cstr(&buf)); + + git_buf_free(&buf); +} + +static void +check_joinbuf_n_4( + const char *a, + const char *b, + const char *c, + const char *d, + const char *expected) +{ + char sep = ';'; + git_buf buf = GIT_BUF_INIT; + git_buf_join_n(&buf, sep, 4, a, b, c, d); + cl_assert(git_buf_oom(&buf) == 0); + cl_assert_equal_s(expected, git_buf_cstr(&buf)); + git_buf_free(&buf); +} + +/* test join */ +void test_core_buffer__8(void) +{ + git_buf a = GIT_BUF_INIT; + + git_buf_join_n(&a, '/', 1, "foo"); + cl_assert(git_buf_oom(&a) == 0); + cl_assert_equal_s("foo", git_buf_cstr(&a)); + + git_buf_join_n(&a, '/', 1, "bar"); + cl_assert(git_buf_oom(&a) == 0); + cl_assert_equal_s("foo/bar", git_buf_cstr(&a)); + + git_buf_join_n(&a, '/', 1, "baz"); + cl_assert(git_buf_oom(&a) == 0); + cl_assert_equal_s("foo/bar/baz", git_buf_cstr(&a)); + + git_buf_free(&a); + + check_joinbuf_2(NULL, "", ""); + check_joinbuf_2(NULL, "a", "a"); + check_joinbuf_2(NULL, "/a", "/a"); + check_joinbuf_2("", "", ""); + check_joinbuf_2("", "a", "a"); + check_joinbuf_2("", "/a", "/a"); + check_joinbuf_2("a", "", "a/"); + check_joinbuf_2("a", "/", "a/"); + check_joinbuf_2("a", "b", "a/b"); + check_joinbuf_2("/", "a", "/a"); + check_joinbuf_2("/", "", "/"); + check_joinbuf_2("/a", "/b", "/a/b"); + check_joinbuf_2("/a", "/b/", "/a/b/"); + check_joinbuf_2("/a/", "b/", "/a/b/"); + check_joinbuf_2("/a/", "/b/", "/a/b/"); + check_joinbuf_2("/a/", "//b/", "/a/b/"); + check_joinbuf_2("/abcd", "/defg", "/abcd/defg"); + check_joinbuf_2("/abcd", "/defg/", "/abcd/defg/"); + check_joinbuf_2("/abcd/", "defg/", "/abcd/defg/"); + check_joinbuf_2("/abcd/", "/defg/", "/abcd/defg/"); + + check_joinbuf_n_2("", "", ""); + check_joinbuf_n_2("", "a", "a"); + check_joinbuf_n_2("", "/a", "/a"); + check_joinbuf_n_2("a", "", "a/"); + check_joinbuf_n_2("a", "/", "a/"); + check_joinbuf_n_2("a", "b", "a/b"); + check_joinbuf_n_2("/", "a", "/a"); + check_joinbuf_n_2("/", "", "/"); + check_joinbuf_n_2("/a", "/b", "/a/b"); + check_joinbuf_n_2("/a", "/b/", "/a/b/"); + check_joinbuf_n_2("/a/", "b/", "/a/b/"); + check_joinbuf_n_2("/a/", "/b/", "/a/b/"); + check_joinbuf_n_2("/abcd", "/defg", "/abcd/defg"); + check_joinbuf_n_2("/abcd", "/defg/", "/abcd/defg/"); + check_joinbuf_n_2("/abcd/", "defg/", "/abcd/defg/"); + check_joinbuf_n_2("/abcd/", "/defg/", "/abcd/defg/"); + + check_joinbuf_n_4("", "", "", "", ""); + check_joinbuf_n_4("", "a", "", "", "a;"); + check_joinbuf_n_4("a", "", "", "", "a;"); + check_joinbuf_n_4("", "", "", "a", "a"); + check_joinbuf_n_4("a", "b", "", ";c;d;", "a;b;c;d;"); + check_joinbuf_n_4("a", "b", "", ";c;d", "a;b;c;d"); + check_joinbuf_n_4("abcd", "efgh", "ijkl", "mnop", "abcd;efgh;ijkl;mnop"); + check_joinbuf_n_4("abcd;", "efgh;", "ijkl;", "mnop;", "abcd;efgh;ijkl;mnop;"); + check_joinbuf_n_4(";abcd;", ";efgh;", ";ijkl;", ";mnop;", ";abcd;efgh;ijkl;mnop;"); +} + +void test_core_buffer__9(void) +{ + git_buf buf = GIT_BUF_INIT; + + /* just some exhaustive tests of various separator placement */ + char *a[] = { "", "-", "a-", "-a", "-a-" }; + char *b[] = { "", "-", "b-", "-b", "-b-" }; + char sep[] = { 0, '-', '/' }; + char *expect_null[] = { "", "-", "a-", "-a", "-a-", + "-", "--", "a--", "-a-", "-a--", + "b-", "-b-", "a-b-", "-ab-", "-a-b-", + "-b", "--b", "a--b", "-a-b", "-a--b", + "-b-", "--b-", "a--b-", "-a-b-", "-a--b-" }; + char *expect_dash[] = { "", "-", "a-", "-a-", "-a-", + "-", "-", "a-", "-a-", "-a-", + "b-", "-b-", "a-b-", "-a-b-", "-a-b-", + "-b", "-b", "a-b", "-a-b", "-a-b", + "-b-", "-b-", "a-b-", "-a-b-", "-a-b-" }; + char *expect_slas[] = { "", "-/", "a-/", "-a/", "-a-/", + "-", "-/-", "a-/-", "-a/-", "-a-/-", + "b-", "-/b-", "a-/b-", "-a/b-", "-a-/b-", + "-b", "-/-b", "a-/-b", "-a/-b", "-a-/-b", + "-b-", "-/-b-", "a-/-b-", "-a/-b-", "-a-/-b-" }; + char **expect_values[] = { expect_null, expect_dash, expect_slas }; + char separator, **expect; + unsigned int s, i, j; + + for (s = 0; s < sizeof(sep) / sizeof(char); ++s) { + separator = sep[s]; + expect = expect_values[s]; + + for (j = 0; j < sizeof(b) / sizeof(char*); ++j) { + for (i = 0; i < sizeof(a) / sizeof(char*); ++i) { + git_buf_join(&buf, separator, a[i], b[j]); + cl_assert_equal_s(*expect, buf.ptr); + expect++; + } + } + } + + git_buf_free(&buf); +} + +void test_core_buffer__10(void) +{ + git_buf a = GIT_BUF_INIT; + + cl_git_pass(git_buf_join_n(&a, '/', 1, "test")); + cl_assert_equal_s(a.ptr, "test"); + cl_git_pass(git_buf_join_n(&a, '/', 1, "string")); + cl_assert_equal_s(a.ptr, "test/string"); + git_buf_clear(&a); + cl_git_pass(git_buf_join_n(&a, '/', 3, "test", "string", "join")); + cl_assert_equal_s(a.ptr, "test/string/join"); + cl_git_pass(git_buf_join_n(&a, '/', 2, a.ptr, "more")); + cl_assert_equal_s(a.ptr, "test/string/join/test/string/join/more"); + + git_buf_free(&a); +} + +void test_core_buffer__11(void) +{ + git_buf a = GIT_BUF_INIT; + git_strarray t; + char *t1[] = { "nothing", "in", "common" }; + char *t2[] = { "something", "something else", "some other" }; + char *t3[] = { "something", "some fun", "no fun" }; + char *t4[] = { "happy", "happier", "happiest" }; + char *t5[] = { "happiest", "happier", "happy" }; + char *t6[] = { "no", "nope", "" }; + char *t7[] = { "", "doesn't matter" }; + + t.strings = t1; + t.count = 3; + cl_git_pass(git_buf_text_common_prefix(&a, &t)); + cl_assert_equal_s(a.ptr, ""); + + t.strings = t2; + t.count = 3; + cl_git_pass(git_buf_text_common_prefix(&a, &t)); + cl_assert_equal_s(a.ptr, "some"); + + t.strings = t3; + t.count = 3; + cl_git_pass(git_buf_text_common_prefix(&a, &t)); + cl_assert_equal_s(a.ptr, ""); + + t.strings = t4; + t.count = 3; + cl_git_pass(git_buf_text_common_prefix(&a, &t)); + cl_assert_equal_s(a.ptr, "happ"); + + t.strings = t5; + t.count = 3; + cl_git_pass(git_buf_text_common_prefix(&a, &t)); + cl_assert_equal_s(a.ptr, "happ"); + + t.strings = t6; + t.count = 3; + cl_git_pass(git_buf_text_common_prefix(&a, &t)); + cl_assert_equal_s(a.ptr, ""); + + t.strings = t7; + t.count = 3; + cl_git_pass(git_buf_text_common_prefix(&a, &t)); + cl_assert_equal_s(a.ptr, ""); + + git_buf_free(&a); +} + +void test_core_buffer__rfind_variants(void) +{ + git_buf a = GIT_BUF_INIT; + ssize_t len; + + cl_git_pass(git_buf_sets(&a, "/this/is/it/")); + + len = (ssize_t)git_buf_len(&a); + + cl_assert(git_buf_rfind(&a, '/') == len - 1); + cl_assert(git_buf_rfind_next(&a, '/') == len - 4); + + cl_assert(git_buf_rfind(&a, 'i') == len - 3); + cl_assert(git_buf_rfind_next(&a, 'i') == len - 3); + + cl_assert(git_buf_rfind(&a, 'h') == 2); + cl_assert(git_buf_rfind_next(&a, 'h') == 2); + + cl_assert(git_buf_rfind(&a, 'q') == -1); + cl_assert(git_buf_rfind_next(&a, 'q') == -1); + + git_buf_free(&a); +} + +void test_core_buffer__puts_escaped(void) +{ + git_buf a = GIT_BUF_INIT; + + git_buf_clear(&a); + cl_git_pass(git_buf_text_puts_escaped(&a, "this is a test", "", "")); + cl_assert_equal_s("this is a test", a.ptr); + + git_buf_clear(&a); + cl_git_pass(git_buf_text_puts_escaped(&a, "this is a test", "t", "\\")); + cl_assert_equal_s("\\this is a \\tes\\t", a.ptr); + + git_buf_clear(&a); + cl_git_pass(git_buf_text_puts_escaped(&a, "this is a test", "i ", "__")); + cl_assert_equal_s("th__is__ __is__ a__ test", a.ptr); + + git_buf_clear(&a); + cl_git_pass(git_buf_text_puts_escape_regex(&a, "^match\\s*[A-Z]+.*")); + cl_assert_equal_s("\\^match\\\\s\\*\\[A-Z\\]\\+\\.\\*", a.ptr); + + git_buf_free(&a); +} + +static void assert_unescape(char *expected, char *to_unescape) { + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_buf_sets(&buf, to_unescape)); + git_buf_text_unescape(&buf); + cl_assert_equal_s(expected, buf.ptr); + cl_assert_equal_sz(strlen(expected), buf.size); + + git_buf_free(&buf); +} + +void test_core_buffer__unescape(void) +{ + assert_unescape("Escaped\\", "Es\\ca\\ped\\"); + assert_unescape("Es\\caped\\", "Es\\\\ca\\ped\\\\"); + assert_unescape("\\", "\\"); + assert_unescape("\\", "\\\\"); + assert_unescape("", ""); +} + +void test_core_buffer__base64(void) +{ + git_buf buf = GIT_BUF_INIT; + + /* t h i s + * 0x 74 68 69 73 + * 0b 01110100 01101000 01101001 01110011 + * 0b 011101 000110 100001 101001 011100 110000 + * 0x 1d 06 21 29 1c 30 + * d G h p c w + */ + cl_git_pass(git_buf_put_base64(&buf, "this", 4)); + cl_assert_equal_s("dGhpcw==", buf.ptr); + + git_buf_clear(&buf); + cl_git_pass(git_buf_put_base64(&buf, "this!", 5)); + cl_assert_equal_s("dGhpcyE=", buf.ptr); + + git_buf_clear(&buf); + cl_git_pass(git_buf_put_base64(&buf, "this!\n", 6)); + cl_assert_equal_s("dGhpcyEK", buf.ptr); + + git_buf_free(&buf); +} + +void test_core_buffer__classify_with_utf8(void) +{ + char *data0 = "Simple text\n"; + size_t data0len = 12; + char *data1 = "Is that UTF-8 data I see…\nYep!\n"; + size_t data1len = 31; + char *data2 = "Internal NUL!!!\000\n\nI see you!\n"; + size_t data2len = 29; + char *data3 = "\xef\xbb\xbfThis is UTF-8 with a BOM.\n"; + size_t data3len = 20; + git_buf b; + + b.ptr = data0; b.size = b.asize = data0len; + cl_assert(!git_buf_text_is_binary(&b)); + cl_assert(!git_buf_text_contains_nul(&b)); + + b.ptr = data1; b.size = b.asize = data1len; + cl_assert(git_buf_text_is_binary(&b)); + cl_assert(!git_buf_text_contains_nul(&b)); + + b.ptr = data2; b.size = b.asize = data2len; + cl_assert(git_buf_text_is_binary(&b)); + cl_assert(git_buf_text_contains_nul(&b)); + + b.ptr = data3; b.size = b.asize = data3len; + cl_assert(!git_buf_text_is_binary(&b)); + cl_assert(!git_buf_text_contains_nul(&b)); +} + +#define SIMILARITY_TEST_DATA_1 \ + "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \ + "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \ + "020\n021\n022\n023\n024\n025\n026\n027\n028\n029\n" \ + "030\n031\n032\n033\n034\n035\n036\n037\n038\n039\n" \ + "040\n041\n042\n043\n044\n045\n046\n047\n048\n049\n" + +void test_core_buffer__similarity_metric(void) +{ + git_hashsig *a, *b; + git_buf buf = GIT_BUF_INIT; + int sim; + + /* in the first case, we compare data to itself and expect 100% match */ + + cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); + cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); + cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); + + cl_assert_equal_i(100, git_hashsig_compare(a, b)); + + git_hashsig_free(a); + git_hashsig_free(b); + + /* if we change just a single byte, how much does that change magnify? */ + + cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); + cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); + cl_git_pass(git_buf_sets(&buf, + "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \ + "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \ + "x020x\n021\n022\n023\n024\n025\n026\n027\n028\n029\n" \ + "030\n031\n032\n033\n034\n035\n036\n037\n038\n039\n" \ + "040\n041\n042\n043\n044\n045\n046\n047\n048\n049\n" + )); + cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); + + sim = git_hashsig_compare(a, b); + + cl_assert_in_range(95, sim, 100); /* expect >95% similarity */ + + git_hashsig_free(a); + git_hashsig_free(b); + + /* let's try comparing data to a superset of itself */ + + cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); + cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); + cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1 + "050\n051\n052\n053\n054\n055\n056\n057\n058\n059\n")); + cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); + + sim = git_hashsig_compare(a, b); + /* 20% lines added ~= 10% lines changed */ + + cl_assert_in_range(85, sim, 95); /* expect similarity around 90% */ + + git_hashsig_free(a); + git_hashsig_free(b); + + /* what if we keep about half the original data and add half new */ + + cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); + cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); + cl_git_pass(git_buf_sets(&buf, + "000\n001\n002\n003\n004\n005\n006\n007\n008\n009\n" \ + "010\n011\n012\n013\n014\n015\n016\n017\n018\n019\n" \ + "020x\n021\n022\n023\n024\n" \ + "x25\nx26\nx27\nx28\nx29\n" \ + "x30\nx31\nx32\nx33\nx34\nx35\nx36\nx37\nx38\nx39\n" \ + "x40\nx41\nx42\nx43\nx44\nx45\nx46\nx47\nx48\nx49\n" + )); + cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); + + sim = git_hashsig_compare(a, b); + /* 50% lines changed */ + + cl_assert_in_range(40, sim, 60); /* expect in the 40-60% similarity range */ + + git_hashsig_free(a); + git_hashsig_free(b); + + /* lastly, let's check that we can hash file content as well */ + + cl_git_pass(git_buf_sets(&buf, SIMILARITY_TEST_DATA_1)); + cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, GIT_HASHSIG_NORMAL)); + + cl_git_pass(git_futils_mkdir("scratch", NULL, 0755, GIT_MKDIR_PATH)); + cl_git_mkfile("scratch/testdata", SIMILARITY_TEST_DATA_1); + cl_git_pass(git_hashsig_create_fromfile( + &b, "scratch/testdata", GIT_HASHSIG_NORMAL)); + + cl_assert_equal_i(100, git_hashsig_compare(a, b)); + + git_hashsig_free(a); + git_hashsig_free(b); + + git_buf_free(&buf); + git_futils_rmdir_r("scratch", NULL, GIT_RMDIR_REMOVE_FILES); +} + + +void test_core_buffer__similarity_metric_whitespace(void) +{ + git_hashsig *a, *b; + git_buf buf = GIT_BUF_INIT; + int sim, i, j; + git_hashsig_option_t opt; + const char *tabbed = + " for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {\n" + " separator = sep[s];\n" + " expect = expect_values[s];\n" + "\n" + " for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {\n" + " for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {\n" + " git_buf_join(&buf, separator, a[i], b[j]);\n" + " cl_assert_equal_s(*expect, buf.ptr);\n" + " expect++;\n" + " }\n" + " }\n" + " }\n"; + const char *spaced = + " for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {\n" + " separator = sep[s];\n" + " expect = expect_values[s];\n" + "\n" + " for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {\n" + " for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {\n" + " git_buf_join(&buf, separator, a[i], b[j]);\n" + " cl_assert_equal_s(*expect, buf.ptr);\n" + " expect++;\n" + " }\n" + " }\n" + " }\n"; + const char *crlf_spaced2 = + " for (s = 0; s < sizeof(sep) / sizeof(char); ++s) {\r\n" + " separator = sep[s];\r\n" + " expect = expect_values[s];\r\n" + "\r\n" + " for (j = 0; j < sizeof(b) / sizeof(char*); ++j) {\r\n" + " for (i = 0; i < sizeof(a) / sizeof(char*); ++i) {\r\n" + " git_buf_join(&buf, separator, a[i], b[j]);\r\n" + " cl_assert_equal_s(*expect, buf.ptr);\r\n" + " expect++;\r\n" + " }\r\n" + " }\r\n" + " }\r\n"; + const char *text[3] = { tabbed, spaced, crlf_spaced2 }; + + /* let's try variations of our own code with whitespace changes */ + + for (opt = GIT_HASHSIG_NORMAL; opt <= GIT_HASHSIG_SMART_WHITESPACE; ++opt) { + for (i = 0; i < 3; ++i) { + for (j = 0; j < 3; ++j) { + cl_git_pass(git_buf_sets(&buf, text[i])); + cl_git_pass(git_hashsig_create(&a, buf.ptr, buf.size, opt)); + + cl_git_pass(git_buf_sets(&buf, text[j])); + cl_git_pass(git_hashsig_create(&b, buf.ptr, buf.size, opt)); + + sim = git_hashsig_compare(a, b); + + if (opt == GIT_HASHSIG_NORMAL) { + if (i == j) + cl_assert_equal_i(100, sim); + else + cl_assert_in_range(0, sim, 30); /* pretty different */ + } else { + cl_assert_equal_i(100, sim); + } + + git_hashsig_free(a); + git_hashsig_free(b); + } + } + } + + git_buf_free(&buf); +} + +#include "../filter/crlf.h" + +#define check_buf(expected,buf) do { \ + cl_assert_equal_s(expected, buf.ptr); \ + cl_assert_equal_sz(strlen(expected), buf.size); } while (0) + +void test_core_buffer__lf_and_crlf_conversions(void) +{ + git_buf src = GIT_BUF_INIT, tgt = GIT_BUF_INIT; + + /* LF source */ + + git_buf_sets(&src, "lf\nlf\nlf\nlf\n"); + + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf("lf\r\nlf\r\nlf\r\nlf\r\n", tgt); + + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf(src.ptr, tgt); + + git_buf_sets(&src, "\nlf\nlf\nlf\nlf\nlf"); + + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf("\r\nlf\r\nlf\r\nlf\r\nlf\r\nlf", tgt); + + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf(src.ptr, tgt); + + /* CRLF source */ + + git_buf_sets(&src, "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n"); + + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf("crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n", tgt); + check_buf(src.ptr, tgt); + + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf("crlf\ncrlf\ncrlf\ncrlf\n", tgt); + + git_buf_sets(&src, "\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf"); + + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf("\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf", tgt); + check_buf(src.ptr, tgt); + + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf("\ncrlf\ncrlf\ncrlf\ncrlf\ncrlf", tgt); + + /* CRLF in LF text */ + + git_buf_sets(&src, "\nlf\nlf\ncrlf\r\nlf\nlf\ncrlf\r\n"); + + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf("\r\nlf\r\nlf\r\ncrlf\r\nlf\r\nlf\r\ncrlf\r\n", tgt); + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf("\nlf\nlf\ncrlf\nlf\nlf\ncrlf\n", tgt); + + /* LF in CRLF text */ + + git_buf_sets(&src, "\ncrlf\r\ncrlf\r\nlf\ncrlf\r\ncrlf"); + + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf("\r\ncrlf\r\ncrlf\r\nlf\r\ncrlf\r\ncrlf", tgt); + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf("\ncrlf\ncrlf\nlf\ncrlf\ncrlf", tgt); + + /* bare CR test */ + + git_buf_sets(&src, "\rcrlf\r\nlf\nlf\ncr\rcrlf\r\nlf\ncr\r"); + + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf("\rcrlf\r\nlf\r\nlf\r\ncr\rcrlf\r\nlf\r\ncr\r", tgt); + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf("\rcrlf\nlf\nlf\ncr\rcrlf\nlf\ncr\r", tgt); + + git_buf_sets(&src, "\rcr\r"); + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf(src.ptr, tgt); + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf("\rcr\r", tgt); + + git_buf_free(&src); + git_buf_free(&tgt); + + /* blob correspondence tests */ + + git_buf_sets(&src, ALL_CRLF_TEXT_RAW); + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf(ALL_CRLF_TEXT_AS_CRLF, tgt); + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf(ALL_CRLF_TEXT_AS_LF, tgt); + git_buf_free(&src); + git_buf_free(&tgt); + + git_buf_sets(&src, ALL_LF_TEXT_RAW); + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf(ALL_LF_TEXT_AS_CRLF, tgt); + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf(ALL_LF_TEXT_AS_LF, tgt); + git_buf_free(&src); + git_buf_free(&tgt); + + git_buf_sets(&src, MORE_CRLF_TEXT_RAW); + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf(MORE_CRLF_TEXT_AS_CRLF, tgt); + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf(MORE_CRLF_TEXT_AS_LF, tgt); + git_buf_free(&src); + git_buf_free(&tgt); + + git_buf_sets(&src, MORE_LF_TEXT_RAW); + cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); + check_buf(MORE_LF_TEXT_AS_CRLF, tgt); + cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); + check_buf(MORE_LF_TEXT_AS_LF, tgt); + git_buf_free(&src); + git_buf_free(&tgt); +} diff --git a/tests/core/caps.c b/tests/core/caps.c new file mode 100644 index 000000000..68a518ed7 --- /dev/null +++ b/tests/core/caps.c @@ -0,0 +1,31 @@ +#include "clar_libgit2.h" + +void test_core_caps__0(void) +{ + int major, minor, rev, caps; + + git_libgit2_version(&major, &minor, &rev); + cl_assert_equal_i(LIBGIT2_VER_MAJOR, major); + cl_assert_equal_i(LIBGIT2_VER_MINOR, minor); + cl_assert_equal_i(LIBGIT2_VER_REVISION, rev); + + caps = git_libgit2_capabilities(); + +#ifdef GIT_THREADS + cl_assert((caps & GIT_CAP_THREADS) != 0); +#else + cl_assert((caps & GIT_CAP_THREADS) == 0); +#endif + +#if defined(GIT_SSL) || defined(GIT_WINHTTP) + cl_assert((caps & GIT_CAP_HTTPS) != 0); +#else + cl_assert((caps & GIT_CAP_HTTPS) == 0); +#endif + +#if defined(GIT_SSH) + cl_assert((caps & GIT_CAP_SSH) != 0); +#else + cl_assert((caps & GIT_CAP_SSH) == 0); +#endif +} diff --git a/tests/core/copy.c b/tests/core/copy.c new file mode 100644 index 000000000..c0c59c056 --- /dev/null +++ b/tests/core/copy.c @@ -0,0 +1,126 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "path.h" +#include "posix.h" + +void test_core_copy__file(void) +{ + struct stat st; + const char *content = "This is some stuff to copy\n"; + + cl_git_mkfile("copy_me", content); + + cl_git_pass(git_futils_cp("copy_me", "copy_me_two", 0664)); + + cl_git_pass(git_path_lstat("copy_me_two", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert(strlen(content) == (size_t)st.st_size); + + cl_git_pass(p_unlink("copy_me_two")); + cl_git_pass(p_unlink("copy_me")); +} + +void test_core_copy__file_in_dir(void) +{ + struct stat st; + const char *content = "This is some other stuff to copy\n"; + + cl_git_pass(git_futils_mkdir("an_dir/in_a_dir", NULL, 0775, GIT_MKDIR_PATH)); + cl_git_mkfile("an_dir/in_a_dir/copy_me", content); + cl_assert(git_path_isdir("an_dir")); + + cl_git_pass(git_futils_mkpath2file + ("an_dir/second_dir/and_more/copy_me_two", 0775)); + + cl_git_pass(git_futils_cp + ("an_dir/in_a_dir/copy_me", + "an_dir/second_dir/and_more/copy_me_two", + 0664)); + + cl_git_pass(git_path_lstat("an_dir/second_dir/and_more/copy_me_two", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert(strlen(content) == (size_t)st.st_size); + + cl_git_pass(git_futils_rmdir_r("an_dir", NULL, GIT_RMDIR_REMOVE_FILES)); + cl_assert(!git_path_isdir("an_dir")); +} + +void test_core_copy__tree(void) +{ + struct stat st; + const char *content = "File content\n"; + + cl_git_pass(git_futils_mkdir("src/b", NULL, 0775, GIT_MKDIR_PATH)); + cl_git_pass(git_futils_mkdir("src/c/d", NULL, 0775, GIT_MKDIR_PATH)); + cl_git_pass(git_futils_mkdir("src/c/e", NULL, 0775, GIT_MKDIR_PATH)); + + cl_git_mkfile("src/f1", content); + cl_git_mkfile("src/b/f2", content); + cl_git_mkfile("src/c/f3", content); + cl_git_mkfile("src/c/d/f4", content); + cl_git_mkfile("src/c/d/.f5", content); + +#ifndef GIT_WIN32 + cl_assert(p_symlink("../../b/f2", "src/c/d/l1") == 0); +#endif + + cl_assert(git_path_isdir("src")); + cl_assert(git_path_isdir("src/b")); + cl_assert(git_path_isdir("src/c/d")); + cl_assert(git_path_isfile("src/c/d/f4")); + + /* copy with no empty dirs, yes links, no dotfiles, no overwrite */ + + cl_git_pass( + git_futils_cp_r("src", "t1", GIT_CPDIR_COPY_SYMLINKS, 0) ); + + cl_assert(git_path_isdir("t1")); + cl_assert(git_path_isdir("t1/b")); + cl_assert(git_path_isdir("t1/c")); + cl_assert(git_path_isdir("t1/c/d")); + cl_assert(!git_path_isdir("t1/c/e")); + + cl_assert(git_path_isfile("t1/f1")); + cl_assert(git_path_isfile("t1/b/f2")); + cl_assert(git_path_isfile("t1/c/f3")); + cl_assert(git_path_isfile("t1/c/d/f4")); + cl_assert(!git_path_isfile("t1/c/d/.f5")); + + cl_git_pass(git_path_lstat("t1/c/f3", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert(strlen(content) == (size_t)st.st_size); + +#ifndef GIT_WIN32 + cl_git_pass(git_path_lstat("t1/c/d/l1", &st)); + cl_assert(S_ISLNK(st.st_mode)); +#endif + + cl_git_pass(git_futils_rmdir_r("t1", NULL, GIT_RMDIR_REMOVE_FILES)); + cl_assert(!git_path_isdir("t1")); + + /* copy with empty dirs, no links, yes dotfiles, no overwrite */ + + cl_git_pass( + git_futils_cp_r("src", "t2", GIT_CPDIR_CREATE_EMPTY_DIRS | GIT_CPDIR_COPY_DOTFILES, 0) ); + + cl_assert(git_path_isdir("t2")); + cl_assert(git_path_isdir("t2/b")); + cl_assert(git_path_isdir("t2/c")); + cl_assert(git_path_isdir("t2/c/d")); + cl_assert(git_path_isdir("t2/c/e")); + + cl_assert(git_path_isfile("t2/f1")); + cl_assert(git_path_isfile("t2/b/f2")); + cl_assert(git_path_isfile("t2/c/f3")); + cl_assert(git_path_isfile("t2/c/d/f4")); + cl_assert(git_path_isfile("t2/c/d/.f5")); + +#ifndef GIT_WIN32 + cl_git_fail(git_path_lstat("t2/c/d/l1", &st)); +#endif + + cl_git_pass(git_futils_rmdir_r("t2", NULL, GIT_RMDIR_REMOVE_FILES)); + cl_assert(!git_path_isdir("t2")); + + cl_git_pass(git_futils_rmdir_r("src", NULL, GIT_RMDIR_REMOVE_FILES)); +} diff --git a/tests/core/dirent.c b/tests/core/dirent.c new file mode 100644 index 000000000..f17260362 --- /dev/null +++ b/tests/core/dirent.c @@ -0,0 +1,236 @@ +#include "clar_libgit2.h" +#include "fileops.h" + +typedef struct name_data { + int count; /* return count */ + char *name; /* filename */ +} name_data; + +typedef struct walk_data { + char *sub; /* sub-directory name */ + name_data *names; /* name state data */ + git_buf path; +} walk_data; + + +static char *top_dir = "dir-walk"; +static walk_data *state_loc; + +static void setup(walk_data *d) +{ + name_data *n; + + cl_must_pass(p_mkdir(top_dir, 0777)); + + cl_must_pass(p_chdir(top_dir)); + + if (strcmp(d->sub, ".") != 0) + cl_must_pass(p_mkdir(d->sub, 0777)); + + cl_git_pass(git_buf_sets(&d->path, d->sub)); + + state_loc = d; + + for (n = d->names; n->name; n++) { + git_file fd = p_creat(n->name, 0666); + cl_assert(fd >= 0); + p_close(fd); + n->count = 0; + } +} + +static void dirent_cleanup__cb(void *_d) +{ + walk_data *d = _d; + name_data *n; + + for (n = d->names; n->name; n++) { + cl_must_pass(p_unlink(n->name)); + } + + if (strcmp(d->sub, ".") != 0) + cl_must_pass(p_rmdir(d->sub)); + + cl_must_pass(p_chdir("..")); + + cl_must_pass(p_rmdir(top_dir)); + + git_buf_free(&d->path); +} + +static void check_counts(walk_data *d) +{ + name_data *n; + + for (n = d->names; n->name; n++) { + cl_assert(n->count == 1); + } +} + +static int one_entry(void *state, git_buf *path) +{ + walk_data *d = (walk_data *) state; + name_data *n; + + if (state != state_loc) + return GIT_ERROR; + + if (path != &d->path) + return GIT_ERROR; + + for (n = d->names; n->name; n++) { + if (!strcmp(n->name, path->ptr)) { + n->count++; + return 0; + } + } + + return GIT_ERROR; +} + + +static name_data dot_names[] = { + { 0, "./a" }, + { 0, "./asdf" }, + { 0, "./pack-foo.pack" }, + { 0, NULL } +}; +static walk_data dot = { + ".", + dot_names, + GIT_BUF_INIT +}; + +/* make sure that the '.' folder is not traversed */ +void test_core_dirent__dont_traverse_dot(void) +{ + cl_set_cleanup(&dirent_cleanup__cb, &dot); + setup(&dot); + + cl_git_pass(git_path_direach(&dot.path, 0, one_entry, &dot)); + + check_counts(&dot); +} + + +static name_data sub_names[] = { + { 0, "sub/a" }, + { 0, "sub/asdf" }, + { 0, "sub/pack-foo.pack" }, + { 0, NULL } +}; +static walk_data sub = { + "sub", + sub_names, + GIT_BUF_INIT +}; + +/* traverse a subfolder */ +void test_core_dirent__traverse_subfolder(void) +{ + cl_set_cleanup(&dirent_cleanup__cb, &sub); + setup(&sub); + + cl_git_pass(git_path_direach(&sub.path, 0, one_entry, &sub)); + + check_counts(&sub); +} + + +static walk_data sub_slash = { + "sub/", + sub_names, + GIT_BUF_INIT +}; + +/* traverse a slash-terminated subfolder */ +void test_core_dirent__traverse_slash_terminated_folder(void) +{ + cl_set_cleanup(&dirent_cleanup__cb, &sub_slash); + setup(&sub_slash); + + cl_git_pass(git_path_direach(&sub_slash.path, 0, one_entry, &sub_slash)); + + check_counts(&sub_slash); +} + + +static name_data empty_names[] = { + { 0, NULL } +}; +static walk_data empty = { + "empty", + empty_names, + GIT_BUF_INIT +}; + +/* make sure that empty folders are not traversed */ +void test_core_dirent__dont_traverse_empty_folders(void) +{ + cl_set_cleanup(&dirent_cleanup__cb, &empty); + setup(&empty); + + cl_git_pass(git_path_direach(&empty.path, 0, one_entry, &empty)); + + check_counts(&empty); + + /* make sure callback not called */ + cl_assert(git_path_is_empty_dir(empty.path.ptr)); +} + +static name_data odd_names[] = { + { 0, "odd/.a" }, + { 0, "odd/..c" }, + /* the following don't work on cygwin/win32 */ + /* { 0, "odd/.b." }, */ + /* { 0, "odd/..d.." }, */ + { 0, NULL } +}; +static walk_data odd = { + "odd", + odd_names, + GIT_BUF_INIT +}; + +/* make sure that strange looking filenames ('..c') are traversed */ +void test_core_dirent__traverse_weird_filenames(void) +{ + cl_set_cleanup(&dirent_cleanup__cb, &odd); + setup(&odd); + + cl_git_pass(git_path_direach(&odd.path, 0, one_entry, &odd)); + + check_counts(&odd); +} + +/* test filename length limits */ +void test_core_dirent__length_limits(void) +{ + char *big_filename = (char *)git__malloc(FILENAME_MAX + 1); + memset(big_filename, 'a', FILENAME_MAX + 1); + big_filename[FILENAME_MAX] = 0; + + cl_must_fail(p_creat(big_filename, 0666)); + + git__free(big_filename); +} + +void test_core_dirent__empty_dir(void) +{ + cl_must_pass(p_mkdir("empty_dir", 0777)); + cl_assert(git_path_is_empty_dir("empty_dir")); + + cl_git_mkfile("empty_dir/content", "whatever\n"); + cl_assert(!git_path_is_empty_dir("empty_dir")); + cl_assert(!git_path_is_empty_dir("empty_dir/content")); + + cl_must_pass(p_unlink("empty_dir/content")); + + cl_must_pass(p_mkdir("empty_dir/content", 0777)); + cl_assert(!git_path_is_empty_dir("empty_dir")); + cl_assert(git_path_is_empty_dir("empty_dir/content")); + + cl_must_pass(p_rmdir("empty_dir/content")); + + cl_must_pass(p_rmdir("empty_dir")); +} diff --git a/tests/core/env.c b/tests/core/env.c new file mode 100644 index 000000000..0fa6472d7 --- /dev/null +++ b/tests/core/env.c @@ -0,0 +1,303 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "path.h" + +#ifdef GIT_WIN32 +#define NUM_VARS 5 +static const char *env_vars[NUM_VARS] = { + "HOME", "HOMEDRIVE", "HOMEPATH", "USERPROFILE", "PROGRAMFILES" +}; +#else +#define NUM_VARS 1 +static const char *env_vars[NUM_VARS] = { "HOME" }; +#endif + +static char *env_save[NUM_VARS]; + +static char *home_values[] = { + "fake_home", + "f\xc3\xa1ke_h\xc3\xb5me", /* all in latin-1 supplement */ + "f\xc4\x80ke_\xc4\xa4ome", /* latin extended */ + "f\xce\xb1\xce\xba\xce\xb5_h\xce\xbfm\xce\xad", /* having fun with greek */ + "fa\xe0" "\xb8" "\x87" "e_\xe0" "\xb8" "\x99" "ome", /* thai characters */ + "f\xe1\x9cx80ke_\xe1\x9c\x91ome", /* tagalog characters */ + "\xe1\xb8\x9f\xe1\xba\xa2" "ke_ho" "\xe1" "\xb9" "\x81" "e", /* latin extended additional */ + "\xf0\x9f\x98\x98\xf0\x9f\x98\x82", /* emoticons */ + NULL +}; + +void test_core_env__initialize(void) +{ + int i; + for (i = 0; i < NUM_VARS; ++i) { + const char *original = cl_getenv(env_vars[i]); +#ifdef GIT_WIN32 + env_save[i] = (char *)original; +#else + env_save[i] = original ? git__strdup(original) : NULL; +#endif + } +} + +static void reset_global_search_path(void) +{ + cl_git_pass(git_futils_dirs_set(GIT_FUTILS_DIR_GLOBAL, NULL)); +} + +static void reset_system_search_path(void) +{ + cl_git_pass(git_futils_dirs_set(GIT_FUTILS_DIR_SYSTEM, NULL)); +} + +void test_core_env__cleanup(void) +{ + int i; + char **val; + + for (i = 0; i < NUM_VARS; ++i) { + cl_setenv(env_vars[i], env_save[i]); + git__free(env_save[i]); + env_save[i] = NULL; + } + + /* these will probably have already been cleaned up, but if a test + * fails, then it's probably good to try and clear out these dirs + */ + for (val = home_values; *val != NULL; val++) { + if (**val != '\0') + (void)p_rmdir(*val); + } + + /* reset search paths to default */ + reset_global_search_path(); + reset_system_search_path(); +} + +static void setenv_and_check(const char *name, const char *value) +{ + char *check; + + cl_git_pass(cl_setenv(name, value)); + + check = cl_getenv(name); + cl_assert_equal_s(value, check); +#ifdef GIT_WIN32 + git__free(check); +#endif +} + +void test_core_env__0(void) +{ + git_buf path = GIT_BUF_INIT, found = GIT_BUF_INIT; + char testfile[16], tidx = '0'; + char **val; + const char *testname = "testfile"; + size_t testlen = strlen(testname); + + strncpy(testfile, testname, sizeof(testfile)); + cl_assert_equal_s(testname, testfile); + + for (val = home_values; *val != NULL; val++) { + + /* if we can't make the directory, let's just assume + * we are on a filesystem that doesn't support the + * characters in question and skip this test... + */ + if (p_mkdir(*val, 0777) != 0) { + *val = ""; /* mark as not created */ + continue; + } + + cl_git_pass(git_path_prettify(&path, *val, NULL)); + + /* vary testfile name in each directory so accidentally leaving + * an environment variable set from a previous iteration won't + * accidentally make this test pass... + */ + testfile[testlen] = tidx++; + cl_git_pass(git_buf_joinpath(&path, path.ptr, testfile)); + cl_git_mkfile(path.ptr, "find me"); + git_buf_rtruncate_at_char(&path, '/'); + + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile)); + + setenv_and_check("HOME", path.ptr); + reset_global_search_path(); + + cl_git_pass(git_futils_find_global_file(&found, testfile)); + + cl_setenv("HOME", env_save[0]); + reset_global_search_path(); + + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile)); + +#ifdef GIT_WIN32 + setenv_and_check("HOMEDRIVE", NULL); + setenv_and_check("HOMEPATH", NULL); + setenv_and_check("USERPROFILE", path.ptr); + reset_global_search_path(); + + cl_git_pass(git_futils_find_global_file(&found, testfile)); + + { + int root = git_path_root(path.ptr); + char old; + + if (root >= 0) { + setenv_and_check("USERPROFILE", NULL); + reset_global_search_path(); + + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile)); + + old = path.ptr[root]; + path.ptr[root] = '\0'; + setenv_and_check("HOMEDRIVE", path.ptr); + path.ptr[root] = old; + setenv_and_check("HOMEPATH", &path.ptr[root]); + reset_global_search_path(); + + cl_git_pass(git_futils_find_global_file(&found, testfile)); + } + } +#endif + + (void)p_rmdir(*val); + } + + git_buf_free(&path); + git_buf_free(&found); +} + + +void test_core_env__1(void) +{ + git_buf path = GIT_BUF_INIT; + + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&path, "nonexistentfile")); + + cl_git_pass(cl_setenv("HOME", "doesnotexist")); +#ifdef GIT_WIN32 + cl_git_pass(cl_setenv("HOMEPATH", "doesnotexist")); + cl_git_pass(cl_setenv("USERPROFILE", "doesnotexist")); +#endif + reset_global_search_path(); + + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&path, "nonexistentfile")); + + cl_git_pass(cl_setenv("HOME", NULL)); +#ifdef GIT_WIN32 + cl_git_pass(cl_setenv("HOMEPATH", NULL)); + cl_git_pass(cl_setenv("USERPROFILE", NULL)); +#endif + reset_global_search_path(); + reset_system_search_path(); + + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&path, "nonexistentfile")); + + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_system_file(&path, "nonexistentfile")); + +#ifdef GIT_WIN32 + cl_git_pass(cl_setenv("PROGRAMFILES", NULL)); + reset_system_search_path(); + + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_system_file(&path, "nonexistentfile")); +#endif + + git_buf_free(&path); +} + +static void check_global_searchpath( + const char *path, int position, const char *file, git_buf *temp) +{ + char out[GIT_PATH_MAX]; + + /* build and set new path */ + if (position < 0) + cl_git_pass(git_buf_join(temp, GIT_PATH_LIST_SEPARATOR, path, "$PATH")); + else if (position > 0) + cl_git_pass(git_buf_join(temp, GIT_PATH_LIST_SEPARATOR, "$PATH", path)); + else + cl_git_pass(git_buf_sets(temp, path)); + + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, temp->ptr)); + + /* get path and make sure $PATH expansion worked */ + cl_git_pass(git_libgit2_opts( + GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, out, sizeof(out))); + + if (position < 0) + cl_assert(git__prefixcmp(out, path) == 0); + else if (position > 0) + cl_assert(git__suffixcmp(out, path) == 0); + else + cl_assert_equal_s(out, path); + + /* find file using new path */ + cl_git_pass(git_futils_find_global_file(temp, file)); + + /* reset path and confirm file not found */ + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, NULL)); + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(temp, file)); +} + +void test_core_env__2(void) +{ + git_buf path = GIT_BUF_INIT, found = GIT_BUF_INIT; + char testfile[16], tidx = '0'; + char **val; + const char *testname = "alternate"; + size_t testlen = strlen(testname); + + strncpy(testfile, testname, sizeof(testfile)); + cl_assert_equal_s(testname, testfile); + + for (val = home_values; *val != NULL; val++) { + + /* if we can't make the directory, let's just assume + * we are on a filesystem that doesn't support the + * characters in question and skip this test... + */ + if (p_mkdir(*val, 0777) != 0 && errno != EEXIST) { + *val = ""; /* mark as not created */ + continue; + } + + cl_git_pass(git_path_prettify(&path, *val, NULL)); + + /* vary testfile name so any sloppiness is resetting variables or + * deleting files won't accidentally make a test pass. + */ + testfile[testlen] = tidx++; + cl_git_pass(git_buf_joinpath(&path, path.ptr, testfile)); + cl_git_mkfile(path.ptr, "find me"); + git_buf_rtruncate_at_char(&path, '/'); + + /* default should be NOTFOUND */ + cl_assert_equal_i( + GIT_ENOTFOUND, git_futils_find_global_file(&found, testfile)); + + /* try plain, append $PATH, and prepend $PATH */ + check_global_searchpath(path.ptr, 0, testfile, &found); + check_global_searchpath(path.ptr, -1, testfile, &found); + check_global_searchpath(path.ptr, 1, testfile, &found); + + /* cleanup */ + cl_git_pass(git_buf_joinpath(&path, path.ptr, testfile)); + (void)p_unlink(path.ptr); + (void)p_rmdir(*val); + } + + git_buf_free(&path); + git_buf_free(&found); +} diff --git a/tests/core/errors.c b/tests/core/errors.c new file mode 100644 index 000000000..512a4134d --- /dev/null +++ b/tests/core/errors.c @@ -0,0 +1,87 @@ +#include "clar_libgit2.h" + +void test_core_errors__public_api(void) +{ + char *str_in_error; + + giterr_clear(); + cl_assert(giterr_last() == NULL); + + giterr_set_oom(); + + cl_assert(giterr_last() != NULL); + cl_assert(giterr_last()->klass == GITERR_NOMEMORY); + str_in_error = strstr(giterr_last()->message, "memory"); + cl_assert(str_in_error != NULL); + + giterr_clear(); + + giterr_set_str(GITERR_REPOSITORY, "This is a test"); + + cl_assert(giterr_last() != NULL); + str_in_error = strstr(giterr_last()->message, "This is a test"); + cl_assert(str_in_error != NULL); + + giterr_clear(); + cl_assert(giterr_last() == NULL); +} + +#include "common.h" +#include "util.h" +#include "posix.h" + +void test_core_errors__new_school(void) +{ + char *str_in_error; + + giterr_clear(); + cl_assert(giterr_last() == NULL); + + giterr_set_oom(); /* internal fn */ + + cl_assert(giterr_last() != NULL); + cl_assert(giterr_last()->klass == GITERR_NOMEMORY); + str_in_error = strstr(giterr_last()->message, "memory"); + cl_assert(str_in_error != NULL); + + giterr_clear(); + + giterr_set(GITERR_REPOSITORY, "This is a test"); /* internal fn */ + + cl_assert(giterr_last() != NULL); + str_in_error = strstr(giterr_last()->message, "This is a test"); + cl_assert(str_in_error != NULL); + + giterr_clear(); + cl_assert(giterr_last() == NULL); + + do { + struct stat st; + memset(&st, 0, sizeof(st)); + cl_assert(p_lstat("this_file_does_not_exist", &st) < 0); + GIT_UNUSED(st); + } while (false); + giterr_set(GITERR_OS, "stat failed"); /* internal fn */ + + cl_assert(giterr_last() != NULL); + str_in_error = strstr(giterr_last()->message, "stat failed"); + cl_assert(str_in_error != NULL); + cl_assert(git__prefixcmp(str_in_error, "stat failed: ") == 0); + cl_assert(strlen(str_in_error) > strlen("stat failed: ")); + +#ifdef GIT_WIN32 + giterr_clear(); + + /* The MSDN docs use this to generate a sample error */ + cl_assert(GetProcessId(NULL) == 0); + giterr_set(GITERR_OS, "GetProcessId failed"); /* internal fn */ + + cl_assert(giterr_last() != NULL); + str_in_error = strstr(giterr_last()->message, "GetProcessId failed"); + cl_assert(str_in_error != NULL); + cl_assert(git__prefixcmp(str_in_error, "GetProcessId failed: ") == 0); + cl_assert(strlen(str_in_error) > strlen("GetProcessId failed: ")); +#endif + + giterr_clear(); +} diff --git a/tests/core/filebuf.c b/tests/core/filebuf.c new file mode 100644 index 000000000..5a3e7510f --- /dev/null +++ b/tests/core/filebuf.c @@ -0,0 +1,126 @@ +#include "clar_libgit2.h" +#include "filebuf.h" + +/* make sure git_filebuf_open doesn't delete an existing lock */ +void test_core_filebuf__0(void) +{ + git_filebuf file = GIT_FILEBUF_INIT; + int fd; + char test[] = "test", testlock[] = "test.lock"; + + fd = p_creat(testlock, 0744); //-V536 + + cl_must_pass(fd); + cl_must_pass(p_close(fd)); + + cl_git_fail(git_filebuf_open(&file, test, 0, 0666)); + cl_assert(git_path_exists(testlock)); + + cl_must_pass(p_unlink(testlock)); +} + + +/* make sure GIT_FILEBUF_APPEND works as expected */ +void test_core_filebuf__1(void) +{ + git_filebuf file = GIT_FILEBUF_INIT; + char test[] = "test"; + + cl_git_mkfile(test, "libgit2 rocks\n"); + + cl_git_pass(git_filebuf_open(&file, test, GIT_FILEBUF_APPEND, 0666)); + cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks")); + cl_git_pass(git_filebuf_commit(&file)); + + cl_assert_equal_file("libgit2 rocks\nlibgit2 rocks\n", 0, test); + + cl_must_pass(p_unlink(test)); +} + + +/* make sure git_filebuf_write writes large buffer correctly */ +void test_core_filebuf__2(void) +{ + git_filebuf file = GIT_FILEBUF_INIT; + char test[] = "test"; + unsigned char buf[4096 * 4]; /* 2 * WRITE_BUFFER_SIZE */ + + memset(buf, 0xfe, sizeof(buf)); + + cl_git_pass(git_filebuf_open(&file, test, 0, 0666)); + cl_git_pass(git_filebuf_write(&file, buf, sizeof(buf))); + cl_git_pass(git_filebuf_commit(&file)); + + cl_assert_equal_file((char *)buf, sizeof(buf), test); + + cl_must_pass(p_unlink(test)); +} + +/* make sure git_filebuf_cleanup clears the buffer */ +void test_core_filebuf__4(void) +{ + git_filebuf file = GIT_FILEBUF_INIT; + char test[] = "test"; + + cl_assert(file.buffer == NULL); + + cl_git_pass(git_filebuf_open(&file, test, 0, 0666)); + cl_assert(file.buffer != NULL); + + git_filebuf_cleanup(&file); + cl_assert(file.buffer == NULL); +} + + +/* make sure git_filebuf_commit clears the buffer */ +void test_core_filebuf__5(void) +{ + git_filebuf file = GIT_FILEBUF_INIT; + char test[] = "test"; + + cl_assert(file.buffer == NULL); + + cl_git_pass(git_filebuf_open(&file, test, 0, 0666)); + cl_assert(file.buffer != NULL); + cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks")); + cl_assert(file.buffer != NULL); + + cl_git_pass(git_filebuf_commit(&file)); + cl_assert(file.buffer == NULL); + + cl_must_pass(p_unlink(test)); +} + + +/* make sure git_filebuf_commit takes umask into account */ +void test_core_filebuf__umask(void) +{ + git_filebuf file = GIT_FILEBUF_INIT; + char test[] = "test"; + struct stat statbuf; + mode_t mask, os_mask; + +#ifdef GIT_WIN32 + os_mask = 0600; +#else + os_mask = 0777; +#endif + + p_umask(mask = p_umask(0)); + + cl_assert(file.buffer == NULL); + + cl_git_pass(git_filebuf_open(&file, test, 0, 0666)); + cl_assert(file.buffer != NULL); + cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks")); + cl_assert(file.buffer != NULL); + + cl_git_pass(git_filebuf_commit(&file)); + cl_assert(file.buffer == NULL); + + cl_must_pass(p_stat("test", &statbuf)); + cl_assert_equal_i(statbuf.st_mode & os_mask, (0666 & ~mask) & os_mask); + + cl_must_pass(p_unlink(test)); +} + diff --git a/tests/core/hex.c b/tests/core/hex.c new file mode 100644 index 000000000..930af1670 --- /dev/null +++ b/tests/core/hex.c @@ -0,0 +1,22 @@ +#include "clar_libgit2.h" +#include "util.h" + +void test_core_hex__fromhex(void) +{ + /* Passing cases */ + cl_assert(git__fromhex('0') == 0x0); + cl_assert(git__fromhex('1') == 0x1); + cl_assert(git__fromhex('3') == 0x3); + cl_assert(git__fromhex('9') == 0x9); + cl_assert(git__fromhex('A') == 0xa); + cl_assert(git__fromhex('C') == 0xc); + cl_assert(git__fromhex('F') == 0xf); + cl_assert(git__fromhex('a') == 0xa); + cl_assert(git__fromhex('c') == 0xc); + cl_assert(git__fromhex('f') == 0xf); + + /* Failing cases */ + cl_assert(git__fromhex('g') == -1); + cl_assert(git__fromhex('z') == -1); + cl_assert(git__fromhex('X') == -1); +} diff --git a/tests/core/iconv.c b/tests/core/iconv.c new file mode 100644 index 000000000..8aedab206 --- /dev/null +++ b/tests/core/iconv.c @@ -0,0 +1,68 @@ +#include "clar_libgit2.h" +#include "path.h" + +#ifdef GIT_USE_ICONV +static git_path_iconv_t ic; +static char *nfc = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D"; +static char *nfd = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D"; +#endif + +void test_core_iconv__initialize(void) +{ +#ifdef GIT_USE_ICONV + cl_git_pass(git_path_iconv_init_precompose(&ic)); +#endif +} + +void test_core_iconv__cleanup(void) +{ +#ifdef GIT_USE_ICONV + git_path_iconv_clear(&ic); +#endif +} + +void test_core_iconv__unchanged(void) +{ +#ifdef GIT_USE_ICONV + char *data = "Ascii data", *original = data; + size_t datalen = strlen(data); + + cl_git_pass(git_path_iconv(&ic, &data, &datalen)); + GIT_UNUSED(datalen); + + /* There are no high bits set, so this should leave data untouched */ + cl_assert(data == original); +#endif +} + +void test_core_iconv__decomposed_to_precomposed(void) +{ +#ifdef GIT_USE_ICONV + char *data = nfd; + size_t datalen = strlen(nfd); + + cl_git_pass(git_path_iconv(&ic, &data, &datalen)); + GIT_UNUSED(datalen); + + /* The decomposed nfd string should be transformed to the nfc form + * (on platforms where iconv is enabled, of course). + */ + cl_assert_equal_s(nfc, data); +#endif +} + +void test_core_iconv__precomposed_is_unmodified(void) +{ +#ifdef GIT_USE_ICONV + char *data = nfc; + size_t datalen = strlen(nfc); + + cl_git_pass(git_path_iconv(&ic, &data, &datalen)); + GIT_UNUSED(datalen); + + /* data is already in precomposed form, so even though some bytes have + * the high-bit set, the iconv transform should result in no change. + */ + cl_assert_equal_s(nfc, data); +#endif +} diff --git a/tests/core/mkdir.c b/tests/core/mkdir.c new file mode 100644 index 000000000..a8c5b10ae --- /dev/null +++ b/tests/core/mkdir.c @@ -0,0 +1,188 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "path.h" +#include "posix.h" + +static void cleanup_basic_dirs(void *ref) +{ + GIT_UNUSED(ref); + git_futils_rmdir_r("d0", NULL, GIT_RMDIR_EMPTY_HIERARCHY); + git_futils_rmdir_r("d1", NULL, GIT_RMDIR_EMPTY_HIERARCHY); + git_futils_rmdir_r("d2", NULL, GIT_RMDIR_EMPTY_HIERARCHY); + git_futils_rmdir_r("d3", NULL, GIT_RMDIR_EMPTY_HIERARCHY); + git_futils_rmdir_r("d4", NULL, GIT_RMDIR_EMPTY_HIERARCHY); +} + +void test_core_mkdir__basic(void) +{ + cl_set_cleanup(cleanup_basic_dirs, NULL); + + /* make a directory */ + cl_assert(!git_path_isdir("d0")); + cl_git_pass(git_futils_mkdir("d0", NULL, 0755, 0)); + cl_assert(git_path_isdir("d0")); + + /* make a path */ + cl_assert(!git_path_isdir("d1")); + cl_git_pass(git_futils_mkdir("d1/d1.1/d1.2", NULL, 0755, GIT_MKDIR_PATH)); + cl_assert(git_path_isdir("d1")); + cl_assert(git_path_isdir("d1/d1.1")); + cl_assert(git_path_isdir("d1/d1.1/d1.2")); + + /* make a dir exclusively */ + cl_assert(!git_path_isdir("d2")); + cl_git_pass(git_futils_mkdir("d2", NULL, 0755, GIT_MKDIR_EXCL)); + cl_assert(git_path_isdir("d2")); + + /* make exclusive failure */ + cl_git_fail(git_futils_mkdir("d2", NULL, 0755, GIT_MKDIR_EXCL)); + + /* make a path exclusively */ + cl_assert(!git_path_isdir("d3")); + cl_git_pass(git_futils_mkdir("d3/d3.1/d3.2", NULL, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL)); + cl_assert(git_path_isdir("d3")); + cl_assert(git_path_isdir("d3/d3.1/d3.2")); + + /* make exclusive path failure */ + cl_git_fail(git_futils_mkdir("d3/d3.1/d3.2", NULL, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL)); + /* ??? Should EXCL only apply to the last item in the path? */ + + /* path with trailing slash? */ + cl_assert(!git_path_isdir("d4")); + cl_git_pass(git_futils_mkdir("d4/d4.1/", NULL, 0755, GIT_MKDIR_PATH)); + cl_assert(git_path_isdir("d4/d4.1")); +} + +static void cleanup_basedir(void *ref) +{ + GIT_UNUSED(ref); + git_futils_rmdir_r("base", NULL, GIT_RMDIR_EMPTY_HIERARCHY); +} + +void test_core_mkdir__with_base(void) +{ +#define BASEDIR "base/dir/here" + + cl_set_cleanup(cleanup_basedir, NULL); + + cl_git_pass(git_futils_mkdir(BASEDIR, NULL, 0755, GIT_MKDIR_PATH)); + + cl_git_pass(git_futils_mkdir("a", BASEDIR, 0755, 0)); + cl_assert(git_path_isdir(BASEDIR "/a")); + + cl_git_pass(git_futils_mkdir("b/b1/b2", BASEDIR, 0755, GIT_MKDIR_PATH)); + cl_assert(git_path_isdir(BASEDIR "/b/b1/b2")); + + /* exclusive with existing base */ + cl_git_pass(git_futils_mkdir("c/c1/c2", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL)); + + /* fail: exclusive with duplicated suffix */ + cl_git_fail(git_futils_mkdir("c/c1/c3", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL)); + + /* fail: exclusive with any duplicated component */ + cl_git_fail(git_futils_mkdir("c/cz/cz", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL)); + + /* success: exclusive without path */ + cl_git_pass(git_futils_mkdir("c/c1/c3", BASEDIR, 0755, GIT_MKDIR_EXCL)); + + /* path with shorter base and existing dirs */ + cl_git_pass(git_futils_mkdir("dir/here/d/", "base", 0755, GIT_MKDIR_PATH)); + cl_assert(git_path_isdir("base/dir/here/d")); + + /* fail: path with shorter base and existing dirs */ + cl_git_fail(git_futils_mkdir("dir/here/e/", "base", 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL)); + + /* fail: base with missing components */ + cl_git_fail(git_futils_mkdir("f/", "base/missing", 0755, GIT_MKDIR_PATH)); + + /* success: shift missing component to path */ + cl_git_pass(git_futils_mkdir("missing/f/", "base/", 0755, GIT_MKDIR_PATH)); +} + +static void cleanup_chmod_root(void *ref) +{ + mode_t *mode = ref; + + if (*mode != 0) { + (void)p_umask(*mode); + git__free(mode); + } + + git_futils_rmdir_r("r", NULL, GIT_RMDIR_EMPTY_HIERARCHY); +} + +#define check_mode(X,A) check_mode_at_line((X), (A), __FILE__, __LINE__) + +static void check_mode_at_line( + mode_t expected, mode_t actual, const char *file, int line) +{ + /* FAT filesystems don't support exec bit, nor group/world bits */ + if (!cl_is_chmod_supported()) { + expected &= 0600; + actual &= 0600; + } + + clar__assert_equal( + file, line, "expected_mode != actual_mode", 1, + "%07o", (int)expected, (int)(actual & 0777)); +} + +void test_core_mkdir__chmods(void) +{ + struct stat st; + mode_t *old = git__malloc(sizeof(mode_t)); + *old = p_umask(022); + + cl_set_cleanup(cleanup_chmod_root, old); + + cl_git_pass(git_futils_mkdir("r", NULL, 0777, 0)); + + cl_git_pass(git_futils_mkdir("mode/is/important", "r", 0777, GIT_MKDIR_PATH)); + + cl_git_pass(git_path_lstat("r/mode", &st)); + check_mode(0755, st.st_mode); + cl_git_pass(git_path_lstat("r/mode/is", &st)); + check_mode(0755, st.st_mode); + cl_git_pass(git_path_lstat("r/mode/is/important", &st)); + check_mode(0755, st.st_mode); + + cl_git_pass(git_futils_mkdir("mode2/is2/important2", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD)); + + cl_git_pass(git_path_lstat("r/mode2", &st)); + check_mode(0755, st.st_mode); + cl_git_pass(git_path_lstat("r/mode2/is2", &st)); + check_mode(0755, st.st_mode); + cl_git_pass(git_path_lstat("r/mode2/is2/important2", &st)); + check_mode(0777, st.st_mode); + + cl_git_pass(git_futils_mkdir("mode3/is3/important3", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD_PATH)); + + cl_git_pass(git_path_lstat("r/mode3", &st)); + check_mode(0777, st.st_mode); + cl_git_pass(git_path_lstat("r/mode3/is3", &st)); + check_mode(0777, st.st_mode); + cl_git_pass(git_path_lstat("r/mode3/is3/important3", &st)); + check_mode(0777, st.st_mode); + + /* test that we chmod existing dir */ + + cl_git_pass(git_futils_mkdir("mode/is/important", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD)); + + cl_git_pass(git_path_lstat("r/mode", &st)); + check_mode(0755, st.st_mode); + cl_git_pass(git_path_lstat("r/mode/is", &st)); + check_mode(0755, st.st_mode); + cl_git_pass(git_path_lstat("r/mode/is/important", &st)); + check_mode(0777, st.st_mode); + + /* test that we chmod even existing dirs if CHMOD_PATH is set */ + + cl_git_pass(git_futils_mkdir("mode2/is2/important2.1", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD_PATH)); + + cl_git_pass(git_path_lstat("r/mode2", &st)); + check_mode(0777, st.st_mode); + cl_git_pass(git_path_lstat("r/mode2/is2", &st)); + check_mode(0777, st.st_mode); + cl_git_pass(git_path_lstat("r/mode2/is2/important2.1", &st)); + check_mode(0777, st.st_mode); +} diff --git a/tests/core/oid.c b/tests/core/oid.c new file mode 100644 index 000000000..7ee6fb67d --- /dev/null +++ b/tests/core/oid.c @@ -0,0 +1,70 @@ +#include "clar_libgit2.h" + +static git_oid id; +static git_oid idp; +static git_oid idm; +const char *str_oid = "ae90f12eea699729ed24555e40b9fd669da12a12"; +const char *str_oid_p = "ae90f12eea699729ed"; +const char *str_oid_m = "ae90f12eea699729ed24555e40b9fd669da12a12THIS IS EXTRA TEXT THAT SHOULD GET IGNORED"; + +void test_core_oid__initialize(void) +{ + cl_git_pass(git_oid_fromstr(&id, str_oid)); + cl_git_pass(git_oid_fromstrp(&idp, str_oid_p)); + cl_git_fail(git_oid_fromstrp(&idm, str_oid_m)); +} + +void test_core_oid__streq(void) +{ + cl_assert_equal_i(0, git_oid_streq(&id, str_oid)); + cl_assert_equal_i(-1, git_oid_streq(&id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")); + + cl_assert_equal_i(-1, git_oid_streq(&id, "deadbeef")); + cl_assert_equal_i(-1, git_oid_streq(&id, "I'm not an oid.... :)")); + + cl_assert_equal_i(0, git_oid_streq(&idp, "ae90f12eea699729ed0000000000000000000000")); + cl_assert_equal_i(0, git_oid_streq(&idp, "ae90f12eea699729ed")); + cl_assert_equal_i(-1, git_oid_streq(&idp, "ae90f12eea699729ed1")); + cl_assert_equal_i(-1, git_oid_streq(&idp, "ae90f12eea699729ec")); + cl_assert_equal_i(-1, git_oid_streq(&idp, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")); + + cl_assert_equal_i(-1, git_oid_streq(&idp, "deadbeef")); + cl_assert_equal_i(-1, git_oid_streq(&idp, "I'm not an oid.... :)")); +} + +void test_core_oid__strcmp(void) +{ + cl_assert_equal_i(0, git_oid_strcmp(&id, str_oid)); + cl_assert(git_oid_strcmp(&id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef") < 0); + + cl_assert(git_oid_strcmp(&id, "deadbeef") < 0); + cl_assert_equal_i(-1, git_oid_strcmp(&id, "I'm not an oid.... :)")); + + cl_assert_equal_i(0, git_oid_strcmp(&idp, "ae90f12eea699729ed0000000000000000000000")); + cl_assert_equal_i(0, git_oid_strcmp(&idp, "ae90f12eea699729ed")); + cl_assert(git_oid_strcmp(&idp, "ae90f12eea699729ed1") < 0); + cl_assert(git_oid_strcmp(&idp, "ae90f12eea699729ec") > 0); + cl_assert(git_oid_strcmp(&idp, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef") < 0); + + cl_assert(git_oid_strcmp(&idp, "deadbeef") < 0); + cl_assert_equal_i(-1, git_oid_strcmp(&idp, "I'm not an oid.... :)")); +} + +void test_core_oid__ncmp(void) +{ + cl_assert(!git_oid_ncmp(&id, &idp, 0)); + cl_assert(!git_oid_ncmp(&id, &idp, 1)); + cl_assert(!git_oid_ncmp(&id, &idp, 2)); + cl_assert(!git_oid_ncmp(&id, &idp, 17)); + cl_assert(!git_oid_ncmp(&id, &idp, 18)); + cl_assert(git_oid_ncmp(&id, &idp, 19)); + cl_assert(git_oid_ncmp(&id, &idp, 40)); + cl_assert(git_oid_ncmp(&id, &idp, 41)); + cl_assert(git_oid_ncmp(&id, &idp, 42)); + + cl_assert(!git_oid_ncmp(&id, &id, 0)); + cl_assert(!git_oid_ncmp(&id, &id, 1)); + cl_assert(!git_oid_ncmp(&id, &id, 39)); + cl_assert(!git_oid_ncmp(&id, &id, 40)); + cl_assert(!git_oid_ncmp(&id, &id, 41)); +} diff --git a/tests/core/oidmap.c b/tests/core/oidmap.c new file mode 100644 index 000000000..ec4b5e775 --- /dev/null +++ b/tests/core/oidmap.c @@ -0,0 +1,110 @@ +#include "clar_libgit2.h" +#include "oidmap.h" + +GIT__USE_OIDMAP; + +typedef struct { + git_oid oid; + size_t extra; +} oidmap_item; + +#define NITEMS 0x0fff + +void test_core_oidmap__basic(void) +{ + git_oidmap *map; + oidmap_item items[NITEMS]; + uint32_t i, j; + + for (i = 0; i < NITEMS; ++i) { + items[i].extra = i; + for (j = 0; j < GIT_OID_RAWSZ / 4; ++j) { + items[i].oid.id[j * 4 ] = (unsigned char)i; + items[i].oid.id[j * 4 + 1] = (unsigned char)(i >> 8); + items[i].oid.id[j * 4 + 2] = (unsigned char)(i >> 16); + items[i].oid.id[j * 4 + 3] = (unsigned char)(i >> 24); + } + } + + map = git_oidmap_alloc(); + cl_assert(map != NULL); + + for (i = 0; i < NITEMS; ++i) { + khiter_t pos; + int ret; + + pos = kh_get(oid, map, &items[i].oid); + cl_assert(pos == kh_end(map)); + + pos = kh_put(oid, map, &items[i].oid, &ret); + cl_assert(ret != 0); + + kh_val(map, pos) = &items[i]; + } + + + for (i = 0; i < NITEMS; ++i) { + khiter_t pos; + + pos = kh_get(oid, map, &items[i].oid); + cl_assert(pos != kh_end(map)); + + cl_assert_equal_p(kh_val(map, pos), &items[i]); + } + + git_oidmap_free(map); +} + +void test_core_oidmap__hash_collision(void) +{ + git_oidmap *map; + oidmap_item items[NITEMS]; + uint32_t i, j; + + for (i = 0; i < NITEMS; ++i) { + uint32_t segment = i / 8; + int modi = i - (segment * 8); + + items[i].extra = i; + + for (j = 0; j < GIT_OID_RAWSZ / 4; ++j) { + items[i].oid.id[j * 4 ] = (unsigned char)modi; + items[i].oid.id[j * 4 + 1] = (unsigned char)(modi >> 8); + items[i].oid.id[j * 4 + 2] = (unsigned char)(modi >> 16); + items[i].oid.id[j * 4 + 3] = (unsigned char)(modi >> 24); + } + + items[i].oid.id[ 8] = (unsigned char)i; + items[i].oid.id[ 9] = (unsigned char)(i >> 8); + items[i].oid.id[10] = (unsigned char)(i >> 16); + items[i].oid.id[11] = (unsigned char)(i >> 24); + } + + map = git_oidmap_alloc(); + cl_assert(map != NULL); + + for (i = 0; i < NITEMS; ++i) { + khiter_t pos; + int ret; + + pos = kh_get(oid, map, &items[i].oid); + cl_assert(pos == kh_end(map)); + + pos = kh_put(oid, map, &items[i].oid, &ret); + cl_assert(ret != 0); + + kh_val(map, pos) = &items[i]; + } + + + for (i = 0; i < NITEMS; ++i) { + khiter_t pos; + + pos = kh_get(oid, map, &items[i].oid); + cl_assert(pos != kh_end(map)); + + cl_assert_equal_p(kh_val(map, pos), &items[i]); + } + + git_oidmap_free(map); +} diff --git a/tests/core/opts.c b/tests/core/opts.c new file mode 100644 index 000000000..3173c648b --- /dev/null +++ b/tests/core/opts.c @@ -0,0 +1,19 @@ +#include "clar_libgit2.h" +#include "cache.h" + +void test_core_opts__readwrite(void) +{ + size_t old_val = 0; + size_t new_val = 0; + + git_libgit2_opts(GIT_OPT_GET_MWINDOW_SIZE, &old_val); + git_libgit2_opts(GIT_OPT_SET_MWINDOW_SIZE, (size_t)1234); + git_libgit2_opts(GIT_OPT_GET_MWINDOW_SIZE, &new_val); + + cl_assert(new_val == 1234); + + git_libgit2_opts(GIT_OPT_SET_MWINDOW_SIZE, old_val); + git_libgit2_opts(GIT_OPT_GET_MWINDOW_SIZE, &new_val); + + cl_assert(new_val == old_val); +} diff --git a/tests/core/path.c b/tests/core/path.c new file mode 100644 index 000000000..cf2d5e944 --- /dev/null +++ b/tests/core/path.c @@ -0,0 +1,583 @@ +#include "clar_libgit2.h" +#include "fileops.h" + +static void +check_dirname(const char *A, const char *B) +{ + git_buf dir = GIT_BUF_INIT; + char *dir2; + + cl_assert(git_path_dirname_r(&dir, A) >= 0); + cl_assert_equal_s(B, dir.ptr); + git_buf_free(&dir); + + cl_assert((dir2 = git_path_dirname(A)) != NULL); + cl_assert_equal_s(B, dir2); + git__free(dir2); +} + +static void +check_basename(const char *A, const char *B) +{ + git_buf base = GIT_BUF_INIT; + char *base2; + + cl_assert(git_path_basename_r(&base, A) >= 0); + cl_assert_equal_s(B, base.ptr); + git_buf_free(&base); + + cl_assert((base2 = git_path_basename(A)) != NULL); + cl_assert_equal_s(B, base2); + git__free(base2); +} + +static void +check_topdir(const char *A, const char *B) +{ + const char *dir; + + cl_assert((dir = git_path_topdir(A)) != NULL); + cl_assert_equal_s(B, dir); +} + +static void +check_joinpath(const char *path_a, const char *path_b, const char *expected_path) +{ + git_buf joined_path = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&joined_path, path_a, path_b)); + cl_assert_equal_s(expected_path, joined_path.ptr); + + git_buf_free(&joined_path); +} + +static void +check_joinpath_n( + const char *path_a, + const char *path_b, + const char *path_c, + const char *path_d, + const char *expected_path) +{ + git_buf joined_path = GIT_BUF_INIT; + + cl_git_pass(git_buf_join_n(&joined_path, '/', 4, + path_a, path_b, path_c, path_d)); + cl_assert_equal_s(expected_path, joined_path.ptr); + + git_buf_free(&joined_path); +} + + +/* get the dirname of a path */ +void test_core_path__00_dirname(void) +{ + check_dirname(NULL, "."); + check_dirname("", "."); + check_dirname("a", "."); + check_dirname("/", "/"); + check_dirname("/usr", "/"); + check_dirname("/usr/", "/"); + check_dirname("/usr/lib", "/usr"); + check_dirname("/usr/lib/", "/usr"); + check_dirname("/usr/lib//", "/usr"); + check_dirname("usr/lib", "usr"); + check_dirname("usr/lib/", "usr"); + check_dirname("usr/lib//", "usr"); + check_dirname(".git/", "."); + + check_dirname(REP16("/abc"), REP15("/abc")); + +#ifdef GIT_WIN32 + check_dirname("C:/path/", "C:/"); + check_dirname("C:/path", "C:/"); + check_dirname("//computername/path/", "//computername/"); + check_dirname("//computername/path", "//computername/"); + check_dirname("//computername/sub/path/", "//computername/sub"); + check_dirname("//computername/sub/path", "//computername/sub"); +#endif +} + +/* get the base name of a path */ +void test_core_path__01_basename(void) +{ + check_basename(NULL, "."); + check_basename("", "."); + check_basename("a", "a"); + check_basename("/", "/"); + check_basename("/usr", "usr"); + check_basename("/usr/", "usr"); + check_basename("/usr/lib", "lib"); + check_basename("/usr/lib//", "lib"); + check_basename("usr/lib", "lib"); + + check_basename(REP16("/abc"), "abc"); + check_basename(REP1024("/abc"), "abc"); +} + +/* get the latest component in a path */ +void test_core_path__02_topdir(void) +{ + check_topdir(".git/", ".git/"); + check_topdir("/.git/", ".git/"); + check_topdir("usr/local/.git/", ".git/"); + check_topdir("./.git/", ".git/"); + check_topdir("/usr/.git/", ".git/"); + check_topdir("/", "/"); + check_topdir("a/", "a/"); + + cl_assert(git_path_topdir("/usr/.git") == NULL); + cl_assert(git_path_topdir(".") == NULL); + cl_assert(git_path_topdir("") == NULL); + cl_assert(git_path_topdir("a") == NULL); +} + +/* properly join path components */ +void test_core_path__05_joins(void) +{ + check_joinpath("", "", ""); + check_joinpath("", "a", "a"); + check_joinpath("", "/a", "/a"); + check_joinpath("a", "", "a/"); + check_joinpath("a", "/", "a/"); + check_joinpath("a", "b", "a/b"); + check_joinpath("/", "a", "/a"); + check_joinpath("/", "", "/"); + check_joinpath("/a", "/b", "/a/b"); + check_joinpath("/a", "/b/", "/a/b/"); + check_joinpath("/a/", "b/", "/a/b/"); + check_joinpath("/a/", "/b/", "/a/b/"); + + check_joinpath("/abcd", "/defg", "/abcd/defg"); + check_joinpath("/abcd", "/defg/", "/abcd/defg/"); + check_joinpath("/abcd/", "defg/", "/abcd/defg/"); + check_joinpath("/abcd/", "/defg/", "/abcd/defg/"); + + check_joinpath("/abcdefgh", "/12345678", "/abcdefgh/12345678"); + check_joinpath("/abcdefgh", "/12345678/", "/abcdefgh/12345678/"); + check_joinpath("/abcdefgh/", "12345678/", "/abcdefgh/12345678/"); + + check_joinpath(REP1024("aaaa"), "", REP1024("aaaa") "/"); + check_joinpath(REP1024("aaaa/"), "", REP1024("aaaa/")); + check_joinpath(REP1024("/aaaa"), "", REP1024("/aaaa") "/"); + + check_joinpath(REP1024("aaaa"), REP1024("bbbb"), + REP1024("aaaa") "/" REP1024("bbbb")); + check_joinpath(REP1024("/aaaa"), REP1024("/bbbb"), + REP1024("/aaaa") REP1024("/bbbb")); +} + +/* properly join path components for more than one path */ +void test_core_path__06_long_joins(void) +{ + check_joinpath_n("", "", "", "", ""); + check_joinpath_n("", "a", "", "", "a/"); + check_joinpath_n("a", "", "", "", "a/"); + check_joinpath_n("", "", "", "a", "a"); + check_joinpath_n("a", "b", "", "/c/d/", "a/b/c/d/"); + check_joinpath_n("a", "b", "", "/c/d", "a/b/c/d"); + check_joinpath_n("abcd", "efgh", "ijkl", "mnop", "abcd/efgh/ijkl/mnop"); + check_joinpath_n("abcd/", "efgh/", "ijkl/", "mnop/", "abcd/efgh/ijkl/mnop/"); + check_joinpath_n("/abcd/", "/efgh/", "/ijkl/", "/mnop/", "/abcd/efgh/ijkl/mnop/"); + + check_joinpath_n(REP1024("a"), REP1024("b"), REP1024("c"), REP1024("d"), + REP1024("a") "/" REP1024("b") "/" + REP1024("c") "/" REP1024("d")); + check_joinpath_n(REP1024("/a"), REP1024("/b"), REP1024("/c"), REP1024("/d"), + REP1024("/a") REP1024("/b") + REP1024("/c") REP1024("/d")); +} + + +static void +check_path_to_dir( + const char* path, + const char* expected) +{ + git_buf tgt = GIT_BUF_INIT; + + git_buf_sets(&tgt, path); + cl_git_pass(git_path_to_dir(&tgt)); + cl_assert_equal_s(expected, tgt.ptr); + + git_buf_free(&tgt); +} + +static void +check_string_to_dir( + const char* path, + size_t maxlen, + const char* expected) +{ + size_t len = strlen(path); + char *buf = git__malloc(len + 2); + cl_assert(buf); + + strncpy(buf, path, len + 2); + + git_path_string_to_dir(buf, maxlen); + + cl_assert_equal_s(expected, buf); + + git__free(buf); +} + +/* convert paths to dirs */ +void test_core_path__07_path_to_dir(void) +{ + check_path_to_dir("", ""); + check_path_to_dir(".", "./"); + check_path_to_dir("./", "./"); + check_path_to_dir("a/", "a/"); + check_path_to_dir("ab", "ab/"); + /* make sure we try just under and just over an expansion that will + * require a realloc + */ + check_path_to_dir("abcdef", "abcdef/"); + check_path_to_dir("abcdefg", "abcdefg/"); + check_path_to_dir("abcdefgh", "abcdefgh/"); + check_path_to_dir("abcdefghi", "abcdefghi/"); + check_path_to_dir(REP1024("abcd") "/", REP1024("abcd") "/"); + check_path_to_dir(REP1024("abcd"), REP1024("abcd") "/"); + + check_string_to_dir("", 1, ""); + check_string_to_dir(".", 1, "."); + check_string_to_dir(".", 2, "./"); + check_string_to_dir(".", 3, "./"); + check_string_to_dir("abcd", 3, "abcd"); + check_string_to_dir("abcd", 4, "abcd"); + check_string_to_dir("abcd", 5, "abcd/"); + check_string_to_dir("abcd", 6, "abcd/"); +} + +/* join path to itself */ +void test_core_path__08_self_join(void) +{ + git_buf path = GIT_BUF_INIT; + size_t asize = 0; + + asize = path.asize; + cl_git_pass(git_buf_sets(&path, "/foo")); + cl_assert_equal_s(path.ptr, "/foo"); + cl_assert(asize < path.asize); + + asize = path.asize; + cl_git_pass(git_buf_joinpath(&path, path.ptr, "this is a new string")); + cl_assert_equal_s(path.ptr, "/foo/this is a new string"); + cl_assert(asize < path.asize); + + asize = path.asize; + cl_git_pass(git_buf_joinpath(&path, path.ptr, "/grow the buffer, grow the buffer, grow the buffer")); + cl_assert_equal_s(path.ptr, "/foo/this is a new string/grow the buffer, grow the buffer, grow the buffer"); + cl_assert(asize < path.asize); + + git_buf_free(&path); + cl_git_pass(git_buf_sets(&path, "/foo/bar")); + + cl_git_pass(git_buf_joinpath(&path, path.ptr + 4, "baz")); + cl_assert_equal_s(path.ptr, "/bar/baz"); + + asize = path.asize; + cl_git_pass(git_buf_joinpath(&path, path.ptr + 4, "somethinglongenoughtorealloc")); + cl_assert_equal_s(path.ptr, "/baz/somethinglongenoughtorealloc"); + cl_assert(asize < path.asize); + + git_buf_free(&path); +} + +static void check_percent_decoding(const char *expected_result, const char *input) +{ + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git__percent_decode(&buf, input)); + cl_assert_equal_s(expected_result, git_buf_cstr(&buf)); + + git_buf_free(&buf); +} + +void test_core_path__09_percent_decode(void) +{ + check_percent_decoding("abcd", "abcd"); + check_percent_decoding("a2%", "a2%"); + check_percent_decoding("a2%3", "a2%3"); + check_percent_decoding("a2%%3", "a2%%3"); + check_percent_decoding("a2%3z", "a2%3z"); + check_percent_decoding("a,", "a%2c"); + check_percent_decoding("a21", "a2%31"); + check_percent_decoding("a2%1", "a2%%31"); + check_percent_decoding("a bc ", "a%20bc%20"); + check_percent_decoding("Vicent Mart" "\355", "Vicent%20Mart%ED"); +} + +static void check_fromurl(const char *expected_result, const char *input, int should_fail) +{ + git_buf buf = GIT_BUF_INIT; + + assert(should_fail || expected_result); + + if (!should_fail) { + cl_git_pass(git_path_fromurl(&buf, input)); + cl_assert_equal_s(expected_result, git_buf_cstr(&buf)); + } else + cl_git_fail(git_path_fromurl(&buf, input)); + + git_buf_free(&buf); +} + +#ifdef GIT_WIN32 +#define ABS_PATH_MARKER "" +#else +#define ABS_PATH_MARKER "/" +#endif + +void test_core_path__10_fromurl(void) +{ + /* Failing cases */ + check_fromurl(NULL, "a", 1); + check_fromurl(NULL, "http:///c:/Temp%20folder/note.txt", 1); + check_fromurl(NULL, "file://c:/Temp%20folder/note.txt", 1); + check_fromurl(NULL, "file:////c:/Temp%20folder/note.txt", 1); + check_fromurl(NULL, "file:///", 1); + check_fromurl(NULL, "file:////", 1); + check_fromurl(NULL, "file://servername/c:/Temp%20folder/note.txt", 1); + + /* Passing cases */ + check_fromurl(ABS_PATH_MARKER "c:/Temp folder/note.txt", "file:///c:/Temp%20folder/note.txt", 0); + check_fromurl(ABS_PATH_MARKER "c:/Temp folder/note.txt", "file://localhost/c:/Temp%20folder/note.txt", 0); + check_fromurl(ABS_PATH_MARKER "c:/Temp+folder/note.txt", "file:///c:/Temp+folder/note.txt", 0); + check_fromurl(ABS_PATH_MARKER "a", "file:///a", 0); +} + +typedef struct { + int expect_idx; + char **expect; +} check_walkup_info; + +static int check_one_walkup_step(void *ref, git_buf *path) +{ + check_walkup_info *info = (check_walkup_info *)ref; + cl_assert(info->expect[info->expect_idx] != NULL); + cl_assert_equal_s(info->expect[info->expect_idx], path->ptr); + info->expect_idx++; + return 0; +} + +void test_core_path__11_walkup(void) +{ + git_buf p = GIT_BUF_INIT; + char *expect[] = { + "/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL, + "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL, + "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL, + "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL, + "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL, + "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL, + "this is a path", NULL, + "///a///b///c///d///e///", "///a///b///c///d///", "///a///b///c///", "///a///b///", "///a///", "///", NULL, + NULL + }; + char *root[] = { NULL, NULL, "/", "", "/a/b", "/a/b/", NULL, NULL, NULL }; + int i, j; + check_walkup_info info; + + info.expect = expect; + + for (i = 0, j = 0; expect[i] != NULL; i++, j++) { + + git_buf_sets(&p, expect[i]); + + info.expect_idx = i; + cl_git_pass( + git_path_walk_up(&p, root[j], check_one_walkup_step, &info) + ); + + cl_assert_equal_s(p.ptr, expect[i]); + + /* skip to next run of expectations */ + while (expect[i] != NULL) i++; + } + + git_buf_free(&p); +} + +void test_core_path__12_offset_to_path_root(void) +{ + cl_assert(git_path_root("non/rooted/path") == -1); + cl_assert(git_path_root("/rooted/path") == 0); + +#ifdef GIT_WIN32 + /* Windows specific tests */ + cl_assert(git_path_root("C:non/rooted/path") == -1); + cl_assert(git_path_root("C:/rooted/path") == 2); + cl_assert(git_path_root("//computername/sharefolder/resource") == 14); + cl_assert(git_path_root("//computername/sharefolder") == 14); + cl_assert(git_path_root("//computername") == -1); +#endif +} + +#define NON_EXISTING_FILEPATH "i_hope_i_do_not_exist" + +void test_core_path__13_cannot_prettify_a_non_existing_file(void) +{ + git_buf p = GIT_BUF_INIT; + + cl_must_pass(git_path_exists(NON_EXISTING_FILEPATH) == false); + cl_assert_equal_i(GIT_ENOTFOUND, git_path_prettify(&p, NON_EXISTING_FILEPATH, NULL)); + cl_assert_equal_i(GIT_ENOTFOUND, git_path_prettify(&p, NON_EXISTING_FILEPATH "/so-do-i", NULL)); + + git_buf_free(&p); +} + +void test_core_path__14_apply_relative(void) +{ + git_buf p = GIT_BUF_INIT; + + cl_git_pass(git_buf_sets(&p, "/this/is/a/base")); + + cl_git_pass(git_path_apply_relative(&p, "../test")); + cl_assert_equal_s("/this/is/a/test", p.ptr); + + cl_git_pass(git_path_apply_relative(&p, "../../the/./end")); + cl_assert_equal_s("/this/is/the/end", p.ptr); + + cl_git_pass(git_path_apply_relative(&p, "./of/this/../the/string")); + cl_assert_equal_s("/this/is/the/end/of/the/string", p.ptr); + + cl_git_pass(git_path_apply_relative(&p, "../../../../../..")); + cl_assert_equal_s("/this/", p.ptr); + + cl_git_pass(git_path_apply_relative(&p, "../")); + cl_assert_equal_s("/", p.ptr); + + cl_git_fail(git_path_apply_relative(&p, "../../..")); + + + cl_git_pass(git_buf_sets(&p, "d:/another/test")); + + cl_git_pass(git_path_apply_relative(&p, "../..")); + cl_assert_equal_s("d:/", p.ptr); + + cl_git_pass(git_path_apply_relative(&p, "from/here/to/../and/./back/.")); + cl_assert_equal_s("d:/from/here/and/back/", p.ptr); + + + cl_git_pass(git_buf_sets(&p, "https://my.url.com/test.git")); + + cl_git_pass(git_path_apply_relative(&p, "../another.git")); + cl_assert_equal_s("https://my.url.com/another.git", p.ptr); + + cl_git_pass(git_path_apply_relative(&p, "../full/path/url.patch")); + cl_assert_equal_s("https://my.url.com/full/path/url.patch", p.ptr); + + cl_git_pass(git_path_apply_relative(&p, "..")); + cl_assert_equal_s("https://my.url.com/full/path/", p.ptr); + + cl_git_pass(git_path_apply_relative(&p, "../../../")); + cl_assert_equal_s("https://", p.ptr); + + + cl_git_pass(git_buf_sets(&p, "../../this/is/relative")); + + cl_git_pass(git_path_apply_relative(&p, "../../preserves/the/prefix")); + cl_assert_equal_s("../../this/preserves/the/prefix", p.ptr); + + cl_git_pass(git_path_apply_relative(&p, "../../../../that")); + cl_assert_equal_s("../../that", p.ptr); + + cl_git_pass(git_path_apply_relative(&p, "../there")); + cl_assert_equal_s("../../there", p.ptr); + git_buf_free(&p); +} + +static void assert_resolve_relative( + git_buf *buf, const char *expected, const char *path) +{ + cl_git_pass(git_buf_sets(buf, path)); + cl_git_pass(git_path_resolve_relative(buf, 0)); + cl_assert_equal_s(expected, buf->ptr); +} + +void test_core_path__15_resolve_relative(void) +{ + git_buf buf = GIT_BUF_INIT; + + assert_resolve_relative(&buf, "", ""); + assert_resolve_relative(&buf, "", "."); + assert_resolve_relative(&buf, "", "./"); + assert_resolve_relative(&buf, "..", ".."); + assert_resolve_relative(&buf, "../", "../"); + assert_resolve_relative(&buf, "..", "./.."); + assert_resolve_relative(&buf, "../", "./../"); + assert_resolve_relative(&buf, "../", "../."); + assert_resolve_relative(&buf, "../", ".././"); + assert_resolve_relative(&buf, "../..", "../.."); + assert_resolve_relative(&buf, "../../", "../../"); + + assert_resolve_relative(&buf, "/", "/"); + assert_resolve_relative(&buf, "/", "/."); + + assert_resolve_relative(&buf, "", "a/.."); + assert_resolve_relative(&buf, "", "a/../"); + assert_resolve_relative(&buf, "", "a/../."); + + assert_resolve_relative(&buf, "/a", "/a"); + assert_resolve_relative(&buf, "/a/", "/a/."); + assert_resolve_relative(&buf, "/", "/a/../"); + assert_resolve_relative(&buf, "/", "/a/../."); + assert_resolve_relative(&buf, "/", "/a/.././"); + + assert_resolve_relative(&buf, "a", "a"); + assert_resolve_relative(&buf, "a/", "a/"); + assert_resolve_relative(&buf, "a/", "a/."); + assert_resolve_relative(&buf, "a/", "a/./"); + + assert_resolve_relative(&buf, "a/b", "a//b"); + assert_resolve_relative(&buf, "a/b/c", "a/b/c"); + assert_resolve_relative(&buf, "b/c", "./b/c"); + assert_resolve_relative(&buf, "a/c", "a/./c"); + assert_resolve_relative(&buf, "a/b/", "a/b/."); + + assert_resolve_relative(&buf, "/a/b/c", "///a/b/c"); + assert_resolve_relative(&buf, "/", "////"); + assert_resolve_relative(&buf, "/a", "///a"); + assert_resolve_relative(&buf, "/", "///."); + assert_resolve_relative(&buf, "/", "///a/.."); + + assert_resolve_relative(&buf, "../../path", "../../test//../././path"); + assert_resolve_relative(&buf, "../d", "a/b/../../../c/../d"); + + cl_git_pass(git_buf_sets(&buf, "/..")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); + + cl_git_pass(git_buf_sets(&buf, "/./..")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); + + cl_git_pass(git_buf_sets(&buf, "/.//..")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); + + cl_git_pass(git_buf_sets(&buf, "/../.")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); + + cl_git_pass(git_buf_sets(&buf, "/../.././../a")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); + + cl_git_pass(git_buf_sets(&buf, "////..")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); + + /* things that start with Windows network paths */ +#ifdef GIT_WIN32 + assert_resolve_relative(&buf, "//a/b/c", "//a/b/c"); + assert_resolve_relative(&buf, "//a/", "//a/b/.."); + assert_resolve_relative(&buf, "//a/b/c", "//a/Q/../b/x/y/../../c"); + + cl_git_pass(git_buf_sets(&buf, "//a/b/../..")); + cl_git_fail(git_path_resolve_relative(&buf, 0)); +#else + assert_resolve_relative(&buf, "/a/b/c", "//a/b/c"); + assert_resolve_relative(&buf, "/a/", "//a/b/.."); + assert_resolve_relative(&buf, "/a/b/c", "//a/Q/../b/x/y/../../c"); + assert_resolve_relative(&buf, "/", "//a/b/../.."); +#endif + + git_buf_free(&buf); +} diff --git a/tests/core/pool.c b/tests/core/pool.c new file mode 100644 index 000000000..3073c4a45 --- /dev/null +++ b/tests/core/pool.c @@ -0,0 +1,145 @@ +#include "clar_libgit2.h" +#include "pool.h" +#include "git2/oid.h" + +void test_core_pool__0(void) +{ + int i; + git_pool p; + void *ptr; + + cl_git_pass(git_pool_init(&p, 1, 4000)); + + for (i = 1; i < 10000; i *= 2) { + ptr = git_pool_malloc(&p, i); + cl_assert(ptr != NULL); + cl_assert(git_pool__ptr_in_pool(&p, ptr)); + cl_assert(!git_pool__ptr_in_pool(&p, &i)); + } + + /* 1+2+4+8+16+32+64+128+256+512+1024 -> original block */ + /* 2048 -> 1 block */ + /* 4096 -> 1 block */ + /* 8192 -> 1 block */ + + cl_assert(git_pool__open_pages(&p) + git_pool__full_pages(&p) == 4); + + git_pool_clear(&p); +} + +void test_core_pool__1(void) +{ + int i; + git_pool p; + + cl_git_pass(git_pool_init(&p, 1, 4000)); + + for (i = 2010; i > 0; i--) + cl_assert(git_pool_malloc(&p, i) != NULL); + + /* with fixed page size, allocation must end up with these values */ + cl_assert(git_pool__open_pages(&p) == 1); + cl_assert(git_pool__full_pages(&p) == 505); + + git_pool_clear(&p); + + cl_git_pass(git_pool_init(&p, 1, 4100)); + + for (i = 2010; i > 0; i--) + cl_assert(git_pool_malloc(&p, i) != NULL); + + /* with fixed page size, allocation must end up with these values */ + cl_assert(git_pool__open_pages(&p) == 1); + cl_assert(git_pool__full_pages(&p) == 492); + + git_pool_clear(&p); +} + +static char to_hex[] = "0123456789abcdef"; + +void test_core_pool__2(void) +{ + git_pool p; + char oid_hex[GIT_OID_HEXSZ]; + git_oid *oid; + int i, j; + + memset(oid_hex, '0', sizeof(oid_hex)); + + cl_git_pass(git_pool_init(&p, sizeof(git_oid), 100)); + + for (i = 1000; i < 10000; i++) { + oid = git_pool_malloc(&p, 1); + cl_assert(oid != NULL); + + for (j = 0; j < 8; j++) + oid_hex[j] = to_hex[(i >> (4 * j)) & 0x0f]; + cl_git_pass(git_oid_fromstr(oid, oid_hex)); + } + + /* with fixed page size, allocation must end up with these values */ + cl_assert(git_pool__open_pages(&p) == 0); + cl_assert(git_pool__full_pages(&p) == 90); + + git_pool_clear(&p); +} + +void test_core_pool__free_list(void) +{ + int i; + git_pool p; + void *ptr, *ptrs[50]; + + cl_git_pass(git_pool_init(&p, 100, 100)); + + for (i = 0; i < 10; ++i) { + ptr = git_pool_malloc(&p, 1); + cl_assert(ptr != NULL); + } + cl_assert_equal_i(10, (int)p.items); + + for (i = 0; i < 50; ++i) { + ptrs[i] = git_pool_malloc(&p, 1); + cl_assert(ptrs[i] != NULL); + } + cl_assert_equal_i(60, (int)p.items); + + git_pool_free(&p, ptr); + cl_assert_equal_i(60, (int)p.items); + + git_pool_free_array(&p, 50, ptrs); + cl_assert_equal_i(60, (int)p.items); + + for (i = 0; i < 50; ++i) { + ptrs[i] = git_pool_malloc(&p, 1); + cl_assert(ptrs[i] != NULL); + } + cl_assert_equal_i(60, (int)p.items); + + for (i = 0; i < 111; ++i) { + ptr = git_pool_malloc(&p, 1); + cl_assert(ptr != NULL); + } + cl_assert_equal_i(170, (int)p.items); + + git_pool_free_array(&p, 50, ptrs); + cl_assert_equal_i(170, (int)p.items); + + for (i = 0; i < 50; ++i) { + ptrs[i] = git_pool_malloc(&p, 1); + cl_assert(ptrs[i] != NULL); + } + cl_assert_equal_i(170, (int)p.items); + + git_pool_clear(&p); +} + +void test_core_pool__strndup_limit(void) +{ + git_pool p; + + cl_git_pass(git_pool_init(&p, 1, 100)); + cl_assert(git_pool_strndup(&p, "foo", -1) == NULL); + git_pool_clear(&p); +} + diff --git a/tests/core/posix.c b/tests/core/posix.c new file mode 100644 index 000000000..1cef937cd --- /dev/null +++ b/tests/core/posix.c @@ -0,0 +1,99 @@ +#ifndef _WIN32 +# include +# include +# include +#else +# include +# ifdef _MSC_VER +# pragma comment(lib, "ws2_32") +# endif +#endif + +#include "clar_libgit2.h" +#include "posix.h" + +void test_core_posix__initialize(void) +{ +#ifdef GIT_WIN32 + /* on win32, the WSA context needs to be initialized + * before any socket calls can be performed */ + WSADATA wsd; + + cl_git_pass(WSAStartup(MAKEWORD(2,2), &wsd)); + cl_assert(LOBYTE(wsd.wVersion) == 2 && HIBYTE(wsd.wVersion) == 2); +#endif +} + +static bool supports_ipv6(void) +{ +#ifdef GIT_WIN32 + /* IPv6 is supported on Vista and newer */ + return git_has_win32_version(6, 0, 0); +#else + return 1; +#endif +} + +void test_core_posix__inet_pton(void) +{ + struct in_addr addr; + struct in6_addr addr6; + size_t i; + + struct in_addr_data { + const char *p; + const uint8_t n[4]; + }; + + struct in6_addr_data { + const char *p; + const uint8_t n[16]; + }; + + static struct in_addr_data in_addr_data[] = { + { "0.0.0.0", { 0, 0, 0, 0 } }, + { "10.42.101.8", { 10, 42, 101, 8 } }, + { "127.0.0.1", { 127, 0, 0, 1 } }, + { "140.177.10.12", { 140, 177, 10, 12 } }, + { "204.232.175.90", { 204, 232, 175, 90 } }, + { "255.255.255.255", { 255, 255, 255, 255 } }, + }; + + static struct in6_addr_data in6_addr_data[] = { + { "::", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { "::1", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, + { "0:0:0:0:0:0:0:1", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, + { "2001:db8:8714:3a90::12", { 0x20, 0x01, 0x0d, 0xb8, 0x87, 0x14, 0x3a, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12 } }, + { "fe80::f8ba:c2d6:86be:3645", { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xba, 0xc2, 0xd6, 0x86, 0xbe, 0x36, 0x45 } }, + { "::ffff:204.152.189.116", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0x98, 0xbd, 0x74 } }, + }; + + /* Test some ipv4 addresses */ + for (i = 0; i < 6; i++) { + cl_assert(p_inet_pton(AF_INET, in_addr_data[i].p, &addr) == 1); + cl_assert(memcmp(&addr, in_addr_data[i].n, sizeof(struct in_addr)) == 0); + } + + /* Test some ipv6 addresses */ + if (supports_ipv6()) + { + for (i = 0; i < 6; i++) { + cl_assert(p_inet_pton(AF_INET6, in6_addr_data[i].p, &addr6) == 1); + cl_assert(memcmp(&addr6, in6_addr_data[i].n, sizeof(struct in6_addr)) == 0); + } + } + + /* Test some invalid strings */ + cl_assert(p_inet_pton(AF_INET, "", &addr) == 0); + cl_assert(p_inet_pton(AF_INET, "foo", &addr) == 0); + cl_assert(p_inet_pton(AF_INET, " 127.0.0.1", &addr) == 0); + cl_assert(p_inet_pton(AF_INET, "bar", &addr) == 0); + 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_assert_equal_i(EAFNOSUPPORT, errno); + + cl_git_fail(p_inet_pton(5, "315.124", NULL)); /* AF_CHAOS */ + cl_assert_equal_i(EAFNOSUPPORT, errno); +} diff --git a/tests/core/rmdir.c b/tests/core/rmdir.c new file mode 100644 index 000000000..f0b0bfa42 --- /dev/null +++ b/tests/core/rmdir.c @@ -0,0 +1,98 @@ +#include "clar_libgit2.h" +#include "fileops.h" + +static const char *empty_tmp_dir = "test_gitfo_rmdir_recurs_test"; + +void test_core_rmdir__initialize(void) +{ + git_buf path = GIT_BUF_INIT; + + cl_must_pass(p_mkdir(empty_tmp_dir, 0777)); + + cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one")); + cl_must_pass(p_mkdir(path.ptr, 0777)); + + cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one/two_one")); + cl_must_pass(p_mkdir(path.ptr, 0777)); + + cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one/two_two")); + cl_must_pass(p_mkdir(path.ptr, 0777)); + + cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/one/two_two/three")); + cl_must_pass(p_mkdir(path.ptr, 0777)); + + cl_git_pass(git_buf_joinpath(&path, empty_tmp_dir, "/two")); + cl_must_pass(p_mkdir(path.ptr, 0777)); + + git_buf_free(&path); +} + +/* make sure empty dir can be deleted recusively */ +void test_core_rmdir__delete_recursive(void) +{ + cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_EMPTY_HIERARCHY)); +} + +/* make sure non-empty dir cannot be deleted recusively */ +void test_core_rmdir__fail_to_delete_non_empty_dir(void) +{ + git_buf file = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&file, empty_tmp_dir, "/two/file.txt")); + + cl_git_mkfile(git_buf_cstr(&file), "dummy"); + + cl_git_fail(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_EMPTY_HIERARCHY)); + + cl_must_pass(p_unlink(file.ptr)); + cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_EMPTY_HIERARCHY)); + + git_buf_free(&file); +} + +void test_core_rmdir__can_skip_non_empty_dir(void) +{ + git_buf file = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&file, empty_tmp_dir, "/two/file.txt")); + + cl_git_mkfile(git_buf_cstr(&file), "dummy"); + + cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_SKIP_NONEMPTY)); + cl_assert(git_path_exists(git_buf_cstr(&file)) == true); + + cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_REMOVE_FILES)); + cl_assert(git_path_exists(empty_tmp_dir) == false); + + git_buf_free(&file); +} + +void test_core_rmdir__can_remove_empty_parents(void) +{ + git_buf file = GIT_BUF_INIT; + + cl_git_pass( + git_buf_joinpath(&file, empty_tmp_dir, "/one/two_two/three/file.txt")); + cl_git_mkfile(git_buf_cstr(&file), "dummy"); + cl_assert(git_path_isfile(git_buf_cstr(&file))); + + cl_git_pass(git_futils_rmdir_r("one/two_two/three/file.txt", empty_tmp_dir, + GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_EMPTY_PARENTS)); + + cl_assert(!git_path_exists(git_buf_cstr(&file))); + + git_buf_rtruncate_at_char(&file, '/'); /* three (only contained file.txt) */ + cl_assert(!git_path_exists(git_buf_cstr(&file))); + + git_buf_rtruncate_at_char(&file, '/'); /* two_two (only contained three) */ + cl_assert(!git_path_exists(git_buf_cstr(&file))); + + git_buf_rtruncate_at_char(&file, '/'); /* one (contained two_one also) */ + cl_assert(git_path_exists(git_buf_cstr(&file))); + + cl_assert(git_path_exists(empty_tmp_dir) == true); + + git_buf_free(&file); + + cl_git_pass(git_futils_rmdir_r(empty_tmp_dir, NULL, GIT_RMDIR_EMPTY_HIERARCHY)); +} diff --git a/tests/core/sortedcache.c b/tests/core/sortedcache.c new file mode 100644 index 000000000..c1869bee0 --- /dev/null +++ b/tests/core/sortedcache.c @@ -0,0 +1,363 @@ +#include "clar_libgit2.h" +#include "sortedcache.h" + +static int name_only_cmp(const void *a, const void *b) +{ + return strcmp(a, b); +} + +void test_core_sortedcache__name_only(void) +{ + git_sortedcache *sc; + void *item; + size_t pos; + + cl_git_pass(git_sortedcache_new( + &sc, 0, NULL, NULL, name_only_cmp, NULL)); + + cl_git_pass(git_sortedcache_wlock(sc)); + cl_git_pass(git_sortedcache_upsert(&item, sc, "aaa")); + cl_git_pass(git_sortedcache_upsert(&item, sc, "bbb")); + cl_git_pass(git_sortedcache_upsert(&item, sc, "zzz")); + cl_git_pass(git_sortedcache_upsert(&item, sc, "mmm")); + cl_git_pass(git_sortedcache_upsert(&item, sc, "iii")); + git_sortedcache_wunlock(sc); + + cl_assert_equal_sz(5, git_sortedcache_entrycount(sc)); + + cl_assert((item = git_sortedcache_lookup(sc, "aaa")) != NULL); + cl_assert_equal_s("aaa", item); + cl_assert((item = git_sortedcache_lookup(sc, "mmm")) != NULL); + cl_assert_equal_s("mmm", item); + cl_assert((item = git_sortedcache_lookup(sc, "zzz")) != NULL); + cl_assert_equal_s("zzz", item); + cl_assert(git_sortedcache_lookup(sc, "qqq") == NULL); + + cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); + cl_assert_equal_s("aaa", item); + cl_assert((item = git_sortedcache_entry(sc, 1)) != NULL); + cl_assert_equal_s("bbb", item); + cl_assert((item = git_sortedcache_entry(sc, 2)) != NULL); + cl_assert_equal_s("iii", item); + cl_assert((item = git_sortedcache_entry(sc, 3)) != NULL); + cl_assert_equal_s("mmm", item); + cl_assert((item = git_sortedcache_entry(sc, 4)) != NULL); + cl_assert_equal_s("zzz", item); + cl_assert(git_sortedcache_entry(sc, 5) == NULL); + + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "aaa")); + cl_assert_equal_sz(0, pos); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "iii")); + cl_assert_equal_sz(2, pos); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "zzz")); + cl_assert_equal_sz(4, pos); + cl_assert_equal_i( + GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "abc")); + + git_sortedcache_clear(sc, true); + + cl_assert_equal_sz(0, git_sortedcache_entrycount(sc)); + cl_assert(git_sortedcache_entry(sc, 0) == NULL); + cl_assert(git_sortedcache_lookup(sc, "aaa") == NULL); + cl_assert(git_sortedcache_entry(sc, 0) == NULL); + + git_sortedcache_free(sc); +} + +typedef struct { + int value; + char smaller_value; + char path[GIT_FLEX_ARRAY]; +} sortedcache_test_struct; + +static int sortedcache_test_struct_cmp(const void *a_, const void *b_) +{ + const sortedcache_test_struct *a = a_, *b = b_; + return strcmp(a->path, b->path); +} + +static void sortedcache_test_struct_free(void *payload, void *item_) +{ + sortedcache_test_struct *item = item_; + int *count = payload; + (*count)++; + item->smaller_value = 0; +} + +void test_core_sortedcache__in_memory(void) +{ + git_sortedcache *sc; + sortedcache_test_struct *item; + int free_count = 0; + + cl_git_pass(git_sortedcache_new( + &sc, offsetof(sortedcache_test_struct, path), + sortedcache_test_struct_free, &free_count, + sortedcache_test_struct_cmp, NULL)); + + cl_git_pass(git_sortedcache_wlock(sc)); + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "aaa")); + item->value = 10; + item->smaller_value = 1; + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "bbb")); + item->value = 20; + item->smaller_value = 2; + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "zzz")); + item->value = 30; + item->smaller_value = 26; + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "mmm")); + item->value = 40; + item->smaller_value = 14; + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "iii")); + item->value = 50; + item->smaller_value = 9; + git_sortedcache_wunlock(sc); + + cl_assert_equal_sz(5, git_sortedcache_entrycount(sc)); + + cl_git_pass(git_sortedcache_rlock(sc)); + + cl_assert((item = git_sortedcache_lookup(sc, "aaa")) != NULL); + cl_assert_equal_s("aaa", item->path); + cl_assert_equal_i(10, item->value); + cl_assert((item = git_sortedcache_lookup(sc, "mmm")) != NULL); + cl_assert_equal_s("mmm", item->path); + cl_assert_equal_i(40, item->value); + cl_assert((item = git_sortedcache_lookup(sc, "zzz")) != NULL); + cl_assert_equal_s("zzz", item->path); + cl_assert_equal_i(30, item->value); + cl_assert(git_sortedcache_lookup(sc, "abc") == NULL); + + /* not on Windows: + * cl_git_pass(git_sortedcache_rlock(sc)); -- grab more than one + */ + + cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); + cl_assert_equal_s("aaa", item->path); + cl_assert_equal_i(10, item->value); + cl_assert((item = git_sortedcache_entry(sc, 1)) != NULL); + cl_assert_equal_s("bbb", item->path); + cl_assert_equal_i(20, item->value); + cl_assert((item = git_sortedcache_entry(sc, 2)) != NULL); + cl_assert_equal_s("iii", item->path); + cl_assert_equal_i(50, item->value); + cl_assert((item = git_sortedcache_entry(sc, 3)) != NULL); + cl_assert_equal_s("mmm", item->path); + cl_assert_equal_i(40, item->value); + cl_assert((item = git_sortedcache_entry(sc, 4)) != NULL); + cl_assert_equal_s("zzz", item->path); + cl_assert_equal_i(30, item->value); + cl_assert(git_sortedcache_entry(sc, 5) == NULL); + + git_sortedcache_runlock(sc); + /* git_sortedcache_runlock(sc); */ + + cl_assert_equal_i(0, free_count); + + git_sortedcache_clear(sc, true); + + cl_assert_equal_i(5, free_count); + + cl_assert_equal_sz(0, git_sortedcache_entrycount(sc)); + cl_assert(git_sortedcache_entry(sc, 0) == NULL); + cl_assert(git_sortedcache_lookup(sc, "aaa") == NULL); + cl_assert(git_sortedcache_entry(sc, 0) == NULL); + + free_count = 0; + + cl_git_pass(git_sortedcache_wlock(sc)); + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "testing")); + item->value = 10; + item->smaller_value = 3; + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "again")); + item->value = 20; + item->smaller_value = 1; + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, "final")); + item->value = 30; + item->smaller_value = 2; + git_sortedcache_wunlock(sc); + + cl_assert_equal_sz(3, git_sortedcache_entrycount(sc)); + + cl_assert((item = git_sortedcache_lookup(sc, "testing")) != NULL); + cl_assert_equal_s("testing", item->path); + cl_assert_equal_i(10, item->value); + cl_assert((item = git_sortedcache_lookup(sc, "again")) != NULL); + cl_assert_equal_s("again", item->path); + cl_assert_equal_i(20, item->value); + cl_assert((item = git_sortedcache_lookup(sc, "final")) != NULL); + cl_assert_equal_s("final", item->path); + cl_assert_equal_i(30, item->value); + cl_assert(git_sortedcache_lookup(sc, "zzz") == NULL); + + cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); + cl_assert_equal_s("again", item->path); + cl_assert_equal_i(20, item->value); + cl_assert((item = git_sortedcache_entry(sc, 1)) != NULL); + cl_assert_equal_s("final", item->path); + cl_assert_equal_i(30, item->value); + cl_assert((item = git_sortedcache_entry(sc, 2)) != NULL); + cl_assert_equal_s("testing", item->path); + cl_assert_equal_i(10, item->value); + cl_assert(git_sortedcache_entry(sc, 3) == NULL); + + { + size_t pos; + + cl_git_pass(git_sortedcache_wlock(sc)); + + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "again")); + cl_assert_equal_sz(0, pos); + cl_git_pass(git_sortedcache_remove(sc, pos)); + cl_assert_equal_i( + GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "again")); + + cl_assert_equal_sz(2, git_sortedcache_entrycount(sc)); + + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "testing")); + cl_assert_equal_sz(1, pos); + cl_git_pass(git_sortedcache_remove(sc, pos)); + cl_assert_equal_i( + GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "testing")); + + cl_assert_equal_sz(1, git_sortedcache_entrycount(sc)); + + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "final")); + cl_assert_equal_sz(0, pos); + cl_git_pass(git_sortedcache_remove(sc, pos)); + cl_assert_equal_i( + GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "final")); + + cl_assert_equal_sz(0, git_sortedcache_entrycount(sc)); + + git_sortedcache_wunlock(sc); + } + + git_sortedcache_free(sc); + + cl_assert_equal_i(3, free_count); +} + +static void sortedcache_test_reload(git_sortedcache *sc) +{ + int count = 0; + git_buf buf = GIT_BUF_INIT; + char *scan, *after; + sortedcache_test_struct *item; + + cl_assert(git_sortedcache_lockandload(sc, &buf) > 0); + + git_sortedcache_clear(sc, false); /* clear once we already have lock */ + + for (scan = buf.ptr; *scan; scan = after + 1) { + int val = strtol(scan, &after, 0); + cl_assert(after > scan); + scan = after; + + for (scan = after; git__isspace(*scan); ++scan) /* find start */; + for (after = scan; *after && *after != '\n'; ++after) /* find eol */; + *after = '\0'; + + cl_git_pass(git_sortedcache_upsert((void **)&item, sc, scan)); + + item->value = val; + item->smaller_value = (char)(count++); + } + + git_sortedcache_wunlock(sc); + + git_buf_free(&buf); +} + +void test_core_sortedcache__on_disk(void) +{ + git_sortedcache *sc; + sortedcache_test_struct *item; + int free_count = 0; + size_t pos; + + cl_git_mkfile("cacheitems.txt", "10 abc\n20 bcd\n30 cde\n"); + + cl_git_pass(git_sortedcache_new( + &sc, offsetof(sortedcache_test_struct, path), + sortedcache_test_struct_free, &free_count, + sortedcache_test_struct_cmp, "cacheitems.txt")); + + /* should need to reload the first time */ + + sortedcache_test_reload(sc); + + /* test what we loaded */ + + cl_assert_equal_sz(3, git_sortedcache_entrycount(sc)); + + cl_assert((item = git_sortedcache_lookup(sc, "abc")) != NULL); + cl_assert_equal_s("abc", item->path); + cl_assert_equal_i(10, item->value); + cl_assert((item = git_sortedcache_lookup(sc, "cde")) != NULL); + cl_assert_equal_s("cde", item->path); + cl_assert_equal_i(30, item->value); + cl_assert(git_sortedcache_lookup(sc, "aaa") == NULL); + + cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); + cl_assert_equal_s("abc", item->path); + cl_assert_equal_i(10, item->value); + cl_assert((item = git_sortedcache_entry(sc, 1)) != NULL); + cl_assert_equal_s("bcd", item->path); + cl_assert_equal_i(20, item->value); + cl_assert(git_sortedcache_entry(sc, 3) == NULL); + + /* should not need to reload this time */ + + cl_assert_equal_i(0, git_sortedcache_lockandload(sc, NULL)); + + /* rewrite ondisk file and reload */ + + cl_assert_equal_i(0, free_count); + + cl_git_rewritefile( + "cacheitems.txt", "100 abc\n200 zzz\n500 aaa\n10 final\n"); + sortedcache_test_reload(sc); + + cl_assert_equal_i(3, free_count); + + /* test what we loaded */ + + cl_assert_equal_sz(4, git_sortedcache_entrycount(sc)); + + cl_assert((item = git_sortedcache_lookup(sc, "abc")) != NULL); + cl_assert_equal_s("abc", item->path); + cl_assert_equal_i(100, item->value); + cl_assert((item = git_sortedcache_lookup(sc, "final")) != NULL); + cl_assert_equal_s("final", item->path); + cl_assert_equal_i(10, item->value); + cl_assert(git_sortedcache_lookup(sc, "cde") == NULL); + + cl_assert((item = git_sortedcache_entry(sc, 0)) != NULL); + cl_assert_equal_s("aaa", item->path); + cl_assert_equal_i(500, item->value); + cl_assert((item = git_sortedcache_entry(sc, 2)) != NULL); + cl_assert_equal_s("final", item->path); + cl_assert_equal_i(10, item->value); + cl_assert((item = git_sortedcache_entry(sc, 3)) != NULL); + cl_assert_equal_s("zzz", item->path); + cl_assert_equal_i(200, item->value); + + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "aaa")); + cl_assert_equal_sz(0, pos); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "abc")); + cl_assert_equal_sz(1, pos); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "final")); + cl_assert_equal_sz(2, pos); + cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "zzz")); + cl_assert_equal_sz(3, pos); + cl_assert_equal_i( + GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "missing")); + cl_assert_equal_i( + GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "cde")); + + git_sortedcache_free(sc); + + cl_assert_equal_i(7, free_count); +} + diff --git a/tests/core/stat.c b/tests/core/stat.c new file mode 100644 index 000000000..2e4abfb79 --- /dev/null +++ b/tests/core/stat.c @@ -0,0 +1,97 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "path.h" +#include "posix.h" + +void test_core_stat__initialize(void) +{ + cl_git_pass(git_futils_mkdir("root/d1/d2", NULL, 0755, GIT_MKDIR_PATH)); + cl_git_mkfile("root/file", "whatever\n"); + cl_git_mkfile("root/d1/file", "whatever\n"); +} + +void test_core_stat__cleanup(void) +{ + git_futils_rmdir_r("root", NULL, GIT_RMDIR_REMOVE_FILES); +} + +#define cl_assert_error(val) \ + do { err = errno; cl_assert_equal_i((val), err); } while (0) + +void test_core_stat__0(void) +{ + struct stat st; + int err; + + cl_assert_equal_i(0, p_lstat("root", &st)); + cl_assert(S_ISDIR(st.st_mode)); + cl_assert_error(0); + + cl_assert_equal_i(0, p_lstat("root/", &st)); + cl_assert(S_ISDIR(st.st_mode)); + cl_assert_error(0); + + cl_assert_equal_i(0, p_lstat("root/file", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_error(0); + + cl_assert_equal_i(0, p_lstat("root/d1", &st)); + cl_assert(S_ISDIR(st.st_mode)); + cl_assert_error(0); + + cl_assert_equal_i(0, p_lstat("root/d1/", &st)); + cl_assert(S_ISDIR(st.st_mode)); + cl_assert_error(0); + + cl_assert_equal_i(0, p_lstat("root/d1/file", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_error(0); + + cl_assert(p_lstat("root/missing", &st) < 0); + cl_assert_error(ENOENT); + + cl_assert(p_lstat("root/missing/but/could/be/created", &st) < 0); + cl_assert_error(ENOENT); + + cl_assert(p_lstat_posixly("root/missing/but/could/be/created", &st) < 0); + cl_assert_error(ENOENT); + + cl_assert(p_lstat("root/d1/missing", &st) < 0); + cl_assert_error(ENOENT); + + cl_assert(p_lstat("root/d1/missing/deeper/path", &st) < 0); + cl_assert_error(ENOENT); + + cl_assert(p_lstat_posixly("root/d1/missing/deeper/path", &st) < 0); + cl_assert_error(ENOENT); + + cl_assert(p_lstat_posixly("root/d1/file/deeper/path", &st) < 0); + cl_assert_error(ENOTDIR); + + cl_assert(p_lstat("root/file/invalid", &st) < 0); +#ifdef GIT_WIN32 + cl_assert_error(ENOENT); +#else + cl_assert_error(ENOTDIR); +#endif + + cl_assert(p_lstat_posixly("root/file/invalid", &st) < 0); + cl_assert_error(ENOTDIR); + + cl_assert(p_lstat("root/file/invalid/deeper_path", &st) < 0); +#ifdef GIT_WIN32 + cl_assert_error(ENOENT); +#else + cl_assert_error(ENOTDIR); +#endif + + cl_assert(p_lstat_posixly("root/file/invalid/deeper_path", &st) < 0); + cl_assert_error(ENOTDIR); + + cl_assert(p_lstat_posixly("root/d1/file/extra", &st) < 0); + cl_assert_error(ENOTDIR); + + cl_assert(p_lstat_posixly("root/d1/file/further/invalid/items", &st) < 0); + cl_assert_error(ENOTDIR); +} + diff --git a/tests/core/string.c b/tests/core/string.c new file mode 100644 index 000000000..ec9575685 --- /dev/null +++ b/tests/core/string.c @@ -0,0 +1,41 @@ +#include "clar_libgit2.h" + +/* compare prefixes */ +void test_core_string__0(void) +{ + cl_assert(git__prefixcmp("", "") == 0); + cl_assert(git__prefixcmp("a", "") == 0); + cl_assert(git__prefixcmp("", "a") < 0); + cl_assert(git__prefixcmp("a", "b") < 0); + cl_assert(git__prefixcmp("b", "a") > 0); + cl_assert(git__prefixcmp("ab", "a") == 0); + cl_assert(git__prefixcmp("ab", "ac") < 0); + cl_assert(git__prefixcmp("ab", "aa") > 0); +} + +/* compare suffixes */ +void test_core_string__1(void) +{ + cl_assert(git__suffixcmp("", "") == 0); + cl_assert(git__suffixcmp("a", "") == 0); + cl_assert(git__suffixcmp("", "a") < 0); + cl_assert(git__suffixcmp("a", "b") < 0); + cl_assert(git__suffixcmp("b", "a") > 0); + cl_assert(git__suffixcmp("ba", "a") == 0); + cl_assert(git__suffixcmp("zaa", "ac") < 0); + cl_assert(git__suffixcmp("zaz", "ac") > 0); +} + +/* compare icase sorting with case equality */ +void test_core_string__2(void) +{ + cl_assert(git__strcasesort_cmp("", "") == 0); + cl_assert(git__strcasesort_cmp("foo", "foo") == 0); + cl_assert(git__strcasesort_cmp("foo", "bar") > 0); + cl_assert(git__strcasesort_cmp("bar", "foo") < 0); + cl_assert(git__strcasesort_cmp("foo", "FOO") > 0); + cl_assert(git__strcasesort_cmp("FOO", "foo") < 0); + cl_assert(git__strcasesort_cmp("foo", "BAR") > 0); + cl_assert(git__strcasesort_cmp("BAR", "foo") < 0); + cl_assert(git__strcasesort_cmp("fooBar", "foobar") < 0); +} diff --git a/tests/core/strmap.c b/tests/core/strmap.c new file mode 100644 index 000000000..f34a4f89f --- /dev/null +++ b/tests/core/strmap.c @@ -0,0 +1,102 @@ +#include "clar_libgit2.h" +#include "strmap.h" + +GIT__USE_STRMAP; + +void test_core_strmap__0(void) +{ + git_strmap *table = git_strmap_alloc(); + cl_assert(table != NULL); + cl_assert(git_strmap_num_entries(table) == 0); + git_strmap_free(table); +} + +static void insert_strings(git_strmap *table, int count) +{ + int i, j, over, err; + char *str; + + for (i = 0; i < count; ++i) { + str = malloc(10); + for (j = 0; j < 10; ++j) + str[j] = 'a' + (i % 26); + str[9] = '\0'; + + /* if > 26, then encode larger value in first letters */ + for (j = 0, over = i / 26; over > 0; j++, over = over / 26) + str[j] = 'A' + (over % 26); + + git_strmap_insert(table, str, str, err); + cl_assert(err >= 0); + } + + cl_assert((int)git_strmap_num_entries(table) == count); +} + +void test_core_strmap__1(void) +{ + int i; + char *str; + git_strmap *table = git_strmap_alloc(); + cl_assert(table != NULL); + + insert_strings(table, 20); + + cl_assert(git_strmap_exists(table, "aaaaaaaaa")); + cl_assert(git_strmap_exists(table, "ggggggggg")); + cl_assert(!git_strmap_exists(table, "aaaaaaaab")); + cl_assert(!git_strmap_exists(table, "abcdefghi")); + + i = 0; + git_strmap_foreach_value(table, str, { i++; free(str); }); + cl_assert(i == 20); + + git_strmap_free(table); +} + +void test_core_strmap__2(void) +{ + khiter_t pos; + int i; + char *str; + git_strmap *table = git_strmap_alloc(); + cl_assert(table != NULL); + + insert_strings(table, 20); + + cl_assert(git_strmap_exists(table, "aaaaaaaaa")); + cl_assert(git_strmap_exists(table, "ggggggggg")); + cl_assert(!git_strmap_exists(table, "aaaaaaaab")); + cl_assert(!git_strmap_exists(table, "abcdefghi")); + + cl_assert(git_strmap_exists(table, "bbbbbbbbb")); + pos = git_strmap_lookup_index(table, "bbbbbbbbb"); + cl_assert(git_strmap_valid_index(table, pos)); + cl_assert_equal_s(git_strmap_value_at(table, pos), "bbbbbbbbb"); + free(git_strmap_value_at(table, pos)); + git_strmap_delete_at(table, pos); + + cl_assert(!git_strmap_exists(table, "bbbbbbbbb")); + + i = 0; + git_strmap_foreach_value(table, str, { i++; free(str); }); + cl_assert(i == 19); + + git_strmap_free(table); +} + +void test_core_strmap__3(void) +{ + int i; + char *str; + git_strmap *table = git_strmap_alloc(); + cl_assert(table != NULL); + + insert_strings(table, 10000); + + i = 0; + git_strmap_foreach_value(table, str, { i++; free(str); }); + cl_assert(i == 10000); + + git_strmap_free(table); +} diff --git a/tests/core/strtol.c b/tests/core/strtol.c new file mode 100644 index 000000000..8765e042b --- /dev/null +++ b/tests/core/strtol.c @@ -0,0 +1,37 @@ +#include "clar_libgit2.h" + +void test_core_strtol__int32(void) +{ + int32_t i; + + cl_git_pass(git__strtol32(&i, "123", NULL, 10)); + cl_assert(i == 123); + cl_git_pass(git__strtol32(&i, " +123 ", NULL, 10)); + cl_assert(i == 123); + cl_git_pass(git__strtol32(&i, " +2147483647 ", NULL, 10)); + cl_assert(i == 2147483647); + cl_git_pass(git__strtol32(&i, " -2147483648 ", NULL, 10)); + cl_assert(i == -2147483648LL); + + cl_git_fail(git__strtol32(&i, " 2147483657 ", NULL, 10)); + cl_git_fail(git__strtol32(&i, " -2147483657 ", NULL, 10)); +} + +void test_core_strtol__int64(void) +{ + int64_t i; + + cl_git_pass(git__strtol64(&i, "123", NULL, 10)); + cl_assert(i == 123); + cl_git_pass(git__strtol64(&i, " +123 ", NULL, 10)); + cl_assert(i == 123); + cl_git_pass(git__strtol64(&i, " +2147483647 ", NULL, 10)); + cl_assert(i == 2147483647); + cl_git_pass(git__strtol64(&i, " -2147483648 ", NULL, 10)); + cl_assert(i == -2147483648LL); + cl_git_pass(git__strtol64(&i, " 2147483657 ", NULL, 10)); + cl_assert(i == 2147483657LL); + cl_git_pass(git__strtol64(&i, " -2147483657 ", NULL, 10)); + cl_assert(i == -2147483657LL); +} + diff --git a/tests/core/vector.c b/tests/core/vector.c new file mode 100644 index 000000000..db52c004f --- /dev/null +++ b/tests/core/vector.c @@ -0,0 +1,275 @@ +#include "clar_libgit2.h" +#include "vector.h" + +/* initial size of 1 would cause writing past array bounds */ +void test_core_vector__0(void) +{ + git_vector x; + int i; + git_vector_init(&x, 1, NULL); + for (i = 0; i < 10; ++i) { + git_vector_insert(&x, (void*) 0xabc); + } + git_vector_free(&x); +} + + +/* don't read past array bounds on remove() */ +void test_core_vector__1(void) +{ + git_vector x; + // make initial capacity exact for our insertions. + git_vector_init(&x, 3, NULL); + git_vector_insert(&x, (void*) 0xabc); + git_vector_insert(&x, (void*) 0xdef); + git_vector_insert(&x, (void*) 0x123); + + git_vector_remove(&x, 0); // used to read past array bounds. + git_vector_free(&x); +} + + +static int test_cmp(const void *a, const void *b) +{ + return *(const int *)a - *(const int *)b; +} + +/* remove duplicates */ +void test_core_vector__2(void) +{ + git_vector x; + int *ptrs[2]; + + ptrs[0] = git__malloc(sizeof(int)); + ptrs[1] = git__malloc(sizeof(int)); + + *ptrs[0] = 2; + *ptrs[1] = 1; + + cl_git_pass(git_vector_init(&x, 5, test_cmp)); + cl_git_pass(git_vector_insert(&x, ptrs[0])); + cl_git_pass(git_vector_insert(&x, ptrs[1])); + cl_git_pass(git_vector_insert(&x, ptrs[1])); + cl_git_pass(git_vector_insert(&x, ptrs[0])); + cl_git_pass(git_vector_insert(&x, ptrs[1])); + cl_assert(x.length == 5); + + git_vector_uniq(&x, NULL); + cl_assert(x.length == 2); + + git_vector_free(&x); + + git__free(ptrs[0]); + git__free(ptrs[1]); +} + + +static int compare_them(const void *a, const void *b) +{ + return (int)((long)a - (long)b); +} + +/* insert_sorted */ +void test_core_vector__3(void) +{ + git_vector x; + long i; + git_vector_init(&x, 1, &compare_them); + + for (i = 0; i < 10; i += 2) { + git_vector_insert_sorted(&x, (void*)(i + 1), NULL); + } + + for (i = 9; i > 0; i -= 2) { + git_vector_insert_sorted(&x, (void*)(i + 1), NULL); + } + + cl_assert(x.length == 10); + for (i = 0; i < 10; ++i) { + cl_assert(git_vector_get(&x, i) == (void*)(i + 1)); + } + + git_vector_free(&x); +} + +/* insert_sorted with duplicates */ +void test_core_vector__4(void) +{ + git_vector x; + long i; + git_vector_init(&x, 1, &compare_them); + + for (i = 0; i < 10; i += 2) { + git_vector_insert_sorted(&x, (void*)(i + 1), NULL); + } + + for (i = 9; i > 0; i -= 2) { + git_vector_insert_sorted(&x, (void*)(i + 1), NULL); + } + + for (i = 0; i < 10; i += 2) { + git_vector_insert_sorted(&x, (void*)(i + 1), NULL); + } + + for (i = 9; i > 0; i -= 2) { + git_vector_insert_sorted(&x, (void*)(i + 1), NULL); + } + + cl_assert(x.length == 20); + for (i = 0; i < 20; ++i) { + cl_assert(git_vector_get(&x, i) == (void*)(i / 2 + 1)); + } + + git_vector_free(&x); +} + +typedef struct { + int content; + int count; +} my_struct; + +static int _struct_count = 0; + +static int compare_structs(const void *a, const void *b) +{ + return ((const my_struct *)a)->content - + ((const my_struct *)b)->content; +} + +static int merge_structs(void **old_raw, void *new) +{ + my_struct *old = *(my_struct **)old_raw; + cl_assert(((my_struct *)old)->content == ((my_struct *)new)->content); + ((my_struct *)old)->count += 1; + git__free(new); + _struct_count--; + return GIT_EEXISTS; +} + +static my_struct *alloc_struct(int value) +{ + my_struct *st = git__malloc(sizeof(my_struct)); + st->content = value; + st->count = 0; + _struct_count++; + return st; +} + +/* insert_sorted with duplicates and special handling */ +void test_core_vector__5(void) +{ + git_vector x; + int i; + + git_vector_init(&x, 1, &compare_structs); + + for (i = 0; i < 10; i += 2) + git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs); + + for (i = 9; i > 0; i -= 2) + git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs); + + cl_assert(x.length == 10); + cl_assert(_struct_count == 10); + + for (i = 0; i < 10; i += 2) + git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs); + + for (i = 9; i > 0; i -= 2) + git_vector_insert_sorted(&x, alloc_struct(i), &merge_structs); + + cl_assert(x.length == 10); + cl_assert(_struct_count == 10); + + for (i = 0; i < 10; ++i) { + cl_assert(((my_struct *)git_vector_get(&x, i))->content == i); + git__free(git_vector_get(&x, i)); + _struct_count--; + } + + git_vector_free(&x); +} + +static int remove_ones(const git_vector *v, size_t idx) +{ + return (git_vector_get(v, idx) == (void *)0x001); +} + +/* Test removal based on callback */ +void test_core_vector__remove_matching(void) +{ + git_vector x; + size_t i; + void *compare; + + git_vector_init(&x, 1, NULL); + git_vector_insert(&x, (void*) 0x001); + + cl_assert(x.length == 1); + git_vector_remove_matching(&x, remove_ones); + cl_assert(x.length == 0); + + git_vector_insert(&x, (void*) 0x001); + git_vector_insert(&x, (void*) 0x001); + git_vector_insert(&x, (void*) 0x001); + + cl_assert(x.length == 3); + git_vector_remove_matching(&x, remove_ones); + cl_assert(x.length == 0); + + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x001); + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x001); + + cl_assert(x.length == 4); + git_vector_remove_matching(&x, remove_ones); + cl_assert(x.length == 2); + + git_vector_foreach(&x, i, compare) { + cl_assert(compare != (void *)0x001); + } + + git_vector_clear(&x); + + git_vector_insert(&x, (void*) 0x001); + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x001); + + cl_assert(x.length == 4); + git_vector_remove_matching(&x, remove_ones); + cl_assert(x.length == 2); + + git_vector_foreach(&x, i, compare) { + cl_assert(compare != (void *)0x001); + } + + git_vector_clear(&x); + + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x001); + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x001); + + cl_assert(x.length == 4); + git_vector_remove_matching(&x, remove_ones); + cl_assert(x.length == 2); + + git_vector_foreach(&x, i, compare) { + cl_assert(compare != (void *)0x001); + } + + git_vector_clear(&x); + + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x003); + git_vector_insert(&x, (void*) 0x002); + git_vector_insert(&x, (void*) 0x003); + + cl_assert(x.length == 4); + git_vector_remove_matching(&x, remove_ones); + cl_assert(x.length == 4); + + git_vector_free(&x); +} diff --git a/tests/date/date.c b/tests/date/date.c new file mode 100644 index 000000000..88881d1e1 --- /dev/null +++ b/tests/date/date.c @@ -0,0 +1,15 @@ +#include "clar_libgit2.h" + +#include "util.h" + +void test_date_date__overflow(void) +{ +#ifdef __LP64__ + git_time_t d2038, d2039; + + /* This is expected to fail on a 32-bit machine. */ + cl_git_pass(git__date_parse(&d2038, "2038-1-1")); + cl_git_pass(git__date_parse(&d2039, "2039-1-1")); + cl_assert(d2038 < d2039); +#endif +} diff --git a/tests/diff/blob.c b/tests/diff/blob.c new file mode 100644 index 000000000..93f20711c --- /dev/null +++ b/tests/diff/blob.c @@ -0,0 +1,1067 @@ +#include "clar_libgit2.h" +#include "diff_helpers.h" + +static git_repository *g_repo = NULL; +static diff_expects expected; +static git_diff_options opts; +static git_blob *d, *alien; + +static void quick_diff_blob_to_str( + const git_blob *blob, const char *blob_path, + const char *str, size_t len, const char *str_path) +{ + memset(&expected, 0, sizeof(expected)); + + if (str && !len) + len = strlen(str); + + cl_git_pass(git_diff_blob_to_buffer( + blob, blob_path, str, len, str_path, + &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); +} + +void test_diff_blob__initialize(void) +{ + git_oid oid; + + g_repo = cl_git_sandbox_init("attr"); + + cl_git_pass(git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION)); + opts.context_lines = 1; + + memset(&expected, 0, sizeof(expected)); + + /* tests/resources/attr/root_test4.txt */ + cl_git_pass(git_oid_fromstrn(&oid, "a0f7217a", 8)); + cl_git_pass(git_blob_lookup_prefix(&d, g_repo, &oid, 4)); + + /* alien.png */ + cl_git_pass(git_oid_fromstrn(&oid, "edf3dcee", 8)); + cl_git_pass(git_blob_lookup_prefix(&alien, g_repo, &oid, 4)); +} + +void test_diff_blob__cleanup(void) +{ + git_blob_free(d); + d = NULL; + + git_blob_free(alien); + alien = NULL; + + cl_git_sandbox_cleanup(); +} + +void test_diff_blob__can_compare_text_blobs(void) +{ + git_blob *a, *b, *c; + git_oid a_oid, b_oid, c_oid; + + /* tests/resources/attr/root_test1 */ + cl_git_pass(git_oid_fromstrn(&a_oid, "45141a79", 8)); + cl_git_pass(git_blob_lookup_prefix(&a, g_repo, &a_oid, 4)); + + /* tests/resources/attr/root_test2 */ + cl_git_pass(git_oid_fromstrn(&b_oid, "4d713dc4", 8)); + cl_git_pass(git_blob_lookup_prefix(&b, g_repo, &b_oid, 4)); + + /* tests/resources/attr/root_test3 */ + cl_git_pass(git_oid_fromstrn(&c_oid, "c96bbb2c2557a832", 16)); + cl_git_pass(git_blob_lookup_prefix(&c, g_repo, &c_oid, 8)); + + /* Doing the equivalent of a `git diff -U1` on these files */ + + /* diff on tests/resources/attr/root_test1 */ + cl_git_pass(git_diff_blobs( + a, NULL, b, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expected.files_binary); + + cl_assert_equal_i(1, expected.hunks); + cl_assert_equal_i(6, expected.lines); + cl_assert_equal_i(1, expected.line_ctxt); + cl_assert_equal_i(5, expected.line_adds); + cl_assert_equal_i(0, expected.line_dels); + + /* diff on tests/resources/attr/root_test2 */ + memset(&expected, 0, sizeof(expected)); + cl_git_pass(git_diff_blobs( + b, NULL, c, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expected.files_binary); + + cl_assert_equal_i(1, expected.hunks); + cl_assert_equal_i(15, expected.lines); + cl_assert_equal_i(3, expected.line_ctxt); + cl_assert_equal_i(9, expected.line_adds); + cl_assert_equal_i(3, expected.line_dels); + + /* diff on tests/resources/attr/root_test3 */ + memset(&expected, 0, sizeof(expected)); + cl_git_pass(git_diff_blobs( + a, NULL, c, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expected.files_binary); + + cl_assert_equal_i(1, expected.hunks); + cl_assert_equal_i(13, expected.lines); + cl_assert_equal_i(0, expected.line_ctxt); + cl_assert_equal_i(12, expected.line_adds); + cl_assert_equal_i(1, expected.line_dels); + + memset(&expected, 0, sizeof(expected)); + cl_git_pass(git_diff_blobs( + c, NULL, d, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expected.files_binary); + + cl_assert_equal_i(2, expected.hunks); + cl_assert_equal_i(14, expected.lines); + cl_assert_equal_i(4, expected.line_ctxt); + cl_assert_equal_i(6, expected.line_adds); + cl_assert_equal_i(4, expected.line_dels); + + git_blob_free(a); + git_blob_free(b); + git_blob_free(c); +} + +void test_diff_blob__can_compare_text_blobs_with_patch(void) +{ + git_blob *a, *b, *c; + git_oid a_oid, b_oid, c_oid; + git_patch *p; + const git_diff_delta *delta; + size_t tc, ta, td; + + /* tests/resources/attr/root_test1 */ + cl_git_pass(git_oid_fromstrn(&a_oid, "45141a79", 8)); + cl_git_pass(git_blob_lookup_prefix(&a, g_repo, &a_oid, 4)); + + /* tests/resources/attr/root_test2 */ + cl_git_pass(git_oid_fromstrn(&b_oid, "4d713dc4", 8)); + cl_git_pass(git_blob_lookup_prefix(&b, g_repo, &b_oid, 4)); + + /* tests/resources/attr/root_test3 */ + cl_git_pass(git_oid_fromstrn(&c_oid, "c96bbb2c2557a832", 16)); + cl_git_pass(git_blob_lookup_prefix(&c, g_repo, &c_oid, 8)); + + /* Doing the equivalent of a `git diff -U1` on these files */ + + /* diff on tests/resources/attr/root_test1 */ + cl_git_pass(git_patch_from_blobs(&p, a, NULL, b, NULL, &opts)); + + cl_assert(p != NULL); + + delta = git_patch_get_delta(p); + cl_assert(delta != NULL); + cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); + cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.oid)); + cl_assert_equal_sz(git_blob_rawsize(a), delta->old_file.size); + cl_assert(git_oid_equal(git_blob_id(b), &delta->new_file.oid)); + cl_assert_equal_sz(git_blob_rawsize(b), delta->new_file.size); + + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(6, git_patch_num_lines_in_hunk(p, 0)); + + cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); + cl_assert_equal_i(1, (int)tc); + cl_assert_equal_i(5, (int)ta); + cl_assert_equal_i(0, (int)td); + + git_patch_free(p); + + /* diff on tests/resources/attr/root_test2 */ + cl_git_pass(git_patch_from_blobs(&p, b, NULL, c, NULL, &opts)); + + cl_assert(p != NULL); + + delta = git_patch_get_delta(p); + cl_assert(delta != NULL); + cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); + cl_assert(git_oid_equal(git_blob_id(b), &delta->old_file.oid)); + cl_assert_equal_sz(git_blob_rawsize(b), delta->old_file.size); + cl_assert(git_oid_equal(git_blob_id(c), &delta->new_file.oid)); + cl_assert_equal_sz(git_blob_rawsize(c), delta->new_file.size); + + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(15, git_patch_num_lines_in_hunk(p, 0)); + + cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); + cl_assert_equal_i(3, (int)tc); + cl_assert_equal_i(9, (int)ta); + cl_assert_equal_i(3, (int)td); + + git_patch_free(p); + + /* diff on tests/resources/attr/root_test3 */ + cl_git_pass(git_patch_from_blobs(&p, a, NULL, c, NULL, &opts)); + + cl_assert(p != NULL); + + delta = git_patch_get_delta(p); + cl_assert(delta != NULL); + cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); + cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.oid)); + cl_assert_equal_sz(git_blob_rawsize(a), delta->old_file.size); + cl_assert(git_oid_equal(git_blob_id(c), &delta->new_file.oid)); + cl_assert_equal_sz(git_blob_rawsize(c), delta->new_file.size); + + cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); + cl_assert_equal_i(0, (int)tc); + cl_assert_equal_i(12, (int)ta); + cl_assert_equal_i(1, (int)td); + + git_patch_free(p); + + /* one more */ + cl_git_pass(git_patch_from_blobs(&p, c, NULL, d, NULL, &opts)); + + cl_assert(p != NULL); + + delta = git_patch_get_delta(p); + cl_assert(delta != NULL); + cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); + cl_assert(git_oid_equal(git_blob_id(c), &delta->old_file.oid)); + cl_assert_equal_sz(git_blob_rawsize(c), delta->old_file.size); + cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.oid)); + cl_assert_equal_sz(git_blob_rawsize(d), delta->new_file.size); + + cl_assert_equal_i(2, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(5, git_patch_num_lines_in_hunk(p, 0)); + cl_assert_equal_i(9, git_patch_num_lines_in_hunk(p, 1)); + + cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); + cl_assert_equal_i(4, (int)tc); + cl_assert_equal_i(6, (int)ta); + cl_assert_equal_i(4, (int)td); + + git_patch_free(p); + + git_blob_free(a); + git_blob_free(b); + git_blob_free(c); +} + +void test_diff_blob__can_compare_against_null_blobs(void) +{ + git_blob *e = NULL; + + cl_git_pass(git_diff_blobs( + d, NULL, e, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(0, expected.files_binary); + + cl_assert_equal_i(1, expected.hunks); + cl_assert_equal_i(14, expected.hunk_old_lines); + cl_assert_equal_i(14, expected.lines); + cl_assert_equal_i(14, expected.line_dels); + + opts.flags |= GIT_DIFF_REVERSE; + memset(&expected, 0, sizeof(expected)); + + cl_git_pass(git_diff_blobs( + d, NULL, e, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, expected.files_binary); + + cl_assert_equal_i(1, expected.hunks); + cl_assert_equal_i(14, expected.hunk_new_lines); + cl_assert_equal_i(14, expected.lines); + cl_assert_equal_i(14, expected.line_adds); + + opts.flags ^= GIT_DIFF_REVERSE; + memset(&expected, 0, sizeof(expected)); + + cl_git_pass(git_diff_blobs( + alien, NULL, NULL, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.files_binary); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(0, expected.hunks); + cl_assert_equal_i(0, expected.lines); + + memset(&expected, 0, sizeof(expected)); + + cl_git_pass(git_diff_blobs( + NULL, NULL, alien, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.files_binary); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, expected.hunks); + cl_assert_equal_i(0, expected.lines); +} + +void test_diff_blob__can_compare_against_null_blobs_with_patch(void) +{ + git_blob *e = NULL; + git_patch *p; + const git_diff_delta *delta; + const git_diff_line *line; + int l, max_l; + + cl_git_pass(git_patch_from_blobs(&p, d, NULL, e, NULL, &opts)); + + cl_assert(p != NULL); + + delta = git_patch_get_delta(p); + cl_assert(delta != NULL); + cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); + cl_assert(git_oid_equal(git_blob_id(d), &delta->old_file.oid)); + cl_assert_equal_sz(git_blob_rawsize(d), delta->old_file.size); + cl_assert(git_oid_iszero(&delta->new_file.oid)); + cl_assert_equal_sz(0, delta->new_file.size); + + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p, 0)); + + max_l = git_patch_num_lines_in_hunk(p, 0); + for (l = 0; l < max_l; ++l) { + cl_git_pass(git_patch_get_line_in_hunk(&line, p, 0, l)); + cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); + } + + git_patch_free(p); + + opts.flags |= GIT_DIFF_REVERSE; + + cl_git_pass(git_patch_from_blobs(&p, d, NULL, e, NULL, &opts)); + + cl_assert(p != NULL); + + delta = git_patch_get_delta(p); + cl_assert(delta != NULL); + cl_assert_equal_i(GIT_DELTA_ADDED, delta->status); + cl_assert(git_oid_iszero(&delta->old_file.oid)); + cl_assert_equal_sz(0, delta->old_file.size); + cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.oid)); + cl_assert_equal_sz(git_blob_rawsize(d), delta->new_file.size); + + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p, 0)); + + max_l = git_patch_num_lines_in_hunk(p, 0); + for (l = 0; l < max_l; ++l) { + cl_git_pass(git_patch_get_line_in_hunk(&line, p, 0, l)); + cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); + } + + git_patch_free(p); + + opts.flags ^= GIT_DIFF_REVERSE; + + cl_git_pass(git_patch_from_blobs(&p, alien, NULL, NULL, NULL, &opts)); + + cl_assert(p != NULL); + + delta = git_patch_get_delta(p); + cl_assert(delta != NULL); + cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); + cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); + + cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); + + git_patch_free(p); + + cl_git_pass(git_patch_from_blobs(&p, NULL, NULL, alien, NULL, &opts)); + + cl_assert(p != NULL); + + delta = git_patch_get_delta(p); + cl_assert(delta != NULL); + cl_assert_equal_i(GIT_DELTA_ADDED, delta->status); + cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); + + cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); + + git_patch_free(p); +} + +static void assert_identical_blobs_comparison(diff_expects *expected) +{ + cl_assert_equal_i(1, expected->files); + cl_assert_equal_i(1, expected->file_status[GIT_DELTA_UNMODIFIED]); + cl_assert_equal_i(0, expected->hunks); + cl_assert_equal_i(0, expected->lines); +} + +void test_diff_blob__can_compare_identical_blobs(void) +{ + opts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; + + cl_git_pass(git_diff_blobs( + d, NULL, d, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + assert_identical_blobs_comparison(&expected); + cl_assert_equal_i(0, expected.files_binary); + + memset(&expected, 0, sizeof(expected)); + cl_git_pass(git_diff_blobs( + NULL, NULL, NULL, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + assert_identical_blobs_comparison(&expected); + cl_assert_equal_i(0, expected.files_binary); + + memset(&expected, 0, sizeof(expected)); + cl_git_pass(git_diff_blobs( + alien, NULL, alien, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + assert_identical_blobs_comparison(&expected); + cl_assert(expected.files_binary > 0); +} + +void test_diff_blob__can_compare_identical_blobs_with_patch(void) +{ + git_patch *p; + const git_diff_delta *delta; + + cl_git_pass(git_patch_from_blobs(&p, d, NULL, d, NULL, &opts)); + cl_assert(p != NULL); + + delta = git_patch_get_delta(p); + cl_assert(delta != NULL); + cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status); + cl_assert_equal_sz(delta->old_file.size, git_blob_rawsize(d)); + cl_assert(git_oid_equal(git_blob_id(d), &delta->old_file.oid)); + cl_assert_equal_sz(delta->new_file.size, git_blob_rawsize(d)); + cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.oid)); + + cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); + git_patch_free(p); + + cl_git_pass(git_patch_from_blobs(&p, NULL, NULL, NULL, NULL, &opts)); + cl_assert(p != NULL); + + delta = git_patch_get_delta(p); + cl_assert(delta != NULL); + cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status); + cl_assert_equal_sz(0, delta->old_file.size); + cl_assert(git_oid_iszero(&delta->old_file.oid)); + cl_assert_equal_sz(0, delta->new_file.size); + cl_assert(git_oid_iszero(&delta->new_file.oid)); + + cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); + git_patch_free(p); + + cl_git_pass(git_patch_from_blobs(&p, alien, NULL, alien, NULL, &opts)); + cl_assert(p != NULL); + cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_patch_get_delta(p)->status); + cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); + git_patch_free(p); +} + +static void assert_binary_blobs_comparison(diff_expects *expected) +{ + cl_assert(expected->files_binary > 0); + + cl_assert_equal_i(1, expected->files); + cl_assert_equal_i(1, expected->file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expected->hunks); + cl_assert_equal_i(0, expected->lines); +} + +void test_diff_blob__can_compare_two_binary_blobs(void) +{ + git_blob *heart; + git_oid h_oid; + + /* heart.png */ + cl_git_pass(git_oid_fromstrn(&h_oid, "de863bff", 8)); + cl_git_pass(git_blob_lookup_prefix(&heart, g_repo, &h_oid, 4)); + + cl_git_pass(git_diff_blobs( + alien, NULL, heart, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + assert_binary_blobs_comparison(&expected); + + memset(&expected, 0, sizeof(expected)); + + cl_git_pass(git_diff_blobs( + heart, NULL, alien, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + assert_binary_blobs_comparison(&expected); + + git_blob_free(heart); +} + +void test_diff_blob__can_compare_a_binary_blob_and_a_text_blob(void) +{ + cl_git_pass(git_diff_blobs( + alien, NULL, d, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + assert_binary_blobs_comparison(&expected); + + memset(&expected, 0, sizeof(expected)); + + cl_git_pass(git_diff_blobs( + d, NULL, alien, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + assert_binary_blobs_comparison(&expected); +} + +/* + * $ git diff fe773770 a0f7217 + * diff --git a/fe773770 b/a0f7217 + * index fe77377..a0f7217 100644 + * --- a/fe773770 + * +++ b/a0f7217 + * @@ -1,6 +1,6 @@ + * Here is some stuff at the start + * + * -This should go in one hunk + * +This should go in one hunk (first) + * + * Some additional lines + * + * @@ -8,7 +8,7 @@ Down here below the other lines + * + * With even more at the end + * + * -Followed by a second hunk of stuff + * +Followed by a second hunk of stuff (second) + * + * That happens down here + */ +void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void) +{ + git_blob *old_d; + git_oid old_d_oid; + + opts.context_lines = 3; + + /* tests/resources/attr/root_test1 from commit f5b0af1 */ + cl_git_pass(git_oid_fromstrn(&old_d_oid, "fe773770", 8)); + cl_git_pass(git_blob_lookup_prefix(&old_d, g_repo, &old_d_oid, 4)); + + /* Test with default inter-hunk-context (not set) => default is 0 */ + cl_git_pass(git_diff_blobs( + old_d, NULL, d, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + cl_assert_equal_i(2, expected.hunks); + + /* Test with inter-hunk-context explicitly set to 0 */ + opts.interhunk_lines = 0; + memset(&expected, 0, sizeof(expected)); + cl_git_pass(git_diff_blobs( + old_d, NULL, d, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + cl_assert_equal_i(2, expected.hunks); + + /* Test with inter-hunk-context explicitly set to 1 */ + opts.interhunk_lines = 1; + memset(&expected, 0, sizeof(expected)); + cl_git_pass(git_diff_blobs( + old_d, NULL, d, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + + cl_assert_equal_i(1, expected.hunks); + + git_blob_free(old_d); +} + +void test_diff_blob__checks_options_version_too_low(void) +{ + const git_error *err; + + opts.version = 0; + cl_git_fail(git_diff_blobs( + d, NULL, alien, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); +} + +void test_diff_blob__checks_options_version_too_high(void) +{ + const git_error *err; + + opts.version = 1024; + cl_git_fail(git_diff_blobs( + d, NULL, alien, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); +} + +void test_diff_blob__can_correctly_detect_a_binary_blob_as_binary(void) +{ + /* alien.png */ + cl_assert_equal_i(true, git_blob_is_binary(alien)); +} + +void test_diff_blob__can_correctly_detect_a_textual_blob_as_non_binary(void) +{ + /* tests/resources/attr/root_test4.txt */ + cl_assert_equal_i(false, git_blob_is_binary(d)); +} + +/* + * git_diff_blob_to_buffer tests + */ + +static void assert_changed_single_one_line_file( + diff_expects *expected, git_delta_t mod) +{ + cl_assert_equal_i(1, expected->files); + cl_assert_equal_i(1, expected->file_status[mod]); + cl_assert_equal_i(1, expected->hunks); + cl_assert_equal_i(1, expected->lines); + + if (mod == GIT_DELTA_ADDED) + cl_assert_equal_i(1, expected->line_adds); + else if (mod == GIT_DELTA_DELETED) + cl_assert_equal_i(1, expected->line_dels); +} + +void test_diff_blob__can_compare_blob_to_buffer(void) +{ + git_blob *a; + git_oid a_oid; + const char *a_content = "Hello from the root\n"; + const char *b_content = "Hello from the root\n\nSome additional lines\n\nDown here below\n\n"; + + /* tests/resources/attr/root_test1 */ + cl_git_pass(git_oid_fromstrn(&a_oid, "45141a79", 8)); + cl_git_pass(git_blob_lookup_prefix(&a, g_repo, &a_oid, 4)); + + /* diff from blob a to content of b */ + quick_diff_blob_to_str(a, NULL, b_content, 0, NULL); + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expected.files_binary); + cl_assert_equal_i(1, expected.hunks); + cl_assert_equal_i(6, expected.lines); + cl_assert_equal_i(1, expected.line_ctxt); + cl_assert_equal_i(5, expected.line_adds); + cl_assert_equal_i(0, expected.line_dels); + + /* diff from blob a to content of a */ + opts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; + quick_diff_blob_to_str(a, NULL, a_content, 0, NULL); + assert_identical_blobs_comparison(&expected); + + /* diff from NULL blob to content of a */ + memset(&expected, 0, sizeof(expected)); + quick_diff_blob_to_str(NULL, NULL, a_content, 0, NULL); + assert_changed_single_one_line_file(&expected, GIT_DELTA_ADDED); + + /* diff from blob a to NULL buffer */ + memset(&expected, 0, sizeof(expected)); + quick_diff_blob_to_str(a, NULL, NULL, 0, NULL); + assert_changed_single_one_line_file(&expected, GIT_DELTA_DELETED); + + /* diff with reverse */ + opts.flags ^= GIT_DIFF_REVERSE; + + memset(&expected, 0, sizeof(expected)); + quick_diff_blob_to_str(a, NULL, NULL, 0, NULL); + assert_changed_single_one_line_file(&expected, GIT_DELTA_ADDED); + + git_blob_free(a); +} + +void test_diff_blob__can_compare_blob_to_buffer_with_patch(void) +{ + git_patch *p; + git_blob *a; + git_oid a_oid; + const char *a_content = "Hello from the root\n"; + const char *b_content = "Hello from the root\n\nSome additional lines\n\nDown here below\n\n"; + size_t tc, ta, td; + + /* tests/resources/attr/root_test1 */ + cl_git_pass(git_oid_fromstrn(&a_oid, "45141a79", 8)); + cl_git_pass(git_blob_lookup_prefix(&a, g_repo, &a_oid, 4)); + + /* diff from blob a to content of b */ + cl_git_pass(git_patch_from_blob_and_buffer( + &p, a, NULL, b_content, strlen(b_content), NULL, &opts)); + + cl_assert(p != NULL); + cl_assert_equal_i(GIT_DELTA_MODIFIED, git_patch_get_delta(p)->status); + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(6, git_patch_num_lines_in_hunk(p, 0)); + + cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); + cl_assert_equal_i(1, (int)tc); + cl_assert_equal_i(5, (int)ta); + cl_assert_equal_i(0, (int)td); + + git_patch_free(p); + + /* diff from blob a to content of a */ + opts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; + cl_git_pass(git_patch_from_blob_and_buffer( + &p, a, NULL, a_content, strlen(a_content), NULL, &opts)); + cl_assert(p != NULL); + cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_patch_get_delta(p)->status); + cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); + git_patch_free(p); + + /* diff from NULL blob to content of a */ + cl_git_pass(git_patch_from_blob_and_buffer( + &p, NULL, NULL, a_content, strlen(a_content), NULL, &opts)); + cl_assert(p != NULL); + cl_assert_equal_i(GIT_DELTA_ADDED, git_patch_get_delta(p)->status); + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); + git_patch_free(p); + + /* diff from blob a to NULL buffer */ + cl_git_pass(git_patch_from_blob_and_buffer( + &p, a, NULL, NULL, 0, NULL, &opts)); + cl_assert(p != NULL); + cl_assert_equal_i(GIT_DELTA_DELETED, git_patch_get_delta(p)->status); + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); + git_patch_free(p); + + /* diff with reverse */ + opts.flags ^= GIT_DIFF_REVERSE; + + cl_git_pass(git_patch_from_blob_and_buffer( + &p, a, NULL, NULL, 0, NULL, &opts)); + cl_assert(p != NULL); + cl_assert_equal_i(GIT_DELTA_ADDED, git_patch_get_delta(p)->status); + cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); + cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); + git_patch_free(p); + + git_blob_free(a); +} + +static void assert_one_modified_with_lines(diff_expects *expected, int lines) +{ + cl_assert_equal_i(1, expected->files); + cl_assert_equal_i(1, expected->file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expected->files_binary); + cl_assert_equal_i(lines, expected->lines); +} + +void test_diff_blob__binary_data_comparisons(void) +{ + git_blob *bin, *nonbin; + git_oid oid; + const char *nonbin_content = "Hello from the root\n"; + size_t nonbin_len = 20; + const char *bin_content = "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n"; + size_t bin_len = 33; + + opts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; + + cl_git_pass(git_oid_fromstrn(&oid, "45141a79", 8)); + cl_git_pass(git_blob_lookup_prefix(&nonbin, g_repo, &oid, 4)); + + cl_git_pass(git_oid_fromstrn(&oid, "b435cd56", 8)); + cl_git_pass(git_blob_lookup_prefix(&bin, g_repo, &oid, 4)); + + /* non-binary to reference content */ + + quick_diff_blob_to_str(nonbin, NULL, nonbin_content, nonbin_len, NULL); + assert_identical_blobs_comparison(&expected); + cl_assert_equal_i(0, expected.files_binary); + + /* binary to reference content */ + + quick_diff_blob_to_str(bin, NULL, bin_content, bin_len, NULL); + assert_identical_blobs_comparison(&expected); + + cl_assert_equal_i(1, expected.files_binary); + + /* non-binary to binary content */ + + quick_diff_blob_to_str(nonbin, NULL, bin_content, bin_len, NULL); + assert_binary_blobs_comparison(&expected); + + /* binary to non-binary content */ + + quick_diff_blob_to_str(bin, NULL, nonbin_content, nonbin_len, NULL); + assert_binary_blobs_comparison(&expected); + + /* non-binary to binary blob */ + + memset(&expected, 0, sizeof(expected)); + cl_git_pass(git_diff_blobs( + bin, NULL, nonbin, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + assert_binary_blobs_comparison(&expected); + + /* + * repeat with FORCE_TEXT + */ + + opts.flags |= GIT_DIFF_FORCE_TEXT; + + quick_diff_blob_to_str(bin, NULL, bin_content, bin_len, NULL); + assert_identical_blobs_comparison(&expected); + + quick_diff_blob_to_str(nonbin, NULL, bin_content, bin_len, NULL); + assert_one_modified_with_lines(&expected, 4); + + quick_diff_blob_to_str(bin, NULL, nonbin_content, nonbin_len, NULL); + assert_one_modified_with_lines(&expected, 4); + + memset(&expected, 0, sizeof(expected)); + cl_git_pass(git_diff_blobs( + bin, NULL, nonbin, NULL, &opts, + diff_file_cb, diff_hunk_cb, diff_line_cb, &expected)); + assert_one_modified_with_lines(&expected, 4); + + /* cleanup */ + git_blob_free(bin); + git_blob_free(nonbin); +} + +void test_diff_blob__using_path_and_attributes(void) +{ + git_config *cfg; + git_blob *bin, *nonbin; + git_oid oid; + const char *nonbin_content = "Hello from the root\n"; + const char *bin_content = + "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n"; + size_t bin_len = 33; + const char *changed; + git_patch *p; + char *pout; + + /* set up custom diff drivers and 'diff' attribute mappings for them */ + + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_bool(cfg, "diff.iam_binary.binary", 1)); + cl_git_pass(git_config_set_bool(cfg, "diff.iam_text.binary", 0)); + cl_git_pass(git_config_set_string( + cfg, "diff.iam_alphactx.xfuncname", "^[A-Za-z]")); + cl_git_pass(git_config_set_bool(cfg, "diff.iam_textalpha.binary", 0)); + cl_git_pass(git_config_set_string( + cfg, "diff.iam_textalpha.xfuncname", "^[A-Za-z]")); + cl_git_pass(git_config_set_string( + cfg, "diff.iam_numctx.funcname", "^[0-9]")); + cl_git_pass(git_config_set_bool(cfg, "diff.iam_textnum.binary", 0)); + cl_git_pass(git_config_set_string( + cfg, "diff.iam_textnum.funcname", "^[0-9]")); + git_config_free(cfg); + + cl_git_append2file( + "attr/.gitattributes", + "\n\n# test_diff_blob__using_path_and_attributes extra\n\n" + "*.binary diff=iam_binary\n" + "*.textary diff=iam_text\n" + "*.alphary diff=iam_alphactx\n" + "*.textalphary diff=iam_textalpha\n" + "*.textnumary diff=iam_textnum\n" + "*.numary diff=iam_numctx\n\n"); + + opts.context_lines = 0; + opts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; + + cl_git_pass(git_oid_fromstrn(&oid, "45141a79", 8)); + cl_git_pass(git_blob_lookup_prefix(&nonbin, g_repo, &oid, 4)); + /* 20b: "Hello from the root\n" */ + + cl_git_pass(git_oid_fromstrn(&oid, "b435cd56", 8)); + cl_git_pass(git_blob_lookup_prefix(&bin, g_repo, &oid, 4)); + /* 33b: "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\n0123456789\n" */ + + /* non-binary to reference content */ + + quick_diff_blob_to_str(nonbin, NULL, nonbin_content, 0, NULL); + assert_identical_blobs_comparison(&expected); + cl_assert_equal_i(0, expected.files_binary); + + /* binary to reference content */ + + quick_diff_blob_to_str(bin, NULL, bin_content, bin_len, NULL); + assert_identical_blobs_comparison(&expected); + cl_assert_equal_i(1, expected.files_binary); + + /* add some text */ + + changed = "Hello from the root\nMore lines\nAnd more\nGo here\n"; + + quick_diff_blob_to_str(nonbin, NULL, changed, 0, NULL); + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expected.files_binary); + cl_assert_equal_i(1, expected.hunks); + cl_assert_equal_i(3, expected.lines); + cl_assert_equal_i(0, expected.line_ctxt); + cl_assert_equal_i(3, expected.line_adds); + cl_assert_equal_i(0, expected.line_dels); + + quick_diff_blob_to_str(nonbin, "foo/bar.binary", changed, 0, NULL); + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, expected.files_binary); + cl_assert_equal_i(0, expected.hunks); + cl_assert_equal_i(0, expected.lines); + cl_assert_equal_i(0, expected.line_ctxt); + cl_assert_equal_i(0, expected.line_adds); + cl_assert_equal_i(0, expected.line_dels); + + quick_diff_blob_to_str(nonbin, "foo/bar.textary", changed, 0, NULL); + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expected.files_binary); + cl_assert_equal_i(1, expected.hunks); + cl_assert_equal_i(3, expected.lines); + cl_assert_equal_i(0, expected.line_ctxt); + cl_assert_equal_i(3, expected.line_adds); + cl_assert_equal_i(0, expected.line_dels); + + quick_diff_blob_to_str(nonbin, "foo/bar.alphary", changed, 0, NULL); + cl_assert_equal_i(1, expected.files); + cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expected.files_binary); + cl_assert_equal_i(1, expected.hunks); + cl_assert_equal_i(3, expected.lines); + cl_assert_equal_i(0, expected.line_ctxt); + cl_assert_equal_i(3, expected.line_adds); + cl_assert_equal_i(0, expected.line_dels); + + cl_git_pass(git_patch_from_blob_and_buffer( + &p, nonbin, "zzz.normal", changed, strlen(changed), NULL, &opts)); + cl_git_pass(git_patch_to_str(&pout, p)); + cl_assert_equal_s( + "diff --git a/zzz.normal b/zzz.normal\n" + "index 45141a7..75b0dbb 100644\n" + "--- a/zzz.normal\n" + "+++ b/zzz.normal\n" + "@@ -1,0 +2,3 @@ Hello from the root\n" + "+More lines\n" + "+And more\n" + "+Go here\n", pout); + git__free(pout); + git_patch_free(p); + + cl_git_pass(git_patch_from_blob_and_buffer( + &p, nonbin, "zzz.binary", changed, strlen(changed), NULL, &opts)); + cl_git_pass(git_patch_to_str(&pout, p)); + cl_assert_equal_s( + "diff --git a/zzz.binary b/zzz.binary\n" + "index 45141a7..75b0dbb 100644\n" + "Binary files a/zzz.binary and b/zzz.binary differ\n", pout); + git__free(pout); + git_patch_free(p); + + cl_git_pass(git_patch_from_blob_and_buffer( + &p, nonbin, "zzz.alphary", changed, strlen(changed), NULL, &opts)); + cl_git_pass(git_patch_to_str(&pout, p)); + cl_assert_equal_s( + "diff --git a/zzz.alphary b/zzz.alphary\n" + "index 45141a7..75b0dbb 100644\n" + "--- a/zzz.alphary\n" + "+++ b/zzz.alphary\n" + "@@ -1,0 +2,3 @@ Hello from the root\n" + "+More lines\n" + "+And more\n" + "+Go here\n", pout); + git__free(pout); + git_patch_free(p); + + cl_git_pass(git_patch_from_blob_and_buffer( + &p, nonbin, "zzz.numary", changed, strlen(changed), NULL, &opts)); + cl_git_pass(git_patch_to_str(&pout, p)); + cl_assert_equal_s( + "diff --git a/zzz.numary b/zzz.numary\n" + "index 45141a7..75b0dbb 100644\n" + "--- a/zzz.numary\n" + "+++ b/zzz.numary\n" + "@@ -1,0 +2,3 @@\n" + "+More lines\n" + "+And more\n" + "+Go here\n", pout); + git__free(pout); + git_patch_free(p); + + /* "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n" + * 33 bytes + */ + + changed = "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\nreplace a line\n"; + + cl_git_pass(git_patch_from_blob_and_buffer( + &p, bin, "zzz.normal", changed, 37, NULL, &opts)); + cl_git_pass(git_patch_to_str(&pout, p)); + cl_assert_equal_s( + "diff --git a/zzz.normal b/zzz.normal\n" + "index b435cd5..1604519 100644\n" + "Binary files a/zzz.normal and b/zzz.normal differ\n", pout); + git__free(pout); + git_patch_free(p); + + cl_git_pass(git_patch_from_blob_and_buffer( + &p, bin, "zzz.textary", changed, 37, NULL, &opts)); + cl_git_pass(git_patch_to_str(&pout, p)); + cl_assert_equal_s( + "diff --git a/zzz.textary b/zzz.textary\n" + "index b435cd5..1604519 100644\n" + "--- a/zzz.textary\n" + "+++ b/zzz.textary\n" + "@@ -3 +3 @@\n" + "-0123456789\n" + "+replace a line\n", pout); + git__free(pout); + git_patch_free(p); + + cl_git_pass(git_patch_from_blob_and_buffer( + &p, bin, "zzz.textalphary", changed, 37, NULL, &opts)); + cl_git_pass(git_patch_to_str(&pout, p)); + cl_assert_equal_s( + "diff --git a/zzz.textalphary b/zzz.textalphary\n" + "index b435cd5..1604519 100644\n" + "--- a/zzz.textalphary\n" + "+++ b/zzz.textalphary\n" + "@@ -3 +3 @@\n" + "-0123456789\n" + "+replace a line\n", pout); + git__free(pout); + git_patch_free(p); + + cl_git_pass(git_patch_from_blob_and_buffer( + &p, bin, "zzz.textnumary", changed, 37, NULL, &opts)); + cl_git_pass(git_patch_to_str(&pout, p)); + cl_assert_equal_s( + "diff --git a/zzz.textnumary b/zzz.textnumary\n" + "index b435cd5..1604519 100644\n" + "--- a/zzz.textnumary\n" + "+++ b/zzz.textnumary\n" + "@@ -3 +3 @@ 0123456789\n" + "-0123456789\n" + "+replace a line\n", pout); + git__free(pout); + git_patch_free(p); + + git_blob_free(nonbin); + git_blob_free(bin); +} diff --git a/tests/diff/diff_helpers.c b/tests/diff/diff_helpers.c new file mode 100644 index 000000000..33bb561f6 --- /dev/null +++ b/tests/diff/diff_helpers.c @@ -0,0 +1,246 @@ +#include "clar_libgit2.h" +#include "diff_helpers.h" + +git_tree *resolve_commit_oid_to_tree( + git_repository *repo, + const char *partial_oid) +{ + size_t len = strlen(partial_oid); + git_oid oid; + git_object *obj = NULL; + git_tree *tree = NULL; + + if (git_oid_fromstrn(&oid, partial_oid, len) == 0) + git_object_lookup_prefix(&obj, repo, &oid, len, GIT_OBJ_ANY); + cl_assert(obj); + if (git_object_type(obj) == GIT_OBJ_TREE) + return (git_tree *)obj; + cl_assert(git_object_type(obj) == GIT_OBJ_COMMIT); + cl_git_pass(git_commit_tree(&tree, (git_commit *)obj)); + git_object_free(obj); + return tree; +} + +static char diff_pick_suffix(int mode) +{ + if (S_ISDIR(mode)) + return '/'; + else if (GIT_PERMS_IS_EXEC(mode)) + return '*'; + else + return ' '; +} + +static void fprintf_delta(FILE *fp, const git_diff_delta *delta, float progress) +{ + char code = git_diff_status_char(delta->status); + char old_suffix = diff_pick_suffix(delta->old_file.mode); + char new_suffix = diff_pick_suffix(delta->new_file.mode); + + fprintf(fp, "%c\t%s", code, delta->old_file.path); + + if ((delta->old_file.path != delta->new_file.path && + strcmp(delta->old_file.path, delta->new_file.path) != 0) || + (delta->old_file.mode != delta->new_file.mode && + delta->old_file.mode != 0 && delta->new_file.mode != 0)) + fprintf(fp, "%c %s%c", old_suffix, delta->new_file.path, new_suffix); + else if (old_suffix != ' ') + fprintf(fp, "%c", old_suffix); + + fprintf(fp, "\t[%.2f]\n", progress); +} + +int diff_file_cb( + const git_diff_delta *delta, + float progress, + void *payload) +{ + diff_expects *e = payload; + + if (e->debug) + fprintf_delta(stderr, delta, progress); + + if (e->names) + cl_assert_equal_s(e->names[e->files], delta->old_file.path); + if (e->statuses) + cl_assert_equal_i(e->statuses[e->files], (int)delta->status); + + e->files++; + + if ((delta->flags & GIT_DIFF_FLAG_BINARY) != 0) + e->files_binary++; + + cl_assert(delta->status <= GIT_DELTA_TYPECHANGE); + + e->file_status[delta->status] += 1; + + return 0; +} + +int diff_print_file_cb( + const git_diff_delta *delta, + float progress, + void *payload) +{ + if (!payload) { + fprintf_delta(stderr, delta, progress); + return 0; + } + + if (!((diff_expects *)payload)->debug) + fprintf_delta(stderr, delta, progress); + + return diff_file_cb(delta, progress, payload); +} + +int diff_hunk_cb( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + void *payload) +{ + diff_expects *e = payload; + const char *scan = hunk->header, *scan_end = scan + hunk->header_len; + + GIT_UNUSED(delta); + + /* confirm no NUL bytes in header text */ + while (scan < scan_end) + cl_assert('\0' != *scan++); + + e->hunks++; + e->hunk_old_lines += hunk->old_lines; + e->hunk_new_lines += hunk->new_lines; + return 0; +} + +int diff_line_cb( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + const git_diff_line *line, + void *payload) +{ + diff_expects *e = payload; + + GIT_UNUSED(delta); + GIT_UNUSED(hunk); + + e->lines++; + switch (line->origin) { + case GIT_DIFF_LINE_CONTEXT: + case GIT_DIFF_LINE_CONTEXT_EOFNL: /* techically not a line */ + e->line_ctxt++; + break; + case GIT_DIFF_LINE_ADDITION: + case GIT_DIFF_LINE_ADD_EOFNL: /* technically not a line add */ + e->line_adds++; + break; + case GIT_DIFF_LINE_DELETION: + case GIT_DIFF_LINE_DEL_EOFNL: /* technically not a line delete */ + e->line_dels++; + break; + default: + break; + } + return 0; +} + +int diff_foreach_via_iterator( + git_diff *diff, + git_diff_file_cb file_cb, + git_diff_hunk_cb hunk_cb, + git_diff_line_cb line_cb, + void *data) +{ + size_t d, num_d = git_diff_num_deltas(diff); + + for (d = 0; d < num_d; ++d) { + git_patch *patch; + const git_diff_delta *delta; + size_t h, num_h; + + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + cl_assert((delta = git_patch_get_delta(patch)) != NULL); + + /* call file_cb for this file */ + if (file_cb != NULL && file_cb(delta, (float)d / num_d, data) != 0) { + git_patch_free(patch); + goto abort; + } + + /* if there are no changes, then the patch will be NULL */ + if (!patch) { + cl_assert(delta->status == GIT_DELTA_UNMODIFIED || + (delta->flags & GIT_DIFF_FLAG_BINARY) != 0); + continue; + } + + if (!hunk_cb && !line_cb) { + git_patch_free(patch); + continue; + } + + num_h = git_patch_num_hunks(patch); + + for (h = 0; h < num_h; h++) { + const git_diff_hunk *hunk; + size_t l, num_l; + + cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h)); + + if (hunk_cb && hunk_cb(delta, hunk, data) != 0) { + git_patch_free(patch); + goto abort; + } + + for (l = 0; l < num_l; ++l) { + const git_diff_line *line; + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l)); + + if (line_cb && + line_cb(delta, hunk, line, data) != 0) { + git_patch_free(patch); + goto abort; + } + } + } + + git_patch_free(patch); + } + + return 0; + +abort: + giterr_clear(); + return GIT_EUSER; +} + +static int diff_print_cb( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + const git_diff_line *line, + void *payload) +{ + FILE *fp = payload; + + GIT_UNUSED(delta); GIT_UNUSED(hunk); + + if (line->origin == GIT_DIFF_LINE_CONTEXT || + line->origin == GIT_DIFF_LINE_ADDITION || + line->origin == GIT_DIFF_LINE_DELETION) + fputc(line->origin, fp); + fwrite(line->content, 1, line->content_len, fp); + return 0; +} + +void diff_print(FILE *fp, git_diff *diff) +{ + cl_git_pass(git_diff_print( + diff, GIT_DIFF_FORMAT_PATCH, diff_print_cb, fp ? fp : stderr)); +} + +void diff_print_raw(FILE *fp, git_diff *diff) +{ + cl_git_pass(git_diff_print( + diff, GIT_DIFF_FORMAT_RAW, diff_print_cb, fp ? fp : stderr)); +} diff --git a/tests/diff/diff_helpers.h b/tests/diff/diff_helpers.h new file mode 100644 index 000000000..bf21f4b1f --- /dev/null +++ b/tests/diff/diff_helpers.h @@ -0,0 +1,64 @@ +#include "fileops.h" +#include "git2/diff.h" + +extern git_tree *resolve_commit_oid_to_tree( + git_repository *repo, const char *partial_oid); + +typedef struct { + int files; + int files_binary; + + int file_status[10]; /* indexed by git_delta_t value */ + + int hunks; + int hunk_new_lines; + int hunk_old_lines; + + int lines; + int line_ctxt; + int line_adds; + int line_dels; + + /* optional arrays of expected specific values */ + const char **names; + int *statuses; + + int debug; + +} diff_expects; + +typedef struct { + const char *path; + const char *matched_pathspec; +} notify_expected; + +extern int diff_file_cb( + const git_diff_delta *delta, + float progress, + void *cb_data); + +extern int diff_print_file_cb( + const git_diff_delta *delta, + float progress, + void *cb_data); + +extern int diff_hunk_cb( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + void *cb_data); + +extern int diff_line_cb( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + const git_diff_line *line, + void *cb_data); + +extern int diff_foreach_via_iterator( + git_diff *diff, + git_diff_file_cb file_cb, + git_diff_hunk_cb hunk_cb, + git_diff_line_cb line_cb, + void *data); + +extern void diff_print(FILE *fp, git_diff *diff); +extern void diff_print_raw(FILE *fp, git_diff *diff); diff --git a/tests/diff/diffiter.c b/tests/diff/diffiter.c new file mode 100644 index 000000000..f886e1baa --- /dev/null +++ b/tests/diff/diffiter.c @@ -0,0 +1,453 @@ +#include "clar_libgit2.h" +#include "diff_helpers.h" + +void test_diff_diffiter__initialize(void) +{ +} + +void test_diff_diffiter__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_diff_diffiter__create(void) +{ + git_repository *repo = cl_git_sandbox_init("attr"); + git_diff *diff; + size_t d, num_d; + + cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); + + num_d = git_diff_num_deltas(diff); + for (d = 0; d < num_d; ++d) { + const git_diff_delta *delta = git_diff_get_delta(diff, d); + cl_assert(delta != NULL); + } + + cl_assert(!git_diff_get_delta(diff, num_d)); + + git_diff_free(diff); +} + +void test_diff_diffiter__iterate_files_1(void) +{ + git_repository *repo = cl_git_sandbox_init("attr"); + git_diff *diff; + size_t d, num_d; + diff_expects exp = { 0 }; + + cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); + + num_d = git_diff_num_deltas(diff); + + for (d = 0; d < num_d; ++d) { + const git_diff_delta *delta = git_diff_get_delta(diff, d); + cl_assert(delta != NULL); + + diff_file_cb(delta, (float)d / (float)num_d, &exp); + } + cl_assert_equal_sz(6, exp.files); + + git_diff_free(diff); +} + +void test_diff_diffiter__iterate_files_2(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + git_diff *diff; + size_t d, num_d; + int count = 0; + + cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); + + num_d = git_diff_num_deltas(diff); + cl_assert_equal_i(8, (int)num_d); + + for (d = 0; d < num_d; ++d) { + const git_diff_delta *delta = git_diff_get_delta(diff, d); + cl_assert(delta != NULL); + count++; + } + cl_assert_equal_i(8, count); + + git_diff_free(diff); +} + +void test_diff_diffiter__iterate_files_and_hunks(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + size_t d, num_d; + int file_count = 0, hunk_count = 0; + + opts.context_lines = 3; + opts.interhunk_lines = 1; + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + + cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); + + num_d = git_diff_num_deltas(diff); + + for (d = 0; d < num_d; ++d) { + git_patch *patch; + size_t h, num_h; + + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + cl_assert(patch); + + file_count++; + + num_h = git_patch_num_hunks(patch); + + for (h = 0; h < num_h; h++) { + const git_diff_hunk *hunk; + + cl_git_pass(git_patch_get_hunk(&hunk, NULL, patch, h)); + cl_assert(hunk); + + hunk_count++; + } + + git_patch_free(patch); + } + + cl_assert_equal_i(13, file_count); + cl_assert_equal_i(8, hunk_count); + + git_diff_free(diff); +} + +void test_diff_diffiter__max_size_threshold(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + int file_count = 0, binary_count = 0, hunk_count = 0; + size_t d, num_d; + + opts.context_lines = 3; + opts.interhunk_lines = 1; + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + + cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); + num_d = git_diff_num_deltas(diff); + + for (d = 0; d < num_d; ++d) { + git_patch *patch; + const git_diff_delta *delta; + + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + cl_assert(patch); + delta = git_patch_get_delta(patch); + cl_assert(delta); + + file_count++; + hunk_count += (int)git_patch_num_hunks(patch); + + assert((delta->flags & (GIT_DIFF_FLAG_BINARY|GIT_DIFF_FLAG_NOT_BINARY)) != 0); + binary_count += ((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); + + git_patch_free(patch); + } + + cl_assert_equal_i(13, file_count); + cl_assert_equal_i(0, binary_count); + cl_assert_equal_i(8, hunk_count); + + git_diff_free(diff); + + /* try again with low file size threshold */ + + file_count = binary_count = hunk_count = 0; + + opts.context_lines = 3; + opts.interhunk_lines = 1; + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + opts.max_size = 50; /* treat anything over 50 bytes as binary! */ + + cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); + num_d = git_diff_num_deltas(diff); + + for (d = 0; d < num_d; ++d) { + git_patch *patch; + const git_diff_delta *delta; + + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + delta = git_patch_get_delta(patch); + + file_count++; + hunk_count += (int)git_patch_num_hunks(patch); + + assert((delta->flags & (GIT_DIFF_FLAG_BINARY|GIT_DIFF_FLAG_NOT_BINARY)) != 0); + binary_count += ((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); + + git_patch_free(patch); + } + + cl_assert_equal_i(13, file_count); + /* Three files are over the 50 byte threshold: + * - staged_changes_file_deleted + * - staged_changes_modified_file + * - staged_new_file_modified_file + */ + cl_assert_equal_i(3, binary_count); + cl_assert_equal_i(5, hunk_count); + + git_diff_free(diff); +} + + +void test_diff_diffiter__iterate_all(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + diff_expects exp = {0}; + size_t d, num_d; + + opts.context_lines = 3; + opts.interhunk_lines = 1; + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + + cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); + + num_d = git_diff_num_deltas(diff); + for (d = 0; d < num_d; ++d) { + git_patch *patch; + size_t h, num_h; + + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + cl_assert(patch); + exp.files++; + + num_h = git_patch_num_hunks(patch); + for (h = 0; h < num_h; h++) { + const git_diff_hunk *range; + size_t l, num_l; + + cl_git_pass(git_patch_get_hunk(&range, &num_l, patch, h)); + cl_assert(range); + exp.hunks++; + + for (l = 0; l < num_l; ++l) { + const git_diff_line *line; + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l)); + cl_assert(line && line->content); + exp.lines++; + } + } + + git_patch_free(patch); + } + + cl_assert_equal_i(13, exp.files); + cl_assert_equal_i(8, exp.hunks); + cl_assert_equal_i(14, exp.lines); + + git_diff_free(diff); +} + +static void iterate_over_patch(git_patch *patch, diff_expects *exp) +{ + size_t h, num_h = git_patch_num_hunks(patch), num_l; + + exp->files++; + exp->hunks += (int)num_h; + + /* let's iterate in reverse, just because we can! */ + for (h = 1, num_l = 0; h <= num_h; ++h) + num_l += git_patch_num_lines_in_hunk(patch, num_h - h); + + exp->lines += (int)num_l; +} + +#define PATCH_CACHE 5 + +void test_diff_diffiter__iterate_randomly_while_saving_state(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + diff_expects exp = {0}; + git_patch *patches[PATCH_CACHE]; + size_t p, d, num_d; + + memset(patches, 0, sizeof(patches)); + + opts.context_lines = 3; + opts.interhunk_lines = 1; + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + + cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); + + num_d = git_diff_num_deltas(diff); + + /* To make sure that references counts work for diff and patch objects, + * this generates patches and randomly caches them. Only when the patch + * is removed from the cache are hunks and lines counted. At the end, + * there are still patches in the cache, so free the diff and try to + * process remaining patches after the diff is freed. + */ + + srand(121212); + p = rand() % PATCH_CACHE; + + for (d = 0; d < num_d; ++d) { + /* take old patch */ + git_patch *patch = patches[p]; + patches[p] = NULL; + + /* cache new patch */ + cl_git_pass(git_patch_from_diff(&patches[p], diff, d)); + cl_assert(patches[p] != NULL); + + /* process old patch if non-NULL */ + if (patch != NULL) { + iterate_over_patch(patch, &exp); + git_patch_free(patch); + } + + p = rand() % PATCH_CACHE; + } + + /* free diff list now - refcounts should keep things safe */ + git_diff_free(diff); + + /* process remaining unprocessed patches */ + for (p = 0; p < PATCH_CACHE; p++) { + git_patch *patch = patches[p]; + + if (patch != NULL) { + iterate_over_patch(patch, &exp); + git_patch_free(patch); + } + } + + /* hopefully it all still added up right */ + cl_assert_equal_i(13, exp.files); + cl_assert_equal_i(8, exp.hunks); + cl_assert_equal_i(14, exp.lines); +} + +/* This output is taken directly from `git diff` on the status test data */ +static const char *expected_patch_text[8] = { + /* 0 */ + "diff --git a/file_deleted b/file_deleted\n" + "deleted file mode 100644\n" + "index 5452d32..0000000\n" + "--- a/file_deleted\n" + "+++ /dev/null\n" + "@@ -1 +0,0 @@\n" + "-file_deleted\n", + /* 1 */ + "diff --git a/modified_file b/modified_file\n" + "index 452e424..0a53963 100644\n" + "--- a/modified_file\n" + "+++ b/modified_file\n" + "@@ -1 +1,2 @@\n" + " modified_file\n" + "+modified_file\n", + /* 2 */ + "diff --git a/staged_changes_file_deleted b/staged_changes_file_deleted\n" + "deleted file mode 100644\n" + "index a6be623..0000000\n" + "--- a/staged_changes_file_deleted\n" + "+++ /dev/null\n" + "@@ -1,2 +0,0 @@\n" + "-staged_changes_file_deleted\n" + "-staged_changes_file_deleted\n", + /* 3 */ + "diff --git a/staged_changes_modified_file b/staged_changes_modified_file\n" + "index 906ee77..011c344 100644\n" + "--- a/staged_changes_modified_file\n" + "+++ b/staged_changes_modified_file\n" + "@@ -1,2 +1,3 @@\n" + " staged_changes_modified_file\n" + " staged_changes_modified_file\n" + "+staged_changes_modified_file\n", + /* 4 */ + "diff --git a/staged_new_file_deleted_file b/staged_new_file_deleted_file\n" + "deleted file mode 100644\n" + "index 90b8c29..0000000\n" + "--- a/staged_new_file_deleted_file\n" + "+++ /dev/null\n" + "@@ -1 +0,0 @@\n" + "-staged_new_file_deleted_file\n", + /* 5 */ + "diff --git a/staged_new_file_modified_file b/staged_new_file_modified_file\n" + "index ed06290..8b090c0 100644\n" + "--- a/staged_new_file_modified_file\n" + "+++ b/staged_new_file_modified_file\n" + "@@ -1 +1,2 @@\n" + " staged_new_file_modified_file\n" + "+staged_new_file_modified_file\n", + /* 6 */ + "diff --git a/subdir/deleted_file b/subdir/deleted_file\n" + "deleted file mode 100644\n" + "index 1888c80..0000000\n" + "--- a/subdir/deleted_file\n" + "+++ /dev/null\n" + "@@ -1 +0,0 @@\n" + "-subdir/deleted_file\n", + /* 7 */ + "diff --git a/subdir/modified_file b/subdir/modified_file\n" + "index a619198..57274b7 100644\n" + "--- a/subdir/modified_file\n" + "+++ b/subdir/modified_file\n" + "@@ -1 +1,2 @@\n" + " subdir/modified_file\n" + "+subdir/modified_file\n" +}; + +void test_diff_diffiter__iterate_and_generate_patch_text(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + git_diff *diff; + size_t d, num_d; + + cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); + + num_d = git_diff_num_deltas(diff); + cl_assert_equal_i(8, (int)num_d); + + for (d = 0; d < num_d; ++d) { + git_patch *patch; + char *text; + + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + cl_assert(patch != NULL); + + cl_git_pass(git_patch_to_str(&text, patch)); + + cl_assert_equal_s(expected_patch_text[d], text); + + git__free(text); + git_patch_free(patch); + } + + git_diff_free(diff); +} + +void test_diff_diffiter__checks_options_version(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + const git_error *err; + + opts.version = 0; + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + + cl_git_fail(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); + + giterr_clear(); + opts.version = 1024; + cl_git_fail(git_diff_index_to_workdir(&diff, repo, NULL, &opts)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); +} + diff --git a/tests/diff/drivers.c b/tests/diff/drivers.c new file mode 100644 index 000000000..fbd1dff81 --- /dev/null +++ b/tests/diff/drivers.c @@ -0,0 +1,163 @@ +#include "clar_libgit2.h" +#include "diff_helpers.h" +#include "repository.h" +#include "diff_driver.h" + +static git_repository *g_repo = NULL; + +void test_diff_drivers__initialize(void) +{ +} + +void test_diff_drivers__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +void test_diff_drivers__patterns(void) +{ + git_config *cfg; + const char *one_sha = "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13"; + git_tree *one; + git_diff *diff; + git_patch *patch; + char *text; + const char *expected0 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Comes through the blood of the vanguards who\n dreamed--too soon--it had sounded.\r\n \r\n -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n"; + const char *expected1 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\nBinary files a/untimely.txt and b/untimely.txt differ\n"; + const char *expected2 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Heaven delivers on earth the Hour that cannot be\n dreamed--too soon--it had sounded.\r\n \r\n -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n"; + + g_repo = cl_git_sandbox_init("renames"); + + one = resolve_commit_oid_to_tree(g_repo, one_sha); + + /* no diff */ + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); + cl_assert_equal_i(0, (int)git_diff_num_deltas(diff)); + git_diff_free(diff); + + /* default diff */ + + cl_git_append2file("renames/untimely.txt", "\r\nSome new stuff\r\n"); + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); + cl_assert_equal_s(expected0, text); + + git__free(text); + git_patch_free(patch); + git_diff_free(diff); + + /* attribute diff set to false */ + + cl_git_rewritefile("renames/.gitattributes", "untimely.txt -diff\n"); + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); + cl_assert_equal_s(expected1, text); + + git__free(text); + git_patch_free(patch); + git_diff_free(diff); + + /* attribute diff set to unconfigured value (should use default) */ + + cl_git_rewritefile("renames/.gitattributes", "untimely.txt diff=kipling0\n"); + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); + cl_assert_equal_s(expected0, text); + + git__free(text); + git_patch_free(patch); + git_diff_free(diff); + + /* let's define that driver */ + + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_bool(cfg, "diff.kipling0.binary", 1)); + git_config_free(cfg); + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); + cl_assert_equal_s(expected1, text); + + git__free(text); + git_patch_free(patch); + git_diff_free(diff); + + /* let's use a real driver with some regular expressions */ + + git_diff_driver_registry_free(g_repo->diff_drivers); + g_repo->diff_drivers = NULL; + + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_bool(cfg, "diff.kipling0.binary", 0)); + cl_git_pass(git_config_set_string(cfg, "diff.kipling0.xfuncname", "^H")); + git_config_free(cfg); + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL)); + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); + cl_assert_equal_s(expected2, text); + + git__free(text); + git_patch_free(patch); + git_diff_free(diff); + + git_tree_free(one); +} + +void test_diff_drivers__long_lines(void) +{ + const char *base = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non nisi ligula. Ut viverra enim sed lobortis suscipit.\nPhasellus eget erat odio. Praesent at est iaculis, ultricies augue vel, dignissim risus. Suspendisse at nisi quis turpis fringilla rutrum id sit amet nulla.\nNam eget dolor fermentum, aliquet nisl at, convallis tellus. Pellentesque rhoncus erat enim, id porttitor elit euismod quis.\nMauris sollicitudin magna odio, non egestas libero vehicula ut. Etiam et quam velit. Fusce eget libero rhoncus, ultricies felis sit amet, egestas purus.\nAliquam in semper tellus. Pellentesque adipiscing rutrum velit, quis malesuada lacus consequat eget.\n"; + git_index *idx; + git_diff *diff; + git_patch *patch; + char *actual; + const char *expected = "diff --git a/longlines.txt b/longlines.txt\nindex c1ce6ef..0134431 100644\n--- a/longlines.txt\n+++ b/longlines.txt\n@@ -3,3 +3,5 @@ Phasellus eget erat odio. Praesent at est iaculis, ultricies augue vel, dignissi\n Nam eget dolor fermentum, aliquet nisl at, convallis tellus. Pellentesque rhoncus erat enim, id porttitor elit euismod quis.\n Mauris sollicitudin magna odio, non egestas libero vehicula ut. Etiam et quam velit. Fusce eget libero rhoncus, ultricies felis sit amet, egestas purus.\n Aliquam in semper tellus. Pellentesque adipiscing rutrum velit, quis malesuada lacus consequat eget.\n+newline\n+newline\n"; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_mkfile("empty_standard_repo/longlines.txt", base); + cl_git_pass(git_repository_index(&idx, g_repo)); + cl_git_pass(git_index_add_bypath(idx, "longlines.txt")); + cl_git_pass(git_index_write(idx)); + git_index_free(idx); + + cl_git_append2file("empty_standard_repo/longlines.txt", "newline\nnewline\n"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); + cl_assert_equal_sz(1, git_diff_num_deltas(diff)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&actual, patch)); + + /* if chmod not supported, overwrite mode bits since anything is possible */ + if (!cl_is_chmod_supported()) { + size_t actual_len = strlen(actual); + if (actual_len > 72 && memcmp(&actual[66], "100644", 6) != 0) + memcpy(&actual[66], "100644", 6); + } + + cl_assert_equal_s(expected, actual); + + free(actual); + git_patch_free(patch); + git_diff_free(diff); +} + diff --git a/tests/diff/index.c b/tests/diff/index.c new file mode 100644 index 000000000..8f4567137 --- /dev/null +++ b/tests/diff/index.c @@ -0,0 +1,167 @@ +#include "clar_libgit2.h" +#include "diff_helpers.h" + +static git_repository *g_repo = NULL; + +void test_diff_index__initialize(void) +{ + g_repo = cl_git_sandbox_init("status"); +} + +void test_diff_index__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_diff_index__0(void) +{ + /* grabbed a couple of commit oids from the history of the attr repo */ + const char *a_commit = "26a125ee1bf"; /* the current HEAD */ + const char *b_commit = "0017bd4ab1ec3"; /* the start */ + git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); + git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit); + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + diff_expects exp; + + cl_assert(a); + cl_assert(b); + + opts.context_lines = 1; + opts.interhunk_lines = 1; + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + /* to generate these values: + * - cd to tests/resources/status, + * - mv .gitted .git + * - git diff --name-status --cached 26a125ee1bf + * - git diff -U1 --cached 26a125ee1bf + * - mv .git .gitted + */ + cl_assert_equal_i(8, exp.files); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); + + cl_assert_equal_i(8, exp.hunks); + + cl_assert_equal_i(11, exp.lines); + cl_assert_equal_i(3, exp.line_ctxt); + cl_assert_equal_i(6, exp.line_adds); + cl_assert_equal_i(2, exp.line_dels); + + git_diff_free(diff); + diff = NULL; + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + /* to generate these values: + * - cd to tests/resources/status, + * - mv .gitted .git + * - git diff --name-status --cached 0017bd4ab1ec3 + * - git diff -U1 --cached 0017bd4ab1ec3 + * - mv .git .gitted + */ + cl_assert_equal_i(12, exp.files); + cl_assert_equal_i(7, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); + + cl_assert_equal_i(12, exp.hunks); + + cl_assert_equal_i(16, exp.lines); + cl_assert_equal_i(3, exp.line_ctxt); + cl_assert_equal_i(11, exp.line_adds); + cl_assert_equal_i(2, exp.line_dels); + + git_diff_free(diff); + diff = NULL; + + git_tree_free(a); + git_tree_free(b); +} + +static int diff_stop_after_2_files( + const git_diff_delta *delta, + float progress, + void *payload) +{ + diff_expects *e = payload; + + GIT_UNUSED(progress); + GIT_UNUSED(delta); + + e->files++; + + return (e->files == 2); +} + +void test_diff_index__1(void) +{ + /* grabbed a couple of commit oids from the history of the attr repo */ + const char *a_commit = "26a125ee1bf"; /* the current HEAD */ + const char *b_commit = "0017bd4ab1ec3"; /* the start */ + git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); + git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit); + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + diff_expects exp; + + cl_assert(a); + cl_assert(b); + + opts.context_lines = 1; + opts.interhunk_lines = 1; + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); + + cl_assert_equal_i( + GIT_EUSER, + git_diff_foreach(diff, diff_stop_after_2_files, NULL, NULL, &exp) + ); + + cl_assert_equal_i(2, exp.files); + + git_diff_free(diff); + diff = NULL; + + git_tree_free(a); + git_tree_free(b); +} + +void test_diff_index__checks_options_version(void) +{ + const char *a_commit = "26a125ee1bf"; + git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + const git_error *err; + + opts.version = 0; + cl_git_fail(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); + cl_assert_equal_p(diff, NULL); + + giterr_clear(); + opts.version = 1024; + cl_git_fail(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); + cl_assert_equal_p(diff, NULL); + + git_tree_free(a); +} + diff --git a/tests/diff/iterator.c b/tests/diff/iterator.c new file mode 100644 index 000000000..bbdae8ad1 --- /dev/null +++ b/tests/diff/iterator.c @@ -0,0 +1,937 @@ +#include "clar_libgit2.h" +#include "diff_helpers.h" +#include "iterator.h" +#include "tree.h" + +void test_diff_iterator__initialize(void) +{ + /* since we are doing tests with different sandboxes, defer setup + * to the actual tests. cleanup will still be done in the global + * cleanup function so that assertion failures don't result in a + * missed cleanup. + */ +} + +void test_diff_iterator__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + + +/* -- TREE ITERATOR TESTS -- */ + +static void tree_iterator_test( + const char *sandbox, + const char *treeish, + const char *start, + const char *end, + int expected_count, + const char **expected_values) +{ + git_tree *t; + git_iterator *i; + const git_index_entry *entry; + int error, count = 0, count_post_reset = 0; + git_repository *repo = cl_git_sandbox_init(sandbox); + + cl_assert(t = resolve_commit_oid_to_tree(repo, treeish)); + cl_git_pass(git_iterator_for_tree( + &i, t, GIT_ITERATOR_DONT_IGNORE_CASE, start, end)); + + /* test loop */ + while (!(error = git_iterator_advance(&entry, i))) { + cl_assert(entry); + if (expected_values != NULL) + cl_assert_equal_s(expected_values[count], entry->path); + count++; + } + cl_assert_equal_i(GIT_ITEROVER, error); + cl_assert(!entry); + cl_assert_equal_i(expected_count, count); + + /* test reset */ + cl_git_pass(git_iterator_reset(i, NULL, NULL)); + + while (!(error = git_iterator_advance(&entry, i))) { + cl_assert(entry); + if (expected_values != NULL) + cl_assert_equal_s(expected_values[count_post_reset], entry->path); + count_post_reset++; + } + cl_assert_equal_i(GIT_ITEROVER, error); + cl_assert(!entry); + cl_assert_equal_i(count, count_post_reset); + + git_iterator_free(i); + git_tree_free(t); +} + +/* results of: git ls-tree -r --name-only 605812a */ +const char *expected_tree_0[] = { + ".gitattributes", + "attr0", + "attr1", + "attr2", + "attr3", + "binfile", + "macro_test", + "root_test1", + "root_test2", + "root_test3", + "root_test4.txt", + "subdir/.gitattributes", + "subdir/abc", + "subdir/subdir_test1", + "subdir/subdir_test2.txt", + "subdir2/subdir2_test1", + NULL +}; + +void test_diff_iterator__tree_0(void) +{ + tree_iterator_test("attr", "605812a", NULL, NULL, 16, expected_tree_0); +} + +/* results of: git ls-tree -r --name-only 6bab5c79 */ +const char *expected_tree_1[] = { + ".gitattributes", + "attr0", + "attr1", + "attr2", + "attr3", + "root_test1", + "root_test2", + "root_test3", + "root_test4.txt", + "subdir/.gitattributes", + "subdir/subdir_test1", + "subdir/subdir_test2.txt", + "subdir2/subdir2_test1", + NULL +}; + +void test_diff_iterator__tree_1(void) +{ + tree_iterator_test("attr", "6bab5c79cd5", NULL, NULL, 13, expected_tree_1); +} + +/* results of: git ls-tree -r --name-only 26a125ee1 */ +const char *expected_tree_2[] = { + "current_file", + "file_deleted", + "modified_file", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "subdir.txt", + "subdir/current_file", + "subdir/deleted_file", + "subdir/modified_file", + NULL +}; + +void test_diff_iterator__tree_2(void) +{ + tree_iterator_test("status", "26a125ee1", NULL, NULL, 12, expected_tree_2); +} + +/* $ git ls-tree -r --name-only 0017bd4ab1e */ +const char *expected_tree_3[] = { + "current_file", + "file_deleted", + "modified_file", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file" +}; + +void test_diff_iterator__tree_3(void) +{ + tree_iterator_test("status", "0017bd4ab1e", NULL, NULL, 8, expected_tree_3); +} + +/* $ git ls-tree -r --name-only 24fa9a9fc4e202313e24b648087495441dab432b */ +const char *expected_tree_4[] = { + "attr0", + "attr1", + "attr2", + "attr3", + "binfile", + "gitattributes", + "macro_bad", + "macro_test", + "root_test1", + "root_test2", + "root_test3", + "root_test4.txt", + "sub/abc", + "sub/file", + "sub/sub/file", + "sub/sub/subsub.txt", + "sub/subdir_test1", + "sub/subdir_test2.txt", + "subdir/.gitattributes", + "subdir/abc", + "subdir/subdir_test1", + "subdir/subdir_test2.txt", + "subdir2/subdir2_test1", + NULL +}; + +void test_diff_iterator__tree_4(void) +{ + tree_iterator_test( + "attr", "24fa9a9fc4e202313e24b648087495441dab432b", NULL, NULL, + 23, expected_tree_4); +} + +void test_diff_iterator__tree_4_ranged(void) +{ + tree_iterator_test( + "attr", "24fa9a9fc4e202313e24b648087495441dab432b", + "sub", "sub", + 11, &expected_tree_4[12]); +} + +const char *expected_tree_ranged_0[] = { + "gitattributes", + "macro_bad", + "macro_test", + "root_test1", + "root_test2", + "root_test3", + "root_test4.txt", + NULL +}; + +void test_diff_iterator__tree_ranged_0(void) +{ + tree_iterator_test( + "attr", "24fa9a9fc4e202313e24b648087495441dab432b", + "git", "root", + 7, expected_tree_ranged_0); +} + +const char *expected_tree_ranged_1[] = { + "sub/subdir_test2.txt", + NULL +}; + +void test_diff_iterator__tree_ranged_1(void) +{ + tree_iterator_test( + "attr", "24fa9a9fc4e202313e24b648087495441dab432b", + "sub/subdir_test2.txt", "sub/subdir_test2.txt", + 1, expected_tree_ranged_1); +} + +void test_diff_iterator__tree_range_empty_0(void) +{ + tree_iterator_test( + "attr", "24fa9a9fc4e202313e24b648087495441dab432b", + "empty", "empty", 0, NULL); +} + +void test_diff_iterator__tree_range_empty_1(void) +{ + tree_iterator_test( + "attr", "24fa9a9fc4e202313e24b648087495441dab432b", + "z_empty_after", NULL, 0, NULL); +} + +void test_diff_iterator__tree_range_empty_2(void) +{ + tree_iterator_test( + "attr", "24fa9a9fc4e202313e24b648087495441dab432b", + NULL, ".aaa_empty_before", 0, NULL); +} + +static void check_tree_entry( + git_iterator *i, + const char *oid, + const char *oid_p, + const char *oid_pp, + const char *oid_ppp) +{ + const git_index_entry *ie; + const git_tree_entry *te; + const git_tree *tree; + git_buf path = GIT_BUF_INIT; + + cl_git_pass(git_iterator_current_tree_entry(&te, i)); + cl_assert(te); + cl_assert(git_oid_streq(&te->oid, oid) == 0); + + cl_git_pass(git_iterator_current(&ie, i)); + cl_git_pass(git_buf_sets(&path, ie->path)); + + if (oid_p) { + git_buf_rtruncate_at_char(&path, '/'); + cl_git_pass(git_iterator_current_parent_tree(&tree, i, path.ptr)); + cl_assert(tree); + cl_assert(git_oid_streq(git_tree_id(tree), oid_p) == 0); + } + + if (oid_pp) { + git_buf_rtruncate_at_char(&path, '/'); + cl_git_pass(git_iterator_current_parent_tree(&tree, i, path.ptr)); + cl_assert(tree); + cl_assert(git_oid_streq(git_tree_id(tree), oid_pp) == 0); + } + + if (oid_ppp) { + git_buf_rtruncate_at_char(&path, '/'); + cl_git_pass(git_iterator_current_parent_tree(&tree, i, path.ptr)); + cl_assert(tree); + cl_assert(git_oid_streq(git_tree_id(tree), oid_ppp) == 0); + } + + git_buf_free(&path); +} + +void test_diff_iterator__tree_special_functions(void) +{ + git_tree *t; + git_iterator *i; + const git_index_entry *entry; + git_repository *repo = cl_git_sandbox_init("attr"); + int error, cases = 0; + const char *rootoid = "ce39a97a7fb1fa90bcf5e711249c1e507476ae0e"; + + t = resolve_commit_oid_to_tree( + repo, "24fa9a9fc4e202313e24b648087495441dab432b"); + cl_assert(t != NULL); + + cl_git_pass(git_iterator_for_tree( + &i, t, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)); + + while (!(error = git_iterator_advance(&entry, i))) { + cl_assert(entry); + + if (strcmp(entry->path, "sub/file") == 0) { + cases++; + check_tree_entry( + i, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057", + "ecb97df2a174987475ac816e3847fc8e9f6c596b", + rootoid, NULL); + } + else if (strcmp(entry->path, "sub/sub/subsub.txt") == 0) { + cases++; + check_tree_entry( + i, "9e5bdc47d6a80f2be0ea3049ad74231b94609242", + "4e49ba8c5b6c32ff28cd9dcb60be34df50fcc485", + "ecb97df2a174987475ac816e3847fc8e9f6c596b", rootoid); + } + else if (strcmp(entry->path, "subdir/.gitattributes") == 0) { + cases++; + check_tree_entry( + i, "99eae476896f4907224978b88e5ecaa6c5bb67a9", + "9fb40b6675dde60b5697afceae91b66d908c02d9", + rootoid, NULL); + } + else if (strcmp(entry->path, "subdir2/subdir2_test1") == 0) { + cases++; + check_tree_entry( + i, "dccada462d3df8ac6de596fb8c896aba9344f941", + "2929de282ce999e95183aedac6451d3384559c4b", + rootoid, NULL); + } + } + cl_assert_equal_i(GIT_ITEROVER, error); + cl_assert(!entry); + cl_assert_equal_i(4, cases); + + git_iterator_free(i); + git_tree_free(t); +} + +/* -- INDEX ITERATOR TESTS -- */ + +static void index_iterator_test( + const char *sandbox, + const char *start, + const char *end, + int expected_count, + const char **expected_names, + const char **expected_oids) +{ + git_index *index; + git_iterator *i; + const git_index_entry *entry; + int error, count = 0; + git_repository *repo = cl_git_sandbox_init(sandbox); + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_iterator_for_index(&i, index, 0, start, end)); + + while (!(error = git_iterator_advance(&entry, i))) { + cl_assert(entry); + + if (expected_names != NULL) + cl_assert_equal_s(expected_names[count], entry->path); + + if (expected_oids != NULL) { + git_oid oid; + cl_git_pass(git_oid_fromstr(&oid, expected_oids[count])); + cl_assert_equal_i(git_oid_cmp(&oid, &entry->oid), 0); + } + + count++; + } + + cl_assert_equal_i(GIT_ITEROVER, error); + cl_assert(!entry); + cl_assert_equal_i(expected_count, count); + + git_iterator_free(i); + git_index_free(index); +} + +static const char *expected_index_0[] = { + "attr0", + "attr1", + "attr2", + "attr3", + "binfile", + "gitattributes", + "macro_bad", + "macro_test", + "root_test1", + "root_test2", + "root_test3", + "root_test4.txt", + "sub/abc", + "sub/file", + "sub/sub/file", + "sub/sub/subsub.txt", + "sub/subdir_test1", + "sub/subdir_test2.txt", + "subdir/.gitattributes", + "subdir/abc", + "subdir/subdir_test1", + "subdir/subdir_test2.txt", + "subdir2/subdir2_test1", +}; + +static const char *expected_index_oids_0[] = { + "556f8c827b8e4a02ad5cab77dca2bcb3e226b0b3", + "3b74db7ab381105dc0d28f8295a77f6a82989292", + "2c66e14f77196ea763fb1e41612c1aa2bc2d8ed2", + "c485abe35abd4aa6fd83b076a78bbea9e2e7e06c", + "d800886d9c86731ae5c4a62b0b77c437015e00d2", + "2b40c5aca159b04ea8d20ffe36cdf8b09369b14a", + "5819a185d77b03325aaf87cafc771db36f6ddca7", + "ff69f8639ce2e6010b3f33a74160aad98b48da2b", + "45141a79a77842c59a63229403220a4e4be74e3d", + "4d713dc48e6b1bd75b0d61ad078ba9ca3a56745d", + "108bb4e7fd7b16490dc33ff7d972151e73d7166e", + "a0f7217ae99f5ac3e88534f5cea267febc5fa85b", + "3e42ffc54a663f9401cc25843d6c0e71a33e4249", + "45b983be36b73c0788dc9cbcb76cbb80fc7bb057", + "45b983be36b73c0788dc9cbcb76cbb80fc7bb057", + "9e5bdc47d6a80f2be0ea3049ad74231b94609242", + "e563cf4758f0d646f1b14b76016aa17fa9e549a4", + "fb5067b1aef3ac1ada4b379dbcb7d17255df7d78", + "99eae476896f4907224978b88e5ecaa6c5bb67a9", + "3e42ffc54a663f9401cc25843d6c0e71a33e4249", + "e563cf4758f0d646f1b14b76016aa17fa9e549a4", + "fb5067b1aef3ac1ada4b379dbcb7d17255df7d78", + "dccada462d3df8ac6de596fb8c896aba9344f941" +}; + +void test_diff_iterator__index_0(void) +{ + index_iterator_test( + "attr", NULL, NULL, 23, expected_index_0, expected_index_oids_0); +} + +static const char *expected_index_range[] = { + "root_test1", + "root_test2", + "root_test3", + "root_test4.txt", +}; + +static const char *expected_index_oids_range[] = { + "45141a79a77842c59a63229403220a4e4be74e3d", + "4d713dc48e6b1bd75b0d61ad078ba9ca3a56745d", + "108bb4e7fd7b16490dc33ff7d972151e73d7166e", + "a0f7217ae99f5ac3e88534f5cea267febc5fa85b", +}; + +void test_diff_iterator__index_range(void) +{ + index_iterator_test( + "attr", "root", "root", 4, expected_index_range, expected_index_oids_range); +} + +void test_diff_iterator__index_range_empty_0(void) +{ + index_iterator_test( + "attr", "empty", "empty", 0, NULL, NULL); +} + +void test_diff_iterator__index_range_empty_1(void) +{ + index_iterator_test( + "attr", "z_empty_after", NULL, 0, NULL, NULL); +} + +void test_diff_iterator__index_range_empty_2(void) +{ + index_iterator_test( + "attr", NULL, ".aaa_empty_before", 0, NULL, NULL); +} + +static const char *expected_index_1[] = { + "current_file", + "file_deleted", + "modified_file", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "subdir.txt", + "subdir/current_file", + "subdir/deleted_file", + "subdir/modified_file", +}; + +static const char* expected_index_oids_1[] = { + "a0de7e0ac200c489c41c59dfa910154a70264e6e", + "5452d32f1dd538eb0405e8a83cc185f79e25e80f", + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a", + "55d316c9ba708999f1918e9677d01dfcae69c6b9", + "a6be623522ce87a1d862128ac42672604f7b468b", + "906ee7711f4f4928ddcb2a5f8fbc500deba0d2a8", + "529a16e8e762d4acb7b9636ff540a00831f9155a", + "90b8c29d8ba39434d1c63e1b093daaa26e5bd972", + "ed062903b8f6f3dccb2fa81117ba6590944ef9bd", + "e8ee89e15bbe9b20137715232387b3de5b28972e", + "53ace0d1cc1145a5f4fe4f78a186a60263190733", + "1888c805345ba265b0ee9449b8877b6064592058", + "a6191982709b746d5650e93c2acf34ef74e11504" +}; + +void test_diff_iterator__index_1(void) +{ + index_iterator_test( + "status", NULL, NULL, 13, expected_index_1, expected_index_oids_1); +} + + +/* -- WORKDIR ITERATOR TESTS -- */ + +static void workdir_iterator_test( + const char *sandbox, + const char *start, + const char *end, + int expected_count, + int expected_ignores, + const char **expected_names, + const char *an_ignored_name) +{ + git_iterator *i; + const git_index_entry *entry; + int error, count = 0, count_all = 0, count_all_post_reset = 0; + git_repository *repo = cl_git_sandbox_init(sandbox); + + cl_git_pass(git_iterator_for_workdir( + &i, repo, GIT_ITERATOR_DONT_AUTOEXPAND, start, end)); + + error = git_iterator_current(&entry, i); + cl_assert((error == 0 && entry != NULL) || + (error == GIT_ITEROVER && entry == NULL)); + + while (entry != NULL) { + int ignored = git_iterator_current_is_ignored(i); + + if (S_ISDIR(entry->mode)) { + cl_git_pass(git_iterator_advance_into(&entry, i)); + continue; + } + + if (expected_names != NULL) + cl_assert_equal_s(expected_names[count_all], entry->path); + + if (an_ignored_name && strcmp(an_ignored_name,entry->path)==0) + cl_assert(ignored); + + if (!ignored) + count++; + count_all++; + + error = git_iterator_advance(&entry, i); + + cl_assert((error == 0 && entry != NULL) || + (error == GIT_ITEROVER && entry == NULL)); + } + + cl_assert_equal_i(expected_count, count); + cl_assert_equal_i(expected_count + expected_ignores, count_all); + + cl_git_pass(git_iterator_reset(i, NULL, NULL)); + + error = git_iterator_current(&entry, i); + cl_assert((error == 0 && entry != NULL) || + (error == GIT_ITEROVER && entry == NULL)); + + while (entry != NULL) { + if (S_ISDIR(entry->mode)) { + cl_git_pass(git_iterator_advance_into(&entry, i)); + continue; + } + + if (expected_names != NULL) + cl_assert_equal_s( + expected_names[count_all_post_reset], entry->path); + count_all_post_reset++; + + error = git_iterator_advance(&entry, i); + cl_assert(error == 0 || error == GIT_ITEROVER); + } + + cl_assert_equal_i(count_all, count_all_post_reset); + + git_iterator_free(i); +} + +void test_diff_iterator__workdir_0(void) +{ + workdir_iterator_test("attr", NULL, NULL, 27, 1, NULL, "ign"); +} + +static const char *status_paths[] = { + "current_file", + "ignored_file", + "modified_file", + "new_file", + "staged_changes", + "staged_changes_modified_file", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_modified_file", + "subdir.txt", + "subdir/current_file", + "subdir/modified_file", + "subdir/new_file", + "\xe8\xbf\x99", + NULL +}; + +void test_diff_iterator__workdir_1(void) +{ + workdir_iterator_test( + "status", NULL, NULL, 13, 1, status_paths, "ignored_file"); +} + +static const char *status_paths_range_0[] = { + "staged_changes", + "staged_changes_modified_file", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_modified_file", + NULL +}; + +void test_diff_iterator__workdir_1_ranged_0(void) +{ + workdir_iterator_test( + "status", "staged", "staged", 5, 0, status_paths_range_0, NULL); +} + +static const char *status_paths_range_1[] = { + "modified_file", NULL +}; + +void test_diff_iterator__workdir_1_ranged_1(void) +{ + workdir_iterator_test( + "status", "modified_file", "modified_file", + 1, 0, status_paths_range_1, NULL); +} + +static const char *status_paths_range_3[] = { + "subdir.txt", + "subdir/current_file", + "subdir/modified_file", + NULL +}; + +void test_diff_iterator__workdir_1_ranged_3(void) +{ + workdir_iterator_test( + "status", "subdir", "subdir/modified_file", + 3, 0, status_paths_range_3, NULL); +} + +static const char *status_paths_range_4[] = { + "subdir/current_file", + "subdir/modified_file", + "subdir/new_file", + "\xe8\xbf\x99", + NULL +}; + +void test_diff_iterator__workdir_1_ranged_4(void) +{ + workdir_iterator_test( + "status", "subdir/", NULL, 4, 0, status_paths_range_4, NULL); +} + +static const char *status_paths_range_5[] = { + "subdir/modified_file", + NULL +}; + +void test_diff_iterator__workdir_1_ranged_5(void) +{ + workdir_iterator_test( + "status", "subdir/modified_file", "subdir/modified_file", + 1, 0, status_paths_range_5, NULL); +} + +void test_diff_iterator__workdir_1_ranged_empty_0(void) +{ + workdir_iterator_test( + "status", "\xff_does_not_exist", NULL, + 0, 0, NULL, NULL); +} + +void test_diff_iterator__workdir_1_ranged_empty_1(void) +{ + workdir_iterator_test( + "status", "empty", "empty", + 0, 0, NULL, NULL); +} + +void test_diff_iterator__workdir_1_ranged_empty_2(void) +{ + workdir_iterator_test( + "status", NULL, "aaaa_empty_before", + 0, 0, NULL, NULL); +} + +void test_diff_iterator__workdir_builtin_ignores(void) +{ + git_repository *repo = cl_git_sandbox_init("attr"); + git_iterator *i; + const git_index_entry *entry; + int idx; + static struct { + const char *path; + bool ignored; + } expected[] = { + { "dir/", true }, + { "file", false }, + { "ign", true }, + { "macro_bad", false }, + { "macro_test", false }, + { "root_test1", false }, + { "root_test2", false }, + { "root_test3", false }, + { "root_test4.txt", false }, + { "sub", false }, + { "sub/.gitattributes", false }, + { "sub/abc", false }, + { "sub/dir/", true }, + { "sub/file", false }, + { "sub/ign/", true }, + { "sub/sub", false }, + { "sub/sub/.gitattributes", false }, + { "sub/sub/dir", false }, /* file is not actually a dir */ + { "sub/sub/file", false }, + { NULL, false } + }; + + cl_git_pass(p_mkdir("attr/sub/sub/.git", 0777)); + cl_git_mkfile("attr/sub/.git", "whatever"); + + cl_git_pass(git_iterator_for_workdir( + &i, repo, GIT_ITERATOR_DONT_AUTOEXPAND, "dir", "sub/sub/file")); + cl_git_pass(git_iterator_current(&entry, i)); + + for (idx = 0; entry != NULL; ++idx) { + int ignored = git_iterator_current_is_ignored(i); + + cl_assert_equal_s(expected[idx].path, entry->path); + cl_assert_(ignored == expected[idx].ignored, expected[idx].path); + + if (!ignored && + (entry->mode == GIT_FILEMODE_TREE || + entry->mode == GIT_FILEMODE_COMMIT)) + { + /* it is possible to advance "into" a submodule */ + cl_git_pass(git_iterator_advance_into(&entry, i)); + } else { + int error = git_iterator_advance(&entry, i); + cl_assert(!error || error == GIT_ITEROVER); + } + } + + cl_assert(expected[idx].path == NULL); + + git_iterator_free(i); +} + +static void check_wd_first_through_third_range( + git_repository *repo, const char *start, const char *end) +{ + git_iterator *i; + const git_index_entry *entry; + int error, idx; + static const char *expected[] = { "FIRST", "second", "THIRD", NULL }; + + cl_git_pass(git_iterator_for_workdir( + &i, repo, GIT_ITERATOR_IGNORE_CASE, start, end)); + cl_git_pass(git_iterator_current(&entry, i)); + + for (idx = 0; entry != NULL; ++idx) { + cl_assert_equal_s(expected[idx], entry->path); + + error = git_iterator_advance(&entry, i); + cl_assert(!error || error == GIT_ITEROVER); + } + + cl_assert(expected[idx] == NULL); + + git_iterator_free(i); +} + +void test_diff_iterator__workdir_handles_icase_range(void) +{ + git_repository *repo; + + repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_remove_placeholders(git_repository_path(repo), "dummy-marker.txt"); + + cl_git_mkfile("empty_standard_repo/before", "whatever\n"); + cl_git_mkfile("empty_standard_repo/FIRST", "whatever\n"); + cl_git_mkfile("empty_standard_repo/second", "whatever\n"); + cl_git_mkfile("empty_standard_repo/THIRD", "whatever\n"); + cl_git_mkfile("empty_standard_repo/zafter", "whatever\n"); + cl_git_mkfile("empty_standard_repo/Zlast", "whatever\n"); + + check_wd_first_through_third_range(repo, "first", "third"); + check_wd_first_through_third_range(repo, "FIRST", "THIRD"); + check_wd_first_through_third_range(repo, "first", "THIRD"); + check_wd_first_through_third_range(repo, "FIRST", "third"); + check_wd_first_through_third_range(repo, "FirSt", "tHiRd"); +} + +static void check_tree_range( + git_repository *repo, + const char *start, + const char *end, + bool ignore_case, + int expected_count) +{ + git_tree *head; + git_iterator *i; + int error, count; + + cl_git_pass(git_repository_head_tree(&head, repo)); + + cl_git_pass(git_iterator_for_tree( + &i, head, + ignore_case ? GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE, + start, end)); + + for (count = 0; !(error = git_iterator_advance(NULL, i)); ++count) + /* count em up */; + + cl_assert_equal_i(GIT_ITEROVER, error); + cl_assert_equal_i(expected_count, count); + + git_iterator_free(i); + git_tree_free(head); +} + +void test_diff_iterator__tree_handles_icase_range(void) +{ + git_repository *repo; + + repo = cl_git_sandbox_init("testrepo"); + + check_tree_range(repo, "B", "C", false, 0); + check_tree_range(repo, "B", "C", true, 1); + check_tree_range(repo, "b", "c", false, 1); + check_tree_range(repo, "b", "c", true, 1); + + check_tree_range(repo, "a", "z", false, 3); + check_tree_range(repo, "a", "z", true, 4); + check_tree_range(repo, "A", "Z", false, 1); + check_tree_range(repo, "A", "Z", true, 4); + check_tree_range(repo, "a", "Z", false, 0); + check_tree_range(repo, "a", "Z", true, 4); + check_tree_range(repo, "A", "z", false, 4); + check_tree_range(repo, "A", "z", true, 4); + + check_tree_range(repo, "new.txt", "new.txt", true, 1); + check_tree_range(repo, "new.txt", "new.txt", false, 1); + check_tree_range(repo, "README", "README", true, 1); + check_tree_range(repo, "README", "README", false, 1); +} + +static void check_index_range( + git_repository *repo, + const char *start, + const char *end, + bool ignore_case, + int expected_count) +{ + git_index *index; + git_iterator *i; + int error, count, caps; + bool is_ignoring_case; + + cl_git_pass(git_repository_index(&index, repo)); + + caps = git_index_caps(index); + is_ignoring_case = ((caps & GIT_INDEXCAP_IGNORE_CASE) != 0); + + if (ignore_case != is_ignoring_case) + cl_git_pass(git_index_set_caps(index, caps ^ GIT_INDEXCAP_IGNORE_CASE)); + + cl_git_pass(git_iterator_for_index(&i, index, 0, start, end)); + + cl_assert(git_iterator_ignore_case(i) == ignore_case); + + for (count = 0; !(error = git_iterator_advance(NULL, i)); ++count) + /* count em up */; + + cl_assert_equal_i(GIT_ITEROVER, error); + cl_assert_equal_i(expected_count, count); + + git_iterator_free(i); + git_index_free(index); +} + +void test_diff_iterator__index_handles_icase_range(void) +{ + git_repository *repo; + git_index *index; + git_tree *head; + + repo = cl_git_sandbox_init("testrepo"); + + /* reset index to match HEAD */ + cl_git_pass(git_repository_head_tree(&head, repo)); + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_read_tree(index, head)); + cl_git_pass(git_index_write(index)); + git_tree_free(head); + git_index_free(index); + + /* do some ranged iterator checks toggling case sensitivity */ + check_index_range(repo, "B", "C", false, 0); + check_index_range(repo, "B", "C", true, 1); + check_index_range(repo, "a", "z", false, 3); + check_index_range(repo, "a", "z", true, 4); +} diff --git a/tests/diff/notify.c b/tests/diff/notify.c new file mode 100644 index 000000000..cc33cb71c --- /dev/null +++ b/tests/diff/notify.c @@ -0,0 +1,228 @@ +#include "clar_libgit2.h" +#include "diff_helpers.h" + +static git_repository *g_repo = NULL; + +void test_diff_notify__initialize(void) +{ +} + +void test_diff_notify__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static int assert_called_notifications( + const git_diff *diff_so_far, + const git_diff_delta *delta_to_add, + const char *matched_pathspec, + void *payload) +{ + bool found = false; + notify_expected *exp = (notify_expected*)payload; + notify_expected *e;; + + GIT_UNUSED(diff_so_far); + + for (e = exp; e->path != NULL; e++) { + if (strcmp(e->path, delta_to_add->new_file.path)) + continue; + + cl_assert_equal_s(e->matched_pathspec, matched_pathspec); + + found = true; + break; + } + + cl_assert(found); + return 0; +} + +static void test_notify( + char **searched_pathspecs, + int pathspecs_count, + notify_expected *expected_matched_pathspecs, + int expected_diffed_files_count) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + diff_expects exp; + + g_repo = cl_git_sandbox_init("status"); + + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + opts.notify_cb = assert_called_notifications; + opts.pathspec.strings = searched_pathspecs; + opts.pathspec.count = pathspecs_count; + + opts.notify_payload = expected_matched_pathspecs; + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(expected_diffed_files_count, exp.files); + + git_diff_free(diff); +} + +void test_diff_notify__notify_single_pathspec(void) +{ + char *searched_pathspecs[] = { + "*_deleted", + }; + notify_expected expected_matched_pathspecs[] = { + { "file_deleted", "*_deleted" }, + { "staged_changes_file_deleted", "*_deleted" }, + { NULL, NULL } + }; + + test_notify(searched_pathspecs, 1, expected_matched_pathspecs, 2); +} + +void test_diff_notify__notify_multiple_pathspec(void) +{ + char *searched_pathspecs[] = { + "staged_changes_cant_find_me", + "subdir/modified_cant_find_me", + "subdir/*", + "staged*" + }; + notify_expected expected_matched_pathspecs[] = { + { "staged_changes_file_deleted", "staged*" }, + { "staged_changes_modified_file", "staged*" }, + { "staged_delete_modified_file", "staged*" }, + { "staged_new_file_deleted_file", "staged*" }, + { "staged_new_file_modified_file", "staged*" }, + { "subdir/deleted_file", "subdir/*" }, + { "subdir/modified_file", "subdir/*" }, + { "subdir/new_file", "subdir/*" }, + { NULL, NULL } + }; + + test_notify(searched_pathspecs, 4, expected_matched_pathspecs, 8); +} + +void test_diff_notify__notify_catchall_with_empty_pathspecs(void) +{ + char *searched_pathspecs[] = { + "", + "" + }; + notify_expected expected_matched_pathspecs[] = { + { "file_deleted", NULL }, + { "ignored_file", NULL }, + { "modified_file", NULL }, + { "new_file", NULL }, + { "\xe8\xbf\x99", NULL }, + { "staged_changes_file_deleted", NULL }, + { "staged_changes_modified_file", NULL }, + { "staged_delete_modified_file", NULL }, + { "staged_new_file_deleted_file", NULL }, + { "staged_new_file_modified_file", NULL }, + { "subdir/deleted_file", NULL }, + { "subdir/modified_file", NULL }, + { "subdir/new_file", NULL }, + { NULL, NULL } + }; + + test_notify(searched_pathspecs, 1, expected_matched_pathspecs, 13); +} + +void test_diff_notify__notify_catchall(void) +{ + char *searched_pathspecs[] = { + "*", + }; + notify_expected expected_matched_pathspecs[] = { + { "file_deleted", "*" }, + { "ignored_file", "*" }, + { "modified_file", "*" }, + { "new_file", "*" }, + { "\xe8\xbf\x99", "*" }, + { "staged_changes_file_deleted", "*" }, + { "staged_changes_modified_file", "*" }, + { "staged_delete_modified_file", "*" }, + { "staged_new_file_deleted_file", "*" }, + { "staged_new_file_modified_file", "*" }, + { "subdir/deleted_file", "*" }, + { "subdir/modified_file", "*" }, + { "subdir/new_file", "*" }, + { NULL, NULL } + }; + + test_notify(searched_pathspecs, 1, expected_matched_pathspecs, 13); +} + +static int abort_diff( + const git_diff *diff_so_far, + const git_diff_delta *delta_to_add, + const char *matched_pathspec, + void *payload) +{ + GIT_UNUSED(diff_so_far); + GIT_UNUSED(delta_to_add); + GIT_UNUSED(matched_pathspec); + GIT_UNUSED(payload); + + return -42; +} + +void test_diff_notify__notify_cb_can_abort_diff(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + char *pathspec = NULL; + + g_repo = cl_git_sandbox_init("status"); + + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + opts.notify_cb = abort_diff; + opts.pathspec.strings = &pathspec; + opts.pathspec.count = 1; + + pathspec = "file_deleted"; + cl_git_fail(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + pathspec = "staged_changes_modified_file"; + cl_git_fail(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); +} + +static int filter_all( + const git_diff *diff_so_far, + const git_diff_delta *delta_to_add, + const char *matched_pathspec, + void *payload) +{ + GIT_UNUSED(diff_so_far); + GIT_UNUSED(delta_to_add); + GIT_UNUSED(matched_pathspec); + GIT_UNUSED(payload); + + return 42; +} + +void test_diff_notify__notify_cb_can_be_used_as_filtering_function(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + char *pathspec = NULL; + diff_expects exp; + + g_repo = cl_git_sandbox_init("status"); + + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + opts.notify_cb = filter_all; + opts.pathspec.strings = &pathspec; + opts.pathspec.count = 1; + + pathspec = "*_deleted"; + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(0, exp.files); + + git_diff_free(diff); +} diff --git a/tests/diff/patch.c b/tests/diff/patch.c new file mode 100644 index 000000000..366e5da58 --- /dev/null +++ b/tests/diff/patch.c @@ -0,0 +1,571 @@ +#include "clar_libgit2.h" +#include "git2/sys/repository.h" + +#include "diff_helpers.h" +#include "repository.h" +#include "buf_text.h" + +static git_repository *g_repo = NULL; + +void test_diff_patch__initialize(void) +{ +} + +void test_diff_patch__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +#define EXPECTED_HEADER "diff --git a/subdir.txt b/subdir.txt\n" \ + "deleted file mode 100644\n" \ + "index e8ee89e..0000000\n" \ + "--- a/subdir.txt\n" \ + "+++ /dev/null\n" + +#define EXPECTED_HUNK "@@ -1,2 +0,0 @@\n" + +static int check_removal_cb( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + const git_diff_line *line, + void *payload) +{ + GIT_UNUSED(payload); + + switch (line->origin) { + case GIT_DIFF_LINE_FILE_HDR: + cl_assert_equal_s(EXPECTED_HEADER, line->content); + cl_assert(hunk == NULL); + goto check_delta; + + case GIT_DIFF_LINE_HUNK_HDR: + cl_assert_equal_s(EXPECTED_HUNK, line->content); + /* Fall through */ + + case GIT_DIFF_LINE_CONTEXT: + case GIT_DIFF_LINE_DELETION: + goto check_hunk; + + default: + /* unexpected code path */ + return -1; + } + +check_hunk: + cl_assert(hunk != NULL); + cl_assert_equal_i(1, hunk->old_start); + cl_assert_equal_i(2, hunk->old_lines); + cl_assert_equal_i(0, hunk->new_start); + cl_assert_equal_i(0, hunk->new_lines); + +check_delta: + cl_assert_equal_s("subdir.txt", delta->old_file.path); + cl_assert_equal_s("subdir.txt", delta->new_file.path); + cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); + + return 0; +} + +void test_diff_patch__can_properly_display_the_removal_of_a_file(void) +{ + /* + * $ git diff 26a125e..735b6a2 + * diff --git a/subdir.txt b/subdir.txt + * deleted file mode 100644 + * index e8ee89e..0000000 + * --- a/subdir.txt + * +++ /dev/null + * @@ -1,2 +0,0 @@ + * -Is it a bird? + * -Is it a plane? + */ + + const char *one_sha = "26a125e"; + const char *another_sha = "735b6a2"; + git_tree *one, *another; + git_diff *diff; + + g_repo = cl_git_sandbox_init("status"); + + one = resolve_commit_oid_to_tree(g_repo, one_sha); + another = resolve_commit_oid_to_tree(g_repo, another_sha); + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, one, another, NULL)); + + cl_git_pass(git_diff_print( + diff, GIT_DIFF_FORMAT_PATCH, check_removal_cb, NULL)); + + git_diff_free(diff); + + git_tree_free(another); + git_tree_free(one); +} + +void test_diff_patch__to_string(void) +{ + const char *one_sha = "26a125e"; + const char *another_sha = "735b6a2"; + git_tree *one, *another; + git_diff *diff; + git_patch *patch; + char *text; + const char *expected = "diff --git a/subdir.txt b/subdir.txt\ndeleted file mode 100644\nindex e8ee89e..0000000\n--- a/subdir.txt\n+++ /dev/null\n@@ -1,2 +0,0 @@\n-Is it a bird?\n-Is it a plane?\n"; + + g_repo = cl_git_sandbox_init("status"); + + one = resolve_commit_oid_to_tree(g_repo, one_sha); + another = resolve_commit_oid_to_tree(g_repo, another_sha); + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, one, another, NULL)); + + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + + cl_git_pass(git_patch_to_str(&text, patch)); + + cl_assert_equal_s(expected, text); + + cl_assert_equal_sz(31, git_patch_size(patch, 0, 0, 0)); + cl_assert_equal_sz(31, git_patch_size(patch, 1, 0, 0)); + cl_assert_equal_sz(31 + 16, git_patch_size(patch, 1, 1, 0)); + cl_assert_equal_sz(strlen(expected), git_patch_size(patch, 1, 1, 1)); + + git__free(text); + git_patch_free(patch); + git_diff_free(diff); + git_tree_free(another); + git_tree_free(one); +} + +void test_diff_patch__config_options(void) +{ + const char *one_sha = "26a125e"; /* current HEAD */ + git_tree *one; + git_config *cfg; + git_diff *diff; + git_patch *patch; + char *text; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + char *onefile = "staged_changes_modified_file"; + const char *expected1 = "diff --git c/staged_changes_modified_file i/staged_changes_modified_file\nindex 70bd944..906ee77 100644\n--- c/staged_changes_modified_file\n+++ i/staged_changes_modified_file\n@@ -1 +1,2 @@\n staged_changes_modified_file\n+staged_changes_modified_file\n"; + const char *expected2 = "diff --git i/staged_changes_modified_file w/staged_changes_modified_file\nindex 906ee77..011c344 100644\n--- i/staged_changes_modified_file\n+++ w/staged_changes_modified_file\n@@ -1,2 +1,3 @@\n staged_changes_modified_file\n staged_changes_modified_file\n+staged_changes_modified_file\n"; + const char *expected3 = "diff --git staged_changes_modified_file staged_changes_modified_file\nindex 906ee77..011c344 100644\n--- staged_changes_modified_file\n+++ staged_changes_modified_file\n@@ -1,2 +1,3 @@\n staged_changes_modified_file\n staged_changes_modified_file\n+staged_changes_modified_file\n"; + const char *expected4 = "diff --git staged_changes_modified_file staged_changes_modified_file\nindex 70bd9443ada0..906ee7711f4f 100644\n--- staged_changes_modified_file\n+++ staged_changes_modified_file\n@@ -1 +1,2 @@\n staged_changes_modified_file\n+staged_changes_modified_file\n"; + + g_repo = cl_git_sandbox_init("status"); + cl_git_pass(git_repository_config(&cfg, g_repo)); + one = resolve_commit_oid_to_tree(g_repo, one_sha); + opts.pathspec.count = 1; + opts.pathspec.strings = &onefile; + + + cl_git_pass(git_config_set_string(cfg, "diff.mnemonicprefix", "true")); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, one, NULL, &opts)); + + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); + cl_assert_equal_s(expected1, text); + + git__free(text); + git_patch_free(patch); + git_diff_free(diff); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); + cl_assert_equal_s(expected2, text); + + git__free(text); + git_patch_free(patch); + git_diff_free(diff); + + + cl_git_pass(git_config_set_string(cfg, "diff.noprefix", "true")); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); + cl_assert_equal_s(expected3, text); + + git__free(text); + git_patch_free(patch); + git_diff_free(diff); + + + cl_git_pass(git_config_set_int32(cfg, "core.abbrev", 12)); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, one, NULL, &opts)); + + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&text, patch)); + cl_assert_equal_s(expected4, text); + + git__free(text); + git_patch_free(patch); + git_diff_free(diff); + + git_tree_free(one); + git_config_free(cfg); +} + +void test_diff_patch__hunks_have_correct_line_numbers(void) +{ + git_config *cfg; + git_tree *head; + git_diff_options opt = GIT_DIFF_OPTIONS_INIT; + git_diff *diff; + git_patch *patch; + const git_diff_delta *delta; + const git_diff_hunk *hunk; + const git_diff_line *line; + size_t hunklen; + git_buf old_content = GIT_BUF_INIT, actual = GIT_BUF_INIT; + const char *new_content = "The Song of Seven Cities\n------------------------\n\nI WAS Lord of Cities very sumptuously builded.\nSeven roaring Cities paid me tribute from afar.\nIvory their outposts were--the guardrooms of them gilded,\nAnd garrisoned with Amazons invincible in war.\n\nThis is some new text;\nNot as good as the old text;\nBut here it is.\n\nSo they warred and trafficked only yesterday, my Cities.\nTo-day there is no mark or mound of where my Cities stood.\nFor the River rose at midnight and it washed away my Cities.\nThey are evened with Atlantis and the towns before the Flood.\n\nRain on rain-gorged channels raised the water-levels round them,\nFreshet backed on freshet swelled and swept their world from sight,\nTill the emboldened floods linked arms and, flashing forward, drowned them--\nDrowned my Seven Cities and their peoples in one night!\n\nLow among the alders lie their derelict foundations,\nThe beams wherein they trusted and the plinths whereon they built--\nMy rulers and their treasure and their unborn populations,\nDead, destroyed, aborted, and defiled with mud and silt!\n\nAnother replacement;\nBreaking up the poem;\nGenerating some hunks.\n\nTo the sound of trumpets shall their seed restore my Cities\nWealthy and well-weaponed, that once more may I behold\nAll the world go softly when it walks before my Cities,\nAnd the horses and the chariots fleeing from them as of old!\n\n -- Rudyard Kipling\n"; + + g_repo = cl_git_sandbox_init("renames"); + + cl_git_pass(git_config_new(&cfg)); + git_repository_set_config(g_repo, cfg); + git_config_free(cfg); + + git_repository_reinit_filesystem(g_repo, false); + + cl_git_pass( + git_futils_readbuffer(&old_content, "renames/songof7cities.txt")); + + cl_git_rewritefile("renames/songof7cities.txt", new_content); + + cl_git_pass(git_repository_head_tree(&head, g_repo)); + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, head, &opt)); + + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_assert((delta = git_patch_get_delta(patch)) != NULL); + + cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); + cl_assert_equal_i(2, (int)git_patch_num_hunks(patch)); + + /* check hunk 0 */ + + cl_git_pass( + git_patch_get_hunk(&hunk, &hunklen, patch, 0)); + + cl_assert_equal_i(18, (int)hunklen); + + cl_assert_equal_i(6, (int)hunk->old_start); + cl_assert_equal_i(15, (int)hunk->old_lines); + cl_assert_equal_i(6, (int)hunk->new_start); + cl_assert_equal_i(9, (int)hunk->new_lines); + + cl_assert_equal_i(18, (int)git_patch_num_lines_in_hunk(patch, 0)); + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 0)); + cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); + cl_assert_equal_s("Ivory their outposts were--the guardrooms of them gilded,\n", actual.ptr); + cl_assert_equal_i(6, line->old_lineno); + cl_assert_equal_i(6, line->new_lineno); + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 3)); + cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); + cl_assert_equal_s("All the world went softly when it walked before my Cities--\n", actual.ptr); + cl_assert_equal_i(9, line->old_lineno); + cl_assert_equal_i(-1, line->new_lineno); + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 12)); + cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); + cl_assert_equal_s("This is some new text;\n", actual.ptr); + cl_assert_equal_i(-1, line->old_lineno); + cl_assert_equal_i(9, line->new_lineno); + + /* check hunk 1 */ + + cl_git_pass(git_patch_get_hunk(&hunk, &hunklen, patch, 1)); + + cl_assert_equal_i(18, (int)hunklen); + + cl_assert_equal_i(31, (int)hunk->old_start); + cl_assert_equal_i(15, (int)hunk->old_lines); + cl_assert_equal_i(25, (int)hunk->new_start); + cl_assert_equal_i(9, (int)hunk->new_lines); + + cl_assert_equal_i(18, (int)git_patch_num_lines_in_hunk(patch, 1)); + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 0)); + cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); + cl_assert_equal_s("My rulers and their treasure and their unborn populations,\n", actual.ptr); + cl_assert_equal_i(31, line->old_lineno); + cl_assert_equal_i(25, line->new_lineno); + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 3)); + cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); + cl_assert_equal_s("The Daughters of the Palace whom they cherished in my Cities,\n", actual.ptr); + cl_assert_equal_i(34, line->old_lineno); + cl_assert_equal_i(-1, line->new_lineno); + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 12)); + cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); + cl_assert_equal_s("Another replacement;\n", actual.ptr); + cl_assert_equal_i(-1, line->old_lineno); + cl_assert_equal_i(28, line->new_lineno); + + git_patch_free(patch); + git_diff_free(diff); + + /* Let's check line numbers when there is no newline */ + + git_buf_rtrim(&old_content); + cl_git_rewritefile("renames/songof7cities.txt", old_content.ptr); + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, head, &opt)); + + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_assert((delta = git_patch_get_delta(patch)) != NULL); + + cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); + cl_assert_equal_i(1, (int)git_patch_num_hunks(patch)); + + /* check hunk 0 */ + + cl_git_pass(git_patch_get_hunk(&hunk, &hunklen, patch, 0)); + + cl_assert_equal_i(6, (int)hunklen); + + cl_assert_equal_i(46, (int)hunk->old_start); + cl_assert_equal_i(4, (int)hunk->old_lines); + cl_assert_equal_i(46, (int)hunk->new_start); + cl_assert_equal_i(4, (int)hunk->new_lines); + + cl_assert_equal_i(6, (int)git_patch_num_lines_in_hunk(patch, 0)); + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 1)); + cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); + cl_assert_equal_s("And the horses and the chariots fleeing from them as of old!\n", actual.ptr); + cl_assert_equal_i(47, line->old_lineno); + cl_assert_equal_i(47, line->new_lineno); + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 2)); + cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); + cl_assert_equal_s("\n", actual.ptr); + cl_assert_equal_i(48, line->old_lineno); + cl_assert_equal_i(48, line->new_lineno); + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 3)); + cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); + cl_assert_equal_s(" -- Rudyard Kipling\n", actual.ptr); + cl_assert_equal_i(49, line->old_lineno); + cl_assert_equal_i(-1, line->new_lineno); + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 4)); + cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); + cl_assert_equal_s(" -- Rudyard Kipling", actual.ptr); + cl_assert_equal_i(-1, line->old_lineno); + cl_assert_equal_i(49, line->new_lineno); + + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 5)); + cl_assert_equal_i(GIT_DIFF_LINE_DEL_EOFNL, (int)line->origin); + cl_git_pass(git_buf_set(&actual, line->content, line->content_len)); + cl_assert_equal_s("\n\\ No newline at end of file\n", actual.ptr); + cl_assert_equal_i(-1, line->old_lineno); + cl_assert_equal_i(49, line->new_lineno); + + git_patch_free(patch); + git_diff_free(diff); + + git_buf_free(&actual); + git_buf_free(&old_content); + git_tree_free(head); +} + +static void check_single_patch_stats( + git_repository *repo, size_t hunks, + size_t adds, size_t dels, size_t ctxt, size_t *sizes, + const char *expected) +{ + git_diff *diff; + git_patch *patch; + const git_diff_delta *delta; + size_t actual_ctxt, actual_adds, actual_dels; + + cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL)); + + cl_assert_equal_i(1, (int)git_diff_num_deltas(diff)); + + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_assert((delta = git_patch_get_delta(patch)) != NULL); + cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); + + cl_assert_equal_i((int)hunks, (int)git_patch_num_hunks(patch)); + + cl_git_pass( git_patch_line_stats( + &actual_ctxt, &actual_adds, &actual_dels, patch) ); + + cl_assert_equal_sz(ctxt, actual_ctxt); + cl_assert_equal_sz(adds, actual_adds); + cl_assert_equal_sz(dels, actual_dels); + + if (expected != NULL) { + char *text; + cl_git_pass(git_patch_to_str(&text, patch)); + cl_assert_equal_s(expected, text); + git__free(text); + + cl_assert_equal_sz( + strlen(expected), git_patch_size(patch, 1, 1, 1)); + } + + if (sizes) { + if (sizes[0]) + cl_assert_equal_sz(sizes[0], git_patch_size(patch, 0, 0, 0)); + if (sizes[1]) + cl_assert_equal_sz(sizes[1], git_patch_size(patch, 1, 0, 0)); + if (sizes[2]) + cl_assert_equal_sz(sizes[2], git_patch_size(patch, 1, 1, 0)); + } + + /* walk lines in hunk with basic sanity checks */ + for (; hunks > 0; --hunks) { + size_t i, max_i; + const git_diff_line *line; + int last_new_lineno = -1, last_old_lineno = -1; + + max_i = git_patch_num_lines_in_hunk(patch, hunks - 1); + + for (i = 0; i < max_i; ++i) { + int expected = 1; + + cl_git_pass( + git_patch_get_line_in_hunk(&line, patch, hunks - 1, i)); + + if (line->origin == GIT_DIFF_LINE_ADD_EOFNL || + line->origin == GIT_DIFF_LINE_DEL_EOFNL || + line->origin == GIT_DIFF_LINE_CONTEXT_EOFNL) + expected = 0; + + if (line->old_lineno >= 0) { + if (last_old_lineno >= 0) + cl_assert_equal_i( + expected, line->old_lineno - last_old_lineno); + last_old_lineno = line->old_lineno; + } + + if (line->new_lineno >= 0) { + if (last_new_lineno >= 0) + cl_assert_equal_i( + expected, line->new_lineno - last_new_lineno); + last_new_lineno = line->new_lineno; + } + } + } + + git_patch_free(patch); + git_diff_free(diff); +} + +void test_diff_patch__line_counts_with_eofnl(void) +{ + git_config *cfg; + git_buf content = GIT_BUF_INIT; + const char *end; + git_index *index; + const char *expected = + /* below is pasted output of 'git diff' with fn context removed */ + "diff --git a/songof7cities.txt b/songof7cities.txt\n" + "index 378a7d9..3d0154e 100644\n" + "--- a/songof7cities.txt\n" + "+++ b/songof7cities.txt\n" + "@@ -42,7 +42,7 @@ With peoples undefeated of the dark, enduring blood.\n" + " \n" + " To the sound of trumpets shall their seed restore my Cities\n" + " Wealthy and well-weaponed, that once more may I behold\n" + "-All the world go softly when it walks before my Cities,\n" + "+#All the world go softly when it walks before my Cities,\n" + " And the horses and the chariots fleeing from them as of old!\n" + " \n" + " -- Rudyard Kipling\n" + "\\ No newline at end of file\n"; + size_t expected_sizes[3] = { 115, 119 + 115 + 114, 119 + 115 + 114 + 71 }; + + g_repo = cl_git_sandbox_init("renames"); + + cl_git_pass(git_config_new(&cfg)); + git_repository_set_config(g_repo, cfg); + git_config_free(cfg); + + git_repository_reinit_filesystem(g_repo, false); + + cl_git_pass(git_futils_readbuffer(&content, "renames/songof7cities.txt")); + + /* remove first line */ + + end = git_buf_cstr(&content) + git_buf_find(&content, '\n') + 1; + git_buf_consume(&content, end); + cl_git_rewritefile("renames/songof7cities.txt", content.ptr); + + check_single_patch_stats(g_repo, 1, 0, 1, 3, NULL, NULL); + + /* remove trailing whitespace */ + + git_buf_rtrim(&content); + cl_git_rewritefile("renames/songof7cities.txt", content.ptr); + + check_single_patch_stats(g_repo, 2, 1, 2, 6, NULL, NULL); + + /* add trailing whitespace */ + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); + cl_git_pass(git_index_write(index)); + git_index_free(index); + + cl_git_pass(git_buf_putc(&content, '\n')); + cl_git_rewritefile("renames/songof7cities.txt", content.ptr); + + check_single_patch_stats(g_repo, 1, 1, 1, 3, NULL, NULL); + + /* no trailing whitespace as context line */ + + { + /* walk back a couple lines, make space and insert char */ + char *scan = content.ptr + content.size; + int i; + + for (i = 0; i < 5; ++i) { + for (--scan; scan > content.ptr && *scan != '\n'; --scan) + /* seek to prev \n */; + } + cl_assert(scan > content.ptr); + + /* overwrite trailing \n with right-shifted content */ + memmove(scan + 1, scan, content.size - (scan - content.ptr) - 1); + /* insert '#' char into space we created */ + scan[1] = '#'; + } + cl_git_rewritefile("renames/songof7cities.txt", content.ptr); + + check_single_patch_stats( + g_repo, 1, 1, 1, 6, expected_sizes, expected); + + git_buf_free(&content); +} diff --git a/tests/diff/pathspec.c b/tests/diff/pathspec.c new file mode 100644 index 000000000..5761d2d2b --- /dev/null +++ b/tests/diff/pathspec.c @@ -0,0 +1,93 @@ +#include "clar_libgit2.h" +#include "diff_helpers.h" + +static git_repository *g_repo = NULL; + +void test_diff_pathspec__initialize(void) +{ + g_repo = cl_git_sandbox_init("status"); +} + +void test_diff_pathspec__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_diff_pathspec__0(void) +{ + const char *a_commit = "26a125ee"; /* the current HEAD */ + const char *b_commit = "0017bd4a"; /* the start */ + git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); + git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit); + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_strarray paths = { NULL, 1 }; + char *path; + git_pathspec *ps; + git_pathspec_match_list *matches; + + cl_assert(a); + cl_assert(b); + + path = "*_file"; + paths.strings = &path; + cl_git_pass(git_pathspec_new(&ps, &paths)); + + cl_git_pass(git_pathspec_match_tree(&matches, a, GIT_PATHSPEC_DEFAULT, ps)); + cl_assert_equal_i(7, (int)git_pathspec_match_list_entrycount(matches)); + cl_assert_equal_s("current_file", git_pathspec_match_list_entry(matches,0)); + cl_assert(git_pathspec_match_list_diff_entry(matches,0) == NULL); + git_pathspec_match_list_free(matches); + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, NULL, a, &opts)); + + cl_git_pass(git_pathspec_match_diff( + &matches, diff, GIT_PATHSPEC_DEFAULT, ps)); + cl_assert_equal_i(7, (int)git_pathspec_match_list_entrycount(matches)); + cl_assert(git_pathspec_match_list_diff_entry(matches, 0) != NULL); + cl_assert(git_pathspec_match_list_entry(matches, 0) == NULL); + cl_assert_equal_s("current_file", + git_pathspec_match_list_diff_entry(matches,0)->new_file.path); + cl_assert_equal_i(GIT_DELTA_ADDED, + (int)git_pathspec_match_list_diff_entry(matches,0)->status); + git_pathspec_match_list_free(matches); + + git_diff_free(diff); + diff = NULL; + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); + + cl_git_pass(git_pathspec_match_diff( + &matches, diff, GIT_PATHSPEC_DEFAULT, ps)); + cl_assert_equal_i(3, (int)git_pathspec_match_list_entrycount(matches)); + cl_assert(git_pathspec_match_list_diff_entry(matches, 0) != NULL); + cl_assert(git_pathspec_match_list_entry(matches, 0) == NULL); + cl_assert_equal_s("subdir/current_file", + git_pathspec_match_list_diff_entry(matches,0)->new_file.path); + cl_assert_equal_i(GIT_DELTA_DELETED, + (int)git_pathspec_match_list_diff_entry(matches,0)->status); + git_pathspec_match_list_free(matches); + + git_diff_free(diff); + diff = NULL; + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); + + cl_git_pass(git_pathspec_match_diff( + &matches, diff, GIT_PATHSPEC_DEFAULT, ps)); + cl_assert_equal_i(4, (int)git_pathspec_match_list_entrycount(matches)); + cl_assert(git_pathspec_match_list_diff_entry(matches, 0) != NULL); + cl_assert(git_pathspec_match_list_entry(matches, 0) == NULL); + cl_assert_equal_s("modified_file", + git_pathspec_match_list_diff_entry(matches,0)->new_file.path); + cl_assert_equal_i(GIT_DELTA_MODIFIED, + (int)git_pathspec_match_list_diff_entry(matches,0)->status); + git_pathspec_match_list_free(matches); + + git_diff_free(diff); + diff = NULL; + + git_tree_free(a); + git_tree_free(b); + git_pathspec_free(ps); +} diff --git a/tests/diff/rename.c b/tests/diff/rename.c new file mode 100644 index 000000000..42bb65aa8 --- /dev/null +++ b/tests/diff/rename.c @@ -0,0 +1,1286 @@ +#include "clar_libgit2.h" +#include "diff_helpers.h" +#include "buf_text.h" + +static git_repository *g_repo = NULL; + +void test_diff_rename__initialize(void) +{ + g_repo = cl_git_sandbox_init("renames"); + + cl_repo_set_bool(g_repo, "core.autocrlf", false); +} + +void test_diff_rename__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +/* + * Renames repo has: + * + * commit 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 - + * serving.txt (25 lines) + * sevencities.txt (50 lines) + * commit 2bc7f351d20b53f1c72c16c4b036e491c478c49a - + * serving.txt -> sixserving.txt (rename, no change, 100% match) + * sevencities.txt -> sevencities.txt (no change) + * sevencities.txt -> songofseven.txt (copy, no change, 100% match) + * commit 1c068dee5790ef1580cfc4cd670915b48d790084 + * songofseven.txt -> songofseven.txt (major rewrite, <20% match - split) + * sixserving.txt -> sixserving.txt (indentation change) + * sixserving.txt -> ikeepsix.txt (copy, add title, >80% match) + * sevencities.txt (no change) + * commit 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 + * songofseven.txt -> untimely.txt (rename, convert to crlf) + * ikeepsix.txt -> ikeepsix.txt (reorder sections in file) + * sixserving.txt -> sixserving.txt (whitespace change - not just indent) + * sevencities.txt -> songof7cities.txt (rename, small text changes) + */ + +void test_diff_rename__match_oid(void) +{ + const char *old_sha = "31e47d8c1fa36d7f8d537b96158e3f024de0a9f2"; + const char *new_sha = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; + git_tree *old_tree, *new_tree; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + diff_expects exp; + + old_tree = resolve_commit_oid_to_tree(g_repo, old_sha); + new_tree = resolve_commit_oid_to_tree(g_repo, new_sha); + + /* Must pass GIT_DIFF_INCLUDE_UNMODIFIED if you expect to emulate + * --find-copies-harder during rename transformion... + */ + diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; + + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, old_tree, new_tree, &diffopts)); + + /* git diff --no-renames \ + * 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 \ + * 2bc7f351d20b53f1c72c16c4b036e491c478c49a + */ + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + + /* git diff 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 \ + * 2bc7f351d20b53f1c72c16c4b036e491c478c49a + * don't use NULL opts to avoid config `diff.renames` contamination + */ + opts.flags = GIT_DIFF_FIND_RENAMES; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(3, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + + git_diff_free(diff); + + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, old_tree, new_tree, &diffopts)); + + /* git diff --find-copies-harder \ + * 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 \ + * 2bc7f351d20b53f1c72c16c4b036e491c478c49a + */ + opts.flags = GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(3, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + + git_diff_free(diff); + + git_tree_free(old_tree); + git_tree_free(new_tree); +} + +void test_diff_rename__checks_options_version(void) +{ + const char *old_sha = "31e47d8c1fa36d7f8d537b96158e3f024de0a9f2"; + const char *new_sha = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; + git_tree *old_tree, *new_tree; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + const git_error *err; + + old_tree = resolve_commit_oid_to_tree(g_repo, old_sha); + new_tree = resolve_commit_oid_to_tree(g_repo, new_sha); + diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, old_tree, new_tree, &diffopts)); + + opts.version = 0; + cl_git_fail(git_diff_find_similar(diff, &opts)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); + + giterr_clear(); + opts.version = 1024; + cl_git_fail(git_diff_find_similar(diff, &opts)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); + + git_diff_free(diff); + git_tree_free(old_tree); + git_tree_free(new_tree); +} + +void test_diff_rename__not_exact_match(void) +{ + const char *sha0 = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; + const char *sha1 = "1c068dee5790ef1580cfc4cd670915b48d790084"; + const char *sha2 = "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13"; + git_tree *old_tree, *new_tree; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + diff_expects exp; + + /* == Changes ===================================================== + * songofseven.txt -> songofseven.txt (major rewrite, <20% match - split) + * sixserving.txt -> sixserving.txt (indentation change) + * sixserving.txt -> ikeepsix.txt (copy, add title, >80% match) + * sevencities.txt (no change) + */ + + old_tree = resolve_commit_oid_to_tree(g_repo, sha0); + new_tree = resolve_commit_oid_to_tree(g_repo, sha1); + + /* Must pass GIT_DIFF_INCLUDE_UNMODIFIED if you expect to emulate + * --find-copies-harder during rename transformion... + */ + diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; + + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, old_tree, new_tree, &diffopts)); + + /* git diff --no-renames \ + * 2bc7f351d20b53f1c72c16c4b036e491c478c49a \ + * 1c068dee5790ef1580cfc4cd670915b48d790084 + */ + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); + + /* git diff -M 2bc7f351d20b53f1c72c16c4b036e491c478c49a \ + * 1c068dee5790ef1580cfc4cd670915b48d790084 + * + * must not pass NULL for opts because it will pick up environment + * values for "diff.renames" and test won't be consistent. + */ + opts.flags = GIT_DIFF_FIND_RENAMES; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); + + git_diff_free(diff); + + /* git diff -M -C \ + * 2bc7f351d20b53f1c72c16c4b036e491c478c49a \ + * 1c068dee5790ef1580cfc4cd670915b48d790084 + */ + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, old_tree, new_tree, &diffopts)); + + opts.flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]); + + git_diff_free(diff); + + /* git diff -M -C --find-copies-harder --break-rewrites \ + * 2bc7f351d20b53f1c72c16c4b036e491c478c49a \ + * 1c068dee5790ef1580cfc4cd670915b48d790084 + */ + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, old_tree, new_tree, &diffopts)); + + opts.flags = GIT_DIFF_FIND_ALL; + opts.break_rewrite_threshold = 70; + + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(5, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNMODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_COPIED]); + + git_diff_free(diff); + + /* == Changes ===================================================== + * songofseven.txt -> untimely.txt (rename, convert to crlf) + * ikeepsix.txt -> ikeepsix.txt (reorder sections in file) + * sixserving.txt -> sixserving.txt (whitespace - not just indent) + * sevencities.txt -> songof7cities.txt (rename, small text changes) + */ + + git_tree_free(old_tree); + old_tree = new_tree; + new_tree = resolve_commit_oid_to_tree(g_repo, sha2); + + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, old_tree, new_tree, &diffopts)); + + /* git diff --no-renames \ + * 1c068dee5790ef1580cfc4cd670915b48d790084 \ + * 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 + */ + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(6, exp.files); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); + git_diff_free(diff); + + /* git diff -M -C \ + * 1c068dee5790ef1580cfc4cd670915b48d790084 \ + * 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 + */ + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, old_tree, new_tree, &diffopts)); + + opts.flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); + + git_diff_free(diff); + + /* git diff -M -C --find-copies-harder --break-rewrites \ + * 1c068dee5790ef1580cfc4cd670915b48d790084 \ + * 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 + * with libgit2 default similarity comparison... + */ + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, old_tree, new_tree, &diffopts)); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + /* the default match algorithm is going to find the internal + * whitespace differences in the lines of sixserving.txt to be + * significant enough that this will decide to split it into an ADD + * and a DELETE + */ + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(5, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); + + git_diff_free(diff); + + /* git diff -M -C --find-copies-harder --break-rewrites \ + * 1c068dee5790ef1580cfc4cd670915b48d790084 \ + * 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 + * with ignore_space whitespace comparision + */ + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, old_tree, new_tree, &diffopts)); + + opts.flags = GIT_DIFF_FIND_ALL | GIT_DIFF_FIND_IGNORE_WHITESPACE; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + /* Ignoring whitespace, this should no longer split sixserver.txt */ + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); + + git_diff_free(diff); + + git_tree_free(old_tree); + git_tree_free(new_tree); +} + +void test_diff_rename__handles_small_files(void) +{ + const char *tree_sha = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; + git_index *index; + git_tree *tree; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + + cl_git_pass(git_repository_index(&index, g_repo)); + + tree = resolve_commit_oid_to_tree(g_repo, tree_sha); + + cl_git_rewritefile("renames/songof7cities.txt", "single line\n"); + cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); + + cl_git_rewritefile("renames/untimely.txt", "untimely\n"); + cl_git_pass(git_index_add_bypath(index, "untimely.txt")); + + /* Tests that we can invoke find_similar on small files + * and that the GIT_EBUFS (too small) error code is not + * propagated to the caller. + */ + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + opts.flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES | + GIT_DIFF_FIND_AND_BREAK_REWRITES; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + git_diff_free(diff); + git_tree_free(tree); + git_index_free(index); +} + +void test_diff_rename__working_directory_changes(void) +{ + const char *sha0 = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; + const char *blobsha = "66311f5cfbe7836c27510a3ba2f43e282e2c8bba"; + git_oid id; + git_tree *tree; + git_blob *blob; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + diff_expects exp; + git_buf old_content = GIT_BUF_INIT, content = GIT_BUF_INIT;; + + tree = resolve_commit_oid_to_tree(g_repo, sha0); + diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED | GIT_DIFF_INCLUDE_UNTRACKED; + + /* + $ git cat-file -p 2bc7f351d20b53f1c72c16c4b036e491c478c49a^{tree} + + 100644 blob 66311f5cfbe7836c27510a3ba2f43e282e2c8bba sevencities.txt + 100644 blob ad0a8e55a104ac54a8a29ed4b84b49e76837a113 sixserving.txt + 100644 blob 66311f5cfbe7836c27510a3ba2f43e282e2c8bba songofseven.txt + + $ for f in *.txt; do + echo `git hash-object -t blob $f` $f + done + + eaf4a3e3bfe68585e90cada20736ace491cd100b ikeepsix.txt + f90d4fc20ecddf21eebe6a37e9225d244339d2b5 sixserving.txt + 4210ffd5c390b21dd5483375e75288dea9ede512 songof7cities.txt + 9a69d960ae94b060f56c2a8702545e2bb1abb935 untimely.txt + */ + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &diffopts)); + + /* git diff --no-renames 2bc7f351d20b53f1c72c16c4b036e491c478c49a */ + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(6, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); + + /* git diff -M 2bc7f351d20b53f1c72c16c4b036e491c478c49a */ + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(5, exp.files); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + + /* rewrite files in the working directory with / without CRLF changes */ + + cl_git_pass( + git_futils_readbuffer(&old_content, "renames/songof7cities.txt")); + cl_git_pass( + git_buf_text_lf_to_crlf(&content, &old_content)); + cl_git_pass( + git_futils_writebuffer(&content, "renames/songof7cities.txt", 0, 0)); + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &diffopts)); + + /* git diff -M 2bc7f351d20b53f1c72c16c4b036e491c478c49a */ + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(5, exp.files); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + + /* try a different whitespace option */ + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &diffopts)); + + opts.flags = GIT_DIFF_FIND_ALL | GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE; + opts.rename_threshold = 70; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(6, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + + /* try a different matching option */ + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &diffopts)); + + opts.flags = GIT_DIFF_FIND_ALL | GIT_DIFF_FIND_EXACT_MATCH_ONLY; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(6, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); + + git_diff_free(diff); + + /* again with exact match blob */ + + cl_git_pass(git_oid_fromstr(&id, blobsha)); + cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); + cl_git_pass(git_buf_set( + &content, git_blob_rawcontent(blob), (size_t)git_blob_rawsize(blob))); + cl_git_rewritefile("renames/songof7cities.txt", content.ptr); + git_blob_free(blob); + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &diffopts)); + + opts.flags = GIT_DIFF_FIND_ALL | GIT_DIFF_FIND_EXACT_MATCH_ONLY; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + /* + fprintf(stderr, "\n\n"); + diff_print_raw(stderr, diff); + */ + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(5, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + + git_tree_free(tree); + git_buf_free(&content); + git_buf_free(&old_content); +} + +void test_diff_rename__patch(void) +{ + const char *sha0 = "2bc7f351d20b53f1c72c16c4b036e491c478c49a"; + const char *sha1 = "1c068dee5790ef1580cfc4cd670915b48d790084"; + git_tree *old_tree, *new_tree; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + git_patch *patch; + const git_diff_delta *delta; + char *text; + const char *expected = "diff --git a/sixserving.txt b/ikeepsix.txt\nindex ad0a8e5..36020db 100644\n--- a/sixserving.txt\n+++ b/ikeepsix.txt\n@@ -1,3 +1,6 @@\n+I Keep Six Honest Serving-Men\n+=============================\n+\n I KEEP six honest serving-men\n (They taught me all I knew);\n Their names are What and Why and When\n@@ -21,4 +24,4 @@ She sends'em abroad on her own affairs,\n One million Hows, two million Wheres,\n And seven million Whys!\n \n- -- Rudyard Kipling\n+ -- Rudyard Kipling\n"; + + old_tree = resolve_commit_oid_to_tree(g_repo, sha0); + new_tree = resolve_commit_oid_to_tree(g_repo, sha1); + + diffopts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, old_tree, new_tree, &diffopts)); + + opts.flags = GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + /* == Changes ===================================================== + * sixserving.txt -> ikeepsix.txt (copy, add title, >80% match) + * sevencities.txt (no change) + * sixserving.txt -> sixserving.txt (indentation change) + * songofseven.txt -> songofseven.txt (major rewrite, <20% match - split) + */ + + cl_assert_equal_i(4, (int)git_diff_num_deltas(diff)); + + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_assert((delta = git_patch_get_delta(patch)) != NULL); + cl_assert_equal_i(GIT_DELTA_COPIED, (int)delta->status); + + cl_git_pass(git_patch_to_str(&text, patch)); + cl_assert_equal_s(expected, text); + git__free(text); + + git_patch_free(patch); + + cl_assert((delta = git_diff_get_delta(diff, 1)) != NULL); + cl_assert_equal_i(GIT_DELTA_UNMODIFIED, (int)delta->status); + + cl_assert((delta = git_diff_get_delta(diff, 2)) != NULL); + cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); + + cl_assert((delta = git_diff_get_delta(diff, 3)) != NULL); + cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status); + + git_diff_free(diff); + git_tree_free(old_tree); + git_tree_free(new_tree); +} + +void test_diff_rename__file_exchange(void) +{ + git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT; + git_index *index; + git_tree *tree; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + diff_expects exp; + + cl_git_pass(git_futils_readbuffer(&c1, "renames/untimely.txt")); + cl_git_pass(git_futils_readbuffer(&c2, "renames/songof7cities.txt")); + cl_git_pass(git_futils_writebuffer(&c1, "renames/songof7cities.txt", 0, 0)); + cl_git_pass(git_futils_writebuffer(&c2, "renames/untimely.txt", 0, 0)); + + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_read_tree(index, tree)); + cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); + cl_git_pass(git_index_add_bypath(index, "untimely.txt")); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(2, exp.files); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(2, exp.files); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_RENAMED]); + + git_diff_free(diff); + git_tree_free(tree); + git_index_free(index); + + git_buf_free(&c1); + git_buf_free(&c2); +} + +void test_diff_rename__file_exchange_three(void) +{ + git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT, c3 = GIT_BUF_INIT; + git_index *index; + git_tree *tree; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + diff_expects exp; + + cl_git_pass(git_futils_readbuffer(&c1, "renames/untimely.txt")); + cl_git_pass(git_futils_readbuffer(&c2, "renames/songof7cities.txt")); + cl_git_pass(git_futils_readbuffer(&c3, "renames/ikeepsix.txt")); + + cl_git_pass(git_futils_writebuffer(&c1, "renames/ikeepsix.txt", 0, 0)); + cl_git_pass(git_futils_writebuffer(&c2, "renames/untimely.txt", 0, 0)); + cl_git_pass(git_futils_writebuffer(&c3, "renames/songof7cities.txt", 0, 0)); + + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_read_tree(index, tree)); + cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); + cl_git_pass(git_index_add_bypath(index, "untimely.txt")); + cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(3, exp.files); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(3, exp.files); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_RENAMED]); + + git_diff_free(diff); + git_tree_free(tree); + git_index_free(index); + + git_buf_free(&c1); + git_buf_free(&c2); + git_buf_free(&c3); +} + +void test_diff_rename__file_partial_exchange(void) +{ + git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT; + git_index *index; + git_tree *tree; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + diff_expects exp; + int i; + + cl_git_pass(git_futils_readbuffer(&c1, "renames/untimely.txt")); + cl_git_pass(git_futils_writebuffer(&c1, "renames/songof7cities.txt", 0, 0)); + for (i = 0; i < 100; ++i) + cl_git_pass(git_buf_puts(&c2, "this is not the content you are looking for\n")); + cl_git_pass(git_futils_writebuffer(&c2, "renames/untimely.txt", 0, 0)); + + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_read_tree(index, tree)); + cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); + cl_git_pass(git_index_add_bypath(index, "untimely.txt")); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(2, exp.files); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(3, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + + git_diff_free(diff); + git_tree_free(tree); + git_index_free(index); + + git_buf_free(&c1); + git_buf_free(&c2); +} + +void test_diff_rename__rename_and_copy_from_same_source(void) +{ + git_buf c1 = GIT_BUF_INIT, c2 = GIT_BUF_INIT; + git_index *index; + git_tree *tree; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + diff_expects exp; + + /* put the first 2/3 of file into one new place + * and the second 2/3 of file into another new place + */ + cl_git_pass(git_futils_readbuffer(&c1, "renames/songof7cities.txt")); + cl_git_pass(git_buf_set(&c2, c1.ptr, c1.size)); + git_buf_truncate(&c1, c1.size * 2 / 3); + git_buf_consume(&c2, ((char *)c2.ptr) + (c2.size / 3)); + cl_git_pass(git_futils_writebuffer(&c1, "renames/song_a.txt", 0, 0)); + cl_git_pass(git_futils_writebuffer(&c2, "renames/song_b.txt", 0, 0)); + + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_read_tree(index, tree)); + cl_git_pass(git_index_add_bypath(index, "song_a.txt")); + cl_git_pass(git_index_add_bypath(index, "song_b.txt")); + + diffopts.flags = GIT_DIFF_INCLUDE_UNMODIFIED; + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(6, exp.files); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNMODIFIED]); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(6, exp.files); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_COPIED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNMODIFIED]); + + git_diff_free(diff); + git_tree_free(tree); + git_index_free(index); + + git_buf_free(&c1); + git_buf_free(&c2); +} + +void test_diff_rename__from_deleted_to_split(void) +{ + git_buf c1 = GIT_BUF_INIT; + git_index *index; + git_tree *tree; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + diff_expects exp; + + /* old file is missing, new file is actually old file renamed */ + + cl_git_pass(git_futils_readbuffer(&c1, "renames/songof7cities.txt")); + cl_git_pass(git_futils_writebuffer(&c1, "renames/untimely.txt", 0, 0)); + + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_read_tree(index, tree)); + cl_git_pass(git_index_remove_bypath(index, "songof7cities.txt")); + cl_git_pass(git_index_add_bypath(index, "untimely.txt")); + + diffopts.flags = GIT_DIFF_INCLUDE_UNMODIFIED; + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNMODIFIED]); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNMODIFIED]); + + git_diff_free(diff); + git_tree_free(tree); + git_index_free(index); + + git_buf_free(&c1); +} + +struct rename_expected +{ + size_t len; + + unsigned int *status; + const char **sources; + const char **targets; + + size_t idx; +}; + +int test_names_expected(const git_diff_delta *delta, float progress, void *p) +{ + struct rename_expected *expected = p; + + GIT_UNUSED(progress); + + cl_assert(expected->idx < expected->len); + + cl_assert_equal_i(delta->status, expected->status[expected->idx]); + + cl_assert(git__strcmp(expected->sources[expected->idx], + delta->old_file.path) == 0); + cl_assert(git__strcmp(expected->targets[expected->idx], + delta->new_file.path) == 0); + + expected->idx++; + + return 0; +} + +void test_diff_rename__rejected_match_can_match_others(void) +{ + git_reference *head, *selfsimilar; + git_index *index; + git_tree *tree; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + git_buf one = GIT_BUF_INIT, two = GIT_BUF_INIT; + unsigned int status[] = { GIT_DELTA_RENAMED, GIT_DELTA_RENAMED }; + const char *sources[] = { "Class1.cs", "Class2.cs" }; + const char *targets[] = { "ClassA.cs", "ClassB.cs" }; + struct rename_expected expect = { 2, status, sources, targets }; + char *ptr; + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); + cl_git_pass(git_reference_symbolic_set_target( + &selfsimilar, head, "refs/heads/renames_similar")); + cl_git_pass(git_checkout_head(g_repo, &opts)); + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_pass(git_futils_readbuffer(&one, "renames/Class1.cs")); + cl_git_pass(git_futils_readbuffer(&two, "renames/Class2.cs")); + + cl_git_pass(p_unlink("renames/Class1.cs")); + cl_git_pass(p_unlink("renames/Class2.cs")); + + cl_git_pass(git_index_remove_bypath(index, "Class1.cs")); + cl_git_pass(git_index_remove_bypath(index, "Class2.cs")); + + cl_assert(ptr = strstr(one.ptr, "Class1")); + ptr[5] = 'A'; + + cl_assert(ptr = strstr(two.ptr, "Class2")); + ptr[5] = 'B'; + + cl_git_pass( + git_futils_writebuffer(&one, "renames/ClassA.cs", O_RDWR|O_CREAT, 0777)); + cl_git_pass( + git_futils_writebuffer(&two, "renames/ClassB.cs", O_RDWR|O_CREAT, 0777)); + + cl_git_pass(git_index_add_bypath(index, "ClassA.cs")); + cl_git_pass(git_index_add_bypath(index, "ClassB.cs")); + + cl_git_pass(git_index_write(index)); + + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass( + git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + cl_git_pass(git_diff_find_similar(diff, &findopts)); + + cl_git_pass( + git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); + + git_diff_free(diff); + git_tree_free(tree); + git_index_free(index); + git_reference_free(head); + git_reference_free(selfsimilar); + git_buf_free(&one); + git_buf_free(&two); +} + +static void write_similarity_file_two(const char *filename, size_t b_lines) +{ + git_buf contents = GIT_BUF_INIT; + size_t i; + + for (i = 0; i < b_lines; i++) + git_buf_printf(&contents, "%02d - bbbbb\r\n", (int)(i+1)); + + for (i = b_lines; i < 50; i++) + git_buf_printf(&contents, "%02d - aaaaa%s", (int)(i+1), (i == 49 ? "" : "\r\n")); + + cl_git_pass( + git_futils_writebuffer(&contents, filename, O_RDWR|O_CREAT, 0777)); + + git_buf_free(&contents); +} + +void test_diff_rename__rejected_match_can_match_others_two(void) +{ + git_reference *head, *selfsimilar; + git_index *index; + git_tree *tree; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + unsigned int status[] = { GIT_DELTA_RENAMED, GIT_DELTA_RENAMED }; + const char *sources[] = { "a.txt", "b.txt" }; + const char *targets[] = { "c.txt", "d.txt" }; + struct rename_expected expect = { 2, status, sources, targets }; + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); + cl_git_pass(git_reference_symbolic_set_target( + &selfsimilar, head, "refs/heads/renames_similar_two")); + cl_git_pass(git_checkout_head(g_repo, &opts)); + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_pass(p_unlink("renames/a.txt")); + cl_git_pass(p_unlink("renames/b.txt")); + + cl_git_pass(git_index_remove_bypath(index, "a.txt")); + cl_git_pass(git_index_remove_bypath(index, "b.txt")); + + write_similarity_file_two("renames/c.txt", 7); + write_similarity_file_two("renames/d.txt", 8); + + cl_git_pass(git_index_add_bypath(index, "c.txt")); + cl_git_pass(git_index_add_bypath(index, "d.txt")); + + cl_git_pass(git_index_write(index)); + + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass( + git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + cl_git_pass(git_diff_find_similar(diff, &findopts)); + + cl_git_pass( + git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); + cl_assert(expect.idx > 0); + + git_diff_free(diff); + git_tree_free(tree); + git_index_free(index); + git_reference_free(head); + git_reference_free(selfsimilar); +} + +void test_diff_rename__rejected_match_can_match_others_three(void) +{ + git_reference *head, *selfsimilar; + git_index *index; + git_tree *tree; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + + /* Both cannot be renames from a.txt */ + unsigned int status[] = { GIT_DELTA_ADDED, GIT_DELTA_RENAMED }; + const char *sources[] = { "0001.txt", "a.txt" }; + const char *targets[] = { "0001.txt", "0002.txt" }; + struct rename_expected expect = { 2, status, sources, targets }; + + opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); + cl_git_pass(git_reference_symbolic_set_target( + &selfsimilar, head, "refs/heads/renames_similar_two")); + cl_git_pass(git_checkout_head(g_repo, &opts)); + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_pass(p_unlink("renames/a.txt")); + + cl_git_pass(git_index_remove_bypath(index, "a.txt")); + + write_similarity_file_two("renames/0001.txt", 7); + write_similarity_file_two("renames/0002.txt", 0); + + cl_git_pass(git_index_add_bypath(index, "0001.txt")); + cl_git_pass(git_index_add_bypath(index, "0002.txt")); + + cl_git_pass(git_index_write(index)); + + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass( + git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + cl_git_pass(git_diff_find_similar(diff, &findopts)); + + cl_git_pass( + git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); + + cl_assert(expect.idx == expect.len); + + git_diff_free(diff); + git_tree_free(tree); + git_index_free(index); + git_reference_free(head); + git_reference_free(selfsimilar); +} + +void test_diff_rename__can_rename_from_rewrite(void) +{ + git_index *index; + git_tree *tree; + git_diff *diff; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + + unsigned int status[] = { GIT_DELTA_RENAMED, GIT_DELTA_RENAMED }; + const char *sources[] = { "ikeepsix.txt", "songof7cities.txt" }; + const char *targets[] = { "songof7cities.txt", "this-is-a-rename.txt" }; + struct rename_expected expect = { 2, status, sources, targets }; + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_pass(p_rename("renames/songof7cities.txt", "renames/this-is-a-rename.txt")); + cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/songof7cities.txt")); + + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + + cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); + cl_git_pass(git_index_add_bypath(index, "this-is-a-rename.txt")); + + cl_git_pass(git_index_write(index)); + + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass( + git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + findopts.flags |= GIT_DIFF_FIND_AND_BREAK_REWRITES | + GIT_DIFF_FIND_REWRITES | + GIT_DIFF_FIND_RENAMES_FROM_REWRITES; + + cl_git_pass(git_diff_find_similar(diff, &findopts)); + + cl_git_pass( + git_diff_foreach(diff, test_names_expected, NULL, NULL, &expect)); + + cl_assert(expect.idx == expect.len); + + git_diff_free(diff); + git_tree_free(tree); + git_index_free(index); +} + +void test_diff_rename__case_changes_are_split(void) +{ + git_index *index; + git_tree *tree; + git_diff *diff = NULL; + diff_expects exp; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/IKEEPSIX.txt")); + + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "IKEEPSIX.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, NULL)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(2, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(1, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + + git_diff_free(diff); + git_index_free(index); + git_tree_free(tree); +} + +void test_diff_rename__unmodified_can_be_renamed(void) +{ + git_index *index; + git_tree *tree; + git_diff *diff = NULL; + diff_expects exp; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/ikeepsix2.txt")); + + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "ikeepsix2.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(2, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_ADDED]); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(1, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(1, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + + git_diff_free(diff); + git_index_free(index); + git_tree_free(tree); +} + +void test_diff_rename__rewrite_on_single_file(void) +{ + git_index *index; + git_diff *diff = NULL; + diff_expects exp; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; + + diffopts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + + findopts.flags = GIT_DIFF_FIND_FOR_UNTRACKED | + GIT_DIFF_FIND_AND_BREAK_REWRITES | + GIT_DIFF_FIND_RENAMES_FROM_REWRITES; + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_rewritefile("renames/ikeepsix.txt", + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &diffopts)); + cl_git_pass(git_diff_find_similar(diff, &findopts)); + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(2, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + git_index_free(index); +} diff --git a/tests/diff/submodules.c b/tests/diff/submodules.c new file mode 100644 index 000000000..24545b2c7 --- /dev/null +++ b/tests/diff/submodules.c @@ -0,0 +1,423 @@ +#include "clar_libgit2.h" +#include "repository.h" +#include "posix.h" +#include "../submodule/submodule_helpers.h" + +static git_repository *g_repo = NULL; + +void test_diff_submodules__initialize(void) +{ +} + +void test_diff_submodules__cleanup(void) +{ +} + +static void check_diff_patches_at_line( + git_diff *diff, const char **expected, const char *file, int line) +{ + const git_diff_delta *delta; + git_patch *patch = NULL; + size_t d, num_d = git_diff_num_deltas(diff); + char *patch_text; + + for (d = 0; d < num_d; ++d, git_patch_free(patch)) { + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + cl_assert((delta = git_patch_get_delta(patch)) != NULL); + + if (delta->status == GIT_DELTA_UNMODIFIED) { + cl_assert_at_line(expected[d] == NULL, file, line); + continue; + } + + if (expected[d] && !strcmp(expected[d], "")) + continue; + if (expected[d] && !strcmp(expected[d], "")) { + cl_git_pass(git_patch_to_str(&patch_text, patch)); + cl_assert_at_line(!strcmp(expected[d], ""), file, line); + } + + cl_git_pass(git_patch_to_str(&patch_text, patch)); + + clar__assert_equal( + file, line, "expected diff did not match actual diff", 1, + "%s", expected[d], patch_text); + git__free(patch_text); + } + + cl_assert_at_line(expected[d] && !strcmp(expected[d], ""), file, line); +} + +#define check_diff_patches(diff, exp) \ + check_diff_patches_at_line(diff, exp, __FILE__, __LINE__) + +void test_diff_submodules__unmodified_submodule(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + static const char *expected[] = { + "", /* .gitmodules */ + NULL, /* added */ + NULL, /* ignored */ + "diff --git a/modified b/modified\nindex 092bfb9..452216e 100644\n--- a/modified\n+++ b/modified\n@@ -1 +1,2 @@\n-yo\n+changed\n+\n", /* modified */ + NULL, /* testrepo.git */ + NULL, /* unmodified */ + NULL, /* untracked */ + "" + }; + + g_repo = setup_fixture_submodules(); + + opts.flags = GIT_DIFF_INCLUDE_IGNORED | + GIT_DIFF_INCLUDE_UNTRACKED | + GIT_DIFF_INCLUDE_UNMODIFIED; + opts.old_prefix = "a"; opts.new_prefix = "b"; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected); + git_diff_free(diff); +} + +void test_diff_submodules__dirty_submodule(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + static const char *expected[] = { + "", /* .gitmodules */ + NULL, /* added */ + NULL, /* ignored */ + "diff --git a/modified b/modified\nindex 092bfb9..452216e 100644\n--- a/modified\n+++ b/modified\n@@ -1 +1,2 @@\n-yo\n+changed\n+\n", /* modified */ + "diff --git a/testrepo b/testrepo\nindex a65fedf..a65fedf 160000\n--- a/testrepo\n+++ b/testrepo\n@@ -1 +1 @@\n-Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750\n+Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750-dirty\n", /* testrepo.git */ + NULL, /* unmodified */ + NULL, /* untracked */ + "" + }; + + g_repo = setup_fixture_submodules(); + + cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); + cl_git_mkfile("submodules/testrepo/all_new.txt", "never seen before"); + + opts.flags = GIT_DIFF_INCLUDE_IGNORED | + GIT_DIFF_INCLUDE_UNTRACKED | + GIT_DIFF_INCLUDE_UNMODIFIED; + opts.old_prefix = "a"; opts.new_prefix = "b"; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected); + git_diff_free(diff); +} + +void test_diff_submodules__dirty_submodule_2(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL, *diff2 = NULL; + char *smpath = "testrepo"; + static const char *expected_none[] = { "" }; + static const char *expected_dirty[] = { + "diff --git a/testrepo b/testrepo\nindex a65fedf..a65fedf 160000\n--- a/testrepo\n+++ b/testrepo\n@@ -1 +1 @@\n-Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750\n+Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750-dirty\n", /* testrepo.git */ + "" + }; + + g_repo = setup_fixture_submodules(); + + cl_git_pass(git_submodule_reload_all(g_repo)); + + opts.flags = GIT_DIFF_INCLUDE_UNTRACKED | + GIT_DIFF_SHOW_UNTRACKED_CONTENT | + GIT_DIFF_RECURSE_UNTRACKED_DIRS | + GIT_DIFF_DISABLE_PATHSPEC_MATCH; + opts.old_prefix = "a"; opts.new_prefix = "b"; + opts.pathspec.count = 1; + opts.pathspec.strings = &smpath; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_none); + git_diff_free(diff); + + cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); + cl_git_mkfile("submodules/testrepo/all_new.txt", "never seen before"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_dirty); + + { + git_tree *head; + + cl_git_pass(git_repository_head_tree(&head, g_repo)); + cl_git_pass(git_diff_tree_to_index(&diff2, g_repo, head, NULL, &opts)); + cl_git_pass(git_diff_merge(diff, diff2)); + git_diff_free(diff2); + git_tree_free(head); + + check_diff_patches(diff, expected_dirty); + } + + git_diff_free(diff); + + cl_git_pass(git_submodule_reload_all(g_repo)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_dirty); + git_diff_free(diff); +} + +void test_diff_submodules__submod2_index_to_wd(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + static const char *expected[] = { + "", /* .gitmodules */ + "diff --git a/sm_changed_file b/sm_changed_file\nindex 4800958..4800958 160000\n--- a/sm_changed_file\n+++ b/sm_changed_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_file */ + "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ + "diff --git a/sm_changed_index b/sm_changed_index\nindex 4800958..4800958 160000\n--- a/sm_changed_index\n+++ b/sm_changed_index\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_index */ + "diff --git a/sm_changed_untracked_file b/sm_changed_untracked_file\nindex 4800958..4800958 160000\n--- a/sm_changed_untracked_file\n+++ b/sm_changed_untracked_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_untracked_file */ + "diff --git a/sm_missing_commits b/sm_missing_commits\nindex 4800958..5e49635 160000\n--- a/sm_missing_commits\n+++ b/sm_missing_commits\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 5e4963595a9774b90524d35a807169049de8ccad\n", /* sm_missing_commits */ + "" + }; + + g_repo = setup_fixture_submod2(); + + opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + opts.old_prefix = "a"; opts.new_prefix = "b"; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected); + git_diff_free(diff); +} + +void test_diff_submodules__submod2_head_to_index(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_tree *head; + git_diff *diff = NULL; + static const char *expected[] = { + "", /* .gitmodules */ + "diff --git a/sm_added_and_uncommited b/sm_added_and_uncommited\nnew file mode 160000\nindex 0000000..4800958\n--- /dev/null\n+++ b/sm_added_and_uncommited\n@@ -0,0 +1 @@\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n", /* sm_added_and_uncommited */ + "" + }; + + g_repo = setup_fixture_submod2(); + + cl_git_pass(git_repository_head_tree(&head, g_repo)); + + opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + opts.old_prefix = "a"; opts.new_prefix = "b"; + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, head, NULL, &opts)); + check_diff_patches(diff, expected); + git_diff_free(diff); + + git_tree_free(head); +} + +void test_diff_submodules__invalid_cache(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_submodule *sm; + char *smpath = "sm_changed_head"; + git_repository *smrepo; + git_index *smindex; + static const char *expected_baseline[] = { + "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ + "" + }; + static const char *expected_unchanged[] = { "" }; + static const char *expected_dirty[] = { + "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247-dirty\n", + "" + }; + static const char *expected_moved[] = { + "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..7002348 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 700234833f6ccc20d744b238612646be071acaae\n", + "" + }; + static const char *expected_moved_dirty[] = { + "diff --git a/sm_changed_head b/sm_changed_head\nindex 3d9386c..7002348 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n+Subproject commit 700234833f6ccc20d744b238612646be071acaae-dirty\n", + "" + }; + + g_repo = setup_fixture_submod2(); + + opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + opts.old_prefix = "a"; opts.new_prefix = "b"; + opts.pathspec.count = 1; + opts.pathspec.strings = &smpath; + + /* baseline */ + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_baseline); + git_diff_free(diff); + + /* update index with new HEAD */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath)); + cl_git_pass(git_submodule_add_to_index(sm, 1)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_unchanged); + git_diff_free(diff); + + /* create untracked file in submodule working directory */ + cl_git_mkfile("submod2/sm_changed_head/new_around_here", "hello"); + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_NONE); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_dirty); + git_diff_free(diff); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_UNTRACKED); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_unchanged); + git_diff_free(diff); + + /* modify tracked file in submodule working directory */ + cl_git_append2file( + "submod2/sm_changed_head/file_to_modify", "\nmore stuff\n"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_dirty); + git_diff_free(diff); + + cl_git_pass(git_submodule_reload_all(g_repo)); + cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_dirty); + git_diff_free(diff); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_unchanged); + git_diff_free(diff); + + /* add file to index in submodule */ + cl_git_pass(git_submodule_open(&smrepo, sm)); + cl_git_pass(git_repository_index(&smindex, smrepo)); + cl_git_pass(git_index_add_bypath(smindex, "file_to_modify")); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_UNTRACKED); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_dirty); + git_diff_free(diff); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_unchanged); + git_diff_free(diff); + + /* commit changed index of submodule */ + cl_repo_commit_from_index(NULL, smrepo, NULL, 1372350000, "Move it"); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_moved); + git_diff_free(diff); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_ALL); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_unchanged); + git_diff_free(diff); + + git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_NONE); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_moved_dirty); + git_diff_free(diff); + + p_unlink("submod2/sm_changed_head/new_around_here"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_moved); + git_diff_free(diff); + + git_index_free(smindex); + git_repository_free(smrepo); +} + +void test_diff_submodules__diff_ignore_options(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_config *cfg; + static const char *expected_normal[] = { + "", /* .gitmodules */ + "diff --git a/sm_changed_file b/sm_changed_file\nindex 4800958..4800958 160000\n--- a/sm_changed_file\n+++ b/sm_changed_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_file */ + "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ + "diff --git a/sm_changed_index b/sm_changed_index\nindex 4800958..4800958 160000\n--- a/sm_changed_index\n+++ b/sm_changed_index\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_index */ + "diff --git a/sm_changed_untracked_file b/sm_changed_untracked_file\nindex 4800958..4800958 160000\n--- a/sm_changed_untracked_file\n+++ b/sm_changed_untracked_file\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0-dirty\n", /* sm_changed_untracked_file */ + "diff --git a/sm_missing_commits b/sm_missing_commits\nindex 4800958..5e49635 160000\n--- a/sm_missing_commits\n+++ b/sm_missing_commits\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 5e4963595a9774b90524d35a807169049de8ccad\n", /* sm_missing_commits */ + "" + }; + static const char *expected_ignore_all[] = { + "", /* .gitmodules */ + "" + }; + static const char *expected_ignore_dirty[] = { + "", /* .gitmodules */ + "diff --git a/sm_changed_head b/sm_changed_head\nindex 4800958..3d9386c 160000\n--- a/sm_changed_head\n+++ b/sm_changed_head\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 3d9386c507f6b093471a3e324085657a3c2b4247\n", /* sm_changed_head */ + "diff --git a/sm_missing_commits b/sm_missing_commits\nindex 4800958..5e49635 160000\n--- a/sm_missing_commits\n+++ b/sm_missing_commits\n@@ -1 +1 @@\n-Subproject commit 480095882d281ed676fe5b863569520e54a7d5c0\n+Subproject commit 5e4963595a9774b90524d35a807169049de8ccad\n", /* sm_missing_commits */ + "" + }; + + g_repo = setup_fixture_submod2(); + + opts.flags = GIT_DIFF_INCLUDE_UNTRACKED; + opts.old_prefix = "a"; opts.new_prefix = "b"; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_normal); + git_diff_free(diff); + + opts.flags |= GIT_DIFF_IGNORE_SUBMODULES; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_ignore_all); + git_diff_free(diff); + + opts.flags &= ~GIT_DIFF_IGNORE_SUBMODULES; + opts.ignore_submodules = GIT_SUBMODULE_IGNORE_ALL; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_ignore_all); + git_diff_free(diff); + + opts.ignore_submodules = GIT_SUBMODULE_IGNORE_DIRTY; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_ignore_dirty); + git_diff_free(diff); + + opts.ignore_submodules = 0; + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_bool(cfg, "diff.ignoreSubmodules", false)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_normal); + git_diff_free(diff); + + cl_git_pass(git_config_set_bool(cfg, "diff.ignoreSubmodules", true)); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_ignore_all); + git_diff_free(diff); + + cl_git_pass(git_config_set_string(cfg, "diff.ignoreSubmodules", "none")); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_normal); + git_diff_free(diff); + + cl_git_pass(git_config_set_string(cfg, "diff.ignoreSubmodules", "dirty")); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + check_diff_patches(diff, expected_ignore_dirty); + git_diff_free(diff); + + git_config_free(cfg); +} diff --git a/tests/diff/tree.c b/tests/diff/tree.c new file mode 100644 index 000000000..582174b8b --- /dev/null +++ b/tests/diff/tree.c @@ -0,0 +1,526 @@ +#include "clar_libgit2.h" +#include "diff_helpers.h" + +static git_repository *g_repo = NULL; +static git_diff_options opts; +static git_diff *diff; +static git_tree *a, *b; +static diff_expects expect; + +void test_diff_tree__initialize(void) +{ + cl_git_pass(git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION)); + + memset(&expect, 0, sizeof(expect)); + + diff = NULL; + a = NULL; + b = NULL; +} + +void test_diff_tree__cleanup(void) +{ + git_diff_free(diff); + git_tree_free(a); + git_tree_free(b); + + cl_git_sandbox_cleanup(); + +} + +void test_diff_tree__0(void) +{ + /* grabbed a couple of commit oids from the history of the attr repo */ + const char *a_commit = "605812a"; + const char *b_commit = "370fe9ec22"; + const char *c_commit = "f5b0af1fb4f5c"; + git_tree *c; + + g_repo = cl_git_sandbox_init("attr"); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); + cl_assert((c = resolve_commit_oid_to_tree(g_repo, c_commit)) != NULL); + + opts.context_lines = 1; + opts.interhunk_lines = 1; + + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + + cl_assert_equal_i(5, expect.files); + cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, expect.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); + + cl_assert_equal_i(5, expect.hunks); + + cl_assert_equal_i(7 + 24 + 1 + 6 + 6, expect.lines); + cl_assert_equal_i(1, expect.line_ctxt); + cl_assert_equal_i(24 + 1 + 5 + 5, expect.line_adds); + cl_assert_equal_i(7 + 1, expect.line_dels); + + git_diff_free(diff); + diff = NULL; + + memset(&expect, 0, sizeof(expect)); + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, c, b, &opts)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + + cl_assert_equal_i(2, expect.files); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); + + cl_assert_equal_i(2, expect.hunks); + + cl_assert_equal_i(8 + 15, expect.lines); + cl_assert_equal_i(1, expect.line_ctxt); + cl_assert_equal_i(1, expect.line_adds); + cl_assert_equal_i(7 + 14, expect.line_dels); + + git_tree_free(c); +} + +#define DIFF_OPTS(FLAGS, CTXT) \ + {GIT_DIFF_OPTIONS_VERSION, (FLAGS), GIT_SUBMODULE_IGNORE_DEFAULT, \ + {NULL,0}, NULL, NULL, (CTXT), 1} + +void test_diff_tree__options(void) +{ + /* grabbed a couple of commit oids from the history of the attr repo */ + const char *a_commit = "6bab5c79cd5140d0"; + const char *b_commit = "605812ab7fe421fdd"; + const char *c_commit = "f5b0af1fb4f5"; + const char *d_commit = "a97cc019851"; + git_tree *c, *d; + diff_expects actual; + int test_ab_or_cd[] = { 0, 0, 0, 0, 1, 1, 1, 1, 1 }; + git_diff_options test_options[] = { + /* a vs b tests */ + DIFF_OPTS(GIT_DIFF_NORMAL, 1), + DIFF_OPTS(GIT_DIFF_NORMAL, 3), + DIFF_OPTS(GIT_DIFF_REVERSE, 2), + DIFF_OPTS(GIT_DIFF_FORCE_TEXT, 2), + /* c vs d tests */ + DIFF_OPTS(GIT_DIFF_NORMAL, 3), + DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE, 3), + DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE_CHANGE, 3), + DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE_EOL, 3), + DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE | GIT_DIFF_REVERSE, 1), + }; + + /* to generate these values: + * - cd to tests/resources/attr, + * - mv .gitted .git + * - git diff [options] 6bab5c79cd5140d0 605812ab7fe421fdd + * - mv .git .gitted + */ +#define EXPECT_STATUS_ADM(ADDS,DELS,MODS) { 0, ADDS, DELS, MODS, 0, 0, 0, 0, 0 } + + diff_expects test_expects[] = { + /* a vs b tests */ + { 5, 0, EXPECT_STATUS_ADM(3, 0, 2), 4, 0, 0, 51, 2, 46, 3 }, + { 5, 0, EXPECT_STATUS_ADM(3, 0, 2), 4, 0, 0, 53, 4, 46, 3 }, + { 5, 0, EXPECT_STATUS_ADM(0, 3, 2), 4, 0, 0, 52, 3, 3, 46 }, + { 5, 0, EXPECT_STATUS_ADM(3, 0, 2), 5, 0, 0, 54, 3, 47, 4 }, + /* c vs d tests */ + { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 22, 9, 10, 3 }, + { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 19, 12, 7, 0 }, + { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 20, 11, 8, 1 }, + { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 20, 11, 8, 1 }, + { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 18, 11, 0, 7 }, + { 0 }, + }; + diff_expects *expected; + int i, j; + + g_repo = cl_git_sandbox_init("attr"); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); + cl_assert((c = resolve_commit_oid_to_tree(g_repo, c_commit)) != NULL); + cl_assert((d = resolve_commit_oid_to_tree(g_repo, d_commit)) != NULL); + + for (i = 0; test_expects[i].files > 0; i++) { + memset(&actual, 0, sizeof(actual)); /* clear accumulator */ + opts = test_options[i]; + + if (test_ab_or_cd[i] == 0) + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); + else + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, c, d, &opts)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &actual)); + + expected = &test_expects[i]; + cl_assert_equal_i(actual.files, expected->files); + for (j = GIT_DELTA_UNMODIFIED; j <= GIT_DELTA_TYPECHANGE; ++j) + cl_assert_equal_i(expected->file_status[j], actual.file_status[j]); + cl_assert_equal_i(actual.hunks, expected->hunks); + cl_assert_equal_i(actual.lines, expected->lines); + cl_assert_equal_i(actual.line_ctxt, expected->line_ctxt); + cl_assert_equal_i(actual.line_adds, expected->line_adds); + cl_assert_equal_i(actual.line_dels, expected->line_dels); + + git_diff_free(diff); + diff = NULL; + } + + git_tree_free(c); + git_tree_free(d); +} + +void test_diff_tree__bare(void) +{ + const char *a_commit = "8496071c1b46c85"; + const char *b_commit = "be3563ae3f79"; + + g_repo = cl_git_sandbox_init("testrepo.git"); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); + + opts.context_lines = 1; + opts.interhunk_lines = 1; + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + + cl_assert_equal_i(3, expect.files); + cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, expect.file_status[GIT_DELTA_MODIFIED]); + + cl_assert_equal_i(3, expect.hunks); + + cl_assert_equal_i(4, expect.lines); + cl_assert_equal_i(0, expect.line_ctxt); + cl_assert_equal_i(3, expect.line_adds); + cl_assert_equal_i(1, expect.line_dels); +} + +void test_diff_tree__merge(void) +{ + /* grabbed a couple of commit oids from the history of the attr repo */ + const char *a_commit = "605812a"; + const char *b_commit = "370fe9ec22"; + const char *c_commit = "f5b0af1fb4f5c"; + git_tree *c; + git_diff *diff1 = NULL, *diff2 = NULL; + + g_repo = cl_git_sandbox_init("attr"); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); + cl_assert((c = resolve_commit_oid_to_tree(g_repo, c_commit)) != NULL); + + cl_git_pass(git_diff_tree_to_tree(&diff1, g_repo, a, b, NULL)); + + cl_git_pass(git_diff_tree_to_tree(&diff2, g_repo, c, b, NULL)); + + git_tree_free(c); + + cl_git_pass(git_diff_merge(diff1, diff2)); + + git_diff_free(diff2); + + cl_git_pass(git_diff_foreach( + diff1, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + + cl_assert_equal_i(6, expect.files); + cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, expect.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(3, expect.file_status[GIT_DELTA_MODIFIED]); + + cl_assert_equal_i(6, expect.hunks); + + cl_assert_equal_i(59, expect.lines); + cl_assert_equal_i(1, expect.line_ctxt); + cl_assert_equal_i(36, expect.line_adds); + cl_assert_equal_i(22, expect.line_dels); + + git_diff_free(diff1); +} + +void test_diff_tree__larger_hunks(void) +{ + const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69"; + const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10"; + size_t d, num_d, h, num_h, l, num_l; + git_patch *patch; + const git_diff_hunk *hunk; + const git_diff_line *line; + + g_repo = cl_git_sandbox_init("diff"); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); + + opts.context_lines = 1; + opts.interhunk_lines = 0; + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); + + num_d = git_diff_num_deltas(diff); + for (d = 0; d < num_d; ++d) { + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + cl_assert(patch); + + num_h = git_patch_num_hunks(patch); + for (h = 0; h < num_h; h++) { + cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h)); + + for (l = 0; l < num_l; ++l) { + cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l)); + cl_assert(line); + } + + cl_git_fail(git_patch_get_line_in_hunk(&line, patch, h, num_l)); + } + + cl_git_fail(git_patch_get_hunk(&hunk, &num_l, patch, num_h)); + + git_patch_free(patch); + } + + cl_git_fail(git_patch_from_diff(&patch, diff, num_d)); + + cl_assert_equal_i(2, (int)num_d); +} + +void test_diff_tree__checks_options_version(void) +{ + const char *a_commit = "8496071c1b46c85"; + const char *b_commit = "be3563ae3f79"; + const git_error *err; + + g_repo = cl_git_sandbox_init("testrepo.git"); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); + + opts.version = 0; + cl_git_fail(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); + + giterr_clear(); + opts.version = 1024; + cl_git_fail(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); + err = giterr_last(); +} + +void process_tree_to_tree_diffing( + const char *old_commit, + const char *new_commit) +{ + g_repo = cl_git_sandbox_init("unsymlinked.git"); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, old_commit)) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, new_commit)) != NULL); + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &expect)); +} + +void test_diff_tree__symlink_blob_mode_changed_to_regular_file(void) +{ + /* + * $ git diff 7fccd7..806999 + * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h + * deleted file mode 120000 + * index 19bf568..0000000 + * --- a/include/Nu/Nu.h + * +++ /dev/null + * @@ -1 +0,0 @@ + * -../../objc/Nu.h + * \ No newline at end of file + * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h + * new file mode 100644 + * index 0000000..f9e6561 + * --- /dev/null + * +++ b/include/Nu/Nu.h + * @@ -0,0 +1 @@ + * +awesome content + * diff --git a/objc/Nu.h b/objc/Nu.h + * deleted file mode 100644 + * index f9e6561..0000000 + * --- a/objc/Nu.h + * +++ /dev/null + * @@ -1 +0,0 @@ + * -awesome content + */ + + process_tree_to_tree_diffing("7fccd7", "806999"); + + cl_assert_equal_i(3, expect.files); + cl_assert_equal_i(2, expect.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, expect.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_TYPECHANGE]); +} + +void test_diff_tree__symlink_blob_mode_changed_to_regular_file_as_typechange(void) +{ + /* + * $ git diff 7fccd7..a8595c + * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h + * deleted file mode 120000 + * index 19bf568..0000000 + * --- a/include/Nu/Nu.h + * +++ /dev/null + * @@ -1 +0,0 @@ + * -../../objc/Nu.h + * \ No newline at end of file + * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h + * new file mode 100755 + * index 0000000..f9e6561 + * --- /dev/null + * +++ b/include/Nu/Nu.h + * @@ -0,0 +1 @@ + * +awesome content + * diff --git a/objc/Nu.h b/objc/Nu.h + * deleted file mode 100644 + * index f9e6561..0000000 + * --- a/objc/Nu.h + * +++ /dev/null + * @@ -1 +0,0 @@ + * -awesome content + */ + + opts.flags = GIT_DIFF_INCLUDE_TYPECHANGE; + process_tree_to_tree_diffing("7fccd7", "a8595c"); + + cl_assert_equal_i(2, expect.files); + cl_assert_equal_i(1, expect.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, expect.file_status[GIT_DELTA_TYPECHANGE]); +} + +void test_diff_tree__regular_blob_mode_changed_to_executable_file(void) +{ + /* + * $ git diff 806999..a8595c + * diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h + * old mode 100644 + * new mode 100755 + */ + + process_tree_to_tree_diffing("806999", "a8595c"); + + cl_assert_equal_i(1, expect.files); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, expect.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_TYPECHANGE]); +} + +void test_diff_tree__issue_1397(void) +{ + /* this test shows that it is not needed */ + + g_repo = cl_git_sandbox_init("issue_1397"); + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, "8a7ef04")) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, "7f483a7")) != NULL); + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + + cl_assert_equal_i(1, expect.files); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, expect.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, expect.file_status[GIT_DELTA_TYPECHANGE]); +} + +static void set_config_int(git_repository *repo, const char *name, int value) +{ + git_config *cfg; + + cl_git_pass(git_repository_config(&cfg, repo)); + cl_git_pass(git_config_set_int32(cfg, name, value)); + git_config_free(cfg); +} + +void test_diff_tree__diff_configs(void) +{ + const char *a_commit = "d70d245e"; + const char *b_commit = "7a9e0b02"; + + g_repo = cl_git_sandbox_init("diff"); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + + cl_assert_equal_i(2, expect.files); + cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(6, expect.hunks); + cl_assert_equal_i(55, expect.lines); + cl_assert_equal_i(33, expect.line_ctxt); + cl_assert_equal_i(7, expect.line_adds); + cl_assert_equal_i(15, expect.line_dels); + + git_diff_free(diff); + diff = NULL; + + set_config_int(g_repo, "diff.context", 1); + + memset(&expect, 0, sizeof(expect)); + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + + cl_assert_equal_i(2, expect.files); + cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(7, expect.hunks); + cl_assert_equal_i(34, expect.lines); + cl_assert_equal_i(12, expect.line_ctxt); + cl_assert_equal_i(7, expect.line_adds); + cl_assert_equal_i(15, expect.line_dels); + + git_diff_free(diff); + diff = NULL; + + set_config_int(g_repo, "diff.context", 0); + set_config_int(g_repo, "diff.noprefix", 1); + + memset(&expect, 0, sizeof(expect)); + + cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect)); + + cl_assert_equal_i(2, expect.files); + cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(7, expect.hunks); + cl_assert_equal_i(22, expect.lines); + cl_assert_equal_i(0, expect.line_ctxt); + cl_assert_equal_i(7, expect.line_adds); + cl_assert_equal_i(15, expect.line_dels); +} diff --git a/tests/diff/workdir.c b/tests/diff/workdir.c new file mode 100644 index 000000000..7cc032232 --- /dev/null +++ b/tests/diff/workdir.c @@ -0,0 +1,1490 @@ +#include "clar_libgit2.h" +#include "diff_helpers.h" +#include "repository.h" + +static git_repository *g_repo = NULL; + +void test_diff_workdir__initialize(void) +{ +} + +void test_diff_workdir__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_diff_workdir__to_index(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + diff_expects exp; + int use_iterator; + + g_repo = cl_git_sandbox_init("status"); + + opts.context_lines = 3; + opts.interhunk_lines = 1; + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + else + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + /* to generate these values: + * - cd to tests/resources/status, + * - mv .gitted .git + * - git diff --name-status + * - git diff + * - mv .git .gitted + */ + cl_assert_equal_i(13, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]); + + cl_assert_equal_i(8, exp.hunks); + + cl_assert_equal_i(14, exp.lines); + cl_assert_equal_i(5, exp.line_ctxt); + cl_assert_equal_i(4, exp.line_adds); + cl_assert_equal_i(5, exp.line_dels); + } + + git_diff_free(diff); +} + +void test_diff_workdir__to_index_with_assume_unchanged(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_index *idx = NULL; + diff_expects exp; + const git_index_entry *iep; + git_index_entry ie; + + g_repo = cl_git_sandbox_init("status"); + + /* do initial diff */ + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(8, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); + git_diff_free(diff); + + /* mark a couple of entries with ASSUME_UNCHANGED */ + + cl_git_pass(git_repository_index(&idx, g_repo)); + + cl_assert((iep = git_index_get_bypath(idx, "modified_file", 0)) != NULL); + memcpy(&ie, iep, sizeof(ie)); + ie.flags |= GIT_IDXENTRY_VALID; + cl_git_pass(git_index_add(idx, &ie)); + + cl_assert((iep = git_index_get_bypath(idx, "file_deleted", 0)) != NULL); + memcpy(&ie, iep, sizeof(ie)); + ie.flags |= GIT_IDXENTRY_VALID; + cl_git_pass(git_index_add(idx, &ie)); + + cl_git_pass(git_index_write(idx)); + git_index_free(idx); + + /* redo diff and see that entries are skipped */ + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + cl_assert_equal_i(6, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); + git_diff_free(diff); + +} + +void test_diff_workdir__to_tree(void) +{ + /* grabbed a couple of commit oids from the history of the attr repo */ + const char *a_commit = "26a125ee1bf"; /* the current HEAD */ + const char *b_commit = "0017bd4ab1ec3"; /* the start */ + git_tree *a, *b; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_diff *diff2 = NULL; + diff_expects exp; + int use_iterator; + + g_repo = cl_git_sandbox_init("status"); + + a = resolve_commit_oid_to_tree(g_repo, a_commit); + b = resolve_commit_oid_to_tree(g_repo, b_commit); + + opts.context_lines = 3; + opts.interhunk_lines = 1; + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + + /* You can't really generate the equivalent of git_diff_tree_to_workdir() + * using C git. It really wants to interpose the index into the diff. + * + * To validate the following results with command line git, I ran the + * following: + * - git ls-tree 26a125 + * - find . ! -path ./.git/\* -a -type f | git hash-object --stdin-paths + * The results are documented at the bottom of this file in the + * long comment entitled "PREPARATION OF TEST DATA". + */ + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + else + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(14, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(5, exp.file_status[GIT_DELTA_UNTRACKED]); + } + + /* Since there is no git diff equivalent, let's just assume that the + * text diffs produced by git_diff_foreach are accurate here. We will + * do more apples-to-apples test comparison below. + */ + + git_diff_free(diff); + diff = NULL; + memset(&exp, 0, sizeof(exp)); + + /* This is a compatible emulation of "git diff " which looks like + * a workdir to tree diff (even though it is not really). This is what + * you would get from "git diff --name-status 26a125ee1bf" + */ + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); + cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); + cl_git_pass(git_diff_merge(diff, diff2)); + git_diff_free(diff2); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + else + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(15, exp.files); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(5, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); + + cl_assert_equal_i(11, exp.hunks); + + cl_assert_equal_i(17, exp.lines); + cl_assert_equal_i(4, exp.line_ctxt); + cl_assert_equal_i(8, exp.line_adds); + cl_assert_equal_i(5, exp.line_dels); + } + + git_diff_free(diff); + diff = NULL; + memset(&exp, 0, sizeof(exp)); + + /* Again, emulating "git diff " for testing purposes using + * "git diff --name-status 0017bd4ab1ec3" instead. + */ + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts)); + cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); + cl_git_pass(git_diff_merge(diff, diff2)); + git_diff_free(diff2); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + else + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(16, exp.files); + cl_assert_equal_i(5, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); + + cl_assert_equal_i(12, exp.hunks); + + cl_assert_equal_i(19, exp.lines); + cl_assert_equal_i(3, exp.line_ctxt); + cl_assert_equal_i(12, exp.line_adds); + cl_assert_equal_i(4, exp.line_dels); + } + + git_diff_free(diff); + + /* Let's try that once more with a reversed diff */ + + opts.flags |= GIT_DIFF_REVERSE; + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts)); + cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); + cl_git_pass(git_diff_merge(diff, diff2)); + git_diff_free(diff2); + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(16, exp.files); + cl_assert_equal_i(5, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); + + cl_assert_equal_i(12, exp.hunks); + + cl_assert_equal_i(19, exp.lines); + cl_assert_equal_i(3, exp.line_ctxt); + cl_assert_equal_i(12, exp.line_dels); + cl_assert_equal_i(4, exp.line_adds); + + git_diff_free(diff); + + /* all done now */ + + git_tree_free(a); + git_tree_free(b); +} + +void test_diff_workdir__to_index_with_pathspec(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + diff_expects exp; + char *pathspec = NULL; + int use_iterator; + + g_repo = cl_git_sandbox_init("status"); + + opts.context_lines = 3; + opts.interhunk_lines = 1; + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + opts.pathspec.strings = &pathspec; + opts.pathspec.count = 1; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, NULL, NULL, &exp)); + else + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(13, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]); + } + + git_diff_free(diff); + + pathspec = "modified_file"; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, NULL, NULL, &exp)); + else + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(1, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]); + } + + git_diff_free(diff); + + pathspec = "subdir"; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, NULL, NULL, &exp)); + else + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(3, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); + } + + git_diff_free(diff); + + pathspec = "*_deleted"; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, NULL, NULL, &exp)); + else + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(2, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]); + } + + git_diff_free(diff); +} + +void test_diff_workdir__filemode_changes(void) +{ + git_diff *diff = NULL; + diff_expects exp; + int use_iterator; + + if (!cl_is_chmod_supported()) + return; + + g_repo = cl_git_sandbox_init("issue_592"); + + cl_repo_set_bool(g_repo, "core.filemode", true); + + /* test once with no mods */ + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + else + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(0, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, exp.hunks); + } + + git_diff_free(diff); + + /* chmod file and test again */ + + cl_assert(cl_toggle_filemode("issue_592/a.txt")); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + else + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(1, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, exp.hunks); + } + + git_diff_free(diff); + + cl_assert(cl_toggle_filemode("issue_592/a.txt")); +} + +void test_diff_workdir__filemode_changes_with_filemode_false(void) +{ + git_diff *diff = NULL; + diff_expects exp; + + if (!cl_is_chmod_supported()) + return; + + g_repo = cl_git_sandbox_init("issue_592"); + + cl_repo_set_bool(g_repo, "core.filemode", false); + + /* test once with no mods */ + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(0, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, exp.hunks); + + git_diff_free(diff); + + /* chmod file and test again */ + + cl_assert(cl_toggle_filemode("issue_592/a.txt")); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(0, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, exp.hunks); + + git_diff_free(diff); + + cl_assert(cl_toggle_filemode("issue_592/a.txt")); +} + +void test_diff_workdir__head_index_and_workdir_all_differ(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff_i2t = NULL, *diff_w2i = NULL; + diff_expects exp; + char *pathspec = "staged_changes_modified_file"; + git_tree *tree; + int use_iterator; + + /* For this file, + * - head->index diff has 1 line of context, 1 line of diff + * - index->workdir diff has 2 lines of context, 1 line of diff + * but + * - head->workdir diff has 1 line of context, 2 lines of diff + * Let's make sure the right one is returned from each fn. + */ + + g_repo = cl_git_sandbox_init("status"); + + tree = resolve_commit_oid_to_tree(g_repo, "26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f"); + + opts.pathspec.strings = &pathspec; + opts.pathspec.count = 1; + + cl_git_pass(git_diff_tree_to_index(&diff_i2t, g_repo, tree, NULL, &opts)); + cl_git_pass(git_diff_index_to_workdir(&diff_w2i, g_repo, NULL, &opts)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + else + cl_git_pass(git_diff_foreach( + diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(1, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.hunks); + cl_assert_equal_i(2, exp.lines); + cl_assert_equal_i(1, exp.line_ctxt); + cl_assert_equal_i(1, exp.line_adds); + cl_assert_equal_i(0, exp.line_dels); + } + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff_w2i, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + else + cl_git_pass(git_diff_foreach( + diff_w2i, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(1, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.hunks); + cl_assert_equal_i(3, exp.lines); + cl_assert_equal_i(2, exp.line_ctxt); + cl_assert_equal_i(1, exp.line_adds); + cl_assert_equal_i(0, exp.line_dels); + } + + cl_git_pass(git_diff_merge(diff_i2t, diff_w2i)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + else + cl_git_pass(git_diff_foreach( + diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(1, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.hunks); + cl_assert_equal_i(3, exp.lines); + cl_assert_equal_i(1, exp.line_ctxt); + cl_assert_equal_i(2, exp.line_adds); + cl_assert_equal_i(0, exp.line_dels); + } + + git_diff_free(diff_i2t); + git_diff_free(diff_w2i); + + git_tree_free(tree); +} + +void test_diff_workdir__eof_newline_changes(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + diff_expects exp; + char *pathspec = "current_file"; + int use_iterator; + + g_repo = cl_git_sandbox_init("status"); + + opts.pathspec.strings = &pathspec; + opts.pathspec.count = 1; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + else + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(0, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, exp.hunks); + cl_assert_equal_i(0, exp.lines); + cl_assert_equal_i(0, exp.line_ctxt); + cl_assert_equal_i(0, exp.line_adds); + cl_assert_equal_i(0, exp.line_dels); + } + + git_diff_free(diff); + + cl_git_append2file("status/current_file", "\n"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + else + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(1, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.hunks); + cl_assert_equal_i(2, exp.lines); + cl_assert_equal_i(1, exp.line_ctxt); + cl_assert_equal_i(1, exp.line_adds); + cl_assert_equal_i(0, exp.line_dels); + } + + git_diff_free(diff); + + cl_git_rewritefile("status/current_file", "current_file"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + for (use_iterator = 0; use_iterator <= 1; use_iterator++) { + memset(&exp, 0, sizeof(exp)); + + if (use_iterator) + cl_git_pass(diff_foreach_via_iterator( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + else + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(1, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.hunks); + cl_assert_equal_i(3, exp.lines); + cl_assert_equal_i(0, exp.line_ctxt); + cl_assert_equal_i(1, exp.line_adds); + cl_assert_equal_i(2, exp.line_dels); + } + + git_diff_free(diff); +} + +/* PREPARATION OF TEST DATA + * + * Since there is no command line equivalent of git_diff_tree_to_workdir, + * it was a bit of a pain to confirm that I was getting the expected + * results in the first part of this tests. Here is what I ended up + * doing to set my expectation for the file counts and results: + * + * Running "git ls-tree 26a125" and "git ls-tree aa27a6" shows: + * + * A a0de7e0ac200c489c41c59dfa910154a70264e6e current_file + * B 5452d32f1dd538eb0405e8a83cc185f79e25e80f file_deleted + * C 452e4244b5d083ddf0460acf1ecc74db9dcfa11a modified_file + * D 32504b727382542f9f089e24fddac5e78533e96c staged_changes + * E 061d42a44cacde5726057b67558821d95db96f19 staged_changes_file_deleted + * F 70bd9443ada07063e7fbf0b3ff5c13f7494d89c2 staged_changes_modified_file + * G e9b9107f290627c04d097733a10055af941f6bca staged_delete_file_deleted + * H dabc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 staged_delete_modified_file + * I 53ace0d1cc1145a5f4fe4f78a186a60263190733 subdir/current_file + * J 1888c805345ba265b0ee9449b8877b6064592058 subdir/deleted_file + * K a6191982709b746d5650e93c2acf34ef74e11504 subdir/modified_file + * L e8ee89e15bbe9b20137715232387b3de5b28972e subdir.txt + * + * -------- + * + * find . ! -path ./.git/\* -a -type f | git hash-object --stdin-paths + * + * A a0de7e0ac200c489c41c59dfa910154a70264e6e current_file + * M 6a79f808a9c6bc9531ac726c184bbcd9351ccf11 ignored_file + * C 0a539630525aca2e7bc84975958f92f10a64c9b6 modified_file + * N d4fa8600b4f37d7516bef4816ae2c64dbf029e3a new_file + * D 55d316c9ba708999f1918e9677d01dfcae69c6b9 staged_changes + * F 011c3440d5c596e21d836aa6d7b10eb581f68c49 staged_changes_modified_file + * H dabc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 staged_delete_modified_file + * O 529a16e8e762d4acb7b9636ff540a00831f9155a staged_new_file + * P 8b090c06d14ffa09c4e880088ebad33893f921d1 staged_new_file_modified_file + * I 53ace0d1cc1145a5f4fe4f78a186a60263190733 subdir/current_file + * K 57274b75eeb5f36fd55527806d567b2240a20c57 subdir/modified_file + * Q 80a86a6931b91bc01c2dbf5ca55bdd24ad1ef466 subdir/new_file + * L e8ee89e15bbe9b20137715232387b3de5b28972e subdir.txt + * + * -------- + * + * A - current_file (UNMODIFIED) -> not in results + * B D file_deleted + * M I ignored_file (IGNORED) + * C M modified_file + * N U new_file (UNTRACKED) + * D M staged_changes + * E D staged_changes_file_deleted + * F M staged_changes_modified_file + * G D staged_delete_file_deleted + * H - staged_delete_modified_file (UNMODIFIED) -> not in results + * O U staged_new_file + * P U staged_new_file_modified_file + * I - subdir/current_file (UNMODIFIED) -> not in results + * J D subdir/deleted_file + * K M subdir/modified_file + * Q U subdir/new_file + * L - subdir.txt (UNMODIFIED) -> not in results + * + * Expect 13 files, 0 ADD, 4 DEL, 4 MOD, 1 IGN, 4 UNTR + */ + + +void test_diff_workdir__larger_hunks(void) +{ + const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69"; + const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10"; + git_tree *a, *b; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + size_t i, d, num_d, h, num_h, l, num_l; + + g_repo = cl_git_sandbox_init("diff"); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); + + opts.context_lines = 1; + opts.interhunk_lines = 0; + + for (i = 0; i <= 2; ++i) { + git_diff *diff = NULL; + git_patch *patch; + const git_diff_hunk *hunk; + const git_diff_line *line; + + /* okay, this is a bit silly, but oh well */ + switch (i) { + case 0: + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + break; + case 1: + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); + break; + case 2: + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, b, &opts)); + break; + } + + num_d = git_diff_num_deltas(diff); + cl_assert_equal_i(2, (int)num_d); + + for (d = 0; d < num_d; ++d) { + cl_git_pass(git_patch_from_diff(&patch, diff, d)); + cl_assert(patch); + + num_h = git_patch_num_hunks(patch); + for (h = 0; h < num_h; h++) { + cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h)); + + for (l = 0; l < num_l; ++l) { + cl_git_pass( + git_patch_get_line_in_hunk(&line, patch, h, l)); + cl_assert(line); + } + + /* confirm fail after the last item */ + cl_git_fail( + git_patch_get_line_in_hunk(&line, patch, h, num_l)); + } + + /* confirm fail after the last item */ + cl_git_fail(git_patch_get_hunk(&hunk, &num_l, patch, num_h)); + + git_patch_free(patch); + } + + git_diff_free(diff); + } + + git_tree_free(a); + git_tree_free(b); +} + +/* Set up a test that exercises this code. The easiest test using existing + * test data is probably to create a sandbox of submod2 and then run a + * git_diff_tree_to_workdir against tree + * 873585b94bdeabccea991ea5e3ec1a277895b698. As for what you should actually + * test, you can start by just checking that the number of lines of diff + * content matches the actual output of git diff. That will at least + * demonstrate that the submodule content is being used to generate somewhat + * comparable outputs. It is a test that would fail without this code and + * will succeed with it. + */ + +#include "../submodule/submodule_helpers.h" + +void test_diff_workdir__submodules(void) +{ + const char *a_commit = "873585b94bdeabccea991ea5e3ec1a277895b698"; + git_tree *a; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + diff_expects exp; + + g_repo = setup_fixture_submod2(); + + a = resolve_commit_oid_to_tree(g_repo, a_commit); + + opts.flags = + GIT_DIFF_INCLUDE_UNTRACKED | + GIT_DIFF_INCLUDE_IGNORED | + GIT_DIFF_RECURSE_UNTRACKED_DIRS | + GIT_DIFF_SHOW_UNTRACKED_CONTENT; + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); + + /* diff_print(stderr, diff); */ + + /* essentially doing: git diff 873585b94bdeabccea991ea5e3ec1a277895b698 */ + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + /* so "git diff 873585" returns: + * M .gitmodules + * A just_a_dir/contents + * A just_a_file + * A sm_added_and_uncommited + * A sm_changed_file + * A sm_changed_head + * A sm_changed_index + * A sm_changed_untracked_file + * M sm_missing_commits + * A sm_unchanged + * which is a little deceptive because of the difference between the + * "git diff " results from "git_diff_tree_to_workdir". The + * only significant difference is that those Added items will show up + * as Untracked items in the pure libgit2 diff. + * + * Then add in the two extra ignored items "not" and "not-submodule" + * to get the 12 files reported here. + */ + + cl_assert_equal_i(12, exp.files); + + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(8, exp.file_status[GIT_DELTA_UNTRACKED]); + + /* the following numbers match "git diff 873585" exactly */ + + cl_assert_equal_i(9, exp.hunks); + + cl_assert_equal_i(33, exp.lines); + cl_assert_equal_i(2, exp.line_ctxt); + cl_assert_equal_i(30, exp.line_adds); + cl_assert_equal_i(1, exp.line_dels); + + git_diff_free(diff); + git_tree_free(a); +} + +void test_diff_workdir__cannot_diff_against_a_bare_repository(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_tree *tree; + + g_repo = cl_git_sandbox_init("testrepo.git"); + + cl_assert_equal_i( + GIT_EBAREREPO, git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_git_pass(git_repository_head_tree(&tree, g_repo)); + + cl_assert_equal_i( + GIT_EBAREREPO, git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); + + git_tree_free(tree); +} + +void test_diff_workdir__to_null_tree(void) +{ + git_diff *diff; + diff_expects exp; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + + opts.flags = GIT_DIFF_INCLUDE_UNTRACKED | + GIT_DIFF_RECURSE_UNTRACKED_DIRS; + + g_repo = cl_git_sandbox_init("status"); + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, NULL, &opts)); + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(exp.files, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); +} + +void test_diff_workdir__checks_options_version(void) +{ + git_diff *diff; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + const git_error *err; + + g_repo = cl_git_sandbox_init("status"); + + opts.version = 0; + cl_git_fail(git_diff_tree_to_workdir(&diff, g_repo, NULL, &opts)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); + + giterr_clear(); + opts.version = 1024; + cl_git_fail(git_diff_tree_to_workdir(&diff, g_repo, NULL, &opts)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); +} + +void test_diff_workdir__can_diff_empty_file(void) +{ + git_diff *diff; + git_tree *tree; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + struct stat st; + git_patch *patch; + + g_repo = cl_git_sandbox_init("attr_index"); + + tree = resolve_commit_oid_to_tree(g_repo, "3812cfef3661"); /* HEAD */ + + /* baseline - make sure there are no outstanding diffs */ + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); + cl_assert_equal_i(2, (int)git_diff_num_deltas(diff)); + git_diff_free(diff); + + /* empty contents of file */ + + cl_git_rewritefile("attr_index/README.txt", ""); + cl_git_pass(git_path_lstat("attr_index/README.txt", &st)); + cl_assert_equal_i(0, (int)st.st_size); + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); + cl_assert_equal_i(3, (int)git_diff_num_deltas(diff)); + /* diffs are: .gitattributes, README.txt, sub/sub/.gitattributes */ + cl_git_pass(git_patch_from_diff(&patch, diff, 1)); + git_patch_free(patch); + git_diff_free(diff); + + /* remove a file altogether */ + + cl_git_pass(p_unlink("attr_index/README.txt")); + cl_assert(!git_path_exists("attr_index/README.txt")); + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts)); + cl_assert_equal_i(3, (int)git_diff_num_deltas(diff)); + cl_git_pass(git_patch_from_diff(&patch, diff, 1)); + git_patch_free(patch); + git_diff_free(diff); + + git_tree_free(tree); +} + +void test_diff_workdir__to_index_issue_1397(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + diff_expects exp; + + g_repo = cl_git_sandbox_init("issue_1397"); + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + opts.context_lines = 3; + opts.interhunk_lines = 1; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(0, exp.files); + cl_assert_equal_i(0, exp.hunks); + cl_assert_equal_i(0, exp.lines); + + git_diff_free(diff); + diff = NULL; + + cl_git_rewritefile("issue_1397/crlf_file.txt", + "first line\r\nsecond line modified\r\nboth with crlf"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(1, exp.files); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + + cl_assert_equal_i(1, exp.hunks); + + cl_assert_equal_i(5, exp.lines); + cl_assert_equal_i(3, exp.line_ctxt); + cl_assert_equal_i(1, exp.line_adds); + cl_assert_equal_i(1, exp.line_dels); + + git_diff_free(diff); +} + +void test_diff_workdir__to_tree_issue_1397(void) +{ + const char *a_commit = "7f483a738"; /* the current HEAD */ + git_tree *a; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_diff *diff2 = NULL; + diff_expects exp; + + g_repo = cl_git_sandbox_init("issue_1397"); + + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + a = resolve_commit_oid_to_tree(g_repo, a_commit); + + opts.context_lines = 3; + opts.interhunk_lines = 1; + + cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(0, exp.files); + cl_assert_equal_i(0, exp.hunks); + cl_assert_equal_i(0, exp.lines); + + git_diff_free(diff); + diff = NULL; + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts)); + cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts)); + cl_git_pass(git_diff_merge(diff, diff2)); + git_diff_free(diff2); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(0, exp.files); + cl_assert_equal_i(0, exp.hunks); + cl_assert_equal_i(0, exp.lines); + + git_diff_free(diff); + git_tree_free(a); +} + +void test_diff_workdir__untracked_directory_scenarios(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + diff_expects exp; + char *pathspec = NULL; + static const char *files0[] = { + "subdir/deleted_file", + "subdir/modified_file", + "subdir/new_file", + NULL + }; + static const char *files1[] = { + "subdir/deleted_file", + "subdir/directory/", + "subdir/modified_file", + "subdir/new_file", + NULL + }; + static const char *files2[] = { + "subdir/deleted_file", + "subdir/directory/more/notignored", + "subdir/modified_file", + "subdir/new_file", + NULL + }; + + g_repo = cl_git_sandbox_init("status"); + cl_git_mkfile("status/.gitignore", "ignored\n"); + + opts.context_lines = 3; + opts.interhunk_lines = 1; + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + opts.pathspec.strings = &pathspec; + opts.pathspec.count = 1; + pathspec = "subdir"; + + /* baseline for "subdir" pathspec */ + + memset(&exp, 0, sizeof(exp)); + exp.names = files0; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(3, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + + /* empty directory */ + + cl_git_pass(p_mkdir("status/subdir/directory", 0777)); + + memset(&exp, 0, sizeof(exp)); + exp.names = files1; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + + /* empty directory in empty directory */ + + cl_git_pass(p_mkdir("status/subdir/directory/empty", 0777)); + + memset(&exp, 0, sizeof(exp)); + exp.names = files1; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + + /* directory with only ignored files */ + + cl_git_pass(p_mkdir("status/subdir/directory/deeper", 0777)); + cl_git_mkfile("status/subdir/directory/deeper/ignored", "ignore me\n"); + + cl_git_pass(p_mkdir("status/subdir/directory/another", 0777)); + cl_git_mkfile("status/subdir/directory/another/ignored", "ignore me\n"); + + memset(&exp, 0, sizeof(exp)); + exp.names = files1; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + + /* directory with ignored directory (contents irrelevant) */ + + cl_git_pass(p_mkdir("status/subdir/directory/more", 0777)); + cl_git_pass(p_mkdir("status/subdir/directory/more/ignored", 0777)); + cl_git_mkfile("status/subdir/directory/more/ignored/notignored", + "inside ignored dir\n"); + + memset(&exp, 0, sizeof(exp)); + exp.names = files1; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + + /* quick version avoids directory scan */ + + opts.flags = opts.flags | GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS; + + memset(&exp, 0, sizeof(exp)); + exp.names = files1; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + + /* directory with nested non-ignored content */ + + opts.flags = opts.flags & ~GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS; + + cl_git_mkfile("status/subdir/directory/more/notignored", + "not ignored deep under untracked\n"); + + memset(&exp, 0, sizeof(exp)); + exp.names = files1; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); + + /* use RECURSE_UNTRACKED_DIRS to get actual untracked files (no ignores) */ + + opts.flags = opts.flags & ~GIT_DIFF_INCLUDE_IGNORED; + opts.flags = opts.flags | GIT_DIFF_RECURSE_UNTRACKED_DIRS; + + memset(&exp, 0, sizeof(exp)); + exp.names = files2; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp)); + + cl_assert_equal_i(4, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]); + cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]); + + git_diff_free(diff); +} + + +void test_diff_workdir__untracked_directory_comes_last(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + + g_repo = cl_git_sandbox_init("renames"); + + cl_git_mkfile("renames/.gitignore", "*.ign\n"); + cl_git_pass(p_mkdir("renames/zzz_untracked", 0777)); + cl_git_mkfile("renames/zzz_untracked/an.ign", "ignore me please"); + cl_git_mkfile("renames/zzz_untracked/skip.ign", "ignore me really"); + cl_git_mkfile("renames/zzz_untracked/test.ign", "ignore me now"); + + opts.context_lines = 3; + opts.interhunk_lines = 1; + opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_assert(diff != NULL); + + git_diff_free(diff); +} + +void test_diff_workdir__untracked_with_bom(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + const git_diff_delta *delta; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_repo_set_bool(g_repo, "core.autocrlf", true); + + cl_git_write2file("empty_standard_repo/bom.txt", + "\xFF\xFE\x31\x00\x32\x00\x33\x00\x34\x00", 10, O_WRONLY|O_CREAT, 0664); + + opts.flags = + GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + cl_assert_equal_i(1, git_diff_num_deltas(diff)); + cl_assert((delta = git_diff_get_delta(diff, 0)) != NULL); + cl_assert_equal_i(GIT_DELTA_UNTRACKED, delta->status); + + /* not known at this point + * cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); + */ + + git_diff_free(diff); +} + +void test_diff_workdir__patience_diff(void) +{ + git_index *index; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_patch *patch = NULL; + char *as_str = NULL; + const char *expected_normal = "diff --git a/test.txt b/test.txt\nindex 34a5acc..d52725f 100644\n--- a/test.txt\n+++ b/test.txt\n@@ -1,10 +1,7 @@\n When I wrote this\n I did not know\n-how to create\n-a patience diff\n I did not know\n how to create\n+a patience diff\n another problem\n-I did not know\n-how to create\n a minimal diff\n"; + const char *expected_patience = "diff --git a/test.txt b/test.txt\nindex 34a5acc..d52725f 100644\n--- a/test.txt\n+++ b/test.txt\n@@ -1,10 +1,7 @@\n When I wrote this\n I did not know\n+I did not know\n how to create\n a patience diff\n-I did not know\n-how to create\n another problem\n-I did not know\n-how to create\n a minimal diff\n"; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_repo_set_bool(g_repo, "core.autocrlf", true); + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_mkfile( + "empty_standard_repo/test.txt", + "When I wrote this\nI did not know\nhow to create\na patience diff\nI did not know\nhow to create\nanother problem\nI did not know\nhow to create\na minimal diff\n"); + cl_git_pass(git_index_add_bypath(index, "test.txt")); + cl_repo_commit_from_index(NULL, g_repo, NULL, 1372350000, "Base"); + git_index_free(index); + + cl_git_rewritefile( + "empty_standard_repo/test.txt", + "When I wrote this\nI did not know\nI did not know\nhow to create\na patience diff\nanother problem\na minimal diff\n"); + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + cl_assert_equal_i(1, git_diff_num_deltas(diff)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&as_str, patch)); + + cl_assert_equal_s(expected_normal, as_str); + git__free(as_str); + git_patch_free(patch); + git_diff_free(diff); + + opts.flags |= GIT_DIFF_PATIENCE; + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + cl_assert_equal_i(1, git_diff_num_deltas(diff)); + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_str(&as_str, patch)); + + cl_assert_equal_s(expected_patience, as_str); + git__free(as_str); + git_patch_free(patch); + git_diff_free(diff); +} + +void test_diff_workdir__with_stale_index(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff *diff = NULL; + git_index *idx = NULL; + diff_expects exp; + + g_repo = cl_git_sandbox_init("status"); + cl_git_pass(git_repository_index(&idx, g_repo)); + + /* make the in-memory index invalid */ + { + git_repository *r2; + git_index *idx2; + cl_git_pass(git_repository_open(&r2, "status")); + cl_git_pass(git_repository_index(&idx2, r2)); + cl_git_pass(git_index_add_bypath(idx2, "new_file")); + cl_git_pass(git_index_add_bypath(idx2, "subdir/new_file")); + cl_git_pass(git_index_remove_bypath(idx2, "staged_new_file")); + cl_git_pass(git_index_remove_bypath(idx2, "staged_changes_file_deleted")); + cl_git_pass(git_index_write(idx2)); + git_index_free(idx2); + git_repository_free(r2); + } + + opts.context_lines = 3; + opts.interhunk_lines = 1; + opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_INCLUDE_UNMODIFIED; + + /* first try with index pointer which should prevent reload */ + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, idx, &opts)); + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + cl_assert_equal_i(17, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]); + cl_assert_equal_i(5, exp.file_status[GIT_DELTA_UNMODIFIED]); + + git_diff_free(diff); + + /* now let's try without the index pointer which should trigger reload */ + + /* two files that were UNTRACKED should have become UNMODIFIED */ + /* one file that was UNMODIFIED should now have become UNTRACKED */ + /* one file that was DELETED should now be gone completely */ + + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp)); + + git_diff_free(diff); + + cl_assert_equal_i(16, exp.files); + cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]); + cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]); + cl_assert_equal_i(6, exp.file_status[GIT_DELTA_UNMODIFIED]); + + git_index_free(idx); +} diff --git a/tests/fetchhead/fetchhead_data.h b/tests/fetchhead/fetchhead_data.h new file mode 100644 index 000000000..294c9fb01 --- /dev/null +++ b/tests/fetchhead/fetchhead_data.h @@ -0,0 +1,31 @@ + +#define FETCH_HEAD_WILDCARD_DATA_LOCAL \ + "49322bb17d3acc9146f98c97d078513228bbf3c0\t\tbranch 'master' of git://github.com/libgit2/TestGitRepository\n" \ + "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" \ + "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of git://github.com/libgit2/TestGitRepository\n" \ + "d96c4e80345534eccee5ac7b07fc7603b56124cb\tnot-for-merge\ttag 'annotated_tag' of git://github.com/libgit2/TestGitRepository\n" \ + "55a1a760df4b86a02094a904dfa511deb5655905\tnot-for-merge\ttag 'blob' of git://github.com/libgit2/TestGitRepository\n" \ + "8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of git://github.com/libgit2/TestGitRepository\n" + +#define FETCH_HEAD_WILDCARD_DATA \ + "49322bb17d3acc9146f98c97d078513228bbf3c0\t\tbranch 'master' of git://github.com/libgit2/TestGitRepository\n" \ + "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" \ + "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of git://github.com/libgit2/TestGitRepository\n" \ + "d96c4e80345534eccee5ac7b07fc7603b56124cb\tnot-for-merge\ttag 'annotated_tag' of git://github.com/libgit2/TestGitRepository\n" \ + "55a1a760df4b86a02094a904dfa511deb5655905\tnot-for-merge\ttag 'blob' of git://github.com/libgit2/TestGitRepository\n" \ + "8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of git://github.com/libgit2/TestGitRepository\n" \ + "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e\tnot-for-merge\ttag 'nearly-dangling' of git://github.com/libgit2/TestGitRepository\n" + +#define FETCH_HEAD_NO_MERGE_DATA \ + "0966a434eb1a025db6b71485ab63a3bfbea520b6\tnot-for-merge\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" \ + "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\tbranch 'master' of git://github.com/libgit2/TestGitRepository\n" \ + "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1\tnot-for-merge\tbranch 'no-parent' of git://github.com/libgit2/TestGitRepository\n" \ + "d96c4e80345534eccee5ac7b07fc7603b56124cb\tnot-for-merge\ttag 'annotated_tag' of git://github.com/libgit2/TestGitRepository\n" \ + "55a1a760df4b86a02094a904dfa511deb5655905\tnot-for-merge\ttag 'blob' of git://github.com/libgit2/TestGitRepository\n" \ + "8f50ba15d49353813cc6e20298002c0d17b0a9ee\tnot-for-merge\ttag 'commit_tree' of git://github.com/libgit2/TestGitRepository\n" \ + "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e\tnot-for-merge\ttag 'nearly-dangling' of git://github.com/libgit2/TestGitRepository\n" + + +#define FETCH_HEAD_EXPLICIT_DATA \ + "0966a434eb1a025db6b71485ab63a3bfbea520b6\t\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" + diff --git a/tests/fetchhead/nonetwork.c b/tests/fetchhead/nonetwork.c new file mode 100644 index 000000000..a68ebb0b7 --- /dev/null +++ b/tests/fetchhead/nonetwork.c @@ -0,0 +1,309 @@ +#include "clar_libgit2.h" + +#include "fileops.h" +#include "fetchhead.h" + +#include "fetchhead_data.h" + +#define DO_LOCAL_TEST 0 + +static git_repository *g_repo; + +void test_fetchhead_nonetwork__initialize(void) +{ + g_repo = NULL; +} + +static void cleanup_repository(void *path) +{ + if (g_repo) { + git_repository_free(g_repo); + g_repo = NULL; + } + + cl_fixture_cleanup((const char *)path); +} + +static void populate_fetchhead(git_vector *out, git_repository *repo) +{ + git_fetchhead_ref *fetchhead_ref; + git_oid oid; + + cl_git_pass(git_oid_fromstr(&oid, + "49322bb17d3acc9146f98c97d078513228bbf3c0")); + cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 1, + "refs/heads/master", + "git://github.com/libgit2/TestGitRepository")); + cl_git_pass(git_vector_insert(out, fetchhead_ref)); + + cl_git_pass(git_oid_fromstr(&oid, + "0966a434eb1a025db6b71485ab63a3bfbea520b6")); + cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0, + "refs/heads/first-merge", + "git://github.com/libgit2/TestGitRepository")); + cl_git_pass(git_vector_insert(out, fetchhead_ref)); + + cl_git_pass(git_oid_fromstr(&oid, + "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1")); + cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0, + "refs/heads/no-parent", + "git://github.com/libgit2/TestGitRepository")); + cl_git_pass(git_vector_insert(out, fetchhead_ref)); + + cl_git_pass(git_oid_fromstr(&oid, + "d96c4e80345534eccee5ac7b07fc7603b56124cb")); + cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0, + "refs/tags/annotated_tag", + "git://github.com/libgit2/TestGitRepository")); + cl_git_pass(git_vector_insert(out, fetchhead_ref)); + + cl_git_pass(git_oid_fromstr(&oid, + "55a1a760df4b86a02094a904dfa511deb5655905")); + cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0, + "refs/tags/blob", + "git://github.com/libgit2/TestGitRepository")); + cl_git_pass(git_vector_insert(out, fetchhead_ref)); + + cl_git_pass(git_oid_fromstr(&oid, + "8f50ba15d49353813cc6e20298002c0d17b0a9ee")); + cl_git_pass(git_fetchhead_ref_create(&fetchhead_ref, &oid, 0, + "refs/tags/commit_tree", + "git://github.com/libgit2/TestGitRepository")); + cl_git_pass(git_vector_insert(out, fetchhead_ref)); + + cl_git_pass(git_fetchhead_write(repo, out)); +} + +void test_fetchhead_nonetwork__write(void) +{ + git_vector fetchhead_vector = GIT_VECTOR_INIT; + git_fetchhead_ref *fetchhead_ref; + git_buf fetchhead_buf = GIT_BUF_INIT; + int equals = 0; + size_t i; + + git_vector_init(&fetchhead_vector, 6, NULL); + + cl_set_cleanup(&cleanup_repository, "./test1"); + cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); + + populate_fetchhead(&fetchhead_vector, g_repo); + + cl_git_pass(git_futils_readbuffer(&fetchhead_buf, + "./test1/.git/FETCH_HEAD")); + + equals = (strcmp(fetchhead_buf.ptr, FETCH_HEAD_WILDCARD_DATA_LOCAL) == 0); + + git_buf_free(&fetchhead_buf); + + git_vector_foreach(&fetchhead_vector, i, fetchhead_ref) { + git_fetchhead_ref_free(fetchhead_ref); + } + + git_vector_free(&fetchhead_vector); + + cl_assert(equals); +} + +typedef struct { + git_vector *fetchhead_vector; + size_t idx; +} fetchhead_ref_cb_data; + +static int fetchhead_ref_cb(const char *name, const char *url, + const git_oid *oid, unsigned int is_merge, void *payload) +{ + fetchhead_ref_cb_data *cb_data = payload; + git_fetchhead_ref *expected; + + cl_assert(payload); + + expected = git_vector_get(cb_data->fetchhead_vector, cb_data->idx); + + cl_assert(git_oid_cmp(&expected->oid, oid) == 0); + cl_assert(expected->is_merge == is_merge); + + if (expected->ref_name) + cl_assert_equal_s(expected->ref_name, name); + else + cl_assert(name == NULL); + + if (expected->remote_url) + cl_assert_equal_s(expected->remote_url, url); + else + cl_assert(url == NULL); + + cb_data->idx++; + + return 0; +} + +void test_fetchhead_nonetwork__read(void) +{ + git_vector fetchhead_vector = GIT_VECTOR_INIT; + git_fetchhead_ref *fetchhead_ref; + fetchhead_ref_cb_data cb_data; + size_t i; + + memset(&cb_data, 0x0, sizeof(fetchhead_ref_cb_data)); + + cl_set_cleanup(&cleanup_repository, "./test1"); + cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); + + populate_fetchhead(&fetchhead_vector, g_repo); + + cb_data.fetchhead_vector = &fetchhead_vector; + + cl_git_pass(git_repository_fetchhead_foreach(g_repo, fetchhead_ref_cb, &cb_data)); + + git_vector_foreach(&fetchhead_vector, i, fetchhead_ref) { + git_fetchhead_ref_free(fetchhead_ref); + } + + git_vector_free(&fetchhead_vector); +} + +static int read_old_style_cb(const char *name, const char *url, + const git_oid *oid, unsigned int is_merge, void *payload) +{ + git_oid expected; + + GIT_UNUSED(payload); + + git_oid_fromstr(&expected, "49322bb17d3acc9146f98c97d078513228bbf3c0"); + + cl_assert(name == NULL); + cl_assert(url == NULL); + cl_assert(git_oid_cmp(&expected, oid) == 0); + cl_assert(is_merge == 1); + + return 0; +} + +void test_fetchhead_nonetwork__read_old_style(void) +{ + cl_set_cleanup(&cleanup_repository, "./test1"); + cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); + + cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\n"); + + cl_git_pass(git_repository_fetchhead_foreach(g_repo, read_old_style_cb, NULL)); +} + +static int read_type_missing(const char *ref_name, const char *remote_url, + const git_oid *oid, unsigned int is_merge, void *payload) +{ + git_oid expected; + + GIT_UNUSED(payload); + + git_oid_fromstr(&expected, "49322bb17d3acc9146f98c97d078513228bbf3c0"); + + cl_assert_equal_s("name", ref_name); + cl_assert_equal_s("remote_url", remote_url); + cl_assert(git_oid_cmp(&expected, oid) == 0); + cl_assert(is_merge == 0); + + return 0; +} + +void test_fetchhead_nonetwork__type_missing(void) +{ + cl_set_cleanup(&cleanup_repository, "./test1"); + cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); + + cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\t'name' of remote_url\n"); + + cl_git_pass(git_repository_fetchhead_foreach(g_repo, read_type_missing, NULL)); +} + +static int read_name_missing(const char *ref_name, const char *remote_url, + const git_oid *oid, unsigned int is_merge, void *payload) +{ + git_oid expected; + + GIT_UNUSED(payload); + + git_oid_fromstr(&expected, "49322bb17d3acc9146f98c97d078513228bbf3c0"); + + cl_assert(ref_name == NULL); + cl_assert_equal_s("remote_url", remote_url); + cl_assert(git_oid_cmp(&expected, oid) == 0); + cl_assert(is_merge == 0); + + return 0; +} + +void test_fetchhead_nonetwork__name_missing(void) +{ + cl_set_cleanup(&cleanup_repository, "./test1"); + cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); + + cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\tremote_url\n"); + + cl_git_pass(git_repository_fetchhead_foreach(g_repo, read_name_missing, NULL)); +} + +static int read_noop(const char *ref_name, const char *remote_url, + const git_oid *oid, unsigned int is_merge, void *payload) +{ + GIT_UNUSED(ref_name); + GIT_UNUSED(remote_url); + GIT_UNUSED(oid); + GIT_UNUSED(is_merge); + GIT_UNUSED(payload); + + return 0; +} + +void test_fetchhead_nonetwork__nonexistent(void) +{ + int error; + + cl_set_cleanup(&cleanup_repository, "./test1"); + cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); + + cl_git_fail((error = git_repository_fetchhead_foreach(g_repo, read_noop, NULL))); + cl_assert(error == GIT_ENOTFOUND); +} + +void test_fetchhead_nonetwork__invalid_unterminated_last_line(void) +{ + cl_set_cleanup(&cleanup_repository, "./test1"); + cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); + + cl_git_rewritefile("./test1/.git/FETCH_HEAD", "unterminated"); + cl_git_fail(git_repository_fetchhead_foreach(g_repo, read_noop, NULL)); +} + +void test_fetchhead_nonetwork__invalid_oid(void) +{ + cl_set_cleanup(&cleanup_repository, "./test1"); + cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); + + cl_git_rewritefile("./test1/.git/FETCH_HEAD", "shortoid\n"); + cl_git_fail(git_repository_fetchhead_foreach(g_repo, read_noop, NULL)); +} + +void test_fetchhead_nonetwork__invalid_for_merge(void) +{ + cl_set_cleanup(&cleanup_repository, "./test1"); + cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); + + 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); +} + +void test_fetchhead_nonetwork__invalid_description(void) +{ + cl_set_cleanup(&cleanup_repository, "./test1"); + cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); + + 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); +} + diff --git a/tests/filter/blob.c b/tests/filter/blob.c new file mode 100644 index 000000000..9600a9779 --- /dev/null +++ b/tests/filter/blob.c @@ -0,0 +1,84 @@ +#include "clar_libgit2.h" +#include "crlf.h" + +static git_repository *g_repo = NULL; + +void test_filter_blob__initialize(void) +{ + g_repo = cl_git_sandbox_init("crlf"); + cl_git_mkfile("crlf/.gitattributes", + "*.txt text\n*.bin binary\n" + "*.crlf text eol=crlf\n" + "*.lf text eol=lf\n" + "*.ident text ident\n" + "*.identcrlf ident text eol=crlf\n" + "*.identlf ident text eol=lf\n"); +} + +void test_filter_blob__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_filter_blob__all_crlf(void) +{ + git_blob *blob; + git_buf buf = { 0 }; + + cl_git_pass(git_revparse_single( + (git_object **)&blob, g_repo, "a9a2e891")); /* all-crlf */ + + cl_assert_equal_s(ALL_CRLF_TEXT_RAW, git_blob_rawcontent(blob)); + + cl_git_pass(git_blob_filtered_content(&buf, blob, "file.bin", 1)); + + cl_assert_equal_s(ALL_CRLF_TEXT_RAW, buf.ptr); + + cl_git_pass(git_blob_filtered_content(&buf, blob, "file.crlf", 1)); + + /* in this case, raw content has crlf in it already */ + cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr); + + cl_git_pass(git_blob_filtered_content(&buf, blob, "file.lf", 1)); + + cl_assert_equal_s(ALL_CRLF_TEXT_AS_LF, buf.ptr); + + git_buf_free(&buf); + git_blob_free(blob); +} + +void test_filter_blob__ident(void) +{ + git_oid id; + git_blob *blob; + git_buf buf = { 0 }; + + cl_git_mkfile("crlf/test.ident", "Some text\n$Id$\nGoes there\n"); + cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "test.ident")); + cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); + cl_assert_equal_s( + "Some text\n$Id$\nGoes there\n", git_blob_rawcontent(blob)); + git_blob_free(blob); + + cl_git_mkfile("crlf/test.ident", "Some text\n$Id: Any old just you want$\nGoes there\n"); + cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "test.ident")); + cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); + cl_assert_equal_s( + "Some text\n$Id$\nGoes there\n", git_blob_rawcontent(blob)); + + cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.bin", 1)); + cl_assert_equal_s( + "Some text\n$Id$\nGoes there\n", buf.ptr); + + cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.identcrlf", 1)); + cl_assert_equal_s( + "Some text\r\n$Id: 3164f585d548ac68027d22b104f2d8100b2b6845$\r\nGoes there\r\n", buf.ptr); + + cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.identlf", 1)); + cl_assert_equal_s( + "Some text\n$Id: 3164f585d548ac68027d22b104f2d8100b2b6845$\nGoes there\n", buf.ptr); + + git_buf_free(&buf); + git_blob_free(blob); + +} diff --git a/tests/filter/crlf.c b/tests/filter/crlf.c new file mode 100644 index 000000000..c9fb9cd7f --- /dev/null +++ b/tests/filter/crlf.c @@ -0,0 +1,71 @@ +#include "clar_libgit2.h" +#include "git2/sys/filter.h" + +static git_repository *g_repo = NULL; + +void test_filter_crlf__initialize(void) +{ + g_repo = cl_git_sandbox_init("crlf"); + + cl_git_mkfile("crlf/.gitattributes", + "*.txt text\n*.bin binary\n*.crlf text eol=crlf\n*.lf text eol=lf\n"); + + cl_repo_set_bool(g_repo, "core.autocrlf", true); +} + +void test_filter_crlf__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_filter_crlf__to_worktree(void) +{ + git_filter_list *fl; + git_filter *crlf; + git_buf in = { 0 }, out = { 0 }; + + cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_WORKTREE)); + + crlf = git_filter_lookup(GIT_FILTER_CRLF); + cl_assert(crlf != NULL); + + cl_git_pass(git_filter_list_push(fl, crlf, NULL)); + + in.ptr = "Some text\nRight here\n"; + in.size = strlen(in.ptr); + + cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); + +#ifdef GIT_WIN32 + cl_assert_equal_s("Some text\r\nRight here\r\n", out.ptr); +#else + cl_assert_equal_s("Some text\nRight here\n", out.ptr); +#endif + + git_filter_list_free(fl); + git_buf_free(&out); +} + +void test_filter_crlf__to_odb(void) +{ + git_filter_list *fl; + git_filter *crlf; + git_buf in = { 0 }, out = { 0 }; + + cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_ODB)); + + crlf = git_filter_lookup(GIT_FILTER_CRLF); + cl_assert(crlf != NULL); + + cl_git_pass(git_filter_list_push(fl, crlf, NULL)); + + in.ptr = "Some text\r\nRight here\r\n"; + in.size = strlen(in.ptr); + + cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); + + cl_assert_equal_s("Some text\nRight here\n", out.ptr); + + git_filter_list_free(fl); + git_buf_free(&out); +} diff --git a/tests/filter/crlf.h b/tests/filter/crlf.h new file mode 100644 index 000000000..9cb98ad4c --- /dev/null +++ b/tests/filter/crlf.h @@ -0,0 +1,25 @@ +#ifndef INCLUDE_filter_crlf_h__ +#define INCLUDE_filter_crlf_h__ + +/* + * file content for files in the resources/crlf repository + */ + +#define UTF8_BOM "\xEF\xBB\xBF" + +#define ALL_CRLF_TEXT_RAW "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n" +#define ALL_LF_TEXT_RAW "lf\nlf\nlf\nlf\nlf\n" +#define MORE_CRLF_TEXT_RAW "crlf\r\ncrlf\r\nlf\ncrlf\r\ncrlf\r\n" +#define MORE_LF_TEXT_RAW "lf\nlf\ncrlf\r\nlf\nlf\n" + +#define ALL_CRLF_TEXT_AS_CRLF ALL_CRLF_TEXT_RAW +#define ALL_LF_TEXT_AS_CRLF "lf\r\nlf\r\nlf\r\nlf\r\nlf\r\n" +#define MORE_CRLF_TEXT_AS_CRLF "crlf\r\ncrlf\r\nlf\r\ncrlf\r\ncrlf\r\n" +#define MORE_LF_TEXT_AS_CRLF "lf\r\nlf\r\ncrlf\r\nlf\r\nlf\r\n" + +#define ALL_CRLF_TEXT_AS_LF "crlf\ncrlf\ncrlf\ncrlf\n" +#define ALL_LF_TEXT_AS_LF ALL_LF_TEXT_RAW +#define MORE_CRLF_TEXT_AS_LF "crlf\ncrlf\nlf\ncrlf\ncrlf\n" +#define MORE_LF_TEXT_AS_LF "lf\nlf\ncrlf\nlf\nlf\n" + +#endif diff --git a/tests/filter/custom.c b/tests/filter/custom.c new file mode 100644 index 000000000..a81885c28 --- /dev/null +++ b/tests/filter/custom.c @@ -0,0 +1,337 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "blob.h" +#include "filter.h" +#include "buf_text.h" +#include "git2/sys/filter.h" +#include "git2/sys/repository.h" + +/* going TO_WORKDIR, filters are executed low to high + * going TO_ODB, filters are executed high to low + */ +#define BITFLIP_FILTER_PRIORITY -1 +#define REVERSE_FILTER_PRIORITY -2 + +#define VERY_SECURE_ENCRYPTION(b) ((b) ^ 0xff) + +#ifdef GIT_WIN32 +# define NEWLINE "\r\n" +#else +# define NEWLINE "\n" +#endif + +static char workdir_data[] = + "some simple" NEWLINE + "data" NEWLINE + "that will be" NEWLINE + "trivially" NEWLINE + "scrambled." NEWLINE; + +/* Represents the data above scrambled (bits flipped) after \r\n -> \n + * conversion, then bytewise reversed + */ +static unsigned char bitflipped_and_reversed_data[] = + { 0xf5, 0xd1, 0x9b, 0x9a, 0x93, 0x9d, 0x92, 0x9e, 0x8d, 0x9c, 0x8c, + 0xf5, 0x86, 0x93, 0x93, 0x9e, 0x96, 0x89, 0x96, 0x8d, 0x8b, 0xf5, + 0x9a, 0x9d, 0xdf, 0x93, 0x93, 0x96, 0x88, 0xdf, 0x8b, 0x9e, 0x97, + 0x8b, 0xf5, 0x9e, 0x8b, 0x9e, 0x9b, 0xf5, 0x9a, 0x93, 0x8f, 0x92, + 0x96, 0x8c, 0xdf, 0x9a, 0x92, 0x90, 0x8c }; + +#define BITFLIPPED_AND_REVERSED_DATA_LEN 51 + +static git_repository *g_repo = NULL; + +static void register_custom_filters(void); + +void test_filter_custom__initialize(void) +{ + register_custom_filters(); + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_mkfile( + "empty_standard_repo/.gitattributes", + "hero* bitflip reverse\n" + "herofile text\n" + "heroflip -reverse binary\n" + "*.bin binary\n"); +} + +void test_filter_custom__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +static int bitflip_filter_apply( + git_filter *self, + void **payload, + git_buf *to, + const git_buf *from, + const git_filter_source *source) +{ + const unsigned char *src = (const unsigned char *)from->ptr; + unsigned char *dst; + size_t i; + + GIT_UNUSED(self); GIT_UNUSED(payload); + + /* verify that attribute path match worked as expected */ + cl_assert_equal_i( + 0, git__strncmp("hero", git_filter_source_path(source), 4)); + + if (!from->size) + return 0; + + cl_git_pass(git_buf_grow(to, from->size)); + + dst = (unsigned char *)to->ptr; + + for (i = 0; i < from->size; i++) + dst[i] = VERY_SECURE_ENCRYPTION(src[i]); + + to->size = from->size; + + return 0; +} + +static void bitflip_filter_free(git_filter *f) +{ + git__free(f); +} + +static git_filter *create_bitflip_filter(void) +{ + git_filter *filter = git__calloc(1, sizeof(git_filter)); + cl_assert(filter); + + filter->version = GIT_FILTER_VERSION; + filter->attributes = "+bitflip"; + filter->shutdown = bitflip_filter_free; + filter->apply = bitflip_filter_apply; + + return filter; +} + + +static int reverse_filter_apply( + git_filter *self, + void **payload, + git_buf *to, + const git_buf *from, + const git_filter_source *source) +{ + const unsigned char *src = (const unsigned char *)from->ptr; + const unsigned char *end = src + from->size; + unsigned char *dst; + + GIT_UNUSED(self); GIT_UNUSED(payload); GIT_UNUSED(source); + + /* verify that attribute path match worked as expected */ + cl_assert_equal_i( + 0, git__strncmp("hero", git_filter_source_path(source), 4)); + + if (!from->size) + return 0; + + cl_git_pass(git_buf_grow(to, from->size)); + + dst = (unsigned char *)to->ptr + from->size - 1; + + while (src < end) + *dst-- = *src++; + + to->size = from->size; + + return 0; +} + +static void reverse_filter_free(git_filter *f) +{ + git__free(f); +} + +static git_filter *create_reverse_filter(const char *attrs) +{ + git_filter *filter = git__calloc(1, sizeof(git_filter)); + cl_assert(filter); + + filter->version = GIT_FILTER_VERSION; + filter->attributes = attrs; + filter->shutdown = reverse_filter_free; + filter->apply = reverse_filter_apply; + + return filter; +} + +static void register_custom_filters(void) +{ + static int filters_registered = 0; + + if (!filters_registered) { + cl_git_pass(git_filter_register( + "bitflip", create_bitflip_filter(), BITFLIP_FILTER_PRIORITY)); + + cl_git_pass(git_filter_register( + "reverse", create_reverse_filter("+reverse"), + REVERSE_FILTER_PRIORITY)); + + /* re-register reverse filter with standard filter=xyz priority */ + cl_git_pass(git_filter_register( + "pre-reverse", + create_reverse_filter("+prereverse"), + GIT_FILTER_DRIVER_PRIORITY)); + + filters_registered = 1; + } +} + + +void test_filter_custom__to_odb(void) +{ + git_filter_list *fl; + git_buf out = { 0 }; + git_buf in = GIT_BUF_INIT_CONST(workdir_data, strlen(workdir_data)); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "herofile", GIT_FILTER_TO_ODB)); + + cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); + + cl_assert_equal_i(BITFLIPPED_AND_REVERSED_DATA_LEN, out.size); + + cl_assert_equal_i( + 0, memcmp(bitflipped_and_reversed_data, out.ptr, out.size)); + + git_filter_list_free(fl); + git_buf_free(&out); +} + +void test_filter_custom__to_workdir(void) +{ + git_filter_list *fl; + git_buf out = { 0 }; + git_buf in = GIT_BUF_INIT_CONST( + bitflipped_and_reversed_data, BITFLIPPED_AND_REVERSED_DATA_LEN); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "herofile", GIT_FILTER_TO_WORKTREE)); + + cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in)); + + cl_assert_equal_i(strlen(workdir_data), out.size); + + cl_assert_equal_i( + 0, memcmp(workdir_data, out.ptr, out.size)); + + git_filter_list_free(fl); + git_buf_free(&out); +} + +void test_filter_custom__can_register_a_custom_filter_in_the_repository(void) +{ + git_filter_list *fl; + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "herofile", GIT_FILTER_TO_WORKTREE)); + /* expect: bitflip, reverse, crlf */ + cl_assert_equal_sz(3, git_filter_list_length(fl)); + git_filter_list_free(fl); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "herocorp", GIT_FILTER_TO_WORKTREE)); + /* expect: bitflip, reverse - possibly crlf depending on global config */ + { + size_t flen = git_filter_list_length(fl); + cl_assert(flen == 2 || flen == 3); + } + git_filter_list_free(fl); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "hero.bin", GIT_FILTER_TO_WORKTREE)); + /* expect: bitflip, reverse */ + cl_assert_equal_sz(2, git_filter_list_length(fl)); + git_filter_list_free(fl); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "heroflip", GIT_FILTER_TO_WORKTREE)); + /* expect: bitflip (because of -reverse) */ + cl_assert_equal_sz(1, git_filter_list_length(fl)); + git_filter_list_free(fl); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "doesntapplytome.bin", GIT_FILTER_TO_WORKTREE)); + /* expect: none */ + cl_assert_equal_sz(0, git_filter_list_length(fl)); + git_filter_list_free(fl); +} + +void test_filter_custom__order_dependency(void) +{ + git_index *index; + git_blob *blob; + git_buf buf = { 0 }; + + /* so if ident and reverse are used together, an interesting thing + * happens - a reversed "$Id$" string is no longer going to trigger + * ident correctly. When checking out, the filters should be applied + * in order CLRF, then ident, then reverse, so ident expansion should + * work correctly. On check in, the content should be reversed, then + * ident, then CRLF filtered. Let's make sure that works... + */ + + cl_git_mkfile( + "empty_standard_repo/.gitattributes", + "hero.*.rev-ident text ident prereverse eol=lf\n"); + + cl_git_mkfile( + "empty_standard_repo/hero.1.rev-ident", + "This is a test\n$Id$\nHave fun!\n"); + + cl_git_mkfile( + "empty_standard_repo/hero.2.rev-ident", + "Another test\n$dI$\nCrazy!\n"); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_add_bypath(index, "hero.1.rev-ident")); + cl_git_pass(git_index_add_bypath(index, "hero.2.rev-ident")); + cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "Filter chains\n"); + git_index_free(index); + + cl_git_pass(git_blob_lookup(&blob, g_repo, + & git_index_get_bypath(index, "hero.1.rev-ident", 0)->oid)); + cl_assert_equal_s( + "\n!nuf evaH\n$dI$\ntset a si sihT", git_blob_rawcontent(blob)); + cl_git_pass(git_blob_filtered_content(&buf, blob, "hero.1.rev-ident", 0)); + /* no expansion because id was reversed at checkin and now at ident + * time, reverse is not applied yet */ + cl_assert_equal_s( + "This is a test\n$Id$\nHave fun!\n", buf.ptr); + git_blob_free(blob); + + cl_git_pass(git_blob_lookup(&blob, g_repo, + & git_index_get_bypath(index, "hero.2.rev-ident", 0)->oid)); + cl_assert_equal_s( + "\n!yzarC\n$Id$\ntset rehtonA", git_blob_rawcontent(blob)); + cl_git_pass(git_blob_filtered_content(&buf, blob, "hero.2.rev-ident", 0)); + /* expansion because reverse was applied at checkin and at ident time, + * reverse is not applied yet */ + cl_assert_equal_s( + "Another test\n$59001fe193103b1016b27027c0c827d036fd0ac8 :dI$\nCrazy!\n", buf.ptr); + cl_assert_equal_i(0, git_oid_strcmp( + git_blob_id(blob), "8ca0df630d728c0c72072b6101b301391ef10095")); + git_blob_free(blob); + + git_buf_free(&buf); +} + +void test_filter_custom__filter_registry_failure_cases(void) +{ + git_filter fake = { GIT_FILTER_VERSION, 0 }; + + cl_assert_equal_i(GIT_EEXISTS, git_filter_register("bitflip", &fake, 0)); + + cl_git_fail(git_filter_unregister(GIT_FILTER_CRLF)); + cl_git_fail(git_filter_unregister(GIT_FILTER_IDENT)); + cl_assert_equal_i(GIT_ENOTFOUND, git_filter_unregister("not-a-filter")); +} diff --git a/tests/filter/ident.c b/tests/filter/ident.c new file mode 100644 index 000000000..2c8e6abea --- /dev/null +++ b/tests/filter/ident.c @@ -0,0 +1,131 @@ +#include "clar_libgit2.h" +#include "git2/sys/filter.h" + +static git_repository *g_repo = NULL; + +void test_filter_ident__initialize(void) +{ + g_repo = cl_git_sandbox_init("crlf"); +} + +void test_filter_ident__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void add_blob_and_filter( + const char *data, + git_filter_list *fl, + const char *expected) +{ + git_oid id; + git_blob *blob; + git_buf out = { 0 }; + + cl_git_mkfile("crlf/identtest", data); + cl_git_pass(git_blob_create_fromworkdir(&id, g_repo, "identtest")); + cl_git_pass(git_blob_lookup(&blob, g_repo, &id)); + + cl_git_pass(git_filter_list_apply_to_blob(&out, fl, blob)); + + cl_assert_equal_s(expected, out.ptr); + + git_blob_free(blob); + git_buf_free(&out); +} + +void test_filter_ident__to_worktree(void) +{ + git_filter_list *fl; + git_filter *ident; + + cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_WORKTREE)); + + ident = git_filter_lookup(GIT_FILTER_IDENT); + cl_assert(ident != NULL); + + cl_git_pass(git_filter_list_push(fl, ident, NULL)); + + add_blob_and_filter( + "Hello\n$Id$\nFun stuff\n", fl, + "Hello\n$Id: b69e2387aafcaf73c4de5b9ab59abe27fdadee30$\nFun stuff\n"); + add_blob_and_filter( + "Hello\n$Id: Junky$\nFun stuff\n", fl, + "Hello\n$Id: 45cd107a7102911cb2a7df08404674327fa050b9$\nFun stuff\n"); + add_blob_and_filter( + "$Id$\nAt the start\n", fl, + "$Id: b13415c767abc196fb95bd17070e8c1113e32160$\nAt the start\n"); + add_blob_and_filter( + "At the end\n$Id$", fl, + "At the end\n$Id: 1344925c6bc65b34c5a7b50f86bf688e48e9a272$"); + add_blob_and_filter( + "$Id$", fl, + "$Id: b3f5ebfb5843bc43ceecff6d4f26bb37c615beb1$"); + add_blob_and_filter( + "$Id: Some sort of junk goes here$", fl, + "$Id: ab2dd3853c7c9a4bff55aca2bea077a73c32ac06$"); + + add_blob_and_filter("$Id: ", fl, "$Id: "); + add_blob_and_filter("$Id", fl, "$Id"); + add_blob_and_filter("$I", fl, "$I"); + add_blob_and_filter("Id$", fl, "Id$"); + + git_filter_list_free(fl); +} + +void test_filter_ident__to_odb(void) +{ + git_filter_list *fl; + git_filter *ident; + + cl_git_pass(git_filter_list_new(&fl, g_repo, GIT_FILTER_TO_ODB)); + + ident = git_filter_lookup(GIT_FILTER_IDENT); + cl_assert(ident != NULL); + + cl_git_pass(git_filter_list_push(fl, ident, NULL)); + + add_blob_and_filter( + "Hello\n$Id$\nFun stuff\n", + fl, "Hello\n$Id$\nFun stuff\n"); + add_blob_and_filter( + "Hello\n$Id: b69e2387aafcaf73c4de5b9ab59abe27fdadee30$\nFun stuff\n", + fl, "Hello\n$Id$\nFun stuff\n"); + add_blob_and_filter( + "Hello\n$Id: Any junk you may have left here$\nFun stuff\n", + fl, "Hello\n$Id$\nFun stuff\n"); + add_blob_and_filter( + "Hello\n$Id:$\nFun stuff\n", + fl, "Hello\n$Id$\nFun stuff\n"); + add_blob_and_filter( + "Hello\n$Id:x$\nFun stuff\n", + fl, "Hello\n$Id$\nFun stuff\n"); + + add_blob_and_filter( + "$Id$\nAt the start\n", fl, "$Id$\nAt the start\n"); + add_blob_and_filter( + "$Id: lots of random text that should be removed from here$\nAt the start\n", fl, "$Id$\nAt the start\n"); + add_blob_and_filter( + "$Id: lots of random text that should not be removed without a terminator\nAt the start\n", fl, "$Id: lots of random text that should not be removed without a terminator\nAt the start\n"); + + add_blob_and_filter( + "At the end\n$Id$", fl, "At the end\n$Id$"); + add_blob_and_filter( + "At the end\n$Id:$", fl, "At the end\n$Id$"); + add_blob_and_filter( + "At the end\n$Id:asdfasdf$", fl, "At the end\n$Id$"); + add_blob_and_filter( + "At the end\n$Id", fl, "At the end\n$Id"); + add_blob_and_filter( + "At the end\n$IddI", fl, "At the end\n$IddI"); + + add_blob_and_filter("$Id$", fl, "$Id$"); + add_blob_and_filter("$Id: any$", fl, "$Id$"); + add_blob_and_filter("$Id: any long stuff goes here you see$", fl, "$Id$"); + add_blob_and_filter("$Id: ", fl, "$Id: "); + add_blob_and_filter("$Id", fl, "$Id"); + add_blob_and_filter("$I", fl, "$I"); + add_blob_and_filter("Id$", fl, "Id$"); + + git_filter_list_free(fl); +} diff --git a/tests/generate.py b/tests/generate.py new file mode 100644 index 000000000..d4fe8f2a3 --- /dev/null +++ b/tests/generate.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python +# +# Copyright (c) Vicent Marti. All rights reserved. +# +# This file is part of clar, distributed under the ISC license. +# For full terms see the included COPYING file. +# + +from __future__ import with_statement +from string import Template +import re, fnmatch, os, codecs, pickle + +class Module(object): + class Template(object): + def __init__(self, module): + self.module = module + + def _render_callback(self, cb): + if not cb: + return ' { NULL, NULL }' + return ' { "%s", &%s }' % (cb['short_name'], cb['symbol']) + + class DeclarationTemplate(Template): + def render(self): + out = "\n".join("extern %s;" % cb['declaration'] for cb in self.module.callbacks) + "\n" + + if self.module.initialize: + out += "extern %s;\n" % self.module.initialize['declaration'] + + if self.module.cleanup: + out += "extern %s;\n" % self.module.cleanup['declaration'] + + return out + + class CallbacksTemplate(Template): + def render(self): + out = "static const struct clar_func _clar_cb_%s[] = {\n" % self.module.name + out += ",\n".join(self._render_callback(cb) for cb in self.module.callbacks) + out += "\n};\n" + return out + + class InfoTemplate(Template): + def render(self): + return Template( + r""" + { + "${clean_name}", + ${initialize}, + ${cleanup}, + ${cb_ptr}, ${cb_count}, ${enabled} + }""" + ).substitute( + clean_name = self.module.clean_name(), + initialize = self._render_callback(self.module.initialize), + cleanup = self._render_callback(self.module.cleanup), + cb_ptr = "_clar_cb_%s" % self.module.name, + cb_count = len(self.module.callbacks), + enabled = int(self.module.enabled) + ) + + def __init__(self, name): + self.name = name + + self.mtime = 0 + self.enabled = True + self.modified = False + + def clean_name(self): + return self.name.replace("_", "::") + + def _skip_comments(self, text): + SKIP_COMMENTS_REGEX = re.compile( + r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', + re.DOTALL | re.MULTILINE) + + def _replacer(match): + s = match.group(0) + return "" if s.startswith('/') else s + + return re.sub(SKIP_COMMENTS_REGEX, _replacer, text) + + def parse(self, contents): + TEST_FUNC_REGEX = r"^(void\s+(test_%s__(\w+))\(\s*void\s*\))\s*\{" + + contents = self._skip_comments(contents) + regex = re.compile(TEST_FUNC_REGEX % self.name, re.MULTILINE) + + self.callbacks = [] + self.initialize = None + self.cleanup = None + + for (declaration, symbol, short_name) in regex.findall(contents): + data = { + "short_name" : short_name, + "declaration" : declaration, + "symbol" : symbol + } + + if short_name == 'initialize': + self.initialize = data + elif short_name == 'cleanup': + self.cleanup = data + else: + self.callbacks.append(data) + + return self.callbacks != [] + + def refresh(self, path): + self.modified = False + + try: + st = os.stat(path) + + # Not modified + if st.st_mtime == self.mtime: + return True + + self.modified = True + self.mtime = st.st_mtime + + with open(path) as fp: + raw_content = fp.read() + + except IOError: + return False + + return self.parse(raw_content) + +class TestSuite(object): + + def __init__(self, path): + self.path = path + + def should_generate(self, path): + if not os.path.isfile(path): + return True + + if any(module.modified for module in self.modules.values()): + return True + + return False + + def find_modules(self): + modules = [] + for root, _, files in os.walk(self.path): + module_root = root[len(self.path):] + module_root = [c for c in module_root.split(os.sep) if c] + + tests_in_module = fnmatch.filter(files, "*.c") + + for test_file in tests_in_module: + full_path = os.path.join(root, test_file) + module_name = "_".join(module_root + [test_file[:-2]]) + + modules.append((full_path, module_name)) + + return modules + + def load_cache(self): + path = os.path.join(self.path, '.clarcache') + cache = {} + + try: + fp = open(path, 'rb') + cache = pickle.load(fp) + fp.close() + except (IOError, ValueError): + pass + + return cache + + def save_cache(self): + path = os.path.join(self.path, '.clarcache') + with open(path, 'wb') as cache: + pickle.dump(self.modules, cache) + + def load(self, force = False): + module_data = self.find_modules() + self.modules = {} if force else self.load_cache() + + for path, name in module_data: + if name not in self.modules: + self.modules[name] = Module(name) + + if not self.modules[name].refresh(path): + del self.modules[name] + + def disable(self, excluded): + for exclude in excluded: + for module in self.modules.values(): + name = module.clean_name() + if name.startswith(exclude): + module.enabled = False + module.modified = True + + def suite_count(self): + return len(self.modules) + + def callback_count(self): + return sum(len(module.callbacks) for module in self.modules.values()) + + def write(self): + output = os.path.join(self.path, 'clar.suite') + + if not self.should_generate(output): + return False + + with open(output, 'w') as data: + for module in self.modules.values(): + t = Module.DeclarationTemplate(module) + data.write(t.render()) + + for module in self.modules.values(): + t = Module.CallbacksTemplate(module) + data.write(t.render()) + + suites = "static struct clar_suite _clar_suites[] = {" + ','.join( + Module.InfoTemplate(module).render() for module in sorted(self.modules.values(), key=lambda module: module.name) + ) + "\n};\n" + + data.write(suites) + + data.write("static const size_t _clar_suite_count = %d;\n" % self.suite_count()) + data.write("static const size_t _clar_callback_count = %d;\n" % self.callback_count()) + + suite.save_cache() + return True + +if __name__ == '__main__': + from optparse import OptionParser + + parser = OptionParser() + parser.add_option('-f', '--force', dest='force', default=False) + parser.add_option('-x', '--exclude', dest='excluded', action='append', default=[]) + + options, args = parser.parse_args() + + for path in args or ['.']: + suite = TestSuite(path) + suite.load(options.force) + suite.disable(options.excluded) + if suite.write(): + print("Written `clar.suite` (%d tests in %d suites)" % (suite.callback_count(), suite.suite_count())) + diff --git a/tests/index/addall.c b/tests/index/addall.c new file mode 100644 index 000000000..44c51279d --- /dev/null +++ b/tests/index/addall.c @@ -0,0 +1,258 @@ +#include "clar_libgit2.h" +#include "../status/status_helpers.h" +#include "posix.h" +#include "fileops.h" + +git_repository *g_repo = NULL; + +void test_index_addall__initialize(void) +{ +} + +void test_index_addall__cleanup(void) +{ + git_repository_free(g_repo); + g_repo = NULL; +} + +#define STATUS_INDEX_FLAGS \ + (GIT_STATUS_INDEX_NEW | GIT_STATUS_INDEX_MODIFIED | \ + GIT_STATUS_INDEX_DELETED | GIT_STATUS_INDEX_RENAMED | \ + GIT_STATUS_INDEX_TYPECHANGE) + +#define STATUS_WT_FLAGS \ + (GIT_STATUS_WT_NEW | GIT_STATUS_WT_MODIFIED | \ + GIT_STATUS_WT_DELETED | GIT_STATUS_WT_TYPECHANGE | \ + GIT_STATUS_WT_RENAMED) + +typedef struct { + size_t index_adds; + size_t index_dels; + size_t index_mods; + size_t wt_adds; + size_t wt_dels; + size_t wt_mods; + size_t ignores; +} index_status_counts; + +static int index_status_cb( + const char *path, unsigned int status_flags, void *payload) +{ + index_status_counts *vals = payload; + + /* cb_status__print(path, status_flags, NULL); */ + + GIT_UNUSED(path); + + if (status_flags & GIT_STATUS_INDEX_NEW) + vals->index_adds++; + if (status_flags & GIT_STATUS_INDEX_MODIFIED) + vals->index_mods++; + if (status_flags & GIT_STATUS_INDEX_DELETED) + vals->index_dels++; + if (status_flags & GIT_STATUS_INDEX_TYPECHANGE) + vals->index_mods++; + + if (status_flags & GIT_STATUS_WT_NEW) + vals->wt_adds++; + if (status_flags & GIT_STATUS_WT_MODIFIED) + vals->wt_mods++; + if (status_flags & GIT_STATUS_WT_DELETED) + vals->wt_dels++; + if (status_flags & GIT_STATUS_WT_TYPECHANGE) + vals->wt_mods++; + + if (status_flags & GIT_STATUS_IGNORED) + vals->ignores++; + + return 0; +} + +static void check_status_at_line( + git_repository *repo, + size_t index_adds, size_t index_dels, size_t index_mods, + size_t wt_adds, size_t wt_dels, size_t wt_mods, size_t ignores, + const char *file, int line) +{ + index_status_counts vals; + + memset(&vals, 0, sizeof(vals)); + + cl_git_pass(git_status_foreach(repo, index_status_cb, &vals)); + + clar__assert_equal( + file,line,"wrong index adds", 1, "%"PRIuZ, index_adds, vals.index_adds); + clar__assert_equal( + file,line,"wrong index dels", 1, "%"PRIuZ, index_dels, vals.index_dels); + clar__assert_equal( + file,line,"wrong index mods", 1, "%"PRIuZ, index_mods, vals.index_mods); + clar__assert_equal( + file,line,"wrong workdir adds", 1, "%"PRIuZ, wt_adds, vals.wt_adds); + clar__assert_equal( + file,line,"wrong workdir dels", 1, "%"PRIuZ, wt_dels, vals.wt_dels); + clar__assert_equal( + file,line,"wrong workdir mods", 1, "%"PRIuZ, wt_mods, vals.wt_mods); + clar__assert_equal( + file,line,"wrong ignores", 1, "%"PRIuZ, ignores, vals.ignores); +} + +#define check_status(R,IA,ID,IM,WA,WD,WM,IG) \ + check_status_at_line(R,IA,ID,IM,WA,WD,WM,IG,__FILE__,__LINE__) + +static void check_stat_data(git_index *index, const char *path, bool match) +{ + const git_index_entry *entry; + struct stat st; + + cl_must_pass(p_lstat(path, &st)); + + /* skip repo base dir name */ + while (*path != '/') + ++path; + ++path; + + entry = git_index_get_bypath(index, path, 0); + cl_assert(entry); + + if (match) { + cl_assert(st.st_ctime == entry->ctime.seconds); + cl_assert(st.st_mtime == entry->mtime.seconds); + cl_assert(st.st_size == entry->file_size); + cl_assert(st.st_uid == entry->uid); + cl_assert(st.st_gid == entry->gid); + cl_assert_equal_i_fmt( + GIT_MODE_TYPE(st.st_mode), GIT_MODE_TYPE(entry->mode), "%07o"); + if (cl_is_chmod_supported()) + cl_assert_equal_b( + GIT_PERMS_IS_EXEC(st.st_mode), GIT_PERMS_IS_EXEC(entry->mode)); + } else { + /* most things will still match */ + cl_assert(st.st_size != entry->file_size); + /* would check mtime, but with second resolution it won't work :( */ + } +} + +void test_index_addall__repo_lifecycle(void) +{ + int error; + git_index *index; + git_strarray paths = { NULL, 0 }; + char *strs[1]; + + cl_git_pass(git_repository_init(&g_repo, "addall", false)); + check_status(g_repo, 0, 0, 0, 0, 0, 0, 0); + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_mkfile("addall/file.foo", "a file"); + check_status(g_repo, 0, 0, 0, 1, 0, 0, 0); + + cl_git_mkfile("addall/.gitignore", "*.foo\n"); + check_status(g_repo, 0, 0, 0, 1, 0, 0, 1); + + cl_git_mkfile("addall/file.bar", "another file"); + check_status(g_repo, 0, 0, 0, 2, 0, 0, 1); + + strs[0] = "file.*"; + paths.strings = strs; + paths.count = 1; + + cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL)); + check_stat_data(index, "addall/file.bar", true); + check_status(g_repo, 1, 0, 0, 1, 0, 0, 1); + + cl_git_rewritefile("addall/file.bar", "new content for file"); + check_stat_data(index, "addall/file.bar", false); + check_status(g_repo, 1, 0, 0, 1, 0, 1, 1); + + cl_git_mkfile("addall/file.zzz", "yet another one"); + cl_git_mkfile("addall/other.zzz", "yet another one"); + cl_git_mkfile("addall/more.zzz", "yet another one"); + check_status(g_repo, 1, 0, 0, 4, 0, 1, 1); + + cl_git_pass(git_index_update_all(index, NULL, NULL, NULL)); + check_stat_data(index, "addall/file.bar", true); + check_status(g_repo, 1, 0, 0, 4, 0, 0, 1); + + cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL)); + check_stat_data(index, "addall/file.zzz", true); + check_status(g_repo, 2, 0, 0, 3, 0, 0, 1); + + cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "first commit"); + check_status(g_repo, 0, 0, 0, 3, 0, 0, 1); + + /* attempt to add an ignored file - does nothing */ + strs[0] = "file.foo"; + cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL)); + check_status(g_repo, 0, 0, 0, 3, 0, 0, 1); + + /* add with check - should generate error */ + error = git_index_add_all( + index, &paths, GIT_INDEX_ADD_CHECK_PATHSPEC, NULL, NULL); + cl_assert_equal_i(GIT_EINVALIDSPEC, error); + check_status(g_repo, 0, 0, 0, 3, 0, 0, 1); + + /* add with force - should allow */ + cl_git_pass(git_index_add_all( + index, &paths, GIT_INDEX_ADD_FORCE, NULL, NULL)); + check_stat_data(index, "addall/file.foo", true); + check_status(g_repo, 1, 0, 0, 3, 0, 0, 0); + + /* now it's in the index, so regular add should work */ + cl_git_rewritefile("addall/file.foo", "new content for file"); + check_stat_data(index, "addall/file.foo", false); + check_status(g_repo, 1, 0, 0, 3, 0, 1, 0); + + cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL)); + check_stat_data(index, "addall/file.foo", true); + check_status(g_repo, 1, 0, 0, 3, 0, 0, 0); + + cl_git_pass(git_index_add_bypath(index, "more.zzz")); + check_stat_data(index, "addall/more.zzz", true); + check_status(g_repo, 2, 0, 0, 2, 0, 0, 0); + + cl_git_rewritefile("addall/file.zzz", "new content for file"); + check_status(g_repo, 2, 0, 0, 2, 0, 1, 0); + + cl_git_pass(git_index_add_bypath(index, "file.zzz")); + check_stat_data(index, "addall/file.zzz", true); + check_status(g_repo, 2, 0, 1, 2, 0, 0, 0); + + strs[0] = "*.zzz"; + cl_git_pass(git_index_remove_all(index, &paths, NULL, NULL)); + check_status(g_repo, 1, 1, 0, 4, 0, 0, 0); + + cl_git_pass(git_index_add_bypath(index, "file.zzz")); + check_status(g_repo, 1, 0, 1, 3, 0, 0, 0); + + cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "second commit"); + check_status(g_repo, 0, 0, 0, 3, 0, 0, 0); + + cl_must_pass(p_unlink("addall/file.zzz")); + check_status(g_repo, 0, 0, 0, 3, 1, 0, 0); + + /* update_all should be able to remove entries */ + cl_git_pass(git_index_update_all(index, NULL, NULL, NULL)); + check_status(g_repo, 0, 1, 0, 3, 0, 0, 0); + + strs[0] = "*"; + cl_git_pass(git_index_add_all(index, &paths, 0, NULL, NULL)); + check_status(g_repo, 3, 1, 0, 0, 0, 0, 0); + + /* must be able to remove at any position while still updating other files */ + cl_must_pass(p_unlink("addall/.gitignore")); + cl_git_rewritefile("addall/file.zzz", "reconstructed file"); + cl_git_rewritefile("addall/more.zzz", "altered file reality"); + check_status(g_repo, 3, 1, 0, 1, 1, 1, 0); + + cl_git_pass(git_index_update_all(index, NULL, NULL, NULL)); + check_status(g_repo, 2, 1, 0, 1, 0, 0, 0); + /* this behavior actually matches 'git add -u' where "file.zzz" has + * been removed from the index, so when you go to update, even though + * it exists in the HEAD, it is not re-added to the index, leaving it + * as a DELETE when comparing HEAD to index and as an ADD comparing + * index to worktree + */ + + git_index_free(index); +} diff --git a/tests/index/conflicts.c b/tests/index/conflicts.c new file mode 100644 index 000000000..6311b3a75 --- /dev/null +++ b/tests/index/conflicts.c @@ -0,0 +1,287 @@ +#include "clar_libgit2.h" +#include "index.h" +#include "git2/repository.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "mergedrepo" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +#define CONFLICTS_ONE_ANCESTOR_OID "1f85ca51b8e0aac893a621b61a9c2661d6aa6d81" +#define CONFLICTS_ONE_OUR_OID "6aea5f295304c36144ad6e9247a291b7f8112399" +#define CONFLICTS_ONE_THEIR_OID "516bd85f78061e09ccc714561d7b504672cb52da" + +#define CONFLICTS_TWO_ANCESTOR_OID "84af62840be1b1c47b778a8a249f3ff45155038c" +#define CONFLICTS_TWO_OUR_OID "8b3f43d2402825c200f835ca1762413e386fd0b2" +#define CONFLICTS_TWO_THEIR_OID "220bd62631c8cf7a83ef39c6b94595f00517211e" + +#define TEST_ANCESTOR_OID "f00ff00ff00ff00ff00ff00ff00ff00ff00ff00f" +#define TEST_OUR_OID "b44bb44bb44bb44bb44bb44bb44bb44bb44bb44b" +#define TEST_THEIR_OID "0123456789abcdef0123456789abcdef01234567" + +// Fixture setup and teardown +void test_index_conflicts__initialize(void) +{ + repo = cl_git_sandbox_init("mergedrepo"); + git_repository_index(&repo_index, repo); +} + +void test_index_conflicts__cleanup(void) +{ + git_index_free(repo_index); + repo_index = NULL; + + cl_git_sandbox_cleanup(); +} + +void test_index_conflicts__add(void) +{ + git_index_entry ancestor_entry, our_entry, their_entry; + + cl_assert(git_index_entrycount(repo_index) == 8); + + memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); + memset(&our_entry, 0x0, sizeof(git_index_entry)); + memset(&their_entry, 0x0, sizeof(git_index_entry)); + + ancestor_entry.path = "test-one.txt"; + ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&ancestor_entry.oid, TEST_ANCESTOR_OID); + + our_entry.path = "test-one.txt"; + ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&our_entry.oid, TEST_OUR_OID); + + their_entry.path = "test-one.txt"; + ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&their_entry.oid, TEST_THEIR_OID); + + cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry)); + + cl_assert(git_index_entrycount(repo_index) == 11); +} + +void test_index_conflicts__add_fixes_incorrect_stage(void) +{ + git_index_entry ancestor_entry, our_entry, their_entry; + const git_index_entry *conflict_entry[3]; + + cl_assert(git_index_entrycount(repo_index) == 8); + + memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); + memset(&our_entry, 0x0, sizeof(git_index_entry)); + memset(&their_entry, 0x0, sizeof(git_index_entry)); + + ancestor_entry.path = "test-one.txt"; + ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&ancestor_entry.oid, TEST_ANCESTOR_OID); + + our_entry.path = "test-one.txt"; + ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&our_entry.oid, TEST_OUR_OID); + + their_entry.path = "test-one.txt"; + ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&their_entry.oid, TEST_THEIR_OID); + + cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry)); + + cl_assert(git_index_entrycount(repo_index) == 11); + + cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], repo_index, "test-one.txt")); + + cl_assert(git_index_entry_stage(conflict_entry[0]) == 1); + cl_assert(git_index_entry_stage(conflict_entry[1]) == 2); + cl_assert(git_index_entry_stage(conflict_entry[2]) == 3); +} + +void test_index_conflicts__get(void) +{ + const git_index_entry *conflict_entry[3]; + git_oid oid; + + cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], + &conflict_entry[2], repo_index, "conflicts-one.txt")); + + cl_assert_equal_s("conflicts-one.txt", conflict_entry[0]->path); + + git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID); + cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0); + + git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID); + cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0); + + git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID); + cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0); + + cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], + &conflict_entry[2], repo_index, "conflicts-two.txt")); + + cl_assert_equal_s("conflicts-two.txt", conflict_entry[0]->path); + + git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0); + + git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID); + cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0); + + git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID); + cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0); +} + +void test_index_conflicts__iterate(void) +{ + git_index_conflict_iterator *iterator; + const git_index_entry *conflict_entry[3]; + git_oid oid; + + cl_git_pass(git_index_conflict_iterator_new(&iterator, repo_index)); + + cl_git_pass(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator)); + + git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID); + cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0); + cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0); + + git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID); + cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0); + cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0); + + git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID); + cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0); + cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0); + + cl_git_pass(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator)); + + git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&conflict_entry[0]->oid, &oid) == 0); + cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0); + + git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID); + cl_assert(git_oid_cmp(&conflict_entry[1]->oid, &oid) == 0); + cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0); + + git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID); + cl_assert(git_oid_cmp(&conflict_entry[2]->oid, &oid) == 0); + cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0); + + cl_assert(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator) == GIT_ITEROVER); + + cl_assert(conflict_entry[0] == NULL); + cl_assert(conflict_entry[2] == NULL); + cl_assert(conflict_entry[2] == NULL); + + git_index_conflict_iterator_free(iterator); +} + +void test_index_conflicts__remove(void) +{ + const git_index_entry *entry; + size_t i; + + cl_assert(git_index_entrycount(repo_index) == 8); + + cl_git_pass(git_index_conflict_remove(repo_index, "conflicts-one.txt")); + cl_assert(git_index_entrycount(repo_index) == 5); + + for (i = 0; i < git_index_entrycount(repo_index); i++) { + cl_assert(entry = git_index_get_byindex(repo_index, i)); + cl_assert(strcmp(entry->path, "conflicts-one.txt") != 0); + } + + cl_git_pass(git_index_conflict_remove(repo_index, "conflicts-two.txt")); + cl_assert(git_index_entrycount(repo_index) == 2); + + for (i = 0; i < git_index_entrycount(repo_index); i++) { + cl_assert(entry = git_index_get_byindex(repo_index, i)); + cl_assert(strcmp(entry->path, "conflicts-two.txt") != 0); + } +} + +void test_index_conflicts__moved_to_reuc_on_add(void) +{ + const git_index_entry *entry; + size_t i; + + cl_assert(git_index_entrycount(repo_index) == 8); + + cl_git_mkfile("./mergedrepo/conflicts-one.txt", "new-file\n"); + + cl_git_pass(git_index_add_bypath(repo_index, "conflicts-one.txt")); + + cl_assert(git_index_entrycount(repo_index) == 6); + + for (i = 0; i < git_index_entrycount(repo_index); i++) { + cl_assert(entry = git_index_get_byindex(repo_index, i)); + + if (strcmp(entry->path, "conflicts-one.txt") == 0) + cl_assert(git_index_entry_stage(entry) == 0); + } +} + +void test_index_conflicts__moved_to_reuc_on_remove(void) +{ + const git_index_entry *entry; + size_t i; + + cl_assert(git_index_entrycount(repo_index) == 8); + + cl_git_pass(p_unlink("./mergedrepo/conflicts-one.txt")); + + cl_git_pass(git_index_remove_bypath(repo_index, "conflicts-one.txt")); + + cl_assert(git_index_entrycount(repo_index) == 5); + + for (i = 0; i < git_index_entrycount(repo_index); i++) { + cl_assert(entry = git_index_get_byindex(repo_index, i)); + cl_assert(strcmp(entry->path, "conflicts-one.txt") != 0); + } +} + +void test_index_conflicts__remove_all_conflicts(void) +{ + size_t i; + const git_index_entry *entry; + + cl_assert(git_index_entrycount(repo_index) == 8); + + cl_assert_equal_i(true, git_index_has_conflicts(repo_index)); + + git_index_conflict_cleanup(repo_index); + + cl_assert_equal_i(false, git_index_has_conflicts(repo_index)); + + cl_assert(git_index_entrycount(repo_index) == 2); + + for (i = 0; i < git_index_entrycount(repo_index); i++) { + cl_assert(entry = git_index_get_byindex(repo_index, i)); + cl_assert(git_index_entry_stage(entry) == 0); + } +} + +void test_index_conflicts__partial(void) +{ + git_index_entry ancestor_entry, our_entry, their_entry; + const git_index_entry *conflict_entry[3]; + + cl_assert(git_index_entrycount(repo_index) == 8); + + memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); + memset(&our_entry, 0x0, sizeof(git_index_entry)); + memset(&their_entry, 0x0, sizeof(git_index_entry)); + + ancestor_entry.path = "test-one.txt"; + ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&ancestor_entry.oid, TEST_ANCESTOR_OID); + + cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, NULL, NULL)); + cl_assert(git_index_entrycount(repo_index) == 9); + + cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], + &conflict_entry[2], repo_index, "test-one.txt")); + + cl_assert(git_oid_cmp(&ancestor_entry.oid, &conflict_entry[0]->oid) == 0); + cl_assert(conflict_entry[1] == NULL); + cl_assert(conflict_entry[2] == NULL); +} diff --git a/tests/index/filemodes.c b/tests/index/filemodes.c new file mode 100644 index 000000000..013932696 --- /dev/null +++ b/tests/index/filemodes.c @@ -0,0 +1,154 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "posix.h" +#include "index.h" + +static git_repository *g_repo = NULL; + +void test_index_filemodes__initialize(void) +{ + g_repo = cl_git_sandbox_init("filemodes"); +} + +void test_index_filemodes__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_index_filemodes__read(void) +{ + git_index *index; + unsigned int i; + static bool expected[6] = { 0, 1, 0, 1, 0, 1 }; + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_assert_equal_i(6, (int)git_index_entrycount(index)); + + for (i = 0; i < 6; ++i) { + const git_index_entry *entry = git_index_get_byindex(index, i); + cl_assert(entry != NULL); + cl_assert(((entry->mode & 0100) ? 1 : 0) == expected[i]); + } + + git_index_free(index); +} + +static void replace_file_with_mode( + const char *filename, const char *backup, unsigned int create_mode) +{ + git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&path, "filemodes", filename)); + cl_git_pass(git_buf_printf(&content, "%s as %08u (%d)", + filename, create_mode, rand())); + + cl_git_pass(p_rename(path.ptr, backup)); + cl_git_write2file( + path.ptr, content.ptr, content.size, + O_WRONLY|O_CREAT|O_TRUNC, create_mode); + + git_buf_free(&path); + git_buf_free(&content); +} + +#define add_and_check_mode(I,F,X) add_and_check_mode_(I,F,X,__FILE__,__LINE__) + +static void add_and_check_mode_( + git_index *index, const char *filename, unsigned int expect_mode, + const char *file, int line) +{ + size_t pos; + const git_index_entry *entry; + + cl_git_pass(git_index_add_bypath(index, filename)); + + clar__assert(!git_index_find(&pos, index, filename), + file, line, "Cannot find index entry", NULL, 1); + + entry = git_index_get_byindex(index, pos); + + clar__assert_equal(file, line, "Expected mode does not match index", + 1, "%07o", (unsigned int)entry->mode, (unsigned int)expect_mode); +} + +void test_index_filemodes__untrusted(void) +{ + git_index *index; + + cl_repo_set_bool(g_repo, "core.filemode", false); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_assert((git_index_caps(index) & GIT_INDEXCAP_NO_FILEMODE) != 0); + + /* 1 - add 0644 over existing 0644 -> expect 0644 */ + replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644); + add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB); + + /* 2 - add 0644 over existing 0755 -> expect 0755 */ + replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644); + add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); + + /* 3 - add 0755 over existing 0644 -> expect 0644 */ + replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755); + add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB); + + /* 4 - add 0755 over existing 0755 -> expect 0755 */ + replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755); + add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); + + /* 5 - add new 0644 -> expect 0644 */ + cl_git_write2file("filemodes/new_off", "blah", 0, + O_WRONLY | O_CREAT | O_TRUNC, 0644); + add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); + + /* 6 - add new 0755 -> expect 0644 if core.filemode == false */ + cl_git_write2file("filemodes/new_on", "blah", 0, + O_WRONLY | O_CREAT | O_TRUNC, 0755); + add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB); + + git_index_free(index); +} + +void test_index_filemodes__trusted(void) +{ + git_index *index; + + /* Only run these tests on platforms where I can actually + * chmod a file and get the stat results I expect! + */ + if (!cl_is_chmod_supported()) + return; + + cl_repo_set_bool(g_repo, "core.filemode", true); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_assert((git_index_caps(index) & GIT_INDEXCAP_NO_FILEMODE) == 0); + + /* 1 - add 0644 over existing 0644 -> expect 0644 */ + replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644); + add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB); + + /* 2 - add 0644 over existing 0755 -> expect 0644 */ + replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644); + add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB); + + /* 3 - add 0755 over existing 0644 -> expect 0755 */ + replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755); + add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB_EXECUTABLE); + + /* 4 - add 0755 over existing 0755 -> expect 0755 */ + replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755); + add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); + + /* 5 - add new 0644 -> expect 0644 */ + cl_git_write2file("filemodes/new_off", "blah", 0, + O_WRONLY | O_CREAT | O_TRUNC, 0644); + add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); + + /* 6 - add 0755 -> expect 0755 */ + cl_git_write2file("filemodes/new_on", "blah", 0, + O_WRONLY | O_CREAT | O_TRUNC, 0755); + add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE); + + git_index_free(index); +} diff --git a/tests/index/inmemory.c b/tests/index/inmemory.c new file mode 100644 index 000000000..38e91e0fd --- /dev/null +++ b/tests/index/inmemory.c @@ -0,0 +1,22 @@ +#include "clar_libgit2.h" + +void test_index_inmemory__can_create_an_inmemory_index(void) +{ + git_index *index; + + cl_git_pass(git_index_new(&index)); + cl_assert_equal_i(0, (int)git_index_entrycount(index)); + + git_index_free(index); +} + +void test_index_inmemory__cannot_add_bypath_to_an_inmemory_index(void) +{ + git_index *index; + + cl_git_pass(git_index_new(&index)); + + cl_assert_equal_i(GIT_ERROR, git_index_add_bypath(index, "test.txt")); + + git_index_free(index); +} diff --git a/tests/index/names.c b/tests/index/names.c new file mode 100644 index 000000000..9007b1b15 --- /dev/null +++ b/tests/index/names.c @@ -0,0 +1,148 @@ +#include "clar_libgit2.h" +#include "index.h" +#include "git2/sys/index.h" +#include "git2/repository.h" +#include "../reset/reset_helpers.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "mergedrepo" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +// Fixture setup and teardown +void test_index_names__initialize(void) +{ + repo = cl_git_sandbox_init("mergedrepo"); + git_repository_index(&repo_index, repo); +} + +void test_index_names__cleanup(void) +{ + git_index_free(repo_index); + repo_index = NULL; + + cl_git_sandbox_cleanup(); +} + +void test_index_names__add(void) +{ + const git_index_name_entry *conflict_name; + + cl_git_pass(git_index_name_add(repo_index, "ancestor", "ours", "theirs")); + cl_git_pass(git_index_name_add(repo_index, "ancestor2", "ours2", NULL)); + cl_git_pass(git_index_name_add(repo_index, "ancestor3", NULL, "theirs3")); + + cl_assert(git_index_name_entrycount(repo_index) == 3); + + conflict_name = git_index_name_get_byindex(repo_index, 0); + cl_assert(strcmp(conflict_name->ancestor, "ancestor") == 0); + cl_assert(strcmp(conflict_name->ours, "ours") == 0); + cl_assert(strcmp(conflict_name->theirs, "theirs") == 0); + + conflict_name = git_index_name_get_byindex(repo_index, 1); + cl_assert(strcmp(conflict_name->ancestor, "ancestor2") == 0); + cl_assert(strcmp(conflict_name->ours, "ours2") == 0); + cl_assert(conflict_name->theirs == NULL); + + conflict_name = git_index_name_get_byindex(repo_index, 2); + cl_assert(strcmp(conflict_name->ancestor, "ancestor3") == 0); + cl_assert(conflict_name->ours == NULL); + cl_assert(strcmp(conflict_name->theirs, "theirs3") == 0); +} + +void test_index_names__roundtrip(void) +{ + const git_index_name_entry *conflict_name; + + cl_git_pass(git_index_name_add(repo_index, "ancestor", "ours", "theirs")); + cl_git_pass(git_index_name_add(repo_index, "ancestor2", "ours2", NULL)); + cl_git_pass(git_index_name_add(repo_index, "ancestor3", NULL, "theirs3")); + + cl_git_pass(git_index_write(repo_index)); + git_index_clear(repo_index); + cl_assert(git_index_name_entrycount(repo_index) == 0); + + cl_git_pass(git_index_read(repo_index, true)); + cl_assert(git_index_name_entrycount(repo_index) == 3); + + conflict_name = git_index_name_get_byindex(repo_index, 0); + cl_assert(strcmp(conflict_name->ancestor, "ancestor") == 0); + cl_assert(strcmp(conflict_name->ours, "ours") == 0); + cl_assert(strcmp(conflict_name->theirs, "theirs") == 0); + + conflict_name = git_index_name_get_byindex(repo_index, 1); + cl_assert(strcmp(conflict_name->ancestor, "ancestor2") == 0); + cl_assert(strcmp(conflict_name->ours, "ours2") == 0); + cl_assert(conflict_name->theirs == NULL); + + conflict_name = git_index_name_get_byindex(repo_index, 2); + cl_assert(strcmp(conflict_name->ancestor, "ancestor3") == 0); + cl_assert(conflict_name->ours == NULL); + cl_assert(strcmp(conflict_name->theirs, "theirs3") == 0); +} + +void test_index_names__cleaned_on_reset_hard(void) +{ + git_object *target; + + retrieve_target_from_oid(&target, repo, "3a34580a35add43a4cf361e8e9a30060a905c876"); + + test_index_names__add(); + cl_git_pass(git_reset(repo, target, GIT_RESET_HARD)); + cl_assert(git_index_name_entrycount(repo_index) == 0); + + git_object_free(target); +} + +void test_index_names__cleaned_on_reset_mixed(void) +{ + git_object *target; + + retrieve_target_from_oid(&target, repo, "3a34580a35add43a4cf361e8e9a30060a905c876"); + + test_index_names__add(); + cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED)); + cl_assert(git_index_name_entrycount(repo_index) == 0); + + git_object_free(target); +} + +void test_index_names__cleaned_on_checkout_tree(void) +{ + git_oid oid; + git_object *obj; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; + + test_index_names__add(); + git_reference_name_to_id(&oid, repo, "refs/heads/master"); + git_object_lookup(&obj, repo, &oid, GIT_OBJ_ANY); + git_checkout_tree(repo, obj, &opts); + cl_assert_equal_sz(0, git_index_name_entrycount(repo_index)); + + git_object_free(obj); +} + +void test_index_names__cleaned_on_checkout_head(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; + + test_index_names__add(); + git_checkout_head(repo, &opts); + cl_assert_equal_sz(0, git_index_name_entrycount(repo_index)); +} + +void test_index_names__retained_on_checkout_index(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; + + test_index_names__add(); + git_checkout_index(repo, repo_index, &opts); + cl_assert(git_index_name_entrycount(repo_index) > 0); +} diff --git a/tests/index/read_tree.c b/tests/index/read_tree.c new file mode 100644 index 000000000..6c6b40121 --- /dev/null +++ b/tests/index/read_tree.c @@ -0,0 +1,46 @@ +#include "clar_libgit2.h" +#include "posix.h" + +/* Test that reading and writing a tree is a no-op */ +void test_index_read_tree__read_write_involution(void) +{ + git_repository *repo; + git_index *index; + git_oid tree_oid; + git_tree *tree; + git_oid expected; + + p_mkdir("read_tree", 0700); + + cl_git_pass(git_repository_init(&repo, "./read_tree", 0)); + cl_git_pass(git_repository_index(&index, repo)); + + cl_assert(git_index_entrycount(index) == 0); + + p_mkdir("./read_tree/abc", 0700); + + /* Sort order: '-' < '/' < '_' */ + cl_git_mkfile("./read_tree/abc-d", NULL); + cl_git_mkfile("./read_tree/abc/d", NULL); + cl_git_mkfile("./read_tree/abc_d", NULL); + + cl_git_pass(git_index_add_bypath(index, "abc-d")); + cl_git_pass(git_index_add_bypath(index, "abc_d")); + cl_git_pass(git_index_add_bypath(index, "abc/d")); + + /* write-tree */ + cl_git_pass(git_index_write_tree(&expected, index)); + + /* read-tree */ + git_tree_lookup(&tree, repo, &expected); + cl_git_pass(git_index_read_tree(index, tree)); + git_tree_free(tree); + + cl_git_pass(git_index_write_tree(&tree_oid, index)); + cl_assert(git_oid_cmp(&expected, &tree_oid) == 0); + + git_index_free(index); + git_repository_free(repo); + + cl_fixture_cleanup("read_tree"); +} diff --git a/tests/index/rename.c b/tests/index/rename.c new file mode 100644 index 000000000..4deef1332 --- /dev/null +++ b/tests/index/rename.c @@ -0,0 +1,50 @@ +#include "clar_libgit2.h" +#include "posix.h" + +void test_index_rename__single_file(void) +{ + git_repository *repo; + git_index *index; + size_t position; + git_oid expected; + const git_index_entry *entry; + + p_mkdir("rename", 0700); + + cl_git_pass(git_repository_init(&repo, "./rename", 0)); + cl_git_pass(git_repository_index(&index, repo)); + + cl_assert(git_index_entrycount(index) == 0); + + cl_git_mkfile("./rename/lame.name.txt", "new_file\n"); + + /* This should add a new blob to the object database in 'd4/fa8600b4f37d7516bef4816ae2c64dbf029e3a' */ + cl_git_pass(git_index_add_bypath(index, "lame.name.txt")); + cl_assert(git_index_entrycount(index) == 1); + + cl_git_pass(git_oid_fromstr(&expected, "d4fa8600b4f37d7516bef4816ae2c64dbf029e3a")); + + cl_assert(!git_index_find(&position, index, "lame.name.txt")); + + entry = git_index_get_byindex(index, position); + cl_assert(git_oid_cmp(&expected, &entry->oid) == 0); + + /* This removes the entry from the index, but not from the object database */ + cl_git_pass(git_index_remove(index, "lame.name.txt", 0)); + cl_assert(git_index_entrycount(index) == 0); + + p_rename("./rename/lame.name.txt", "./rename/fancy.name.txt"); + + cl_git_pass(git_index_add_bypath(index, "fancy.name.txt")); + cl_assert(git_index_entrycount(index) == 1); + + cl_assert(!git_index_find(&position, index, "fancy.name.txt")); + + entry = git_index_get_byindex(index, position); + cl_assert(git_oid_cmp(&expected, &entry->oid) == 0); + + git_index_free(index); + git_repository_free(repo); + + cl_fixture_cleanup("rename"); +} diff --git a/tests/index/reuc.c b/tests/index/reuc.c new file mode 100644 index 000000000..a18d5602e --- /dev/null +++ b/tests/index/reuc.c @@ -0,0 +1,372 @@ +#include "clar_libgit2.h" +#include "index.h" +#include "git2/sys/index.h" +#include "git2/repository.h" +#include "../reset/reset_helpers.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "mergedrepo" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +#define ONE_ANCESTOR_OID "478871385b9cd03908c5383acfd568bef023c6b3" +#define ONE_OUR_OID "4458b8bc9e72b6c8755ae456f60e9844d0538d8c" +#define ONE_THEIR_OID "8b72416545c7e761b64cecad4f1686eae4078aa8" + +#define TWO_ANCESTOR_OID "9d81f82fccc7dcd7de7a1ffead1815294c2e092c" +#define TWO_OUR_OID "8f3c06cff9a83757cec40c80bc9bf31a2582bde9" +#define TWO_THEIR_OID "887b153b165d32409c70163e0f734c090f12f673" + +// Fixture setup and teardown +void test_index_reuc__initialize(void) +{ + repo = cl_git_sandbox_init("mergedrepo"); + git_repository_index(&repo_index, repo); +} + +void test_index_reuc__cleanup(void) +{ + git_index_free(repo_index); + repo_index = NULL; + + cl_git_sandbox_cleanup(); +} + +void test_index_reuc__add(void) +{ + git_oid ancestor_oid, our_oid, their_oid; + const git_index_reuc_entry *reuc; + + git_oid_fromstr(&ancestor_oid, ONE_ANCESTOR_OID); + git_oid_fromstr(&our_oid, ONE_OUR_OID); + git_oid_fromstr(&their_oid, ONE_THEIR_OID); + + cl_git_pass(git_index_reuc_add(repo_index, "newfile.txt", + 0100644, &ancestor_oid, + 0100644, &our_oid, + 0100644, &their_oid)); + + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "newfile.txt")); + + cl_assert_equal_s("newfile.txt", reuc->path); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + cl_assert(git_oid_cmp(&reuc->oid[0], &ancestor_oid) == 0); + cl_assert(git_oid_cmp(&reuc->oid[1], &our_oid) == 0); + cl_assert(git_oid_cmp(&reuc->oid[2], &their_oid) == 0); +} + +void test_index_reuc__add_no_ancestor(void) +{ + git_oid ancestor_oid, our_oid, their_oid; + const git_index_reuc_entry *reuc; + + memset(&ancestor_oid, 0x0, sizeof(git_oid)); + git_oid_fromstr(&our_oid, ONE_OUR_OID); + git_oid_fromstr(&their_oid, ONE_THEIR_OID); + + cl_git_pass(git_index_reuc_add(repo_index, "newfile.txt", + 0, NULL, + 0100644, &our_oid, + 0100644, &their_oid)); + + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "newfile.txt")); + + cl_assert_equal_s("newfile.txt", reuc->path); + cl_assert(reuc->mode[0] == 0); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + cl_assert(git_oid_cmp(&reuc->oid[0], &ancestor_oid) == 0); + cl_assert(git_oid_cmp(&reuc->oid[1], &our_oid) == 0); + cl_assert(git_oid_cmp(&reuc->oid[2], &their_oid) == 0); +} + +void test_index_reuc__read_bypath(void) +{ + const git_index_reuc_entry *reuc; + git_oid oid; + + cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); + + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "two.txt")); + + cl_assert_equal_s("two.txt", reuc->path); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + git_oid_fromstr(&oid, TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, TWO_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, TWO_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); + + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "one.txt")); + + cl_assert_equal_s("one.txt", reuc->path); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + git_oid_fromstr(&oid, ONE_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, ONE_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, ONE_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); +} + +void test_index_reuc__ignore_case(void) +{ + const git_index_reuc_entry *reuc; + git_oid oid; + int index_caps; + + index_caps = git_index_caps(repo_index); + + index_caps &= ~GIT_INDEXCAP_IGNORE_CASE; + cl_git_pass(git_index_set_caps(repo_index, index_caps)); + + cl_assert(!git_index_reuc_get_bypath(repo_index, "TWO.txt")); + + index_caps |= GIT_INDEXCAP_IGNORE_CASE; + cl_git_pass(git_index_set_caps(repo_index, index_caps)); + + cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); + + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "TWO.txt")); + + cl_assert_equal_s("two.txt", reuc->path); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + git_oid_fromstr(&oid, TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, TWO_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, TWO_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); +} + +void test_index_reuc__read_byindex(void) +{ + const git_index_reuc_entry *reuc; + git_oid oid; + + cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); + + cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 0)); + + cl_assert_equal_s("one.txt", reuc->path); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + git_oid_fromstr(&oid, ONE_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, ONE_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, ONE_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); + + cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 1)); + + cl_assert_equal_s("two.txt", reuc->path); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + git_oid_fromstr(&oid, TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, TWO_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, TWO_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); +} + +void test_index_reuc__updates_existing(void) +{ + const git_index_reuc_entry *reuc; + git_oid ancestor_oid, our_oid, their_oid, oid; + int index_caps; + + git_index_clear(repo_index); + + index_caps = git_index_caps(repo_index); + + index_caps |= GIT_INDEXCAP_IGNORE_CASE; + cl_git_pass(git_index_set_caps(repo_index, index_caps)); + + git_oid_fromstr(&ancestor_oid, TWO_ANCESTOR_OID); + git_oid_fromstr(&our_oid, TWO_OUR_OID); + git_oid_fromstr(&their_oid, TWO_THEIR_OID); + + cl_git_pass(git_index_reuc_add(repo_index, "two.txt", + 0100644, &ancestor_oid, + 0100644, &our_oid, + 0100644, &their_oid)); + + cl_git_pass(git_index_reuc_add(repo_index, "TWO.txt", + 0100644, &our_oid, + 0100644, &their_oid, + 0100644, &ancestor_oid)); + + cl_assert_equal_i(1, git_index_reuc_entrycount(repo_index)); + + cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 0)); + + cl_assert_equal_s("TWO.txt", reuc->path); + git_oid_fromstr(&oid, TWO_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, TWO_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); +} + +void test_index_reuc__remove(void) +{ + git_oid oid; + const git_index_reuc_entry *reuc; + + cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); + + cl_git_pass(git_index_reuc_remove(repo_index, 0)); + cl_git_fail(git_index_reuc_remove(repo_index, 1)); + + cl_assert_equal_i(1, git_index_reuc_entrycount(repo_index)); + + cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 0)); + + cl_assert_equal_s("two.txt", reuc->path); + cl_assert(reuc->mode[0] == 0100644); + cl_assert(reuc->mode[1] == 0100644); + cl_assert(reuc->mode[2] == 0100644); + git_oid_fromstr(&oid, TWO_ANCESTOR_OID); + cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + git_oid_fromstr(&oid, TWO_OUR_OID); + cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + git_oid_fromstr(&oid, TWO_THEIR_OID); + cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); +} + +void test_index_reuc__write(void) +{ + git_oid ancestor_oid, our_oid, their_oid; + const git_index_reuc_entry *reuc; + + git_index_clear(repo_index); + + /* Write out of order to ensure sorting is correct */ + git_oid_fromstr(&ancestor_oid, TWO_ANCESTOR_OID); + git_oid_fromstr(&our_oid, TWO_OUR_OID); + git_oid_fromstr(&their_oid, TWO_THEIR_OID); + + cl_git_pass(git_index_reuc_add(repo_index, "two.txt", + 0100644, &ancestor_oid, + 0100644, &our_oid, + 0100644, &their_oid)); + + git_oid_fromstr(&ancestor_oid, ONE_ANCESTOR_OID); + git_oid_fromstr(&our_oid, ONE_OUR_OID); + git_oid_fromstr(&their_oid, ONE_THEIR_OID); + + cl_git_pass(git_index_reuc_add(repo_index, "one.txt", + 0100644, &ancestor_oid, + 0100644, &our_oid, + 0100644, &their_oid)); + + cl_git_pass(git_index_write(repo_index)); + cl_assert_equal_i(2, git_index_reuc_entrycount(repo_index)); + + /* ensure sort order was round-tripped correct */ + cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 0)); + cl_assert_equal_s("one.txt", reuc->path); + + cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 1)); + cl_assert_equal_s("two.txt", reuc->path); +} + +static int reuc_entry_exists(void) +{ + return (git_index_reuc_get_bypath(repo_index, "newfile.txt") != NULL); +} + +void test_index_reuc__cleaned_on_reset_hard(void) +{ + git_object *target; + + retrieve_target_from_oid(&target, repo, "3a34580a35add43a4cf361e8e9a30060a905c876"); + + test_index_reuc__add(); + cl_git_pass(git_reset(repo, target, GIT_RESET_HARD)); + cl_assert(reuc_entry_exists() == false); + + git_object_free(target); +} + +void test_index_reuc__cleaned_on_reset_mixed(void) +{ + git_object *target; + + retrieve_target_from_oid(&target, repo, "3a34580a35add43a4cf361e8e9a30060a905c876"); + + test_index_reuc__add(); + cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED)); + cl_assert(reuc_entry_exists() == false); + + git_object_free(target); +} + +void test_index_reuc__retained_on_reset_soft(void) +{ + git_object *target; + + retrieve_target_from_oid(&target, repo, "3a34580a35add43a4cf361e8e9a30060a905c876"); + + git_reset(repo, target, GIT_RESET_HARD); + + test_index_reuc__add(); + cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT)); + cl_assert(reuc_entry_exists() == true); + + git_object_free(target); +} + +void test_index_reuc__cleaned_on_checkout_tree(void) +{ + git_oid oid; + git_object *obj; + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; + + test_index_reuc__add(); + git_reference_name_to_id(&oid, repo, "refs/heads/master"); + git_object_lookup(&obj, repo, &oid, GIT_OBJ_ANY); + git_checkout_tree(repo, obj, &opts); + cl_assert(reuc_entry_exists() == false); + + git_object_free(obj); +} + +void test_index_reuc__cleaned_on_checkout_head(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; + + test_index_reuc__add(); + git_checkout_head(repo, &opts); + cl_assert(reuc_entry_exists() == false); +} + +void test_index_reuc__retained_on_checkout_index(void) +{ + git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT; + + opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY; + + test_index_reuc__add(); + git_checkout_index(repo, repo_index, &opts); + cl_assert(reuc_entry_exists() == true); +} diff --git a/tests/index/stage.c b/tests/index/stage.c new file mode 100644 index 000000000..58dc1fb5e --- /dev/null +++ b/tests/index/stage.c @@ -0,0 +1,62 @@ +#include "clar_libgit2.h" +#include "index.h" +#include "git2/repository.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "mergedrepo" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +// Fixture setup and teardown +void test_index_stage__initialize(void) +{ + repo = cl_git_sandbox_init("mergedrepo"); + git_repository_index(&repo_index, repo); +} + +void test_index_stage__cleanup(void) +{ + git_index_free(repo_index); + repo_index = NULL; + + cl_git_sandbox_cleanup(); +} + + +void test_index_stage__add_always_adds_stage_0(void) +{ + size_t entry_idx; + const git_index_entry *entry; + + cl_git_mkfile("./mergedrepo/new-file.txt", "new-file\n"); + + cl_git_pass(git_index_add_bypath(repo_index, "new-file.txt")); + + cl_assert(!git_index_find(&entry_idx, repo_index, "new-file.txt")); + cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); + cl_assert(git_index_entry_stage(entry) == 0); +} + +void test_index_stage__find_gets_first_stage(void) +{ + size_t entry_idx; + const git_index_entry *entry; + + cl_assert(!git_index_find(&entry_idx, repo_index, "one.txt")); + cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); + cl_assert(git_index_entry_stage(entry) == 0); + + cl_assert(!git_index_find(&entry_idx, repo_index, "two.txt")); + cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); + cl_assert(git_index_entry_stage(entry) == 0); + + cl_assert(!git_index_find(&entry_idx, repo_index, "conflicts-one.txt")); + cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); + cl_assert(git_index_entry_stage(entry) == 1); + + cl_assert(!git_index_find(&entry_idx, repo_index, "conflicts-two.txt")); + cl_assert((entry = git_index_get_byindex(repo_index, entry_idx)) != NULL); + cl_assert(git_index_entry_stage(entry) == 1); +} + diff --git a/tests/index/tests.c b/tests/index/tests.c new file mode 100644 index 000000000..e5202980c --- /dev/null +++ b/tests/index/tests.c @@ -0,0 +1,537 @@ +#include "clar_libgit2.h" +#include "index.h" + +static const size_t index_entry_count = 109; +static const size_t index_entry_count_2 = 1437; +#define TEST_INDEX_PATH cl_fixture("testrepo.git/index") +#define TEST_INDEX2_PATH cl_fixture("gitgit.index") +#define TEST_INDEXBIG_PATH cl_fixture("big.index") + + +/* Suite data */ +struct test_entry { + size_t index; + char path[128]; + git_off_t file_size; + git_time_t mtime; +}; + +static struct test_entry test_entries[] = { + {4, "Makefile", 5064, 0x4C3F7F33}, + {62, "tests/Makefile", 2631, 0x4C3F7F33}, + {36, "src/index.c", 10014, 0x4C43368D}, + {6, "git.git-authors", 2709, 0x4C3F7F33}, + {48, "src/revobject.h", 1448, 0x4C3F7FE2} +}; + +/* Helpers */ +static void copy_file(const char *src, const char *dst) +{ + git_buf source_buf = GIT_BUF_INIT; + git_file dst_fd; + + cl_git_pass(git_futils_readbuffer(&source_buf, src)); + + dst_fd = git_futils_creat_withpath(dst, 0777, 0666); /* -V536 */ + if (dst_fd < 0) + goto cleanup; + + cl_git_pass(p_write(dst_fd, source_buf.ptr, source_buf.size)); + +cleanup: + git_buf_free(&source_buf); + p_close(dst_fd); +} + +static void files_are_equal(const char *a, const char *b) +{ + git_buf buf_a = GIT_BUF_INIT; + git_buf buf_b = GIT_BUF_INIT; + int pass; + + if (git_futils_readbuffer(&buf_a, a) < 0) + cl_assert(0); + + if (git_futils_readbuffer(&buf_b, b) < 0) { + git_buf_free(&buf_a); + cl_assert(0); + } + + pass = (buf_a.size == buf_b.size && !memcmp(buf_a.ptr, buf_b.ptr, buf_a.size)); + + git_buf_free(&buf_a); + git_buf_free(&buf_b); + + cl_assert(pass); +} + + +/* Fixture setup and teardown */ +void test_index_tests__initialize(void) +{ +} + +void test_index_tests__empty_index(void) +{ + git_index *index; + + cl_git_pass(git_index_open(&index, "in-memory-index")); + cl_assert(index->on_disk == 0); + + cl_assert(git_index_entrycount(index) == 0); + cl_assert(index->entries.sorted); + + git_index_free(index); +} + +void test_index_tests__default_test_index(void) +{ + git_index *index; + unsigned int i; + git_index_entry **entries; + + cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); + cl_assert(index->on_disk); + + cl_assert(git_index_entrycount(index) == index_entry_count); + cl_assert(index->entries.sorted); + + entries = (git_index_entry **)index->entries.contents; + + for (i = 0; i < ARRAY_SIZE(test_entries); ++i) { + git_index_entry *e = entries[test_entries[i].index]; + + cl_assert_equal_s(e->path, test_entries[i].path); + cl_assert(e->mtime.seconds == test_entries[i].mtime); + cl_assert(e->file_size == test_entries[i].file_size); + } + + git_index_free(index); +} + +void test_index_tests__gitgit_index(void) +{ + git_index *index; + + cl_git_pass(git_index_open(&index, TEST_INDEX2_PATH)); + cl_assert(index->on_disk); + + cl_assert(git_index_entrycount(index) == index_entry_count_2); + cl_assert(index->entries.sorted); + cl_assert(index->tree != NULL); + + git_index_free(index); +} + +void test_index_tests__find_in_existing(void) +{ + git_index *index; + unsigned int i; + + cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); + + for (i = 0; i < ARRAY_SIZE(test_entries); ++i) { + size_t idx; + + cl_assert(!git_index_find(&idx, index, test_entries[i].path)); + cl_assert(idx == test_entries[i].index); + } + + git_index_free(index); +} + +void test_index_tests__find_in_empty(void) +{ + git_index *index; + unsigned int i; + + cl_git_pass(git_index_open(&index, "fake-index")); + + for (i = 0; i < ARRAY_SIZE(test_entries); ++i) { + cl_assert(GIT_ENOTFOUND == git_index_find(NULL, index, test_entries[i].path)); + } + + git_index_free(index); +} + +void test_index_tests__write(void) +{ + git_index *index; + + copy_file(TEST_INDEXBIG_PATH, "index_rewrite"); + + cl_git_pass(git_index_open(&index, "index_rewrite")); + cl_assert(index->on_disk); + + cl_git_pass(git_index_write(index)); + files_are_equal(TEST_INDEXBIG_PATH, "index_rewrite"); + + git_index_free(index); + + p_unlink("index_rewrite"); +} + +void test_index_tests__sort0(void) +{ + /* sort the entires in an index */ + + /* + * TODO: This no longer applies: + * index sorting in Git uses some specific changes to the way + * directories are sorted. + * + * We need to specificially check for this by creating a new + * index, adding entries in random order and then + * checking for consistency + */ +} + +void test_index_tests__sort1(void) +{ + /* sort the entires in an empty index */ + git_index *index; + + cl_git_pass(git_index_open(&index, "fake-index")); + + /* FIXME: this test is slightly dumb */ + cl_assert(index->entries.sorted); + + git_index_free(index); +} + +static void cleanup_myrepo(void *opaque) +{ + GIT_UNUSED(opaque); + cl_fixture_cleanup("myrepo"); +} + +void test_index_tests__add(void) +{ + git_index *index; + git_filebuf file = GIT_FILEBUF_INIT; + git_repository *repo; + const git_index_entry *entry; + git_oid id1; + + cl_set_cleanup(&cleanup_myrepo, NULL); + + /* Intialize a new repository */ + cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); + + /* Ensure we're the only guy in the room */ + cl_git_pass(git_repository_index(&index, repo)); + cl_assert(git_index_entrycount(index) == 0); + + /* Create a new file in the working directory */ + cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777)); + cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0, 0666)); + cl_git_pass(git_filebuf_write(&file, "hey there\n", 10)); + cl_git_pass(git_filebuf_commit(&file)); + + /* Store the expected hash of the file/blob + * This has been generated by executing the following + * $ echo "hey there" | git hash-object --stdin + */ + cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); + + /* Add the new file to the index */ + cl_git_pass(git_index_add_bypath(index, "test.txt")); + + /* Wow... it worked! */ + cl_assert(git_index_entrycount(index) == 1); + entry = git_index_get_byindex(index, 0); + + /* And the built-in hashing mechanism worked as expected */ + cl_assert(git_oid_cmp(&id1, &entry->oid) == 0); + + /* Test access by path instead of index */ + cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); + cl_assert(git_oid_cmp(&id1, &entry->oid) == 0); + + git_index_free(index); + git_repository_free(repo); +} + +static void cleanup_1397(void *opaque) +{ + GIT_UNUSED(opaque); + cl_git_sandbox_cleanup(); +} + +void test_index_tests__add_issue_1397(void) +{ + git_index *index; + git_repository *repo; + const git_index_entry *entry; + git_oid id1; + + cl_set_cleanup(&cleanup_1397, NULL); + + repo = cl_git_sandbox_init("issue_1397"); + + cl_repo_set_bool(repo, "core.autocrlf", true); + + /* Ensure we're the only guy in the room */ + cl_git_pass(git_repository_index(&index, repo)); + + /* Store the expected hash of the file/blob + * This has been generated by executing the following + * $ git hash-object crlf_file.txt + */ + cl_git_pass(git_oid_fromstr(&id1, "8312e0889a9cbab77c732b6bc39b51a683e3a318")); + + /* Make sure the initial SHA-1 is correct */ + cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL); + cl_assert_(git_oid_cmp(&id1, &entry->oid) == 0, "first oid check"); + + /* Update the index */ + cl_git_pass(git_index_add_bypath(index, "crlf_file.txt")); + + /* Check the new SHA-1 */ + cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL); + cl_assert_(git_oid_cmp(&id1, &entry->oid) == 0, "second oid check"); + + git_index_free(index); +} + +void test_index_tests__add_bypath_to_a_bare_repository_returns_EBAREPO(void) +{ + git_repository *bare_repo; + git_index *index; + + cl_git_pass(git_repository_open(&bare_repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_repository_index(&index, bare_repo)); + + cl_assert_equal_i(GIT_EBAREREPO, git_index_add_bypath(index, "test.txt")); + + git_index_free(index); + git_repository_free(bare_repo); +} + +/* Test that writing an invalid filename fails */ +void test_index_tests__write_invalid_filename(void) +{ + git_repository *repo; + git_index *index; + git_oid expected; + + p_mkdir("read_tree", 0700); + + cl_git_pass(git_repository_init(&repo, "./read_tree", 0)); + cl_git_pass(git_repository_index(&index, repo)); + + cl_assert(git_index_entrycount(index) == 0); + + cl_git_mkfile("./read_tree/.git/hello", NULL); + + cl_git_pass(git_index_add_bypath(index, ".git/hello")); + + /* write-tree */ + cl_git_fail(git_index_write_tree(&expected, index)); + + git_index_free(index); + git_repository_free(repo); + + cl_fixture_cleanup("read_tree"); +} + +void test_index_tests__remove_entry(void) +{ + git_repository *repo; + git_index *index; + + p_mkdir("index_test", 0770); + + cl_git_pass(git_repository_init(&repo, "index_test", 0)); + cl_git_pass(git_repository_index(&index, repo)); + cl_assert(git_index_entrycount(index) == 0); + + cl_git_mkfile("index_test/hello", NULL); + cl_git_pass(git_index_add_bypath(index, "hello")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_index_read(index, true)); /* reload */ + cl_assert(git_index_entrycount(index) == 1); + cl_assert(git_index_get_bypath(index, "hello", 0) != NULL); + + cl_git_pass(git_index_remove(index, "hello", 0)); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_index_read(index, true)); /* reload */ + cl_assert(git_index_entrycount(index) == 0); + cl_assert(git_index_get_bypath(index, "hello", 0) == NULL); + + git_index_free(index); + git_repository_free(repo); + cl_fixture_cleanup("index_test"); +} + +void test_index_tests__remove_directory(void) +{ + git_repository *repo; + git_index *index; + + p_mkdir("index_test", 0770); + + cl_git_pass(git_repository_init(&repo, "index_test", 0)); + cl_git_pass(git_repository_index(&index, repo)); + cl_assert_equal_i(0, (int)git_index_entrycount(index)); + + p_mkdir("index_test/a", 0770); + cl_git_mkfile("index_test/a/1.txt", NULL); + cl_git_mkfile("index_test/a/2.txt", NULL); + cl_git_mkfile("index_test/a/3.txt", NULL); + cl_git_mkfile("index_test/b.txt", NULL); + + cl_git_pass(git_index_add_bypath(index, "a/1.txt")); + cl_git_pass(git_index_add_bypath(index, "a/2.txt")); + cl_git_pass(git_index_add_bypath(index, "a/3.txt")); + cl_git_pass(git_index_add_bypath(index, "b.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_index_read(index, true)); /* reload */ + cl_assert_equal_i(4, (int)git_index_entrycount(index)); + cl_assert(git_index_get_bypath(index, "a/1.txt", 0) != NULL); + cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL); + cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL); + + cl_git_pass(git_index_remove(index, "a/1.txt", 0)); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_index_read(index, true)); /* reload */ + cl_assert_equal_i(3, (int)git_index_entrycount(index)); + cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL); + cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL); + cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL); + + cl_git_pass(git_index_remove_directory(index, "a", 0)); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_index_read(index, true)); /* reload */ + cl_assert_equal_i(1, (int)git_index_entrycount(index)); + cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL); + cl_assert(git_index_get_bypath(index, "a/2.txt", 0) == NULL); + cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL); + + git_index_free(index); + git_repository_free(repo); + cl_fixture_cleanup("index_test"); +} + +void test_index_tests__preserves_case(void) +{ + git_repository *repo; + git_index *index; + const git_index_entry *entry; + int index_caps; + + cl_set_cleanup(&cleanup_myrepo, NULL); + + cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); + cl_git_pass(git_repository_index(&index, repo)); + + index_caps = git_index_caps(index); + + cl_git_rewritefile("myrepo/test.txt", "hey there\n"); + cl_git_pass(git_index_add_bypath(index, "test.txt")); + + cl_git_pass(p_rename("myrepo/test.txt", "myrepo/TEST.txt")); + cl_git_rewritefile("myrepo/TEST.txt", "hello again\n"); + cl_git_pass(git_index_add_bypath(index, "TEST.txt")); + + if (index_caps & GIT_INDEXCAP_IGNORE_CASE) + cl_assert_equal_i(1, (int)git_index_entrycount(index)); + else + cl_assert_equal_i(2, (int)git_index_entrycount(index)); + + /* Test access by path instead of index */ + cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); + /* The path should *not* have changed without an explicit remove */ + cl_assert(git__strcmp(entry->path, "test.txt") == 0); + + cl_assert((entry = git_index_get_bypath(index, "TEST.txt", 0)) != NULL); + if (index_caps & GIT_INDEXCAP_IGNORE_CASE) + /* The path should *not* have changed without an explicit remove */ + cl_assert(git__strcmp(entry->path, "test.txt") == 0); + else + cl_assert(git__strcmp(entry->path, "TEST.txt") == 0); + + git_index_free(index); + git_repository_free(repo); +} + +void test_index_tests__elocked(void) +{ + git_repository *repo; + git_index *index; + git_filebuf file = GIT_FILEBUF_INIT; + const git_error *err; + int error; + + cl_set_cleanup(&cleanup_myrepo, NULL); + + cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); + cl_git_pass(git_repository_index(&index, repo)); + + /* Lock the index file so we fail to lock it */ + cl_git_pass(git_filebuf_open(&file, index->index_file_path, 0, 0666)); + error = git_index_write(index); + cl_assert_equal_i(GIT_ELOCKED, error); + + err = giterr_last(); + cl_assert_equal_i(err->klass, GITERR_INDEX); + + git_filebuf_cleanup(&file); + git_index_free(index); + git_repository_free(repo); +} + +void test_index_tests__reload_from_disk(void) +{ + git_repository *repo; + git_index *read_index; + git_index *write_index; + + cl_set_cleanup(&cleanup_myrepo, NULL); + + cl_git_pass(git_futils_mkdir("./myrepo", NULL, 0777, GIT_MKDIR_PATH)); + cl_git_mkfile("./myrepo/a.txt", "a\n"); + cl_git_mkfile("./myrepo/b.txt", "b\n"); + + cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); + cl_git_pass(git_repository_index(&write_index, repo)); + cl_assert_equal_i(false, write_index->on_disk); + + cl_git_pass(git_index_open(&read_index, write_index->index_file_path)); + cl_assert_equal_i(false, read_index->on_disk); + + /* Stage two new files agaisnt the write_index */ + cl_git_pass(git_index_add_bypath(write_index, "a.txt")); + cl_git_pass(git_index_add_bypath(write_index, "b.txt")); + + cl_assert_equal_sz(2, git_index_entrycount(write_index)); + + /* Persist the index changes to disk */ + cl_git_pass(git_index_write(write_index)); + cl_assert_equal_i(true, write_index->on_disk); + + /* Sync the changes back into the read_index */ + cl_assert_equal_sz(0, git_index_entrycount(read_index)); + + cl_git_pass(git_index_read(read_index, true)); + cl_assert_equal_i(true, read_index->on_disk); + + cl_assert_equal_sz(2, git_index_entrycount(read_index)); + + /* Remove the index file from the filesystem */ + cl_git_pass(p_unlink(write_index->index_file_path)); + + /* Sync the changes back into the read_index */ + cl_git_pass(git_index_read(read_index, true)); + cl_assert_equal_i(false, read_index->on_disk); + cl_assert_equal_sz(0, git_index_entrycount(read_index)); + + git_index_free(read_index); + git_index_free(write_index); + git_repository_free(repo); +} diff --git a/tests/main.c b/tests/main.c new file mode 100644 index 000000000..6b498939d --- /dev/null +++ b/tests/main.c @@ -0,0 +1,20 @@ +#include "clar_libgit2.h" + +#ifdef _WIN32 +int __cdecl main(int argc, char *argv[]) +#else +int main(int argc, char *argv[]) +#endif +{ + int res; + + git_threads_init(); + + /* Run the test suite */ + res = clar_test(argc, argv); + + giterr_clear(); + git_threads_shutdown(); + + return res; +} diff --git a/tests/merge/merge_helpers.c b/tests/merge/merge_helpers.c new file mode 100644 index 000000000..43619be0d --- /dev/null +++ b/tests/merge/merge_helpers.c @@ -0,0 +1,333 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "refs.h" +#include "tree.h" +#include "merge_helpers.h" +#include "merge.h" +#include "git2/merge.h" +#include "git2/sys/index.h" + +int merge_trees_from_branches( + git_index **index, git_repository *repo, + const char *ours_name, const char *theirs_name, + git_merge_tree_opts *opts) +{ + git_commit *our_commit, *their_commit, *ancestor_commit = NULL; + git_tree *our_tree, *their_tree, *ancestor_tree = NULL; + git_oid our_oid, their_oid, ancestor_oid; + git_buf branch_buf = GIT_BUF_INIT; + int error; + + git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours_name); + cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr)); + cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid)); + + git_buf_clear(&branch_buf); + git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs_name); + cl_git_pass(git_reference_name_to_id(&their_oid, repo, branch_buf.ptr)); + cl_git_pass(git_commit_lookup(&their_commit, repo, &their_oid)); + + error = git_merge_base(&ancestor_oid, repo, git_commit_id(our_commit), git_commit_id(their_commit)); + + if (error != GIT_ENOTFOUND) { + cl_git_pass(error); + + cl_git_pass(git_commit_lookup(&ancestor_commit, repo, &ancestor_oid)); + cl_git_pass(git_commit_tree(&ancestor_tree, ancestor_commit)); + } + + cl_git_pass(git_commit_tree(&our_tree, our_commit)); + cl_git_pass(git_commit_tree(&their_tree, their_commit)); + + cl_git_pass(git_merge_trees(index, repo, ancestor_tree, our_tree, their_tree, opts)); + + git_buf_free(&branch_buf); + git_tree_free(our_tree); + git_tree_free(their_tree); + git_tree_free(ancestor_tree); + git_commit_free(our_commit); + git_commit_free(their_commit); + git_commit_free(ancestor_commit); + + return 0; +} + +int merge_branches(git_merge_result **result, git_repository *repo, const char *ours_branch, const char *theirs_branch, git_merge_opts *opts) +{ + git_reference *head_ref, *theirs_ref; + git_merge_head *theirs_head; + git_checkout_opts head_checkout_opts = GIT_CHECKOUT_OPTS_INIT; + + head_checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + cl_git_pass(git_reference_symbolic_create(&head_ref, repo, "HEAD", ours_branch, 1)); + cl_git_pass(git_checkout_head(repo, &head_checkout_opts)); + + cl_git_pass(git_reference_lookup(&theirs_ref, repo, theirs_branch)); + cl_git_pass(git_merge_head_from_ref(&theirs_head, repo, theirs_ref)); + + cl_git_pass(git_merge(result, repo, (const git_merge_head **)&theirs_head, 1, opts)); + + git_reference_free(head_ref); + git_reference_free(theirs_ref); + git_merge_head_free(theirs_head); + + return 0; +} + +void merge__dump_index_entries(git_vector *index_entries) +{ + size_t i; + const git_index_entry *index_entry; + + printf ("\nINDEX [%d]:\n", (int)index_entries->length); + for (i = 0; i < index_entries->length; i++) { + index_entry = index_entries->contents[i]; + + printf("%o ", index_entry->mode); + printf("%s ", git_oid_allocfmt(&index_entry->oid)); + printf("%d ", git_index_entry_stage(index_entry)); + printf("%s ", index_entry->path); + printf("\n"); + } + printf("\n"); +} + +void merge__dump_names(git_index *index) +{ + size_t i; + const git_index_name_entry *conflict_name; + + for (i = 0; i < git_index_name_entrycount(index); i++) { + conflict_name = git_index_name_get_byindex(index, i); + + printf("%s %s %s\n", conflict_name->ancestor, conflict_name->ours, conflict_name->theirs); + } + printf("\n"); +} + +void merge__dump_reuc(git_index *index) +{ + size_t i; + const git_index_reuc_entry *reuc; + + printf ("\nREUC:\n"); + for (i = 0; i < git_index_reuc_entrycount(index); i++) { + reuc = git_index_reuc_get_byindex(index, i); + + printf("%s ", reuc->path); + printf("%o ", reuc->mode[0]); + printf("%s\n", git_oid_allocfmt(&reuc->oid[0])); + printf(" %o ", reuc->mode[1]); + printf(" %s\n", git_oid_allocfmt(&reuc->oid[1])); + printf(" %o ", reuc->mode[2]); + printf(" %s ", git_oid_allocfmt(&reuc->oid[2])); + printf("\n"); + } + printf("\n"); +} + +static int index_entry_eq_merge_index_entry(const struct merge_index_entry *expected, const git_index_entry *actual) +{ + git_oid expected_oid; + bool test_oid; + + if (strlen(expected->oid_str) != 0) { + cl_git_pass(git_oid_fromstr(&expected_oid, expected->oid_str)); + test_oid = 1; + } else + test_oid = 0; + + if (actual->mode != expected->mode || + (test_oid && git_oid_cmp(&actual->oid, &expected_oid) != 0) || + git_index_entry_stage(actual) != expected->stage) + return 0; + + if (actual->mode == 0 && (actual->path != NULL || strlen(expected->path) > 0)) + return 0; + + if (actual->mode != 0 && (strcmp(actual->path, expected->path) != 0)) + return 0; + + return 1; +} + +static int name_entry_eq(const char *expected, const char *actual) +{ + if (strlen(expected) == 0) + return (actual == NULL) ? 1 : 0; + + return (strcmp(expected, actual) == 0) ? 1 : 0; +} + +static int name_entry_eq_merge_name_entry(const struct merge_name_entry *expected, const git_index_name_entry *actual) +{ + if (name_entry_eq(expected->ancestor_path, actual->ancestor) == 0 || + name_entry_eq(expected->our_path, actual->ours) == 0 || + name_entry_eq(expected->their_path, actual->theirs) == 0) + return 0; + + return 1; +} + +static int index_conflict_data_eq_merge_diff(const struct merge_index_conflict_data *expected, git_merge_diff *actual) +{ + if (!index_entry_eq_merge_index_entry(&expected->ancestor.entry, &actual->ancestor_entry) || + !index_entry_eq_merge_index_entry(&expected->ours.entry, &actual->our_entry) || + !index_entry_eq_merge_index_entry(&expected->theirs.entry, &actual->their_entry)) + return 0; + + if (expected->ours.status != actual->our_status || + expected->theirs.status != actual->their_status) + return 0; + + return 1; +} + +int merge_test_merge_conflicts(git_vector *conflicts, const struct merge_index_conflict_data expected[], size_t expected_len) +{ + git_merge_diff *actual; + size_t i; + + if (conflicts->length != expected_len) + return 0; + + for (i = 0; i < expected_len; i++) { + actual = conflicts->contents[i]; + + if (!index_conflict_data_eq_merge_diff(&expected[i], actual)) + return 0; + } + + return 1; +} + +int merge_test_index(git_index *index, const struct merge_index_entry expected[], size_t expected_len) +{ + size_t i; + const git_index_entry *index_entry; + + /* + dump_index_entries(&index->entries); + */ + + if (git_index_entrycount(index) != expected_len) + return 0; + + for (i = 0; i < expected_len; i++) { + if ((index_entry = git_index_get_byindex(index, i)) == NULL) + return 0; + + if (!index_entry_eq_merge_index_entry(&expected[i], index_entry)) + return 0; + } + + return 1; +} + +int merge_test_names(git_index *index, const struct merge_name_entry expected[], size_t expected_len) +{ + size_t i; + const git_index_name_entry *name_entry; + + /* + dump_names(index); + */ + + if (git_index_name_entrycount(index) != expected_len) + return 0; + + for (i = 0; i < expected_len; i++) { + if ((name_entry = git_index_name_get_byindex(index, i)) == NULL) + return 0; + + if (! name_entry_eq_merge_name_entry(&expected[i], name_entry)) + return 0; + } + + return 1; +} + +int merge_test_reuc(git_index *index, const struct merge_reuc_entry expected[], size_t expected_len) +{ + size_t i; + const git_index_reuc_entry *reuc_entry; + git_oid expected_oid; + + /* + dump_reuc(index); + */ + + if (git_index_reuc_entrycount(index) != expected_len) + return 0; + + for (i = 0; i < expected_len; i++) { + if ((reuc_entry = git_index_reuc_get_byindex(index, i)) == NULL) + return 0; + + if (strcmp(reuc_entry->path, expected[i].path) != 0 || + reuc_entry->mode[0] != expected[i].ancestor_mode || + reuc_entry->mode[1] != expected[i].our_mode || + reuc_entry->mode[2] != expected[i].their_mode) + return 0; + + if (expected[i].ancestor_mode > 0) { + cl_git_pass(git_oid_fromstr(&expected_oid, expected[i].ancestor_oid_str)); + + if (git_oid_cmp(&reuc_entry->oid[0], &expected_oid) != 0) + return 0; + } + + if (expected[i].our_mode > 0) { + cl_git_pass(git_oid_fromstr(&expected_oid, expected[i].our_oid_str)); + + if (git_oid_cmp(&reuc_entry->oid[1], &expected_oid) != 0) + return 0; + } + + if (expected[i].their_mode > 0) { + cl_git_pass(git_oid_fromstr(&expected_oid, expected[i].their_oid_str)); + + if (git_oid_cmp(&reuc_entry->oid[2], &expected_oid) != 0) + return 0; + } + } + + return 1; +} + +int dircount(void *payload, git_buf *pathbuf) +{ + int *entries = payload; + size_t len = git_buf_len(pathbuf); + + if (len < 5 || strcmp(pathbuf->ptr + (git_buf_len(pathbuf) - 5), "/.git") != 0) + (*entries)++; + + return 0; +} + +int merge_test_workdir(git_repository *repo, const struct merge_index_entry expected[], size_t expected_len) +{ + size_t actual_len = 0, i; + git_oid actual_oid, expected_oid; + git_buf wd = GIT_BUF_INIT; + + git_buf_puts(&wd, repo->workdir); + git_path_direach(&wd, 0, dircount, &actual_len); + + if (actual_len != expected_len) + return 0; + + for (i = 0; i < expected_len; i++) { + git_blob_create_fromworkdir(&actual_oid, repo, expected[i].path); + git_oid_fromstr(&expected_oid, expected[i].oid_str); + + if (git_oid_cmp(&actual_oid, &expected_oid) != 0) + return 0; + } + + git_buf_free(&wd); + + return 1; +} diff --git a/tests/merge/merge_helpers.h b/tests/merge/merge_helpers.h new file mode 100644 index 000000000..ae3274437 --- /dev/null +++ b/tests/merge/merge_helpers.h @@ -0,0 +1,62 @@ +#ifndef INCLUDE_cl_merge_helpers_h__ +#define INCLUDE_cl_merge_helpers_h__ + +#include "merge.h" +#include "git2/merge.h" + +struct merge_index_entry { + uint16_t mode; + char oid_str[41]; + int stage; + char path[128]; +}; + +struct merge_name_entry { + char ancestor_path[128]; + char our_path[128]; + char their_path[128]; +}; + +struct merge_index_with_status { + struct merge_index_entry entry; + unsigned int status; +}; + +struct merge_reuc_entry { + char path[128]; + unsigned int ancestor_mode; + unsigned int our_mode; + unsigned int their_mode; + char ancestor_oid_str[41]; + char our_oid_str[41]; + char their_oid_str[41]; +}; + +struct merge_index_conflict_data { + struct merge_index_with_status ancestor; + struct merge_index_with_status ours; + struct merge_index_with_status theirs; + git_merge_diff_type_t change_type; +}; + +int merge_trees_from_branches( + git_index **index, git_repository *repo, + const char *ours_name, const char *theirs_name, + git_merge_tree_opts *opts); + +int merge_branches(git_merge_result **result, git_repository *repo, + const char *ours_branch, const char *theirs_branch, git_merge_opts *opts); + +int merge_test_diff_list(git_merge_diff_list *diff_list, const struct merge_index_entry expected[], size_t expected_len); + +int merge_test_merge_conflicts(git_vector *conflicts, const struct merge_index_conflict_data expected[], size_t expected_len); + +int merge_test_index(git_index *index, const struct merge_index_entry expected[], size_t expected_len); + +int merge_test_names(git_index *index, const struct merge_name_entry expected[], size_t expected_len); + +int merge_test_reuc(git_index *index, const struct merge_reuc_entry expected[], size_t expected_len); + +int merge_test_workdir(git_repository *repo, const struct merge_index_entry expected[], size_t expected_len); + +#endif diff --git a/tests/merge/trees/automerge.c b/tests/merge/trees/automerge.c new file mode 100644 index 000000000..746ce5068 --- /dev/null +++ b/tests/merge/trees/automerge.c @@ -0,0 +1,217 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "buffer.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "fileops.h" + +static git_repository *repo; + +#define TEST_REPO_PATH "merge-resolve" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +#define THEIRS_AUTOMERGE_BRANCH "branch" + +#define THEIRS_UNRELATED_BRANCH "unrelated" +#define THEIRS_UNRELATED_OID "55b4e4687e7a0d9ca367016ed930f385d4022e6f" +#define THEIRS_UNRELATED_PARENT "d6cf6c7741b3316826af1314042550c97ded1d50" + +#define OURS_DIRECTORY_FILE "df_side1" +#define THEIRS_DIRECTORY_FILE "df_side2" + +/* Non-conflicting files, index entries are common to every merge operation */ +#define ADDED_IN_MASTER_INDEX_ENTRY \ + { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" } +#define AUTOMERGEABLE_INDEX_ENTRY \ + { 0100644, "f2e1550a0c9e53d5811175864a29536642ae3821", 0, "automergeable.txt" } +#define CHANGED_IN_BRANCH_INDEX_ENTRY \ + { 0100644, "4eb04c9e79e88f6640d01ff5b25ca2a60764f216", 0, "changed-in-branch.txt" } +#define CHANGED_IN_MASTER_INDEX_ENTRY \ + { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" } +#define UNCHANGED_INDEX_ENTRY \ + { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" } + +/* Expected REUC entries */ +#define AUTOMERGEABLE_REUC_ENTRY \ + { "automergeable.txt", 0100644, 0100644, 0100644, \ + "6212c31dab5e482247d7977e4f0dd3601decf13b", \ + "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", \ + "058541fc37114bfc1dddf6bd6bffc7fae5c2e6fe" } +#define CONFLICTING_REUC_ENTRY \ + { "conflicting.txt", 0100644, 0100644, 0100644, \ + "d427e0b2e138501a3d15cc376077a3631e15bd46", \ + "4e886e602529caa9ab11d71f86634bd1b6e0de10", \ + "2bd0a343aeef7a2cf0d158478966a6e587ff3863" } +#define REMOVED_IN_BRANCH_REUC_ENTRY \ + { "removed-in-branch.txt", 0100644, 0100644, 0, \ + "dfe3f22baa1f6fce5447901c3086bae368de6bdd", \ + "dfe3f22baa1f6fce5447901c3086bae368de6bdd", \ + "" } +#define REMOVED_IN_MASTER_REUC_ENTRY \ + { "removed-in-master.txt", 0100644, 0, 0100644, \ + "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", \ + "", \ + "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5" } + +#define AUTOMERGEABLE_MERGED_FILE \ + "this file is changed in master\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is changed in branch\n" + +#define AUTOMERGEABLE_MERGED_FILE_CRLF \ + "this file is changed in master\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is changed in branch\r\n" + +// Fixture setup and teardown +void test_merge_trees_automerge__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); +} + +void test_merge_trees_automerge__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_merge_trees_automerge__automerge(void) +{ + git_index *index; + const git_index_entry *entry; + git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; + git_blob *blob; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + + { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, + { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, + + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY + }; + + cl_git_pass(merge_trees_from_branches(&index, repo, "master", THEIRS_AUTOMERGE_BRANCH, &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 8)); + cl_assert(merge_test_reuc(index, merge_reuc_entries, 3)); + + cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL); + cl_assert(entry->file_size == strlen(AUTOMERGEABLE_MERGED_FILE)); + + cl_git_pass(git_object_lookup((git_object **)&blob, repo, &entry->oid, GIT_OBJ_BLOB)); + cl_assert(memcmp(git_blob_rawcontent(blob), AUTOMERGEABLE_MERGED_FILE, (size_t)entry->file_size) == 0); + + git_index_free(index); + git_blob_free(blob); +} + +void test_merge_trees_automerge__favor_ours(void) +{ + git_index *index; + git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + CONFLICTING_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY, + }; + + opts.automerge_flags = GIT_MERGE_AUTOMERGE_FAVOR_OURS; + + cl_git_pass(merge_trees_from_branches(&index, repo, "master", THEIRS_AUTOMERGE_BRANCH, &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 6)); + cl_assert(merge_test_reuc(index, merge_reuc_entries, 4)); + + git_index_free(index); +} + +void test_merge_trees_automerge__favor_theirs(void) +{ + git_index *index; + git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 0, "conflicting.txt" }, + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + CONFLICTING_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY, + }; + + opts.automerge_flags = GIT_MERGE_AUTOMERGE_FAVOR_THEIRS; + + cl_git_pass(merge_trees_from_branches(&index, repo, "master", THEIRS_AUTOMERGE_BRANCH, &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 6)); + cl_assert(merge_test_reuc(index, merge_reuc_entries, 4)); + + git_index_free(index); +} + +void test_merge_trees_automerge__unrelated(void) +{ + git_index *index; + git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, + { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 2, "automergeable.txt" }, + { 0100644, "d07ec190c306ec690bac349e87d01c4358e49bb2", 3, "automergeable.txt" }, + { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, + { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, + { 0100644, "4b253da36a0ae8bfce63aeabd8c5b58429925594", 3, "conflicting.txt" }, + { 0100644, "ef58fdd8086c243bdc81f99e379acacfd21d32d6", 0, "new-in-unrelated1.txt" }, + { 0100644, "948ba6e701c1edab0c2d394fb7c5538334129793", 0, "new-in-unrelated2.txt" }, + { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, + { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, + }; + + cl_git_pass(merge_trees_from_branches(&index, repo, "master", THEIRS_UNRELATED_BRANCH, &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 11)); + + git_index_free(index); +} diff --git a/tests/merge/trees/modeconflict.c b/tests/merge/trees/modeconflict.c new file mode 100644 index 000000000..d858b8f66 --- /dev/null +++ b/tests/merge/trees/modeconflict.c @@ -0,0 +1,59 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "buffer.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "fileops.h" + +static git_repository *repo; + +#define TEST_REPO_PATH "merge-resolve" + +#define DF_SIDE1_BRANCH "df_side1" +#define DF_SIDE2_BRANCH "df_side2" + +// Fixture setup and teardown +void test_merge_trees_modeconflict__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); +} + +void test_merge_trees_modeconflict__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_merge_trees_modeconflict__df_conflict(void) +{ + git_index *index; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "49130a28ef567af9a6a6104c38773fedfa5f9742", 2, "dir-10" }, + { 0100644, "6c06dcd163587c2cc18be44857e0b71116382aeb", 3, "dir-10" }, + { 0100644, "43aafd43bea779ec74317dc361f45ae3f532a505", 0, "dir-6" }, + { 0100644, "a031a28ae70e33a641ce4b8a8f6317f1ab79dee4", 3, "dir-7" }, + { 0100644, "5012fd565b1393bdfda1805d4ec38ce6619e1fd1", 1, "dir-7/file.txt" }, + { 0100644, "a5563304ddf6caba25cb50323a2ea6f7dbfcadca", 2, "dir-7/file.txt" }, + { 0100644, "e9ad6ec3e38364a3d07feda7c4197d4d845c53b5", 0, "dir-8" }, + { 0100644, "3ef4d30382ca33fdeba9fda895a99e0891ba37aa", 2, "dir-9" }, + { 0100644, "fc4c636d6515e9e261f9260dbcf3cc6eca97ea08", 1, "dir-9/file.txt" }, + { 0100644, "76ab0e2868197ec158ddd6c78d8a0d2fd73d38f9", 3, "dir-9/file.txt" }, + { 0100644, "5c2411f8075f48a6b2fdb85ebc0d371747c4df15", 0, "file-1/new" }, + { 0100644, "a39a620dae5bc8b4e771cd4d251b7d080401a21e", 1, "file-2" }, + { 0100644, "d963979c237d08b6ba39062ee7bf64c7d34a27f8", 2, "file-2" }, + { 0100644, "5c341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d", 0, "file-2/new" }, + { 0100644, "9efe7723802d4305142eee177e018fee1572c4f4", 0, "file-3/new" }, + { 0100644, "bacac9b3493509aa15e1730e1545fc0919d1dae0", 1, "file-4" }, + { 0100644, "7663fce0130db092936b137cabd693ec234eb060", 3, "file-4" }, + { 0100644, "e49f917b448d1340b31d76e54ba388268fd4c922", 0, "file-4/new" }, + { 0100644, "cab2cf23998b40f1af2d9d9a756dc9e285a8df4b", 2, "file-5/new" }, + { 0100644, "f5504f36e6f4eb797a56fc5bac6c6c7f32969bf2", 3, "file-5/new" }, + }; + + cl_git_pass(merge_trees_from_branches(&index, repo, DF_SIDE1_BRANCH, DF_SIDE2_BRANCH, NULL)); + + cl_assert(merge_test_index(index, merge_index_entries, 20)); + + git_index_free(index); +} diff --git a/tests/merge/trees/renames.c b/tests/merge/trees/renames.c new file mode 100644 index 000000000..427b6bd8f --- /dev/null +++ b/tests/merge/trees/renames.c @@ -0,0 +1,252 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "buffer.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "fileops.h" + +static git_repository *repo; + +#define TEST_REPO_PATH "merge-resolve" + +#define BRANCH_RENAME_OURS "rename_conflict_ours" +#define BRANCH_RENAME_THEIRS "rename_conflict_theirs" + +// Fixture setup and teardown +void test_merge_trees_renames__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); +} + +void test_merge_trees_renames__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_merge_trees_renames__index(void) +{ + git_index *index; + git_merge_tree_opts *opts = NULL; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 1, "0b-rewritten-in-ours.txt" }, + { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 2, "0b-rewritten-in-ours.txt" }, + { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 3, "0b-rewritten-in-ours.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 1, "0c-rewritten-in-theirs.txt" }, + { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 2, "0c-rewritten-in-theirs.txt" }, + { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 3, "0c-rewritten-in-theirs.txt" }, + { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, + { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, + { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, + { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, + { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 2, "3a-newname-in-ours-deleted-in-theirs.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 1, "3a-renamed-in-ours-deleted-in-theirs.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 3, "3b-newname-in-theirs-deleted-in-ours.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 1, "3b-renamed-in-theirs-deleted-in-ours.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 2, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 3, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 1, "4a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 2, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 3, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 1, "4b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 2, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 3, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 1, "5a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 3, "5a-renamed-in-ours-added-in-theirs.txt" }, + { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 2, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 3, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 1, "5b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 2, "5b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 2, "6-both-renamed-1-to-2-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 3, "6-both-renamed-1-to-2-theirs.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 1, "6-both-renamed-1-to-2.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 1, "7-both-renamed-side-1.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 3, "7-both-renamed-side-1.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 1, "7-both-renamed-side-2.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 2, "7-both-renamed-side-2.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" }, + }; + + struct merge_name_entry merge_name_entries[] = { + { + "3a-renamed-in-ours-deleted-in-theirs.txt", + "3a-newname-in-ours-deleted-in-theirs.txt", + "" + }, + + { + "3b-renamed-in-theirs-deleted-in-ours.txt", + "", + "3b-newname-in-theirs-deleted-in-ours.txt", + }, + + { + "4a-renamed-in-ours-added-in-theirs.txt", + "4a-newname-in-ours-added-in-theirs.txt", + "", + }, + + { + "4b-renamed-in-theirs-added-in-ours.txt", + "", + "4b-newname-in-theirs-added-in-ours.txt", + }, + + { + "5a-renamed-in-ours-added-in-theirs.txt", + "5a-newname-in-ours-added-in-theirs.txt", + "5a-renamed-in-ours-added-in-theirs.txt", + }, + + { + "5b-renamed-in-theirs-added-in-ours.txt", + "5b-renamed-in-theirs-added-in-ours.txt", + "5b-newname-in-theirs-added-in-ours.txt", + }, + + { + "6-both-renamed-1-to-2.txt", + "6-both-renamed-1-to-2-ours.txt", + "6-both-renamed-1-to-2-theirs.txt", + }, + + { + "7-both-renamed-side-1.txt", + "7-both-renamed.txt", + "7-both-renamed-side-1.txt", + }, + + { + "7-both-renamed-side-2.txt", + "7-both-renamed-side-2.txt", + "7-both-renamed.txt", + }, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + { "1a-newname-in-ours-edited-in-theirs.txt", + 0, 0100644, 0, + "", + "c3d02eeef75183df7584d8d13ac03053910c1301", + "" }, + + { "1a-newname-in-ours.txt", + 0, 0100644, 0, + "", + "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", + "" }, + + { "1a-renamed-in-ours-edited-in-theirs.txt", + 0100644, 0, 0100644, + "c3d02eeef75183df7584d8d13ac03053910c1301", + "", + "0d872f8e871a30208305978ecbf9e66d864f1638" }, + + { "1a-renamed-in-ours.txt", + 0100644, 0, 0100644, + "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", + "", + "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb" }, + + { "1b-newname-in-theirs-edited-in-ours.txt", + 0, 0, 0100644, + "", + "", + "241a1005cd9b980732741b74385b891142bcba28" }, + + { "1b-newname-in-theirs.txt", + 0, 0, 0100644, + "", + "", + "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136" }, + + { "1b-renamed-in-theirs-edited-in-ours.txt", + 0100644, 0100644, 0, + "241a1005cd9b980732741b74385b891142bcba28", + "ed9523e62e453e50dd9be1606af19399b96e397a", + "" }, + + { "1b-renamed-in-theirs.txt", + 0100644, 0100644, 0, + "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", + "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", + "" }, + + { "2-newname-in-both.txt", + 0, 0100644, 0100644, + "", + "178940b450f238a56c0d75b7955cb57b38191982", + "178940b450f238a56c0d75b7955cb57b38191982" }, + + { "2-renamed-in-both.txt", + 0100644, 0, 0, + "178940b450f238a56c0d75b7955cb57b38191982", + "", + "" }, + }; + + cl_git_pass(merge_trees_from_branches(&index, repo, + BRANCH_RENAME_OURS, BRANCH_RENAME_THEIRS, + opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 41)); + cl_assert(merge_test_names(index, merge_name_entries, 9)); + cl_assert(merge_test_reuc(index, merge_reuc_entries, 10)); + + git_index_free(index); +} + +void test_merge_trees_renames__no_rename_index(void) +{ + git_index *index; + git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 1, "0b-rewritten-in-ours.txt" }, + { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 2, "0b-rewritten-in-ours.txt" }, + { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 3, "0b-rewritten-in-ours.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 1, "0c-rewritten-in-theirs.txt" }, + { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 2, "0c-rewritten-in-theirs.txt" }, + { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 3, "0c-rewritten-in-theirs.txt" }, + { 0100644, "c3d02eeef75183df7584d8d13ac03053910c1301", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, + { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, + { 0100644, "c3d02eeef75183df7584d8d13ac03053910c1301", 1, "1a-renamed-in-ours-edited-in-theirs.txt" }, + { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 3, "1a-renamed-in-ours-edited-in-theirs.txt" }, + { 0100644, "241a1005cd9b980732741b74385b891142bcba28", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, + { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, + { 0100644, "241a1005cd9b980732741b74385b891142bcba28", 1, "1b-renamed-in-theirs-edited-in-ours.txt" }, + { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 2, "1b-renamed-in-theirs-edited-in-ours.txt" }, + { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 2, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 3, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 2, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 3, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 2, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 3, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 2, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 3, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-theirs.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" }, + }; + + cl_git_pass(merge_trees_from_branches(&index, repo, + BRANCH_RENAME_OURS, BRANCH_RENAME_THEIRS, + &opts)); + + cl_assert(merge_test_index(index, merge_index_entries, 32)); + + git_index_free(index); +} diff --git a/tests/merge/trees/treediff.c b/tests/merge/trees/treediff.c new file mode 100644 index 000000000..357859df3 --- /dev/null +++ b/tests/merge/trees/treediff.c @@ -0,0 +1,542 @@ +#include "clar_libgit2.h" +#include "git2/tree.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "diff.h" +#include "hashsig.h" + +static git_repository *repo; + +#define TEST_REPO_PATH "merge-resolve" + +#define TREE_OID_ANCESTOR "0d52e3a556e189ba0948ae56780918011c1b167d" +#define TREE_OID_MASTER "1f81433e3161efbf250576c58fede7f6b836f3d3" +#define TREE_OID_BRANCH "eea9286df54245fea72c5b557291470eb825f38f" +#define TREE_OID_RENAMES1 "f5f9dd5886a6ee20272be0aafc790cba43b31931" +#define TREE_OID_RENAMES2 "5fbfbdc04b4eca46f54f4853a3c5a1dce28f5165" + +#define TREE_OID_DF_ANCESTOR "b8a3a806d3950e8c0a03a34f234a92eff0e2c68d" +#define TREE_OID_DF_SIDE1 "ee1d6f164893c1866a323f072eeed36b855656be" +#define TREE_OID_DF_SIDE2 "6178885b38fe96e825ac0f492c0a941f288b37f6" + +#define TREE_OID_RENAME_CONFLICT_ANCESTOR "476dbb3e207313d1d8aaa120c6ad204bf1295e53" +#define TREE_OID_RENAME_CONFLICT_OURS "c4efe31e9decccc8b2b4d3df9aac2cdfe2995618" +#define TREE_OID_RENAME_CONFLICT_THEIRS "9e7f4359c469f309b6057febf4c6e80742cbed5b" + +void test_merge_trees_treediff__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); +} + +void test_merge_trees_treediff__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void test_find_differences( + const char *ancestor_oidstr, + const char *ours_oidstr, + const char *theirs_oidstr, + struct merge_index_conflict_data *treediff_conflict_data, + size_t treediff_conflict_data_len) +{ + git_merge_diff_list *merge_diff_list = git_merge_diff_list__alloc(repo); + git_oid ancestor_oid, ours_oid, theirs_oid; + git_tree *ancestor_tree, *ours_tree, *theirs_tree; + + git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; + opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; + opts.target_limit = 1000; + opts.rename_threshold = 50; + + opts.metric = git__malloc(sizeof(git_diff_similarity_metric)); + cl_assert(opts.metric != NULL); + + opts.metric->file_signature = git_diff_find_similar__hashsig_for_file; + opts.metric->buffer_signature = git_diff_find_similar__hashsig_for_buf; + opts.metric->free_signature = git_diff_find_similar__hashsig_free; + opts.metric->similarity = git_diff_find_similar__calc_similarity; + opts.metric->payload = (void *)GIT_HASHSIG_SMART_WHITESPACE; + + cl_git_pass(git_oid_fromstr(&ancestor_oid, ancestor_oidstr)); + cl_git_pass(git_oid_fromstr(&ours_oid, ours_oidstr)); + cl_git_pass(git_oid_fromstr(&theirs_oid, theirs_oidstr)); + + cl_git_pass(git_tree_lookup(&ancestor_tree, repo, &ancestor_oid)); + cl_git_pass(git_tree_lookup(&ours_tree, repo, &ours_oid)); + cl_git_pass(git_tree_lookup(&theirs_tree, repo, &theirs_oid)); + + cl_git_pass(git_merge_diff_list__find_differences(merge_diff_list, ancestor_tree, ours_tree, theirs_tree)); + cl_git_pass(git_merge_diff_list__find_renames(repo, merge_diff_list, &opts)); + + /* + dump_merge_index(merge_index); + */ + + cl_assert(treediff_conflict_data_len == merge_diff_list->conflicts.length); + + cl_assert(merge_test_merge_conflicts(&merge_diff_list->conflicts, treediff_conflict_data, treediff_conflict_data_len)); + + git_tree_free(ancestor_tree); + git_tree_free(ours_tree); + git_tree_free(theirs_tree); + + git_merge_diff_list__free(merge_diff_list); + + git__free(opts.metric); +} + +void test_merge_trees_treediff__simple(void) +{ + struct merge_index_conflict_data treediff_conflict_data[] = { + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, GIT_DELTA_ADDED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE + }, + + { + { { 0100644, "6212c31dab5e482247d7977e4f0dd3601decf13b", 0, "automergeable.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" }, GIT_DELTA_MODIFIED }, + { { 0100644, "058541fc37114bfc1dddf6bd6bffc7fae5c2e6fe", 0, "automergeable.txt" }, GIT_DELTA_MODIFIED }, + GIT_MERGE_DIFF_BOTH_MODIFIED + }, + + { + { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "4eb04c9e79e88f6640d01ff5b25ca2a60764f216", 0, "changed-in-branch.txt" }, GIT_DELTA_MODIFIED }, + GIT_MERGE_DIFF_NONE + }, + + { + { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, GIT_DELTA_MODIFIED }, + { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE + }, + + { + { { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 0, "conflicting.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, GIT_DELTA_MODIFIED }, + { { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 0, "conflicting.txt" }, GIT_DELTA_MODIFIED }, + GIT_MERGE_DIFF_BOTH_MODIFIED + }, + + { + { { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + GIT_MERGE_DIFF_NONE + }, + + { + { { 0100644, "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", 0, "removed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + { { 0100644, "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", 0, "removed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE + }, + }; + + test_find_differences(TREE_OID_ANCESTOR, TREE_OID_MASTER, TREE_OID_BRANCH, treediff_conflict_data, 7); +} + +void test_merge_trees_treediff__df_conflicts(void) +{ + struct merge_index_conflict_data treediff_conflict_data[] = { + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "49130a28ef567af9a6a6104c38773fedfa5f9742", 0, "dir-10" }, GIT_DELTA_ADDED }, + { { 0100644, "6c06dcd163587c2cc18be44857e0b71116382aeb", 0, "dir-10" }, GIT_DELTA_ADDED }, + GIT_MERGE_DIFF_BOTH_ADDED, + }, + + { + { { 0100644, "242591eb280ee9eeb2ce63524b9a8b9bc4cb515d", 0, "dir-10/file.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + GIT_MERGE_DIFF_BOTH_DELETED, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "43aafd43bea779ec74317dc361f45ae3f532a505", 0, "dir-6" }, GIT_DELTA_ADDED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "cf8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d", 0, "dir-6/file.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "cf8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d", 0, "dir-6/file.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "a031a28ae70e33a641ce4b8a8f6317f1ab79dee4", 0, "dir-7" }, GIT_DELTA_ADDED }, + GIT_MERGE_DIFF_DIRECTORY_FILE, + }, + + { + { { 0100644, "5012fd565b1393bdfda1805d4ec38ce6619e1fd1", 0, "dir-7/file.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "a5563304ddf6caba25cb50323a2ea6f7dbfcadca", 0, "dir-7/file.txt" }, GIT_DELTA_MODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + GIT_MERGE_DIFF_DF_CHILD, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "e9ad6ec3e38364a3d07feda7c4197d4d845c53b5", 0, "dir-8" }, GIT_DELTA_ADDED }, + { {0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "f20c9063fa0bda9a397c96947a7b687305c49753", 0, "dir-8/file.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + { { 0100644, "f20c9063fa0bda9a397c96947a7b687305c49753", 0, "dir-8/file.txt" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "3ef4d30382ca33fdeba9fda895a99e0891ba37aa", 0, "dir-9" }, GIT_DELTA_ADDED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_DIRECTORY_FILE, + }, + + { + { { 0100644, "fc4c636d6515e9e261f9260dbcf3cc6eca97ea08", 0, "dir-9/file.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + { { 0100644, "76ab0e2868197ec158ddd6c78d8a0d2fd73d38f9", 0, "dir-9/file.txt" }, GIT_DELTA_MODIFIED }, + GIT_MERGE_DIFF_DF_CHILD, + }, + + { + { { 0100644, "1e4ff029aee68d0d69ef9eb6efa6cbf1ec732f99", 0, "file-1" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "1e4ff029aee68d0d69ef9eb6efa6cbf1ec732f99", 0, "file-1" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "5c2411f8075f48a6b2fdb85ebc0d371747c4df15", 0, "file-1/new" }, GIT_DELTA_ADDED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "a39a620dae5bc8b4e771cd4d251b7d080401a21e", 0, "file-2" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "d963979c237d08b6ba39062ee7bf64c7d34a27f8", 0, "file-2" }, GIT_DELTA_MODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + GIT_MERGE_DIFF_DIRECTORY_FILE, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "5c341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d", 0, "file-2/new" }, GIT_DELTA_ADDED }, + GIT_MERGE_DIFF_DF_CHILD, + }, + + { + { { 0100644, "032ebc5ab85d9553bb187d3cd40875ff23a63ed0", 0, "file-3" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + { { 0100644, "032ebc5ab85d9553bb187d3cd40875ff23a63ed0", 0, "file-3" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "9efe7723802d4305142eee177e018fee1572c4f4", 0, "file-3/new" }, GIT_DELTA_ADDED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "bacac9b3493509aa15e1730e1545fc0919d1dae0", 0, "file-4" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + { { 0100644, "7663fce0130db092936b137cabd693ec234eb060", 0, "file-4" }, GIT_DELTA_MODIFIED }, + GIT_MERGE_DIFF_DIRECTORY_FILE, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "e49f917b448d1340b31d76e54ba388268fd4c922", 0, "file-4/new" }, GIT_DELTA_ADDED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_DF_CHILD, + }, + + { + { { 0100644, "ac4045f965119e6998f4340ed0f411decfb3ec05", 0, "file-5" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + GIT_MERGE_DIFF_BOTH_DELETED, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "cab2cf23998b40f1af2d9d9a756dc9e285a8df4b", 0, "file-5/new" }, GIT_DELTA_ADDED }, + { { 0100644, "f5504f36e6f4eb797a56fc5bac6c6c7f32969bf2", 0, "file-5/new" }, GIT_DELTA_ADDED }, + GIT_MERGE_DIFF_BOTH_ADDED, + }, + }; + + test_find_differences(TREE_OID_DF_ANCESTOR, TREE_OID_DF_SIDE1, TREE_OID_DF_SIDE2, treediff_conflict_data, 20); +} + +void test_merge_trees_treediff__strict_renames(void) +{ + struct merge_index_conflict_data treediff_conflict_data[] = { + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, GIT_DELTA_ADDED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "6212c31dab5e482247d7977e4f0dd3601decf13b", 0, "automergeable.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" }, GIT_DELTA_MODIFIED }, + { { 0100644, "6212c31dab5e482247d7977e4f0dd3601decf13b", 0, "automergeable.txt" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, GIT_DELTA_MODIFIED }, + { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 0, "conflicting.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, GIT_DELTA_MODIFIED }, + { { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 0, "conflicting.txt" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "renamed-in-branch.txt" }, GIT_DELTA_RENAMED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", 0, "removed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + { { 0100644, "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", 0, "removed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "renamed.txt" }, GIT_DELTA_ADDED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "copied.txt" }, GIT_DELTA_RENAMED }, + GIT_MERGE_DIFF_NONE, + }, + }; + + test_find_differences(TREE_OID_ANCESTOR, TREE_OID_MASTER, TREE_OID_RENAMES1, treediff_conflict_data, 8); +} + +void test_merge_trees_treediff__rename_conflicts(void) +{ + struct merge_index_conflict_data treediff_conflict_data[] = { + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, GIT_DELTA_ADDED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-rewritten-in-ours.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 0, "0b-rewritten-in-ours.txt" }, GIT_DELTA_MODIFIED }, + { { 0100644, "b2d399ae15224e1d58066e3c8df70ce37de7a656", 0, "0b-rewritten-in-ours.txt" }, GIT_DELTA_MODIFIED }, + GIT_MERGE_DIFF_BOTH_MODIFIED, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, GIT_DELTA_ADDED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-rewritten-in-theirs.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 0, "0c-rewritten-in-theirs.txt" }, GIT_DELTA_MODIFIED }, + { { 0100644, "712ebba6669ea847d9829e4f1059d6c830c8b531", 0, "0c-rewritten-in-theirs.txt" }, GIT_DELTA_MODIFIED }, + GIT_MERGE_DIFF_BOTH_MODIFIED, + }, + + { + { { 0100644, "c3d02eeef75183df7584d8d13ac03053910c1301", 0, "1a-renamed-in-ours-edited-in-theirs.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "c3d02eeef75183df7584d8d13ac03053910c1301", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, GIT_DELTA_RENAMED }, + { { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-renamed-in-ours-edited-in-theirs.txt" }, GIT_DELTA_MODIFIED }, + GIT_MERGE_DIFF_RENAMED_MODIFIED, + }, + + { + { { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-renamed-in-ours.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, GIT_DELTA_RENAMED }, + { { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-renamed-in-ours.txt" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "241a1005cd9b980732741b74385b891142bcba28", 0, "1b-renamed-in-theirs-edited-in-ours.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-renamed-in-theirs-edited-in-ours.txt" }, GIT_DELTA_MODIFIED }, + { { 0100644, "241a1005cd9b980732741b74385b891142bcba28", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, GIT_DELTA_RENAMED }, + GIT_MERGE_DIFF_RENAMED_MODIFIED, + }, + + { + { { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-renamed-in-theirs.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-renamed-in-theirs.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, GIT_DELTA_RENAMED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-renamed-in-both.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, GIT_DELTA_RENAMED }, + { { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, GIT_DELTA_RENAMED }, + GIT_MERGE_DIFF_BOTH_RENAMED, + }, + + { + { { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-renamed-in-ours-deleted-in-theirs.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, GIT_DELTA_RENAMED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + GIT_MERGE_DIFF_RENAMED_DELETED, + }, + + { + { { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-renamed-in-theirs-deleted-in-ours.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + { { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, GIT_DELTA_RENAMED }, + GIT_MERGE_DIFF_RENAMED_DELETED, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 0, "4a-newname-in-ours-added-in-theirs.txt" }, GIT_DELTA_ADDED }, + GIT_MERGE_DIFF_RENAMED_ADDED, + }, + + { + { { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-renamed-in-ours-added-in-theirs.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-newname-in-ours-added-in-theirs.txt" }, GIT_DELTA_RENAMED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + GIT_MERGE_DIFF_RENAMED_ADDED, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 0, "4b-newname-in-theirs-added-in-ours.txt" }, GIT_DELTA_ADDED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_RENAMED_ADDED, + }, + + { + { { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 0, "4b-renamed-in-theirs-added-in-ours.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + { { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 0, "4b-newname-in-theirs-added-in-ours.txt" }, GIT_DELTA_RENAMED }, + GIT_MERGE_DIFF_RENAMED_ADDED, + }, + + { + { { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "5-both-renamed-1-to-2.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "5-both-renamed-1-to-2-ours.txt" }, GIT_DELTA_RENAMED }, + { { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "5-both-renamed-1-to-2-theirs.txt" }, GIT_DELTA_RENAMED }, + GIT_MERGE_DIFF_BOTH_RENAMED_1_TO_2, + }, + + { + { { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "6-both-renamed-side-1.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "6-both-renamed.txt" }, GIT_DELTA_RENAMED }, + { { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "6-both-renamed-side-1.txt" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1, + }, + + { + { { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "6-both-renamed-side-2.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "6-both-renamed-side-2.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "6-both-renamed.txt" }, GIT_DELTA_RENAMED }, + GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1, + }, + }; + test_find_differences(TREE_OID_RENAME_CONFLICT_ANCESTOR, + TREE_OID_RENAME_CONFLICT_OURS, TREE_OID_RENAME_CONFLICT_THEIRS, treediff_conflict_data, 18); +} + +void test_merge_trees_treediff__best_renames(void) +{ + struct merge_index_conflict_data treediff_conflict_data[] = { + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, GIT_DELTA_ADDED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "6212c31dab5e482247d7977e4f0dd3601decf13b", 0, "automergeable.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" }, GIT_DELTA_MODIFIED }, + { { 0100644, "45299c1ca5e07bba1fd90843056fb559f96b1f5a", 0, "renamed-90.txt" }, GIT_DELTA_RENAMED }, + GIT_MERGE_DIFF_RENAMED_MODIFIED, + }, + + { + { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, GIT_DELTA_MODIFIED }, + { { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 0, "conflicting.txt" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, GIT_DELTA_MODIFIED }, + { { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 0, "conflicting.txt" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0100644, "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", 0, "removed-in-master.txt" },GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_DELETED }, + { { 0100644, "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", 0, "removed-in-master.txt" }, GIT_DELTA_UNMODIFIED }, + GIT_MERGE_DIFF_MODIFIED_DELETED, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "5843febcb23480df0b5edb22a21c59c772bb8e29", 0, "renamed-50.txt" }, GIT_DELTA_ADDED }, + GIT_MERGE_DIFF_NONE, + }, + + { + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0, "", 0, "" }, GIT_DELTA_UNMODIFIED }, + { { 0100644, "a77a56a49f8f3ae242e02717f18ebbc60c5cc543", 0, "renamed-75.txt" }, GIT_DELTA_ADDED }, + GIT_MERGE_DIFF_NONE, + }, + }; + + test_find_differences(TREE_OID_ANCESTOR, TREE_OID_MASTER, TREE_OID_RENAMES2, treediff_conflict_data, 7); +} diff --git a/tests/merge/trees/trivial.c b/tests/merge/trees/trivial.c new file mode 100644 index 000000000..bfd5dfed3 --- /dev/null +++ b/tests/merge/trees/trivial.c @@ -0,0 +1,397 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "refs.h" +#include "fileops.h" +#include "git2/sys/index.h" + +static git_repository *repo; + +#define TEST_REPO_PATH "merge-resolve" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + + +// Fixture setup and teardown +void test_merge_trees_trivial__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); +} + +void test_merge_trees_trivial__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + + +static int merge_trivial(git_index **index, const char *ours, const char *theirs, bool automerge) +{ + git_commit *our_commit, *their_commit, *ancestor_commit; + git_tree *our_tree, *their_tree, *ancestor_tree; + git_oid our_oid, their_oid, ancestor_oid; + git_buf branch_buf = GIT_BUF_INIT; + git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; + + opts.automerge_flags |= automerge ? 0 : GIT_MERGE_AUTOMERGE_NONE; + + git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours); + cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr)); + cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid)); + + git_buf_clear(&branch_buf); + git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs); + cl_git_pass(git_reference_name_to_id(&their_oid, repo, branch_buf.ptr)); + cl_git_pass(git_commit_lookup(&their_commit, repo, &their_oid)); + + cl_git_pass(git_merge_base(&ancestor_oid, repo, git_commit_id(our_commit), git_commit_id(their_commit))); + cl_git_pass(git_commit_lookup(&ancestor_commit, repo, &ancestor_oid)); + + cl_git_pass(git_commit_tree(&ancestor_tree, ancestor_commit)); + cl_git_pass(git_commit_tree(&our_tree, our_commit)); + cl_git_pass(git_commit_tree(&their_tree, their_commit)); + + cl_git_pass(git_merge_trees(index, repo, ancestor_tree, our_tree, their_tree, &opts)); + + git_buf_free(&branch_buf); + git_tree_free(our_tree); + git_tree_free(their_tree); + git_tree_free(ancestor_tree); + git_commit_free(our_commit); + git_commit_free(their_commit); + git_commit_free(ancestor_commit); + + return 0; +} + +static int merge_trivial_conflict_entrycount(git_index *index) +{ + const git_index_entry *entry; + int count = 0; + size_t i; + + for (i = 0; i < git_index_entrycount(index); i++) { + cl_assert(entry = git_index_get_byindex(index, i)); + + if (git_index_entry_stage(entry) > 0) + count++; + } + + return count; +} + +/* 2ALT: ancest:(empty)+, head:*empty*, remote:remote = result:remote */ +void test_merge_trees_trivial__2alt(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-2alt", "trivial-2alt-branch", 0)); + + cl_assert(entry = git_index_get_bypath(result, "new-in-branch.txt", 0)); + cl_assert(git_index_reuc_entrycount(result) == 0); + cl_assert(merge_trivial_conflict_entrycount(result) == 0); + + git_index_free(result); +} + +/* 3ALT: ancest:(empty)+, head:head, remote:*empty* = result:head */ +void test_merge_trees_trivial__3alt(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-3alt", "trivial-3alt-branch", 0)); + + cl_assert(entry = git_index_get_bypath(result, "new-in-3alt.txt", 0)); + cl_assert(git_index_reuc_entrycount(result) == 0); + cl_assert(merge_trivial_conflict_entrycount(result) == 0); + + git_index_free(result); +} + +/* 4: ancest:(empty)^, head:head, remote:remote = result:no merge */ +void test_merge_trees_trivial__4(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-4", "trivial-4-branch", 0)); + + cl_assert((entry = git_index_get_bypath(result, "new-and-different.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(result) == 0); + + cl_assert(merge_trivial_conflict_entrycount(result) == 2); + cl_assert(entry = git_index_get_bypath(result, "new-and-different.txt", 2)); + cl_assert(entry = git_index_get_bypath(result, "new-and-different.txt", 3)); + + git_index_free(result); +} + +/* 5ALT: ancest:*, head:head, remote:head = result:head */ +void test_merge_trees_trivial__5alt_1(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-5alt-1", "trivial-5alt-1-branch", 0)); + + cl_assert(entry = git_index_get_bypath(result, "new-and-same.txt", 0)); + cl_assert(git_index_reuc_entrycount(result) == 0); + cl_assert(merge_trivial_conflict_entrycount(result) == 0); + + git_index_free(result); +} + +/* 5ALT: ancest:*, head:head, remote:head = result:head */ +void test_merge_trees_trivial__5alt_2(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-5alt-2", "trivial-5alt-2-branch", 0)); + + cl_assert(entry = git_index_get_bypath(result, "modified-to-same.txt", 0)); + cl_assert(git_index_reuc_entrycount(result) == 0); + cl_assert(merge_trivial_conflict_entrycount(result) == 0); + + git_index_free(result); +} + +/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */ +void test_merge_trees_trivial__6(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-6", "trivial-6-branch", 0)); + + cl_assert((entry = git_index_get_bypath(result, "removed-in-both.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(result) == 0); + + cl_assert(merge_trivial_conflict_entrycount(result) == 1); + cl_assert(entry = git_index_get_bypath(result, "removed-in-both.txt", 1)); + + git_index_free(result); +} + +/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */ +void test_merge_trees_trivial__6_automerge(void) +{ + git_index *result; + const git_index_entry *entry; + const git_index_reuc_entry *reuc; + + cl_git_pass(merge_trivial(&result, "trivial-6", "trivial-6-branch", 1)); + + cl_assert((entry = git_index_get_bypath(result, "removed-in-both.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(result) == 1); + cl_assert(reuc = git_index_reuc_get_bypath(result, "removed-in-both.txt")); + + cl_assert(merge_trivial_conflict_entrycount(result) == 0); + + git_index_free(result); +} + +/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */ +void test_merge_trees_trivial__8(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-8", "trivial-8-branch", 0)); + + cl_assert((entry = git_index_get_bypath(result, "removed-in-8.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(result) == 0); + + cl_assert(merge_trivial_conflict_entrycount(result) == 2); + cl_assert(entry = git_index_get_bypath(result, "removed-in-8.txt", 1)); + cl_assert(entry = git_index_get_bypath(result, "removed-in-8.txt", 3)); + + git_index_free(result); +} + +/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */ +void test_merge_trees_trivial__8_automerge(void) +{ + git_index *result; + const git_index_entry *entry; + const git_index_reuc_entry *reuc; + + cl_git_pass(merge_trivial(&result, "trivial-8", "trivial-8-branch", 1)); + + cl_assert((entry = git_index_get_bypath(result, "removed-in-8.txt", 0)) == NULL); + + cl_assert(git_index_reuc_entrycount(result) == 1); + cl_assert(reuc = git_index_reuc_get_bypath(result, "removed-in-8.txt")); + + cl_assert(merge_trivial_conflict_entrycount(result) == 0); + + git_index_free(result); +} + +/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */ +void test_merge_trees_trivial__7(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-7", "trivial-7-branch", 0)); + + cl_assert((entry = git_index_get_bypath(result, "removed-in-7.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(result) == 0); + + cl_assert(merge_trivial_conflict_entrycount(result) == 2); + cl_assert(entry = git_index_get_bypath(result, "removed-in-7.txt", 1)); + cl_assert(entry = git_index_get_bypath(result, "removed-in-7.txt", 3)); + + git_index_free(result); +} + +/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */ +void test_merge_trees_trivial__7_automerge(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-7", "trivial-7-branch", 0)); + + cl_assert((entry = git_index_get_bypath(result, "removed-in-7.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(result) == 0); + + cl_assert(merge_trivial_conflict_entrycount(result) == 2); + cl_assert(entry = git_index_get_bypath(result, "removed-in-7.txt", 1)); + cl_assert(entry = git_index_get_bypath(result, "removed-in-7.txt", 3)); + + git_index_free(result); +} + +/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */ +void test_merge_trees_trivial__10(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-10", "trivial-10-branch", 0)); + + cl_assert((entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(result) == 0); + + cl_assert(merge_trivial_conflict_entrycount(result) == 2); + cl_assert(entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 1)); + cl_assert(entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 2)); + + git_index_free(result); +} + +/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */ +void test_merge_trees_trivial__10_automerge(void) +{ + git_index *result; + const git_index_entry *entry; + const git_index_reuc_entry *reuc; + + cl_git_pass(merge_trivial(&result, "trivial-10", "trivial-10-branch", 1)); + + cl_assert((entry = git_index_get_bypath(result, "removed-in-10-branch.txt", 0)) == NULL); + + cl_assert(git_index_reuc_entrycount(result) == 1); + cl_assert(reuc = git_index_reuc_get_bypath(result, "removed-in-10-branch.txt")); + + cl_assert(merge_trivial_conflict_entrycount(result) == 0); + + git_index_free(result); +} + +/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */ +void test_merge_trees_trivial__9(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-9", "trivial-9-branch", 0)); + + cl_assert((entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(result) == 0); + + cl_assert(merge_trivial_conflict_entrycount(result) == 2); + cl_assert(entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 1)); + cl_assert(entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 2)); + + git_index_free(result); +} + +/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */ +void test_merge_trees_trivial__9_automerge(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-9", "trivial-9-branch", 1)); + + cl_assert((entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(result) == 0); + + cl_assert(merge_trivial_conflict_entrycount(result) == 2); + cl_assert(entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 1)); + cl_assert(entry = git_index_get_bypath(result, "removed-in-9-branch.txt", 2)); + + git_index_free(result); +} + +/* 13: ancest:ancest+, head:head, remote:ancest = result:head */ +void test_merge_trees_trivial__13(void) +{ + git_index *result; + const git_index_entry *entry; + git_oid expected_oid; + + cl_git_pass(merge_trivial(&result, "trivial-13", "trivial-13-branch", 0)); + + cl_assert(entry = git_index_get_bypath(result, "modified-in-13.txt", 0)); + cl_git_pass(git_oid_fromstr(&expected_oid, "1cff9ec6a47a537380dedfdd17c9e76d74259a2b")); + cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0); + + cl_assert(git_index_reuc_entrycount(result) == 0); + cl_assert(merge_trivial_conflict_entrycount(result) == 0); + + git_index_free(result); +} + +/* 14: ancest:ancest+, head:ancest, remote:remote = result:remote */ +void test_merge_trees_trivial__14(void) +{ + git_index *result; + const git_index_entry *entry; + git_oid expected_oid; + + cl_git_pass(merge_trivial(&result, "trivial-14", "trivial-14-branch", 0)); + + cl_assert(entry = git_index_get_bypath(result, "modified-in-14-branch.txt", 0)); + cl_git_pass(git_oid_fromstr(&expected_oid, "26153a3ff3649b6c2bb652d3f06878c6e0a172f9")); + cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0); + + cl_assert(git_index_reuc_entrycount(result) == 0); + cl_assert(merge_trivial_conflict_entrycount(result) == 0); + + git_index_free(result); +} + +/* 11: ancest:ancest+, head:head, remote:remote = result:no merge */ +void test_merge_trees_trivial__11(void) +{ + git_index *result; + const git_index_entry *entry; + + cl_git_pass(merge_trivial(&result, "trivial-11", "trivial-11-branch", 0)); + + cl_assert((entry = git_index_get_bypath(result, "modified-in-both.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(result) == 0); + + cl_assert(merge_trivial_conflict_entrycount(result) == 3); + cl_assert(entry = git_index_get_bypath(result, "modified-in-both.txt", 1)); + cl_assert(entry = git_index_get_bypath(result, "modified-in-both.txt", 2)); + cl_assert(entry = git_index_get_bypath(result, "modified-in-both.txt", 3)); + + git_index_free(result); +} diff --git a/tests/merge/workdir/fastforward.c b/tests/merge/workdir/fastforward.c new file mode 100644 index 000000000..861f38354 --- /dev/null +++ b/tests/merge/workdir/fastforward.c @@ -0,0 +1,148 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "git2/sys/index.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "refs.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "merge-resolve" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +#define THEIRS_FASTFORWARD_BRANCH "ff_branch" +#define THEIRS_FASTFORWARD_OID "fd89f8cffb663ac89095a0f9764902e93ceaca6a" + +#define THEIRS_NOFASTFORWARD_BRANCH "branch" +#define THEIRS_NOFASTFORWARD_OID "7cb63eed597130ba4abb87b3e544b85021905520" + + +// Fixture setup and teardown +void test_merge_workdir_fastforward__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); + git_repository_index(&repo_index, repo); +} + +void test_merge_workdir_fastforward__cleanup(void) +{ + git_index_free(repo_index); + cl_git_sandbox_cleanup(); +} + +static git_merge_result *merge_fastforward_branch(int flags) +{ + git_reference *their_ref; + git_merge_head *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + opts.merge_flags = flags; + + cl_git_pass(git_reference_lookup(&their_ref, repo, GIT_REFS_HEADS_DIR THEIRS_FASTFORWARD_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref)); + + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); + + git_merge_head_free(their_heads[0]); + git_reference_free(their_ref); + + return result; +} + +void test_merge_workdir_fastforward__fastforward(void) +{ + git_merge_result *result; + git_oid expected, ff_oid; + + cl_git_pass(git_oid_fromstr(&expected, THEIRS_FASTFORWARD_OID)); + + cl_assert(result = merge_fastforward_branch(0)); + cl_assert(git_merge_result_is_fastforward(result)); + cl_git_pass(git_merge_result_fastforward_oid(&ff_oid, result)); + cl_assert(git_oid_cmp(&ff_oid, &expected) == 0); + + git_merge_result_free(result); +} + +void test_merge_workdir_fastforward__fastforward_only(void) +{ + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + git_reference *their_ref; + git_merge_head *their_head; + int error; + + opts.merge_flags = GIT_MERGE_FASTFORWARD_ONLY; + + cl_git_pass(git_reference_lookup(&their_ref, repo, GIT_REFS_HEADS_DIR THEIRS_NOFASTFORWARD_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref)); + + cl_git_fail((error = git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts))); + cl_assert(error == GIT_ENONFASTFORWARD); + + git_merge_head_free(their_head); + git_reference_free(their_ref); +} + +void test_merge_workdir_fastforward__no_fastforward(void) +{ + git_merge_result *result; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, + { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" }, + { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, + { 0100644, "bd9cb4cd0a770cb9adcb5fce212142ef40ea1c35", 0, "changed-in-master.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, + { 0100644, "364bbe4ce80c7bd31e6307dce77d46e3e1759fb3", 0, "new-in-ff.txt" }, + { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, + { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, + }; + + cl_assert(result = merge_fastforward_branch(GIT_MERGE_NO_FASTFORWARD)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + git_merge_result_free(result); +} + +void test_merge_workdir_fastforward__uptodate(void) +{ + git_reference *their_ref; + git_merge_head *their_heads[1]; + git_merge_result *result; + + cl_git_pass(git_reference_lookup(&their_ref, repo, GIT_HEAD_FILE)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref)); + + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, NULL)); + + cl_assert(git_merge_result_is_uptodate(result)); + + git_merge_head_free(their_heads[0]); + git_reference_free(their_ref); + git_merge_result_free(result); +} + +void test_merge_workdir_fastforward__uptodate_merging_prev_commit(void) +{ + git_oid their_oid; + git_merge_head *their_heads[1]; + git_merge_result *result; + + cl_git_pass(git_oid_fromstr(&their_oid, "c607fc30883e335def28cd686b51f6cfa02b06ec")); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oid)); + + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, NULL)); + + cl_assert(git_merge_result_is_uptodate(result)); + + git_merge_head_free(their_heads[0]); + git_merge_result_free(result); +} + diff --git a/tests/merge/workdir/renames.c b/tests/merge/workdir/renames.c new file mode 100644 index 000000000..d38397983 --- /dev/null +++ b/tests/merge/workdir/renames.c @@ -0,0 +1,156 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "buffer.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "fileops.h" +#include "refs.h" + +static git_repository *repo; + +#define TEST_REPO_PATH "merge-resolve" + +#define BRANCH_RENAME_OURS "rename_conflict_ours" +#define BRANCH_RENAME_THEIRS "rename_conflict_theirs" + +// Fixture setup and teardown +void test_merge_workdir_renames__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); +} + +void test_merge_workdir_renames__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_merge_workdir_renames__renames(void) +{ + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, + { 0100644, "8aac75de2a34b4d340bf62a6e58197269cb55797", 0, "0b-rewritten-in-ours.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, + { 0100644, "7edc726325da726751a4195e434e4377b0f67f9a", 0, "0c-rewritten-in-theirs.txt" }, + { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, + { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, + { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, + { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, + { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-newname-in-ours-added-in-theirs.txt~HEAD" }, + { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 0, "4a-newname-in-ours-added-in-theirs.txt~rename_conflict_theirs" }, + { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 0, "4b-newname-in-theirs-added-in-ours.txt~HEAD" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 0, "4b-newname-in-theirs-added-in-ours.txt~rename_conflict_theirs" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 0, "5a-newname-in-ours-added-in-theirs.txt~HEAD" }, + { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 0, "5a-newname-in-ours-added-in-theirs.txt~rename_conflict_theirs" }, + { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 0, "5b-newname-in-theirs-added-in-ours.txt~HEAD" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 0, "5b-newname-in-theirs-added-in-ours.txt~rename_conflict_theirs" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-theirs.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt~HEAD" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" }, + }; + + opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; + opts.merge_tree_opts.rename_threshold = 50; + + cl_git_pass(merge_branches(&result, repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &opts)); + cl_assert(merge_test_workdir(repo, merge_index_entries, 24)); + + git_merge_result_free(result); +} + +void test_merge_workdir_renames__ours(void) +{ + git_index *index; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, + { 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e", 0, "0b-rewritten-in-ours.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, + { 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09", 0, "0c-rewritten-in-theirs.txt" }, + { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, + { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, + { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, + { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, + { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 0, "4b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 0, "5a-newname-in-ours-added-in-theirs.txt" }, + { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 0, "5b-newname-in-theirs-added-in-ours.txt" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 0, "5b-renamed-in-theirs-added-in-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-ours.txt" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed-side-2.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt" }, + }; + + opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; + opts.merge_tree_opts.rename_threshold = 50; + opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS; + + cl_git_pass(merge_branches(&result, repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &opts)); + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_write(index)); + cl_assert(merge_test_workdir(repo, merge_index_entries, 20)); + + git_merge_result_free(result); + git_index_free(index); +} + +void test_merge_workdir_renames__similar(void) +{ + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + /* + * Note: this differs slightly from the core git merge result - there, 4a is + * tracked as a rename/delete instead of a rename/add and the theirs side + * is not placed in workdir in any form. + */ + struct merge_index_entry merge_index_entries[] = { + { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, + { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, + { 0100644, "8aac75de2a34b4d340bf62a6e58197269cb55797", 0, "0b-rewritten-in-ours.txt" }, + { 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31", 0, "0c-duplicated-in-theirs.txt" }, + { 0100644, "7edc726325da726751a4195e434e4377b0f67f9a", 0, "0c-rewritten-in-theirs.txt" }, + { 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638", 0, "1a-newname-in-ours-edited-in-theirs.txt" }, + { 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb", 0, "1a-newname-in-ours.txt" }, + { 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a", 0, "1b-newname-in-theirs-edited-in-ours.txt" }, + { 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136", 0, "1b-newname-in-theirs.txt" }, + { 0100644, "178940b450f238a56c0d75b7955cb57b38191982", 0, "2-newname-in-both.txt" }, + { 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9", 0, "3a-newname-in-ours-deleted-in-theirs.txt" }, + { 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495", 0, "3b-newname-in-theirs-deleted-in-ours.txt" }, + { 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c", 0, "4a-newname-in-ours-added-in-theirs.txt~HEAD" }, + { 0100644, "8b5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a", 0, "4a-newname-in-ours-added-in-theirs.txt~rename_conflict_theirs" }, + { 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9", 0, "4b-newname-in-theirs-added-in-ours.txt~HEAD" }, + { 0100644, "98d52d07c0b0bbf2b46548f6aa521295c2cb55db", 0, "4b-newname-in-theirs-added-in-ours.txt~rename_conflict_theirs" }, + { 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436", 0, "5a-newname-in-ours-added-in-theirs.txt~HEAD" }, + { 0100644, "98ba4205fcf31f5dd93c916d35fe3f3b3d0e6714", 0, "5a-newname-in-ours-added-in-theirs.txt~rename_conflict_theirs" }, + { 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced", 0, "5b-newname-in-theirs-added-in-ours.txt~HEAD" }, + { 0100644, "63247125386de9ec90a27ad36169307bf8a11a38", 0, "5b-newname-in-theirs-added-in-ours.txt~rename_conflict_theirs" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-ours.txt" }, + { 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450", 0, "6-both-renamed-1-to-2-theirs.txt" }, + { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt~HEAD" }, + { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" }, + }; + + opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; + opts.merge_tree_opts.rename_threshold = 50; + + cl_git_pass(merge_branches(&result, repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &opts)); + cl_assert(merge_test_workdir(repo, merge_index_entries, 24)); + + git_merge_result_free(result); +} + diff --git a/tests/merge/workdir/setup.c b/tests/merge/workdir/setup.c new file mode 100644 index 000000000..870d55ef2 --- /dev/null +++ b/tests/merge/workdir/setup.c @@ -0,0 +1,1057 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "merge.h" +#include "refs.h" +#include "fileops.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "merge-resolve" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +#define ORIG_HEAD "bd593285fc7fe4ca18ccdbabf027f5d689101452" + +#define THEIRS_SIMPLE_BRANCH "branch" +#define THEIRS_SIMPLE_OID "7cb63eed597130ba4abb87b3e544b85021905520" + +#define OCTO1_BRANCH "octo1" +#define OCTO1_OID "16f825815cfd20a07a75c71554e82d8eede0b061" + +#define OCTO2_BRANCH "octo2" +#define OCTO2_OID "158dc7bedb202f5b26502bf3574faa7f4238d56c" + +#define OCTO3_BRANCH "octo3" +#define OCTO3_OID "50ce7d7d01217679e26c55939eef119e0c93e272" + +#define OCTO4_BRANCH "octo4" +#define OCTO4_OID "54269b3f6ec3d7d4ede24dd350dd5d605495c3ae" + +#define OCTO5_BRANCH "octo5" +#define OCTO5_OID "e4f618a2c3ed0669308735727df5ebf2447f022f" + +// Fixture setup and teardown +void test_merge_workdir_setup__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); + git_repository_index(&repo_index, repo); +} + +void test_merge_workdir_setup__cleanup(void) +{ + git_index_free(repo_index); + cl_git_sandbox_cleanup(); +} + +static bool test_file_contents(const char *filename, const char *expected) +{ + git_buf file_path_buf = GIT_BUF_INIT, file_buf = GIT_BUF_INIT; + bool equals; + + git_buf_printf(&file_path_buf, "%s/%s", git_repository_path(repo), filename); + + cl_git_pass(git_futils_readbuffer(&file_buf, file_path_buf.ptr)); + equals = (strcmp(file_buf.ptr, expected) == 0); + + git_buf_free(&file_path_buf); + git_buf_free(&file_buf); + + return equals; +} + +static void write_file_contents(const char *filename, const char *output) +{ + git_buf file_path_buf = GIT_BUF_INIT; + + git_buf_printf(&file_path_buf, "%s/%s", git_repository_path(repo), + filename); + cl_git_rewritefile(file_path_buf.ptr, output); + + git_buf_free(&file_path_buf); +} + +/* git merge octo1 */ +void test_merge_workdir_setup__one_branch(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_merge_head *our_head, *their_heads[1]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'\n")); + + git_reference_free(octo1_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); +} + +/* git merge --no-ff octo1 */ +void test_merge_workdir_setup__no_fastforward(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_merge_head *our_head, *their_heads[1]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, GIT_MERGE_NO_FASTFORWARD)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'\n")); + + git_reference_free(octo1_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); +} + +/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 */ +void test_merge_workdir_setup__one_oid(void) +{ + git_oid our_oid; + git_oid octo1_oid; + git_merge_head *our_head, *their_heads[1]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'\n")); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); +} + +/* git merge octo1 octo2 */ +void test_merge_workdir_setup__two_branches(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_reference *octo2_ref; + git_merge_head *our_head, *their_heads[2]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO2_BRANCH "'\n")); + + git_reference_free(octo1_ref); + git_reference_free(octo2_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); +} + +/* git merge octo1 octo2 octo3 */ +void test_merge_workdir_setup__three_branches(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_reference *octo2_ref; + git_reference *octo3_ref; + git_merge_head *our_head, *their_heads[3]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + + cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO2_BRANCH "' and '" OCTO3_BRANCH "'\n")); + + git_reference_free(octo1_ref); + git_reference_free(octo2_ref); + git_reference_free(octo3_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); + git_merge_head_free(their_heads[2]); +} + +/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 158dc7bedb202f5b26502bf3574faa7f4238d56c 50ce7d7d01217679e26c55939eef119e0c93e272 */ +void test_merge_workdir_setup__three_oids(void) +{ + git_oid our_oid; + git_oid octo1_oid; + git_oid octo2_oid; + git_oid octo3_oid; + git_merge_head *our_head, *their_heads[3]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid)); + + cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo2_oid)); + + cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo3_oid)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; commit '" OCTO2_OID "'; commit '" OCTO3_OID "'\n")); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); + git_merge_head_free(their_heads[2]); +} + +/* git merge octo1 158dc7bedb202f5b26502bf3574faa7f4238d56c */ +void test_merge_workdir_setup__branches_and_oids_1(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_oid octo2_oid; + git_merge_head *our_head, *their_heads[2]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo2_oid)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'; commit '" OCTO2_OID "'\n")); + + git_reference_free(octo1_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); +} + +/* git merge octo1 158dc7bedb202f5b26502bf3574faa7f4238d56c octo3 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae */ +void test_merge_workdir_setup__branches_and_oids_2(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_oid octo2_oid; + git_reference *octo3_ref; + git_oid octo4_oid; + git_merge_head *our_head, *their_heads[4]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo2_oid)); + + cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref)); + + cl_git_pass(git_oid_fromstr(&octo4_oid, OCTO4_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[3], repo, &octo4_oid)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "'; commit '" OCTO2_OID "'; commit '" OCTO4_OID "'\n")); + + git_reference_free(octo1_ref); + git_reference_free(octo3_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); + git_merge_head_free(their_heads[2]); + git_merge_head_free(their_heads[3]); +} + +/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 octo2 50ce7d7d01217679e26c55939eef119e0c93e272 octo4 */ +void test_merge_workdir_setup__branches_and_oids_3(void) +{ + git_oid our_oid; + git_oid octo1_oid; + git_reference *octo2_ref; + git_oid octo3_oid; + git_reference *octo4_ref; + git_merge_head *our_head, *their_heads[4]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid)); + + cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + + cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo3_oid)); + + cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[3], repo, octo4_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; branches '" OCTO2_BRANCH "' and '" OCTO4_BRANCH "'; commit '" OCTO3_OID "'\n")); + + git_reference_free(octo2_ref); + git_reference_free(octo4_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); + git_merge_head_free(their_heads[2]); + git_merge_head_free(their_heads[3]); +} + +/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 octo2 50ce7d7d01217679e26c55939eef119e0c93e272 octo4 octo5 */ +void test_merge_workdir_setup__branches_and_oids_4(void) +{ + git_oid our_oid; + git_oid octo1_oid; + git_reference *octo2_ref; + git_oid octo3_oid; + git_reference *octo4_ref; + git_reference *octo5_ref; + git_merge_head *our_head, *their_heads[5]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid)); + + cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + + cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo3_oid)); + + cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[3], repo, octo4_ref)); + + cl_git_pass(git_reference_lookup(&octo5_ref, repo, GIT_REFS_HEADS_DIR OCTO5_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[4], repo, octo5_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 5, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n" OCTO5_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; branches '" OCTO2_BRANCH "', '" OCTO4_BRANCH "' and '" OCTO5_BRANCH "'; commit '" OCTO3_OID "'\n")); + + git_reference_free(octo2_ref); + git_reference_free(octo4_ref); + git_reference_free(octo5_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); + git_merge_head_free(their_heads[2]); + git_merge_head_free(their_heads[3]); + git_merge_head_free(their_heads[4]); +} + +/* git merge octo1 octo1 octo1 */ +void test_merge_workdir_setup__three_same_branches(void) +{ + git_oid our_oid; + git_reference *octo1_1_ref; + git_reference *octo1_2_ref; + git_reference *octo1_3_ref; + git_merge_head *our_head, *their_heads[3]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_1_ref)); + + cl_git_pass(git_reference_lookup(&octo1_2_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo1_2_ref)); + + cl_git_pass(git_reference_lookup(&octo1_3_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo1_3_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO1_OID "\n" OCTO1_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO1_BRANCH "' and '" OCTO1_BRANCH "'\n")); + + git_reference_free(octo1_1_ref); + git_reference_free(octo1_2_ref); + git_reference_free(octo1_3_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); + git_merge_head_free(their_heads[2]); +} + +/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 16f825815cfd20a07a75c71554e82d8eede0b061 16f825815cfd20a07a75c71554e82d8eede0b061 */ +void test_merge_workdir_setup__three_same_oids(void) +{ + git_oid our_oid; + git_oid octo1_1_oid; + git_oid octo1_2_oid; + git_oid octo1_3_oid; + git_merge_head *our_head, *their_heads[3]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_oid_fromstr(&octo1_1_oid, OCTO1_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_1_oid)); + + cl_git_pass(git_oid_fromstr(&octo1_2_oid, OCTO1_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo1_2_oid)); + + cl_git_pass(git_oid_fromstr(&octo1_3_oid, OCTO1_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo1_3_oid)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO1_OID "\n" OCTO1_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; commit '" OCTO1_OID "'; commit '" OCTO1_OID "'\n")); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); + git_merge_head_free(their_heads[2]); +} + +static int create_remote_tracking_branch(const char *branch_name, const char *oid_str) +{ + int error = 0; + + git_buf remotes_path = GIT_BUF_INIT, + origin_path = GIT_BUF_INIT, + filename = GIT_BUF_INIT, + data = GIT_BUF_INIT; + + if ((error = git_buf_puts(&remotes_path, git_repository_path(repo))) < 0 || + (error = git_buf_puts(&remotes_path, GIT_REFS_REMOTES_DIR)) < 0) + goto done; + + if (!git_path_exists(git_buf_cstr(&remotes_path)) && + (error = p_mkdir(git_buf_cstr(&remotes_path), 0777)) < 0) + goto done; + + if ((error = git_buf_puts(&origin_path, git_buf_cstr(&remotes_path))) < 0 || + (error = git_buf_puts(&origin_path, "origin")) < 0) + goto done; + + if (!git_path_exists(git_buf_cstr(&origin_path)) && + (error = p_mkdir(git_buf_cstr(&origin_path), 0777)) < 0) + goto done; + + if ((error = git_buf_puts(&filename, git_buf_cstr(&origin_path))) < 0 || + (error = git_buf_puts(&filename, "/")) < 0 || + (error = git_buf_puts(&filename, branch_name)) < 0 || + (error = git_buf_puts(&data, oid_str)) < 0 || + (error = git_buf_puts(&data, "\n")) < 0) + goto done; + + cl_git_rewritefile(git_buf_cstr(&filename), git_buf_cstr(&data)); + +done: + git_buf_free(&remotes_path); + git_buf_free(&origin_path); + git_buf_free(&filename); + git_buf_free(&data); + + return error; +} + +/* git merge refs/remotes/origin/octo1 */ +void test_merge_workdir_setup__remote_tracking_one_branch(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_merge_head *our_head, *their_heads[1]; + + cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID)); + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branch 'refs/remotes/origin/" OCTO1_BRANCH "'\n")); + + git_reference_free(octo1_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); +} + +/* git merge refs/remotes/origin/octo1 refs/remotes/origin/octo2 */ +void test_merge_workdir_setup__remote_tracking_two_branches(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_reference *octo2_ref; + git_merge_head *our_head, *their_heads[2]; + + cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID)); + cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID)); + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branches 'refs/remotes/origin/" OCTO1_BRANCH "' and 'refs/remotes/origin/" OCTO2_BRANCH "'\n")); + + git_reference_free(octo1_ref); + git_reference_free(octo2_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); +} + +/* git merge refs/remotes/origin/octo1 refs/remotes/origin/octo2 refs/remotes/origin/octo3 */ +void test_merge_workdir_setup__remote_tracking_three_branches(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_reference *octo2_ref; + git_reference *octo3_ref; + git_merge_head *our_head, *their_heads[3]; + + cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID)); + cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID)); + cl_git_pass(create_remote_tracking_branch(OCTO3_BRANCH, OCTO3_OID)); + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + + cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO3_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branches 'refs/remotes/origin/" OCTO1_BRANCH "', 'refs/remotes/origin/" OCTO2_BRANCH "' and 'refs/remotes/origin/" OCTO3_BRANCH "'\n")); + + git_reference_free(octo1_ref); + git_reference_free(octo2_ref); + git_reference_free(octo3_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); + git_merge_head_free(their_heads[2]); +} + +/* git merge octo1 refs/remotes/origin/octo2 */ +void test_merge_workdir_setup__normal_branch_and_remote_tracking_branch(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_reference *octo2_ref; + git_merge_head *our_head, *their_heads[2]; + + cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID)); + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "', remote-tracking branch 'refs/remotes/origin/" OCTO2_BRANCH "'\n")); + + git_reference_free(octo1_ref); + git_reference_free(octo2_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); +} + +/* git merge refs/remotes/origin/octo1 octo2 */ +void test_merge_workdir_setup__remote_tracking_branch_and_normal_branch(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_reference *octo2_ref; + git_merge_head *our_head, *their_heads[2]; + + cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID)); + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO2_BRANCH "', remote-tracking branch 'refs/remotes/origin/" OCTO1_BRANCH "'\n")); + + git_reference_free(octo1_ref); + git_reference_free(octo2_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); +} + +/* git merge octo1 refs/remotes/origin/octo2 octo3 refs/remotes/origin/octo4 */ +void test_merge_workdir_setup__two_remote_tracking_branch_and_two_normal_branches(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_reference *octo2_ref; + git_reference *octo3_ref; + git_reference *octo4_ref; + git_merge_head *our_head, *their_heads[4]; + + cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID)); + cl_git_pass(create_remote_tracking_branch(OCTO4_BRANCH, OCTO4_OID)); + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref)); + + cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref)); + + cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO4_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[3], repo, octo4_ref)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "', remote-tracking branches 'refs/remotes/origin/" OCTO2_BRANCH "' and 'refs/remotes/origin/" OCTO4_BRANCH "'\n")); + + git_reference_free(octo1_ref); + git_reference_free(octo2_ref); + git_reference_free(octo3_ref); + git_reference_free(octo4_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); + git_merge_head_free(their_heads[2]); + git_merge_head_free(their_heads[3]); +} + +/* git pull origin branch octo1 */ +void test_merge_workdir_setup__pull_one(void) +{ + git_oid our_oid; + git_oid octo1_1_oid; + git_merge_head *our_head, *their_heads[1]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_oid_fromstr(&octo1_1_oid, OCTO1_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_1_oid)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch 'octo1' of http://remote.url/repo.git\n")); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); +} + +/* git pull origin octo1 octo2 */ +void test_merge_workdir_setup__pull_two(void) +{ + git_oid our_oid; + git_oid octo1_oid; + git_oid octo2_oid; + git_merge_head *our_head, *their_heads[2]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_oid)); + + cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.url/repo.git", &octo2_oid)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO2_BRANCH "' of http://remote.url/repo.git\n")); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); +} + +/* git pull origin octo1 octo2 octo3 */ +void test_merge_workdir_setup__pull_three(void) +{ + git_oid our_oid; + git_oid octo1_oid; + git_oid octo2_oid; + git_oid octo3_oid; + git_merge_head *our_head, *their_heads[3]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_oid)); + + cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.url/repo.git", &octo2_oid)); + + cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.url/repo.git", &octo3_oid)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO2_BRANCH "' and '" OCTO3_BRANCH "' of http://remote.url/repo.git\n")); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); + git_merge_head_free(their_heads[2]); +} + +void test_merge_workdir_setup__three_remotes(void) +{ + git_oid our_oid; + git_oid octo1_oid; + git_oid octo2_oid; + git_oid octo3_oid; + git_merge_head *our_head, *their_heads[3]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.first/repo.git", &octo1_oid)); + + cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.second/repo.git", &octo2_oid)); + + cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.third/repo.git", &octo3_oid)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "' of http://remote.first/repo.git, branch '" OCTO2_BRANCH "' of http://remote.second/repo.git, branch '" OCTO3_BRANCH "' of http://remote.third/repo.git\n")); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); + git_merge_head_free(their_heads[2]); +} + +void test_merge_workdir_setup__two_remotes(void) +{ + git_oid our_oid; + git_oid octo1_oid; + git_oid octo2_oid; + git_oid octo3_oid; + git_oid octo4_oid; + git_merge_head *our_head, *their_heads[4]; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.first/repo.git", &octo1_oid)); + + cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.second/repo.git", &octo2_oid)); + + cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.first/repo.git", &octo3_oid)); + + cl_git_pass(git_oid_fromstr(&octo4_oid, OCTO4_OID)); + cl_git_pass(git_merge_head_from_fetchhead(&their_heads[3], repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH, "http://remote.second/repo.git", &octo4_oid)); + + cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "' of http://remote.first/repo.git, branches '" OCTO2_BRANCH "' and '" OCTO4_BRANCH "' of http://remote.second/repo.git\n")); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_head_free(their_heads[1]); + git_merge_head_free(their_heads[2]); + git_merge_head_free(their_heads[3]); +} + +struct merge_head_cb_data { + const char **oid_str; + unsigned int len; + + unsigned int i; +}; + +static int merge_head_foreach_cb(const git_oid *oid, void *payload) +{ + git_oid expected_oid; + struct merge_head_cb_data *cb_data = payload; + + git_oid_fromstr(&expected_oid, cb_data->oid_str[cb_data->i]); + cl_assert(git_oid_cmp(&expected_oid, oid) == 0); + cb_data->i++; + return 0; +} + +void test_merge_workdir_setup__head_notfound(void) +{ + int error; + + cl_git_fail((error = git_repository_mergehead_foreach(repo, + merge_head_foreach_cb, NULL))); + cl_assert(error == GIT_ENOTFOUND); +} + +void test_merge_workdir_setup__head_invalid_oid(void) +{ + int error; + + write_file_contents(GIT_MERGE_HEAD_FILE, "invalid-oid\n"); + + cl_git_fail((error = git_repository_mergehead_foreach(repo, + merge_head_foreach_cb, NULL))); + cl_assert(error == -1); +} + +void test_merge_workdir_setup__head_foreach_nonewline(void) +{ + int error; + + write_file_contents(GIT_MERGE_HEAD_FILE, THEIRS_SIMPLE_OID); + + cl_git_fail((error = git_repository_mergehead_foreach(repo, + merge_head_foreach_cb, NULL))); + cl_assert(error == -1); +} + +void test_merge_workdir_setup__head_foreach_one(void) +{ + const char *expected = THEIRS_SIMPLE_OID; + + struct merge_head_cb_data cb_data = { &expected, 1 }; + + write_file_contents(GIT_MERGE_HEAD_FILE, THEIRS_SIMPLE_OID "\n"); + + cl_git_pass(git_repository_mergehead_foreach(repo, + merge_head_foreach_cb, &cb_data)); + + cl_assert(cb_data.i == cb_data.len); +} + +void test_merge_workdir_setup__head_foreach_octopus(void) +{ + const char *expected[] = { THEIRS_SIMPLE_OID, + OCTO1_OID, OCTO2_OID, OCTO3_OID, OCTO4_OID, OCTO5_OID }; + + struct merge_head_cb_data cb_data = { expected, 6 }; + + write_file_contents(GIT_MERGE_HEAD_FILE, + THEIRS_SIMPLE_OID "\n" + OCTO1_OID "\n" + OCTO2_OID "\n" + OCTO3_OID "\n" + OCTO4_OID "\n" + OCTO5_OID "\n"); + + cl_git_pass(git_repository_mergehead_foreach(repo, + merge_head_foreach_cb, &cb_data)); + + cl_assert(cb_data.i == cb_data.len); +} + +void test_merge_workdir_setup__retained_after_success(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_merge_head *our_head, *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + opts.merge_flags |= GIT_MERGE_NO_FASTFORWARD; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_heads[0], 1, &opts)); + + cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); + cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n")); + cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff")); + cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'\n")); + + git_reference_free(octo1_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_result_free(result); +} + +void test_merge_workdir_setup__removed_after_failure(void) +{ + git_oid our_oid; + git_reference *octo1_ref; + git_merge_head *our_head, *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + opts.merge_flags |= GIT_MERGE_NO_FASTFORWARD; + + cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); + cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid)); + + cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); + + cl_git_rewritefile("merge-resolve/new-in-octo1.txt", + "Conflicting file!\n\nMerge will fail!\n"); + + cl_git_fail(git_merge( + &result, repo, (const git_merge_head **)&their_heads[0], 1, &opts)); + + cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_HEAD_FILE)); + cl_assert(!git_path_exists("merge-resolve/" GIT_ORIG_HEAD_FILE)); + cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_MODE_FILE)); + cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_MSG_FILE)); + + git_reference_free(octo1_ref); + + git_merge_head_free(our_head); + git_merge_head_free(their_heads[0]); + git_merge_result_free(result); +} diff --git a/tests/merge/workdir/simple.c b/tests/merge/workdir/simple.c new file mode 100644 index 000000000..4a3b86ee4 --- /dev/null +++ b/tests/merge/workdir/simple.c @@ -0,0 +1,491 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "buffer.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "refs.h" +#include "fileops.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "merge-resolve" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + +#define THEIRS_SIMPLE_BRANCH "branch" +#define THEIRS_SIMPLE_OID "7cb63eed597130ba4abb87b3e544b85021905520" + +#define THEIRS_UNRELATED_BRANCH "unrelated" +#define THEIRS_UNRELATED_OID "55b4e4687e7a0d9ca367016ed930f385d4022e6f" +#define THEIRS_UNRELATED_PARENT "d6cf6c7741b3316826af1314042550c97ded1d50" + +#define OURS_DIRECTORY_FILE "df_side1" +#define THEIRS_DIRECTORY_FILE "fc90237dc4891fa6c69827fc465632225e391618" + + +/* Non-conflicting files, index entries are common to every merge operation */ +#define ADDED_IN_MASTER_INDEX_ENTRY \ + { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, \ + "added-in-master.txt" } +#define AUTOMERGEABLE_INDEX_ENTRY \ + { 0100644, "f2e1550a0c9e53d5811175864a29536642ae3821", 0, \ + "automergeable.txt" } +#define CHANGED_IN_BRANCH_INDEX_ENTRY \ + { 0100644, "4eb04c9e79e88f6640d01ff5b25ca2a60764f216", 0, \ + "changed-in-branch.txt" } +#define CHANGED_IN_MASTER_INDEX_ENTRY \ + { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, \ + "changed-in-master.txt" } +#define UNCHANGED_INDEX_ENTRY \ + { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, \ + "unchanged.txt" } + +/* Unrelated files */ +#define UNRELATED_NEW1 \ + { 0100644, "ef58fdd8086c243bdc81f99e379acacfd21d32d6", 0, \ + "new-in-unrelated1.txt" } +#define UNRELATED_NEW2 \ + { 0100644, "948ba6e701c1edab0c2d394fb7c5538334129793", 0, \ + "new-in-unrelated2.txt" } + +/* Expected REUC entries */ +#define AUTOMERGEABLE_REUC_ENTRY \ + { "automergeable.txt", 0100644, 0100644, 0100644, \ + "6212c31dab5e482247d7977e4f0dd3601decf13b", \ + "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", \ + "058541fc37114bfc1dddf6bd6bffc7fae5c2e6fe" } +#define CONFLICTING_REUC_ENTRY \ + { "conflicting.txt", 0100644, 0100644, 0100644, \ + "d427e0b2e138501a3d15cc376077a3631e15bd46", \ + "4e886e602529caa9ab11d71f86634bd1b6e0de10", \ + "2bd0a343aeef7a2cf0d158478966a6e587ff3863" } +#define REMOVED_IN_BRANCH_REUC_ENTRY \ + { "removed-in-branch.txt", 0100644, 0100644, 0, \ + "dfe3f22baa1f6fce5447901c3086bae368de6bdd", \ + "dfe3f22baa1f6fce5447901c3086bae368de6bdd", \ + "" } +#define REMOVED_IN_MASTER_REUC_ENTRY \ + { "removed-in-master.txt", 0100644, 0, 0100644, \ + "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5", \ + "", \ + "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5" } + +#define AUTOMERGEABLE_MERGED_FILE \ + "this file is changed in master\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is automergeable\n" \ + "this file is changed in branch\n" + +#define AUTOMERGEABLE_MERGED_FILE_CRLF \ + "this file is changed in master\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is automergeable\r\n" \ + "this file is changed in branch\r\n" + +#define CONFLICTING_DIFF3_FILE \ + "<<<<<<< HEAD\n" \ + "this file is changed in master and branch\n" \ + "=======\n" \ + "this file is changed in branch and master\n" \ + ">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n" + +// Fixture setup and teardown +void test_merge_workdir_simple__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); + git_repository_index(&repo_index, repo); +} + +void test_merge_workdir_simple__cleanup(void) +{ + git_index_free(repo_index); + cl_git_sandbox_cleanup(); +} + +static git_merge_result *merge_simple_branch(int automerge_flags, int checkout_strategy) +{ + git_oid their_oids[1]; + git_merge_head *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_SIMPLE_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0])); + + opts.merge_tree_opts.automerge_flags = automerge_flags; + opts.checkout_opts.checkout_strategy = checkout_strategy; + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); + + git_merge_head_free(their_heads[0]); + + return result; +} + +static void set_core_autocrlf_to(git_repository *repo, bool value) +{ + git_config *cfg; + + cl_git_pass(git_repository_config(&cfg, repo)); + cl_git_pass(git_config_set_bool(cfg, "core.autocrlf", value)); + + git_config_free(cfg); +} + +void test_merge_workdir_simple__automerge(void) +{ + git_index *index; + const git_index_entry *entry; + git_merge_result *result; + git_buf automergeable_buf = GIT_BUF_INIT; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + + { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, + { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, + + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY + }; + + + set_core_autocrlf_to(repo, false); + + cl_assert(result = merge_simple_branch(0, 0)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_git_pass(git_futils_readbuffer(&automergeable_buf, + TEST_REPO_PATH "/automergeable.txt")); + cl_assert(strcmp(automergeable_buf.ptr, AUTOMERGEABLE_MERGED_FILE) == 0); + git_buf_free(&automergeable_buf); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); + cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); + + git_merge_result_free(result); + + git_repository_index(&index, repo); + + cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL); + cl_assert(entry->file_size == strlen(AUTOMERGEABLE_MERGED_FILE)); + + git_index_free(index); +} + +void test_merge_workdir_simple__automerge_crlf(void) +{ +#ifdef GIT_WIN32 + git_index *index; + const git_index_entry *entry; + + git_merge_result *result; + git_buf automergeable_buf = GIT_BUF_INIT; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + + { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, + { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, + + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY + }; + + set_core_autocrlf_to(repo, true); + + cl_assert(result = merge_simple_branch(0, 0)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_git_pass(git_futils_readbuffer(&automergeable_buf, + TEST_REPO_PATH "/automergeable.txt")); + cl_assert(strcmp(automergeable_buf.ptr, AUTOMERGEABLE_MERGED_FILE_CRLF) == 0); + git_buf_free(&automergeable_buf); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); + cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); + + git_merge_result_free(result); + + git_repository_index(&index, repo); + + cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL); + cl_assert(entry->file_size == strlen(AUTOMERGEABLE_MERGED_FILE_CRLF)); + + git_index_free(index); +#endif /* GIT_WIN32 */ +} + +void test_merge_workdir_simple__diff3(void) +{ + git_merge_result *result; + git_buf conflicting_buf = GIT_BUF_INIT; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + + { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, + { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, + + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY + }; + + cl_assert(result = merge_simple_branch(0, 0)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_git_pass(git_futils_readbuffer(&conflicting_buf, + TEST_REPO_PATH "/conflicting.txt")); + cl_assert(strcmp(conflicting_buf.ptr, CONFLICTING_DIFF3_FILE) == 0); + git_buf_free(&conflicting_buf); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); + cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); + + git_merge_result_free(result); +} + +void test_merge_workdir_simple__checkout_ours(void) +{ + git_merge_result *result; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + + { 0100644, "d427e0b2e138501a3d15cc376077a3631e15bd46", 1, "conflicting.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, + { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 3, "conflicting.txt" }, + + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY + }; + + cl_assert(result = merge_simple_branch(0, GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); + cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); + + cl_assert(git_path_exists(TEST_REPO_PATH "/conflicting.txt")); + + git_merge_result_free(result); +} + +void test_merge_workdir_simple__favor_ours(void) +{ + git_merge_result *result; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + CONFLICTING_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY, + }; + + cl_assert(result = merge_simple_branch(GIT_MERGE_AUTOMERGE_FAVOR_OURS, 0)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 6)); + cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4)); + + git_merge_result_free(result); +} + +void test_merge_workdir_simple__favor_theirs(void) +{ + git_merge_result *result; + + struct merge_index_entry merge_index_entries[] = { + ADDED_IN_MASTER_INDEX_ENTRY, + AUTOMERGEABLE_INDEX_ENTRY, + CHANGED_IN_BRANCH_INDEX_ENTRY, + CHANGED_IN_MASTER_INDEX_ENTRY, + { 0100644, "2bd0a343aeef7a2cf0d158478966a6e587ff3863", 0, "conflicting.txt" }, + UNCHANGED_INDEX_ENTRY, + }; + + struct merge_reuc_entry merge_reuc_entries[] = { + AUTOMERGEABLE_REUC_ENTRY, + CONFLICTING_REUC_ENTRY, + REMOVED_IN_BRANCH_REUC_ENTRY, + REMOVED_IN_MASTER_REUC_ENTRY, + }; + + cl_assert(result = merge_simple_branch(GIT_MERGE_AUTOMERGE_FAVOR_THEIRS, 0)); + cl_assert(!git_merge_result_is_fastforward(result)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 6)); + cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4)); + + git_merge_result_free(result); +} + +void test_merge_workdir_simple__directory_file(void) +{ + git_reference *head; + git_oid their_oids[1], head_commit_id; + git_merge_head *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + git_commit *head_commit; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "49130a28ef567af9a6a6104c38773fedfa5f9742", 2, "dir-10" }, + { 0100644, "6c06dcd163587c2cc18be44857e0b71116382aeb", 3, "dir-10" }, + { 0100644, "43aafd43bea779ec74317dc361f45ae3f532a505", 0, "dir-6" }, + { 0100644, "a031a28ae70e33a641ce4b8a8f6317f1ab79dee4", 3, "dir-7" }, + { 0100644, "5012fd565b1393bdfda1805d4ec38ce6619e1fd1", 1, "dir-7/file.txt" }, + { 0100644, "a5563304ddf6caba25cb50323a2ea6f7dbfcadca", 2, "dir-7/file.txt" }, + { 0100644, "e9ad6ec3e38364a3d07feda7c4197d4d845c53b5", 0, "dir-8" }, + { 0100644, "3ef4d30382ca33fdeba9fda895a99e0891ba37aa", 2, "dir-9" }, + { 0100644, "fc4c636d6515e9e261f9260dbcf3cc6eca97ea08", 1, "dir-9/file.txt" }, + { 0100644, "76ab0e2868197ec158ddd6c78d8a0d2fd73d38f9", 3, "dir-9/file.txt" }, + { 0100644, "5c2411f8075f48a6b2fdb85ebc0d371747c4df15", 0, "file-1/new" }, + { 0100644, "a39a620dae5bc8b4e771cd4d251b7d080401a21e", 1, "file-2" }, + { 0100644, "d963979c237d08b6ba39062ee7bf64c7d34a27f8", 2, "file-2" }, + { 0100644, "5c341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d", 0, "file-2/new" }, + { 0100644, "9efe7723802d4305142eee177e018fee1572c4f4", 0, "file-3/new" }, + { 0100644, "bacac9b3493509aa15e1730e1545fc0919d1dae0", 1, "file-4" }, + { 0100644, "7663fce0130db092936b137cabd693ec234eb060", 3, "file-4" }, + { 0100644, "e49f917b448d1340b31d76e54ba388268fd4c922", 0, "file-4/new" }, + { 0100644, "cab2cf23998b40f1af2d9d9a756dc9e285a8df4b", 2, "file-5/new" }, + { 0100644, "f5504f36e6f4eb797a56fc5bac6c6c7f32969bf2", 3, "file-5/new" }, + }; + + cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_DIR OURS_DIRECTORY_FILE, 1)); + cl_git_pass(git_reference_name_to_id(&head_commit_id, repo, GIT_HEAD_FILE)); + cl_git_pass(git_commit_lookup(&head_commit, repo, &head_commit_id)); + cl_git_pass(git_reset(repo, (git_object *)head_commit, GIT_RESET_HARD)); + + cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_DIRECTORY_FILE)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0])); + + opts.merge_tree_opts.automerge_flags = 0; + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 20)); + + git_reference_free(head); + git_commit_free(head_commit); + git_merge_head_free(their_heads[0]); + git_merge_result_free(result); +} + +void test_merge_workdir_simple__unrelated(void) +{ + git_oid their_oids[1]; + git_merge_head *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, + { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" }, + { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, + { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" }, + { 0100644, "ef58fdd8086c243bdc81f99e379acacfd21d32d6", 0, "new-in-unrelated1.txt" }, + { 0100644, "948ba6e701c1edab0c2d394fb7c5538334129793", 0, "new-in-unrelated2.txt" }, + { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, + { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, + }; + + cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_PARENT)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0])); + + opts.merge_tree_opts.automerge_flags = 0; + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 9)); + + git_merge_head_free(their_heads[0]); + git_merge_result_free(result); +} + +void test_merge_workdir_simple__unrelated_with_conflicts(void) +{ + git_oid their_oids[1]; + git_merge_head *their_heads[1]; + git_merge_result *result; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, + { 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 2, "automergeable.txt" }, + { 0100644, "d07ec190c306ec690bac349e87d01c4358e49bb2", 3, "automergeable.txt" }, + { 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" }, + { 0100644, "11deab00b2d3a6f5a3073988ac050c2d7b6655e2", 0, "changed-in-master.txt" }, + { 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 2, "conflicting.txt" }, + { 0100644, "4b253da36a0ae8bfce63aeabd8c5b58429925594", 3, "conflicting.txt" }, + { 0100644, "ef58fdd8086c243bdc81f99e379acacfd21d32d6", 0, "new-in-unrelated1.txt" }, + { 0100644, "948ba6e701c1edab0c2d394fb7c5538334129793", 0, "new-in-unrelated2.txt" }, + { 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" }, + { 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" }, + }; + + cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_OID)); + cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &their_oids[0])); + + opts.merge_tree_opts.automerge_flags = 0; + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); + + cl_assert(merge_test_index(repo_index, merge_index_entries, 11)); + + git_merge_head_free(their_heads[0]); + git_merge_result_free(result); +} + diff --git a/tests/merge/workdir/trivial.c b/tests/merge/workdir/trivial.c new file mode 100644 index 000000000..9f9566243 --- /dev/null +++ b/tests/merge/workdir/trivial.c @@ -0,0 +1,341 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/merge.h" +#include "git2/sys/index.h" +#include "merge.h" +#include "../merge_helpers.h" +#include "refs.h" +#include "fileops.h" + +static git_repository *repo; +static git_index *repo_index; + +#define TEST_REPO_PATH "merge-resolve" +#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index" + + +// Fixture setup and teardown +void test_merge_workdir_trivial__initialize(void) +{ + repo = cl_git_sandbox_init(TEST_REPO_PATH); + git_repository_index(&repo_index, repo); +} + +void test_merge_workdir_trivial__cleanup(void) +{ + git_index_free(repo_index); + cl_git_sandbox_cleanup(); +} + + +static int merge_trivial(const char *ours, const char *theirs, bool automerge) +{ + git_buf branch_buf = GIT_BUF_INIT; + git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; + git_reference *our_ref, *their_ref; + git_merge_head *their_heads[1]; + git_merge_opts opts = GIT_MERGE_OPTS_INIT; + git_merge_result *result; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; + + opts.merge_tree_opts.automerge_flags |= automerge ? 0 : GIT_MERGE_AUTOMERGE_NONE; + + git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours); + cl_git_pass(git_reference_symbolic_create(&our_ref, repo, "HEAD", branch_buf.ptr, 1)); + + cl_git_pass(git_checkout_head(repo, &checkout_opts)); + + git_buf_clear(&branch_buf); + git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs); + cl_git_pass(git_reference_lookup(&their_ref, repo, branch_buf.ptr)); + cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref)); + + cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); + + git_buf_free(&branch_buf); + git_reference_free(our_ref); + git_reference_free(their_ref); + git_merge_head_free(their_heads[0]); + git_merge_result_free(result); + + return 0; +} + +static size_t merge_trivial_conflict_entrycount(void) +{ + const git_index_entry *entry; + size_t count = 0; + size_t i; + + for (i = 0; i < git_index_entrycount(repo_index); i++) { + cl_assert(entry = git_index_get_byindex(repo_index, i)); + + if (git_index_entry_stage(entry) > 0) + count++; + } + + return count; +} + +/* 2ALT: ancest:(empty)+, head:*empty*, remote:remote = result:remote */ +void test_merge_workdir_trivial__2alt(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-2alt", "trivial-2alt-branch", 0)); + + cl_assert(entry = git_index_get_bypath(repo_index, "new-in-branch.txt", 0)); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 3ALT: ancest:(empty)+, head:head, remote:*empty* = result:head */ +void test_merge_workdir_trivial__3alt(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-3alt", "trivial-3alt-branch", 0)); + + cl_assert(entry = git_index_get_bypath(repo_index, "new-in-3alt.txt", 0)); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 4: ancest:(empty)^, head:head, remote:remote = result:no merge */ +void test_merge_workdir_trivial__4(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-4", "trivial-4-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "new-and-different.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "new-and-different.txt", 2)); + cl_assert(entry = git_index_get_bypath(repo_index, "new-and-different.txt", 3)); +} + +/* 5ALT: ancest:*, head:head, remote:head = result:head */ +void test_merge_workdir_trivial__5alt_1(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-5alt-1", "trivial-5alt-1-branch", 0)); + + cl_assert(entry = git_index_get_bypath(repo_index, "new-and-same.txt", 0)); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 5ALT: ancest:*, head:head, remote:head = result:head */ +void test_merge_workdir_trivial__5alt_2(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-5alt-2", "trivial-5alt-2-branch", 0)); + + cl_assert(entry = git_index_get_bypath(repo_index, "modified-to-same.txt", 0)); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */ +void test_merge_workdir_trivial__6(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-6", "trivial-6-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 1); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 1)); +} + +/* 6: ancest:ancest+, head:(empty), remote:(empty) = result:no merge */ +void test_merge_workdir_trivial__6_automerge(void) +{ + const git_index_entry *entry; + const git_index_reuc_entry *reuc; + + cl_git_pass(merge_trivial("trivial-6", "trivial-6-branch", 1)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-both.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 1); + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "removed-in-both.txt")); + + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */ +void test_merge_workdir_trivial__8(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-8", "trivial-8-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 3)); +} + +/* 8: ancest:ancest^, head:(empty), remote:ancest = result:no merge */ +void test_merge_workdir_trivial__8_automerge(void) +{ + const git_index_entry *entry; + const git_index_reuc_entry *reuc; + + cl_git_pass(merge_trivial("trivial-8", "trivial-8-branch", 1)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-8.txt", 0)) == NULL); + + cl_assert(git_index_reuc_entrycount(repo_index) == 1); + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "removed-in-8.txt")); + + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */ +void test_merge_workdir_trivial__7(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-7", "trivial-7-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 3)); +} + +/* 7: ancest:ancest+, head:(empty), remote:remote = result:no merge */ +void test_merge_workdir_trivial__7_automerge(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-7", "trivial-7-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-7.txt", 3)); +} + +/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */ +void test_merge_workdir_trivial__10(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-10", "trivial-10-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 2)); +} + +/* 10: ancest:ancest^, head:ancest, remote:(empty) = result:no merge */ +void test_merge_workdir_trivial__10_automerge(void) +{ + const git_index_entry *entry; + const git_index_reuc_entry *reuc; + + cl_git_pass(merge_trivial("trivial-10", "trivial-10-branch", 1)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-10-branch.txt", 0)) == NULL); + + cl_assert(git_index_reuc_entrycount(repo_index) == 1); + cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "removed-in-10-branch.txt")); + + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */ +void test_merge_workdir_trivial__9(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-9", "trivial-9-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 2)); +} + +/* 9: ancest:ancest+, head:head, remote:(empty) = result:no merge */ +void test_merge_workdir_trivial__9_automerge(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-9", "trivial-9-branch", 1)); + + cl_assert((entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 2); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "removed-in-9-branch.txt", 2)); +} + +/* 13: ancest:ancest+, head:head, remote:ancest = result:head */ +void test_merge_workdir_trivial__13(void) +{ + const git_index_entry *entry; + git_oid expected_oid; + + cl_git_pass(merge_trivial("trivial-13", "trivial-13-branch", 0)); + + cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-13.txt", 0)); + cl_git_pass(git_oid_fromstr(&expected_oid, "1cff9ec6a47a537380dedfdd17c9e76d74259a2b")); + cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0); + + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 14: ancest:ancest+, head:ancest, remote:remote = result:remote */ +void test_merge_workdir_trivial__14(void) +{ + const git_index_entry *entry; + git_oid expected_oid; + + cl_git_pass(merge_trivial("trivial-14", "trivial-14-branch", 0)); + + cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-14-branch.txt", 0)); + cl_git_pass(git_oid_fromstr(&expected_oid, "26153a3ff3649b6c2bb652d3f06878c6e0a172f9")); + cl_assert(git_oid_cmp(&entry->oid, &expected_oid) == 0); + + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + cl_assert(merge_trivial_conflict_entrycount() == 0); +} + +/* 11: ancest:ancest+, head:head, remote:remote = result:no merge */ +void test_merge_workdir_trivial__11(void) +{ + const git_index_entry *entry; + + cl_git_pass(merge_trivial("trivial-11", "trivial-11-branch", 0)); + + cl_assert((entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 0)) == NULL); + cl_assert(git_index_reuc_entrycount(repo_index) == 0); + + cl_assert(merge_trivial_conflict_entrycount() == 3); + cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 1)); + cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 2)); + cl_assert(entry = git_index_get_bypath(repo_index, "modified-in-both.txt", 3)); +} diff --git a/tests/network/cred.c b/tests/network/cred.c new file mode 100644 index 000000000..6994cc0c3 --- /dev/null +++ b/tests/network/cred.c @@ -0,0 +1,50 @@ +#include "clar_libgit2.h" + +#include "git2/cred_helpers.h" + +void test_network_cred__stock_userpass_validates_args(void) +{ + git_cred_userpass_payload payload = {0}; + + cl_git_fail(git_cred_userpass(NULL, NULL, NULL, 0, NULL)); + + payload.username = "user"; + cl_git_fail(git_cred_userpass(NULL, NULL, NULL, 0, &payload)); + + payload.username = NULL; + payload.username = "pass"; + cl_git_fail(git_cred_userpass(NULL, NULL, NULL, 0, &payload)); +} + +void test_network_cred__stock_userpass_validates_that_method_is_allowed(void) +{ + git_cred *cred; + git_cred_userpass_payload payload = {"user", "pass"}; + + cl_git_fail(git_cred_userpass(&cred, NULL, NULL, 0, &payload)); + cl_git_pass(git_cred_userpass(&cred, NULL, NULL, GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload)); + cred->free(cred); +} + +void test_network_cred__stock_userpass_properly_handles_username_in_url(void) +{ + git_cred *cred; + git_cred_userpass_plaintext *plain; + git_cred_userpass_payload payload = {"alice", "password"}; + + cl_git_pass(git_cred_userpass(&cred, NULL, NULL, GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload)); + plain = (git_cred_userpass_plaintext*)cred; + cl_assert_equal_s(plain->username, "alice"); + cred->free(cred); + + cl_git_pass(git_cred_userpass(&cred, NULL, "bob", GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload)); + plain = (git_cred_userpass_plaintext*)cred; + cl_assert_equal_s(plain->username, "alice"); + cred->free(cred); + + payload.username = NULL; + cl_git_pass(git_cred_userpass(&cred, NULL, "bob", GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload)); + plain = (git_cred_userpass_plaintext*)cred; + cl_assert_equal_s(plain->username, "bob"); + cred->free(cred); +} diff --git a/tests/network/fetchlocal.c b/tests/network/fetchlocal.c new file mode 100644 index 000000000..28c7115bf --- /dev/null +++ b/tests/network/fetchlocal.c @@ -0,0 +1,88 @@ +#include "clar_libgit2.h" + +#include "buffer.h" +#include "path.h" +#include "remote.h" + +static int transfer_cb(const git_transfer_progress *stats, void *payload) +{ + int *callcount = (int*)payload; + GIT_UNUSED(stats); + (*callcount)++; + return 0; +} + +static void cleanup_local_repo(void *path) +{ + cl_fixture_cleanup((char *)path); +} + +void test_network_fetchlocal__complete(void) +{ + git_repository *repo; + git_remote *origin; + int callcount = 0; + git_strarray refnames = {0}; + + const char *url = cl_git_fixture_url("testrepo.git"); + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + callbacks.transfer_progress = transfer_cb; + callbacks.payload = &callcount; + + cl_set_cleanup(&cleanup_local_repo, "foo"); + cl_git_pass(git_repository_init(&repo, "foo", true)); + + cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); + git_remote_set_callbacks(origin, &callbacks); + cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_download(origin)); + cl_git_pass(git_remote_update_tips(origin)); + + cl_git_pass(git_reference_list(&refnames, repo)); + cl_assert_equal_i(19, (int)refnames.count); + cl_assert(callcount > 0); + + git_strarray_free(&refnames); + git_remote_free(origin); + git_repository_free(repo); +} + +static void cleanup_sandbox(void *unused) +{ + GIT_UNUSED(unused); + cl_git_sandbox_cleanup(); +} + +void test_network_fetchlocal__partial(void) +{ + git_repository *repo = cl_git_sandbox_init("partial-testrepo"); + git_remote *origin; + int callcount = 0; + git_strarray refnames = {0}; + const char *url; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + callbacks.transfer_progress = transfer_cb; + callbacks.payload = &callcount; + + cl_set_cleanup(&cleanup_sandbox, NULL); + cl_git_pass(git_reference_list(&refnames, repo)); + cl_assert_equal_i(1, (int)refnames.count); + + url = cl_git_fixture_url("testrepo.git"); + cl_git_pass(git_remote_create(&origin, repo, GIT_REMOTE_ORIGIN, url)); + git_remote_set_callbacks(origin, &callbacks); + cl_git_pass(git_remote_connect(origin, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_download(origin)); + cl_git_pass(git_remote_update_tips(origin)); + + git_strarray_free(&refnames); + + cl_git_pass(git_reference_list(&refnames, repo)); + cl_assert_equal_i(20, (int)refnames.count); /* 18 remote + 1 local */ + cl_assert(callcount > 0); + + git_strarray_free(&refnames); + git_remote_free(origin); +} diff --git a/tests/network/refspecs.c b/tests/network/refspecs.c new file mode 100644 index 000000000..676a1fa99 --- /dev/null +++ b/tests/network/refspecs.c @@ -0,0 +1,87 @@ +#include "clar_libgit2.h" +#include "refspec.h" +#include "remote.h" + +static void assert_refspec(unsigned int direction, const char *input, bool is_expected_to_be_valid) +{ + git_refspec refspec; + int error; + + error = git_refspec__parse(&refspec, input, direction == GIT_DIRECTION_FETCH); + git_refspec__free(&refspec); + + if (is_expected_to_be_valid) + cl_assert_equal_i(0, error); + else + cl_assert_equal_i(GIT_ERROR, error); +} + +void test_network_refspecs__parsing(void) +{ + // Ported from https://github.com/git/git/blob/abd2bde78bd994166900290434a2048e660dabed/t/t5511-refspec.sh + + assert_refspec(GIT_DIRECTION_PUSH, "", false); + assert_refspec(GIT_DIRECTION_PUSH, ":", true); + assert_refspec(GIT_DIRECTION_PUSH, "::", false); + assert_refspec(GIT_DIRECTION_PUSH, "+:", true); + + assert_refspec(GIT_DIRECTION_FETCH, "", true); + assert_refspec(GIT_DIRECTION_PUSH, ":", true); + assert_refspec(GIT_DIRECTION_FETCH, "::", false); + + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*:refs/remotes/frotz/*", true); + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*:refs/remotes/frotz", false); + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads:refs/remotes/frotz/*", false); + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/master:refs/remotes/frotz/xyzzy", true); + + /* + * These have invalid LHS, but we do not have a formal "valid sha-1 + * expression syntax checker" so they are not checked with the current + * code. They will be caught downstream anyway, but we may want to + * have tighter check later... + */ + //assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/master::refs/remotes/frotz/xyzzy", false); + //assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/maste :refs/remotes/frotz/xyzzy", false); + + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*:refs/remotes/frotz/*", true); + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*:refs/remotes/frotz", false); + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads:refs/remotes/frotz/*", false); + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/master:refs/remotes/frotz/xyzzy", true); + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/master::refs/remotes/frotz/xyzzy", false); + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/maste :refs/remotes/frotz/xyzzy", false); + + assert_refspec(GIT_DIRECTION_PUSH, "master~1:refs/remotes/frotz/backup", true); + assert_refspec(GIT_DIRECTION_FETCH, "master~1:refs/remotes/frotz/backup", false); + assert_refspec(GIT_DIRECTION_PUSH, "HEAD~4:refs/remotes/frotz/new", true); + assert_refspec(GIT_DIRECTION_FETCH, "HEAD~4:refs/remotes/frotz/new", false); + + assert_refspec(GIT_DIRECTION_PUSH, "HEAD", true); + assert_refspec(GIT_DIRECTION_FETCH, "HEAD", true); + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/ nitfol", false); + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/ nitfol", false); + + assert_refspec(GIT_DIRECTION_PUSH, "HEAD:", false); + assert_refspec(GIT_DIRECTION_FETCH, "HEAD:", true); + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/ nitfol:", false); + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/ nitfol:", false); + + assert_refspec(GIT_DIRECTION_PUSH, ":refs/remotes/frotz/deleteme", true); + assert_refspec(GIT_DIRECTION_FETCH, ":refs/remotes/frotz/HEAD-to-me", true); + assert_refspec(GIT_DIRECTION_PUSH, ":refs/remotes/frotz/delete me", false); + assert_refspec(GIT_DIRECTION_FETCH, ":refs/remotes/frotz/HEAD to me", false); + + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/for-linus:refs/remotes/mine/*-blah", false); + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/for-linus:refs/remotes/mine/*-blah", false); + + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads*/for-linus:refs/remotes/mine/*", false); + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads*/for-linus:refs/remotes/mine/*", false); + + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/*/for-linus:refs/remotes/mine/*", false); + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/*/for-linus:refs/remotes/mine/*", false); + + assert_refspec(GIT_DIRECTION_FETCH, "refs/heads/*/for-linus:refs/remotes/mine/*", true); + assert_refspec(GIT_DIRECTION_PUSH, "refs/heads/*/for-linus:refs/remotes/mine/*", true); + + assert_refspec(GIT_DIRECTION_FETCH, "master", true); + assert_refspec(GIT_DIRECTION_PUSH, "master", true); +} diff --git a/tests/network/remote/createthenload.c b/tests/network/remote/createthenload.c new file mode 100644 index 000000000..ac6cfccd3 --- /dev/null +++ b/tests/network/remote/createthenload.c @@ -0,0 +1,37 @@ +#include "clar_libgit2.h" + +static git_remote *_remote; +static git_repository *_repo; +static git_config *_config; +static char url[] = "http://github.com/libgit2/libgit2.git"; + +void test_network_remote_createthenload__initialize(void) +{ + cl_fixture_sandbox("testrepo.git"); + + cl_git_pass(git_repository_open(&_repo, "testrepo.git")); + + cl_git_pass(git_repository_config(&_config, _repo)); + cl_git_pass(git_config_set_string(_config, "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*")); + cl_git_pass(git_config_set_string(_config, "remote.origin.url", url)); + git_config_free(_config); + + cl_git_pass(git_remote_load(&_remote, _repo, "origin")); +} + +void test_network_remote_createthenload__cleanup(void) +{ + git_remote_free(_remote); + _remote = NULL; + + git_repository_free(_repo); + _repo = NULL; + + cl_fixture_cleanup("testrepo.git"); +} + +void test_network_remote_createthenload__parsing(void) +{ + cl_assert_equal_s(git_remote_name(_remote), "origin"); + cl_assert_equal_s(git_remote_url(_remote), url); +} diff --git a/tests/network/remote/isvalidname.c b/tests/network/remote/isvalidname.c new file mode 100644 index 000000000..c26fbd0a5 --- /dev/null +++ b/tests/network/remote/isvalidname.c @@ -0,0 +1,17 @@ +#include "clar_libgit2.h" + +void test_network_remote_isvalidname__can_detect_invalid_formats(void) +{ + cl_assert_equal_i(false, git_remote_is_valid_name("/")); + cl_assert_equal_i(false, git_remote_is_valid_name("//")); + cl_assert_equal_i(false, git_remote_is_valid_name(".lock")); + cl_assert_equal_i(false, git_remote_is_valid_name("a.lock")); + cl_assert_equal_i(false, git_remote_is_valid_name("/no/leading/slash")); + cl_assert_equal_i(false, git_remote_is_valid_name("no/trailing/slash/")); +} + +void test_network_remote_isvalidname__wont_hopefully_choke_on_valid_formats(void) +{ + cl_assert_equal_i(true, git_remote_is_valid_name("webmatrix")); + cl_assert_equal_i(true, git_remote_is_valid_name("yishaigalatzer/rules")); +} diff --git a/tests/network/remote/local.c b/tests/network/remote/local.c new file mode 100644 index 000000000..309142925 --- /dev/null +++ b/tests/network/remote/local.c @@ -0,0 +1,234 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "path.h" +#include "posix.h" + +static git_repository *repo; +static git_buf file_path_buf = GIT_BUF_INIT; +static git_remote *remote; + +void test_network_remote_local__initialize(void) +{ + cl_git_pass(git_repository_init(&repo, "remotelocal/", 0)); + cl_assert(repo != NULL); +} + +void test_network_remote_local__cleanup(void) +{ + git_buf_free(&file_path_buf); + + git_remote_free(remote); + remote = NULL; + + git_repository_free(repo); + repo = NULL; + + cl_fixture_cleanup("remotelocal"); +} + +static void connect_to_local_repository(const char *local_repository) +{ + git_buf_sets(&file_path_buf, cl_git_path_url(local_repository)); + + cl_git_pass(git_remote_create_inmemory(&remote, repo, NULL, git_buf_cstr(&file_path_buf))); + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); +} + +void test_network_remote_local__connected(void) +{ + connect_to_local_repository(cl_fixture("testrepo.git")); + cl_assert(git_remote_connected(remote)); + + git_remote_disconnect(remote); + cl_assert(!git_remote_connected(remote)); +} + +void test_network_remote_local__retrieve_advertised_references(void) +{ + const git_remote_head **refs; + size_t refs_len; + + connect_to_local_repository(cl_fixture("testrepo.git")); + + cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); + + cl_assert_equal_i(refs_len, 28); +} + +void test_network_remote_local__retrieve_advertised_references_after_disconnect(void) +{ + const git_remote_head **refs; + size_t refs_len; + + connect_to_local_repository(cl_fixture("testrepo.git")); + git_remote_disconnect(remote); + + cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); + + cl_assert_equal_i(refs_len, 28); +} + +void test_network_remote_local__retrieve_advertised_references_from_spaced_repository(void) +{ + const git_remote_head **refs; + size_t refs_len; + + cl_fixture_sandbox("testrepo.git"); + cl_git_pass(p_rename("testrepo.git", "spaced testrepo.git")); + + connect_to_local_repository("spaced testrepo.git"); + + cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); + + cl_assert_equal_i(refs_len, 28); + + git_remote_free(remote); /* Disconnect from the "spaced repo" before the cleanup */ + remote = NULL; + + cl_fixture_cleanup("spaced testrepo.git"); +} + +void test_network_remote_local__nested_tags_are_completely_peeled(void) +{ + const git_remote_head **refs; + size_t refs_len, i; + + connect_to_local_repository(cl_fixture("testrepo.git")); + + cl_git_pass(git_remote_ls(&refs, &refs_len, remote)); + + for (i = 0; i < refs_len; i++) { + if (!strcmp(refs[i]->name, "refs/tags/test^{}")) + cl_git_pass(git_oid_streq(&refs[i]->oid, "e90810b8df3e80c413d903f631643c716887138d")); + } +} + +void test_network_remote_local__shorthand_fetch_refspec0(void) +{ + const char *refspec = "master:remotes/sloppy/master"; + const char *refspec2 = "master:boh/sloppy/master"; + + git_reference *ref; + + connect_to_local_repository(cl_fixture("testrepo.git")); + cl_git_pass(git_remote_add_fetch(remote, refspec)); + cl_git_pass(git_remote_add_fetch(remote, refspec2)); + + cl_git_pass(git_remote_download(remote)); + cl_git_pass(git_remote_update_tips(remote)); + + cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/sloppy/master")); + git_reference_free(ref); + + cl_git_pass(git_reference_lookup(&ref, repo, "refs/heads/boh/sloppy/master")); + git_reference_free(ref); +} + +void test_network_remote_local__shorthand_fetch_refspec1(void) +{ + const char *refspec = "master"; + const char *refspec2 = "hard_tag"; + + git_reference *ref; + + connect_to_local_repository(cl_fixture("testrepo.git")); + git_remote_clear_refspecs(remote); + cl_git_pass(git_remote_add_fetch(remote, refspec)); + cl_git_pass(git_remote_add_fetch(remote, refspec2)); + + cl_git_pass(git_remote_download(remote)); + cl_git_pass(git_remote_update_tips(remote)); + + cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/master")); + + cl_git_fail(git_reference_lookup(&ref, repo, "refs/tags/hard_tag")); +} + +void test_network_remote_local__tagopt(void) +{ + git_reference *ref; + + connect_to_local_repository(cl_fixture("testrepo.git")); + git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL); + + cl_git_pass(git_remote_download(remote)); + cl_git_pass(git_remote_update_tips(remote)); + + + cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/master")); + + cl_git_pass(git_reference_lookup(&ref, repo, "refs/tags/hard_tag")); + git_reference_free(ref); +} + +void test_network_remote_local__push_to_bare_remote(void) +{ + /* Should be able to push to a bare remote */ + git_remote *localremote; + git_push *push; + + /* Get some commits */ + connect_to_local_repository(cl_fixture("testrepo.git")); + cl_git_pass(git_remote_add_fetch(remote, "master:master")); + cl_git_pass(git_remote_download(remote)); + cl_git_pass(git_remote_update_tips(remote)); + git_remote_disconnect(remote); + + /* Set up an empty bare repo to push into */ + { + git_repository *localbarerepo; + cl_git_pass(git_repository_init(&localbarerepo, "./localbare.git", 1)); + git_repository_free(localbarerepo); + } + + /* Connect to the bare repo */ + cl_git_pass(git_remote_create_inmemory(&localremote, repo, NULL, "./localbare.git")); + cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH)); + + /* Try to push */ + cl_git_pass(git_push_new(&push, localremote)); + cl_git_pass(git_push_add_refspec(push, "refs/heads/master:")); + cl_git_pass(git_push_finish(push)); + cl_assert(git_push_unpack_ok(push)); + + /* Clean up */ + git_push_free(push); + git_remote_free(localremote); + cl_fixture_cleanup("localbare.git"); +} + +void test_network_remote_local__push_to_non_bare_remote(void) +{ + /* Shouldn't be able to push to a non-bare remote */ + git_remote *localremote; + git_push *push; + + /* Get some commits */ + connect_to_local_repository(cl_fixture("testrepo.git")); + cl_git_pass(git_remote_add_fetch(remote, "master:master")); + cl_git_pass(git_remote_download(remote)); + cl_git_pass(git_remote_update_tips(remote)); + git_remote_disconnect(remote); + + /* Set up an empty non-bare repo to push into */ + { + git_repository *remoterepo = NULL; + cl_git_pass(git_repository_init(&remoterepo, "localnonbare", 0)); + git_repository_free(remoterepo); + } + + /* Connect to the bare repo */ + cl_git_pass(git_remote_create_inmemory(&localremote, repo, NULL, "./localnonbare")); + cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH)); + + /* Try to push */ + cl_git_pass(git_push_new(&push, localremote)); + cl_git_pass(git_push_add_refspec(push, "refs/heads/master:")); + cl_git_fail_with(git_push_finish(push), GIT_EBAREREPO); + cl_assert_equal_i(0, git_push_unpack_ok(push)); + + /* Clean up */ + git_push_free(push); + git_remote_free(localremote); + cl_fixture_cleanup("localbare.git"); +} diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c new file mode 100644 index 000000000..954ded82c --- /dev/null +++ b/tests/network/remote/remotes.c @@ -0,0 +1,510 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "refspec.h" +#include "remote.h" + +static git_remote *_remote; +static git_repository *_repo; +static const git_refspec *_refspec; + +void test_network_remote_remotes__initialize(void) +{ + _repo = cl_git_sandbox_init("testrepo.git"); + + cl_git_pass(git_remote_load(&_remote, _repo, "test")); + + _refspec = git_remote_get_refspec(_remote, 0); + cl_assert(_refspec != NULL); +} + +void test_network_remote_remotes__cleanup(void) +{ + git_remote_free(_remote); + _remote = NULL; + + cl_git_sandbox_cleanup(); +} + +void test_network_remote_remotes__parsing(void) +{ + git_remote *_remote2 = NULL; + + cl_assert_equal_s(git_remote_name(_remote), "test"); + cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); + cl_assert(git_remote_pushurl(_remote) == NULL); + + cl_assert_equal_s(git_remote__urlfordirection(_remote, GIT_DIRECTION_FETCH), + "git://github.com/libgit2/libgit2"); + cl_assert_equal_s(git_remote__urlfordirection(_remote, GIT_DIRECTION_PUSH), + "git://github.com/libgit2/libgit2"); + + cl_git_pass(git_remote_load(&_remote2, _repo, "test_with_pushurl")); + cl_assert_equal_s(git_remote_name(_remote2), "test_with_pushurl"); + cl_assert_equal_s(git_remote_url(_remote2), "git://github.com/libgit2/fetchlibgit2"); + cl_assert_equal_s(git_remote_pushurl(_remote2), "git://github.com/libgit2/pushlibgit2"); + + cl_assert_equal_s(git_remote__urlfordirection(_remote2, GIT_DIRECTION_FETCH), + "git://github.com/libgit2/fetchlibgit2"); + cl_assert_equal_s(git_remote__urlfordirection(_remote2, GIT_DIRECTION_PUSH), + "git://github.com/libgit2/pushlibgit2"); + + git_remote_free(_remote2); +} + +void test_network_remote_remotes__pushurl(void) +{ + cl_git_pass(git_remote_set_pushurl(_remote, "git://github.com/libgit2/notlibgit2")); + cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/notlibgit2"); + + cl_git_pass(git_remote_set_pushurl(_remote, NULL)); + cl_assert(git_remote_pushurl(_remote) == NULL); +} + +void test_network_remote_remotes__error_when_no_push_available(void) +{ + git_remote *r; + git_transport *t; + git_push *p; + + cl_git_pass(git_remote_create_inmemory(&r, _repo, NULL, cl_fixture("testrepo.git"))); + + cl_git_pass(git_transport_local(&t,r,NULL)); + + /* Make sure that push is really not available */ + t->push = NULL; + cl_git_pass(git_remote_set_transport(r, t)); + + cl_git_pass(git_remote_connect(r, GIT_DIRECTION_PUSH)); + cl_git_pass(git_push_new(&p, r)); + cl_git_pass(git_push_add_refspec(p, "refs/heads/master")); + cl_git_fail_with(git_push_finish(p), GIT_ERROR); + + git_push_free(p); + git_remote_free(r); +} + +void test_network_remote_remotes__parsing_ssh_remote(void) +{ + cl_assert( git_remote_valid_url("git@github.com:libgit2/libgit2.git") ); +} + +void test_network_remote_remotes__parsing_local_path_fails_if_path_not_found(void) +{ + cl_assert( !git_remote_valid_url("/home/git/repos/libgit2.git") ); +} + +void test_network_remote_remotes__supported_transport_methods_are_supported(void) +{ + cl_assert( git_remote_supported_url("git://github.com/libgit2/libgit2") ); +} + +void test_network_remote_remotes__unsupported_transport_methods_are_unsupported(void) +{ +#ifndef GIT_SSH + cl_assert( !git_remote_supported_url("git@github.com:libgit2/libgit2.git") ); +#endif +} + +void test_network_remote_remotes__refspec_parsing(void) +{ + cl_assert_equal_s(git_refspec_src(_refspec), "refs/heads/*"); + cl_assert_equal_s(git_refspec_dst(_refspec), "refs/remotes/test/*"); +} + +void test_network_remote_remotes__add_fetchspec(void) +{ + size_t size; + + size = git_remote_refspec_count(_remote); + + cl_git_pass(git_remote_add_fetch(_remote, "refs/*:refs/*")); + + size++; + cl_assert_equal_i((int)size, (int)git_remote_refspec_count(_remote)); + + _refspec = git_remote_get_refspec(_remote, size - 1); + cl_assert_equal_s(git_refspec_src(_refspec), "refs/*"); + cl_assert_equal_s(git_refspec_dst(_refspec), "refs/*"); + cl_assert_equal_s(git_refspec_string(_refspec), "refs/*:refs/*"); + cl_assert_equal_b(_refspec->push, false); +} + +void test_network_remote_remotes__add_pushspec(void) +{ + size_t size; + + size = git_remote_refspec_count(_remote); + + cl_git_pass(git_remote_add_push(_remote, "refs/*:refs/*")); + size++; + cl_assert_equal_i((int)size, (int)git_remote_refspec_count(_remote)); + + _refspec = git_remote_get_refspec(_remote, size - 1); + cl_assert_equal_s(git_refspec_src(_refspec), "refs/*"); + cl_assert_equal_s(git_refspec_dst(_refspec), "refs/*"); + cl_assert_equal_s(git_refspec_string(_refspec), "refs/*:refs/*"); + + cl_assert_equal_b(_refspec->push, true); +} + +void test_network_remote_remotes__save(void) +{ + git_strarray array; + const char *fetch_refspec1 = "refs/heads/ns1/*:refs/remotes/upstream/ns1/*"; + const char *fetch_refspec2 = "refs/heads/ns2/*:refs/remotes/upstream/ns2/*"; + const char *push_refspec1 = "refs/heads/ns1/*:refs/heads/ns1/*"; + const char *push_refspec2 = "refs/heads/ns2/*:refs/heads/ns2/*"; + + git_remote_free(_remote); + _remote = NULL; + + /* Set up the remote and save it to config */ + cl_git_pass(git_remote_create(&_remote, _repo, "upstream", "git://github.com/libgit2/libgit2")); + git_remote_clear_refspecs(_remote); + + cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec1)); + cl_git_pass(git_remote_add_fetch(_remote, fetch_refspec2)); + cl_git_pass(git_remote_add_push(_remote, push_refspec1)); + cl_git_pass(git_remote_add_push(_remote, push_refspec2)); + cl_git_pass(git_remote_set_pushurl(_remote, "git://github.com/libgit2/libgit2_push")); + cl_git_pass(git_remote_save(_remote)); + git_remote_free(_remote); + _remote = NULL; + + /* Load it from config and make sure everything matches */ + cl_git_pass(git_remote_load(&_remote, _repo, "upstream")); + + cl_git_pass(git_remote_get_fetch_refspecs(&array, _remote)); + cl_assert_equal_i(2, (int)array.count); + cl_assert_equal_s(fetch_refspec1, array.strings[0]); + cl_assert_equal_s(fetch_refspec2, array.strings[1]); + git_strarray_free(&array); + + cl_git_pass(git_remote_get_push_refspecs(&array, _remote)); + cl_assert_equal_i(2, (int)array.count); + cl_assert_equal_s(push_refspec1, array.strings[0]); + cl_assert_equal_s(push_refspec2, array.strings[1]); + git_strarray_free(&array); + + cl_assert_equal_s(git_remote_url(_remote), "git://github.com/libgit2/libgit2"); + cl_assert_equal_s(git_remote_pushurl(_remote), "git://github.com/libgit2/libgit2_push"); + + /* remove the pushurl again and see if we can save that too */ + cl_git_pass(git_remote_set_pushurl(_remote, NULL)); + cl_git_pass(git_remote_save(_remote)); + git_remote_free(_remote); + _remote = NULL; + + cl_git_pass(git_remote_load(&_remote, _repo, "upstream")); + cl_assert(git_remote_pushurl(_remote) == NULL); +} + +void test_network_remote_remotes__fnmatch(void) +{ + cl_assert(git_refspec_src_matches(_refspec, "refs/heads/master")); + cl_assert(git_refspec_src_matches(_refspec, "refs/heads/multi/level/branch")); +} + +void test_network_remote_remotes__transform(void) +{ + char ref[1024] = {0}; + + cl_git_pass(git_refspec_transform(ref, sizeof(ref), _refspec, "refs/heads/master")); + cl_assert_equal_s(ref, "refs/remotes/test/master"); +} + +void test_network_remote_remotes__transform_destination_to_source(void) +{ + char ref[1024] = {0}; + + cl_git_pass(git_refspec_rtransform(ref, sizeof(ref), _refspec, "refs/remotes/test/master")); + cl_assert_equal_s(ref, "refs/heads/master"); +} + +void test_network_remote_remotes__transform_r(void) +{ + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_refspec_transform_r(&buf, _refspec, "refs/heads/master")); + cl_assert_equal_s(git_buf_cstr(&buf), "refs/remotes/test/master"); + git_buf_free(&buf); +} + +void test_network_remote_remotes__missing_refspecs(void) +{ + git_config *cfg; + + git_remote_free(_remote); + _remote = NULL; + + cl_git_pass(git_repository_config(&cfg, _repo)); + cl_git_pass(git_config_set_string(cfg, "remote.specless.url", "http://example.com")); + cl_git_pass(git_remote_load(&_remote, _repo, "specless")); + + git_config_free(cfg); +} + +void test_network_remote_remotes__list(void) +{ + git_strarray list; + git_config *cfg; + + cl_git_pass(git_remote_list(&list, _repo)); + cl_assert(list.count == 5); + git_strarray_free(&list); + + cl_git_pass(git_repository_config(&cfg, _repo)); + + /* Create a new remote */ + cl_git_pass(git_config_set_string(cfg, "remote.specless.url", "http://example.com")); + + /* Update a remote (previously without any url/pushurl entry) */ + cl_git_pass(git_config_set_string(cfg, "remote.no-remote-url.pushurl", "http://example.com")); + + cl_git_pass(git_remote_list(&list, _repo)); + cl_assert(list.count == 7); + git_strarray_free(&list); + + git_config_free(cfg); +} + +void test_network_remote_remotes__loading_a_missing_remote_returns_ENOTFOUND(void) +{ + git_remote_free(_remote); + _remote = NULL; + + cl_assert_equal_i(GIT_ENOTFOUND, git_remote_load(&_remote, _repo, "just-left-few-minutes-ago")); +} + +void test_network_remote_remotes__loading_with_an_invalid_name_returns_EINVALIDSPEC(void) +{ + git_remote_free(_remote); + _remote = NULL; + + cl_assert_equal_i(GIT_EINVALIDSPEC, git_remote_load(&_remote, _repo, "Inv@{id")); +} + +/* + * $ git remote add addtest http://github.com/libgit2/libgit2 + * + * $ cat .git/config + * [...] + * [remote "addtest"] + * url = http://github.com/libgit2/libgit2 + * fetch = +refs/heads/\*:refs/remotes/addtest/\* + */ +void test_network_remote_remotes__add(void) +{ + git_remote_free(_remote); + _remote = NULL; + + cl_git_pass(git_remote_create(&_remote, _repo, "addtest", "http://github.com/libgit2/libgit2")); + cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, git_remote_autotag(_remote)); + + git_remote_free(_remote); + _remote = NULL; + + cl_git_pass(git_remote_load(&_remote, _repo, "addtest")); + cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, git_remote_autotag(_remote)); + + _refspec = git_vector_get(&_remote->refspecs, 0); + cl_assert_equal_s("refs/heads/*", git_refspec_src(_refspec)); + cl_assert(git_refspec_force(_refspec) == 1); + cl_assert_equal_s("refs/remotes/addtest/*", git_refspec_dst(_refspec)); + cl_assert_equal_s(git_remote_url(_remote), "http://github.com/libgit2/libgit2"); +} + +void test_network_remote_remotes__cannot_add_a_nameless_remote(void) +{ + git_remote *remote; + + cl_assert_equal_i( + GIT_EINVALIDSPEC, + git_remote_create(&remote, _repo, NULL, "git://github.com/libgit2/libgit2")); +} + +void test_network_remote_remotes__cannot_save_an_inmemory_remote(void) +{ + git_remote *remote; + + cl_git_pass(git_remote_create_inmemory(&remote, _repo, NULL, "git://github.com/libgit2/libgit2")); + + cl_assert_equal_p(NULL, git_remote_name(remote)); + + cl_git_fail(git_remote_save(remote)); + git_remote_free(remote); +} + +void test_network_remote_remotes__cannot_add_a_remote_with_an_invalid_name(void) +{ + git_remote *remote = NULL; + + cl_assert_equal_i( + GIT_EINVALIDSPEC, + git_remote_create(&remote, _repo, "Inv@{id", "git://github.com/libgit2/libgit2")); + cl_assert_equal_p(remote, NULL); + + cl_assert_equal_i( + GIT_EINVALIDSPEC, + git_remote_create(&remote, _repo, "", "git://github.com/libgit2/libgit2")); + cl_assert_equal_p(remote, NULL); +} + +void test_network_remote_remotes__tagopt(void) +{ + const char *opt; + git_config *cfg; + + cl_git_pass(git_repository_config(&cfg, _repo)); + + git_remote_set_autotag(_remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL); + cl_git_pass(git_remote_save(_remote)); + cl_git_pass(git_config_get_string(&opt, cfg, "remote.test.tagopt")); + cl_assert_equal_s("--tags", opt); + + git_remote_set_autotag(_remote, GIT_REMOTE_DOWNLOAD_TAGS_NONE); + cl_git_pass(git_remote_save(_remote)); + cl_git_pass(git_config_get_string(&opt, cfg, "remote.test.tagopt")); + cl_assert_equal_s("--no-tags", opt); + + git_remote_set_autotag(_remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); + cl_git_pass(git_remote_save(_remote)); + cl_assert(git_config_get_string(&opt, cfg, "remote.test.tagopt") == GIT_ENOTFOUND); + + git_config_free(cfg); +} + +void test_network_remote_remotes__can_load_with_an_empty_url(void) +{ + git_remote *remote = NULL; + + cl_git_pass(git_remote_load(&remote, _repo, "empty-remote-url")); + + cl_assert(remote->url == NULL); + cl_assert(remote->pushurl == NULL); + + cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + + cl_assert(giterr_last() != NULL); + cl_assert(giterr_last()->klass == GITERR_INVALID); + + git_remote_free(remote); +} + +void test_network_remote_remotes__can_load_with_only_an_empty_pushurl(void) +{ + git_remote *remote = NULL; + + cl_git_pass(git_remote_load(&remote, _repo, "empty-remote-pushurl")); + + cl_assert(remote->url == NULL); + cl_assert(remote->pushurl == NULL); + + cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + + git_remote_free(remote); +} + +void test_network_remote_remotes__returns_ENOTFOUND_when_neither_url_nor_pushurl(void) +{ + git_remote *remote = NULL; + + cl_git_fail_with( + git_remote_load(&remote, _repo, "no-remote-url"), GIT_ENOTFOUND); +} + +void test_network_remote_remotes__check_structure_version(void) +{ + git_transport transport = GIT_TRANSPORT_INIT; + const git_error *err; + + git_remote_free(_remote); + _remote = NULL; + cl_git_pass(git_remote_create_inmemory(&_remote, _repo, NULL, "test-protocol://localhost")); + + transport.version = 0; + cl_git_fail(git_remote_set_transport(_remote, &transport)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); + + giterr_clear(); + transport.version = 1024; + cl_git_fail(git_remote_set_transport(_remote, &transport)); + err = giterr_last(); + cl_assert_equal_i(GITERR_INVALID, err->klass); +} + +void assert_cannot_create_remote(const char *name, int expected_error) +{ + git_remote *remote = NULL; + + cl_git_fail_with( + git_remote_create(&remote, _repo, name, "git://github.com/libgit2/libgit2"), + expected_error); + + cl_assert_equal_p(remote, NULL); +} + +void test_network_remote_remotes__cannot_create_a_remote_which_name_conflicts_with_an_existing_remote(void) +{ + assert_cannot_create_remote("test", GIT_EEXISTS); +} + +void test_network_remote_remotes__cannot_create_a_remote_which_name_is_invalid(void) +{ + assert_cannot_create_remote("/", GIT_EINVALIDSPEC); + assert_cannot_create_remote("//", GIT_EINVALIDSPEC); + assert_cannot_create_remote(".lock", GIT_EINVALIDSPEC); + assert_cannot_create_remote("a.lock", GIT_EINVALIDSPEC); +} + +void test_network_remote_remote__git_remote_create_with_fetchspec(void) +{ + git_remote *remote; + git_strarray array; + + cl_git_pass(git_remote_create_with_fetchspec(&remote, _repo, "test-new", "git://github.com/libgit2/libgit2", "+refs/*:refs/*")); + git_remote_get_fetch_refspecs(&array, remote); + cl_assert_equal_s("+refs/*:refs/*", array.strings[0]); + git_remote_free(remote); +} + +static const char *fetch_refspecs[] = { + "+refs/heads/*:refs/remotes/origin/*", + "refs/tags/*:refs/tags/*", + "+refs/pull/*:refs/pull/*", +}; + +static const char *push_refspecs[] = { + "refs/heads/*:refs/heads/*", + "refs/tags/*:refs/tags/*", + "refs/notes/*:refs/notes/*", +}; + +void test_network_remote_remotes__query_refspecs(void) +{ + git_remote *remote; + git_strarray array; + int i; + + cl_git_pass(git_remote_create_inmemory(&remote, _repo, NULL, "git://github.com/libgit2/libgit2")); + + for (i = 0; i < 3; i++) { + cl_git_pass(git_remote_add_fetch(remote, fetch_refspecs[i])); + cl_git_pass(git_remote_add_push(remote, push_refspecs[i])); + } + + cl_git_pass(git_remote_get_fetch_refspecs(&array, remote)); + for (i = 0; i < 3; i++) { + cl_assert_equal_s(fetch_refspecs[i], array.strings[i]); + } + git_strarray_free(&array); + + cl_git_pass(git_remote_get_push_refspecs(&array, remote)); + for (i = 0; i < 3; i++) { + cl_assert_equal_s(push_refspecs[i], array.strings[i]); + } + git_strarray_free(&array); + + git_remote_free(remote); +} diff --git a/tests/network/remote/rename.c b/tests/network/remote/rename.c new file mode 100644 index 000000000..ed98ee811 --- /dev/null +++ b/tests/network/remote/rename.c @@ -0,0 +1,174 @@ +#include "clar_libgit2.h" +#include "config/config_helpers.h" + +#include "repository.h" + +static git_remote *_remote; +static git_repository *_repo; + +void test_network_remote_rename__initialize(void) +{ + _repo = cl_git_sandbox_init("testrepo.git"); + + cl_git_pass(git_remote_load(&_remote, _repo, "test")); +} + +void test_network_remote_rename__cleanup(void) +{ + git_remote_free(_remote); + _remote = NULL; + + cl_git_sandbox_cleanup(); +} + +static int dont_call_me_cb(const char *fetch_refspec, void *payload) +{ + GIT_UNUSED(fetch_refspec); + GIT_UNUSED(payload); + + cl_assert(false); + + return -1; +} + +void test_network_remote_rename__renaming_a_remote_moves_related_configuration_section(void) +{ + assert_config_entry_existence(_repo, "remote.test.fetch", true); + assert_config_entry_existence(_repo, "remote.just/renamed.fetch", false); + + cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL)); + + assert_config_entry_existence(_repo, "remote.test.fetch", false); + assert_config_entry_existence(_repo, "remote.just/renamed.fetch", true); +} + +void test_network_remote_rename__renaming_a_remote_updates_branch_related_configuration_entries(void) +{ + assert_config_entry_value(_repo, "branch.master.remote", "test"); + + cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL)); + + assert_config_entry_value(_repo, "branch.master.remote", "just/renamed"); +} + +void test_network_remote_rename__renaming_a_remote_updates_default_fetchrefspec(void) +{ + cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL)); + + assert_config_entry_value(_repo, "remote.just/renamed.fetch", "+refs/heads/*:refs/remotes/just/renamed/*"); +} + +void test_network_remote_rename__renaming_a_remote_without_a_fetchrefspec_doesnt_create_one(void) +{ + git_config *config; + + git_remote_free(_remote); + cl_git_pass(git_repository_config__weakptr(&config, _repo)); + cl_git_pass(git_config_delete_entry(config, "remote.test.fetch")); + + cl_git_pass(git_remote_load(&_remote, _repo, "test")); + + assert_config_entry_existence(_repo, "remote.test.fetch", false); + + cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL)); + + assert_config_entry_existence(_repo, "remote.just/renamed.fetch", false); +} + +static int ensure_refspecs(const char* refspec_name, void *payload) +{ + int i = 0; + bool found = false; + const char ** exp = (const char **)payload; + + while (exp[i]) { + if (strcmp(exp[i++], refspec_name)) + continue; + + found = true; + break; + } + + cl_assert(found); + + return 0; +} + +void test_network_remote_rename__renaming_a_remote_notifies_of_non_default_fetchrefspec(void) +{ + git_config *config; + + char *expected_refspecs[] = { + "+refs/*:refs/*", + NULL + }; + + git_remote_free(_remote); + cl_git_pass(git_repository_config__weakptr(&config, _repo)); + cl_git_pass(git_config_set_string(config, "remote.test.fetch", "+refs/*:refs/*")); + cl_git_pass(git_remote_load(&_remote, _repo, "test")); + + cl_git_pass(git_remote_rename(_remote, "just/renamed", ensure_refspecs, &expected_refspecs)); + + assert_config_entry_value(_repo, "remote.just/renamed.fetch", "+refs/*:refs/*"); +} + +void test_network_remote_rename__new_name_can_contain_dots(void) +{ + cl_git_pass(git_remote_rename(_remote, "just.renamed", dont_call_me_cb, NULL)); + cl_assert_equal_s("just.renamed", git_remote_name(_remote)); +} + +void test_network_remote_rename__new_name_must_conform_to_reference_naming_conventions(void) +{ + cl_assert_equal_i( + GIT_EINVALIDSPEC, + git_remote_rename(_remote, "new@{name", dont_call_me_cb, NULL)); +} + +void test_network_remote_rename__renamed_name_is_persisted(void) +{ + git_remote *renamed; + git_repository *another_repo; + + cl_git_fail(git_remote_load(&renamed, _repo, "just/renamed")); + + cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL)); + + cl_git_pass(git_repository_open(&another_repo, "testrepo.git")); + cl_git_pass(git_remote_load(&renamed, _repo, "just/renamed")); + + git_remote_free(renamed); + git_repository_free(another_repo); +} + +void test_network_remote_rename__cannot_overwrite_an_existing_remote(void) +{ + cl_assert_equal_i(GIT_EEXISTS, git_remote_rename(_remote, "test", dont_call_me_cb, NULL)); + cl_assert_equal_i(GIT_EEXISTS, git_remote_rename(_remote, "test_with_pushurl", dont_call_me_cb, NULL)); +} + +void test_network_remote_rename__renaming_a_remote_moves_the_underlying_reference(void) +{ + git_reference *underlying; + + cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&underlying, _repo, "refs/remotes/just/renamed")); + cl_git_pass(git_reference_lookup(&underlying, _repo, "refs/remotes/test/master")); + git_reference_free(underlying); + + cl_git_pass(git_remote_rename(_remote, "just/renamed", dont_call_me_cb, NULL)); + + cl_assert_equal_i(GIT_ENOTFOUND, git_reference_lookup(&underlying, _repo, "refs/remotes/test/master")); + cl_git_pass(git_reference_lookup(&underlying, _repo, "refs/remotes/just/renamed/master")); + git_reference_free(underlying); +} + +void test_network_remote_rename__cannot_rename_an_inmemory_remote(void) +{ + git_remote *remote; + + cl_git_pass(git_remote_create_inmemory(&remote, _repo, NULL, "file:///blah")); + cl_git_fail(git_remote_rename(remote, "newname", NULL, NULL)); + + git_remote_free(remote); +} diff --git a/tests/network/urlparse.c b/tests/network/urlparse.c new file mode 100644 index 000000000..2a9c2f69f --- /dev/null +++ b/tests/network/urlparse.c @@ -0,0 +1,193 @@ +#include "clar_libgit2.h" +#include "netops.h" + +static char *host, *port, *path, *user, *pass; +static gitno_connection_data conndata; + +void test_network_urlparse__initialize(void) +{ + host = port = path = user = pass = NULL; + memset(&conndata, 0, sizeof(conndata)); +} + +void test_network_urlparse__cleanup(void) +{ +#define FREE_AND_NULL(x) if (x) { git__free(x); x = NULL; } + FREE_AND_NULL(host); + FREE_AND_NULL(port); + FREE_AND_NULL(path); + FREE_AND_NULL(user); + FREE_AND_NULL(pass); + + gitno_connection_data_free_ptrs(&conndata); +} + +void test_network_urlparse__trivial(void) +{ + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "http://example.com/resource", "8080")); + cl_assert_equal_s(host, "example.com"); + cl_assert_equal_s(port, "8080"); + cl_assert_equal_s(path, "/resource"); + cl_assert_equal_p(user, NULL); + cl_assert_equal_p(pass, NULL); +} + +void test_network_urlparse__encoded_password(void) +{ + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "https://user:pass%2fis%40bad@hostname.com:1234/", "1")); + cl_assert_equal_s(host, "hostname.com"); + cl_assert_equal_s(port, "1234"); + cl_assert_equal_s(path, "/"); + cl_assert_equal_s(user, "user"); + cl_assert_equal_s(pass, "pass/is@bad"); +} + +void test_network_urlparse__user(void) +{ + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "https://user@example.com/resource", "8080")); + cl_assert_equal_s(host, "example.com"); + cl_assert_equal_s(port, "8080"); + cl_assert_equal_s(path, "/resource"); + cl_assert_equal_s(user, "user"); + cl_assert_equal_p(pass, NULL); +} + +void test_network_urlparse__user_pass(void) +{ + /* user:pass@hostname.tld/resource */ + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "https://user:pass@example.com/resource", "8080")); + cl_assert_equal_s(host, "example.com"); + cl_assert_equal_s(port, "8080"); + cl_assert_equal_s(path, "/resource"); + cl_assert_equal_s(user, "user"); + cl_assert_equal_s(pass, "pass"); +} + +void test_network_urlparse__port(void) +{ + /* hostname.tld:port/resource */ + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "https://example.com:9191/resource", "8080")); + cl_assert_equal_s(host, "example.com"); + cl_assert_equal_s(port, "9191"); + cl_assert_equal_s(path, "/resource"); + cl_assert_equal_p(user, NULL); + cl_assert_equal_p(pass, NULL); +} + +void test_network_urlparse__user_port(void) +{ + /* user@hostname.tld:port/resource */ + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "https://user@example.com:9191/resource", "8080")); + cl_assert_equal_s(host, "example.com"); + cl_assert_equal_s(port, "9191"); + cl_assert_equal_s(path, "/resource"); + cl_assert_equal_s(user, "user"); + cl_assert_equal_p(pass, NULL); +} + +void test_network_urlparse__user_pass_port(void) +{ + /* user:pass@hostname.tld:port/resource */ + cl_git_pass(gitno_extract_url_parts(&host, &port, &path, &user, &pass, + "https://user:pass@example.com:9191/resource", "8080")); + cl_assert_equal_s(host, "example.com"); + cl_assert_equal_s(port, "9191"); + cl_assert_equal_s(path, "/resource"); + cl_assert_equal_s(user, "user"); + cl_assert_equal_s(pass, "pass"); +} + +void test_network_urlparse__connection_data_http(void) +{ + cl_git_pass(gitno_connection_data_from_url(&conndata, + "http://example.com/foo/bar/baz", "bar/baz")); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/foo/"); + cl_assert_equal_p(conndata.user, NULL); + cl_assert_equal_p(conndata.pass, NULL); + cl_assert_equal_i(conndata.use_ssl, false); +} + +void test_network_urlparse__connection_data_ssl(void) +{ + cl_git_pass(gitno_connection_data_from_url(&conndata, + "https://example.com/foo/bar/baz", "bar/baz")); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/foo/"); + cl_assert_equal_p(conndata.user, NULL); + cl_assert_equal_p(conndata.pass, NULL); + cl_assert_equal_i(conndata.use_ssl, true); +} + +void test_network_urlparse__encoded_username_password(void) +{ + cl_git_pass(gitno_connection_data_from_url(&conndata, + "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz", "bar/baz")); + cl_assert_equal_s(conndata.host, "example.com"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/foo/"); + cl_assert_equal_s(conndata.user, "user/name"); + cl_assert_equal_s(conndata.pass, "pass@word%zyx%v"); + cl_assert_equal_i(conndata.use_ssl, true); +} + +void test_network_urlparse__connection_data_cross_host_redirect(void) +{ + conndata.host = git__strdup("bar.com"); + cl_git_fail_with(gitno_connection_data_from_url(&conndata, + "https://foo.com/bar/baz", NULL), + -1); +} + +void test_network_urlparse__connection_data_http_downgrade(void) +{ + conndata.use_ssl = true; + cl_git_fail_with(gitno_connection_data_from_url(&conndata, + "http://foo.com/bar/baz", NULL), + -1); +} + +void test_network_urlparse__connection_data_relative_redirect(void) +{ + cl_git_pass(gitno_connection_data_from_url(&conndata, + "http://foo.com/bar/baz/biff", NULL)); + cl_git_pass(gitno_connection_data_from_url(&conndata, + "/zap/baz/biff?bam", NULL)); + cl_assert_equal_s(conndata.host, "foo.com"); + cl_assert_equal_s(conndata.port, "80"); + cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam"); + cl_assert_equal_p(conndata.user, NULL); + cl_assert_equal_p(conndata.pass, NULL); + cl_assert_equal_i(conndata.use_ssl, false); +} + +void test_network_urlparse__connection_data_relative_redirect_ssl(void) +{ + cl_git_pass(gitno_connection_data_from_url(&conndata, + "https://foo.com/bar/baz/biff", NULL)); + cl_git_pass(gitno_connection_data_from_url(&conndata, + "/zap/baz/biff?bam", NULL)); + cl_assert_equal_s(conndata.host, "foo.com"); + cl_assert_equal_s(conndata.port, "443"); + cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam"); + cl_assert_equal_p(conndata.user, NULL); + cl_assert_equal_p(conndata.pass, NULL); + cl_assert_equal_i(conndata.use_ssl, true); +} + +/* Run this under valgrind */ +void test_network_urlparse__connection_data_cleanup(void) +{ + cl_git_pass(gitno_connection_data_from_url(&conndata, + "http://foo.com/bar/baz/biff", "baz/biff")); + cl_git_pass(gitno_connection_data_from_url(&conndata, + "https://foo.com/bar/baz/biff", "baz/biff")); +} diff --git a/tests/notes/notes.c b/tests/notes/notes.c new file mode 100644 index 000000000..82dcaf8ca --- /dev/null +++ b/tests/notes/notes.c @@ -0,0 +1,387 @@ +#include "clar_libgit2.h" + +static git_repository *_repo; +static git_signature *_sig; + +void test_notes_notes__initialize(void) +{ + _repo = cl_git_sandbox_init("testrepo.git"); + cl_git_pass(git_signature_now(&_sig, "alice", "alice@example.com")); +} + +void test_notes_notes__cleanup(void) +{ + git_signature_free(_sig); + _sig = NULL; + + cl_git_sandbox_cleanup(); +} + +static void assert_note_equal(git_note *note, char *message, git_oid *note_oid) { + git_blob *blob; + + cl_assert_equal_s(git_note_message(note), message); + cl_assert(!git_oid_cmp(git_note_oid(note), note_oid)); + + cl_git_pass(git_blob_lookup(&blob, _repo, note_oid)); + cl_assert_equal_s(git_note_message(note), (const char *)git_blob_rawcontent(blob)); + + git_blob_free(blob); +} + +static void create_note(git_oid *note_oid, const char *canonical_namespace, const char *target_sha, const char *message) +{ + git_oid oid; + + cl_git_pass(git_oid_fromstr(&oid, target_sha)); + cl_git_pass(git_note_create(note_oid, _repo, _sig, _sig, canonical_namespace, &oid, message, 0)); +} + +static struct { + const char *note_sha; + const char *annotated_object_sha; +} +list_expectations[] = { + { "1c73b1f51762155d357bcd1fd4f2c409ef80065b", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045" }, + { "1c73b1f51762155d357bcd1fd4f2c409ef80065b", "9fd738e8f7967c078dceed8190330fc8648ee56a" }, + { "257b43746b6b46caa4aa788376c647cce0a33e2b", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750" }, + { "1ec1c8e03f461f4f5d3f3702172483662e7223f3", "c47800c7266a2be04c571c04d5a6614691ea99bd" }, + { NULL, NULL } +}; + +#define EXPECTATIONS_COUNT (sizeof(list_expectations)/sizeof(list_expectations[0])) - 1 + +static int note_list_cb( + const git_oid *blob_id, const git_oid *annotated_obj_id, void *payload) +{ + git_oid expected_note_oid, expected_target_oid; + + unsigned int *count = (unsigned int *)payload; + + cl_assert(*count < EXPECTATIONS_COUNT); + + cl_git_pass(git_oid_fromstr(&expected_note_oid, list_expectations[*count].note_sha)); + cl_assert(git_oid_cmp(&expected_note_oid, blob_id) == 0); + + cl_git_pass(git_oid_fromstr(&expected_target_oid, list_expectations[*count].annotated_object_sha)); + cl_assert(git_oid_cmp(&expected_target_oid, annotated_obj_id) == 0); + + (*count)++; + + return 0; +} + +/* + * $ git notes --ref i-can-see-dead-notes add -m "I decorate a65f" a65fedf39aefe402d3bb6e24df4d4f5fe4547750 + * $ git notes --ref i-can-see-dead-notes add -m "I decorate c478" c47800c7266a2be04c571c04d5a6614691ea99bd + * $ git notes --ref i-can-see-dead-notes add -m "I decorate 9fd7 and 4a20" 9fd738e8f7967c078dceed8190330fc8648ee56a + * $ git notes --ref i-can-see-dead-notes add -m "I decorate 9fd7 and 4a20" 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 + * + * $ git notes --ref i-can-see-dead-notes list + * 1c73b1f51762155d357bcd1fd4f2c409ef80065b 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 + * 1c73b1f51762155d357bcd1fd4f2c409ef80065b 9fd738e8f7967c078dceed8190330fc8648ee56a + * 257b43746b6b46caa4aa788376c647cce0a33e2b a65fedf39aefe402d3bb6e24df4d4f5fe4547750 + * 1ec1c8e03f461f4f5d3f3702172483662e7223f3 c47800c7266a2be04c571c04d5a6614691ea99bd + * + * $ git ls-tree refs/notes/i-can-see-dead-notes + * 100644 blob 1c73b1f51762155d357bcd1fd4f2c409ef80065b 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 + * 100644 blob 1c73b1f51762155d357bcd1fd4f2c409ef80065b 9fd738e8f7967c078dceed8190330fc8648ee56a + * 100644 blob 257b43746b6b46caa4aa788376c647cce0a33e2b a65fedf39aefe402d3bb6e24df4d4f5fe4547750 + * 100644 blob 1ec1c8e03f461f4f5d3f3702172483662e7223f3 c47800c7266a2be04c571c04d5a6614691ea99bd +*/ +void test_notes_notes__can_retrieve_a_list_of_notes_for_a_given_namespace(void) +{ + git_oid note_oid1, note_oid2, note_oid3, note_oid4; + unsigned int retrieved_notes = 0; + + create_note(¬e_oid1, "refs/notes/i-can-see-dead-notes", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "I decorate a65f\n"); + create_note(¬e_oid2, "refs/notes/i-can-see-dead-notes", "c47800c7266a2be04c571c04d5a6614691ea99bd", "I decorate c478\n"); + create_note(¬e_oid3, "refs/notes/i-can-see-dead-notes", "9fd738e8f7967c078dceed8190330fc8648ee56a", "I decorate 9fd7 and 4a20\n"); + create_note(¬e_oid4, "refs/notes/i-can-see-dead-notes", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", "I decorate 9fd7 and 4a20\n"); + + cl_git_pass(git_note_foreach +(_repo, "refs/notes/i-can-see-dead-notes", note_list_cb, &retrieved_notes)); + + cl_assert_equal_i(4, retrieved_notes); +} + +static int note_cancel_cb( + const git_oid *blob_id, const git_oid *annotated_obj_id, void *payload) +{ + unsigned int *count = (unsigned int *)payload; + + GIT_UNUSED(blob_id); + GIT_UNUSED(annotated_obj_id); + + (*count)++; + + return (*count > 2); +} + +void test_notes_notes__can_cancel_foreach(void) +{ + git_oid note_oid1, note_oid2, note_oid3, note_oid4; + unsigned int retrieved_notes = 0; + + create_note(¬e_oid1, "refs/notes/i-can-see-dead-notes", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "I decorate a65f\n"); + create_note(¬e_oid2, "refs/notes/i-can-see-dead-notes", "c47800c7266a2be04c571c04d5a6614691ea99bd", "I decorate c478\n"); + create_note(¬e_oid3, "refs/notes/i-can-see-dead-notes", "9fd738e8f7967c078dceed8190330fc8648ee56a", "I decorate 9fd7 and 4a20\n"); + create_note(¬e_oid4, "refs/notes/i-can-see-dead-notes", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", "I decorate 9fd7 and 4a20\n"); + + cl_assert_equal_i( + GIT_EUSER, + git_note_foreach(_repo, "refs/notes/i-can-see-dead-notes", + note_cancel_cb, &retrieved_notes)); +} + +void test_notes_notes__retrieving_a_list_of_notes_for_an_unknown_namespace_returns_ENOTFOUND(void) +{ + int error; + unsigned int retrieved_notes = 0; + + error = git_note_foreach(_repo, "refs/notes/i-am-not", note_list_cb, &retrieved_notes); + cl_git_fail(error); + cl_assert_equal_i(GIT_ENOTFOUND, error); + + cl_assert_equal_i(0, retrieved_notes); +} + +void test_notes_notes__inserting_a_note_without_passing_a_namespace_uses_the_default_namespace(void) +{ + git_oid note_oid, target_oid; + git_note *note, *default_namespace_note; + const char *default_ref; + + cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); + cl_git_pass(git_note_default_ref(&default_ref, _repo)); + + create_note(¬e_oid, NULL, "08b041783f40edfe12bb406c9c9a8a040177c125", "hello world\n"); + + cl_git_pass(git_note_read(¬e, _repo, NULL, &target_oid)); + cl_git_pass(git_note_read(&default_namespace_note, _repo, default_ref, &target_oid)); + + assert_note_equal(note, "hello world\n", ¬e_oid); + assert_note_equal(default_namespace_note, "hello world\n", ¬e_oid); + + git_note_free(note); + git_note_free(default_namespace_note); +} + +void test_notes_notes__can_insert_a_note_with_a_custom_namespace(void) +{ + git_oid note_oid, target_oid; + git_note *note; + + cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); + + create_note(¬e_oid, "refs/notes/some/namespace", "08b041783f40edfe12bb406c9c9a8a040177c125", "hello world on a custom namespace\n"); + + cl_git_pass(git_note_read(¬e, _repo, "refs/notes/some/namespace", &target_oid)); + + assert_note_equal(note, "hello world on a custom namespace\n", ¬e_oid); + + git_note_free(note); +} + +/* + * $ git notes --ref fanout list 8496071c1b46c854b31185ea97743be6a8774479 + * 08b041783f40edfe12bb406c9c9a8a040177c125 + */ +void test_notes_notes__creating_a_note_on_a_target_which_already_has_one_returns_EEXISTS(void) +{ + int error; + git_oid note_oid, target_oid; + + cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); + + create_note(¬e_oid, NULL, "08b041783f40edfe12bb406c9c9a8a040177c125", "hello world\n"); + error = git_note_create(¬e_oid, _repo, _sig, _sig, NULL, &target_oid, "hello world\n", 0); + cl_git_fail(error); + cl_assert_equal_i(GIT_EEXISTS, error); + + create_note(¬e_oid, "refs/notes/some/namespace", "08b041783f40edfe12bb406c9c9a8a040177c125", "hello world\n"); + error = git_note_create(¬e_oid, _repo, _sig, _sig, "refs/notes/some/namespace", &target_oid, "hello world\n", 0); + cl_git_fail(error); + cl_assert_equal_i(GIT_EEXISTS, error); +} + + +void test_notes_notes__creating_a_note_on_a_target_can_overwrite_existing_note(void) +{ + git_oid note_oid, target_oid; + git_note *note, *namespace_note; + + cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); + + create_note(¬e_oid, NULL, "08b041783f40edfe12bb406c9c9a8a040177c125", "hello old world\n"); + cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, NULL, &target_oid, "hello new world\n", 1)); + + cl_git_pass(git_note_read(¬e, _repo, NULL, &target_oid)); + assert_note_equal(note, "hello new world\n", ¬e_oid); + + create_note(¬e_oid, "refs/notes/some/namespace", "08b041783f40edfe12bb406c9c9a8a040177c125", "hello old world\n"); + cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, "refs/notes/some/namespace", &target_oid, "hello new ref world\n", 1)); + + cl_git_pass(git_note_read(&namespace_note, _repo, "refs/notes/some/namespace", &target_oid)); + assert_note_equal(namespace_note, "hello new ref world\n", ¬e_oid); + + git_note_free(note); + git_note_free(namespace_note); +} + +static char *messages[] = { + "08c041783f40edfe12bb406c9c9a8a040177c125", + "96c45fbe09ab7445fc7c60fd8d17f32494399343", + "48cc7e38dcfc1ec87e70ec03e08c3e83d7a16aa1", + "24c3eaafb681c3df668f9df96f58e7b8c756eb04", + "96ca1b6ccc7858ae94684777f85ac0e7447f7040", + "7ac2db4378a08bb244a427c357e0082ee0d57ac6", + "e6cba23dbf4ef84fe35e884f017f4e24dc228572", + "c8cf3462c7d8feba716deeb2ebe6583bd54589e2", + "39c16b9834c2d665ac5f68ad91dc5b933bad8549", + "f3c582b1397df6a664224ebbaf9d4cc952706597", + "29cec67037fe8e89977474988219016ae7f342a6", + "36c4cd238bf8e82e27b740e0741b025f2e8c79ab", + "f1c45a47c02e01d5a9a326f1d9f7f756373387f8", + "4aca84406f5daee34ab513a60717c8d7b1763ead", + "84ce167da452552f63ed8407b55d5ece4901845f", + NULL +}; + +#define MESSAGES_COUNT (sizeof(messages)/sizeof(messages[0])) - 1 + +/* + * $ git ls-tree refs/notes/fanout + * 040000 tree 4b22b35d44b5a4f589edf3dc89196399771796ea 84 + * + * $ git ls-tree 4b22b35 + * 040000 tree d71aab4f9b04b45ce09bcaa636a9be6231474759 96 + * + * $ git ls-tree d71aab4 + * 100644 blob 08b041783f40edfe12bb406c9c9a8a040177c125 071c1b46c854b31185ea97743be6a8774479 + */ +void test_notes_notes__can_insert_a_note_in_an_existing_fanout(void) +{ + size_t i; + git_oid note_oid, target_oid; + git_note *_note; + + cl_git_pass(git_oid_fromstr(&target_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); + + for (i = 0; i < MESSAGES_COUNT; i++) { + cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, "refs/notes/fanout", &target_oid, messages[i], 0)); + cl_git_pass(git_note_read(&_note, _repo, "refs/notes/fanout", &target_oid)); + git_note_free(_note); + + git_oid_cpy(&target_oid, ¬e_oid); + } +} + +/* + * $ git notes --ref fanout list 8496071c1b46c854b31185ea97743be6a8774479 + * 08b041783f40edfe12bb406c9c9a8a040177c125 + */ +void test_notes_notes__can_read_a_note_in_an_existing_fanout(void) +{ + git_oid note_oid, target_oid; + git_note *note; + + cl_git_pass(git_oid_fromstr(&target_oid, "8496071c1b46c854b31185ea97743be6a8774479")); + cl_git_pass(git_note_read(¬e, _repo, "refs/notes/fanout", &target_oid)); + + cl_git_pass(git_oid_fromstr(¬e_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); + cl_assert(!git_oid_cmp(git_note_oid(note), ¬e_oid)); + + git_note_free(note); +} + +void test_notes_notes__can_remove_a_note_in_an_existing_fanout(void) +{ + git_oid target_oid; + git_note *note; + + cl_git_pass(git_oid_fromstr(&target_oid, "8496071c1b46c854b31185ea97743be6a8774479")); + cl_git_pass(git_note_remove(_repo, "refs/notes/fanout", _sig, _sig, &target_oid)); + + cl_git_fail(git_note_read(¬e, _repo, "refs/notes/fanout", &target_oid)); +} + +void test_notes_notes__removing_a_note_which_doesnt_exists_returns_ENOTFOUND(void) +{ + int error; + git_oid target_oid; + + cl_git_pass(git_oid_fromstr(&target_oid, "8496071c1b46c854b31185ea97743be6a8774479")); + cl_git_pass(git_note_remove(_repo, "refs/notes/fanout", _sig, _sig, &target_oid)); + + error = git_note_remove(_repo, "refs/notes/fanout", _sig, _sig, &target_oid); + cl_git_fail(error); + cl_assert_equal_i(GIT_ENOTFOUND, error); +} + +void test_notes_notes__can_iterate_default_namespace(void) +{ + git_note_iterator *iter; + git_note *note; + git_oid note_id, annotated_id; + git_oid note_created[2]; + const char* note_message[] = { + "I decorate a65f\n", + "I decorate c478\n" + }; + int i, err; + + create_note(¬e_created[0], "refs/notes/commits", + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", note_message[0]); + create_note(¬e_created[1], "refs/notes/commits", + "c47800c7266a2be04c571c04d5a6614691ea99bd", note_message[1]); + + cl_git_pass(git_note_iterator_new(&iter, _repo, NULL)); + + for (i = 0; (err = git_note_next(¬e_id, &annotated_id, iter)) >= 0; ++i) { + cl_git_pass(git_note_read(¬e, _repo, NULL, &annotated_id)); + cl_assert_equal_s(git_note_message(note), note_message[i]); + git_note_free(note); + } + + cl_assert_equal_i(GIT_ITEROVER, err); + cl_assert_equal_i(2, i); + git_note_iterator_free(iter); +} + +void test_notes_notes__can_iterate_custom_namespace(void) +{ + git_note_iterator *iter; + git_note *note; + git_oid note_id, annotated_id; + git_oid note_created[2]; + const char* note_message[] = { + "I decorate a65f\n", + "I decorate c478\n" + }; + int i, err; + + create_note(¬e_created[0], "refs/notes/beer", + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", note_message[0]); + create_note(¬e_created[1], "refs/notes/beer", + "c47800c7266a2be04c571c04d5a6614691ea99bd", note_message[1]); + + cl_git_pass(git_note_iterator_new(&iter, _repo, "refs/notes/beer")); + + for (i = 0; (err = git_note_next(¬e_id, &annotated_id, iter)) >= 0; ++i) { + cl_git_pass(git_note_read(¬e, _repo, "refs/notes/beer", &annotated_id)); + cl_assert_equal_s(git_note_message(note), note_message[i]); + git_note_free(note); + } + + cl_assert_equal_i(GIT_ITEROVER, err); + cl_assert_equal_i(2, i); + git_note_iterator_free(iter); +} + +void test_notes_notes__empty_iterate(void) +{ + git_note_iterator *iter; + + cl_git_fail(git_note_iterator_new(&iter, _repo, "refs/notes/commits")); +} diff --git a/tests/notes/notesref.c b/tests/notes/notesref.c new file mode 100644 index 000000000..c89b71ba5 --- /dev/null +++ b/tests/notes/notesref.c @@ -0,0 +1,64 @@ +#include "clar_libgit2.h" + +#include "notes.h" + +static git_repository *_repo; +static git_note *_note; +static git_signature *_sig; +static git_config *_cfg; + +void test_notes_notesref__initialize(void) +{ + cl_fixture_sandbox("testrepo.git"); + cl_git_pass(git_repository_open(&_repo, "testrepo.git")); +} + +void test_notes_notesref__cleanup(void) +{ + git_note_free(_note); + _note = NULL; + + git_signature_free(_sig); + _sig = NULL; + + git_config_free(_cfg); + _cfg = NULL; + + git_repository_free(_repo); + _repo = NULL; + + cl_fixture_cleanup("testrepo.git"); +} + +void test_notes_notesref__config_corenotesref(void) +{ + git_oid oid, note_oid; + const char *default_ref; + + cl_git_pass(git_signature_now(&_sig, "alice", "alice@example.com")); + cl_git_pass(git_oid_fromstr(&oid, "8496071c1b46c854b31185ea97743be6a8774479")); + + cl_git_pass(git_repository_config(&_cfg, _repo)); + + cl_git_pass(git_config_set_string(_cfg, "core.notesRef", "refs/notes/mydefaultnotesref")); + + cl_git_pass(git_note_create(¬e_oid, _repo, _sig, _sig, NULL, &oid, "test123test\n", 0)); + + cl_git_pass(git_note_read(&_note, _repo, NULL, &oid)); + cl_assert_equal_s("test123test\n", git_note_message(_note)); + cl_assert(!git_oid_cmp(git_note_oid(_note), ¬e_oid)); + + git_note_free(_note); + + cl_git_pass(git_note_read(&_note, _repo, "refs/notes/mydefaultnotesref", &oid)); + cl_assert_equal_s("test123test\n", git_note_message(_note)); + cl_assert(!git_oid_cmp(git_note_oid(_note), ¬e_oid)); + + cl_git_pass(git_note_default_ref(&default_ref, _repo)); + cl_assert_equal_s("refs/notes/mydefaultnotesref", default_ref); + + cl_git_pass(git_config_delete_entry(_cfg, "core.notesRef")); + + cl_git_pass(git_note_default_ref(&default_ref, _repo)); + cl_assert_equal_s(GIT_NOTES_DEFAULT_REF, default_ref); +} diff --git a/tests/object/blob/filter.c b/tests/object/blob/filter.c new file mode 100644 index 000000000..0b2d6bf9e --- /dev/null +++ b/tests/object/blob/filter.c @@ -0,0 +1,143 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "blob.h" +#include "buf_text.h" + +static git_repository *g_repo = NULL; + +#define CRLF_NUM_TEST_OBJECTS 9 + +static const char *g_crlf_raw[CRLF_NUM_TEST_OBJECTS] = { + "", + "foo\nbar\n", + "foo\rbar\r", + "foo\r\nbar\r\n", + "foo\nbar\rboth\r\nreversed\n\ragain\nproblems\r", + "123\n\000\001\002\003\004abc\255\254\253\r\n", + "\xEF\xBB\xBFThis is UTF-8\n", + "\xEF\xBB\xBF\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\r\n\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\r\n", + "\xFE\xFF\x00T\x00h\x00i\x00s\x00!" +}; + +static git_off_t g_crlf_raw_len[CRLF_NUM_TEST_OBJECTS] = { + -1, -1, -1, -1, -1, 17, -1, -1, 12 +}; + +static git_oid g_crlf_oids[CRLF_NUM_TEST_OBJECTS]; + +static git_buf g_crlf_filtered[CRLF_NUM_TEST_OBJECTS] = { + { "", 0, 0 }, + { "foo\nbar\n", 0, 8 }, + { "foo\rbar\r", 0, 8 }, + { "foo\nbar\n", 0, 8 }, + { "foo\nbar\rboth\nreversed\n\ragain\nproblems\r", 0, 38 }, + { "123\n\000\001\002\003\004abc\255\254\253\n", 0, 16 }, + { "\xEF\xBB\xBFThis is UTF-8\n", 0, 17 }, + { "\xEF\xBB\xBF\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\n\xE3\x81\xBB\xE3\x81\x92\xE3\x81\xBB\xE3\x81\x92\n", 0, 29 }, + { "\xFE\xFF\x00T\x00h\x00i\x00s\x00!", 0, 12 } +}; + +static git_buf_text_stats g_crlf_filtered_stats[CRLF_NUM_TEST_OBJECTS] = { + { 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 2, 0, 6, 0 }, + { 0, 0, 2, 0, 0, 6, 0 }, + { 0, 0, 2, 2, 2, 6, 0 }, + { 0, 0, 4, 4, 1, 31, 0 }, + { 0, 1, 1, 2, 1, 9, 5 }, + { GIT_BOM_UTF8, 0, 0, 1, 0, 16, 0 }, + { GIT_BOM_UTF8, 0, 2, 2, 2, 27, 0 }, + { GIT_BOM_UTF16_BE, 5, 0, 0, 0, 7, 5 }, +}; + +void test_object_blob_filter__initialize(void) +{ + int i; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) { + if (g_crlf_raw_len[i] < 0) + g_crlf_raw_len[i] = strlen(g_crlf_raw[i]); + + cl_git_pass(git_blob_create_frombuffer( + &g_crlf_oids[i], g_repo, g_crlf_raw[i], (size_t)g_crlf_raw_len[i])); + } +} + +void test_object_blob_filter__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_object_blob_filter__unfiltered(void) +{ + int i; + git_blob *blob; + + for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) { + size_t raw_len = (size_t)g_crlf_raw_len[i]; + + cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i])); + + cl_assert_equal_sz(raw_len, (size_t)git_blob_rawsize(blob)); + cl_assert_equal_i( + 0, memcmp(g_crlf_raw[i], git_blob_rawcontent(blob), raw_len)); + + git_blob_free(blob); + } +} + +void test_object_blob_filter__stats(void) +{ + int i; + git_blob *blob; + git_buf buf = GIT_BUF_INIT; + git_buf_text_stats stats; + + for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) { + cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i])); + cl_git_pass(git_blob__getbuf(&buf, blob)); + git_buf_text_gather_stats(&stats, &buf, false); + cl_assert_equal_i( + 0, memcmp(&g_crlf_filtered_stats[i], &stats, sizeof(stats))); + git_blob_free(blob); + } + + git_buf_free(&buf); +} + +void test_object_blob_filter__to_odb(void) +{ + git_filter_list *fl = NULL; + git_config *cfg; + int i; + git_blob *blob; + git_buf out = GIT_BUF_INIT; + + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_assert(cfg); + + git_attr_cache_flush(g_repo); + cl_git_append2file("empty_standard_repo/.gitattributes", "*.txt text\n"); + + cl_git_pass(git_filter_list_load( + &fl, g_repo, NULL, "filename.txt", GIT_FILTER_TO_ODB)); + cl_assert(fl != NULL); + + for (i = 0; i < CRLF_NUM_TEST_OBJECTS; i++) { + cl_git_pass(git_blob_lookup(&blob, g_repo, &g_crlf_oids[i])); + + cl_git_pass(git_filter_list_apply_to_blob(&out, fl, blob)); + + cl_assert_equal_sz(g_crlf_filtered[i].size, out.size); + + cl_assert_equal_i( + 0, memcmp(out.ptr, g_crlf_filtered[i].ptr, out.size)); + + git_blob_free(blob); + } + + git_filter_list_free(fl); + git_buf_free(&out); + git_config_free(cfg); +} diff --git a/tests/object/blob/fromchunks.c b/tests/object/blob/fromchunks.c new file mode 100644 index 000000000..03ed4efb4 --- /dev/null +++ b/tests/object/blob/fromchunks.c @@ -0,0 +1,119 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "posix.h" +#include "path.h" +#include "fileops.h" + +static git_repository *repo; +static char textual_content[] = "libgit2\n\r\n\0"; + +void test_object_blob_fromchunks__initialize(void) +{ + repo = cl_git_sandbox_init("testrepo.git"); +} + +void test_object_blob_fromchunks__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static int text_chunked_source_cb(char *content, size_t max_length, void *payload) +{ + int *count; + + GIT_UNUSED(max_length); + + count = (int *)payload; + (*count)--; + + if (*count == 0) + return 0; + + strcpy(content, textual_content); + return (int)strlen(textual_content); +} + +void test_object_blob_fromchunks__can_create_a_blob_from_a_in_memory_chunk_provider(void) +{ + git_oid expected_oid, oid; + git_object *blob; + int howmany = 7; + + cl_git_pass(git_oid_fromstr(&expected_oid, "321cbdf08803c744082332332838df6bd160f8f9")); + + cl_git_fail_with( + git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY), + GIT_ENOTFOUND); + + cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany)); + + cl_git_pass(git_object_lookup(&blob, repo, &expected_oid, GIT_OBJ_ANY)); + cl_assert(git_oid_cmp(&expected_oid, git_object_id(blob)) == 0); + + git_object_free(blob); +} + +void test_object_blob_fromchunks__doesnot_overwrite_an_already_existing_object(void) +{ + git_buf path = GIT_BUF_INIT; + git_buf content = GIT_BUF_INIT; + git_oid expected_oid, oid; + int howmany = 7; + + cl_git_pass(git_oid_fromstr(&expected_oid, "321cbdf08803c744082332332838df6bd160f8f9")); + + cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany)); + + /* Let's replace the content of the blob file storage with something else... */ + cl_git_pass(git_buf_joinpath(&path, git_repository_path(repo), "objects/32/1cbdf08803c744082332332838df6bd160f8f9")); + cl_git_pass(p_unlink(git_buf_cstr(&path))); + cl_git_mkfile(git_buf_cstr(&path), "boom"); + + /* ...request a creation of the same blob... */ + howmany = 7; + cl_git_pass(git_blob_create_fromchunks(&oid, repo, NULL, text_chunked_source_cb, &howmany)); + + /* ...and ensure the content of the faked blob file hasn't been altered */ + cl_git_pass(git_futils_readbuffer(&content, git_buf_cstr(&path))); + cl_assert(!git__strcmp("boom", git_buf_cstr(&content))); + + git_buf_free(&path); + git_buf_free(&content); +} + +#define GITATTR "* text=auto\n" \ + "*.txt text\n" \ + "*.data binary\n" + +static void write_attributes(git_repository *repo) +{ + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&buf, git_repository_path(repo), "info")); + cl_git_pass(git_buf_joinpath(&buf, git_buf_cstr(&buf), "attributes")); + + cl_git_pass(git_futils_mkpath2file(git_buf_cstr(&buf), 0777)); + cl_git_rewritefile(git_buf_cstr(&buf), GITATTR); + + git_buf_free(&buf); +} + +static void assert_named_chunked_blob(const char *expected_sha, const char *fake_name) +{ + git_oid expected_oid, oid; + int howmany = 7; + + cl_git_pass(git_oid_fromstr(&expected_oid, expected_sha)); + + cl_git_pass(git_blob_create_fromchunks(&oid, repo, fake_name, text_chunked_source_cb, &howmany)); + cl_assert(git_oid_cmp(&expected_oid, &oid) == 0); +} + +void test_object_blob_fromchunks__creating_a_blob_from_chunks_honors_the_attributes_directives(void) +{ + write_attributes(repo); + + assert_named_chunked_blob("321cbdf08803c744082332332838df6bd160f8f9", "dummy.data"); + assert_named_chunked_blob("e9671e138a780833cb689753570fd10a55be84fb", "dummy.txt"); + assert_named_chunked_blob("e9671e138a780833cb689753570fd10a55be84fb", "dummy.dunno"); +} diff --git a/tests/object/blob/write.c b/tests/object/blob/write.c new file mode 100644 index 000000000..203bc67c1 --- /dev/null +++ b/tests/object/blob/write.c @@ -0,0 +1,69 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "posix.h" +#include "path.h" +#include "fileops.h" + +static git_repository *repo; + +#define WORKDIR "empty_standard_repo" +#define BARE_REPO "testrepo.git" +#define ELSEWHERE "elsewhere" + +typedef int (*blob_creator_fn)( + git_oid *, + git_repository *, + const char *); + +void test_object_blob_write__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void assert_blob_creation(const char *path_to_file, const char *blob_from_path, blob_creator_fn creator) +{ + git_oid oid; + cl_git_mkfile(path_to_file, "1..2...3... Can you hear me?\n"); + + cl_must_pass(creator(&oid, repo, blob_from_path)); + cl_assert(git_oid_streq(&oid, "da5e4f20c91c81b44a7e298f3d3fb3fe2f178e32") == 0); +} + +void test_object_blob_write__can_create_a_blob_in_a_standard_repo_from_a_file_located_in_the_working_directory(void) +{ + repo = cl_git_sandbox_init(WORKDIR); + + assert_blob_creation(WORKDIR "/test.txt", "test.txt", &git_blob_create_fromworkdir); +} + +void test_object_blob_write__can_create_a_blob_in_a_standard_repo_from_a_absolute_filepath_pointing_outside_of_the_working_directory(void) +{ + git_buf full_path = GIT_BUF_INIT; + + repo = cl_git_sandbox_init(WORKDIR); + + cl_must_pass(p_mkdir(ELSEWHERE, 0777)); + cl_must_pass(git_path_prettify_dir(&full_path, ELSEWHERE, NULL)); + cl_must_pass(git_buf_puts(&full_path, "test.txt")); + + assert_blob_creation(ELSEWHERE "/test.txt", git_buf_cstr(&full_path), &git_blob_create_fromdisk); + + git_buf_free(&full_path); + cl_must_pass(git_futils_rmdir_r(ELSEWHERE, NULL, GIT_RMDIR_REMOVE_FILES)); +} + +void test_object_blob_write__can_create_a_blob_in_a_bare_repo_from_a_absolute_filepath(void) +{ + git_buf full_path = GIT_BUF_INIT; + + repo = cl_git_sandbox_init(BARE_REPO); + + cl_must_pass(p_mkdir(ELSEWHERE, 0777)); + cl_must_pass(git_path_prettify_dir(&full_path, ELSEWHERE, NULL)); + cl_must_pass(git_buf_puts(&full_path, "test.txt")); + + assert_blob_creation(ELSEWHERE "/test.txt", git_buf_cstr(&full_path), &git_blob_create_fromdisk); + + git_buf_free(&full_path); + cl_must_pass(git_futils_rmdir_r(ELSEWHERE, NULL, GIT_RMDIR_REMOVE_FILES)); +} diff --git a/tests/object/cache.c b/tests/object/cache.c new file mode 100644 index 000000000..b927b2514 --- /dev/null +++ b/tests/object/cache.c @@ -0,0 +1,287 @@ +#include "clar_libgit2.h" +#include "repository.h" + +static git_repository *g_repo; + +void test_object_cache__initialize(void) +{ + g_repo = NULL; +} + +void test_object_cache__cleanup(void) +{ + git_repository_free(g_repo); + g_repo = NULL; + + git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJ_BLOB, (size_t)0); +} + +static struct { + git_otype type; + const char *sha; +} g_data[] = { + /* HEAD */ + { GIT_OBJ_BLOB, "a8233120f6ad708f843d861ce2b7228ec4e3dec6" }, /* README */ + { GIT_OBJ_BLOB, "3697d64be941a53d4ae8f6a271e4e3fa56b022cc" }, /* branch_file.txt */ + { GIT_OBJ_BLOB, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd" }, /* new.txt */ + + /* refs/heads/subtrees */ + { GIT_OBJ_BLOB, "1385f264afb75a56a5bec74243be9b367ba4ca08" }, /* README */ + { GIT_OBJ_TREE, "f1425cef211cc08caa31e7b545ffb232acb098c3" }, /* ab */ + { GIT_OBJ_BLOB, "d6c93164c249c8000205dd4ec5cbca1b516d487f" }, /* ab/4.txt */ + { GIT_OBJ_TREE, "9a03079b8a8ee85a0bee58bf9be3da8b62414ed4" }, /* ab/c */ + { GIT_OBJ_BLOB, "270b8ea76056d5cad83af921837702d3e3c2924d" }, /* ab/c/3.txt */ + { GIT_OBJ_TREE, "b6361fc6a97178d8fc8639fdeed71c775ab52593" }, /* ab/de */ + { GIT_OBJ_BLOB, "e7b4ad382349ff96dd8199000580b9b1e2042eb0" }, /* ab/de/2.txt */ + { GIT_OBJ_TREE, "3259a6bd5b57fb9c1281bb7ed3167b50f224cb54" }, /* ab/de/fgh */ + { GIT_OBJ_BLOB, "1f67fc4386b2d171e0d21be1c447e12660561f9b" }, /* ab/de/fgh/1.txt */ + { GIT_OBJ_BLOB, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057" }, /* branch_file.txt */ + { GIT_OBJ_BLOB, "fa49b077972391ad58037050f2a75f74e3671e92" }, /* new.txt */ + + /* refs/heads/chomped */ + { GIT_OBJ_BLOB, "0266163a49e280c4f5ed1e08facd36a2bd716bcf" }, /* readme.txt */ + + { 0, NULL }, + { 0, NULL } +}; + +void test_object_cache__cache_everything(void) +{ + int i, start; + git_oid oid; + git_odb_object *odb_obj; + git_object *obj; + git_odb *odb; + + git_libgit2_opts( + GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJ_BLOB, (size_t)32767); + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_repository_odb(&odb, g_repo)); + + start = (int)git_cache_size(&g_repo->objects); + + for (i = 0; g_data[i].sha != NULL; ++i) { + int count = (int)git_cache_size(&g_repo->objects); + + cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); + + /* alternate between loading raw and parsed objects */ + if ((i & 1) == 0) { + cl_git_pass(git_odb_read(&odb_obj, odb, &oid)); + cl_assert(g_data[i].type == git_odb_object_type(odb_obj)); + git_odb_object_free(odb_obj); + } else { + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + cl_assert(g_data[i].type == git_object_type(obj)); + git_object_free(obj); + } + + cl_assert_equal_i(count + 1, (int)git_cache_size(&g_repo->objects)); + } + + cl_assert_equal_i(i, (int)git_cache_size(&g_repo->objects) - start); + + git_odb_free(odb); + + for (i = 0; g_data[i].sha != NULL; ++i) { + int count = (int)git_cache_size(&g_repo->objects); + + cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + cl_assert(g_data[i].type == git_object_type(obj)); + git_object_free(obj); + + cl_assert_equal_i(count, (int)git_cache_size(&g_repo->objects)); + } +} + +void test_object_cache__cache_no_blobs(void) +{ + int i, start, nonblobs = 0; + git_oid oid; + git_odb_object *odb_obj; + git_object *obj; + git_odb *odb; + + git_libgit2_opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, (int)GIT_OBJ_BLOB, (size_t)0); + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_repository_odb(&odb, g_repo)); + + start = (int)git_cache_size(&g_repo->objects); + + for (i = 0; g_data[i].sha != NULL; ++i) { + int count = (int)git_cache_size(&g_repo->objects); + + cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); + + /* alternate between loading raw and parsed objects */ + if ((i & 1) == 0) { + cl_git_pass(git_odb_read(&odb_obj, odb, &oid)); + cl_assert(g_data[i].type == git_odb_object_type(odb_obj)); + git_odb_object_free(odb_obj); + } else { + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + cl_assert(g_data[i].type == git_object_type(obj)); + git_object_free(obj); + } + + if (g_data[i].type == GIT_OBJ_BLOB) + cl_assert_equal_i(count, (int)git_cache_size(&g_repo->objects)); + else { + cl_assert_equal_i(count + 1, (int)git_cache_size(&g_repo->objects)); + nonblobs++; + } + } + + cl_assert_equal_i(nonblobs, (int)git_cache_size(&g_repo->objects) - start); + + git_odb_free(odb); +} + +static void *cache_parsed(void *arg) +{ + int i; + git_oid oid; + git_object *obj; + + for (i = ((int *)arg)[1]; g_data[i].sha != NULL; i += 2) { + cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + cl_assert(g_data[i].type == git_object_type(obj)); + git_object_free(obj); + } + + for (i = 0; i < ((int *)arg)[1]; i += 2) { + cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + cl_assert(g_data[i].type == git_object_type(obj)); + git_object_free(obj); + } + + return arg; +} + +static void *cache_raw(void *arg) +{ + int i; + git_oid oid; + git_odb *odb; + git_odb_object *odb_obj; + + cl_git_pass(git_repository_odb(&odb, g_repo)); + + for (i = ((int *)arg)[1]; g_data[i].sha != NULL; i += 2) { + cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); + cl_git_pass(git_odb_read(&odb_obj, odb, &oid)); + cl_assert(g_data[i].type == git_odb_object_type(odb_obj)); + git_odb_object_free(odb_obj); + } + + for (i = 0; i < ((int *)arg)[1]; i += 2) { + cl_git_pass(git_oid_fromstr(&oid, g_data[i].sha)); + cl_git_pass(git_odb_read(&odb_obj, odb, &oid)); + cl_assert(g_data[i].type == git_odb_object_type(odb_obj)); + git_odb_object_free(odb_obj); + } + + git_odb_free(odb); + + return arg; +} + +#define REPEAT 20 +#define THREADCOUNT 50 + +void test_object_cache__threadmania(void) +{ + int try, th, max_i; + void *data; + void *(*fn)(void *); + +#ifdef GIT_THREADS + git_thread t[THREADCOUNT]; +#endif + + for (max_i = 0; g_data[max_i].sha != NULL; ++max_i) + /* count up */; + + for (try = 0; try < REPEAT; ++try) { + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); + + for (th = 0; th < THREADCOUNT; ++th) { + data = git__malloc(2 * sizeof(int)); + + ((int *)data)[0] = th; + ((int *)data)[1] = th % max_i; + + fn = (th & 1) ? cache_parsed : cache_raw; + +#ifdef GIT_THREADS + cl_git_pass(git_thread_create(&t[th], NULL, fn, data)); +#else + cl_assert(fn(data) == data); + git__free(data); +#endif + } + +#ifdef GIT_THREADS + for (th = 0; th < THREADCOUNT; ++th) { + cl_git_pass(git_thread_join(t[th], &data)); + cl_assert_equal_i(th, ((int *)data)[0]); + git__free(data); + } +#endif + + git_repository_free(g_repo); + g_repo = NULL; + } +} + +static void *cache_quick(void *arg) +{ + git_oid oid; + git_object *obj; + + cl_git_pass(git_oid_fromstr(&oid, g_data[4].sha)); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + cl_assert(g_data[4].type == git_object_type(obj)); + git_object_free(obj); + + return arg; +} + +void test_object_cache__fast_thread_rush(void) +{ + int try, th, data[THREADCOUNT*2]; +#ifdef GIT_THREADS + git_thread t[THREADCOUNT*2]; +#endif + + for (try = 0; try < REPEAT; ++try) { + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); + + for (th = 0; th < THREADCOUNT*2; ++th) { + data[th] = th; +#ifdef GIT_THREADS + cl_git_pass( + git_thread_create(&t[th], NULL, cache_quick, &data[th])); +#else + cl_assert(cache_quick(&data[th]) == &data[th]); +#endif + } + +#ifdef GIT_THREADS + for (th = 0; th < THREADCOUNT*2; ++th) { + void *rval; + cl_git_pass(git_thread_join(t[th], &rval)); + cl_assert_equal_i(th, *((int *)rval)); + } +#endif + + git_repository_free(g_repo); + g_repo = NULL; + } +} diff --git a/tests/object/commit/commitstagedfile.c b/tests/object/commit/commitstagedfile.c new file mode 100644 index 000000000..9867ab418 --- /dev/null +++ b/tests/object/commit/commitstagedfile.c @@ -0,0 +1,132 @@ +#include "clar_libgit2.h" +#include "posix.h" + +static git_repository *repo; + +void test_object_commit_commitstagedfile__initialize(void) +{ + cl_fixture("treebuilder"); + cl_git_pass(git_repository_init(&repo, "treebuilder/", 0)); + cl_assert(repo != NULL); +} + +void test_object_commit_commitstagedfile__cleanup(void) +{ + git_repository_free(repo); + repo = NULL; + + cl_fixture_cleanup("treebuilder"); +} + +void test_object_commit_commitstagedfile__generate_predictable_object_ids(void) +{ + git_index *index; + const git_index_entry *entry; + git_oid expected_blob_oid, tree_oid, expected_tree_oid, commit_oid, expected_commit_oid; + git_signature *signature; + git_tree *tree; + char buffer[128]; + + /* + * The test below replicates the following git scenario + * + * $ echo "test" > test.txt + * $ git hash-object test.txt + * 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 + * + * $ git add . + * $ git commit -m "Initial commit" + * + * $ git log + * commit 1fe3126578fc4eca68c193e4a3a0a14a0704624d + * Author: nulltoken + * Date: Wed Dec 14 08:29:03 2011 +0100 + * + * Initial commit + * + * $ git show 1fe3 --format=raw + * commit 1fe3126578fc4eca68c193e4a3a0a14a0704624d + * tree 2b297e643c551e76cfa1f93810c50811382f9117 + * author nulltoken 1323847743 +0100 + * committer nulltoken 1323847743 +0100 + * + * Initial commit + * + * diff --git a/test.txt b/test.txt + * new file mode 100644 + * index 0000000..9daeafb + * --- /dev/null + * +++ b/test.txt + * @@ -0,0 +1 @@ + * +test + * + * $ git ls-tree 2b297 + * 100644 blob 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 test.txt + */ + + cl_git_pass(git_oid_fromstr(&expected_commit_oid, "1fe3126578fc4eca68c193e4a3a0a14a0704624d")); + cl_git_pass(git_oid_fromstr(&expected_tree_oid, "2b297e643c551e76cfa1f93810c50811382f9117")); + cl_git_pass(git_oid_fromstr(&expected_blob_oid, "9daeafb9864cf43055ae93beb0afd6c7d144bfa4")); + + /* + * Add a new file to the index + */ + cl_git_mkfile("treebuilder/test.txt", "test\n"); + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_bypath(index, "test.txt")); + + entry = git_index_get_byindex(index, 0); + + cl_assert(git_oid_cmp(&expected_blob_oid, &entry->oid) == 0); + + /* + * Information about index entry should match test file + */ + { + struct stat st; + cl_must_pass(p_lstat("treebuilder/test.txt", &st)); + cl_assert(entry->file_size == st.st_size); +#ifndef _WIN32 + /* + * Windows doesn't populate these fields, and the signage is + * wrong in the Windows version of the struct, so lets avoid + * the "comparing signed and unsigned" compilation warning in + * that case. + */ + cl_assert(entry->uid == st.st_uid); + cl_assert(entry->gid == st.st_gid); +#endif + } + + /* + * Build the tree from the index + */ + cl_git_pass(git_index_write_tree(&tree_oid, index)); + + cl_assert(git_oid_cmp(&expected_tree_oid, &tree_oid) == 0); + + /* + * Commit the staged file + */ + cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); + cl_git_pass(git_tree_lookup(&tree, repo, &tree_oid)); + + cl_assert_equal_i(16, git_message_prettify(buffer, 128, "Initial commit", 0)); + + cl_git_pass(git_commit_create_v( + &commit_oid, + repo, + "HEAD", + signature, + signature, + NULL, + buffer, + tree, + 0)); + + cl_assert(git_oid_cmp(&expected_commit_oid, &commit_oid) == 0); + + git_signature_free(signature); + git_tree_free(tree); + git_index_free(index); +} diff --git a/tests/object/lookup.c b/tests/object/lookup.c new file mode 100644 index 000000000..cfa6d4678 --- /dev/null +++ b/tests/object/lookup.c @@ -0,0 +1,65 @@ +#include "clar_libgit2.h" + +#include "repository.h" + +static git_repository *g_repo; + +void test_object_lookup__initialize(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); +} + +void test_object_lookup__cleanup(void) +{ + git_repository_free(g_repo); + g_repo = NULL; +} + +void test_object_lookup__lookup_wrong_type_returns_enotfound(void) +{ + const char *commit = "e90810b8df3e80c413d903f631643c716887138d"; + git_oid oid; + git_object *object; + + cl_git_pass(git_oid_fromstr(&oid, commit)); + cl_assert_equal_i( + GIT_ENOTFOUND, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_TAG)); +} + +void test_object_lookup__lookup_nonexisting_returns_enotfound(void) +{ + const char *unknown = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; + git_oid oid; + git_object *object; + + cl_git_pass(git_oid_fromstr(&oid, unknown)); + cl_assert_equal_i( + GIT_ENOTFOUND, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_ANY)); +} + +void test_object_lookup__lookup_wrong_type_by_abbreviated_id_returns_enotfound(void) +{ + const char *commit = "e90810b"; + git_oid oid; + git_object *object; + + cl_git_pass(git_oid_fromstrn(&oid, commit, strlen(commit))); + cl_assert_equal_i( + GIT_ENOTFOUND, git_object_lookup_prefix(&object, g_repo, &oid, strlen(commit), GIT_OBJ_TAG)); +} + +void test_object_lookup__lookup_wrong_type_eventually_returns_enotfound(void) +{ + const char *commit = "e90810b8df3e80c413d903f631643c716887138d"; + git_oid oid; + git_object *object; + + cl_git_pass(git_oid_fromstr(&oid, commit)); + + cl_git_pass(git_object_lookup(&object, g_repo, &oid, GIT_OBJ_COMMIT)); + git_object_free(object); + + cl_assert_equal_i( + GIT_ENOTFOUND, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_TAG)); +} + diff --git a/tests/object/lookupbypath.c b/tests/object/lookupbypath.c new file mode 100644 index 000000000..31aac7647 --- /dev/null +++ b/tests/object/lookupbypath.c @@ -0,0 +1,83 @@ +#include "clar_libgit2.h" + +#include "repository.h" + +static git_repository *g_repo; +static git_tree *g_root_tree; +static git_commit *g_head_commit; +static git_object *g_expectedobject, + *g_actualobject; + +void test_object_lookupbypath__initialize(void) +{ + git_reference *head; + git_tree_entry *tree_entry; + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("attr/.gitted"))); + + cl_git_pass(git_repository_head(&head, g_repo)); + cl_git_pass(git_reference_peel((git_object**)&g_head_commit, head, GIT_OBJ_COMMIT)); + cl_git_pass(git_commit_tree(&g_root_tree, g_head_commit)); + cl_git_pass(git_tree_entry_bypath(&tree_entry, g_root_tree, "subdir/subdir_test2.txt")); + cl_git_pass(git_object_lookup(&g_expectedobject, g_repo, git_tree_entry_id(tree_entry), + GIT_OBJ_ANY)); + + git_tree_entry_free(tree_entry); + git_reference_free(head); + + g_actualobject = NULL; +} +void test_object_lookupbypath__cleanup(void) +{ + git_object_free(g_actualobject); + git_object_free(g_expectedobject); + git_tree_free(g_root_tree); + git_commit_free(g_head_commit); + g_expectedobject = NULL; + git_repository_free(g_repo); + g_repo = NULL; +} + +void test_object_lookupbypath__errors(void) +{ + cl_assert_equal_i(GIT_EINVALIDSPEC, + git_object_lookup_bypath(&g_actualobject, (git_object*)g_root_tree, + "subdir/subdir_test2.txt", GIT_OBJ_TREE)); // It's not a tree + cl_assert_equal_i(GIT_ENOTFOUND, + git_object_lookup_bypath(&g_actualobject, (git_object*)g_root_tree, + "file/doesnt/exist", GIT_OBJ_ANY)); +} + +void test_object_lookupbypath__from_root_tree(void) +{ + cl_git_pass(git_object_lookup_bypath(&g_actualobject, (git_object*)g_root_tree, + "subdir/subdir_test2.txt", GIT_OBJ_BLOB)); + cl_assert_equal_i(0, git_oid_cmp(git_object_id(g_expectedobject), + git_object_id(g_actualobject))); +} + +void test_object_lookupbypath__from_head_commit(void) +{ + cl_git_pass(git_object_lookup_bypath(&g_actualobject, (git_object*)g_head_commit, + "subdir/subdir_test2.txt", GIT_OBJ_BLOB)); + cl_assert_equal_i(0, git_oid_cmp(git_object_id(g_expectedobject), + git_object_id(g_actualobject))); +} + +void test_object_lookupbypath__from_subdir_tree(void) +{ + git_tree_entry *entry = NULL; + git_tree *tree = NULL; + + cl_git_pass(git_tree_entry_bypath(&entry, g_root_tree, "subdir")); + cl_git_pass(git_tree_lookup(&tree, g_repo, git_tree_entry_id(entry))); + + cl_git_pass(git_object_lookup_bypath(&g_actualobject, (git_object*)tree, + "subdir_test2.txt", GIT_OBJ_BLOB)); + cl_assert_equal_i(0, git_oid_cmp(git_object_id(g_expectedobject), + git_object_id(g_actualobject))); + + git_tree_entry_free(entry); + git_tree_free(tree); +} + diff --git a/tests/object/message.c b/tests/object/message.c new file mode 100644 index 000000000..7ef6374b3 --- /dev/null +++ b/tests/object/message.c @@ -0,0 +1,236 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "message.h" + +static void assert_message_prettifying(char *expected_output, char *input, int strip_comments) +{ + git_buf prettified_message = GIT_BUF_INIT; + + git_message__prettify(&prettified_message, input, strip_comments); + cl_assert_equal_s(expected_output, git_buf_cstr(&prettified_message)); + + git_buf_free(&prettified_message); +} + +#define t40 "A quick brown fox jumps over the lazy do" +#define s40 " " +#define sss s40 s40 s40 s40 s40 s40 s40 s40 s40 s40 // # 400 +#define ttt t40 t40 t40 t40 t40 t40 t40 t40 t40 t40 // # 400 + +/* Ported from git.git */ +/* see https://github.com/git/git/blob/master/t/t0030-stripspace.sh */ +void test_object_message__long_lines_without_spaces_should_be_unchanged(void) +{ + assert_message_prettifying(ttt "\n", ttt, 0); + assert_message_prettifying(ttt ttt "\n", ttt ttt, 0); + assert_message_prettifying(ttt ttt ttt "\n", ttt ttt ttt, 0); + assert_message_prettifying(ttt ttt ttt ttt "\n", ttt ttt ttt ttt, 0); +} + +void test_object_message__lines_with_spaces_at_the_beginning_should_be_unchanged(void) +{ + assert_message_prettifying(sss ttt "\n", sss ttt, 0); + assert_message_prettifying(sss sss ttt "\n", sss sss ttt, 0); + assert_message_prettifying(sss sss sss ttt "\n", sss sss sss ttt, 0); +} + +void test_object_message__lines_with_intermediate_spaces_should_be_unchanged(void) +{ + assert_message_prettifying(ttt sss ttt "\n", ttt sss ttt, 0); + assert_message_prettifying(ttt sss sss ttt "\n", ttt sss sss ttt, 0); +} + +void test_object_message__consecutive_blank_lines_should_be_unified(void) +{ + assert_message_prettifying(ttt "\n\n" ttt "\n", ttt "\n\n\n\n\n" ttt "\n", 0); + assert_message_prettifying(ttt ttt "\n\n" ttt "\n", ttt ttt "\n\n\n\n\n" ttt "\n", 0); + assert_message_prettifying(ttt ttt ttt "\n\n" ttt "\n", ttt ttt ttt "\n\n\n\n\n" ttt "\n", 0); + + assert_message_prettifying(ttt "\n\n" ttt ttt "\n", ttt "\n\n\n\n\n" ttt ttt "\n", 0); + assert_message_prettifying(ttt "\n\n" ttt ttt ttt "\n", ttt "\n\n\n\n\n" ttt ttt ttt "\n", 0); + + assert_message_prettifying(ttt "\n\n" ttt "\n", ttt "\n\t\n \n\n \t\t\n" ttt "\n", 0); + assert_message_prettifying(ttt ttt "\n\n" ttt "\n", ttt ttt "\n\t\n \n\n \t\t\n" ttt "\n", 0); + assert_message_prettifying(ttt ttt ttt "\n\n" ttt "\n", ttt ttt ttt "\n\t\n \n\n \t\t\n" ttt "\n", 0); + + assert_message_prettifying(ttt "\n\n" ttt ttt "\n", ttt "\n\t\n \n\n \t\t\n" ttt ttt "\n", 0); + assert_message_prettifying(ttt "\n\n" ttt ttt ttt "\n", ttt "\n\t\n \n\n \t\t\n" ttt ttt ttt "\n", 0); +} + +void test_object_message__only_consecutive_blank_lines_should_be_completely_removed(void) +{ + assert_message_prettifying("", "\n", 0); + assert_message_prettifying("", "\n\n\n", 0); + assert_message_prettifying("", sss "\n" sss "\n" sss "\n", 0); + assert_message_prettifying("", sss sss "\n" sss "\n\n", 0); +} + +void test_object_message__consecutive_blank_lines_at_the_beginning_should_be_removed(void) +{ + assert_message_prettifying(ttt "\n", "\n" ttt "\n", 0); + assert_message_prettifying(ttt "\n", "\n\n\n" ttt "\n", 0); + assert_message_prettifying(ttt ttt "\n", "\n\n\n" ttt ttt "\n", 0); + assert_message_prettifying(ttt ttt ttt "\n", "\n\n\n" ttt ttt ttt "\n", 0); + assert_message_prettifying(ttt ttt ttt ttt "\n", "\n\n\n" ttt ttt ttt ttt "\n", 0); + assert_message_prettifying(ttt "\n", sss "\n" sss "\n" sss "\n" ttt "\n", 0); + assert_message_prettifying(ttt "\n", "\n" sss "\n" sss sss "\n" ttt "\n", 0); + assert_message_prettifying(ttt "\n", sss sss "\n" sss "\n\n" ttt "\n", 0); + assert_message_prettifying(ttt "\n", sss sss sss "\n\n\n" ttt "\n", 0); + assert_message_prettifying(ttt "\n", "\n" sss sss sss "\n\n" ttt "\n", 0); + assert_message_prettifying(ttt "\n", "\n\n" sss sss sss "\n" ttt "\n", 0); +} + +void test_object_message__consecutive_blank_lines_at_the_end_should_be_removed(void) +{ + assert_message_prettifying(ttt "\n", ttt "\n\n", 0); + assert_message_prettifying(ttt "\n", ttt "\n\n\n\n", 0); + assert_message_prettifying(ttt ttt "\n", ttt ttt "\n\n\n\n", 0); + assert_message_prettifying(ttt ttt ttt "\n", ttt ttt ttt "\n\n\n\n", 0); + assert_message_prettifying(ttt ttt ttt ttt "\n", ttt ttt ttt ttt "\n\n\n\n", 0); + assert_message_prettifying(ttt "\n", ttt "\n" sss "\n" sss "\n" sss "\n", 0); + assert_message_prettifying(ttt "\n", ttt "\n\n" sss "\n" sss sss "\n", 0); + assert_message_prettifying(ttt "\n", ttt "\n" sss sss "\n" sss "\n\n", 0); + assert_message_prettifying(ttt "\n", ttt "\n" sss sss sss "\n\n\n", 0); + assert_message_prettifying(ttt "\n", ttt "\n\n" sss sss sss "\n\n", 0); + assert_message_prettifying(ttt "\n", ttt "\n\n\n" sss sss sss "\n\n", 0); +} + +void test_object_message__text_without_newline_at_end_should_end_with_newline(void) +{ + assert_message_prettifying(ttt "\n", ttt, 0); + assert_message_prettifying(ttt ttt "\n", ttt ttt, 0); + assert_message_prettifying(ttt ttt ttt "\n", ttt ttt ttt, 0); + assert_message_prettifying(ttt ttt ttt ttt "\n", ttt ttt ttt ttt, 0); +} + +void test_object_message__text_plus_spaces_without_newline_should_not_show_spaces_and_end_with_newline(void) +{ + assert_message_prettifying(ttt "\n", ttt sss, 0); + assert_message_prettifying(ttt ttt "\n", ttt ttt sss, 0); + assert_message_prettifying(ttt ttt ttt "\n", ttt ttt ttt sss, 0); + assert_message_prettifying(ttt "\n", ttt sss sss, 0); + assert_message_prettifying(ttt ttt "\n", ttt ttt sss sss, 0); + assert_message_prettifying(ttt "\n", ttt sss sss sss, 0); +} + +void test_object_message__text_plus_spaces_ending_with_newline_should_be_cleaned_and_newline_must_remain(void){ + assert_message_prettifying(ttt "\n", ttt sss "\n", 0); + assert_message_prettifying(ttt "\n", ttt sss sss "\n", 0); + assert_message_prettifying(ttt "\n", ttt sss sss sss "\n", 0); + assert_message_prettifying(ttt ttt "\n", ttt ttt sss "\n", 0); + assert_message_prettifying(ttt ttt "\n", ttt ttt sss sss "\n", 0); + assert_message_prettifying(ttt ttt ttt "\n", ttt ttt ttt sss "\n", 0); +} + +void test_object_message__spaces_with_newline_at_end_should_be_replaced_with_empty_string(void) +{ + assert_message_prettifying("", sss "\n", 0); + assert_message_prettifying("", sss sss "\n", 0); + assert_message_prettifying("", sss sss sss "\n", 0); + assert_message_prettifying("", sss sss sss sss "\n", 0); +} + +void test_object_message__spaces_without_newline_at_end_should_be_replaced_with_empty_string(void) +{ + assert_message_prettifying("", "", 0); + assert_message_prettifying("", sss sss, 0); + assert_message_prettifying("", sss sss sss, 0); + assert_message_prettifying("", sss sss sss sss, 0); +} + +void test_object_message__consecutive_text_lines_should_be_unchanged(void) +{ + assert_message_prettifying(ttt ttt "\n" ttt "\n", ttt ttt "\n" ttt "\n", 0); + assert_message_prettifying(ttt "\n" ttt ttt "\n" ttt "\n", ttt "\n" ttt ttt "\n" ttt "\n", 0); + assert_message_prettifying(ttt "\n" ttt "\n" ttt "\n" ttt ttt "\n", ttt "\n" ttt "\n" ttt "\n" ttt ttt "\n", 0); + assert_message_prettifying(ttt "\n" ttt "\n\n" ttt ttt "\n" ttt "\n", ttt "\n" ttt "\n\n" ttt ttt "\n" ttt "\n", 0); + assert_message_prettifying(ttt ttt "\n\n" ttt "\n" ttt ttt "\n", ttt ttt "\n\n" ttt "\n" ttt ttt "\n", 0); + assert_message_prettifying(ttt "\n" ttt ttt "\n\n" ttt "\n", ttt "\n" ttt ttt "\n\n" ttt "\n", 0); +} + +void test_object_message__strip_comments(void) +{ + assert_message_prettifying("", "# comment", 1); + assert_message_prettifying("", "# comment\n", 1); + assert_message_prettifying("", "# comment \n", 1); + + assert_message_prettifying(ttt "\n", ttt "\n" "# comment\n", 1); + assert_message_prettifying(ttt "\n", "# comment\n" ttt "\n", 1); + assert_message_prettifying(ttt "\n" ttt "\n", ttt "\n" "# comment\n" ttt "\n", 1); +} + +void test_object_message__keep_comments(void) +{ + assert_message_prettifying("# comment\n", "# comment", 0); + assert_message_prettifying("# comment\n", "# comment\n", 0); + assert_message_prettifying("# comment\n", "# comment \n", 0); + + assert_message_prettifying(ttt "\n" "# comment\n", ttt "\n" "# comment\n", 0); + assert_message_prettifying("# comment\n" ttt "\n", "# comment\n" ttt "\n", 0); + assert_message_prettifying(ttt "\n" "# comment\n" ttt "\n", ttt "\n" "# comment\n" ttt "\n", 0); +} + +void test_object_message__message_prettify(void) +{ + char buffer[100]; + + cl_assert(git_message_prettify(buffer, sizeof(buffer), "", 0) == 1); + cl_assert_equal_s(buffer, ""); + cl_assert(git_message_prettify(buffer, sizeof(buffer), "", 1) == 1); + cl_assert_equal_s(buffer, ""); + + cl_assert_equal_i(7, git_message_prettify(buffer, sizeof(buffer), "Short", 0)); + cl_assert_equal_s("Short\n", buffer); + cl_assert_equal_i(7, git_message_prettify(buffer, sizeof(buffer), "Short", 1)); + cl_assert_equal_s("Short\n", buffer); + + cl_assert(git_message_prettify(buffer, sizeof(buffer), "This is longer\nAnd multiline\n# with some comments still in\n", 0) > 0); + cl_assert_equal_s(buffer, "This is longer\nAnd multiline\n# with some comments still in\n"); + + cl_assert(git_message_prettify(buffer, sizeof(buffer), "This is longer\nAnd multiline\n# with some comments still in\n", 1) > 0); + cl_assert_equal_s(buffer, "This is longer\nAnd multiline\n"); + + /* try out overflow */ + cl_assert(git_message_prettify(buffer, sizeof(buffer), + "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" + "1234567890" "1234567890" "1234567890" "1234567890" "12345678", + 0) > 0); + cl_assert_equal_s(buffer, + "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" + "1234567890" "1234567890" "1234567890" "1234567890" "12345678\n"); + + cl_assert(git_message_prettify(buffer, sizeof(buffer), + "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" + "1234567890" "1234567890" "1234567890" "1234567890" "12345678\n", + 0) > 0); + cl_assert_equal_s(buffer, + "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" + "1234567890" "1234567890" "1234567890" "1234567890" "12345678\n"); + + cl_git_fail(git_message_prettify(buffer, sizeof(buffer), + "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" + "1234567890" "1234567890" "1234567890" "1234567890" "123456789", + 0)); + cl_git_fail(git_message_prettify(buffer, sizeof(buffer), + "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" + "1234567890" "1234567890" "1234567890" "1234567890" "123456789\n", + 0)); + cl_git_fail(git_message_prettify(buffer, sizeof(buffer), + "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" + "1234567890" "1234567890" "1234567890" "1234567890" "1234567890", + 0)); + cl_git_fail(git_message_prettify(buffer, sizeof(buffer), + "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" + "1234567890" "1234567890" "1234567890" "1234567890" "1234567890""x", + 0)); + + cl_assert(git_message_prettify(buffer, sizeof(buffer), + "1234567890" "1234567890" "1234567890" "1234567890" "1234567890\n" + "# 1234567890" "1234567890" "1234567890" "1234567890" "1234567890\n" + "1234567890", + 1) > 0); + + cl_assert(git_message_prettify(NULL, 0, "", 0) == 1); + cl_assert(git_message_prettify(NULL, 0, "Short test", 0) == 12); + cl_assert(git_message_prettify(NULL, 0, "Test\n# with\nComments", 1) == 15); +} diff --git a/tests/object/peel.c b/tests/object/peel.c new file mode 100644 index 000000000..b6c9c7a3b --- /dev/null +++ b/tests/object/peel.c @@ -0,0 +1,105 @@ +#include "clar_libgit2.h" + +static git_repository *g_repo; + +void test_object_peel__initialize(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); +} + +void test_object_peel__cleanup(void) +{ + git_repository_free(g_repo); + g_repo = NULL; +} + +static void assert_peel( + const char *sha, + git_otype requested_type, + const char* expected_sha, + git_otype expected_type) +{ + git_oid oid, expected_oid; + git_object *obj; + git_object *peeled; + + cl_git_pass(git_oid_fromstr(&oid, sha)); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + + cl_git_pass(git_object_peel(&peeled, obj, requested_type)); + + cl_git_pass(git_oid_fromstr(&expected_oid, expected_sha)); + cl_assert_equal_i(0, git_oid_cmp(&expected_oid, git_object_id(peeled))); + + cl_assert_equal_i(expected_type, git_object_type(peeled)); + + git_object_free(peeled); + git_object_free(obj); +} + +static void assert_peel_error(int error, const char *sha, git_otype requested_type) +{ + git_oid oid; + git_object *obj; + git_object *peeled; + + cl_git_pass(git_oid_fromstr(&oid, sha)); + cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY)); + + cl_assert_equal_i(error, git_object_peel(&peeled, obj, requested_type)); + + git_object_free(obj); +} + +void test_object_peel__peeling_an_object_into_its_own_type_returns_another_instance_of_it(void) +{ + assert_peel("e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_COMMIT, + "e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_COMMIT); + assert_peel("7b4384978d2493e851f9cca7858815fac9b10980", GIT_OBJ_TAG, + "7b4384978d2493e851f9cca7858815fac9b10980", GIT_OBJ_TAG); + assert_peel("53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE, + "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE); + assert_peel("0266163a49e280c4f5ed1e08facd36a2bd716bcf", GIT_OBJ_BLOB, + "0266163a49e280c4f5ed1e08facd36a2bd716bcf", GIT_OBJ_BLOB); +} + +void test_object_peel__can_peel_a_tag(void) +{ + assert_peel("7b4384978d2493e851f9cca7858815fac9b10980", GIT_OBJ_COMMIT, + "e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_COMMIT); + assert_peel("7b4384978d2493e851f9cca7858815fac9b10980", GIT_OBJ_TREE, + "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE); +} + +void test_object_peel__can_peel_a_commit(void) +{ + assert_peel("e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_TREE, + "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE); +} + +void test_object_peel__cannot_peel_a_tree(void) +{ + assert_peel_error(GIT_EAMBIGUOUS, "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_BLOB); +} + +void test_object_peel__cannot_peel_a_blob(void) +{ + assert_peel_error(GIT_ENOTFOUND, "0266163a49e280c4f5ed1e08facd36a2bd716bcf", GIT_OBJ_COMMIT); +} + +void test_object_peel__target_any_object_for_type_change(void) +{ + /* tag to commit */ + assert_peel("7b4384978d2493e851f9cca7858815fac9b10980", GIT_OBJ_ANY, + "e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_COMMIT); + + /* commit to tree */ + assert_peel("e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_ANY, + "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE); + + /* fail to peel tree */ + assert_peel_error(GIT_EAMBIGUOUS, "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_ANY); + + /* fail to peel blob */ + assert_peel_error(GIT_ENOTFOUND, "0266163a49e280c4f5ed1e08facd36a2bd716bcf", GIT_OBJ_ANY); +} diff --git a/tests/object/raw/chars.c b/tests/object/raw/chars.c new file mode 100644 index 000000000..206bf7119 --- /dev/null +++ b/tests/object/raw/chars.c @@ -0,0 +1,41 @@ + +#include "clar_libgit2.h" + +#include "odb.h" + +void test_object_raw_chars__find_invalid_chars_in_oid(void) +{ + git_oid out; + unsigned char exp[] = { + 0x16, 0xa6, 0x77, 0x70, 0xb7, + 0xd8, 0xd7, 0x23, 0x17, 0xc4, + 0xb7, 0x75, 0x21, 0x3c, 0x23, + 0xa8, 0xbd, 0x74, 0xf5, 0xe0, + }; + char in[41] = "16a67770b7d8d72317c4b775213c23a8bd74f5e0"; + unsigned int i; + + for (i = 0; i < 256; i++) { + in[38] = (char)i; + if (git__fromhex(i) >= 0) { + exp[19] = (unsigned char)(git__fromhex(i) << 4); + cl_git_pass(git_oid_fromstr(&out, in)); + cl_assert(memcmp(out.id, exp, sizeof(out.id)) == 0); + } else { + cl_git_fail(git_oid_fromstr(&out, in)); + } + } +} + +void test_object_raw_chars__build_valid_oid_from_raw_bytes(void) +{ + git_oid out; + unsigned char exp[] = { + 0x16, 0xa6, 0x77, 0x70, 0xb7, + 0xd8, 0xd7, 0x23, 0x17, 0xc4, + 0xb7, 0x75, 0x21, 0x3c, 0x23, + 0xa8, 0xbd, 0x74, 0xf5, 0xe0, + }; + git_oid_fromraw(&out, exp); + cl_git_pass(memcmp(out.id, exp, sizeof(out.id))); +} diff --git a/tests/object/raw/compare.c b/tests/object/raw/compare.c new file mode 100644 index 000000000..1c9ce4b81 --- /dev/null +++ b/tests/object/raw/compare.c @@ -0,0 +1,124 @@ + +#include "clar_libgit2.h" + +#include "odb.h" + +void test_object_raw_compare__succeed_on_copy_oid(void) +{ + git_oid a, b; + unsigned char exp[] = { + 0x16, 0xa6, 0x77, 0x70, 0xb7, + 0xd8, 0xd7, 0x23, 0x17, 0xc4, + 0xb7, 0x75, 0x21, 0x3c, 0x23, + 0xa8, 0xbd, 0x74, 0xf5, 0xe0, + }; + memset(&b, 0, sizeof(b)); + git_oid_fromraw(&a, exp); + git_oid_cpy(&b, &a); + cl_git_pass(memcmp(a.id, exp, sizeof(a.id))); +} + +void test_object_raw_compare__succeed_on_oid_comparison_lesser(void) +{ + git_oid a, b; + unsigned char a_in[] = { + 0x16, 0xa6, 0x77, 0x70, 0xb7, + 0xd8, 0xd7, 0x23, 0x17, 0xc4, + 0xb7, 0x75, 0x21, 0x3c, 0x23, + 0xa8, 0xbd, 0x74, 0xf5, 0xe0, + }; + unsigned char b_in[] = { + 0x16, 0xa6, 0x77, 0x70, 0xb7, + 0xd8, 0xd7, 0x23, 0x17, 0xc4, + 0xb7, 0x75, 0x21, 0x3c, 0x23, + 0xa8, 0xbd, 0x74, 0xf5, 0xf0, + }; + git_oid_fromraw(&a, a_in); + git_oid_fromraw(&b, b_in); + cl_assert(git_oid_cmp(&a, &b) < 0); +} + +void test_object_raw_compare__succeed_on_oid_comparison_equal(void) +{ + git_oid a, b; + unsigned char a_in[] = { + 0x16, 0xa6, 0x77, 0x70, 0xb7, + 0xd8, 0xd7, 0x23, 0x17, 0xc4, + 0xb7, 0x75, 0x21, 0x3c, 0x23, + 0xa8, 0xbd, 0x74, 0xf5, 0xe0, + }; + git_oid_fromraw(&a, a_in); + git_oid_fromraw(&b, a_in); + cl_assert(git_oid_cmp(&a, &b) == 0); +} + +void test_object_raw_compare__succeed_on_oid_comparison_greater(void) +{ + git_oid a, b; + unsigned char a_in[] = { + 0x16, 0xa6, 0x77, 0x70, 0xb7, + 0xd8, 0xd7, 0x23, 0x17, 0xc4, + 0xb7, 0x75, 0x21, 0x3c, 0x23, + 0xa8, 0xbd, 0x74, 0xf5, 0xe0, + }; + unsigned char b_in[] = { + 0x16, 0xa6, 0x77, 0x70, 0xb7, + 0xd8, 0xd7, 0x23, 0x17, 0xc4, + 0xb7, 0x75, 0x21, 0x3c, 0x23, + 0xa8, 0xbd, 0x74, 0xf5, 0xd0, + }; + git_oid_fromraw(&a, a_in); + git_oid_fromraw(&b, b_in); + cl_assert(git_oid_cmp(&a, &b) > 0); +} + +void test_object_raw_compare__compare_fmt_oids(void) +{ + const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0"; + git_oid in; + char out[GIT_OID_HEXSZ + 1]; + + cl_git_pass(git_oid_fromstr(&in, exp)); + + /* Format doesn't touch the last byte */ + out[GIT_OID_HEXSZ] = 'Z'; + git_oid_fmt(out, &in); + cl_assert(out[GIT_OID_HEXSZ] == 'Z'); + + /* Format produced the right result */ + out[GIT_OID_HEXSZ] = '\0'; + cl_assert_equal_s(exp, out); +} + +void test_object_raw_compare__compare_allocfmt_oids(void) +{ + const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0"; + git_oid in; + char *out; + + cl_git_pass(git_oid_fromstr(&in, exp)); + + out = git_oid_allocfmt(&in); + cl_assert(out); + cl_assert_equal_s(exp, out); + git__free(out); +} + +void test_object_raw_compare__compare_pathfmt_oids(void) +{ + const char *exp1 = "16a0123456789abcdef4b775213c23a8bd74f5e0"; + const char *exp2 = "16/a0123456789abcdef4b775213c23a8bd74f5e0"; + git_oid in; + char out[GIT_OID_HEXSZ + 2]; + + cl_git_pass(git_oid_fromstr(&in, exp1)); + + /* Format doesn't touch the last byte */ + out[GIT_OID_HEXSZ + 1] = 'Z'; + git_oid_pathfmt(out, &in); + cl_assert(out[GIT_OID_HEXSZ + 1] == 'Z'); + + /* Format produced the right result */ + out[GIT_OID_HEXSZ + 1] = '\0'; + cl_assert_equal_s(exp2, out); +} diff --git a/tests/object/raw/convert.c b/tests/object/raw/convert.c new file mode 100644 index 000000000..88b1380a4 --- /dev/null +++ b/tests/object/raw/convert.c @@ -0,0 +1,112 @@ + +#include "clar_libgit2.h" + +#include "odb.h" + +void test_object_raw_convert__succeed_on_oid_to_string_conversion(void) +{ + const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0"; + git_oid in; + char out[GIT_OID_HEXSZ + 1]; + char *str; + int i; + + cl_git_pass(git_oid_fromstr(&in, exp)); + + /* NULL buffer pointer, returns static empty string */ + str = git_oid_tostr(NULL, sizeof(out), &in); + cl_assert(str && *str == '\0' && str != out); + + /* zero buffer size, returns static empty string */ + str = git_oid_tostr(out, 0, &in); + cl_assert(str && *str == '\0' && str != out); + + /* NULL oid pointer, sets existing buffer to empty string */ + str = git_oid_tostr(out, sizeof(out), NULL); + cl_assert(str && *str == '\0' && str == out); + + /* n == 1, returns out as an empty string */ + str = git_oid_tostr(out, 1, &in); + cl_assert(str && *str == '\0' && str == out); + + for (i = 1; i < GIT_OID_HEXSZ; i++) { + out[i+1] = 'Z'; + str = git_oid_tostr(out, i+1, &in); + /* returns out containing c-string */ + cl_assert(str && str == out); + /* must be '\0' terminated */ + cl_assert(*(str+i) == '\0'); + /* must not touch bytes past end of string */ + cl_assert(*(str+(i+1)) == 'Z'); + /* i == n-1 charaters of string */ + cl_git_pass(strncmp(exp, out, i)); + } + + /* returns out as hex formatted c-string */ + str = git_oid_tostr(out, sizeof(out), &in); + cl_assert(str && str == out && *(str+GIT_OID_HEXSZ) == '\0'); + cl_assert_equal_s(exp, out); +} + +void test_object_raw_convert__succeed_on_oid_to_string_conversion_big(void) +{ + const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0"; + git_oid in; + char big[GIT_OID_HEXSZ + 1 + 3]; /* note + 4 => big buffer */ + char *str; + + cl_git_pass(git_oid_fromstr(&in, exp)); + + /* place some tail material */ + big[GIT_OID_HEXSZ+0] = 'W'; /* should be '\0' afterwards */ + big[GIT_OID_HEXSZ+1] = 'X'; /* should remain untouched */ + big[GIT_OID_HEXSZ+2] = 'Y'; /* ditto */ + big[GIT_OID_HEXSZ+3] = 'Z'; /* ditto */ + + /* returns big as hex formatted c-string */ + str = git_oid_tostr(big, sizeof(big), &in); + cl_assert(str && str == big && *(str+GIT_OID_HEXSZ) == '\0'); + cl_assert_equal_s(exp, big); + + /* check tail material is untouched */ + cl_assert(str && str == big && *(str+GIT_OID_HEXSZ+1) == 'X'); + cl_assert(str && str == big && *(str+GIT_OID_HEXSZ+2) == 'Y'); + cl_assert(str && str == big && *(str+GIT_OID_HEXSZ+3) == 'Z'); +} + +static void check_partial_oid( + char *buffer, size_t count, const git_oid *oid, const char *expected) +{ + git_oid_nfmt(buffer, count, oid); + buffer[count] = '\0'; + cl_assert_equal_s(expected, buffer); +} + +void test_object_raw_convert__convert_oid_partially(void) +{ + const char *exp = "16a0123456789abcdef4b775213c23a8bd74f5e0"; + git_oid in; + char big[GIT_OID_HEXSZ + 1 + 3]; /* note + 4 => big buffer */ + + cl_git_pass(git_oid_fromstr(&in, exp)); + + git_oid_nfmt(big, sizeof(big), &in); + cl_assert_equal_s(exp, big); + + git_oid_nfmt(big, GIT_OID_HEXSZ + 1, &in); + cl_assert_equal_s(exp, big); + + check_partial_oid(big, 1, &in, "1"); + check_partial_oid(big, 2, &in, "16"); + check_partial_oid(big, 3, &in, "16a"); + check_partial_oid(big, 4, &in, "16a0"); + check_partial_oid(big, 5, &in, "16a01"); + + check_partial_oid(big, GIT_OID_HEXSZ, &in, exp); + check_partial_oid( + big, GIT_OID_HEXSZ - 1, &in, "16a0123456789abcdef4b775213c23a8bd74f5e"); + check_partial_oid( + big, GIT_OID_HEXSZ - 2, &in, "16a0123456789abcdef4b775213c23a8bd74f5"); + check_partial_oid( + big, GIT_OID_HEXSZ - 3, &in, "16a0123456789abcdef4b775213c23a8bd74f"); +} diff --git a/tests/object/raw/data.h b/tests/object/raw/data.h new file mode 100644 index 000000000..cf23819f1 --- /dev/null +++ b/tests/object/raw/data.h @@ -0,0 +1,323 @@ + +/* + * Raw data + */ +static unsigned char commit_data[] = { + 0x74, 0x72, 0x65, 0x65, 0x20, 0x64, 0x66, 0x66, + 0x32, 0x64, 0x61, 0x39, 0x30, 0x62, 0x32, 0x35, + 0x34, 0x65, 0x31, 0x62, 0x65, 0x62, 0x38, 0x38, + 0x39, 0x64, 0x31, 0x66, 0x31, 0x66, 0x31, 0x32, + 0x38, 0x38, 0x62, 0x65, 0x31, 0x38, 0x30, 0x33, + 0x37, 0x38, 0x32, 0x64, 0x66, 0x0a, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x20, 0x41, 0x20, 0x55, + 0x20, 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x3e, 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, + 0x31, 0x34, 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, + 0x30, 0x30, 0x30, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x72, 0x20, 0x43, 0x20, + 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72, + 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, + 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34, + 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30, + 0x30, 0x0a, 0x0a, 0x41, 0x20, 0x6f, 0x6e, 0x65, + 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x73, 0x75, 0x6d, + 0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x54, 0x68, + 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x6f, + 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, + 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72, + 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70, + 0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, + 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x0a, 0x53, 0x69, + 0x67, 0x6e, 0x65, 0x64, 0x2d, 0x6f, 0x66, 0x2d, + 0x62, 0x79, 0x3a, 0x20, 0x41, 0x20, 0x55, 0x20, + 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x3e, 0x0a, +}; + + +static unsigned char tree_data[] = { + 0x31, 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x6f, + 0x6e, 0x65, 0x00, 0x8b, 0x13, 0x78, 0x91, 0x79, + 0x1f, 0xe9, 0x69, 0x27, 0xad, 0x78, 0xe6, 0x4b, + 0x0a, 0xad, 0x7b, 0xde, 0xd0, 0x8b, 0xdc, 0x31, + 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x73, 0x6f, + 0x6d, 0x65, 0x00, 0xfd, 0x84, 0x30, 0xbc, 0x86, + 0x4c, 0xfc, 0xd5, 0xf1, 0x0e, 0x55, 0x90, 0xf8, + 0xa4, 0x47, 0xe0, 0x1b, 0x94, 0x2b, 0xfe, 0x31, + 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x74, 0x77, + 0x6f, 0x00, 0x78, 0x98, 0x19, 0x22, 0x61, 0x3b, + 0x2a, 0xfb, 0x60, 0x25, 0x04, 0x2f, 0xf6, 0xbd, + 0x87, 0x8a, 0xc1, 0x99, 0x4e, 0x85, 0x31, 0x30, + 0x30, 0x36, 0x34, 0x34, 0x20, 0x7a, 0x65, 0x72, + 0x6f, 0x00, 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, + 0xd6, 0x43, 0x4b, 0x8b, 0x29, 0xae, 0x77, 0x5a, + 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91, +}; + +static unsigned char tag_data[] = { + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x33, + 0x64, 0x37, 0x66, 0x38, 0x61, 0x36, 0x61, 0x66, + 0x30, 0x37, 0x36, 0x63, 0x38, 0x63, 0x33, 0x66, + 0x32, 0x30, 0x30, 0x37, 0x31, 0x61, 0x38, 0x39, + 0x33, 0x35, 0x63, 0x64, 0x62, 0x65, 0x38, 0x32, + 0x32, 0x38, 0x35, 0x39, 0x34, 0x64, 0x31, 0x0a, + 0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x0a, 0x74, 0x61, 0x67, 0x20, + 0x76, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0a, 0x74, + 0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x43, 0x20, + 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72, + 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, + 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34, + 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30, + 0x30, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, + 0x61, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x30, + 0x2e, 0x30, 0x2e, 0x31, 0x0a, +}; + +/* + * Dummy data + */ +static unsigned char zero_data[] = { + 0x00, +}; + +static unsigned char one_data[] = { + 0x0a, +}; + +static unsigned char two_data[] = { + 0x61, 0x0a, +}; + +static unsigned char some_data[] = { + 0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, + 0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, + 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, + 0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, + 0x6e, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69, + 0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, + 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0a, + 0x20, 0x2a, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e, + 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, + 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, + 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x2a, 0x20, 0x61, + 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, + 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, + 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x2a, 0x0a, + 0x20, 0x2a, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, + 0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x20, 0x2a, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, + 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x6c, + 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x70, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e, + 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20, + 0x2a, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, + 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69, + 0x6e, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x62, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74, + 0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x67, + 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0a, 0x20, 0x2a, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, + 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, + 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x2a, + 0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20, + 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x2e, 0x20, 0x20, 0x28, 0x54, 0x68, 0x65, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, + 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, + 0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, + 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, + 0x64, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79, + 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65, + 0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, + 0x74, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, + 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x0a, 0x20, 0x2a, 0x20, 0x6d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65, + 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x0a, 0x20, + 0x2a, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62, + 0x69, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, + 0x29, 0x0a, 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, + 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, + 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, + 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74, + 0x0a, 0x20, 0x2a, 0x20, 0x57, 0x49, 0x54, 0x48, + 0x4f, 0x55, 0x54, 0x20, 0x41, 0x4e, 0x59, 0x20, + 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59, + 0x3b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, + 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69, + 0x65, 0x64, 0x20, 0x77, 0x61, 0x72, 0x72, 0x61, + 0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x0a, 0x20, + 0x2a, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41, + 0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, + 0x59, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x49, 0x54, + 0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52, + 0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49, + 0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55, + 0x52, 0x50, 0x4f, 0x53, 0x45, 0x2e, 0x20, 0x20, + 0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x47, 0x4e, 0x55, 0x0a, 0x20, 0x2a, 0x20, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, + 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x64, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a, + 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x59, 0x6f, + 0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, + 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x72, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, + 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, + 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, + 0x20, 0x2a, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, + 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, + 0x61, 0x6d, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x20, 0x43, 0x4f, 0x50, 0x59, 0x49, 0x4e, 0x47, + 0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, + 0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, + 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x2a, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, + 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, + 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x35, 0x31, 0x20, + 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x6c, 0x69, 0x6e, + 0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2c, + 0x20, 0x46, 0x69, 0x66, 0x74, 0x68, 0x20, 0x46, + 0x6c, 0x6f, 0x6f, 0x72, 0x2c, 0x0a, 0x20, 0x2a, + 0x20, 0x42, 0x6f, 0x73, 0x74, 0x6f, 0x6e, 0x2c, + 0x20, 0x4d, 0x41, 0x20, 0x30, 0x32, 0x31, 0x31, + 0x30, 0x2d, 0x31, 0x33, 0x30, 0x31, 0x2c, 0x20, + 0x55, 0x53, 0x41, 0x2e, 0x0a, 0x20, 0x2a, 0x2f, + 0x0a, +}; + +/* + * SHA1 Hashes + */ +static char *commit_id = "3d7f8a6af076c8c3f20071a8935cdbe8228594d1"; +static char *tree_id = "dff2da90b254e1beb889d1f1f1288be1803782df"; +static char *tag_id = "09d373e1dfdc16b129ceec6dd649739911541e05"; +static char *zero_id = "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"; +static char *one_id = "8b137891791fe96927ad78e64b0aad7bded08bdc"; +static char *two_id = "78981922613b2afb6025042ff6bd878ac1994e85"; +static char *some_id = "fd8430bc864cfcd5f10e5590f8a447e01b942bfe"; + +/* + * In-memory objects + */ +static git_rawobj tree_obj = { + tree_data, + sizeof(tree_data), + GIT_OBJ_TREE +}; + +static git_rawobj tag_obj = { + tag_data, + sizeof(tag_data), + GIT_OBJ_TAG +}; + +static git_rawobj zero_obj = { + zero_data, + 0, + GIT_OBJ_BLOB +}; + +static git_rawobj one_obj = { + one_data, + sizeof(one_data), + GIT_OBJ_BLOB +}; + +static git_rawobj two_obj = { + two_data, + sizeof(two_data), + GIT_OBJ_BLOB +}; + +static git_rawobj commit_obj = { + commit_data, + sizeof(commit_data), + GIT_OBJ_COMMIT +}; + +static git_rawobj some_obj = { + some_data, + sizeof(some_data), + GIT_OBJ_BLOB +}; + +static git_rawobj junk_obj = { + NULL, + 0, + GIT_OBJ_BAD +}; diff --git a/tests/object/raw/fromstr.c b/tests/object/raw/fromstr.c new file mode 100644 index 000000000..8c11c105f --- /dev/null +++ b/tests/object/raw/fromstr.c @@ -0,0 +1,30 @@ + +#include "clar_libgit2.h" + +#include "odb.h" + +void test_object_raw_fromstr__fail_on_invalid_oid_string(void) +{ + git_oid out; + cl_git_fail(git_oid_fromstr(&out, "")); + cl_git_fail(git_oid_fromstr(&out, "moo")); + cl_git_fail(git_oid_fromstr(&out, "16a67770b7d8d72317c4b775213c23a8bd74f5ez")); +} + +void test_object_raw_fromstr__succeed_on_valid_oid_string(void) +{ + git_oid out; + unsigned char exp[] = { + 0x16, 0xa6, 0x77, 0x70, 0xb7, + 0xd8, 0xd7, 0x23, 0x17, 0xc4, + 0xb7, 0x75, 0x21, 0x3c, 0x23, + 0xa8, 0xbd, 0x74, 0xf5, 0xe0, + }; + + cl_git_pass(git_oid_fromstr(&out, "16a67770b7d8d72317c4b775213c23a8bd74f5e0")); + cl_git_pass(memcmp(out.id, exp, sizeof(out.id))); + + cl_git_pass(git_oid_fromstr(&out, "16A67770B7D8D72317C4b775213C23A8BD74F5E0")); + cl_git_pass(memcmp(out.id, exp, sizeof(out.id))); + +} diff --git a/tests/object/raw/hash.c b/tests/object/raw/hash.c new file mode 100644 index 000000000..ede31e145 --- /dev/null +++ b/tests/object/raw/hash.c @@ -0,0 +1,166 @@ + +#include "clar_libgit2.h" + +#include "odb.h" +#include "hash.h" + +#include "data.h" + +static void hash_object_pass(git_oid *oid, git_rawobj *obj) +{ + cl_git_pass(git_odb_hash(oid, obj->data, obj->len, obj->type)); +} +static void hash_object_fail(git_oid *oid, git_rawobj *obj) +{ + cl_git_fail(git_odb_hash(oid, obj->data, obj->len, obj->type)); +} + +static char *hello_id = "22596363b3de40b06f981fb85d82312e8c0ed511"; +static char *hello_text = "hello world\n"; + +static char *bye_id = "ce08fe4884650f067bd5703b6a59a8b3b3c99a09"; +static char *bye_text = "bye world\n"; + +void test_object_raw_hash__hash_by_blocks(void) +{ + git_hash_ctx ctx; + git_oid id1, id2; + + cl_git_pass(git_hash_ctx_init(&ctx)); + + /* should already be init'd */ + cl_git_pass(git_hash_update(&ctx, hello_text, strlen(hello_text))); + cl_git_pass(git_hash_final(&id2, &ctx)); + cl_git_pass(git_oid_fromstr(&id1, hello_id)); + cl_assert(git_oid_cmp(&id1, &id2) == 0); + + /* reinit should permit reuse */ + cl_git_pass(git_hash_init(&ctx)); + cl_git_pass(git_hash_update(&ctx, bye_text, strlen(bye_text))); + cl_git_pass(git_hash_final(&id2, &ctx)); + cl_git_pass(git_oid_fromstr(&id1, bye_id)); + cl_assert(git_oid_cmp(&id1, &id2) == 0); + + git_hash_ctx_cleanup(&ctx); +} + +void test_object_raw_hash__hash_buffer_in_single_call(void) +{ + git_oid id1, id2; + + cl_git_pass(git_oid_fromstr(&id1, hello_id)); + git_hash_buf(&id2, hello_text, strlen(hello_text)); + cl_assert(git_oid_cmp(&id1, &id2) == 0); +} + +void test_object_raw_hash__hash_vector(void) +{ + git_oid id1, id2; + git_buf_vec vec[2]; + + cl_git_pass(git_oid_fromstr(&id1, hello_id)); + + vec[0].data = hello_text; + vec[0].len = 4; + vec[1].data = hello_text+4; + vec[1].len = strlen(hello_text)-4; + + git_hash_vec(&id2, vec, 2); + + cl_assert(git_oid_cmp(&id1, &id2) == 0); +} + +void test_object_raw_hash__hash_junk_data(void) +{ + git_oid id, id_zero; + + cl_git_pass(git_oid_fromstr(&id_zero, zero_id)); + + /* invalid types: */ + junk_obj.data = some_data; + hash_object_fail(&id, &junk_obj); + + junk_obj.type = GIT_OBJ__EXT1; + hash_object_fail(&id, &junk_obj); + + junk_obj.type = GIT_OBJ__EXT2; + hash_object_fail(&id, &junk_obj); + + junk_obj.type = GIT_OBJ_OFS_DELTA; + hash_object_fail(&id, &junk_obj); + + junk_obj.type = GIT_OBJ_REF_DELTA; + hash_object_fail(&id, &junk_obj); + + /* data can be NULL only if len is zero: */ + junk_obj.type = GIT_OBJ_BLOB; + junk_obj.data = NULL; + hash_object_pass(&id, &junk_obj); + cl_assert(git_oid_cmp(&id, &id_zero) == 0); + + junk_obj.len = 1; + hash_object_fail(&id, &junk_obj); +} + +void test_object_raw_hash__hash_commit_object(void) +{ + git_oid id1, id2; + + cl_git_pass(git_oid_fromstr(&id1, commit_id)); + hash_object_pass(&id2, &commit_obj); + cl_assert(git_oid_cmp(&id1, &id2) == 0); +} + +void test_object_raw_hash__hash_tree_object(void) +{ + git_oid id1, id2; + + cl_git_pass(git_oid_fromstr(&id1, tree_id)); + hash_object_pass(&id2, &tree_obj); + cl_assert(git_oid_cmp(&id1, &id2) == 0); +} + +void test_object_raw_hash__hash_tag_object(void) +{ + git_oid id1, id2; + + cl_git_pass(git_oid_fromstr(&id1, tag_id)); + hash_object_pass(&id2, &tag_obj); + cl_assert(git_oid_cmp(&id1, &id2) == 0); +} + +void test_object_raw_hash__hash_zero_length_object(void) +{ + git_oid id1, id2; + + cl_git_pass(git_oid_fromstr(&id1, zero_id)); + hash_object_pass(&id2, &zero_obj); + cl_assert(git_oid_cmp(&id1, &id2) == 0); +} + +void test_object_raw_hash__hash_one_byte_object(void) +{ + git_oid id1, id2; + + cl_git_pass(git_oid_fromstr(&id1, one_id)); + hash_object_pass(&id2, &one_obj); + cl_assert(git_oid_cmp(&id1, &id2) == 0); +} + +void test_object_raw_hash__hash_two_byte_object(void) +{ + git_oid id1, id2; + + cl_git_pass(git_oid_fromstr(&id1, two_id)); + hash_object_pass(&id2, &two_obj); + cl_assert(git_oid_cmp(&id1, &id2) == 0); +} + +void test_object_raw_hash__hash_multi_byte_object(void) +{ + git_oid id1, id2; + + cl_git_pass(git_oid_fromstr(&id1, some_id)); + hash_object_pass(&id2, &some_obj); + cl_assert(git_oid_cmp(&id1, &id2) == 0); +} diff --git a/tests/object/raw/short.c b/tests/object/raw/short.c new file mode 100644 index 000000000..813cd86b6 --- /dev/null +++ b/tests/object/raw/short.c @@ -0,0 +1,137 @@ + +#include "clar_libgit2.h" + +#include "odb.h" +#include "hash.h" + +void test_object_raw_short__oid_shortener_no_duplicates(void) +{ + git_oid_shorten *os; + int min_len; + + os = git_oid_shorten_new(0); + cl_assert(os != NULL); + + git_oid_shorten_add(os, "22596363b3de40b06f981fb85d82312e8c0ed511"); + git_oid_shorten_add(os, "ce08fe4884650f067bd5703b6a59a8b3b3c99a09"); + git_oid_shorten_add(os, "16a0123456789abcdef4b775213c23a8bd74f5e0"); + min_len = git_oid_shorten_add(os, "ce08fe4884650f067bd5703b6a59a8b3b3c99a09"); + + cl_assert(min_len == GIT_OID_HEXSZ + 1); + + git_oid_shorten_free(os); +} + +static int insert_sequential_oids( + char ***out, git_oid_shorten *os, int n, int fail) +{ + int i, min_len = 0; + char numbuf[16]; + git_oid oid; + char **oids = git__calloc(n, sizeof(char *)); + cl_assert(oids != NULL); + + for (i = 0; i < n; ++i) { + p_snprintf(numbuf, sizeof(numbuf), "%u", (unsigned int)i); + git_hash_buf(&oid, numbuf, strlen(numbuf)); + + oids[i] = git__malloc(GIT_OID_HEXSZ + 1); + cl_assert(oids[i]); + git_oid_nfmt(oids[i], GIT_OID_HEXSZ + 1, &oid); + + min_len = git_oid_shorten_add(os, oids[i]); + + /* After "fail", we expect git_oid_shorten_add to fail */ + if (fail >= 0 && i >= fail) + cl_assert(min_len < 0); + else + cl_assert(min_len >= 0); + } + + *out = oids; + + return min_len; +} + +static void free_oids(int n, char **oids) +{ + int i; + + for (i = 0; i < n; ++i) { + git__free(oids[i]); + } + git__free(oids); +} + +void test_object_raw_short__oid_shortener_stresstest_git_oid_shorten(void) +{ +#define MAX_OIDS 1000 + + git_oid_shorten *os; + size_t i, j; + int min_len = 0, found_collision; + char **oids; + + os = git_oid_shorten_new(0); + cl_assert(os != NULL); + + /* + * Insert in the shortener 1000 unique SHA1 ids + */ + min_len = insert_sequential_oids(&oids, os, MAX_OIDS, MAX_OIDS); + cl_assert(min_len > 0); + + /* + * Compare the first `min_char - 1` characters of each + * SHA1 OID. If the minimizer worked, we should find at + * least one collision + */ + found_collision = 0; + for (i = 0; i < MAX_OIDS; ++i) { + for (j = i + 1; j < MAX_OIDS; ++j) { + if (memcmp(oids[i], oids[j], min_len - 1) == 0) + found_collision = 1; + } + } + cl_assert_equal_b(true, found_collision); + + /* + * Compare the first `min_char` characters of each + * SHA1 OID. If the minimizer worked, every single preffix + * should be unique. + */ + found_collision = 0; + for (i = 0; i < MAX_OIDS; ++i) { + for (j = i + 1; j < MAX_OIDS; ++j) { + if (memcmp(oids[i], oids[j], min_len) == 0) + found_collision = 1; + } + } + cl_assert_equal_b(false, found_collision); + + /* cleanup */ + free_oids(MAX_OIDS, oids); + git_oid_shorten_free(os); + +#undef MAX_OIDS +} + +void test_object_raw_short__oid_shortener_too_much_oids(void) +{ + /* The magic number of oids at which an oid_shortener will fail. + * This was experimentally established. */ +#define MAX_OIDS 24556 + + git_oid_shorten *os; + char **oids; + + os = git_oid_shorten_new(0); + cl_assert(os != NULL); + + cl_assert(insert_sequential_oids(&oids, os, MAX_OIDS, MAX_OIDS - 1) < 0); + + free_oids(MAX_OIDS, oids); + git_oid_shorten_free(os); + +#undef MAX_OIDS +} diff --git a/tests/object/raw/size.c b/tests/object/raw/size.c new file mode 100644 index 000000000..930c6de23 --- /dev/null +++ b/tests/object/raw/size.c @@ -0,0 +1,13 @@ + +#include "clar_libgit2.h" + +#include "odb.h" + +void test_object_raw_size__validate_oid_size(void) +{ + git_oid out; + cl_assert(20 == GIT_OID_RAWSZ); + cl_assert(40 == GIT_OID_HEXSZ); + cl_assert(sizeof(out) == GIT_OID_RAWSZ); + cl_assert(sizeof(out.id) == GIT_OID_RAWSZ); +} diff --git a/tests/object/raw/type2string.c b/tests/object/raw/type2string.c new file mode 100644 index 000000000..a3585487f --- /dev/null +++ b/tests/object/raw/type2string.c @@ -0,0 +1,54 @@ + +#include "clar_libgit2.h" + +#include "odb.h" +#include "hash.h" + +void test_object_raw_type2string__convert_type_to_string(void) +{ + cl_assert_equal_s(git_object_type2string(GIT_OBJ_BAD), ""); + cl_assert_equal_s(git_object_type2string(GIT_OBJ__EXT1), ""); + cl_assert_equal_s(git_object_type2string(GIT_OBJ_COMMIT), "commit"); + cl_assert_equal_s(git_object_type2string(GIT_OBJ_TREE), "tree"); + cl_assert_equal_s(git_object_type2string(GIT_OBJ_BLOB), "blob"); + cl_assert_equal_s(git_object_type2string(GIT_OBJ_TAG), "tag"); + cl_assert_equal_s(git_object_type2string(GIT_OBJ__EXT2), ""); + cl_assert_equal_s(git_object_type2string(GIT_OBJ_OFS_DELTA), "OFS_DELTA"); + cl_assert_equal_s(git_object_type2string(GIT_OBJ_REF_DELTA), "REF_DELTA"); + + cl_assert_equal_s(git_object_type2string(-2), ""); + cl_assert_equal_s(git_object_type2string(8), ""); + cl_assert_equal_s(git_object_type2string(1234), ""); +} + +void test_object_raw_type2string__convert_string_to_type(void) +{ + cl_assert(git_object_string2type(NULL) == GIT_OBJ_BAD); + cl_assert(git_object_string2type("") == GIT_OBJ_BAD); + cl_assert(git_object_string2type("commit") == GIT_OBJ_COMMIT); + cl_assert(git_object_string2type("tree") == GIT_OBJ_TREE); + cl_assert(git_object_string2type("blob") == GIT_OBJ_BLOB); + cl_assert(git_object_string2type("tag") == GIT_OBJ_TAG); + cl_assert(git_object_string2type("OFS_DELTA") == GIT_OBJ_OFS_DELTA); + cl_assert(git_object_string2type("REF_DELTA") == GIT_OBJ_REF_DELTA); + + cl_assert(git_object_string2type("CoMmIt") == GIT_OBJ_BAD); + cl_assert(git_object_string2type("hohoho") == GIT_OBJ_BAD); +} + +void test_object_raw_type2string__check_type_is_loose(void) +{ + cl_assert(git_object_typeisloose(GIT_OBJ_BAD) == 0); + cl_assert(git_object_typeisloose(GIT_OBJ__EXT1) == 0); + cl_assert(git_object_typeisloose(GIT_OBJ_COMMIT) == 1); + cl_assert(git_object_typeisloose(GIT_OBJ_TREE) == 1); + cl_assert(git_object_typeisloose(GIT_OBJ_BLOB) == 1); + cl_assert(git_object_typeisloose(GIT_OBJ_TAG) == 1); + cl_assert(git_object_typeisloose(GIT_OBJ__EXT2) == 0); + cl_assert(git_object_typeisloose(GIT_OBJ_OFS_DELTA) == 0); + cl_assert(git_object_typeisloose(GIT_OBJ_REF_DELTA) == 0); + + cl_assert(git_object_typeisloose(-2) == 0); + cl_assert(git_object_typeisloose(8) == 0); + cl_assert(git_object_typeisloose(1234) == 0); +} diff --git a/tests/object/raw/write.c b/tests/object/raw/write.c new file mode 100644 index 000000000..273f08f2c --- /dev/null +++ b/tests/object/raw/write.c @@ -0,0 +1,462 @@ +#include "clar_libgit2.h" +#include "git2/odb_backend.h" + +#include "fileops.h" +#include "odb.h" + +typedef struct object_data { + char *id; /* object id (sha1) */ + char *dir; /* object store (fan-out) directory name */ + char *file; /* object store filename */ +} object_data; + +static const char *odb_dir = "test-objects"; + +void test_body(object_data *d, git_rawobj *o); + + + +// Helpers +static void remove_object_files(object_data *d) +{ + cl_git_pass(p_unlink(d->file)); + cl_git_pass(p_rmdir(d->dir)); + cl_assert(errno != ENOTEMPTY); + cl_git_pass(p_rmdir(odb_dir) < 0); +} + +static void streaming_write(git_oid *oid, git_odb *odb, git_rawobj *raw) +{ + git_odb_stream *stream; + int error; + + cl_git_pass(git_odb_open_wstream(&stream, odb, raw->len, raw->type)); + git_odb_stream_write(stream, raw->data, raw->len); + error = git_odb_stream_finalize_write(oid, stream); + git_odb_stream_free(stream); + cl_git_pass(error); +} + +static void check_object_files(object_data *d) +{ + cl_assert(git_path_exists(d->dir)); + cl_assert(git_path_exists(d->file)); +} + +static void cmp_objects(git_rawobj *o1, git_rawobj *o2) +{ + cl_assert(o1->type == o2->type); + cl_assert(o1->len == o2->len); + if (o1->len > 0) + cl_assert(memcmp(o1->data, o2->data, o1->len) == 0); +} + +static void make_odb_dir(void) +{ + cl_git_pass(p_mkdir(odb_dir, GIT_OBJECT_DIR_MODE)); +} + + +// Standard test form +void test_body(object_data *d, git_rawobj *o) +{ + git_odb *db; + git_oid id1, id2; + git_odb_object *obj; + git_rawobj tmp; + + make_odb_dir(); + cl_git_pass(git_odb_open(&db, odb_dir)); + cl_git_pass(git_oid_fromstr(&id1, d->id)); + + streaming_write(&id2, db, o); + cl_assert(git_oid_cmp(&id1, &id2) == 0); + check_object_files(d); + + cl_git_pass(git_odb_read(&obj, db, &id1)); + + tmp.data = obj->buffer; + tmp.len = obj->cached.size; + tmp.type = obj->cached.type; + + cmp_objects(&tmp, o); + + git_odb_object_free(obj); + git_odb_free(db); + remove_object_files(d); +} + + +void test_object_raw_write__loose_object(void) +{ + object_data commit = { + "3d7f8a6af076c8c3f20071a8935cdbe8228594d1", + "test-objects/3d", + "test-objects/3d/7f8a6af076c8c3f20071a8935cdbe8228594d1", + }; + + unsigned char commit_data[] = { + 0x74, 0x72, 0x65, 0x65, 0x20, 0x64, 0x66, 0x66, + 0x32, 0x64, 0x61, 0x39, 0x30, 0x62, 0x32, 0x35, + 0x34, 0x65, 0x31, 0x62, 0x65, 0x62, 0x38, 0x38, + 0x39, 0x64, 0x31, 0x66, 0x31, 0x66, 0x31, 0x32, + 0x38, 0x38, 0x62, 0x65, 0x31, 0x38, 0x30, 0x33, + 0x37, 0x38, 0x32, 0x64, 0x66, 0x0a, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x20, 0x41, 0x20, 0x55, + 0x20, 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x3e, 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, + 0x31, 0x34, 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, + 0x30, 0x30, 0x30, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x72, 0x20, 0x43, 0x20, + 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72, + 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, + 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34, + 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30, + 0x30, 0x0a, 0x0a, 0x41, 0x20, 0x6f, 0x6e, 0x65, + 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x73, 0x75, 0x6d, + 0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x54, 0x68, + 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x6f, + 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, + 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72, + 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70, + 0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, + 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x0a, 0x53, 0x69, + 0x67, 0x6e, 0x65, 0x64, 0x2d, 0x6f, 0x66, 0x2d, + 0x62, 0x79, 0x3a, 0x20, 0x41, 0x20, 0x55, 0x20, + 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x3e, 0x0a, + }; + + git_rawobj commit_obj = { + commit_data, + sizeof(commit_data), + GIT_OBJ_COMMIT + }; + + test_body(&commit, &commit_obj); +} + +void test_object_raw_write__loose_tree(void) +{ + static object_data tree = { + "dff2da90b254e1beb889d1f1f1288be1803782df", + "test-objects/df", + "test-objects/df/f2da90b254e1beb889d1f1f1288be1803782df", + }; + + static unsigned char tree_data[] = { + 0x31, 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x6f, + 0x6e, 0x65, 0x00, 0x8b, 0x13, 0x78, 0x91, 0x79, + 0x1f, 0xe9, 0x69, 0x27, 0xad, 0x78, 0xe6, 0x4b, + 0x0a, 0xad, 0x7b, 0xde, 0xd0, 0x8b, 0xdc, 0x31, + 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x73, 0x6f, + 0x6d, 0x65, 0x00, 0xfd, 0x84, 0x30, 0xbc, 0x86, + 0x4c, 0xfc, 0xd5, 0xf1, 0x0e, 0x55, 0x90, 0xf8, + 0xa4, 0x47, 0xe0, 0x1b, 0x94, 0x2b, 0xfe, 0x31, + 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x74, 0x77, + 0x6f, 0x00, 0x78, 0x98, 0x19, 0x22, 0x61, 0x3b, + 0x2a, 0xfb, 0x60, 0x25, 0x04, 0x2f, 0xf6, 0xbd, + 0x87, 0x8a, 0xc1, 0x99, 0x4e, 0x85, 0x31, 0x30, + 0x30, 0x36, 0x34, 0x34, 0x20, 0x7a, 0x65, 0x72, + 0x6f, 0x00, 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, + 0xd6, 0x43, 0x4b, 0x8b, 0x29, 0xae, 0x77, 0x5a, + 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91, + }; + + static git_rawobj tree_obj = { + tree_data, + sizeof(tree_data), + GIT_OBJ_TREE + }; + + test_body(&tree, &tree_obj); +} + +void test_object_raw_write__loose_tag(void) +{ + static object_data tag = { + "09d373e1dfdc16b129ceec6dd649739911541e05", + "test-objects/09", + "test-objects/09/d373e1dfdc16b129ceec6dd649739911541e05", + }; + + static unsigned char tag_data[] = { + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x33, + 0x64, 0x37, 0x66, 0x38, 0x61, 0x36, 0x61, 0x66, + 0x30, 0x37, 0x36, 0x63, 0x38, 0x63, 0x33, 0x66, + 0x32, 0x30, 0x30, 0x37, 0x31, 0x61, 0x38, 0x39, + 0x33, 0x35, 0x63, 0x64, 0x62, 0x65, 0x38, 0x32, + 0x32, 0x38, 0x35, 0x39, 0x34, 0x64, 0x31, 0x0a, + 0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x0a, 0x74, 0x61, 0x67, 0x20, + 0x76, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0a, 0x74, + 0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x43, 0x20, + 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72, + 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, + 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34, + 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30, + 0x30, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, + 0x61, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x30, + 0x2e, 0x30, 0x2e, 0x31, 0x0a, + }; + + static git_rawobj tag_obj = { + tag_data, + sizeof(tag_data), + GIT_OBJ_TAG + }; + + + test_body(&tag, &tag_obj); +} + +void test_object_raw_write__zero_length(void) +{ + static object_data zero = { + "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "test-objects/e6", + "test-objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391", + }; + + static unsigned char zero_data[] = { + 0x00 /* dummy data */ + }; + + static git_rawobj zero_obj = { + zero_data, + 0, + GIT_OBJ_BLOB + }; + + test_body(&zero, &zero_obj); +} + +void test_object_raw_write__one_byte(void) +{ + static object_data one = { + "8b137891791fe96927ad78e64b0aad7bded08bdc", + "test-objects/8b", + "test-objects/8b/137891791fe96927ad78e64b0aad7bded08bdc", + }; + + static unsigned char one_data[] = { + 0x0a, + }; + + static git_rawobj one_obj = { + one_data, + sizeof(one_data), + GIT_OBJ_BLOB + }; + + test_body(&one, &one_obj); +} + +void test_object_raw_write__two_byte(void) +{ + static object_data two = { + "78981922613b2afb6025042ff6bd878ac1994e85", + "test-objects/78", + "test-objects/78/981922613b2afb6025042ff6bd878ac1994e85", + }; + + static unsigned char two_data[] = { + 0x61, 0x0a, + }; + + static git_rawobj two_obj = { + two_data, + sizeof(two_data), + GIT_OBJ_BLOB + }; + + test_body(&two, &two_obj); +} + +void test_object_raw_write__several_bytes(void) +{ + static object_data some = { + "fd8430bc864cfcd5f10e5590f8a447e01b942bfe", + "test-objects/fd", + "test-objects/fd/8430bc864cfcd5f10e5590f8a447e01b942bfe", + }; + + static unsigned char some_data[] = { + 0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, + 0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, + 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, + 0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, + 0x6e, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69, + 0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, + 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0a, + 0x20, 0x2a, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e, + 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, + 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, + 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x2a, 0x20, 0x61, + 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, + 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, + 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x2a, 0x0a, + 0x20, 0x2a, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, + 0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x20, 0x2a, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, + 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x6c, + 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x70, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e, + 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20, + 0x2a, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, + 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69, + 0x6e, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x62, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74, + 0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x67, + 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0a, 0x20, 0x2a, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, + 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, + 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x2a, + 0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20, + 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x2e, 0x20, 0x20, 0x28, 0x54, 0x68, 0x65, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, + 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, + 0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, + 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, + 0x64, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79, + 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65, + 0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, + 0x74, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, + 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x0a, 0x20, 0x2a, 0x20, 0x6d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65, + 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x0a, 0x20, + 0x2a, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62, + 0x69, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, + 0x29, 0x0a, 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, + 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, + 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, + 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74, + 0x0a, 0x20, 0x2a, 0x20, 0x57, 0x49, 0x54, 0x48, + 0x4f, 0x55, 0x54, 0x20, 0x41, 0x4e, 0x59, 0x20, + 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59, + 0x3b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, + 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69, + 0x65, 0x64, 0x20, 0x77, 0x61, 0x72, 0x72, 0x61, + 0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x0a, 0x20, + 0x2a, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41, + 0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, + 0x59, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x49, 0x54, + 0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52, + 0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49, + 0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55, + 0x52, 0x50, 0x4f, 0x53, 0x45, 0x2e, 0x20, 0x20, + 0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x47, 0x4e, 0x55, 0x0a, 0x20, 0x2a, 0x20, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, + 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x64, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a, + 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x59, 0x6f, + 0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, + 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x72, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, + 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, + 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, + 0x20, 0x2a, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, + 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, + 0x61, 0x6d, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x20, 0x43, 0x4f, 0x50, 0x59, 0x49, 0x4e, 0x47, + 0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, + 0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, + 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x2a, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, + 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, + 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x35, 0x31, 0x20, + 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x6c, 0x69, 0x6e, + 0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2c, + 0x20, 0x46, 0x69, 0x66, 0x74, 0x68, 0x20, 0x46, + 0x6c, 0x6f, 0x6f, 0x72, 0x2c, 0x0a, 0x20, 0x2a, + 0x20, 0x42, 0x6f, 0x73, 0x74, 0x6f, 0x6e, 0x2c, + 0x20, 0x4d, 0x41, 0x20, 0x30, 0x32, 0x31, 0x31, + 0x30, 0x2d, 0x31, 0x33, 0x30, 0x31, 0x2c, 0x20, + 0x55, 0x53, 0x41, 0x2e, 0x0a, 0x20, 0x2a, 0x2f, + 0x0a, + }; + + static git_rawobj some_obj = { + some_data, + sizeof(some_data), + GIT_OBJ_BLOB + }; + + test_body(&some, &some_obj); +} diff --git a/tests/object/tag/list.c b/tests/object/tag/list.c new file mode 100644 index 000000000..6d5a24347 --- /dev/null +++ b/tests/object/tag/list.c @@ -0,0 +1,115 @@ +#include "clar_libgit2.h" + +#include "tag.h" + +static git_repository *g_repo; + +#define MAX_USED_TAGS 6 + +struct pattern_match_t +{ + const char* pattern; + const size_t expected_matches; + const char* expected_results[MAX_USED_TAGS]; +}; + +// Helpers +static void ensure_tag_pattern_match(git_repository *repo, + const struct pattern_match_t* data) +{ + int already_found[MAX_USED_TAGS] = { 0 }; + git_strarray tag_list; + int error = 0; + size_t sucessfully_found = 0; + size_t i, j; + + cl_assert(data->expected_matches <= MAX_USED_TAGS); + + if ((error = git_tag_list_match(&tag_list, data->pattern, repo)) < 0) + goto exit; + + if (tag_list.count != data->expected_matches) + { + error = GIT_ERROR; + goto exit; + } + + // we have to be prepared that tags come in any order. + for (i = 0; i < tag_list.count; i++) + { + for (j = 0; j < data->expected_matches; j++) + { + if (!already_found[j] && !strcmp(data->expected_results[j], tag_list.strings[i])) + { + already_found[j] = 1; + sucessfully_found++; + break; + } + } + } + cl_assert_equal_i((int)sucessfully_found, (int)data->expected_matches); + +exit: + git_strarray_free(&tag_list); + cl_git_pass(error); +} + +// Fixture setup and teardown +void test_object_tag_list__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_object_tag_list__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_object_tag_list__list_all(void) +{ + // list all tag names from the repository + git_strarray tag_list; + + cl_git_pass(git_tag_list(&tag_list, g_repo)); + + cl_assert_equal_i((int)tag_list.count, 6); + + git_strarray_free(&tag_list); +} + +static const struct pattern_match_t matches[] = { + // All tags, including a packed one and two namespaced ones. + { "", 6, { "e90810b", "point_to_blob", "test", "packed-tag", "foo/bar", "foo/foo/bar" } }, + + // beginning with + { "t*", 1, { "test" } }, + + // ending with + { "*b", 2, { "e90810b", "point_to_blob" } }, + + // exact match + { "e", 0 }, + { "e90810b", 1, { "e90810b" } }, + + // either or + { "e90810[ab]", 1, { "e90810b" } }, + + // glob in the middle + { "foo/*/bar", 1, { "foo/foo/bar" } }, + + // The matching of '*' is based on plain string matching analog to the regular expression ".*" + // => a '/' in the tag name has no special meaning. + // Compare to `git tag -l "*bar"` + { "*bar", 2, { "foo/bar", "foo/foo/bar" } }, + + // End of list + { NULL } +}; + +void test_object_tag_list__list_by_pattern(void) +{ + // list all tag names from the repository matching a specified pattern + size_t i = 0; + while (matches[i].pattern) + ensure_tag_pattern_match(g_repo, &matches[i++]); +} diff --git a/tests/object/tag/peel.c b/tests/object/tag/peel.c new file mode 100644 index 000000000..e2cd8d6a8 --- /dev/null +++ b/tests/object/tag/peel.c @@ -0,0 +1,61 @@ +#include "clar_libgit2.h" +#include "tag.h" + +static git_repository *repo; +static git_tag *tag; +static git_object *target; + +void test_object_tag_peel__initialize(void) +{ + cl_fixture_sandbox("testrepo.git"); + cl_git_pass(git_repository_open(&repo, "testrepo.git")); +} + +void test_object_tag_peel__cleanup(void) +{ + git_tag_free(tag); + tag = NULL; + + git_object_free(target); + target = NULL; + + git_repository_free(repo); + repo = NULL; + + cl_fixture_cleanup("testrepo.git"); +} + +static void retrieve_tag_from_oid(git_tag **tag_out, git_repository *repo, const char *sha) +{ + git_oid oid; + + cl_git_pass(git_oid_fromstr(&oid, sha)); + cl_git_pass(git_tag_lookup(tag_out, repo, &oid)); +} + +void test_object_tag_peel__can_peel_to_a_commit(void) +{ + retrieve_tag_from_oid(&tag, repo, "7b4384978d2493e851f9cca7858815fac9b10980"); + + cl_git_pass(git_tag_peel(&target, tag)); + cl_assert(git_object_type(target) == GIT_OBJ_COMMIT); + cl_git_pass(git_oid_streq(git_object_id(target), "e90810b8df3e80c413d903f631643c716887138d")); +} + +void test_object_tag_peel__can_peel_several_nested_tags_to_a_commit(void) +{ + retrieve_tag_from_oid(&tag, repo, "b25fa35b38051e4ae45d4222e795f9df2e43f1d1"); + + cl_git_pass(git_tag_peel(&target, tag)); + cl_assert(git_object_type(target) == GIT_OBJ_COMMIT); + cl_git_pass(git_oid_streq(git_object_id(target), "e90810b8df3e80c413d903f631643c716887138d")); +} + +void test_object_tag_peel__can_peel_to_a_non_commit(void) +{ + retrieve_tag_from_oid(&tag, repo, "521d87c1ec3aef9824daf6d96cc0ae3710766d91"); + + cl_git_pass(git_tag_peel(&target, tag)); + cl_assert(git_object_type(target) == GIT_OBJ_BLOB); + cl_git_pass(git_oid_streq(git_object_id(target), "1385f264afb75a56a5bec74243be9b367ba4ca08")); +} diff --git a/tests/object/tag/read.c b/tests/object/tag/read.c new file mode 100644 index 000000000..c9787a413 --- /dev/null +++ b/tests/object/tag/read.c @@ -0,0 +1,142 @@ +#include "clar_libgit2.h" + +#include "tag.h" + +static const char *tag1_id = "b25fa35b38051e4ae45d4222e795f9df2e43f1d1"; +static const char *tag2_id = "7b4384978d2493e851f9cca7858815fac9b10980"; +static const char *tagged_commit = "e90810b8df3e80c413d903f631643c716887138d"; +static const char *bad_tag_id = "eda9f45a2a98d4c17a09d681d88569fa4ea91755"; +static const char *badly_tagged_commit = "e90810b8df3e80c413d903f631643c716887138d"; +static const char *short_tag_id = "5da7760512a953e3c7c4e47e4392c7a4338fb729"; +static const char *short_tagged_commit = "4a5ed60bafcf4638b7c8356bd4ce1916bfede93c"; +static const char *taggerless = "4a23e2e65ad4e31c4c9db7dc746650bfad082679"; + +static git_repository *g_repo; + +// Fixture setup and teardown +void test_object_tag_read__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_object_tag_read__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + + +void test_object_tag_read__parse(void) +{ + // read and parse a tag from the repository + git_tag *tag1, *tag2; + git_commit *commit; + git_oid id1, id2, id_commit; + + git_oid_fromstr(&id1, tag1_id); + git_oid_fromstr(&id2, tag2_id); + git_oid_fromstr(&id_commit, tagged_commit); + + cl_git_pass(git_tag_lookup(&tag1, g_repo, &id1)); + + cl_assert_equal_s(git_tag_name(tag1), "test"); + cl_assert(git_tag_target_type(tag1) == GIT_OBJ_TAG); + + cl_git_pass(git_tag_target((git_object **)&tag2, tag1)); + cl_assert(tag2 != NULL); + + cl_assert(git_oid_cmp(&id2, git_tag_id(tag2)) == 0); + + cl_git_pass(git_tag_target((git_object **)&commit, tag2)); + cl_assert(commit != NULL); + + cl_assert(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0); + + git_tag_free(tag1); + git_tag_free(tag2); + git_commit_free(commit); +} + +void test_object_tag_read__parse_without_tagger(void) +{ + // read and parse a tag without a tagger field + git_repository *bad_tag_repo; + git_tag *bad_tag; + git_commit *commit; + git_oid id, id_commit; + + // TODO: This is a little messy + cl_git_pass(git_repository_open(&bad_tag_repo, cl_fixture("bad_tag.git"))); + + git_oid_fromstr(&id, bad_tag_id); + git_oid_fromstr(&id_commit, badly_tagged_commit); + + cl_git_pass(git_tag_lookup(&bad_tag, bad_tag_repo, &id)); + cl_assert(bad_tag != NULL); + + cl_assert_equal_s(git_tag_name(bad_tag), "e90810b"); + cl_assert(git_oid_cmp(&id, git_tag_id(bad_tag)) == 0); + cl_assert(bad_tag->tagger == NULL); + + cl_git_pass(git_tag_target((git_object **)&commit, bad_tag)); + cl_assert(commit != NULL); + + cl_assert(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0); + + + git_tag_free(bad_tag); + git_commit_free(commit); + git_repository_free(bad_tag_repo); +} + +void test_object_tag_read__parse_without_message(void) +{ + // read and parse a tag without a message field + git_repository *short_tag_repo; + git_tag *short_tag; + git_commit *commit; + git_oid id, id_commit; + + // TODO: This is a little messy + cl_git_pass(git_repository_open(&short_tag_repo, cl_fixture("short_tag.git"))); + + git_oid_fromstr(&id, short_tag_id); + git_oid_fromstr(&id_commit, short_tagged_commit); + + cl_git_pass(git_tag_lookup(&short_tag, short_tag_repo, &id)); + cl_assert(short_tag != NULL); + + cl_assert_equal_s(git_tag_name(short_tag), "no_description"); + cl_assert(git_oid_cmp(&id, git_tag_id(short_tag)) == 0); + cl_assert(short_tag->message == NULL); + + cl_git_pass(git_tag_target((git_object **)&commit, short_tag)); + cl_assert(commit != NULL); + + cl_assert(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0); + + git_tag_free(short_tag); + git_commit_free(commit); + git_repository_free(short_tag_repo); +} + +void test_object_tag_read__without_tagger_nor_message(void) +{ + git_tag *tag; + git_oid id; + git_repository *repo; + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + + cl_git_pass(git_oid_fromstr(&id, taggerless)); + + cl_git_pass(git_tag_lookup(&tag, repo, &id)); + + cl_assert_equal_s(git_tag_name(tag), "taggerless"); + cl_assert(git_tag_target_type(tag) == GIT_OBJ_COMMIT); + + cl_assert(tag->message == NULL); + cl_assert(tag->tagger == NULL); + + git_tag_free(tag); + git_repository_free(repo); +} diff --git a/tests/object/tag/write.c b/tests/object/tag/write.c new file mode 100644 index 000000000..68e4b6c61 --- /dev/null +++ b/tests/object/tag/write.c @@ -0,0 +1,260 @@ +#include "clar_libgit2.h" + +static const char* tagger_name = "Vicent Marti"; +static const char* tagger_email = "vicent@github.com"; +static const char* tagger_message = "This is my tag.\n\nThere are many tags, but this one is mine\n"; + +static const char *tag2_id = "7b4384978d2493e851f9cca7858815fac9b10980"; +static const char *tagged_commit = "e90810b8df3e80c413d903f631643c716887138d"; + +static git_repository *g_repo; + +// Fixture setup and teardown +void test_object_tag_write__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_object_tag_write__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_object_tag_write__basic(void) +{ + // write a tag to the repository and read it again + git_tag *tag; + git_oid target_id, tag_id; + git_signature *tagger; + const git_signature *tagger1; + git_reference *ref_tag; + git_object *target; + + git_oid_fromstr(&target_id, tagged_commit); + cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); + + /* create signature */ + cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60)); + + cl_git_pass( + git_tag_create(&tag_id, g_repo, + "the-tag", target, tagger, tagger_message, 0) + ); + + git_object_free(target); + git_signature_free(tagger); + + cl_git_pass(git_tag_lookup(&tag, g_repo, &tag_id)); + cl_assert(git_oid_cmp(git_tag_target_id(tag), &target_id) == 0); + + /* Check attributes were set correctly */ + tagger1 = git_tag_tagger(tag); + cl_assert(tagger1 != NULL); + cl_assert_equal_s(tagger1->name, tagger_name); + cl_assert_equal_s(tagger1->email, tagger_email); + cl_assert(tagger1->when.time == 123456789); + cl_assert(tagger1->when.offset == 60); + + cl_assert_equal_s(git_tag_message(tag), tagger_message); + + cl_git_pass(git_reference_lookup(&ref_tag, g_repo, "refs/tags/the-tag")); + cl_assert(git_oid_cmp(git_reference_target(ref_tag), &tag_id) == 0); + cl_git_pass(git_reference_delete(ref_tag)); + git_reference_free(ref_tag); + + git_tag_free(tag); +} + +void test_object_tag_write__overwrite(void) +{ + // Attempt to write a tag bearing the same name than an already existing tag + git_oid target_id, tag_id; + git_signature *tagger; + git_object *target; + + git_oid_fromstr(&target_id, tagged_commit); + cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); + + /* create signature */ + cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60)); + + cl_assert_equal_i(GIT_EEXISTS, git_tag_create( + &tag_id, /* out id */ + g_repo, + "e90810b", + target, + tagger, + tagger_message, + 0)); + + git_object_free(target); + git_signature_free(tagger); +} + +void test_object_tag_write__replace(void) +{ + // Replace an already existing tag + git_oid target_id, tag_id, old_tag_id; + git_signature *tagger; + git_reference *ref_tag; + git_object *target; + + git_oid_fromstr(&target_id, tagged_commit); + cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); + + cl_git_pass(git_reference_lookup(&ref_tag, g_repo, "refs/tags/e90810b")); + git_oid_cpy(&old_tag_id, git_reference_target(ref_tag)); + git_reference_free(ref_tag); + + /* create signature */ + cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60)); + + cl_git_pass(git_tag_create( + &tag_id, /* out id */ + g_repo, + "e90810b", + target, + tagger, + tagger_message, + 1)); + + git_object_free(target); + git_signature_free(tagger); + + cl_git_pass(git_reference_lookup(&ref_tag, g_repo, "refs/tags/e90810b")); + cl_assert(git_oid_cmp(git_reference_target(ref_tag), &tag_id) == 0); + cl_assert(git_oid_cmp(git_reference_target(ref_tag), &old_tag_id) != 0); + + git_reference_free(ref_tag); +} + +void test_object_tag_write__lightweight(void) +{ + // write a lightweight tag to the repository and read it again + git_oid target_id, object_id; + git_reference *ref_tag; + git_object *target; + + git_oid_fromstr(&target_id, tagged_commit); + cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); + + cl_git_pass(git_tag_create_lightweight( + &object_id, + g_repo, + "light-tag", + target, + 0)); + + git_object_free(target); + + cl_assert(git_oid_cmp(&object_id, &target_id) == 0); + + cl_git_pass(git_reference_lookup(&ref_tag, g_repo, "refs/tags/light-tag")); + cl_assert(git_oid_cmp(git_reference_target(ref_tag), &target_id) == 0); + + cl_git_pass(git_tag_delete(g_repo, "light-tag")); + + git_reference_free(ref_tag); +} + +void test_object_tag_write__lightweight_over_existing(void) +{ + // Attempt to write a lightweight tag bearing the same name than an already existing tag + git_oid target_id, object_id, existing_object_id; + git_object *target; + + git_oid_fromstr(&target_id, tagged_commit); + cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); + + cl_assert_equal_i(GIT_EEXISTS, git_tag_create_lightweight( + &object_id, + g_repo, + "e90810b", + target, + 0)); + + git_oid_fromstr(&existing_object_id, tag2_id); + cl_assert(git_oid_cmp(&object_id, &existing_object_id) == 0); + + git_object_free(target); +} + +void test_object_tag_write__delete(void) +{ + // Delete an already existing tag + git_reference *ref_tag; + + cl_git_pass(git_tag_delete(g_repo, "e90810b")); + + cl_git_fail(git_reference_lookup(&ref_tag, g_repo, "refs/tags/e90810b")); + + git_reference_free(ref_tag); +} + +void test_object_tag_write__creating_with_an_invalid_name_returns_EINVALIDSPEC(void) +{ + git_oid target_id, tag_id; + git_signature *tagger; + git_object *target; + + git_oid_fromstr(&target_id, tagged_commit); + cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); + + cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60)); + + cl_assert_equal_i(GIT_EINVALIDSPEC, + git_tag_create(&tag_id, g_repo, + "Inv@{id", target, tagger, tagger_message, 0) + ); + + cl_assert_equal_i(GIT_EINVALIDSPEC, + git_tag_create_lightweight(&tag_id, g_repo, + "Inv@{id", target, 0) + ); + + git_object_free(target); + git_signature_free(tagger); +} + +void test_object_tag_write__deleting_with_an_invalid_name_returns_EINVALIDSPEC(void) +{ + cl_assert_equal_i(GIT_EINVALIDSPEC, git_tag_delete(g_repo, "Inv@{id")); +} + +void create_annotation(git_oid *tag_id, const char *name) +{ + git_object *target; + git_oid target_id; + git_signature *tagger; + + cl_git_pass(git_signature_new(&tagger, tagger_name, tagger_email, 123456789, 60)); + + git_oid_fromstr(&target_id, tagged_commit); + cl_git_pass(git_object_lookup(&target, g_repo, &target_id, GIT_OBJ_COMMIT)); + + cl_git_pass(git_tag_annotation_create(tag_id, g_repo, name, target, tagger, "boom!")); + git_object_free(target); + git_signature_free(tagger); +} + +void test_object_tag_write__creating_an_annotation_stores_the_new_object_in_the_odb(void) +{ + git_oid tag_id; + git_tag *tag; + + create_annotation(&tag_id, "new_tag"); + + cl_git_pass(git_tag_lookup(&tag, g_repo, &tag_id)); + cl_assert_equal_s("new_tag", git_tag_name(tag)); + + git_tag_free(tag); +} + +void test_object_tag_write__creating_an_annotation_does_not_create_a_reference(void) +{ + git_oid tag_id; + git_reference *tag_ref; + + create_annotation(&tag_id, "new_tag"); + cl_git_fail_with(git_reference_lookup(&tag_ref, g_repo, "refs/tags/new_tag"), GIT_ENOTFOUND); +} diff --git a/tests/object/tree/attributes.c b/tests/object/tree/attributes.c new file mode 100644 index 000000000..85216cd1b --- /dev/null +++ b/tests/object/tree/attributes.c @@ -0,0 +1,115 @@ +#include "clar_libgit2.h" +#include "tree.h" + +static const char *blob_oid = "3d0970ec547fc41ef8a5882dde99c6adce65b021"; +static const char *tree_oid = "1b05fdaa881ee45b48cbaa5e9b037d667a47745e"; + +void test_object_tree_attributes__ensure_correctness_of_attributes_on_insertion(void) +{ + git_treebuilder *builder; + git_oid oid; + + cl_git_pass(git_oid_fromstr(&oid, blob_oid)); + + cl_git_pass(git_treebuilder_create(&builder, NULL)); + + cl_git_fail(git_treebuilder_insert(NULL, builder, "one.txt", &oid, (git_filemode_t)0777777)); + cl_git_fail(git_treebuilder_insert(NULL, builder, "one.txt", &oid, (git_filemode_t)0100666)); + cl_git_fail(git_treebuilder_insert(NULL, builder, "one.txt", &oid, (git_filemode_t)0000001)); + + git_treebuilder_free(builder); +} + +void test_object_tree_attributes__group_writable_tree_entries_created_with_an_antique_git_version_can_still_be_accessed(void) +{ + git_repository *repo; + git_oid tid; + git_tree *tree; + const git_tree_entry *entry; + + cl_git_pass(git_repository_open(&repo, cl_fixture("deprecated-mode.git"))); + + cl_git_pass(git_oid_fromstr(&tid, tree_oid)); + cl_git_pass(git_tree_lookup(&tree, repo, &tid)); + + entry = git_tree_entry_byname(tree, "old_mode.txt"); + cl_assert_equal_i( + GIT_FILEMODE_BLOB, + git_tree_entry_filemode(entry)); + + git_tree_free(tree); + git_repository_free(repo); +} + +void test_object_tree_attributes__treebuilder_reject_invalid_filemode(void) +{ + git_treebuilder *builder; + git_oid bid; + const git_tree_entry *entry; + + cl_git_pass(git_oid_fromstr(&bid, blob_oid)); + cl_git_pass(git_treebuilder_create(&builder, NULL)); + + cl_git_fail(git_treebuilder_insert( + &entry, + builder, + "normalized.txt", + &bid, + GIT_FILEMODE_BLOB_GROUP_WRITABLE)); + + git_treebuilder_free(builder); +} + +void test_object_tree_attributes__normalize_attributes_when_creating_a_tree_from_an_existing_one(void) +{ + git_repository *repo; + git_treebuilder *builder; + git_oid tid, tid2; + git_tree *tree; + const git_tree_entry *entry; + + repo = cl_git_sandbox_init("deprecated-mode.git"); + + cl_git_pass(git_oid_fromstr(&tid, tree_oid)); + cl_git_pass(git_tree_lookup(&tree, repo, &tid)); + + cl_git_pass(git_treebuilder_create(&builder, tree)); + + entry = git_treebuilder_get(builder, "old_mode.txt"); + cl_assert_equal_i( + GIT_FILEMODE_BLOB, + git_tree_entry_filemode(entry)); + + cl_git_pass(git_treebuilder_write(&tid2, repo, builder)); + git_treebuilder_free(builder); + git_tree_free(tree); + + cl_git_pass(git_tree_lookup(&tree, repo, &tid2)); + entry = git_tree_entry_byname(tree, "old_mode.txt"); + cl_assert_equal_i( + GIT_FILEMODE_BLOB, + git_tree_entry_filemode(entry)); + + git_tree_free(tree); + cl_git_sandbox_cleanup(); +} + +void test_object_tree_attributes__normalize_600(void) +{ + git_oid id; + git_tree *tree; + git_repository *repo; + const git_tree_entry *entry; + + repo = cl_git_sandbox_init("deprecated-mode.git"); + + git_oid_fromstr(&id, "0810fb7818088ff5ac41ee49199b51473b1bd6c7"); + cl_git_pass(git_tree_lookup(&tree, repo, &id)); + + entry = git_tree_entry_byname(tree, "ListaTeste.xml"); + cl_assert_equal_i(git_tree_entry_filemode(entry), GIT_FILEMODE_BLOB); + cl_assert_equal_i(git_tree_entry_filemode_raw(entry), 0100600); + + git_tree_free(tree); + cl_git_sandbox_cleanup(); +} diff --git a/tests/object/tree/duplicateentries.c b/tests/object/tree/duplicateentries.c new file mode 100644 index 000000000..9262f9a1a --- /dev/null +++ b/tests/object/tree/duplicateentries.c @@ -0,0 +1,157 @@ +#include "clar_libgit2.h" +#include "tree.h" + +static git_repository *_repo; + +void test_object_tree_duplicateentries__initialize(void) { + _repo = cl_git_sandbox_init("testrepo"); +} + +void test_object_tree_duplicateentries__cleanup(void) { + cl_git_sandbox_cleanup(); +} + +/* + * $ git show --format=raw refs/heads/dir + * commit 144344043ba4d4a405da03de3844aa829ae8be0e + * tree d52a8fe84ceedf260afe4f0287bbfca04a117e83 + * parent cf80f8de9f1185bf3a05f993f6121880dd0cfbc9 + * author Ben Straub 1343755506 -0700 + * committer Ben Straub 1343755506 -0700 + * + * Change a file mode + * + * diff --git a/a/b.txt b/a/b.txt + * old mode 100644 + * new mode 100755 + * + * $ git ls-tree d52a8fe84ceedf260afe4f0287bbfca04a117e83 + * 100644 blob a8233120f6ad708f843d861ce2b7228ec4e3dec6 README + * 040000 tree 4e0883eeeeebc1fb1735161cea82f7cb5fab7e63 a + * 100644 blob 45b983be36b73c0788dc9cbcb76cbb80fc7bb057 branch_file.txt + * 100644 blob a71586c1dfe8a71c6cbf6c129f404c5642ff31bd new.txt + */ + +static void tree_checker( + git_oid *tid, + const char *expected_sha, + git_filemode_t expected_filemode) +{ + git_tree *tree; + const git_tree_entry *entry; + git_oid oid; + + cl_git_pass(git_tree_lookup(&tree, _repo, tid)); + cl_assert_equal_i(1, (int)git_tree_entrycount(tree)); + entry = git_tree_entry_byindex(tree, 0); + + cl_git_pass(git_oid_fromstr(&oid, expected_sha)); + + cl_assert_equal_i(0, git_oid_cmp(&oid, git_tree_entry_id(entry))); + cl_assert_equal_i(expected_filemode, git_tree_entry_filemode(entry)); + + git_tree_free(tree); +} + +static void tree_creator(git_oid *out, void (*fn)(git_treebuilder *)) +{ + git_treebuilder *builder; + + cl_git_pass(git_treebuilder_create(&builder, NULL)); + + fn(builder); + + cl_git_pass(git_treebuilder_write(out, _repo, builder)); + git_treebuilder_free(builder); +} + +static void two_blobs(git_treebuilder *bld) +{ + git_oid oid; + const git_tree_entry *entry; + + cl_git_pass(git_oid_fromstr(&oid, + "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); /* blob oid (README) */ + + cl_git_pass(git_treebuilder_insert( + &entry, bld, "duplicate", &oid, + GIT_FILEMODE_BLOB)); + + cl_git_pass(git_oid_fromstr(&oid, + "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd")); /* blob oid (new.txt) */ + + cl_git_pass(git_treebuilder_insert( + &entry, bld, "duplicate", &oid, + GIT_FILEMODE_BLOB)); +} + +static void one_blob_and_one_tree(git_treebuilder *bld) +{ + git_oid oid; + const git_tree_entry *entry; + + cl_git_pass(git_oid_fromstr(&oid, + "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); /* blob oid (README) */ + + cl_git_pass(git_treebuilder_insert( + &entry, bld, "duplicate", &oid, + GIT_FILEMODE_BLOB)); + + cl_git_pass(git_oid_fromstr(&oid, + "4e0883eeeeebc1fb1735161cea82f7cb5fab7e63")); /* tree oid (a) */ + + cl_git_pass(git_treebuilder_insert( + &entry, bld, "duplicate", &oid, + GIT_FILEMODE_TREE)); +} + +void test_object_tree_duplicateentries__cannot_create_a_duplicate_entry_through_the_treebuilder(void) +{ + git_oid tid; + + tree_creator(&tid, two_blobs); + tree_checker(&tid, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd", GIT_FILEMODE_BLOB); + + tree_creator(&tid, one_blob_and_one_tree); + tree_checker(&tid, "4e0883eeeeebc1fb1735161cea82f7cb5fab7e63", GIT_FILEMODE_TREE); +} + +static void add_fake_conflicts(git_index *index) +{ + git_index_entry ancestor_entry, our_entry, their_entry; + + memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); + memset(&our_entry, 0x0, sizeof(git_index_entry)); + memset(&their_entry, 0x0, sizeof(git_index_entry)); + + ancestor_entry.path = "duplicate"; + ancestor_entry.mode = GIT_FILEMODE_BLOB; + ancestor_entry.flags |= (1 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&ancestor_entry.oid, "a8233120f6ad708f843d861ce2b7228ec4e3dec6"); + + our_entry.path = "duplicate"; + our_entry.mode = GIT_FILEMODE_BLOB; + ancestor_entry.flags |= (2 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&our_entry.oid, "45b983be36b73c0788dc9cbcb76cbb80fc7bb057"); + + their_entry.path = "duplicate"; + their_entry.mode = GIT_FILEMODE_BLOB; + ancestor_entry.flags |= (3 << GIT_IDXENTRY_STAGESHIFT); + git_oid_fromstr(&their_entry.oid, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd"); + + cl_git_pass(git_index_conflict_add(index, &ancestor_entry, &our_entry, &their_entry)); +} + +void test_object_tree_duplicateentries__cannot_create_a_duplicate_entry_building_a_tree_from_a_index_with_conflicts(void) +{ + git_index *index; + git_oid tid; + + cl_git_pass(git_repository_index(&index, _repo)); + + add_fake_conflicts(index); + + cl_assert_equal_i(GIT_EUNMERGED, git_index_write_tree(&tid, index)); + + git_index_free(index); +} diff --git a/tests/object/tree/frompath.c b/tests/object/tree/frompath.c new file mode 100644 index 000000000..86ca47e94 --- /dev/null +++ b/tests/object/tree/frompath.c @@ -0,0 +1,68 @@ +#include "clar_libgit2.h" + +static git_repository *repo; +static git_tree *tree; + +void test_object_tree_frompath__initialize(void) +{ + git_oid id; + const char *tree_with_subtrees_oid = "ae90f12eea699729ed24555e40b9fd669da12a12"; + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + cl_assert(repo != NULL); + + cl_git_pass(git_oid_fromstr(&id, tree_with_subtrees_oid)); + cl_git_pass(git_tree_lookup(&tree, repo, &id)); + cl_assert(tree != NULL); +} + +void test_object_tree_frompath__cleanup(void) +{ + git_tree_free(tree); + tree = NULL; + + git_repository_free(repo); + repo = NULL; +} + +static void assert_tree_from_path( + git_tree *root, + const char *path, + const char *expected_entry_name) +{ + git_tree_entry *entry; + + cl_git_pass(git_tree_entry_bypath(&entry, root, path)); + cl_assert_equal_s(git_tree_entry_name(entry), expected_entry_name); + git_tree_entry_free(entry); +} + +void test_object_tree_frompath__retrieve_tree_from_path_to_treeentry(void) +{ + git_tree_entry *e; + + assert_tree_from_path(tree, "README", "README"); + assert_tree_from_path(tree, "ab/de/fgh/1.txt", "1.txt"); + assert_tree_from_path(tree, "ab/de/fgh", "fgh"); + assert_tree_from_path(tree, "ab/de/fgh/", "fgh"); + assert_tree_from_path(tree, "ab/de", "de"); + assert_tree_from_path(tree, "ab/", "ab"); + assert_tree_from_path(tree, "ab/de/", "de"); + + cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "i-do-not-exist.txt")); + cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "README/")); + cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "ab/de/fgh/i-do-not-exist.txt")); + cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "nope/de/fgh/1.txt")); + cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "ab/me-neither/fgh/2.txt")); + cl_assert_equal_i(GIT_ENOTFOUND, git_tree_entry_bypath(&e, tree, "ab/me-neither/fgh/2.txt/")); +} + +void test_object_tree_frompath__fail_when_processing_an_invalid_path(void) +{ + git_tree_entry *e; + + cl_must_fail(git_tree_entry_bypath(&e, tree, "/")); + cl_must_fail(git_tree_entry_bypath(&e, tree, "/ab")); + cl_must_fail(git_tree_entry_bypath(&e, tree, "/ab/de")); + cl_must_fail(git_tree_entry_bypath(&e, tree, "ab//de")); +} diff --git a/tests/object/tree/read.c b/tests/object/tree/read.c new file mode 100644 index 000000000..59a809bf1 --- /dev/null +++ b/tests/object/tree/read.c @@ -0,0 +1,75 @@ +#include "clar_libgit2.h" + +#include "tree.h" + +static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd"; + +static git_repository *g_repo; + +// Fixture setup and teardown +void test_object_tree_read__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_object_tree_read__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + + + +void test_object_tree_read__loaded(void) +{ + // acces randomly the entries on a loaded tree + git_oid id; + git_tree *tree; + + git_oid_fromstr(&id, tree_oid); + + cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); + + cl_assert(git_tree_entry_byname(tree, "README") != NULL); + cl_assert(git_tree_entry_byname(tree, "NOTEXISTS") == NULL); + cl_assert(git_tree_entry_byname(tree, "") == NULL); + cl_assert(git_tree_entry_byindex(tree, 0) != NULL); + cl_assert(git_tree_entry_byindex(tree, 2) != NULL); + cl_assert(git_tree_entry_byindex(tree, 3) == NULL); + cl_assert(git_tree_entry_byindex(tree, (unsigned int)-1) == NULL); + + git_tree_free(tree); +} + +void test_object_tree_read__two(void) +{ + // read a tree from the repository + git_oid id; + git_tree *tree; + const git_tree_entry *entry; + git_object *obj; + + git_oid_fromstr(&id, tree_oid); + + cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); + + cl_assert(git_tree_entrycount(tree) == 3); + + /* GH-86: git_object_lookup() should also check the type if the object comes from the cache */ + cl_assert(git_object_lookup(&obj, g_repo, &id, GIT_OBJ_TREE) == 0); + cl_assert(obj != NULL); + git_object_free(obj); + obj = NULL; + cl_git_fail(git_object_lookup(&obj, g_repo, &id, GIT_OBJ_BLOB)); + cl_assert(obj == NULL); + + entry = git_tree_entry_byname(tree, "README"); + cl_assert(entry != NULL); + + cl_assert_equal_s(git_tree_entry_name(entry), "README"); + + cl_git_pass(git_tree_entry_to_object(&obj, g_repo, entry)); + cl_assert(obj != NULL); + + git_object_free(obj); + git_tree_free(tree); +} diff --git a/tests/object/tree/walk.c b/tests/object/tree/walk.c new file mode 100644 index 000000000..1207e864c --- /dev/null +++ b/tests/object/tree/walk.c @@ -0,0 +1,177 @@ +#include "clar_libgit2.h" +#include "tree.h" + +static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd"; +static git_repository *g_repo; + +void test_object_tree_walk__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_object_tree_walk__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static int treewalk_count_cb( + const char *root, const git_tree_entry *entry, void *payload) +{ + int *count = payload; + + GIT_UNUSED(root); + GIT_UNUSED(entry); + + (*count) += 1; + + return 0; +} + +void test_object_tree_walk__0(void) +{ + git_oid id; + git_tree *tree; + int ct; + + git_oid_fromstr(&id, tree_oid); + + cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); + + ct = 0; + cl_git_pass(git_tree_walk(tree, GIT_TREEWALK_PRE, treewalk_count_cb, &ct)); + cl_assert_equal_i(3, ct); + + ct = 0; + cl_git_pass(git_tree_walk(tree, GIT_TREEWALK_POST, treewalk_count_cb, &ct)); + cl_assert_equal_i(3, ct); + + git_tree_free(tree); +} + + +static int treewalk_stop_cb( + const char *root, const git_tree_entry *entry, void *payload) +{ + int *count = payload; + + GIT_UNUSED(root); + GIT_UNUSED(entry); + + (*count) += 1; + + return (*count == 2) ? -1 : 0; +} + +static int treewalk_stop_immediately_cb( + const char *root, const git_tree_entry *entry, void *payload) +{ + GIT_UNUSED(root); + GIT_UNUSED(entry); + GIT_UNUSED(payload); + return -100; +} + +void test_object_tree_walk__1(void) +{ + git_oid id; + git_tree *tree; + int ct; + + git_oid_fromstr(&id, tree_oid); + + cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); + + ct = 0; + cl_assert_equal_i( + GIT_EUSER, git_tree_walk(tree, GIT_TREEWALK_PRE, treewalk_stop_cb, &ct)); + cl_assert_equal_i(2, ct); + + ct = 0; + cl_assert_equal_i( + GIT_EUSER, git_tree_walk(tree, GIT_TREEWALK_POST, treewalk_stop_cb, &ct)); + cl_assert_equal_i(2, ct); + + cl_assert_equal_i( + GIT_EUSER, git_tree_walk( + tree, GIT_TREEWALK_PRE, treewalk_stop_immediately_cb, NULL)); + + cl_assert_equal_i( + GIT_EUSER, git_tree_walk( + tree, GIT_TREEWALK_POST, treewalk_stop_immediately_cb, NULL)); + + git_tree_free(tree); +} + + +struct treewalk_skip_data { + int files; + int dirs; + const char *skip; + const char *stop; +}; + +static int treewalk_skip_de_cb( + const char *root, const git_tree_entry *entry, void *payload) +{ + struct treewalk_skip_data *data = payload; + const char *name = git_tree_entry_name(entry); + + GIT_UNUSED(root); + + if (git_tree_entry_type(entry) == GIT_OBJ_TREE) + data->dirs++; + else + data->files++; + + if (data->skip && !strcmp(name, data->skip)) + return 1; + else if (data->stop && !strcmp(name, data->stop)) + return -1; + else + return 0; +} + +void test_object_tree_walk__2(void) +{ + git_oid id; + git_tree *tree; + struct treewalk_skip_data data; + + /* look up a deep tree */ + git_oid_fromstr(&id, "ae90f12eea699729ed24555e40b9fd669da12a12"); + cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); + + memset(&data, 0, sizeof(data)); + data.skip = "de"; + + cl_assert_equal_i(0, git_tree_walk( + tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); + cl_assert_equal_i(5, data.files); + cl_assert_equal_i(3, data.dirs); + + memset(&data, 0, sizeof(data)); + data.stop = "3.txt"; + + cl_assert_equal_i(GIT_EUSER, git_tree_walk( + tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); + cl_assert_equal_i(3, data.files); + cl_assert_equal_i(2, data.dirs); + + memset(&data, 0, sizeof(data)); + data.skip = "new.txt"; + + cl_assert_equal_i(0, git_tree_walk( + tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); + cl_assert_equal_i(7, data.files); + cl_assert_equal_i(4, data.dirs); + + memset(&data, 0, sizeof(data)); + data.stop = "new.txt"; + + cl_assert_equal_i(GIT_EUSER, git_tree_walk( + tree, GIT_TREEWALK_PRE, treewalk_skip_de_cb, &data)); + cl_assert_equal_i(7, data.files); + cl_assert_equal_i(4, data.dirs); + + git_tree_free(tree); +} diff --git a/tests/object/tree/write.c b/tests/object/tree/write.c new file mode 100644 index 000000000..468c0ccd1 --- /dev/null +++ b/tests/object/tree/write.c @@ -0,0 +1,262 @@ +#include "clar_libgit2.h" + +#include "tree.h" + +static const char *blob_oid = "fa49b077972391ad58037050f2a75f74e3671e92"; +static const char *first_tree = "181037049a54a1eb5fab404658a3a250b44335d7"; +static const char *second_tree = "f60079018b664e4e79329a7ef9559c8d9e0378d1"; +static const char *third_tree = "eb86d8b81d6adbd5290a935d6c9976882de98488"; + +static git_repository *g_repo; + +// Fixture setup and teardown +void test_object_tree_write__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_object_tree_write__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_object_tree_write__from_memory(void) +{ + // write a tree from a memory + git_treebuilder *builder; + git_tree *tree; + git_oid id, bid, rid, id2; + + git_oid_fromstr(&id, first_tree); + git_oid_fromstr(&id2, second_tree); + git_oid_fromstr(&bid, blob_oid); + + //create a second tree from first tree using `git_treebuilder_insert` on REPOSITORY_FOLDER. + cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); + cl_git_pass(git_treebuilder_create(&builder, tree)); + + cl_git_fail(git_treebuilder_insert(NULL, builder, "", + &bid, GIT_FILEMODE_BLOB)); + cl_git_fail(git_treebuilder_insert(NULL, builder, "/", + &bid, GIT_FILEMODE_BLOB)); + cl_git_fail(git_treebuilder_insert(NULL, builder, ".git", + &bid, GIT_FILEMODE_BLOB)); + cl_git_fail(git_treebuilder_insert(NULL, builder, "..", + &bid, GIT_FILEMODE_BLOB)); + cl_git_fail(git_treebuilder_insert(NULL, builder, ".", + &bid, GIT_FILEMODE_BLOB)); + cl_git_fail(git_treebuilder_insert(NULL, builder, "folder/new.txt", + &bid, GIT_FILEMODE_BLOB)); + + cl_git_pass(git_treebuilder_insert( + NULL, builder, "new.txt", &bid, GIT_FILEMODE_BLOB)); + + cl_git_pass(git_treebuilder_write(&rid, g_repo, builder)); + + cl_assert(git_oid_cmp(&rid, &id2) == 0); + + git_treebuilder_free(builder); + git_tree_free(tree); +} + +void test_object_tree_write__subtree(void) +{ + // write a hierarchical tree from a memory + git_treebuilder *builder; + git_tree *tree; + git_oid id, bid, subtree_id, id2, id3; + git_oid id_hiearar; + + git_oid_fromstr(&id, first_tree); + git_oid_fromstr(&id2, second_tree); + git_oid_fromstr(&id3, third_tree); + git_oid_fromstr(&bid, blob_oid); + + //create subtree + cl_git_pass(git_treebuilder_create(&builder, NULL)); + cl_git_pass(git_treebuilder_insert( + NULL, builder, "new.txt", &bid, GIT_FILEMODE_BLOB)); //-V536 + cl_git_pass(git_treebuilder_write(&subtree_id, g_repo, builder)); + git_treebuilder_free(builder); + + // create parent tree + cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); + cl_git_pass(git_treebuilder_create(&builder, tree)); + cl_git_pass(git_treebuilder_insert( + NULL, builder, "new", &subtree_id, GIT_FILEMODE_TREE)); //-V536 + cl_git_pass(git_treebuilder_write(&id_hiearar, g_repo, builder)); + git_treebuilder_free(builder); + git_tree_free(tree); + + cl_assert(git_oid_cmp(&id_hiearar, &id3) == 0); + + // check data is correct + cl_git_pass(git_tree_lookup(&tree, g_repo, &id_hiearar)); + cl_assert(2 == git_tree_entrycount(tree)); + git_tree_free(tree); +} + +/* + * And the Lord said: Is this tree properly sorted? + */ +void test_object_tree_write__sorted_subtrees(void) +{ + git_treebuilder *builder; + unsigned int i; + int position_c = -1, position_cake = -1, position_config = -1; + + struct { + unsigned int attr; + const char *filename; + } entries[] = { + { GIT_FILEMODE_BLOB, ".gitattributes" }, + { GIT_FILEMODE_BLOB, ".gitignore" }, + { GIT_FILEMODE_BLOB, ".htaccess" }, + { GIT_FILEMODE_BLOB, "Capfile" }, + { GIT_FILEMODE_BLOB, "Makefile"}, + { GIT_FILEMODE_BLOB, "README"}, + { GIT_FILEMODE_TREE, "app"}, + { GIT_FILEMODE_TREE, "cake"}, + { GIT_FILEMODE_TREE, "config"}, + { GIT_FILEMODE_BLOB, "c"}, + { GIT_FILEMODE_BLOB, "git_test.txt"}, + { GIT_FILEMODE_BLOB, "htaccess.htaccess"}, + { GIT_FILEMODE_BLOB, "index.php"}, + { GIT_FILEMODE_TREE, "plugins"}, + { GIT_FILEMODE_TREE, "schemas"}, + { GIT_FILEMODE_TREE, "ssl-certs"}, + { GIT_FILEMODE_TREE, "vendors"} + }; + + git_oid blank_oid, tree_oid; + + memset(&blank_oid, 0x0, sizeof(blank_oid)); + + cl_git_pass(git_treebuilder_create(&builder, NULL)); + + for (i = 0; i < ARRAY_SIZE(entries); ++i) { + cl_git_pass(git_treebuilder_insert(NULL, + builder, entries[i].filename, &blank_oid, entries[i].attr)); + } + + cl_git_pass(git_treebuilder_write(&tree_oid, g_repo, builder)); + + for (i = 0; i < builder->entries.length; ++i) { + git_tree_entry *entry = git_vector_get(&builder->entries, i); + + if (strcmp(entry->filename, "c") == 0) + position_c = i; + + if (strcmp(entry->filename, "cake") == 0) + position_cake = i; + + if (strcmp(entry->filename, "config") == 0) + position_config = i; + } + + cl_assert(position_c != -1); + cl_assert(position_cake != -1); + cl_assert(position_config != -1); + + cl_assert(position_c < position_cake); + cl_assert(position_cake < position_config); + + git_treebuilder_free(builder); +} + +void test_object_tree_write__removing_and_re_adding_in_treebuilder(void) +{ + git_treebuilder *builder; + int i, aardvark_i, apple_i, apple_after_i, apple_extra_i, last_i; + git_oid blank_oid, tree_oid; + git_tree *tree; + struct { + unsigned int attr; + const char *filename; + } entries[] = { + { GIT_FILEMODE_BLOB, "aardvark" }, + { GIT_FILEMODE_BLOB, ".first" }, + { GIT_FILEMODE_BLOB, "apple" }, + { GIT_FILEMODE_BLOB, "last"}, + { GIT_FILEMODE_BLOB, "apple_after"}, + { GIT_FILEMODE_BLOB, "after_aardvark"}, + { 0, NULL }, + }; + + memset(&blank_oid, 0x0, sizeof(blank_oid)); + + cl_git_pass(git_treebuilder_create(&builder, NULL)); + + cl_assert_equal_i(0, (int)git_treebuilder_entrycount(builder)); + + for (i = 0; entries[i].filename; ++i) + cl_git_pass(git_treebuilder_insert(NULL, + builder, entries[i].filename, &blank_oid, entries[i].attr)); + + cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder)); + + cl_git_pass(git_treebuilder_remove(builder, "apple")); + cl_assert_equal_i(5, (int)git_treebuilder_entrycount(builder)); + + cl_git_pass(git_treebuilder_remove(builder, "apple_after")); + cl_assert_equal_i(4, (int)git_treebuilder_entrycount(builder)); + + cl_git_pass(git_treebuilder_insert( + NULL, builder, "before_last", &blank_oid, GIT_FILEMODE_BLOB)); + cl_assert_equal_i(5, (int)git_treebuilder_entrycount(builder)); + + /* reinsert apple_after */ + cl_git_pass(git_treebuilder_insert( + NULL, builder, "apple_after", &blank_oid, GIT_FILEMODE_BLOB)); + cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder)); + + cl_git_pass(git_treebuilder_remove(builder, "last")); + cl_assert_equal_i(5, (int)git_treebuilder_entrycount(builder)); + + /* reinsert last */ + cl_git_pass(git_treebuilder_insert( + NULL, builder, "last", &blank_oid, GIT_FILEMODE_BLOB)); + cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder)); + + cl_git_pass(git_treebuilder_insert( + NULL, builder, "apple_extra", &blank_oid, GIT_FILEMODE_BLOB)); + cl_assert_equal_i(7, (int)git_treebuilder_entrycount(builder)); + + cl_git_pass(git_treebuilder_write(&tree_oid, g_repo, builder)); + + git_treebuilder_free(builder); + + cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_oid)); + + cl_assert_equal_i(7, (int)git_tree_entrycount(tree)); + + cl_assert(git_tree_entry_byname(tree, ".first") != NULL); + cl_assert(git_tree_entry_byname(tree, "apple") == NULL); + cl_assert(git_tree_entry_byname(tree, "apple_after") != NULL); + cl_assert(git_tree_entry_byname(tree, "apple_extra") != NULL); + cl_assert(git_tree_entry_byname(tree, "last") != NULL); + + aardvark_i = apple_i = apple_after_i = apple_extra_i = last_i = -1; + + for (i = 0; i < 7; ++i) { + const git_tree_entry *entry = git_tree_entry_byindex(tree, i); + + if (!strcmp(entry->filename, "aardvark")) + aardvark_i = i; + else if (!strcmp(entry->filename, "apple")) + apple_i = i; + else if (!strcmp(entry->filename, "apple_after")) + apple_after_i = i; + else if (!strcmp(entry->filename, "apple_extra")) + apple_extra_i = i; + else if (!strcmp(entry->filename, "last")) + last_i = i; + } + + cl_assert_equal_i(-1, apple_i); + cl_assert_equal_i(6, last_i); + cl_assert(aardvark_i < apple_after_i); + cl_assert(apple_after_i < apple_extra_i); + + git_tree_free(tree); +} diff --git a/tests/odb/alternates.c b/tests/odb/alternates.c new file mode 100644 index 000000000..c75f6feaa --- /dev/null +++ b/tests/odb/alternates.c @@ -0,0 +1,80 @@ +#include "clar_libgit2.h" +#include "odb.h" +#include "filebuf.h" + +static git_buf destpath, filepath; +static const char *paths[] = { + "A.git", "B.git", "C.git", "D.git", "E.git", "F.git", "G.git" +}; +static git_filebuf file; +static git_repository *repo; + +void test_odb_alternates__cleanup(void) +{ + size_t i; + + git_buf_free(&destpath); + git_buf_free(&filepath); + + for (i = 0; i < ARRAY_SIZE(paths); i++) + cl_fixture_cleanup(paths[i]); +} + +static void init_linked_repo(const char *path, const char *alternate) +{ + git_buf_clear(&destpath); + git_buf_clear(&filepath); + + cl_git_pass(git_repository_init(&repo, path, 1)); + cl_git_pass(git_path_prettify(&destpath, alternate, NULL)); + cl_git_pass(git_buf_joinpath(&destpath, destpath.ptr, "objects")); + cl_git_pass(git_buf_joinpath(&filepath, git_repository_path(repo), "objects/info")); + cl_git_pass(git_futils_mkdir(filepath.ptr, NULL, 0755, GIT_MKDIR_PATH)); + cl_git_pass(git_buf_joinpath(&filepath, filepath.ptr , "alternates")); + + cl_git_pass(git_filebuf_open(&file, git_buf_cstr(&filepath), 0, 0666)); + git_filebuf_printf(&file, "%s\n", git_buf_cstr(&destpath)); + cl_git_pass(git_filebuf_commit(&file)); + + git_repository_free(repo); +} + +void test_odb_alternates__chained(void) +{ + git_commit *commit; + git_oid oid; + + /* Set the alternate A -> testrepo.git */ + init_linked_repo(paths[0], cl_fixture("testrepo.git")); + + /* Set the alternate B -> A */ + init_linked_repo(paths[1], paths[0]); + + /* Now load B and see if we can find an object from testrepo.git */ + cl_git_pass(git_repository_open(&repo, paths[1])); + git_oid_fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + cl_git_pass(git_commit_lookup(&commit, repo, &oid)); + git_commit_free(commit); + git_repository_free(repo); +} + +void test_odb_alternates__long_chain(void) +{ + git_commit *commit; + git_oid oid; + size_t i; + + /* Set the alternate A -> testrepo.git */ + init_linked_repo(paths[0], cl_fixture("testrepo.git")); + + /* Set up the five-element chain */ + for (i = 1; i < ARRAY_SIZE(paths); i++) { + init_linked_repo(paths[i], paths[i-1]); + } + + /* Now load the last one and see if we can find an object from testrepo.git */ + cl_git_pass(git_repository_open(&repo, paths[ARRAY_SIZE(paths)-1])); + git_oid_fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + cl_git_fail(git_commit_lookup(&commit, repo, &oid)); + git_repository_free(repo); +} diff --git a/tests/odb/backend/nonrefreshing.c b/tests/odb/backend/nonrefreshing.c new file mode 100644 index 000000000..b43529479 --- /dev/null +++ b/tests/odb/backend/nonrefreshing.c @@ -0,0 +1,274 @@ +#include "clar_libgit2.h" +#include "git2/sys/odb_backend.h" +#include "repository.h" + +typedef struct fake_backend { + git_odb_backend parent; + + git_error_code error_code; + + int exists_calls; + int read_calls; + int read_header_calls; + int read_prefix_calls; +} fake_backend; + +static git_repository *_repo; +static fake_backend *_fake; +static git_oid _oid; + +static int fake_backend__exists(git_odb_backend *backend, const git_oid *oid) +{ + fake_backend *fake; + + GIT_UNUSED(oid); + + fake = (fake_backend *)backend; + + fake->exists_calls++; + + return (fake->error_code == GIT_OK); +} + +static int fake_backend__read( + void **buffer_p, size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *oid) +{ + fake_backend *fake; + + GIT_UNUSED(buffer_p); + GIT_UNUSED(len_p); + GIT_UNUSED(type_p); + GIT_UNUSED(oid); + + fake = (fake_backend *)backend; + + fake->read_calls++; + + *len_p = 0; + *buffer_p = NULL; + *type_p = GIT_OBJ_BLOB; + + return fake->error_code; +} + +static int fake_backend__read_header( + size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *oid) +{ + fake_backend *fake; + + GIT_UNUSED(len_p); + GIT_UNUSED(type_p); + GIT_UNUSED(oid); + + fake = (fake_backend *)backend; + + fake->read_header_calls++; + + *len_p = 0; + *type_p = GIT_OBJ_BLOB; + + return fake->error_code; +} + +static int fake_backend__read_prefix( + git_oid *out_oid, void **buffer_p, size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *short_oid, size_t len) +{ + fake_backend *fake; + + GIT_UNUSED(out_oid); + GIT_UNUSED(buffer_p); + GIT_UNUSED(len_p); + GIT_UNUSED(type_p); + GIT_UNUSED(short_oid); + GIT_UNUSED(len); + + fake = (fake_backend *)backend; + + fake->read_prefix_calls++; + + *len_p = 0; + *buffer_p = NULL; + *type_p = GIT_OBJ_BLOB; + + return fake->error_code; +} + +static void fake_backend__free(git_odb_backend *_backend) +{ + fake_backend *backend; + + backend = (fake_backend *)_backend; + + git__free(backend); +} + +static int build_fake_backend( + git_odb_backend **out, + git_error_code error_code) +{ + fake_backend *backend; + + backend = git__calloc(1, sizeof(fake_backend)); + GITERR_CHECK_ALLOC(backend); + + backend->parent.version = GIT_ODB_BACKEND_VERSION; + + backend->parent.refresh = NULL; + backend->error_code = error_code; + + backend->parent.read = fake_backend__read; + backend->parent.read_prefix = fake_backend__read_prefix; + backend->parent.read_header = fake_backend__read_header; + backend->parent.exists = fake_backend__exists; + backend->parent.free = &fake_backend__free; + + *out = (git_odb_backend *)backend; + + return 0; +} + +static void setup_repository_and_backend(git_error_code error_code) +{ + git_odb *odb = NULL; + git_odb_backend *backend = NULL; + + _repo = cl_git_sandbox_init("testrepo.git"); + + cl_git_pass(build_fake_backend(&backend, error_code)); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_git_pass(git_odb_add_backend(odb, backend, 10)); + + _fake = (fake_backend *)backend; + + cl_git_pass(git_oid_fromstr(&_oid, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")); +} + +void test_odb_backend_nonrefreshing__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_odb_backend_nonrefreshing__exists_is_invoked_once_on_failure(void) +{ + git_odb *odb; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_assert_equal_b(false, git_odb_exists(odb, &_oid)); + + cl_assert_equal_i(1, _fake->exists_calls); +} + +void test_odb_backend_nonrefreshing__read_is_invoked_once_on_failure(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_fail_with( + git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY), + GIT_ENOTFOUND); + + cl_assert_equal_i(1, _fake->read_calls); +} + +void test_odb_backend_nonrefreshing__readprefix_is_invoked_once_on_failure(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_fail_with( + git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY), + GIT_ENOTFOUND); + + cl_assert_equal_i(1, _fake->read_prefix_calls); +} + +void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_failure(void) +{ + git_odb *odb; + size_t len; + git_otype type; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + + cl_git_fail_with( + git_odb_read_header(&len, &type, odb, &_oid), + GIT_ENOTFOUND); + + cl_assert_equal_i(1, _fake->read_header_calls); +} + +void test_odb_backend_nonrefreshing__exists_is_invoked_once_on_success(void) +{ + git_odb *odb; + + setup_repository_and_backend(GIT_OK); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_assert_equal_b(true, git_odb_exists(odb, &_oid)); + + cl_assert_equal_i(1, _fake->exists_calls); +} + +void test_odb_backend_nonrefreshing__read_is_invoked_once_on_success(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_OK); + + cl_git_pass(git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY)); + + cl_assert_equal_i(1, _fake->read_calls); + + git_object_free(obj); +} + +void test_odb_backend_nonrefreshing__readprefix_is_invoked_once_on_success(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_OK); + + cl_git_pass(git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY)); + + cl_assert_equal_i(1, _fake->read_prefix_calls); + + git_object_free(obj); +} + +void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_success(void) +{ + git_odb *odb; + size_t len; + git_otype type; + + setup_repository_and_backend(GIT_OK); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + + cl_git_pass(git_odb_read_header(&len, &type, odb, &_oid)); + + cl_assert_equal_i(1, _fake->read_header_calls); +} + +void test_odb_backend_nonrefreshing__read_is_invoked_once_when_revparsing_a_full_oid(void) +{ + git_object *obj; + + setup_repository_and_backend(GIT_ENOTFOUND); + + cl_git_fail_with( + git_revparse_single(&obj, _repo, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"), + GIT_ENOTFOUND); + + cl_assert_equal_i(1, _fake->read_calls); +} diff --git a/tests/odb/foreach.c b/tests/odb/foreach.c new file mode 100644 index 000000000..f643d9621 --- /dev/null +++ b/tests/odb/foreach.c @@ -0,0 +1,80 @@ +#include "clar_libgit2.h" +#include "odb.h" +#include "git2/odb_backend.h" +#include "pack.h" + +static git_odb *_odb; +static git_repository *_repo; +static int nobj; + +void test_odb_foreach__cleanup(void) +{ + git_odb_free(_odb); + git_repository_free(_repo); + + _odb = NULL; + _repo = NULL; +} + +static int foreach_cb(const git_oid *oid, void *data) +{ + GIT_UNUSED(data); + GIT_UNUSED(oid); + + nobj++; + + return 0; +} + +/* + * $ git --git-dir tests-clar/resources/testrepo.git count-objects --verbose + * count: 47 + * size: 4 + * in-pack: 1640 + * packs: 3 + * size-pack: 425 + * prune-packable: 0 + * garbage: 0 + */ +void test_odb_foreach__foreach(void) +{ + cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); + git_repository_odb(&_odb, _repo); + + cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL)); + cl_assert_equal_i(47 + 1640, nobj); /* count + in-pack */ +} + +void test_odb_foreach__one_pack(void) +{ + git_odb_backend *backend = NULL; + + cl_git_pass(git_odb_new(&_odb)); + cl_git_pass(git_odb_backend_one_pack(&backend, cl_fixture("testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx"))); + cl_git_pass(git_odb_add_backend(_odb, backend, 1)); + _repo = NULL; + + nobj = 0; + cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL)); + cl_assert(nobj == 1628); +} + +static int foreach_stop_cb(const git_oid *oid, void *data) +{ + GIT_UNUSED(data); + GIT_UNUSED(oid); + + nobj++; + + return (nobj == 1000); +} + +void test_odb_foreach__interrupt_foreach(void) +{ + nobj = 0; + cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); + git_repository_odb(&_odb, _repo); + + cl_assert_equal_i(GIT_EUSER, git_odb_foreach(_odb, foreach_stop_cb, NULL)); + cl_assert(nobj == 1000); +} diff --git a/tests/odb/loose.c b/tests/odb/loose.c new file mode 100644 index 000000000..a85f1430d --- /dev/null +++ b/tests/odb/loose.c @@ -0,0 +1,146 @@ +#include "clar_libgit2.h" +#include "odb.h" +#include "git2/odb_backend.h" +#include "posix.h" +#include "loose_data.h" + +#ifdef __ANDROID_API__ +# define S_IREAD S_IRUSR +# define S_IWRITE S_IWUSR +#endif + +static void write_object_files(object_data *d) +{ + int fd; + + if (p_mkdir(d->dir, GIT_OBJECT_DIR_MODE) < 0) + cl_assert(errno == EEXIST); + + cl_assert((fd = p_creat(d->file, S_IREAD | S_IWRITE)) >= 0); + cl_must_pass(p_write(fd, d->bytes, d->blen)); + + p_close(fd); +} + +static void cmp_objects(git_rawobj *o, object_data *d) +{ + cl_assert(o->type == git_object_string2type(d->type)); + cl_assert(o->len == d->dlen); + + if (o->len > 0) + cl_assert(memcmp(o->data, d->data, o->len) == 0); +} + +static void test_read_object(object_data *data) +{ + git_oid id; + git_odb_object *obj; + git_odb *odb; + git_rawobj tmp; + + write_object_files(data); + + cl_git_pass(git_odb_open(&odb, "test-objects")); + cl_git_pass(git_oid_fromstr(&id, data->id)); + cl_git_pass(git_odb_read(&obj, odb, &id)); + + tmp.data = obj->buffer; + tmp.len = obj->cached.size; + tmp.type = obj->cached.type; + + cmp_objects(&tmp, data); + + git_odb_object_free(obj); + git_odb_free(odb); +} + +void test_odb_loose__initialize(void) +{ + cl_must_pass(p_mkdir("test-objects", GIT_OBJECT_DIR_MODE)); +} + +void test_odb_loose__cleanup(void) +{ + cl_fixture_cleanup("test-objects"); +} + +void test_odb_loose__exists(void) +{ + git_oid id, id2; + git_odb *odb; + + write_object_files(&one); + cl_git_pass(git_odb_open(&odb, "test-objects")); + + cl_git_pass(git_oid_fromstr(&id, one.id)); + + cl_assert(git_odb_exists(odb, &id)); + + /* Test for a non-existant object */ + cl_git_pass(git_oid_fromstr(&id2, "8b137891791fe96927ad78e64b0aad7bded08baa")); + cl_assert(!git_odb_exists(odb, &id2)); + + git_odb_free(odb); +} + +void test_odb_loose__simple_reads(void) +{ + test_read_object(&commit); + test_read_object(&tree); + test_read_object(&tag); + test_read_object(&zero); + test_read_object(&one); + test_read_object(&two); + test_read_object(&some); +} + +void test_write_object_permission( + mode_t dir_mode, mode_t file_mode, + mode_t expected_dir_mode, mode_t expected_file_mode) +{ + git_odb *odb; + git_odb_backend *backend; + git_oid oid; + struct stat statbuf; + mode_t mask, os_mask; + + /* Windows does not return group/user bits from stat, + * files are never executable. + */ +#ifdef GIT_WIN32 + os_mask = 0600; +#else + os_mask = 0777; +#endif + + mask = p_umask(0); + p_umask(mask); + + cl_git_pass(git_odb_new(&odb)); + cl_git_pass(git_odb_backend_loose(&backend, "test-objects", -1, 0, dir_mode, file_mode)); + 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)); + + cl_git_pass(p_stat("test-objects/67", &statbuf)); + cl_assert_equal_i(statbuf.st_mode & os_mask, (expected_dir_mode & ~mask) & os_mask); + + cl_git_pass(p_stat("test-objects/67/b808feb36201507a77f85e6d898f0a2836e4a5", &statbuf)); + cl_assert_equal_i(statbuf.st_mode & os_mask, (expected_file_mode & ~mask) & os_mask); + + git_odb_free(odb); +} + +void test_odb_loose__permissions_standard(void) +{ + test_write_object_permission(0, 0, GIT_OBJECT_DIR_MODE, GIT_OBJECT_FILE_MODE); +} + +void test_odb_loose_permissions_readonly(void) +{ + test_write_object_permission(0777, 0444, 0777, 0444); +} + +void test_odb_loose__permissions_readwrite(void) +{ + test_write_object_permission(0777, 0666, 0777, 0666); +} diff --git a/tests/odb/loose_data.h b/tests/odb/loose_data.h new file mode 100644 index 000000000..c10c9bc7f --- /dev/null +++ b/tests/odb/loose_data.h @@ -0,0 +1,522 @@ +typedef struct object_data { + unsigned char *bytes; /* (compressed) bytes stored in object store */ + size_t blen; /* length of data in object store */ + char *id; /* object id (sha1) */ + char *type; /* object type */ + char *dir; /* object store (fan-out) directory name */ + char *file; /* object store filename */ + unsigned char *data; /* (uncompressed) object data */ + size_t dlen; /* length of (uncompressed) object data */ +} object_data; + +/* one == 8b137891791fe96927ad78e64b0aad7bded08bdc */ +static unsigned char one_bytes[] = { + 0x31, 0x78, 0x9c, 0xe3, 0x02, 0x00, 0x00, 0x0b, + 0x00, 0x0b, +}; + +static unsigned char one_data[] = { + 0x0a, +}; + +static object_data one = { + one_bytes, + sizeof(one_bytes), + "8b137891791fe96927ad78e64b0aad7bded08bdc", + "blob", + "test-objects/8b", + "test-objects/8b/137891791fe96927ad78e64b0aad7bded08bdc", + one_data, + sizeof(one_data), +}; + + +/* commit == 3d7f8a6af076c8c3f20071a8935cdbe8228594d1 */ +static unsigned char commit_bytes[] = { + 0x78, 0x01, 0x85, 0x50, 0xc1, 0x6a, 0xc3, 0x30, + 0x0c, 0xdd, 0xd9, 0x5f, 0xa1, 0xfb, 0x96, 0x12, + 0xbb, 0x29, 0x71, 0x46, 0x19, 0x2b, 0x3d, 0x97, + 0x1d, 0xd6, 0x7d, 0x80, 0x1d, 0xcb, 0x89, 0x21, + 0xb6, 0x82, 0xed, 0x40, 0xf3, 0xf7, 0xf3, 0x48, + 0x29, 0x3b, 0x6d, 0xd2, 0xe5, 0xbd, 0x27, 0xbd, + 0x27, 0x50, 0x4f, 0xde, 0xbb, 0x0c, 0xfb, 0x43, + 0xf3, 0x94, 0x23, 0x22, 0x18, 0x6b, 0x85, 0x51, + 0x5d, 0xad, 0xc5, 0xa1, 0x41, 0xae, 0x51, 0x4b, + 0xd9, 0x19, 0x6e, 0x4b, 0x0b, 0x29, 0x35, 0x72, + 0x59, 0xef, 0x5b, 0x29, 0x8c, 0x65, 0x6a, 0xc9, + 0x23, 0x45, 0x38, 0xc1, 0x17, 0x5c, 0x7f, 0xc0, + 0x71, 0x13, 0xde, 0xf1, 0xa6, 0xfc, 0x3c, 0xe1, + 0xae, 0x27, 0xff, 0x06, 0x5c, 0x88, 0x56, 0xf2, + 0x46, 0x74, 0x2d, 0x3c, 0xd7, 0xa5, 0x58, 0x51, + 0xcb, 0xb9, 0x8c, 0x11, 0xce, 0xf0, 0x01, 0x97, + 0x0d, 0x1e, 0x1f, 0xea, 0x3f, 0x6e, 0x76, 0x02, + 0x0a, 0x58, 0x4d, 0x2e, 0x20, 0x6c, 0x1e, 0x48, + 0x8b, 0xf7, 0x2a, 0xae, 0x8c, 0x5d, 0x47, 0x04, + 0x4d, 0x66, 0x05, 0xb2, 0x90, 0x0b, 0xbe, 0xcf, + 0x3d, 0xa6, 0xa4, 0x06, 0x7c, 0x29, 0x3c, 0x64, + 0xe5, 0x82, 0x0b, 0x03, 0xd8, 0x25, 0x96, 0x8d, + 0x08, 0x78, 0x9b, 0x27, 0x15, 0x54, 0x76, 0x14, + 0xd8, 0xdd, 0x35, 0x2f, 0x71, 0xa6, 0x84, 0x8f, + 0x90, 0x51, 0x85, 0x01, 0x13, 0xb8, 0x90, 0x23, + 0x99, 0xa5, 0x47, 0x03, 0x7a, 0xfd, 0x15, 0xbf, + 0x63, 0xec, 0xd3, 0x0d, 0x01, 0x4d, 0x45, 0xb6, + 0xd2, 0xeb, 0xeb, 0xdf, 0xef, 0x60, 0xdf, 0xef, + 0x1f, 0x78, 0x35, +}; + +static unsigned char commit_data[] = { + 0x74, 0x72, 0x65, 0x65, 0x20, 0x64, 0x66, 0x66, + 0x32, 0x64, 0x61, 0x39, 0x30, 0x62, 0x32, 0x35, + 0x34, 0x65, 0x31, 0x62, 0x65, 0x62, 0x38, 0x38, + 0x39, 0x64, 0x31, 0x66, 0x31, 0x66, 0x31, 0x32, + 0x38, 0x38, 0x62, 0x65, 0x31, 0x38, 0x30, 0x33, + 0x37, 0x38, 0x32, 0x64, 0x66, 0x0a, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x20, 0x41, 0x20, 0x55, + 0x20, 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x3e, 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, + 0x31, 0x34, 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, + 0x30, 0x30, 0x30, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x72, 0x20, 0x43, 0x20, + 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72, + 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, + 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34, + 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30, + 0x30, 0x0a, 0x0a, 0x41, 0x20, 0x6f, 0x6e, 0x65, + 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x73, 0x75, 0x6d, + 0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x54, 0x68, + 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x6f, + 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, + 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72, + 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70, + 0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, + 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x0a, 0x53, 0x69, + 0x67, 0x6e, 0x65, 0x64, 0x2d, 0x6f, 0x66, 0x2d, + 0x62, 0x79, 0x3a, 0x20, 0x41, 0x20, 0x55, 0x20, + 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x3e, 0x0a, +}; + +static object_data commit = { + commit_bytes, + sizeof(commit_bytes), + "3d7f8a6af076c8c3f20071a8935cdbe8228594d1", + "commit", + "test-objects/3d", + "test-objects/3d/7f8a6af076c8c3f20071a8935cdbe8228594d1", + commit_data, + sizeof(commit_data), +}; + +/* tree == dff2da90b254e1beb889d1f1f1288be1803782df */ +static unsigned char tree_bytes[] = { + 0x78, 0x01, 0x2b, 0x29, 0x4a, 0x4d, 0x55, 0x30, + 0x34, 0x32, 0x63, 0x30, 0x34, 0x30, 0x30, 0x33, + 0x31, 0x51, 0xc8, 0xcf, 0x4b, 0x65, 0xe8, 0x16, + 0xae, 0x98, 0x58, 0x29, 0xff, 0x32, 0x53, 0x7d, + 0x6d, 0xc5, 0x33, 0x6f, 0xae, 0xb5, 0xd5, 0xf7, + 0x2e, 0x74, 0xdf, 0x81, 0x4a, 0x17, 0xe7, 0xe7, + 0xa6, 0x32, 0xfc, 0x6d, 0x31, 0xd8, 0xd3, 0xe6, + 0xf3, 0xe7, 0xea, 0x47, 0xbe, 0xd0, 0x09, 0x3f, + 0x96, 0xb8, 0x3f, 0x90, 0x9e, 0xa2, 0xfd, 0x0f, + 0x2a, 0x5f, 0x52, 0x9e, 0xcf, 0x50, 0x31, 0x43, + 0x52, 0x29, 0xd1, 0x5a, 0xeb, 0x77, 0x82, 0x2a, + 0x8b, 0xfe, 0xb7, 0xbd, 0xed, 0x5d, 0x07, 0x67, + 0xfa, 0xb5, 0x42, 0xa5, 0xab, 0x52, 0x8b, 0xf2, + 0x19, 0x9e, 0xcd, 0x7d, 0x34, 0x7b, 0xd3, 0xc5, + 0x6b, 0xce, 0xde, 0xdd, 0x9a, 0xeb, 0xca, 0xa3, + 0x6e, 0x1c, 0x7a, 0xd2, 0x13, 0x3c, 0x11, 0x00, + 0xe2, 0xaa, 0x38, 0x57, +}; + +static unsigned char tree_data[] = { + 0x31, 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x6f, + 0x6e, 0x65, 0x00, 0x8b, 0x13, 0x78, 0x91, 0x79, + 0x1f, 0xe9, 0x69, 0x27, 0xad, 0x78, 0xe6, 0x4b, + 0x0a, 0xad, 0x7b, 0xde, 0xd0, 0x8b, 0xdc, 0x31, + 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x73, 0x6f, + 0x6d, 0x65, 0x00, 0xfd, 0x84, 0x30, 0xbc, 0x86, + 0x4c, 0xfc, 0xd5, 0xf1, 0x0e, 0x55, 0x90, 0xf8, + 0xa4, 0x47, 0xe0, 0x1b, 0x94, 0x2b, 0xfe, 0x31, + 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x74, 0x77, + 0x6f, 0x00, 0x78, 0x98, 0x19, 0x22, 0x61, 0x3b, + 0x2a, 0xfb, 0x60, 0x25, 0x04, 0x2f, 0xf6, 0xbd, + 0x87, 0x8a, 0xc1, 0x99, 0x4e, 0x85, 0x31, 0x30, + 0x30, 0x36, 0x34, 0x34, 0x20, 0x7a, 0x65, 0x72, + 0x6f, 0x00, 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, + 0xd6, 0x43, 0x4b, 0x8b, 0x29, 0xae, 0x77, 0x5a, + 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91, +}; + +static object_data tree = { + tree_bytes, + sizeof(tree_bytes), + "dff2da90b254e1beb889d1f1f1288be1803782df", + "tree", + "test-objects/df", + "test-objects/df/f2da90b254e1beb889d1f1f1288be1803782df", + tree_data, + sizeof(tree_data), +}; + +/* tag == 09d373e1dfdc16b129ceec6dd649739911541e05 */ +static unsigned char tag_bytes[] = { + 0x78, 0x01, 0x35, 0x4e, 0xcb, 0x0a, 0xc2, 0x40, + 0x10, 0xf3, 0xbc, 0x5f, 0x31, 0x77, 0xa1, 0xec, + 0xa3, 0xed, 0x6e, 0x41, 0x44, 0xf0, 0x2c, 0x5e, + 0xfc, 0x81, 0xe9, 0x76, 0xb6, 0xad, 0xb4, 0xb4, + 0x6c, 0x07, 0xd1, 0xbf, 0x77, 0x44, 0x0d, 0x39, + 0x84, 0x10, 0x92, 0x30, 0xf6, 0x60, 0xbc, 0xdb, + 0x2d, 0xed, 0x9d, 0x22, 0x83, 0xeb, 0x7c, 0x0a, + 0x58, 0x63, 0xd2, 0xbe, 0x8e, 0x21, 0xba, 0x64, + 0xb5, 0xf6, 0x06, 0x43, 0xe3, 0xaa, 0xd8, 0xb5, + 0x14, 0xac, 0x0d, 0x55, 0x53, 0x76, 0x46, 0xf1, + 0x6b, 0x25, 0x88, 0xcb, 0x3c, 0x8f, 0xac, 0x58, + 0x3a, 0x1e, 0xba, 0xd0, 0x85, 0xd8, 0xd8, 0xf7, + 0x94, 0xe1, 0x0c, 0x57, 0xb8, 0x8c, 0xcc, 0x22, + 0x0f, 0xdf, 0x90, 0xc8, 0x13, 0x3d, 0x71, 0x5e, + 0x27, 0x2a, 0xc4, 0x39, 0x82, 0xb1, 0xd6, 0x07, + 0x53, 0xda, 0xc6, 0xc3, 0x5e, 0x0b, 0x94, 0xba, + 0x0d, 0xe3, 0x06, 0x42, 0x1e, 0x08, 0x3e, 0x95, + 0xbf, 0x4b, 0x69, 0xc9, 0x90, 0x69, 0x22, 0xdc, + 0xe8, 0xbf, 0xf2, 0x06, 0x42, 0x9a, 0x36, 0xb1, +}; + +static unsigned char tag_data[] = { + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x33, + 0x64, 0x37, 0x66, 0x38, 0x61, 0x36, 0x61, 0x66, + 0x30, 0x37, 0x36, 0x63, 0x38, 0x63, 0x33, 0x66, + 0x32, 0x30, 0x30, 0x37, 0x31, 0x61, 0x38, 0x39, + 0x33, 0x35, 0x63, 0x64, 0x62, 0x65, 0x38, 0x32, + 0x32, 0x38, 0x35, 0x39, 0x34, 0x64, 0x31, 0x0a, + 0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x0a, 0x74, 0x61, 0x67, 0x20, + 0x76, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0a, 0x74, + 0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x43, 0x20, + 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72, + 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e, + 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34, + 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30, + 0x30, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, + 0x61, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x30, + 0x2e, 0x30, 0x2e, 0x31, 0x0a, +}; + +static object_data tag = { + tag_bytes, + sizeof(tag_bytes), + "09d373e1dfdc16b129ceec6dd649739911541e05", + "tag", + "test-objects/09", + "test-objects/09/d373e1dfdc16b129ceec6dd649739911541e05", + tag_data, + sizeof(tag_data), +}; + +/* zero == e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 */ +static unsigned char zero_bytes[] = { + 0x78, 0x01, 0x4b, 0xca, 0xc9, 0x4f, 0x52, 0x30, + 0x60, 0x00, 0x00, 0x09, 0xb0, 0x01, 0xf0, +}; + +static unsigned char zero_data[] = { + 0x00 /* dummy data */ +}; + +static object_data zero = { + zero_bytes, + sizeof(zero_bytes), + "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "blob", + "test-objects/e6", + "test-objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391", + zero_data, + 0, +}; + +/* two == 78981922613b2afb6025042ff6bd878ac1994e85 */ +static unsigned char two_bytes[] = { + 0x78, 0x01, 0x4b, 0xca, 0xc9, 0x4f, 0x52, 0x30, + 0x62, 0x48, 0xe4, 0x02, 0x00, 0x0e, 0x64, 0x02, + 0x5d, +}; + +static unsigned char two_data[] = { + 0x61, 0x0a, +}; + +static object_data two = { + two_bytes, + sizeof(two_bytes), + "78981922613b2afb6025042ff6bd878ac1994e85", + "blob", + "test-objects/78", + "test-objects/78/981922613b2afb6025042ff6bd878ac1994e85", + two_data, + sizeof(two_data), +}; + +/* some == fd8430bc864cfcd5f10e5590f8a447e01b942bfe */ +static unsigned char some_bytes[] = { + 0x78, 0x01, 0x7d, 0x54, 0xc1, 0x4e, 0xe3, 0x30, + 0x10, 0xdd, 0x33, 0x5f, 0x31, 0xc7, 0x5d, 0x94, + 0xa5, 0x84, 0xd5, 0x22, 0xad, 0x7a, 0x0a, 0x15, + 0x85, 0x48, 0xd0, 0x56, 0x49, 0x2a, 0xd4, 0xa3, + 0x13, 0x4f, 0x88, 0x85, 0x63, 0x47, 0xb6, 0x43, + 0xc9, 0xdf, 0xef, 0x8c, 0x69, 0x17, 0x56, 0x0b, + 0x7b, 0xaa, 0x62, 0x7b, 0xde, 0xbc, 0xf7, 0xe6, + 0x4d, 0x6b, 0x6d, 0x6b, 0x48, 0xd3, 0xcb, 0x5f, + 0x5f, 0x66, 0xa7, 0x27, 0x70, 0x0a, 0x55, 0xa7, + 0x3c, 0xb4, 0x4a, 0x23, 0xf0, 0xaf, 0x43, 0x04, + 0x6f, 0xdb, 0xb0, 0x17, 0x0e, 0xe7, 0x30, 0xd9, + 0x11, 0x1a, 0x61, 0xc0, 0xa1, 0x54, 0x3e, 0x38, + 0x55, 0x8f, 0x81, 0x9e, 0x05, 0x10, 0x46, 0xce, + 0xac, 0x83, 0xde, 0x4a, 0xd5, 0x4e, 0x0c, 0x42, + 0x67, 0xa3, 0x91, 0xe8, 0x20, 0x74, 0x08, 0x01, + 0x5d, 0xef, 0xc1, 0xb6, 0xf1, 0xe3, 0x66, 0xb5, + 0x85, 0x1b, 0x34, 0xe8, 0x84, 0x86, 0xcd, 0x58, + 0x6b, 0xd5, 0xc0, 0x9d, 0x6a, 0xd0, 0x78, 0x4c, + 0xe0, 0x19, 0x9d, 0x57, 0xd6, 0xc0, 0x45, 0xc2, + 0x18, 0xc2, 0xc3, 0xc0, 0x0f, 0x7c, 0x87, 0x12, + 0xea, 0x29, 0x56, 0x2f, 0x99, 0x4f, 0x79, 0xe0, + 0x03, 0x4b, 0x4b, 0x4d, 0x44, 0xa0, 0x92, 0x33, + 0x2a, 0xe0, 0x9a, 0xdc, 0x80, 0x90, 0x52, 0xf1, + 0x11, 0x04, 0x1b, 0x4b, 0x06, 0xea, 0xae, 0x3c, + 0xe3, 0x7a, 0x50, 0x74, 0x4a, 0x84, 0xfe, 0xc3, + 0x81, 0x41, 0xf8, 0x89, 0x18, 0x43, 0x67, 0x9d, + 0x87, 0x47, 0xf5, 0x8c, 0x51, 0xf6, 0x68, 0xb4, + 0xea, 0x55, 0x20, 0x2a, 0x6f, 0x80, 0xdc, 0x42, + 0x2b, 0xf3, 0x14, 0x2b, 0x1a, 0xdb, 0x0f, 0xe4, + 0x9a, 0x64, 0x84, 0xa3, 0x90, 0xa8, 0xf9, 0x8f, + 0x9d, 0x86, 0x9e, 0xd3, 0xab, 0x5a, 0x99, 0xc8, + 0xd9, 0xc3, 0x5e, 0x85, 0x0e, 0x2c, 0xb5, 0x73, + 0x30, 0x38, 0xfb, 0xe8, 0x44, 0xef, 0x5f, 0x95, + 0x1b, 0xc9, 0xd0, 0xef, 0x3c, 0x26, 0x32, 0x1e, + 0xff, 0x2d, 0xb6, 0x23, 0x7b, 0x3f, 0xd1, 0x3c, + 0x78, 0x1a, 0x0d, 0xcb, 0xe6, 0xf6, 0xd4, 0x44, + 0x99, 0x47, 0x1a, 0x9e, 0xed, 0x23, 0xb5, 0x91, + 0x6a, 0xdf, 0x53, 0x39, 0x03, 0xf8, 0x5a, 0xb1, + 0x0f, 0x1f, 0xce, 0x81, 0x11, 0xde, 0x01, 0x7a, + 0x90, 0x16, 0xc4, 0x30, 0xe8, 0x89, 0xed, 0x7b, + 0x65, 0x4b, 0xd7, 0x03, 0x36, 0xc1, 0xcf, 0xa1, + 0xa5, 0xb1, 0xe3, 0x8b, 0xe8, 0x07, 0x4d, 0xf3, + 0x23, 0x25, 0x13, 0x35, 0x27, 0xf5, 0x8c, 0x11, + 0xd3, 0xa0, 0x9a, 0xa8, 0xf5, 0x38, 0x7d, 0xce, + 0x55, 0xc2, 0x71, 0x79, 0x13, 0xc7, 0xa3, 0xda, + 0x77, 0x68, 0xc0, 0xd8, 0x10, 0xdd, 0x24, 0x8b, + 0x15, 0x59, 0xc5, 0x10, 0xe2, 0x20, 0x99, 0x8e, + 0xf0, 0x05, 0x9b, 0x31, 0x88, 0x5a, 0xe3, 0xd9, + 0x37, 0xba, 0xe2, 0xdb, 0xbf, 0x92, 0xfa, 0x66, + 0x16, 0x97, 0x47, 0xd9, 0x9d, 0x1d, 0x28, 0x7c, + 0x9d, 0x08, 0x1c, 0xc7, 0xbd, 0xd2, 0x1a, 0x6a, + 0x04, 0xf2, 0xa2, 0x1d, 0x75, 0x02, 0x14, 0x5d, + 0xc6, 0x78, 0xc8, 0xab, 0xdb, 0xf5, 0xb6, 0x82, + 0x6c, 0xb5, 0x83, 0x87, 0xac, 0x28, 0xb2, 0x55, + 0xb5, 0x9b, 0xc7, 0xc1, 0xb0, 0xb7, 0xf8, 0x4c, + 0xbc, 0x38, 0x0e, 0x8a, 0x04, 0x2a, 0x62, 0x41, + 0x6b, 0xe0, 0x84, 0x09, 0x13, 0xe9, 0xe1, 0xea, + 0xfb, 0xeb, 0x62, 0x71, 0x4b, 0x25, 0xd9, 0x55, + 0x7e, 0x97, 0x57, 0x3b, 0x20, 0x33, 0x96, 0x79, + 0xb5, 0xba, 0x2e, 0x4b, 0x58, 0xae, 0x0b, 0xc8, + 0x60, 0x93, 0x15, 0x55, 0xbe, 0xd8, 0xde, 0x65, + 0x05, 0x6c, 0xb6, 0xc5, 0x66, 0x5d, 0x5e, 0x93, + 0xf7, 0x25, 0x65, 0x98, 0x41, 0x29, 0x86, 0x0c, + 0xf2, 0xf1, 0x14, 0xa2, 0xb3, 0xbd, 0x75, 0x08, + 0x12, 0x83, 0x50, 0xda, 0x1f, 0x23, 0xbe, 0xa3, + 0x1d, 0xf4, 0x9d, 0x1d, 0xb5, 0x84, 0x4e, 0x50, + 0x38, 0x1d, 0x36, 0x48, 0x21, 0x95, 0xd1, 0xac, + 0x81, 0x99, 0x1d, 0xc1, 0x3f, 0x41, 0xe6, 0x9e, + 0x42, 0x5b, 0x0a, 0x48, 0xcc, 0x5f, 0xe0, 0x7d, + 0x3f, 0xc4, 0x6f, 0x0e, 0xfe, 0xc0, 0x2d, 0xfe, + 0x01, 0x2c, 0xd6, 0x9b, 0x5d, 0xbe, 0xba, 0x21, + 0xca, 0x79, 0xcb, 0xe3, 0x49, 0x60, 0xef, 0x68, + 0x05, 0x28, 0x9b, 0x8c, 0xc1, 0x12, 0x3e, 0xdb, + 0xc7, 0x04, 0x7e, 0xa6, 0x74, 0x29, 0xcc, 0x13, + 0xed, 0x07, 0x94, 0x81, 0xd6, 0x96, 0xaa, 0x97, + 0xaa, 0xa5, 0xc0, 0x2f, 0xb5, 0xb5, 0x2e, 0xe6, + 0xfc, 0xca, 0xfa, 0x60, 0x4d, 0x02, 0xf7, 0x19, + 0x9c, 0x5f, 0xa4, 0xe9, 0xf9, 0xf7, 0xf4, 0xc7, + 0x79, 0x9a, 0xc0, 0xb6, 0xcc, 0x58, 0xec, 0xec, + 0xe4, 0x37, 0x22, 0xfa, 0x8b, 0x53, +}; + +static unsigned char some_data[] = { + 0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68, + 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, + 0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, + 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, + 0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, + 0x6e, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69, + 0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, + 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0a, + 0x20, 0x2a, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e, + 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, + 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c, + 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x2a, 0x20, 0x61, + 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, + 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, + 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x2a, 0x0a, + 0x20, 0x2a, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65, + 0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x20, 0x2a, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, + 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x6c, + 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x70, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e, + 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20, + 0x2a, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, + 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69, + 0x6e, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x62, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74, + 0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x67, + 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0a, 0x20, 0x2a, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, + 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, + 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x2a, + 0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20, + 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x2e, 0x20, 0x20, 0x28, 0x54, 0x68, 0x65, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, + 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, + 0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, + 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, + 0x64, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79, + 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65, + 0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, + 0x74, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, + 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x0a, 0x20, 0x2a, 0x20, 0x6d, + 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65, + 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x0a, 0x20, + 0x2a, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62, + 0x69, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, + 0x29, 0x0a, 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, + 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, + 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, + 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74, + 0x0a, 0x20, 0x2a, 0x20, 0x57, 0x49, 0x54, 0x48, + 0x4f, 0x55, 0x54, 0x20, 0x41, 0x4e, 0x59, 0x20, + 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59, + 0x3b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, + 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69, + 0x65, 0x64, 0x20, 0x77, 0x61, 0x72, 0x72, 0x61, + 0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x0a, 0x20, + 0x2a, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41, + 0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, + 0x59, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x49, 0x54, + 0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52, + 0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49, + 0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55, + 0x52, 0x50, 0x4f, 0x53, 0x45, 0x2e, 0x20, 0x20, + 0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x47, 0x4e, 0x55, 0x0a, 0x20, 0x2a, 0x20, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, + 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x64, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a, + 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x59, 0x6f, + 0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, + 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x72, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, + 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, + 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a, + 0x20, 0x2a, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, + 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, + 0x61, 0x6d, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x20, 0x43, 0x4f, 0x50, 0x59, 0x49, 0x4e, 0x47, + 0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, + 0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, + 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x2a, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, + 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, + 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x35, 0x31, 0x20, + 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x6c, 0x69, 0x6e, + 0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2c, + 0x20, 0x46, 0x69, 0x66, 0x74, 0x68, 0x20, 0x46, + 0x6c, 0x6f, 0x6f, 0x72, 0x2c, 0x0a, 0x20, 0x2a, + 0x20, 0x42, 0x6f, 0x73, 0x74, 0x6f, 0x6e, 0x2c, + 0x20, 0x4d, 0x41, 0x20, 0x30, 0x32, 0x31, 0x31, + 0x30, 0x2d, 0x31, 0x33, 0x30, 0x31, 0x2c, 0x20, + 0x55, 0x53, 0x41, 0x2e, 0x0a, 0x20, 0x2a, 0x2f, + 0x0a, +}; + +static object_data some = { + some_bytes, + sizeof(some_bytes), + "fd8430bc864cfcd5f10e5590f8a447e01b942bfe", + "blob", + "test-objects/fd", + "test-objects/fd/8430bc864cfcd5f10e5590f8a447e01b942bfe", + some_data, + sizeof(some_data), +}; diff --git a/tests/odb/mixed.c b/tests/odb/mixed.c new file mode 100644 index 000000000..51970ceec --- /dev/null +++ b/tests/odb/mixed.c @@ -0,0 +1,93 @@ +#include "clar_libgit2.h" +#include "odb.h" + +static git_odb *_odb; + +void test_odb_mixed__initialize(void) +{ + cl_git_pass(git_odb_open(&_odb, cl_fixture("duplicate.git/objects"))); +} + +void test_odb_mixed__cleanup(void) +{ + git_odb_free(_odb); + _odb = NULL; +} + +void test_odb_mixed__dup_oid(void) { + const char hex[] = "ce013625030ba8dba906f756967f9e9ca394464a"; + const char short_hex[] = "ce01362"; + git_oid oid; + git_odb_object *obj; + + cl_git_pass(git_oid_fromstr(&oid, hex)); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, GIT_OID_HEXSZ)); + git_odb_object_free(obj); + cl_git_pass(git_oid_fromstrn(&oid, short_hex, sizeof(short_hex) - 1)); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, sizeof(short_hex) - 1)); + git_odb_object_free(obj); +} + +/* some known sha collisions of file content: + * 'aabqhq' and 'aaazvc' with prefix 'dea509d0' (+ '9' and + 'b') + * 'aaeufo' and 'aaaohs' with prefix '81b5bff5' (+ 'f' and + 'b') + * 'aafewy' and 'aaepta' with prefix '739e3c4c' + * 'aahsyn' and 'aadrjg' with prefix '0ddeaded' (+ '9' and + 'e') + */ + +void test_odb_mixed__dup_oid_prefix_0(void) { + char hex[10]; + git_oid oid; + git_odb_object *obj; + + /* ambiguous in the same pack file */ + + strncpy(hex, "dea509d0", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_assert_equal_i( + GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + + strncpy(hex, "dea509d09", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + git_odb_object_free(obj); + + strncpy(hex, "dea509d0b", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + git_odb_object_free(obj); + + /* ambiguous in different pack files */ + + strncpy(hex, "81b5bff5", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_assert_equal_i( + GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + + strncpy(hex, "81b5bff5b", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + git_odb_object_free(obj); + + strncpy(hex, "81b5bff5f", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + git_odb_object_free(obj); + + /* ambiguous in pack file and loose */ + + strncpy(hex, "0ddeaded", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_assert_equal_i( + GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + + strncpy(hex, "0ddeaded9", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + git_odb_object_free(obj); + + strncpy(hex, "0ddeadede", sizeof(hex)); + cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); + cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); + git_odb_object_free(obj); +} diff --git a/tests/odb/pack_data.h b/tests/odb/pack_data.h new file mode 100644 index 000000000..e6371beb1 --- /dev/null +++ b/tests/odb/pack_data.h @@ -0,0 +1,151 @@ + +static const char *packed_objects[] = { + "0266163a49e280c4f5ed1e08facd36a2bd716bcf", + "53fc32d17276939fc79ed05badaef2db09990016", + "6336846bd5c88d32f93ae57d846683e61ab5c530", + "6dcf9bf7541ee10456529833502442f385010c3d", + "bed08a0b30b72a9d4aed7f1af8c8ca124e8d64b9", + "e90810b8df3e80c413d903f631643c716887138d", + "fc3c3a2083e9f6f89e6bd53e9420e70d1e357c9b", + "fc58168adf502d0c0ef614c3111a7038fc8c09c8", + "fd0ec0333948dfe23265ac46be0205a436a8c3a5", + "fd8430bc864cfcd5f10e5590f8a447e01b942bfe", + "fd899f45951c15c1c5f7c34b1c864e91bd6556c6", + "fda23b974899e7e1f938619099280bfda13bdca9", + "fdbec189efb657c8325962b494875987881a356b", + "fe1ca6bd22b5d8353ce6c2f3aba80805c438a7a5", + "fe3a6a42c87ff1239370c741a265f3997add87c1", + "deb106bfd2d36ecf9f0079224c12022201a39ad1", + "dec93efc79e60f2680de3e666755d335967eec30", + "def425bf8568b9c1e20879bf5be6f9c52b7361c4", + "df48000ac4f48570054e3a71a81916357997b680", + "dfae6ed8f6dd8acc3b40a31811ea316239223559", + "dff79e27d3d2cdc09790ded80fe2ea8ff5d61034", + "e00e46abe4c542e17c8bc83d72cf5be8018d7b0e", + "e01b107b4f77f8f98645adac0206a504f2d29d7c", + "e032d863f512c47b479bd984f8b6c8061f66b7d4", + "e044baa468a1c74f9f9da36805445f6888358b49", + "e04529998989ba8ae3419538dd57969af819b241", + "e0637ddfbea67c8d7f557c709e095af8906e9176", + "e0743ad4031231e71700abdc6fdbe94f189d20e5", + "cf33ac7a3d8b2b8f6bb266518aadbf59de397608", + "cf5f7235b9c9689b133f6ea12015720b411329bd", + "cf6cccf1297284833a9a03138a1f5738fa1c6c94", + "cf7992bde17ce7a79cab5f0c1fcbe8a0108721ed", + "cfe3a027ab12506d4144ee8a35669ae8fc4b7ab1", + "cfe96f31dfad7bab49977aa1df7302f7fafcb025", + "cff54d138945ef4de384e9d2759291d0c13ea90a", + "d01f7573ac34c2f502bd1cf18cde73480c741151", + "d03f567593f346a1ca96a57f8191def098d126e3", + "d047b47aadf88501238f36f5c17dd0a50dc62087", + "d0a0d63086fae3b0682af7261df21f7d0f7f066d", + "d0a44bd6ed0be21b725a96c0891bbc79bc1a540c", + "d0d7e736e536a41bcb885005f8bf258c61cad682", + "d0e7959d4b95ffec6198df6f5a7ae259b23a5f50", + "bf2fe2acca17d13356ce802ba9dc8343f710dfb7", + "bf55f407d6d9418e51f42ea7a3a6aadf17388349", + "bf92206f8b633b88a66dca4a911777630b06fbac", + "bfaf8c42eb8842abe206179fee864cfba87e3ca9", + "bfe05675d4e8f6b59d50932add8790f1a06b10ee", + "bff8618112330763327cfa6ce6e914db84f51ddf", + "bff873e9853ed99fed52c25f7ad29f78b27dcec2", + "c01c3fae7251098d7af1b459bcd0786e81d4616d", + "c0220fca67f48b8a5d4163d53b1486224be3a198", + "c02d0b160b82ee72469c269f13de4c26a7ea09cb", + "c059510ad1b45ab58390e042d7dee1ac46703854", + "c07204a1897aeeaa3c248d29dbfa9b033baf9755", + "c073337a4dd7276931b4b3fdbc3f0040e9441793", + "0fd7e4bfba5b3a82be88d1057757ca8b2c5e6d26", + "100746511cc45c9f1ad6721c4ef5be49222fee4d", + "1088490171d9b984d68b8b9be9ca003f4eafff59", + "1093c8ff4cb78fcf5f79dbbeedcb6e824bd4e253", + "10aa3fa72afab7ee31e116ae06442fe0f7b79df2", + "10b759e734e8299aa0dca08be935d95d886127b6", + "111d5ccf0bb010c4e8d7af3eedfa12ef4c5e265b", + "11261fbff21758444d426356ff6327ee01e90752", + "112998d425717bb922ce74e8f6f0f831d8dc4510", + "2ef4e5d838b6507bd61d457cf6466662b791c5c0", + "2ef4faa0f82efa00eeac6cae9e8b2abccc8566ee", + "2f06098183b0d7be350acbe39cdbaccff2df0c4a", + "2f1c5d509ac5bffb3c62f710a1c2c542e126dfd1", + "2f205b20fc16423c42b3ba51b2ea78d7b9ff3578", + "2f9b6b6e3d9250ba09360734aa47973a993b59d1", + "30c62a2d5a8d644f1311d4f7fe3f6a788e4c8188", + "31438e245492d85fd6da4d1406eba0fbde8332a4", + "3184a3abdfea231992254929ff4e275898e5bbf6", + "3188ffdbb3a3d52e0f78f30c484533899224436e", + "32581d0093429770d044a60eb0e9cc0462bedb13", + "32679a9544d83e5403202c4d5efb61ad02492847", + "4e7e9f60b7e2049b7f5697daf133161a18ef688f", + "4e8cda27ddc8be7db875ceb0f360c37734724c6d", + "4ea481c61c59ab55169b7cbaae536ad50b49d6f0", + "4f0adcd0e61eabe06fe32be66b16559537124b7a", + "4f1355c91100d12f9e7202f91b245df0c110867c", + "4f6eadeb08b9d0d1e8b1b3eac8a34940adf29a2d", + "4f9339df943c53117a5fc8e86e2f38716ff3a668", + "4fc3874b118752e40de556b1c3e7b4a9f1737d00", + "4ff1dd0992dd6baafdb5e166be6f9f23b59bdf87", + "5018a35e0b7e2eec7ce5050baf9c7343f3f74164", + "50298f44a45eda3a29dae82dbe911b5aa176ac07", + "502acd164fb115768d723144da2e7bb5a24891bb", + "50330c02bd4fd95c9db1fcf2f97f4218e42b7226", + "5052bf355d9f8c52446561a39733a8767bf31e37", + "6f2cd729ae42988c1dd43588d3a6661ba48ad7a0", + "6f4e2c42d9138bfbf3e0f908f1308828cc6f2178", + "6f6a17db05a83620cef4572761831c20a70ba9b9", + "6faad60901e36538634f0d8b8ff3f21f83503c71", + "6fc72e46de3df0c3842dab302bbacf697a63abab", + "6fdccd49f442a7204399ca9b418f017322dbded8", + "6fe7568fc3861c334cb008fd85d57d9647249ef5", + "700f55d91d7b55665594676a4bada1f1457a0598", + "702bd70595a7b19afc48a1f784a6505be68469d4", + "7033f9ee0e52b08cb5679cd49b7b7999eaf9eaf8", + "70957110ce446c4e250f865760fb3da513cdcc92", + "8ec696a4734f16479d091bc70574d23dd9fe7443", + "8ed341c55ed4d6f4cdc8bf4f0ca18a08c93f6962", + "8edc2805f1f11b63e44bf81f4557f8b473612b69", + "8ef9060a954118a698fc10e20acdc430566a100f", + "8f0c4b543f4bb6eb1518ecfc3d4699e43108d393", + "8fac94df3035405c2e60b3799153ce7c428af6b9", + "904c0ac12b23548de524adae712241b423d765a3", + "90bbaa9a809c3a768d873a9cc7d52b4f3bf3d1b9", + "90d4d2f0fc362beabbbf76b4ffda0828229c198d", + "90f9ff6755330b685feff6c3d81782ee3592ab04", + "91822c50ebe4f9bf5bbb8308ecf9f6557062775c", + "91d973263a55708fa8255867b3202d81ef9c2868", + "af292c99c6148d772af3315a1c74e83330e7ead7", + "af3b99d5be330dbbce0b9250c3a5fb05911908cc", + "af55d0cdeb280af2db8697e5afa506e081012719", + "af795e498d411142ddb073e8ca2c5447c3295a4c", + "afadc73a392f8cc8e2cc77dd62a7433dd3bafa8c", + "affd84ed8ec7ce67612fe3c12a80f8164b101f6a", + "b0941f9c70ffe67f0387a827b338e64ecf3190f0", + "b0a3077f9ef6e093f8d9869bdb0c07095bd722cb", + "b0a8568a7614806378a54db5706ee3b06ae58693", + "b0fb7372f242233d1d35ce7d8e74d3990cbc5841", + "b10489944b9ead17427551759d180d10203e06ba", + "b196a807b323f2748ffc6b1d42cd0812d04c9a40", + "b1bb1d888f0c5e19278536d49fa77db035fac7ae" +}; + +static const char *loose_objects[] = { + "45b983be36b73c0788dc9cbcb76cbb80fc7bb057", + "a8233120f6ad708f843d861ce2b7228ec4e3dec6", + "fd093bff70906175335656e6ce6ae05783708765", + "c47800c7266a2be04c571c04d5a6614691ea99bd", + "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd", + "8496071c1b46c854b31185ea97743be6a8774479", + "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", + "814889a078c031f61ed08ab5fa863aea9314344d", + "5b5b025afb0b4c913b4c338a42934a3863bf3644", + "1385f264afb75a56a5bec74243be9b367ba4ca08", + "f60079018b664e4e79329a7ef9559c8d9e0378d1", + "be3563ae3f795b2b4353bcce3a527ad0a4f7f644", + "75057dd4114e74cca1d750d0aee1647c903cb60a", + "fa49b077972391ad58037050f2a75f74e3671e92", + "9fd738e8f7967c078dceed8190330fc8648ee56a", + "1810dff58d8a660512d4832e740f692884338ccd", + "181037049a54a1eb5fab404658a3a250b44335d7", + "a4a7dce85cf63874e984719f4fdd239f5145052f", + "4a202b346bb0fb0db7eff3cffeb3c70babbd2045" +}; diff --git a/tests/odb/pack_data_one.h b/tests/odb/pack_data_one.h new file mode 100644 index 000000000..13570ba78 --- /dev/null +++ b/tests/odb/pack_data_one.h @@ -0,0 +1,19 @@ +/* Just a few to make sure it's working, the rest is tested already */ +static const char *packed_objects_one[] = { + "9fcf811e00fa469688943a9152c16d4ee90fb9a9", + "a93f42a5b5e9de40fa645a9ff1e276a021c9542b", + "12bf5f3e3470d90db177ccf1b5e8126409377fc6", + "ed1ea164cdbe3c4b200fb4fa19861ea90eaee222", + "dfae6ed8f6dd8acc3b40a31811ea316239223559", + "aefe66d192771201e369fde830530f4475beec30", + "775e4b4c1296e9e3104f2a36ca9cf9356a130959", + "412ec4e4a6a7419bc1be00561fe474e54cb499fe", + "236e7579fed7763be77209efb8708960982f3cb3", + "09fe9364461cf60dd1c46b0e9545b1e47bb1a297", + "d76d8a6390d1cf32138d98a91b1eb7e0275a12f5", + "d0fdf2dcff2f548952eec536ccc6d266550041bc", + "a20d733a9fa79fa5b4cbb9639864f93325ec27a6", + "785d3fe8e7db5ade2c2242fecd46c32a7f4dc59f", + "4d8d0fd9cb6045075385701c3f933ec13345e9c4", + "0cfd861bd547b6520d1fc2e190e8359e0a9c9b90" +}; diff --git a/tests/odb/packed.c b/tests/odb/packed.c new file mode 100644 index 000000000..b4f549b58 --- /dev/null +++ b/tests/odb/packed.c @@ -0,0 +1,79 @@ +#include "clar_libgit2.h" +#include "odb.h" +#include "pack_data.h" + +static git_odb *_odb; + +void test_odb_packed__initialize(void) +{ + cl_git_pass(git_odb_open(&_odb, cl_fixture("testrepo.git/objects"))); +} + +void test_odb_packed__cleanup(void) +{ + git_odb_free(_odb); + _odb = NULL; +} + +void test_odb_packed__mass_read(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(packed_objects); ++i) { + git_oid id; + git_odb_object *obj; + + cl_git_pass(git_oid_fromstr(&id, packed_objects[i])); + cl_assert(git_odb_exists(_odb, &id) == 1); + cl_git_pass(git_odb_read(&obj, _odb, &id)); + + git_odb_object_free(obj); + } +} + +void test_odb_packed__read_header_0(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(packed_objects); ++i) { + git_oid id; + git_odb_object *obj; + size_t len; + git_otype type; + + cl_git_pass(git_oid_fromstr(&id, packed_objects[i])); + + cl_git_pass(git_odb_read(&obj, _odb, &id)); + cl_git_pass(git_odb_read_header(&len, &type, _odb, &id)); + + cl_assert(obj->cached.size == len); + cl_assert(obj->cached.type == type); + + git_odb_object_free(obj); + } +} + +void test_odb_packed__read_header_1(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(loose_objects); ++i) { + git_oid id; + git_odb_object *obj; + size_t len; + git_otype type; + + cl_git_pass(git_oid_fromstr(&id, loose_objects[i])); + + cl_assert(git_odb_exists(_odb, &id) == 1); + + cl_git_pass(git_odb_read(&obj, _odb, &id)); + cl_git_pass(git_odb_read_header(&len, &type, _odb, &id)); + + cl_assert(obj->cached.size == len); + cl_assert(obj->cached.type == type); + + git_odb_object_free(obj); + } +} + diff --git a/tests/odb/packed_one.c b/tests/odb/packed_one.c new file mode 100644 index 000000000..0c6ed387b --- /dev/null +++ b/tests/odb/packed_one.c @@ -0,0 +1,60 @@ +#include "clar_libgit2.h" +#include "git2/odb_backend.h" + +#include "pack_data_one.h" +#include "pack.h" + +static git_odb *_odb; + +void test_odb_packed_one__initialize(void) +{ + git_odb_backend *backend = NULL; + + cl_git_pass(git_odb_new(&_odb)); + cl_git_pass(git_odb_backend_one_pack(&backend, cl_fixture("testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx"))); + cl_git_pass(git_odb_add_backend(_odb, backend, 1)); +} + +void test_odb_packed_one__cleanup(void) +{ + git_odb_free(_odb); + _odb = NULL; +} + +void test_odb_packed_one__mass_read(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(packed_objects_one); ++i) { + git_oid id; + git_odb_object *obj; + + cl_git_pass(git_oid_fromstr(&id, packed_objects_one[i])); + cl_assert(git_odb_exists(_odb, &id) == 1); + cl_git_pass(git_odb_read(&obj, _odb, &id)); + + git_odb_object_free(obj); + } +} + +void test_odb_packed_one__read_header_0(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(packed_objects_one); ++i) { + git_oid id; + git_odb_object *obj; + size_t len; + git_otype type; + + cl_git_pass(git_oid_fromstr(&id, packed_objects_one[i])); + + cl_git_pass(git_odb_read(&obj, _odb, &id)); + cl_git_pass(git_odb_read_header(&len, &type, _odb, &id)); + + cl_assert(obj->cached.size == len); + cl_assert(obj->cached.type == type); + + git_odb_object_free(obj); + } +} diff --git a/tests/odb/sorting.c b/tests/odb/sorting.c new file mode 100644 index 000000000..147a160c8 --- /dev/null +++ b/tests/odb/sorting.c @@ -0,0 +1,69 @@ +#include "clar_libgit2.h" +#include "git2/sys/odb_backend.h" + +typedef struct { + git_odb_backend base; + size_t position; +} fake_backend; + +static git_odb_backend *new_backend(size_t position) +{ + fake_backend *b; + + b = git__calloc(1, sizeof(fake_backend)); + if (b == NULL) + return NULL; + + b->base.version = GIT_ODB_BACKEND_VERSION; + b->position = position; + return (git_odb_backend *)b; +} + +static void check_backend_sorting(git_odb *odb) +{ + size_t i, max_i = git_odb_num_backends(odb); + fake_backend *internal; + + for (i = 0; i < max_i; ++i) { + cl_git_pass(git_odb_get_backend((git_odb_backend **)&internal, odb, i)); + cl_assert(internal != NULL); + cl_assert_equal_sz(i, internal->position); + } +} + +static git_odb *_odb; + +void test_odb_sorting__initialize(void) +{ + cl_git_pass(git_odb_new(&_odb)); +} + +void test_odb_sorting__cleanup(void) +{ + git_odb_free(_odb); + _odb = NULL; +} + +void test_odb_sorting__basic_backends_sorting(void) +{ + cl_git_pass(git_odb_add_backend(_odb, new_backend(0), 5)); + cl_git_pass(git_odb_add_backend(_odb, new_backend(2), 3)); + cl_git_pass(git_odb_add_backend(_odb, new_backend(1), 4)); + cl_git_pass(git_odb_add_backend(_odb, new_backend(3), 1)); + + check_backend_sorting(_odb); +} + +void test_odb_sorting__alternate_backends_sorting(void) +{ + cl_git_pass(git_odb_add_backend(_odb, new_backend(0), 5)); + cl_git_pass(git_odb_add_backend(_odb, new_backend(2), 3)); + cl_git_pass(git_odb_add_backend(_odb, new_backend(1), 4)); + cl_git_pass(git_odb_add_backend(_odb, new_backend(3), 1)); + cl_git_pass(git_odb_add_alternate(_odb, new_backend(4), 5)); + cl_git_pass(git_odb_add_alternate(_odb, new_backend(6), 3)); + cl_git_pass(git_odb_add_alternate(_odb, new_backend(5), 4)); + cl_git_pass(git_odb_add_alternate(_odb, new_backend(7), 1)); + + check_backend_sorting(_odb); +} diff --git a/tests/odb/streamwrite.c b/tests/odb/streamwrite.c new file mode 100644 index 000000000..591a20040 --- /dev/null +++ b/tests/odb/streamwrite.c @@ -0,0 +1,56 @@ +#include "clar_libgit2.h" +#include "git2/odb_backend.h" + +static git_repository *repo; +static git_odb *odb; +static git_odb_stream *stream; + +void test_odb_streamwrite__initialize(void) +{ + repo = cl_git_sandbox_init("testrepo.git"); + cl_git_pass(git_repository_odb(&odb, repo)); + + cl_git_pass(git_odb_open_wstream(&stream, odb, 14, GIT_OBJ_BLOB)); + cl_assert_equal_sz(14, stream->declared_size); +} + +void test_odb_streamwrite__cleanup(void) +{ + git_odb_stream_free(stream); + git_odb_free(odb); + cl_git_sandbox_cleanup(); +} + +void test_odb_streamwrite__can_accept_chunks(void) +{ + git_oid oid; + + cl_git_pass(git_odb_stream_write(stream, "deadbeef", 8)); + cl_assert_equal_sz(8, stream->received_bytes); + + cl_git_pass(git_odb_stream_write(stream, "deadbeef", 6)); + cl_assert_equal_sz(8 + 6, stream->received_bytes); + + cl_git_pass(git_odb_stream_finalize_write(&oid, stream)); +} + +void test_odb_streamwrite__can_detect_missing_bytes(void) +{ + git_oid oid; + + cl_git_pass(git_odb_stream_write(stream, "deadbeef", 8)); + cl_assert_equal_sz(8, stream->received_bytes); + + cl_git_pass(git_odb_stream_write(stream, "deadbeef", 4)); + cl_assert_equal_sz(8 + 4, stream->received_bytes); + + cl_git_fail(git_odb_stream_finalize_write(&oid, stream)); +} + +void test_odb_streamwrite__can_detect_additional_bytes(void) +{ + cl_git_pass(git_odb_stream_write(stream, "deadbeef", 8)); + cl_assert_equal_sz(8, stream->received_bytes); + + cl_git_fail(git_odb_stream_write(stream, "deadbeef", 7)); +} diff --git a/tests/online/clone.c b/tests/online/clone.c new file mode 100644 index 000000000..aa3d6b26a --- /dev/null +++ b/tests/online/clone.c @@ -0,0 +1,256 @@ +#include "clar_libgit2.h" + +#include "git2/clone.h" +#include "git2/cred_helpers.h" +#include "remote.h" +#include "fileops.h" +#include "refs.h" + +#define LIVE_REPO_URL "http://github.com/libgit2/TestGitRepository" +#define LIVE_EMPTYREPO_URL "http://github.com/libgit2/TestEmptyRepository" +#define BB_REPO_URL "https://libgit2@bitbucket.org/libgit2/testgitrepository.git" +#define BB_REPO_URL_WITH_PASS "https://libgit2:libgit2@bitbucket.org/libgit2/testgitrepository.git" +#define BB_REPO_URL_WITH_WRONG_PASS "https://libgit2:wrong@bitbucket.org/libgit2/testgitrepository.git" +#define ASSEMBLA_REPO_URL "https://libgit2:_Libgit2@git.assembla.com/libgit2-test-repos.git" + +static git_repository *g_repo; +static git_clone_options g_options; + +void test_online_clone__initialize(void) +{ + git_checkout_opts dummy_opts = GIT_CHECKOUT_OPTS_INIT; + git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; + + g_repo = NULL; + + memset(&g_options, 0, sizeof(git_clone_options)); + g_options.version = GIT_CLONE_OPTIONS_VERSION; + g_options.checkout_opts = dummy_opts; + g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; + g_options.remote_callbacks = dummy_callbacks; +} + +void test_online_clone__cleanup(void) +{ + if (g_repo) { + git_repository_free(g_repo); + g_repo = NULL; + } + cl_fixture_cleanup("./foo"); +} + +void test_online_clone__network_full(void) +{ + git_remote *origin; + + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); + cl_assert(!git_repository_is_bare(g_repo)); + cl_git_pass(git_remote_load(&origin, g_repo, "origin")); + + cl_assert_equal_i(GIT_REMOTE_DOWNLOAD_TAGS_AUTO, origin->download_tags); + + git_remote_free(origin); +} + +void test_online_clone__network_bare(void) +{ + git_remote *origin; + + g_options.bare = true; + + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); + cl_assert(git_repository_is_bare(g_repo)); + cl_git_pass(git_remote_load(&origin, g_repo, "origin")); + + git_remote_free(origin); +} + +void test_online_clone__empty_repository(void) +{ + git_reference *head; + + cl_git_pass(git_clone(&g_repo, LIVE_EMPTYREPO_URL, "./foo", &g_options)); + + cl_assert_equal_i(true, git_repository_is_empty(g_repo)); + cl_assert_equal_i(true, git_repository_head_unborn(g_repo)); + + cl_git_pass(git_reference_lookup(&head, g_repo, GIT_HEAD_FILE)); + cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); + cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); + + git_reference_free(head); +} + +static void checkout_progress(const char *path, size_t cur, size_t tot, void *payload) +{ + bool *was_called = (bool*)payload; + GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot); + (*was_called) = true; +} + +static int fetch_progress(const git_transfer_progress *stats, void *payload) +{ + bool *was_called = (bool*)payload; + GIT_UNUSED(stats); + (*was_called) = true; + return 0; +} + +void test_online_clone__can_checkout_a_cloned_repo(void) +{ + git_buf path = GIT_BUF_INIT; + git_reference *head; + bool checkout_progress_cb_was_called = false, + fetch_progress_cb_was_called = false; + + g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + g_options.checkout_opts.progress_cb = &checkout_progress; + g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called; + g_options.remote_callbacks.transfer_progress = &fetch_progress; + g_options.remote_callbacks.payload = &fetch_progress_cb_was_called; + + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); + cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path))); + + cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); + cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); + cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); + + cl_assert_equal_i(true, checkout_progress_cb_was_called); + cl_assert_equal_i(true, fetch_progress_cb_was_called); + + git_reference_free(head); + git_buf_free(&path); +} + +void test_online_clone__clone_into(void) +{ + git_buf path = GIT_BUF_INIT; + git_remote *remote; + git_reference *head; + git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + bool checkout_progress_cb_was_called = false, + fetch_progress_cb_was_called = false; + + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; + checkout_opts.progress_cb = &checkout_progress; + checkout_opts.progress_payload = &checkout_progress_cb_was_called; + + cl_git_pass(git_repository_init(&g_repo, "./foo", false)); + cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL)); + + callbacks.transfer_progress = &fetch_progress; + callbacks.payload = &fetch_progress_cb_was_called; + git_remote_set_callbacks(remote, &callbacks); + + cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL)); + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); + cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path))); + + cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); + cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); + cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); + + cl_assert_equal_i(true, checkout_progress_cb_was_called); + cl_assert_equal_i(true, fetch_progress_cb_was_called); + + git_remote_free(remote); + git_reference_free(head); + git_buf_free(&path); +} + +static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *payload) +{ + int *callcount = (int*)payload; + GIT_UNUSED(refname); GIT_UNUSED(a); GIT_UNUSED(b); + *callcount = *callcount + 1; + return 0; +} + +void test_online_clone__custom_remote_callbacks(void) +{ + int callcount = 0; + + g_options.remote_callbacks.update_tips = update_tips; + g_options.remote_callbacks.payload = &callcount; + + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); + cl_assert(callcount > 0); +} + +void test_online_clone__credentials(void) +{ + /* Remote URL environment variable must be set. User and password are optional. */ + const char *remote_url = cl_getenv("GITTEST_REMOTE_URL"); + git_cred_userpass_payload user_pass = { + cl_getenv("GITTEST_REMOTE_USER"), + cl_getenv("GITTEST_REMOTE_PASS") + }; + + if (!remote_url) return; + + g_options.remote_callbacks.credentials = git_cred_userpass; + g_options.remote_callbacks.payload = &user_pass; + + cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options)); + git_repository_free(g_repo); g_repo = NULL; + cl_fixture_cleanup("./foo"); +} + +void test_online_clone__bitbucket_style(void) +{ + git_cred_userpass_payload user_pass = { + "libgit2", "libgit2" + }; + + g_options.remote_callbacks.credentials = git_cred_userpass; + g_options.remote_callbacks.payload = &user_pass; + + cl_git_pass(git_clone(&g_repo, BB_REPO_URL, "./foo", &g_options)); + git_repository_free(g_repo); g_repo = NULL; + cl_fixture_cleanup("./foo"); + + /* User and pass from URL */ + user_pass.password = "wrong"; + cl_git_pass(git_clone(&g_repo, BB_REPO_URL_WITH_PASS, "./foo", &g_options)); + git_repository_free(g_repo); g_repo = NULL; + cl_fixture_cleanup("./foo"); + + /* Wrong password in URL, fall back to user_pass */ + user_pass.password = "libgit2"; + cl_git_pass(git_clone(&g_repo, BB_REPO_URL_WITH_WRONG_PASS, "./foo", &g_options)); + git_repository_free(g_repo); g_repo = NULL; + cl_fixture_cleanup("./foo"); +} + +void test_online_clone__assembla_style(void) +{ + cl_git_pass(git_clone(&g_repo, ASSEMBLA_REPO_URL, "./foo", NULL)); +} + +static int cancel_at_half(const git_transfer_progress *stats, void *payload) +{ + GIT_UNUSED(payload); + + if (stats->received_objects > (stats->total_objects/2)) + return 1; + return 0; +} + +void test_online_clone__can_cancel(void) +{ + g_options.remote_callbacks.transfer_progress = cancel_at_half; + + cl_git_fail_with(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options), GIT_EUSER); +} + + + + + + diff --git a/tests/online/fetch.c b/tests/online/fetch.c new file mode 100644 index 000000000..5153a7ae0 --- /dev/null +++ b/tests/online/fetch.c @@ -0,0 +1,171 @@ +#include "clar_libgit2.h" + +static git_repository *_repo; +static int counter; + +void test_online_fetch__initialize(void) +{ + cl_git_pass(git_repository_init(&_repo, "./fetch", 0)); +} + +void test_online_fetch__cleanup(void) +{ + git_repository_free(_repo); + _repo = NULL; + + cl_fixture_cleanup("./fetch"); +} + +static int update_tips(const char *refname, const git_oid *a, const git_oid *b, void *data) +{ + GIT_UNUSED(refname); GIT_UNUSED(a); GIT_UNUSED(b); GIT_UNUSED(data); + + ++counter; + + return 0; +} + +static int progress(const git_transfer_progress *stats, void *payload) +{ + size_t *bytes_received = (size_t *)payload; + *bytes_received = stats->received_bytes; + return 0; +} + +static void do_fetch(const char *url, git_remote_autotag_option_t flag, int n) +{ + git_remote *remote; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + size_t bytes_received = 0; + + callbacks.transfer_progress = progress; + callbacks.update_tips = update_tips; + callbacks.payload = &bytes_received; + counter = 0; + + cl_git_pass(git_remote_create(&remote, _repo, "test", url)); + git_remote_set_callbacks(remote, &callbacks); + git_remote_set_autotag(remote, flag); + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_download(remote)); + cl_git_pass(git_remote_update_tips(remote)); + git_remote_disconnect(remote); + cl_assert_equal_i(counter, n); + cl_assert(bytes_received > 0); + + git_remote_free(remote); +} + +void test_online_fetch__default_git(void) +{ + do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); +} + +void test_online_fetch__default_http(void) +{ + do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); +} + +void test_online_fetch__default_https(void) +{ + do_fetch("https://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_AUTO, 6); +} + +void test_online_fetch__no_tags_git(void) +{ + do_fetch("git://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3); +} + +void test_online_fetch__no_tags_http(void) +{ + do_fetch("http://github.com/libgit2/TestGitRepository.git", GIT_REMOTE_DOWNLOAD_TAGS_NONE, 3); +} + +static int transferProgressCallback(const git_transfer_progress *stats, void *payload) +{ + bool *invoked = (bool *)payload; + + GIT_UNUSED(stats); + *invoked = true; + return 0; +} + +void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date(void) +{ + git_repository *_repository; + bool invoked = false; + git_remote *remote; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + git_clone_options opts = GIT_CLONE_OPTIONS_INIT; + opts.bare = true; + + cl_git_pass(git_clone(&_repository, "https://github.com/libgit2/TestGitRepository.git", + "./fetch/lg2", &opts)); + git_repository_free(_repository); + + cl_git_pass(git_repository_open(&_repository, "./fetch/lg2")); + + cl_git_pass(git_remote_load(&remote, _repository, "origin")); + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + + cl_assert_equal_i(false, invoked); + + callbacks.transfer_progress = &transferProgressCallback; + callbacks.payload = &invoked; + git_remote_set_callbacks(remote, &callbacks); + cl_git_pass(git_remote_download(remote)); + + cl_assert_equal_i(false, invoked); + + cl_git_pass(git_remote_update_tips(remote)); + git_remote_disconnect(remote); + + git_remote_free(remote); + git_repository_free(_repository); +} + +static int cancel_at_half(const git_transfer_progress *stats, void *payload) +{ + GIT_UNUSED(payload); + + if (stats->received_objects > (stats->total_objects/2)) + return -1; + return 0; +} + +void test_online_fetch__can_cancel(void) +{ + git_remote *remote; + size_t bytes_received = 0; + git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; + + cl_git_pass(git_remote_create(&remote, _repo, "test", + "http://github.com/libgit2/TestGitRepository.git")); + + callbacks.transfer_progress = cancel_at_half; + callbacks.payload = &bytes_received; + git_remote_set_callbacks(remote, &callbacks); + + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + cl_git_fail_with(git_remote_download(remote), GIT_EUSER); + git_remote_disconnect(remote); + git_remote_free(remote); +} + +void test_online_fetch__ls_disconnected(void) +{ + const git_remote_head **refs; + size_t refs_len_before, refs_len_after; + git_remote *remote; + + cl_git_pass(git_remote_create(&remote, _repo, "test", + "http://github.com/libgit2/TestGitRepository.git")); + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_ls(&refs, &refs_len_before, remote)); + git_remote_disconnect(remote); + cl_git_pass(git_remote_ls(&refs, &refs_len_after, remote)); + + cl_assert_equal_i(refs_len_before, refs_len_after); + + git_remote_free(remote); +} diff --git a/tests/online/fetchhead.c b/tests/online/fetchhead.c new file mode 100644 index 000000000..57b183f88 --- /dev/null +++ b/tests/online/fetchhead.c @@ -0,0 +1,91 @@ +#include "clar_libgit2.h" + +#include "fileops.h" +#include "fetchhead.h" +#include "../fetchhead/fetchhead_data.h" +#include "git2/clone.h" + +#define LIVE_REPO_URL "git://github.com/libgit2/TestGitRepository" + +static git_repository *g_repo; +static git_clone_options g_options; + +void test_online_fetchhead__initialize(void) +{ + git_remote_callbacks dummy_callbacks = GIT_REMOTE_CALLBACKS_INIT; + g_repo = NULL; + + memset(&g_options, 0, sizeof(git_clone_options)); + g_options.version = GIT_CLONE_OPTIONS_VERSION; + g_options.remote_callbacks = dummy_callbacks; +} + +void test_online_fetchhead__cleanup(void) +{ + if (g_repo) { + git_repository_free(g_repo); + g_repo = NULL; + } + + cl_fixture_cleanup("./foo"); +} + +static void fetchhead_test_clone(void) +{ + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options)); +} + +static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fetchhead) +{ + git_remote *remote; + git_buf fetchhead_buf = GIT_BUF_INIT; + int equals = 0; + + cl_git_pass(git_remote_load(&remote, g_repo, "origin")); + git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_AUTO); + + if(fetchspec != NULL) { + git_remote_clear_refspecs(remote); + git_remote_add_fetch(remote, fetchspec); + } + + cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_download(remote)); + cl_git_pass(git_remote_update_tips(remote)); + git_remote_disconnect(remote); + git_remote_free(remote); + + cl_git_pass(git_futils_readbuffer(&fetchhead_buf, "./foo/.git/FETCH_HEAD")); + + equals = (strcmp(fetchhead_buf.ptr, expected_fetchhead) == 0); + + git_buf_free(&fetchhead_buf); + + cl_assert(equals); +} + +void test_online_fetchhead__wildcard_spec(void) +{ + fetchhead_test_clone(); + fetchhead_test_fetch(NULL, FETCH_HEAD_WILDCARD_DATA); +} + +void test_online_fetchhead__explicit_spec(void) +{ + fetchhead_test_clone(); + fetchhead_test_fetch("refs/heads/first-merge:refs/remotes/origin/first-merge", FETCH_HEAD_EXPLICIT_DATA); +} + +void test_online_fetchhead__no_merges(void) +{ + git_config *config; + + fetchhead_test_clone(); + + cl_git_pass(git_repository_config(&config, g_repo)); + cl_git_pass(git_config_delete_entry(config, "branch.master.remote")); + cl_git_pass(git_config_delete_entry(config, "branch.master.merge")); + git_config_free(config); + + fetchhead_test_fetch(NULL, FETCH_HEAD_NO_MERGE_DATA); +} diff --git a/tests/online/push.c b/tests/online/push.c new file mode 100644 index 000000000..aeb1ab47d --- /dev/null +++ b/tests/online/push.c @@ -0,0 +1,770 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "posix.h" +#include "vector.h" +#include "../submodule/submodule_helpers.h" +#include "push_util.h" +#include "refspec.h" +#include "remote.h" + +static git_repository *_repo; + +static char *_remote_ssh_key; +static char *_remote_ssh_pubkey; +static char *_remote_ssh_passphrase; + +static char *_remote_url; +static char *_remote_user; +static char *_remote_pass; + +static int cred_acquire_cb(git_cred **, const char *, const char *, unsigned int, void *); + +static git_remote *_remote; +static record_callbacks_data _record_cbs_data = {{ 0 }}; +static git_remote_callbacks _record_cbs = RECORD_CALLBACKS_INIT(&_record_cbs_data); + +static git_oid _oid_b6; +static git_oid _oid_b5; +static git_oid _oid_b4; +static git_oid _oid_b3; +static git_oid _oid_b2; +static git_oid _oid_b1; + +static git_oid _tag_commit; +static git_oid _tag_tree; +static git_oid _tag_blob; +static git_oid _tag_lightweight; +static git_oid _tag_tag; + +static int cred_acquire_cb( + git_cred **cred, + const char *url, + const char *user_from_url, + unsigned int allowed_types, + void *payload) +{ + GIT_UNUSED(url); + GIT_UNUSED(user_from_url); + GIT_UNUSED(payload); + + if (GIT_CREDTYPE_SSH_KEY & allowed_types) { + if (!_remote_user || !_remote_ssh_pubkey || !_remote_ssh_key || !_remote_ssh_passphrase) { + printf("GITTEST_REMOTE_USER, GITTEST_REMOTE_SSH_PUBKEY, GITTEST_REMOTE_SSH_KEY and GITTEST_REMOTE_SSH_PASSPHRASE must be set\n"); + return -1; + } + return git_cred_ssh_key_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase); + } + + if (GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) { + if (!_remote_user || !_remote_pass) { + printf("GITTEST_REMOTE_USER and GITTEST_REMOTE_PASS must be set\n"); + return -1; + } + + return git_cred_userpass_plaintext_new(cred, _remote_user, _remote_pass); + } + + return -1; +} + +/* the results of a push status. when used for expected values, msg may be NULL + * to indicate that it should not be matched. */ +typedef struct { + const char *ref; + int success; + const char *msg; +} push_status; + +/** + * git_push_status_foreach callback that records status entries. + * @param data (git_vector *) of push_status instances + */ +static int record_push_status_cb(const char *ref, const char *msg, void *data) +{ + git_vector *statuses = (git_vector *)data; + push_status *s; + + cl_assert(s = git__malloc(sizeof(*s))); + s->ref = ref; + s->success = (msg == NULL); + s->msg = msg; + + git_vector_insert(statuses, s); + + return 0; +} + +static void do_verify_push_status(git_push *push, const push_status expected[], const size_t expected_len) +{ + git_vector actual = GIT_VECTOR_INIT; + push_status *iter; + bool failed = false; + size_t i; + + git_push_status_foreach(push, record_push_status_cb, &actual); + + if (expected_len != actual.length) + failed = true; + else + git_vector_foreach(&actual, i, iter) + if (strcmp(expected[i].ref, iter->ref) || + (expected[i].success != iter->success) || + (expected[i].msg && (!iter->msg || strcmp(expected[i].msg, iter->msg)))) { + failed = true; + break; + } + + if (failed) { + git_buf msg = GIT_BUF_INIT; + + git_buf_puts(&msg, "Expected and actual push statuses differ:\nEXPECTED:\n"); + + for(i = 0; i < expected_len; i++) { + git_buf_printf(&msg, "%s: %s\n", + expected[i].ref, + expected[i].success ? "success" : "failed"); + } + + git_buf_puts(&msg, "\nACTUAL:\n"); + + git_vector_foreach(&actual, i, iter) { + if (iter->success) + git_buf_printf(&msg, "%s: success\n", iter->ref); + else + git_buf_printf(&msg, "%s: failed with message: %s", iter->ref, iter->msg); + } + + cl_fail(git_buf_cstr(&msg)); + + git_buf_free(&msg); + } + + git_vector_foreach(&actual, i, iter) + git__free(iter); + + git_vector_free(&actual); +} + +/** + * Verifies that after git_push_finish(), refs on a remote have the expected + * names, oids, and order. + * + * @param remote remote to verify + * @param expected_refs expected remote refs after push + * @param expected_refs_len length of expected_refs + */ +static void verify_refs(git_remote *remote, expected_ref expected_refs[], size_t expected_refs_len) +{ + const git_remote_head **actual_refs; + size_t actual_refs_len; + + git_remote_ls(&actual_refs, &actual_refs_len, remote); + verify_remote_refs(actual_refs, actual_refs_len, expected_refs, expected_refs_len); +} + +/** + * Verifies that after git_push_update_tips(), remote tracking branches have the expected + * names and oids. + * + * @param remote remote to verify + * @param expected_refs expected remote refs after push + * @param expected_refs_len length of expected_refs + */ +static void verify_tracking_branches(git_remote *remote, expected_ref expected_refs[], size_t expected_refs_len) +{ + git_refspec *fetch_spec; + size_t i, j; + git_buf msg = GIT_BUF_INIT; + git_buf ref_name = GIT_BUF_INIT; + git_vector actual_refs = GIT_VECTOR_INIT; + git_branch_iterator *iter; + char *actual_ref; + git_oid oid; + int failed = 0, error; + git_branch_t branch_type; + git_reference *ref; + + /* Get current remote branches */ + cl_git_pass(git_branch_iterator_new(&iter, remote->repo, GIT_BRANCH_REMOTE)); + + while ((error = git_branch_next(&ref, &branch_type, iter)) == 0) { + cl_assert_equal_i(branch_type, GIT_BRANCH_REMOTE); + + cl_git_pass(git_vector_insert(&actual_refs, git__strdup(git_reference_name(ref)))); + } + + cl_assert_equal_i(error, GIT_ITEROVER); + + /* Loop through expected refs, make sure they exist */ + for (i = 0; i < expected_refs_len; i++) { + + /* Convert remote reference name into tracking branch name. + * If the spec is not under refs/heads/, then skip. + */ + fetch_spec = git_remote__matching_refspec(remote, expected_refs[i].name); + if (!fetch_spec) + continue; + + cl_git_pass(git_refspec_transform_r(&ref_name, fetch_spec, expected_refs[i].name)); + + /* Find matching remote branch */ + git_vector_foreach(&actual_refs, j, actual_ref) { + if (!strcmp(git_buf_cstr(&ref_name), actual_ref)) + break; + } + + if (j == actual_refs.length) { + git_buf_printf(&msg, "Did not find expected tracking branch '%s'.", git_buf_cstr(&ref_name)); + failed = 1; + goto failed; + } + + /* Make sure tracking branch is at expected commit ID */ + cl_git_pass(git_reference_name_to_id(&oid, remote->repo, actual_ref)); + + if (git_oid_cmp(expected_refs[i].oid, &oid) != 0) { + git_buf_puts(&msg, "Tracking branch commit does not match expected ID."); + failed = 1; + goto failed; + } + + git__free(actual_ref); + cl_git_pass(git_vector_remove(&actual_refs, j)); + } + + /* Make sure there are no extra branches */ + if (actual_refs.length > 0) { + git_buf_puts(&msg, "Unexpected remote tracking branches exist."); + failed = 1; + goto failed; + } + +failed: + + if(failed) + cl_fail(git_buf_cstr(&msg)); + + git_vector_foreach(&actual_refs, i, actual_ref) + git__free(actual_ref); + + git_vector_free(&actual_refs); + git_buf_free(&msg); + git_buf_free(&ref_name); + return; +} + +void test_online_push__initialize(void) +{ + git_vector delete_specs = GIT_VECTOR_INIT; + const git_remote_head **heads; + size_t i, heads_len; + char *curr_del_spec; + + _repo = cl_git_sandbox_init("push_src"); + + cl_fixture_sandbox("testrepo.git"); + cl_rename("push_src/submodule/.gitted", "push_src/submodule/.git"); + + rewrite_gitmodules(git_repository_workdir(_repo)); + + /* git log --format=oneline --decorate --graph + * *-. 951bbbb90e2259a4c8950db78946784fb53fcbce (HEAD, b6) merge b3, b4, and b5 to b6 + * |\ \ + * | | * fa38b91f199934685819bea316186d8b008c52a2 (b5) added submodule named 'submodule' pointing to '../testrepo.git' + * | * | 27b7ce66243eb1403862d05f958c002312df173d (b4) edited fold\b.txt + * | |/ + * * | d9b63a88223d8367516f50bd131a5f7349b7f3e4 (b3) edited a.txt + * |/ + * * a78705c3b2725f931d3ee05348d83cc26700f247 (b2, b1) added fold and fold/b.txt + * * 5c0bb3d1b9449d1cc69d7519fd05166f01840915 added a.txt + */ + git_oid_fromstr(&_oid_b6, "951bbbb90e2259a4c8950db78946784fb53fcbce"); + git_oid_fromstr(&_oid_b5, "fa38b91f199934685819bea316186d8b008c52a2"); + git_oid_fromstr(&_oid_b4, "27b7ce66243eb1403862d05f958c002312df173d"); + git_oid_fromstr(&_oid_b3, "d9b63a88223d8367516f50bd131a5f7349b7f3e4"); + git_oid_fromstr(&_oid_b2, "a78705c3b2725f931d3ee05348d83cc26700f247"); + git_oid_fromstr(&_oid_b1, "a78705c3b2725f931d3ee05348d83cc26700f247"); + + git_oid_fromstr(&_tag_commit, "805c54522e614f29f70d2413a0470247d8b424ac"); + git_oid_fromstr(&_tag_tree, "ff83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e"); + git_oid_fromstr(&_tag_blob, "b483ae7ba66decee9aee971f501221dea84b1498"); + git_oid_fromstr(&_tag_lightweight, "951bbbb90e2259a4c8950db78946784fb53fcbce"); + git_oid_fromstr(&_tag_tag, "eea4f2705eeec2db3813f2430829afce99cd00b5"); + + /* Remote URL environment variable must be set. User and password are optional. */ + _remote_url = cl_getenv("GITTEST_REMOTE_URL"); + _remote_user = cl_getenv("GITTEST_REMOTE_USER"); + _remote_pass = cl_getenv("GITTEST_REMOTE_PASS"); + _remote_ssh_key = cl_getenv("GITTEST_REMOTE_SSH_KEY"); + _remote_ssh_pubkey = cl_getenv("GITTEST_REMOTE_SSH_PUBKEY"); + _remote_ssh_passphrase = cl_getenv("GITTEST_REMOTE_SSH_PASSPHRASE"); + _remote = NULL; + + if (_remote_url) { + cl_git_pass(git_remote_create(&_remote, _repo, "test", _remote_url)); + + record_callbacks_data_clear(&_record_cbs_data); + git_remote_set_callbacks(_remote, &_record_cbs); + + cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); + + /* Clean up previously pushed branches. Fails if receive.denyDeletes is + * set on the remote. Also, on Git 1.7.0 and newer, you must run + * 'git config receive.denyDeleteCurrent ignore' in the remote repo in + * order to delete the remote branch pointed to by HEAD (usually master). + * See: https://raw.github.com/git/git/master/Documentation/RelNotes/1.7.0.txt + */ + cl_git_pass(git_remote_ls(&heads, &heads_len, _remote)); + cl_git_pass(create_deletion_refspecs(&delete_specs, heads, heads_len)); + if (delete_specs.length) { + git_push *push; + + cl_git_pass(git_push_new(&push, _remote)); + + git_vector_foreach(&delete_specs, i, curr_del_spec) { + git_push_add_refspec(push, curr_del_spec); + git__free(curr_del_spec); + } + + cl_git_pass(git_push_finish(push)); + git_push_free(push); + } + + git_remote_disconnect(_remote); + git_vector_free(&delete_specs); + + /* Now that we've deleted everything, fetch from the remote */ + cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_FETCH)); + cl_git_pass(git_remote_download(_remote)); + cl_git_pass(git_remote_update_tips(_remote)); + git_remote_disconnect(_remote); + } else + printf("GITTEST_REMOTE_URL unset; skipping push test\n"); +} + +void test_online_push__cleanup(void) +{ + if (_remote) + git_remote_free(_remote); + _remote = NULL; + + /* Freed by cl_git_sandbox_cleanup */ + _repo = NULL; + + record_callbacks_data_clear(&_record_cbs_data); + + cl_fixture_cleanup("testrepo.git"); + cl_git_sandbox_cleanup(); +} + +static int push_pack_progress_cb(int stage, unsigned int current, unsigned int total, void* payload) +{ + int *was_called = (int *) payload; + GIT_UNUSED(stage); GIT_UNUSED(current); GIT_UNUSED(total); + *was_called = 1; + return 0; +} + +static int push_transfer_progress_cb(unsigned int current, unsigned int total, size_t bytes, void* payload) +{ + int *was_called = (int *) payload; + GIT_UNUSED(current); GIT_UNUSED(total); GIT_UNUSED(bytes); + *was_called = 1; + return 0; +} + +/** + * Calls push and relists refs on remote to verify success. + * + * @param refspecs refspecs to push + * @param refspecs_len length of refspecs + * @param expected_refs expected remote refs after push + * @param expected_refs_len length of expected_refs + * @param expected_ret expected return value from git_push_finish() + * @param check_progress_cb Check that the push progress callbacks are called + */ +static void do_push(const char *refspecs[], size_t refspecs_len, + push_status expected_statuses[], size_t expected_statuses_len, + expected_ref expected_refs[], size_t expected_refs_len, int expected_ret, int check_progress_cb) +{ + git_push *push; + git_push_options opts = GIT_PUSH_OPTIONS_INIT; + size_t i; + int ret; + int pack_progress_called = 0, transfer_progress_called = 0; + + if (_remote) { + /* Auto-detect the number of threads to use */ + opts.pb_parallelism = 0; + + cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); + + cl_git_pass(git_push_new(&push, _remote)); + cl_git_pass(git_push_set_options(push, &opts)); + + if (check_progress_cb) + cl_git_pass(git_push_set_callbacks(push, push_pack_progress_cb, &pack_progress_called, push_transfer_progress_cb, &transfer_progress_called)); + + for (i = 0; i < refspecs_len; i++) + cl_git_pass(git_push_add_refspec(push, refspecs[i])); + + if (expected_ret < 0) { + cl_git_fail(ret = git_push_finish(push)); + cl_assert_equal_i(0, git_push_unpack_ok(push)); + } + else { + cl_git_pass(ret = git_push_finish(push)); + cl_assert_equal_i(1, git_push_unpack_ok(push)); + } + + if (check_progress_cb) { + cl_assert_equal_i(1, pack_progress_called); + cl_assert_equal_i(1, transfer_progress_called); + } + + do_verify_push_status(push, expected_statuses, expected_statuses_len); + + cl_assert_equal_i(expected_ret, ret); + + verify_refs(_remote, expected_refs, expected_refs_len); + + cl_git_pass(git_push_update_tips(push)); + verify_tracking_branches(_remote, expected_refs, expected_refs_len); + + git_push_free(push); + + git_remote_disconnect(_remote); + } +} + +/* Call push_finish() without ever calling git_push_add_refspec() */ +void test_online_push__noop(void) +{ + do_push(NULL, 0, NULL, 0, NULL, 0, 0, 0); +} + +void test_online_push__b1(void) +{ + const char *specs[] = { "refs/heads/b1:refs/heads/b1" }; + push_status exp_stats[] = { { "refs/heads/b1", 1 } }; + expected_ref exp_refs[] = { { "refs/heads/b1", &_oid_b1 } }; + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); +} + +void test_online_push__b2(void) +{ + const char *specs[] = { "refs/heads/b2:refs/heads/b2" }; + push_status exp_stats[] = { { "refs/heads/b2", 1 } }; + expected_ref exp_refs[] = { { "refs/heads/b2", &_oid_b2 } }; + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); +} + +void test_online_push__b3(void) +{ + const char *specs[] = { "refs/heads/b3:refs/heads/b3" }; + push_status exp_stats[] = { { "refs/heads/b3", 1 } }; + expected_ref exp_refs[] = { { "refs/heads/b3", &_oid_b3 } }; + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); +} + +void test_online_push__b4(void) +{ + const char *specs[] = { "refs/heads/b4:refs/heads/b4" }; + push_status exp_stats[] = { { "refs/heads/b4", 1 } }; + expected_ref exp_refs[] = { { "refs/heads/b4", &_oid_b4 } }; + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); +} + +void test_online_push__b5(void) +{ + const char *specs[] = { "refs/heads/b5:refs/heads/b5" }; + push_status exp_stats[] = { { "refs/heads/b5", 1 } }; + expected_ref exp_refs[] = { { "refs/heads/b5", &_oid_b5 } }; + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); +} + +void test_online_push__multi(void) +{ + const char *specs[] = { + "refs/heads/b1:refs/heads/b1", + "refs/heads/b2:refs/heads/b2", + "refs/heads/b3:refs/heads/b3", + "refs/heads/b4:refs/heads/b4", + "refs/heads/b5:refs/heads/b5" + }; + push_status exp_stats[] = { + { "refs/heads/b1", 1 }, + { "refs/heads/b2", 1 }, + { "refs/heads/b3", 1 }, + { "refs/heads/b4", 1 }, + { "refs/heads/b5", 1 } + }; + expected_ref exp_refs[] = { + { "refs/heads/b1", &_oid_b1 }, + { "refs/heads/b2", &_oid_b2 }, + { "refs/heads/b3", &_oid_b3 }, + { "refs/heads/b4", &_oid_b4 }, + { "refs/heads/b5", &_oid_b5 } + }; + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); +} + +void test_online_push__implicit_tgt(void) +{ + const char *specs1[] = { "refs/heads/b1:" }; + push_status exp_stats1[] = { { "refs/heads/b1", 1 } }; + expected_ref exp_refs1[] = { { "refs/heads/b1", &_oid_b1 } }; + + const char *specs2[] = { "refs/heads/b2:" }; + push_status exp_stats2[] = { { "refs/heads/b2", 1 } }; + expected_ref exp_refs2[] = { + { "refs/heads/b1", &_oid_b1 }, + { "refs/heads/b2", &_oid_b2 } + }; + + do_push(specs1, ARRAY_SIZE(specs1), + exp_stats1, ARRAY_SIZE(exp_stats1), + exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1); + do_push(specs2, ARRAY_SIZE(specs2), + exp_stats2, ARRAY_SIZE(exp_stats2), + exp_refs2, ARRAY_SIZE(exp_refs2), 0, 0); +} + +void test_online_push__fast_fwd(void) +{ + /* Fast forward b1 in tgt from _oid_b1 to _oid_b6. */ + + const char *specs_init[] = { "refs/heads/b1:refs/heads/b1" }; + push_status exp_stats_init[] = { { "refs/heads/b1", 1 } }; + expected_ref exp_refs_init[] = { { "refs/heads/b1", &_oid_b1 } }; + + const char *specs_ff[] = { "refs/heads/b6:refs/heads/b1" }; + push_status exp_stats_ff[] = { { "refs/heads/b1", 1 } }; + expected_ref exp_refs_ff[] = { { "refs/heads/b1", &_oid_b6 } }; + + /* Do a force push to reset b1 in target back to _oid_b1 */ + const char *specs_reset[] = { "+refs/heads/b1:refs/heads/b1" }; + /* Force should have no effect on a fast forward push */ + const char *specs_ff_force[] = { "+refs/heads/b6:refs/heads/b1" }; + + do_push(specs_init, ARRAY_SIZE(specs_init), + exp_stats_init, ARRAY_SIZE(exp_stats_init), + exp_refs_init, ARRAY_SIZE(exp_refs_init), 0, 1); + + do_push(specs_ff, ARRAY_SIZE(specs_ff), + exp_stats_ff, ARRAY_SIZE(exp_stats_ff), + exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0, 0); + + do_push(specs_reset, ARRAY_SIZE(specs_reset), + exp_stats_init, ARRAY_SIZE(exp_stats_init), + exp_refs_init, ARRAY_SIZE(exp_refs_init), 0, 0); + + do_push(specs_ff_force, ARRAY_SIZE(specs_ff_force), + exp_stats_ff, ARRAY_SIZE(exp_stats_ff), + exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0, 0); +} + +void test_online_push__tag_commit(void) +{ + const char *specs[] = { "refs/tags/tag-commit:refs/tags/tag-commit" }; + push_status exp_stats[] = { { "refs/tags/tag-commit", 1 } }; + expected_ref exp_refs[] = { { "refs/tags/tag-commit", &_tag_commit } }; + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); +} + +void test_online_push__tag_tree(void) +{ + const char *specs[] = { "refs/tags/tag-tree:refs/tags/tag-tree" }; + push_status exp_stats[] = { { "refs/tags/tag-tree", 1 } }; + expected_ref exp_refs[] = { { "refs/tags/tag-tree", &_tag_tree } }; + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); +} + +void test_online_push__tag_blob(void) +{ + const char *specs[] = { "refs/tags/tag-blob:refs/tags/tag-blob" }; + push_status exp_stats[] = { { "refs/tags/tag-blob", 1 } }; + expected_ref exp_refs[] = { { "refs/tags/tag-blob", &_tag_blob } }; + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); +} + +void test_online_push__tag_lightweight(void) +{ + const char *specs[] = { "refs/tags/tag-lightweight:refs/tags/tag-lightweight" }; + push_status exp_stats[] = { { "refs/tags/tag-lightweight", 1 } }; + expected_ref exp_refs[] = { { "refs/tags/tag-lightweight", &_tag_lightweight } }; + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); +} + +void test_online_push__tag_to_tag(void) +{ + const char *specs[] = { "refs/tags/tag-tag:refs/tags/tag-tag" }; + push_status exp_stats[] = { { "refs/tags/tag-tag", 1 } }; + expected_ref exp_refs[] = { { "refs/tags/tag-tag", &_tag_tag } }; + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0, 0); +} + +void test_online_push__force(void) +{ + const char *specs1[] = {"refs/heads/b3:refs/heads/tgt"}; + push_status exp_stats1[] = { { "refs/heads/tgt", 1 } }; + expected_ref exp_refs1[] = { { "refs/heads/tgt", &_oid_b3 } }; + + const char *specs2[] = {"refs/heads/b4:refs/heads/tgt"}; + + const char *specs2_force[] = {"+refs/heads/b4:refs/heads/tgt"}; + push_status exp_stats2_force[] = { { "refs/heads/tgt", 1 } }; + expected_ref exp_refs2_force[] = { { "refs/heads/tgt", &_oid_b4 } }; + + do_push(specs1, ARRAY_SIZE(specs1), + exp_stats1, ARRAY_SIZE(exp_stats1), + exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1); + + do_push(specs2, ARRAY_SIZE(specs2), + NULL, 0, + exp_refs1, ARRAY_SIZE(exp_refs1), GIT_ENONFASTFORWARD, 0); + + /* Non-fast-forward update with force should pass. */ + do_push(specs2_force, ARRAY_SIZE(specs2_force), + exp_stats2_force, ARRAY_SIZE(exp_stats2_force), + exp_refs2_force, ARRAY_SIZE(exp_refs2_force), 0, 1); +} + +void test_online_push__delete(void) +{ + const char *specs1[] = { + "refs/heads/b1:refs/heads/tgt1", + "refs/heads/b1:refs/heads/tgt2" + }; + push_status exp_stats1[] = { + { "refs/heads/tgt1", 1 }, + { "refs/heads/tgt2", 1 } + }; + expected_ref exp_refs1[] = { + { "refs/heads/tgt1", &_oid_b1 }, + { "refs/heads/tgt2", &_oid_b1 } + }; + + const char *specs_del_fake[] = { ":refs/heads/fake" }; + /* Force has no effect for delete. */ + const char *specs_del_fake_force[] = { "+:refs/heads/fake" }; + push_status exp_stats_fake[] = { { "refs/heads/fake", 1 } }; + + const char *specs_delete[] = { ":refs/heads/tgt1" }; + push_status exp_stats_delete[] = { { "refs/heads/tgt1", 1 } }; + expected_ref exp_refs_delete[] = { { "refs/heads/tgt2", &_oid_b1 } }; + /* Force has no effect for delete. */ + const char *specs_delete_force[] = { "+:refs/heads/tgt1" }; + + do_push(specs1, ARRAY_SIZE(specs1), + exp_stats1, ARRAY_SIZE(exp_stats1), + exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1); + + /* When deleting a non-existent branch, the git client sends zero for both + * the old and new commit id. This should succeed on the server with the + * same status report as if the branch were actually deleted. The server + * returns a warning on the side-band iff the side-band is supported. + * Since libgit2 doesn't support the side-band yet, there are no warnings. + */ + do_push(specs_del_fake, ARRAY_SIZE(specs_del_fake), + exp_stats_fake, 1, + exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0); + do_push(specs_del_fake_force, ARRAY_SIZE(specs_del_fake_force), + exp_stats_fake, 1, + exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0); + + /* Delete one of the pushed branches. */ + do_push(specs_delete, ARRAY_SIZE(specs_delete), + exp_stats_delete, ARRAY_SIZE(exp_stats_delete), + exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0, 0); + + /* Re-push branches and retry delete with force. */ + do_push(specs1, ARRAY_SIZE(specs1), + exp_stats1, ARRAY_SIZE(exp_stats1), + exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0); + do_push(specs_delete_force, ARRAY_SIZE(specs_delete_force), + exp_stats_delete, ARRAY_SIZE(exp_stats_delete), + exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0, 0); +} + +void test_online_push__bad_refspecs(void) +{ + /* All classes of refspecs that should be rejected by + * git_push_add_refspec() should go in this test. + */ + git_push *push; + + if (_remote) { +// cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH)); + cl_git_pass(git_push_new(&push, _remote)); + + /* Unexpanded branch names not supported */ + cl_git_fail(git_push_add_refspec(push, "b6:b6")); + + git_push_free(push); + } +} + +void test_online_push__expressions(void) +{ + /* TODO: Expressions in refspecs doesn't actually work yet */ + const char *specs_left_expr[] = { "refs/heads/b2~1:refs/heads/b2" }; + + /* expect not NULL to indicate failure (core git replies "funny refname", + * other servers may be less pithy. */ + const char *specs_right_expr[] = { "refs/heads/b2:refs/heads/b2~1" }; + push_status exp_stats_right_expr[] = { { "refs/heads/b2~1", 0 } }; + + /* TODO: Find a more precise way of checking errors than a exit code of -1. */ + do_push(specs_left_expr, ARRAY_SIZE(specs_left_expr), + NULL, 0, + NULL, 0, -1, 0); + + do_push(specs_right_expr, ARRAY_SIZE(specs_right_expr), + exp_stats_right_expr, ARRAY_SIZE(exp_stats_right_expr), + NULL, 0, 0, 1); +} + +void test_online_push__notes(void) +{ + git_oid note_oid, *target_oid, expected_oid; + git_signature *signature; + const char *specs[] = { "refs/notes/commits:refs/notes/commits" }; + push_status exp_stats[] = { { "refs/notes/commits", 1 } }; + expected_ref exp_refs[] = { { "refs/notes/commits", &expected_oid } }; + git_oid_fromstr(&expected_oid, "8461a99b27b7043e58ff6e1f5d2cf07d282534fb"); + + target_oid = &_oid_b6; + + /* Create note to push */ + cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ + cl_git_pass(git_note_create(¬e_oid, _repo, signature, signature, NULL, target_oid, "hello world\n", 0)); + + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0, 1); + + git_signature_free(signature); +} diff --git a/tests/online/push_util.c b/tests/online/push_util.c new file mode 100644 index 000000000..038c144db --- /dev/null +++ b/tests/online/push_util.c @@ -0,0 +1,132 @@ + +#include "clar_libgit2.h" +#include "buffer.h" +#include "vector.h" +#include "push_util.h" + +const git_oid OID_ZERO = {{ 0 }}; + +void updated_tip_free(updated_tip *t) +{ + git__free(t->name); + git__free(t->old_oid); + git__free(t->new_oid); + git__free(t); +} + +void record_callbacks_data_clear(record_callbacks_data *data) +{ + size_t i; + updated_tip *tip; + + git_vector_foreach(&data->updated_tips, i, tip) + updated_tip_free(tip); + + git_vector_free(&data->updated_tips); +} + +int record_update_tips_cb(const char *refname, const git_oid *a, const git_oid *b, void *data) +{ + updated_tip *t; + record_callbacks_data *record_data = (record_callbacks_data *)data; + + cl_assert(t = git__malloc(sizeof(*t))); + + cl_assert(t->name = git__strdup(refname)); + cl_assert(t->old_oid = git__malloc(sizeof(*t->old_oid))); + git_oid_cpy(t->old_oid, a); + + cl_assert(t->new_oid = git__malloc(sizeof(*t->new_oid))); + git_oid_cpy(t->new_oid, b); + + git_vector_insert(&record_data->updated_tips, t); + + return 0; +} + +int create_deletion_refspecs(git_vector *out, const git_remote_head **heads, size_t heads_len) +{ + git_buf del_spec = GIT_BUF_INIT; + size_t i; + + for (i = 0; i < heads_len; i++) { + const git_remote_head *head = heads[i]; + /* Ignore malformed ref names (which also saves us from tag^{} */ + if (!git_reference_is_valid_name(head->name)) + return 0; + + /* Create a refspec that deletes a branch in the remote */ + if (strcmp(head->name, "refs/heads/master")) { + cl_git_pass(git_buf_putc(&del_spec, ':')); + cl_git_pass(git_buf_puts(&del_spec, head->name)); + cl_git_pass(git_vector_insert(out, git_buf_detach(&del_spec))); + } + } + + return 0; +} + +int record_ref_cb(git_remote_head *head, void *payload) +{ + git_vector *refs = (git_vector *) payload; + return git_vector_insert(refs, head); +} + +void verify_remote_refs(const git_remote_head *actual_refs[], size_t actual_refs_len, const expected_ref expected_refs[], size_t expected_refs_len) +{ + size_t i, j = 0; + git_buf msg = GIT_BUF_INIT; + const git_remote_head *actual; + char *oid_str; + bool master_present = false; + + /* We don't care whether "master" is present on the other end or not */ + for (i = 0; i < actual_refs_len; i++) { + actual = actual_refs[i]; + if (!strcmp(actual->name, "refs/heads/master")) { + master_present = true; + break; + } + } + + if (expected_refs_len + (master_present ? 1 : 0) != actual_refs_len) + goto failed; + + for (i = 0; i < actual_refs_len; i++) { + actual = actual_refs[i]; + if (master_present && !strcmp(actual->name, "refs/heads/master")) + continue; + + if (strcmp(expected_refs[j].name, actual->name) || + git_oid_cmp(expected_refs[j].oid, &actual->oid)) + goto failed; + + j++; + } + + return; + +failed: + git_buf_puts(&msg, "Expected and actual refs differ:\nEXPECTED:\n"); + + for(i = 0; i < expected_refs_len; i++) { + cl_assert(oid_str = git_oid_allocfmt(expected_refs[i].oid)); + cl_git_pass(git_buf_printf(&msg, "%s = %s\n", expected_refs[i].name, oid_str)); + git__free(oid_str); + } + + git_buf_puts(&msg, "\nACTUAL:\n"); + for (i = 0; i < actual_refs_len; i++) { + actual = actual_refs[i]; + if (master_present && !strcmp(actual->name, "refs/heads/master")) + continue; + + cl_assert(oid_str = git_oid_allocfmt(&actual->oid)); + cl_git_pass(git_buf_printf(&msg, "%s = %s\n", actual->name, oid_str)); + git__free(oid_str); + } + + cl_fail(git_buf_cstr(&msg)); + + git_buf_free(&msg); +} diff --git a/tests/online/push_util.h b/tests/online/push_util.h new file mode 100644 index 000000000..a7207c49e --- /dev/null +++ b/tests/online/push_util.h @@ -0,0 +1,71 @@ +#ifndef INCLUDE_cl_push_util_h__ +#define INCLUDE_cl_push_util_h__ + +#include "git2/oid.h" + +/* Constant for zero oid */ +extern const git_oid OID_ZERO; + +/** + * Macro for initializing git_remote_callbacks to use test helpers that + * record data in a record_callbacks_data instance. + * @param data pointer to a record_callbacks_data instance + */ +#define RECORD_CALLBACKS_INIT(data) \ + { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, record_update_tips_cb, data } + +typedef struct { + char *name; + git_oid *old_oid; + git_oid *new_oid; +} updated_tip; + +typedef struct { + git_vector updated_tips; +} record_callbacks_data; + +typedef struct { + const char *name; + const git_oid *oid; +} expected_ref; + +void updated_tip_free(updated_tip *t); + +void record_callbacks_data_clear(record_callbacks_data *data); + +/** + * Callback for git_remote_update_tips that records updates + * + * @param data (git_vector *) of updated_tip instances + */ +int record_update_tips_cb(const char *refname, const git_oid *a, const git_oid *b, void *data); + +/** + * Create a set of refspecs that deletes each of the inputs + * + * @param out the vector in which to store the refspecs + * @param heads the remote heads + * @param heads_len the size of the array + */ +int create_deletion_refspecs(git_vector *out, const git_remote_head **heads, size_t heads_len); + +/** + * Callback for git_remote_list that adds refspecs to vector + * + * @param head a ref on the remote + * @param payload (git_vector *) of git_remote_head instances + */ +int record_ref_cb(git_remote_head *head, void *payload); + +/** + * Verifies that refs on remote stored by record_ref_cb match the expected + * names, oids, and order. + * + * @param actual_refs actual refs in the remote + * @param actual_refs_len length of actual_refs + * @param expected_refs expected remote refs + * @param expected_refs_len length of expected_refs + */ +void verify_remote_refs(const git_remote_head *actual_refs[], size_t actual_refs_len, const expected_ref expected_refs[], size_t expected_refs_len); + +#endif /* INCLUDE_cl_push_util_h__ */ diff --git a/tests/pack/indexer.c b/tests/pack/indexer.c new file mode 100644 index 000000000..07963a9e7 --- /dev/null +++ b/tests/pack/indexer.c @@ -0,0 +1,126 @@ +#include "clar_libgit2.h" +#include +#include "fileops.h" +#include "hash.h" +#include "iterator.h" +#include "vector.h" +#include "posix.h" + + +/* + * This is a packfile with three objects. The second is a delta which + * depends on the third, which is also a delta. + */ +unsigned char out_of_order_pack[] = { + 0x50, 0x41, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, + 0x32, 0x78, 0x9c, 0x63, 0x67, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x76, + 0xe6, 0x8f, 0xe8, 0x12, 0x9b, 0x54, 0x6b, 0x10, 0x1a, 0xee, 0x95, 0x10, + 0xc5, 0x32, 0x8e, 0x7f, 0x21, 0xca, 0x1d, 0x18, 0x78, 0x9c, 0x63, 0x62, + 0x66, 0x4e, 0xcb, 0xcf, 0x07, 0x00, 0x02, 0xac, 0x01, 0x4d, 0x75, 0x01, + 0xd7, 0x71, 0x36, 0x66, 0xf4, 0xde, 0x82, 0x27, 0x76, 0xc7, 0x62, 0x2c, + 0x10, 0xf1, 0xb0, 0x7d, 0xe2, 0x80, 0xdc, 0x78, 0x9c, 0x63, 0x62, 0x62, + 0x62, 0xb7, 0x03, 0x00, 0x00, 0x69, 0x00, 0x4c, 0xde, 0x7d, 0xaa, 0xe4, + 0x19, 0x87, 0x58, 0x80, 0x61, 0x09, 0x9a, 0x33, 0xca, 0x7a, 0x31, 0x92, + 0x6f, 0xae, 0x66, 0x75 +}; +unsigned int out_of_order_pack_len = 112; + +/* + * Packfile with two objects. The second is a delta against an object + * which is not in the packfile + */ +unsigned char thin_pack[] = { + 0x50, 0x41, 0x43, 0x4b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x32, 0x78, 0x9c, 0x63, 0x67, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x76, + 0xe6, 0x8f, 0xe8, 0x12, 0x9b, 0x54, 0x6b, 0x10, 0x1a, 0xee, 0x95, 0x10, + 0xc5, 0x32, 0x8e, 0x7f, 0x21, 0xca, 0x1d, 0x18, 0x78, 0x9c, 0x63, 0x62, + 0x66, 0x4e, 0xcb, 0xcf, 0x07, 0x00, 0x02, 0xac, 0x01, 0x4d, 0x42, 0x52, + 0x3a, 0x6f, 0x39, 0xd1, 0xfe, 0x66, 0x68, 0x6b, 0xa5, 0xe5, 0xe2, 0x97, + 0xac, 0x94, 0x6c, 0x76, 0x0b, 0x04 +}; +unsigned int thin_pack_len = 78; + +unsigned char base_obj[] = { 07, 076 }; +unsigned int base_obj_len = 2; + +void test_pack_indexer__out_of_order(void) +{ + git_indexer *idx; + git_transfer_progress stats; + + cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); + cl_git_pass(git_indexer_append(idx, out_of_order_pack, out_of_order_pack_len, &stats)); + cl_git_pass(git_indexer_commit(idx, &stats)); + + cl_assert_equal_i(stats.total_objects, 3); + cl_assert_equal_i(stats.received_objects, 3); + cl_assert_equal_i(stats.indexed_objects, 3); + + git_indexer_free(idx); +} + +void test_pack_indexer__fix_thin(void) +{ + git_indexer *idx; + git_transfer_progress stats; + git_repository *repo; + git_odb *odb; + git_oid id, should_id; + + cl_git_pass(git_repository_init(&repo, "thin.git", true)); + cl_git_pass(git_repository_odb(&odb, repo)); + + /* Store the missing base into your ODB so the indexer can fix the pack */ + cl_git_pass(git_odb_write(&id, odb, base_obj, base_obj_len, GIT_OBJ_BLOB)); + git_oid_fromstr(&should_id, "e68fe8129b546b101aee9510c5328e7f21ca1d18"); + cl_assert(!git_oid_cmp(&id, &should_id)); + + cl_git_pass(git_indexer_new(&idx, ".", 0, odb, NULL, NULL)); + cl_git_pass(git_indexer_append(idx, thin_pack, thin_pack_len, &stats)); + cl_git_pass(git_indexer_commit(idx, &stats)); + + cl_assert_equal_i(stats.total_objects, 2); + cl_assert_equal_i(stats.received_objects, 2); + cl_assert_equal_i(stats.indexed_objects, 2); + cl_assert_equal_i(stats.local_objects, 1); + + git_oid_fromstr(&should_id, "11f0f69b334728fdd8bc86b80499f22f29d85b15"); + cl_assert(!git_oid_cmp(git_indexer_hash(idx), &should_id)); + + git_indexer_free(idx); + git_odb_free(odb); + git_repository_free(repo); + + /* + * The pack's name/hash only tells us what objects there are, + * so we need to go through the packfile again in order to + * figure out whether we calculated the trailer correctly. + */ + { + unsigned char buffer[128]; + int fd; + ssize_t read; + struct stat st; + const char *name = "pack-11f0f69b334728fdd8bc86b80499f22f29d85b15.pack"; + + fd = p_open(name, O_RDONLY); + cl_assert(fd != -1); + + cl_git_pass(p_stat(name, &st)); + + cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); + read = p_read(fd, buffer, sizeof(buffer)); + cl_assert(read != -1); + p_close(fd); + + cl_git_pass(git_indexer_append(idx, buffer, read, &stats)); + cl_git_pass(git_indexer_commit(idx, &stats)); + + cl_assert_equal_i(stats.total_objects, 3); + cl_assert_equal_i(stats.received_objects, 3); + cl_assert_equal_i(stats.indexed_objects, 3); + cl_assert_equal_i(stats.local_objects, 0); + + git_indexer_free(idx); + } +} diff --git a/tests/pack/packbuilder.c b/tests/pack/packbuilder.c new file mode 100644 index 000000000..54d1e8022 --- /dev/null +++ b/tests/pack/packbuilder.c @@ -0,0 +1,204 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "pack.h" +#include "hash.h" +#include "iterator.h" +#include "vector.h" +#include "posix.h" + +static git_repository *_repo; +static git_revwalk *_revwalker; +static git_packbuilder *_packbuilder; +static git_indexer *_indexer; +static git_vector _commits; +static int _commits_is_initialized; + +void test_pack_packbuilder__initialize(void) +{ + _repo = cl_git_sandbox_init("testrepo.git"); + cl_git_pass(git_revwalk_new(&_revwalker, _repo)); + cl_git_pass(git_packbuilder_new(&_packbuilder, _repo)); + cl_git_pass(git_vector_init(&_commits, 0, NULL)); + _commits_is_initialized = 1; +} + +void test_pack_packbuilder__cleanup(void) +{ + git_oid *o; + unsigned int i; + + if (_commits_is_initialized) { + _commits_is_initialized = 0; + git_vector_foreach(&_commits, i, o) { + git__free(o); + } + git_vector_free(&_commits); + } + + git_packbuilder_free(_packbuilder); + _packbuilder = NULL; + + git_revwalk_free(_revwalker); + _revwalker = NULL; + + git_indexer_free(_indexer); + _indexer = NULL; + + cl_git_sandbox_cleanup(); + _repo = NULL; +} + +static void seed_packbuilder(void) +{ + git_oid oid, *o; + unsigned int i; + + git_revwalk_sorting(_revwalker, GIT_SORT_TIME); + cl_git_pass(git_revwalk_push_ref(_revwalker, "HEAD")); + + while (git_revwalk_next(&oid, _revwalker) == 0) { + o = git__malloc(GIT_OID_RAWSZ); + cl_assert(o != NULL); + git_oid_cpy(o, &oid); + cl_git_pass(git_vector_insert(&_commits, o)); + } + + git_vector_foreach(&_commits, i, o) { + cl_git_pass(git_packbuilder_insert(_packbuilder, o, NULL)); + } + + git_vector_foreach(&_commits, i, o) { + git_object *obj; + cl_git_pass(git_object_lookup(&obj, _repo, o, GIT_OBJ_COMMIT)); + cl_git_pass(git_packbuilder_insert_tree(_packbuilder, + git_commit_tree_id((git_commit *)obj))); + git_object_free(obj); + } +} + +static int feed_indexer(void *ptr, size_t len, void *payload) +{ + git_transfer_progress *stats = (git_transfer_progress *)payload; + + return git_indexer_append(_indexer, ptr, len, stats); +} + +void test_pack_packbuilder__create_pack(void) +{ + git_transfer_progress stats; + git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT; + git_hash_ctx ctx; + git_oid hash; + char hex[41]; hex[40] = '\0'; + + seed_packbuilder(); + + cl_git_pass(git_indexer_new(&_indexer, ".", 0, NULL, NULL, NULL)); + cl_git_pass(git_packbuilder_foreach(_packbuilder, feed_indexer, &stats)); + cl_git_pass(git_indexer_commit(_indexer, &stats)); + + git_oid_fmt(hex, git_indexer_hash(_indexer)); + git_buf_printf(&path, "pack-%s.pack", hex); + + /* + * By default, packfiles are created with only one thread. + * Therefore we can predict the object ordering and make sure + * we create exactly the same pack as git.git does when *not* + * reusing existing deltas (as libgit2). + * + * $ cd tests-clar/resources/testrepo.git + * $ git rev-list --objects HEAD | \ + * git pack-objects -q --no-reuse-delta --threads=1 pack + * $ sha1sum git-80e61eb315239ef3c53033e37fee43b744d57122.pack + * 5d410bdf97cf896f9007681b92868471d636954b + * + */ + + cl_git_pass(git_futils_readbuffer(&buf, git_buf_cstr(&path))); + + cl_git_pass(git_hash_ctx_init(&ctx)); + cl_git_pass(git_hash_update(&ctx, buf.ptr, buf.size)); + cl_git_pass(git_hash_final(&hash, &ctx)); + git_hash_ctx_cleanup(&ctx); + + git_buf_free(&path); + git_buf_free(&buf); + + git_oid_fmt(hex, &hash); + + cl_assert_equal_s(hex, "5d410bdf97cf896f9007681b92868471d636954b"); +} + +void test_pack_packbuilder__get_hash(void) +{ + char hex[41]; hex[40] = '\0'; + + seed_packbuilder(); + + git_packbuilder_write(_packbuilder, ".", 0, NULL, NULL); + git_oid_fmt(hex, git_packbuilder_hash(_packbuilder)); + + cl_assert_equal_s(hex, "80e61eb315239ef3c53033e37fee43b744d57122"); +} + +static void test_write_pack_permission(mode_t given, mode_t expected) +{ + struct stat statbuf; + mode_t mask, os_mask; + + seed_packbuilder(); + + git_packbuilder_write(_packbuilder, ".", given, NULL, NULL); + + /* Windows does not return group/user bits from stat, + * files are never executable. + */ +#ifdef GIT_WIN32 + os_mask = 0600; +#else + os_mask = 0777; +#endif + + mask = p_umask(0); + p_umask(mask); + + cl_git_pass(p_stat("pack-80e61eb315239ef3c53033e37fee43b744d57122.idx", &statbuf)); + cl_assert_equal_i(statbuf.st_mode & os_mask, (expected & ~mask) & os_mask); + + cl_git_pass(p_stat("pack-80e61eb315239ef3c53033e37fee43b744d57122.pack", &statbuf)); + cl_assert_equal_i(statbuf.st_mode & os_mask, (expected & ~mask) & os_mask); +} + +void test_pack_packbuilder__permissions_standard(void) +{ + test_write_pack_permission(0, GIT_PACK_FILE_MODE); +} + +void test_pack_packbuilder__permissions_readonly(void) +{ + test_write_pack_permission(0444, 0444); +} + +void test_pack_packbuilder__permissions_readwrite(void) +{ + test_write_pack_permission(0666, 0666); +} + +static git_transfer_progress stats; +static int foreach_cb(void *buf, size_t len, void *payload) +{ + git_indexer *idx = (git_indexer *) payload; + cl_git_pass(git_indexer_append(idx, buf, len, &stats)); + return 0; +} + +void test_pack_packbuilder__foreach(void) +{ + git_indexer *idx; + + seed_packbuilder(); + cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); + cl_git_pass(git_packbuilder_foreach(_packbuilder, foreach_cb, idx)); + cl_git_pass(git_indexer_commit(idx, &stats)); + git_indexer_free(idx); +} diff --git a/tests/refs/branches/create.c b/tests/refs/branches/create.c new file mode 100644 index 000000000..693a592a3 --- /dev/null +++ b/tests/refs/branches/create.c @@ -0,0 +1,76 @@ +#include "clar_libgit2.h" +#include "refs.h" + +static git_repository *repo; +static git_commit *target; +static git_reference *branch; + +void test_refs_branches_create__initialize(void) +{ + cl_fixture_sandbox("testrepo.git"); + cl_git_pass(git_repository_open(&repo, "testrepo.git")); + + branch = NULL; +} + +void test_refs_branches_create__cleanup(void) +{ + git_reference_free(branch); + branch = NULL; + + git_commit_free(target); + target = NULL; + + git_repository_free(repo); + repo = NULL; + + cl_fixture_cleanup("testrepo.git"); +} + +static void retrieve_target_from_oid(git_commit **out, git_repository *repo, const char *sha) +{ + git_oid oid; + + cl_git_pass(git_oid_fromstr(&oid, sha)); + cl_git_pass(git_commit_lookup(out, repo, &oid)); +} + +static void retrieve_known_commit(git_commit **commit, git_repository *repo) +{ + retrieve_target_from_oid(commit, repo, "e90810b8df3e80c413d903f631643c716887138d"); +} + +#define NEW_BRANCH_NAME "new-branch-on-the-block" + +void test_refs_branches_create__can_create_a_local_branch(void) +{ + retrieve_known_commit(&target, repo); + + cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, 0)); + cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target))); +} + +void test_refs_branches_create__can_not_create_a_branch_if_its_name_collide_with_an_existing_one(void) +{ + retrieve_known_commit(&target, repo); + + cl_assert_equal_i(GIT_EEXISTS, git_branch_create(&branch, repo, "br2", target, 0)); +} + +void test_refs_branches_create__can_force_create_over_an_existing_branch(void) +{ + retrieve_known_commit(&target, repo); + + cl_git_pass(git_branch_create(&branch, repo, "br2", target, 1)); + cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target))); + cl_assert_equal_s("refs/heads/br2", git_reference_name(branch)); +} + + +void test_refs_branches_create__creating_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void) +{ + retrieve_known_commit(&target, repo); + + cl_assert_equal_i(GIT_EINVALIDSPEC, + git_branch_create(&branch, repo, "inv@{id", target, 0)); +} \ No newline at end of file diff --git a/tests/refs/branches/delete.c b/tests/refs/branches/delete.c new file mode 100644 index 000000000..de90cb734 --- /dev/null +++ b/tests/refs/branches/delete.c @@ -0,0 +1,117 @@ +#include "clar_libgit2.h" +#include "refs.h" +#include "repo/repo_helpers.h" +#include "config/config_helpers.h" + +static git_repository *repo; +static git_reference *fake_remote; + +void test_refs_branches_delete__initialize(void) +{ + git_oid id; + + cl_fixture_sandbox("testrepo.git"); + cl_git_pass(git_repository_open(&repo, "testrepo.git")); + + cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); + cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0)); +} + +void test_refs_branches_delete__cleanup(void) +{ + git_reference_free(fake_remote); + fake_remote = NULL; + + git_repository_free(repo); + repo = NULL; + + cl_fixture_cleanup("testrepo.git"); +} + +void test_refs_branches_delete__can_not_delete_a_branch_pointed_at_by_HEAD(void) +{ + git_reference *head; + git_reference *branch; + + /* Ensure HEAD targets the local master branch */ + cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE)); + cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); + git_reference_free(head); + + cl_git_pass(git_branch_lookup(&branch, repo, "master", GIT_BRANCH_LOCAL)); + cl_git_fail(git_branch_delete(branch)); + git_reference_free(branch); +} + +void test_refs_branches_delete__can_delete_a_branch_even_if_HEAD_is_missing(void) +{ + git_reference *head; + git_reference *branch; + + cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE)); + git_reference_delete(head); + git_reference_free(head); + + cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL)); + cl_git_pass(git_branch_delete(branch)); + git_reference_free(branch); +} + +void test_refs_branches_delete__can_delete_a_branch_when_HEAD_is_unborn(void) +{ + git_reference *branch; + + make_head_unborn(repo, NON_EXISTING_HEAD); + + cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL)); + cl_git_pass(git_branch_delete(branch)); + git_reference_free(branch); +} + +void test_refs_branches_delete__can_delete_a_branch_pointed_at_by_detached_HEAD(void) +{ + git_reference *head, *branch; + + cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE)); + cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); + cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); + git_reference_free(head); + + /* Detach HEAD and make it target the commit that "master" points to */ + git_repository_detach_head(repo); + + cl_git_pass(git_branch_lookup(&branch, repo, "master", GIT_BRANCH_LOCAL)); + cl_git_pass(git_branch_delete(branch)); + git_reference_free(branch); +} + +void test_refs_branches_delete__can_delete_a_local_branch(void) +{ + git_reference *branch; + cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL)); + cl_git_pass(git_branch_delete(branch)); + git_reference_free(branch); +} + +void test_refs_branches_delete__can_delete_a_remote_branch(void) +{ + git_reference *branch; + cl_git_pass(git_branch_lookup(&branch, repo, "nulltoken/master", GIT_BRANCH_REMOTE)); + cl_git_pass(git_branch_delete(branch)); + git_reference_free(branch); +} + +void test_refs_branches_delete__deleting_a_branch_removes_related_configuration_data(void) +{ + git_reference *branch; + + assert_config_entry_existence(repo, "branch.track-local.remote", true); + assert_config_entry_existence(repo, "branch.track-local.merge", true); + + cl_git_pass(git_branch_lookup(&branch, repo, "track-local", GIT_BRANCH_LOCAL)); + cl_git_pass(git_branch_delete(branch)); + git_reference_free(branch); + + assert_config_entry_existence(repo, "branch.track-local.remote", false); + assert_config_entry_existence(repo, "branch.track-local.merge", false); +} diff --git a/tests/refs/branches/ishead.c b/tests/refs/branches/ishead.c new file mode 100644 index 000000000..b1ad09c3e --- /dev/null +++ b/tests/refs/branches/ishead.c @@ -0,0 +1,116 @@ +#include "clar_libgit2.h" +#include "refs.h" +#include "repo/repo_helpers.h" + +static git_repository *repo; +static git_reference *branch; + +void test_refs_branches_ishead__initialize(void) +{ + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); +} + +void test_refs_branches_ishead__cleanup(void) +{ + git_reference_free(branch); + branch = NULL; + + git_repository_free(repo); + repo = NULL; +} + +void test_refs_branches_ishead__can_tell_if_a_branch_is_pointed_at_by_HEAD(void) +{ + cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master")); + + cl_assert_equal_i(true, git_branch_is_head(branch)); +} + +void test_refs_branches_ishead__can_properly_handle_unborn_HEAD(void) +{ + git_repository_free(repo); + + repo = cl_git_sandbox_init("testrepo.git"); + + make_head_unborn(repo, NON_EXISTING_HEAD); + + cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master")); + + cl_assert_equal_i(false, git_branch_is_head(branch)); + + cl_git_sandbox_cleanup(); + repo = NULL; +} + +void test_refs_branches_ishead__can_properly_handle_missing_HEAD(void) +{ + git_repository_free(repo); + + repo = cl_git_sandbox_init("testrepo.git"); + + delete_head(repo); + + cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master")); + + cl_assert_equal_i(false, git_branch_is_head(branch)); + + cl_git_sandbox_cleanup(); + repo = NULL; +} + +void test_refs_branches_ishead__can_tell_if_a_branch_is_not_pointed_at_by_HEAD(void) +{ + cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/br2")); + + cl_assert_equal_i(false, git_branch_is_head(branch)); +} + +void test_refs_branches_ishead__wont_be_fooled_by_a_non_branch(void) +{ + cl_git_pass(git_reference_lookup(&branch, repo, "refs/tags/e90810b")); + + cl_assert_equal_i(false, git_branch_is_head(branch)); +} + +/* + * $ git init . + * Initialized empty Git repository in d:/temp/tempee/.git/ + * + * $ touch a && git add a + * $ git commit -m" boom" + * [master (root-commit) b47b758] boom + * 0 files changed + * create mode 100644 a + * + * $ echo "ref: refs/heads/master" > .git/refs/heads/linked + * $ echo "ref: refs/heads/linked" > .git/refs/heads/super + * $ echo "ref: refs/heads/super" > .git/HEAD + * + * $ git branch + * linked -> master + * * master + * super -> master + */ +void test_refs_branches_ishead__only_direct_references_are_considered(void) +{ + git_reference *linked, *super, *head; + + git_repository_free(repo); + repo = cl_git_sandbox_init("testrepo.git"); + + cl_git_pass(git_reference_symbolic_create(&linked, repo, "refs/heads/linked", "refs/heads/master", 0)); + cl_git_pass(git_reference_symbolic_create(&super, repo, "refs/heads/super", "refs/heads/linked", 0)); + cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, "refs/heads/super", 1)); + + cl_assert_equal_i(false, git_branch_is_head(linked)); + cl_assert_equal_i(false, git_branch_is_head(super)); + + cl_git_pass(git_repository_head(&branch, repo)); + cl_assert_equal_s("refs/heads/master", git_reference_name(branch)); + + git_reference_free(linked); + git_reference_free(super); + git_reference_free(head); + cl_git_sandbox_cleanup(); + repo = NULL; +} diff --git a/tests/refs/branches/iterator.c b/tests/refs/branches/iterator.c new file mode 100644 index 000000000..904c6a146 --- /dev/null +++ b/tests/refs/branches/iterator.c @@ -0,0 +1,151 @@ +#include "clar_libgit2.h" +#include "refs.h" + +static git_repository *repo; +static git_reference *fake_remote; + +void test_refs_branches_iterator__initialize(void) +{ + git_oid id; + + cl_fixture_sandbox("testrepo.git"); + cl_git_pass(git_repository_open(&repo, "testrepo.git")); + + cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); + cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0)); +} + +void test_refs_branches_iterator__cleanup(void) +{ + git_reference_free(fake_remote); + fake_remote = NULL; + + git_repository_free(repo); + repo = NULL; + + cl_fixture_cleanup("testrepo.git"); + + cl_git_sandbox_cleanup(); +} + +static void assert_retrieval(unsigned int flags, unsigned int expected_count) +{ + git_branch_iterator *iter; + git_reference *ref; + int count = 0, error; + git_branch_t type; + + cl_git_pass(git_branch_iterator_new(&iter, repo, flags)); + while ((error = git_branch_next(&ref, &type, iter)) == 0) { + count++; + git_reference_free(ref); + } + + git_branch_iterator_free(iter); + cl_assert_equal_i(error, GIT_ITEROVER); + cl_assert_equal_i(expected_count, count); +} + +void test_refs_branches_iterator__retrieve_all_branches(void) +{ + assert_retrieval(GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE, 14); +} + +void test_refs_branches_iterator__retrieve_remote_branches(void) +{ + assert_retrieval(GIT_BRANCH_REMOTE, 2); +} + +void test_refs_branches_iterator__retrieve_local_branches(void) +{ + assert_retrieval(GIT_BRANCH_LOCAL, 12); +} + +struct expectations { + const char *branch_name; + int encounters; +}; + +static void assert_branch_has_been_found(struct expectations *findings, const char* expected_branch_name) +{ + int pos = 0; + + for (pos = 0; findings[pos].branch_name; ++pos) { + if (strcmp(expected_branch_name, findings[pos].branch_name) == 0) { + cl_assert_equal_i(1, findings[pos].encounters); + return; + } + } + + cl_fail("expected branch not found in list."); +} + +static void contains_branches(struct expectations exp[], git_branch_iterator *iter) +{ + git_reference *ref; + git_branch_t type; + int error, pos = 0; + + while ((error = git_branch_next(&ref, &type, iter)) == 0) { + for (pos = 0; exp[pos].branch_name; ++pos) { + if (strcmp(git_reference_shorthand(ref), exp[pos].branch_name) == 0) + exp[pos].encounters++; + } + + git_reference_free(ref); + } + + cl_assert_equal_i(error, GIT_ITEROVER); +} + +/* + * $ git branch -r + * nulltoken/HEAD -> nulltoken/master + * nulltoken/master + */ +void test_refs_branches_iterator__retrieve_remote_symbolic_HEAD_when_present(void) +{ + git_branch_iterator *iter; + struct expectations exp[] = { + { "nulltoken/HEAD", 0 }, + { "nulltoken/master", 0 }, + { NULL, 0 } + }; + + git_reference_free(fake_remote); + cl_git_pass(git_reference_symbolic_create(&fake_remote, repo, "refs/remotes/nulltoken/HEAD", "refs/remotes/nulltoken/master", 0)); + + assert_retrieval(GIT_BRANCH_REMOTE, 3); + + cl_git_pass(git_branch_iterator_new(&iter, repo, GIT_BRANCH_REMOTE)); + contains_branches(exp, iter); + git_branch_iterator_free(iter); + + assert_branch_has_been_found(exp, "nulltoken/HEAD"); + assert_branch_has_been_found(exp, "nulltoken/master"); +} + +void test_refs_branches_iterator__mix_of_packed_and_loose(void) +{ + git_branch_iterator *iter; + struct expectations exp[] = { + { "master", 0 }, + { "origin/HEAD", 0 }, + { "origin/master", 0 }, + { "origin/packed", 0 }, + { NULL, 0 } + }; + git_repository *r2; + + r2 = cl_git_sandbox_init("testrepo2"); + + cl_git_pass(git_branch_iterator_new(&iter, r2, GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE)); + contains_branches(exp, iter); + + git_branch_iterator_free(iter); + + assert_branch_has_been_found(exp, "master"); + assert_branch_has_been_found(exp, "origin/HEAD"); + assert_branch_has_been_found(exp, "origin/master"); + assert_branch_has_been_found(exp, "origin/packed"); +} diff --git a/tests/refs/branches/lookup.c b/tests/refs/branches/lookup.c new file mode 100644 index 000000000..95d49a4b3 --- /dev/null +++ b/tests/refs/branches/lookup.c @@ -0,0 +1,45 @@ +#include "clar_libgit2.h" +#include "refs.h" + +static git_repository *repo; +static git_reference *branch; + +void test_refs_branches_lookup__initialize(void) +{ + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + + branch = NULL; +} + +void test_refs_branches_lookup__cleanup(void) +{ + git_reference_free(branch); + branch = NULL; + + git_repository_free(repo); + repo = NULL; +} + +void test_refs_branches_lookup__can_retrieve_a_local_branch(void) +{ + cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL)); +} + +void test_refs_branches_lookup__can_retrieve_a_remote_tracking_branch(void) +{ + cl_git_pass(git_branch_lookup(&branch, repo, "test/master", GIT_BRANCH_REMOTE)); +} + +void test_refs_branches_lookup__trying_to_retrieve_an_unknown_branch_returns_ENOTFOUND(void) +{ + cl_assert_equal_i(GIT_ENOTFOUND, git_branch_lookup(&branch, repo, "where/are/you", GIT_BRANCH_LOCAL)); + cl_assert_equal_i(GIT_ENOTFOUND, git_branch_lookup(&branch, repo, "over/here", GIT_BRANCH_REMOTE)); +} + +void test_refs_branches_lookup__trying_to_retrieve_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void) +{ + cl_assert_equal_i(GIT_EINVALIDSPEC, + git_branch_lookup(&branch, repo, "are/you/inv@{id", GIT_BRANCH_LOCAL)); + cl_assert_equal_i(GIT_EINVALIDSPEC, + git_branch_lookup(&branch, repo, "yes/i am", GIT_BRANCH_REMOTE)); +} diff --git a/tests/refs/branches/move.c b/tests/refs/branches/move.c new file mode 100644 index 000000000..ecf14e006 --- /dev/null +++ b/tests/refs/branches/move.c @@ -0,0 +1,146 @@ +#include "clar_libgit2.h" +#include "refs.h" +#include "config/config_helpers.h" + +static git_repository *repo; + +void test_refs_branches_move__initialize(void) +{ + repo = cl_git_sandbox_init("testrepo.git"); +} + +void test_refs_branches_move__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +#define NEW_BRANCH_NAME "new-branch-on-the-block" + +void test_refs_branches_move__can_move_a_local_branch(void) +{ + git_reference *original_ref, *new_ref; + + cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); + + cl_git_pass(git_branch_move(&new_ref, original_ref, NEW_BRANCH_NAME, 0)); + cl_assert_equal_s(GIT_REFS_HEADS_DIR NEW_BRANCH_NAME, git_reference_name(new_ref)); + + git_reference_free(original_ref); + git_reference_free(new_ref); +} + +void test_refs_branches_move__can_move_a_local_branch_to_a_different_namespace(void) +{ + git_reference *original_ref, *new_ref, *newer_ref; + + cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); + + /* Downward */ + cl_git_pass(git_branch_move(&new_ref, original_ref, "somewhere/" NEW_BRANCH_NAME, 0)); + git_reference_free(original_ref); + + /* Upward */ + cl_git_pass(git_branch_move(&newer_ref, new_ref, "br2", 0)); + git_reference_free(new_ref); + + git_reference_free(newer_ref); +} + +void test_refs_branches_move__can_move_a_local_branch_to_a_partially_colliding_namespace(void) +{ + git_reference *original_ref, *new_ref, *newer_ref; + + cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); + + /* Downward */ + cl_git_pass(git_branch_move(&new_ref, original_ref, "br2/" NEW_BRANCH_NAME, 0)); + git_reference_free(original_ref); + + /* Upward */ + cl_git_pass(git_branch_move(&newer_ref, new_ref, "br2", 0)); + git_reference_free(new_ref); + + git_reference_free(newer_ref); +} + +void test_refs_branches_move__can_not_move_a_branch_if_its_destination_name_collide_with_an_existing_one(void) +{ + git_reference *original_ref, *new_ref; + + cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); + + cl_assert_equal_i(GIT_EEXISTS, git_branch_move(&new_ref, original_ref, "master", 0)); + + git_reference_free(original_ref); +} + +void test_refs_branches_move__moving_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void) +{ + git_reference *original_ref, *new_ref; + + cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); + + cl_assert_equal_i(GIT_EINVALIDSPEC, git_branch_move(&new_ref, original_ref, "Inv@{id", 0)); + + git_reference_free(original_ref); +} + +void test_refs_branches_move__can_not_move_a_non_branch(void) +{ + git_reference *tag, *new_ref; + + cl_git_pass(git_reference_lookup(&tag, repo, "refs/tags/e90810b")); + cl_git_fail(git_branch_move(&new_ref, tag, NEW_BRANCH_NAME, 0)); + + git_reference_free(tag); +} + +void test_refs_branches_move__can_force_move_over_an_existing_branch(void) +{ + git_reference *original_ref, *new_ref; + + cl_git_pass(git_reference_lookup(&original_ref, repo, "refs/heads/br2")); + + cl_git_pass(git_branch_move(&new_ref, original_ref, "master", 1)); + + git_reference_free(original_ref); + git_reference_free(new_ref); +} + +void test_refs_branches_move__moving_a_branch_moves_related_configuration_data(void) +{ + git_reference *branch; + git_reference *new_branch; + + cl_git_pass(git_branch_lookup(&branch, repo, "track-local", GIT_BRANCH_LOCAL)); + + assert_config_entry_existence(repo, "branch.track-local.remote", true); + assert_config_entry_existence(repo, "branch.track-local.merge", true); + assert_config_entry_existence(repo, "branch.moved.remote", false); + assert_config_entry_existence(repo, "branch.moved.merge", false); + + cl_git_pass(git_branch_move(&new_branch, branch, "moved", 0)); + git_reference_free(branch); + + assert_config_entry_existence(repo, "branch.track-local.remote", false); + assert_config_entry_existence(repo, "branch.track-local.merge", false); + assert_config_entry_existence(repo, "branch.moved.remote", true); + assert_config_entry_existence(repo, "branch.moved.merge", true); + + git_reference_free(new_branch); +} + +void test_refs_branches_move__moving_the_branch_pointed_at_by_HEAD_updates_HEAD(void) +{ + git_reference *branch; + git_reference *new_branch; + + cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master")); + cl_git_pass(git_branch_move(&new_branch, branch, "master2", 0)); + git_reference_free(branch); + git_reference_free(new_branch); + + cl_git_pass(git_repository_head(&branch, repo)); + cl_assert_equal_s("refs/heads/master2", git_reference_name(branch)); + git_reference_free(branch); +} diff --git a/tests/refs/branches/name.c b/tests/refs/branches/name.c new file mode 100644 index 000000000..176f836a4 --- /dev/null +++ b/tests/refs/branches/name.c @@ -0,0 +1,45 @@ +#include "clar_libgit2.h" +#include "branch.h" + +static git_repository *repo; +static git_reference *ref; + +void test_refs_branches_name__initialize(void) +{ + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); +} + +void test_refs_branches_name__cleanup(void) +{ + git_reference_free(ref); + ref = NULL; + + git_repository_free(repo); + repo = NULL; +} + +void test_refs_branches_name__can_get_local_branch_name(void) +{ + const char *name; + + cl_git_pass(git_branch_lookup(&ref,repo,"master",GIT_BRANCH_LOCAL)); + cl_git_pass(git_branch_name(&name,ref)); + cl_assert_equal_s("master",name); +} + +void test_refs_branches_name__can_get_remote_branch_name(void) +{ + const char *name; + + cl_git_pass(git_branch_lookup(&ref,repo,"test/master",GIT_BRANCH_REMOTE)); + cl_git_pass(git_branch_name(&name,ref)); + cl_assert_equal_s("test/master",name); +} + +void test_refs_branches_name__error_when_ref_is_no_branch(void) +{ + const char *name; + + cl_git_pass(git_reference_lookup(&ref,repo,"refs/notes/fanout")); + cl_git_fail(git_branch_name(&name,ref)); +} diff --git a/tests/refs/branches/remote.c b/tests/refs/branches/remote.c new file mode 100644 index 000000000..c110adb33 --- /dev/null +++ b/tests/refs/branches/remote.c @@ -0,0 +1,86 @@ +#include "clar_libgit2.h" +#include "branch.h" +#include "remote.h" + +static git_repository *g_repo; +static const char *remote_tracking_branch_name = "refs/remotes/test/master"; +static const char *expected_remote_name = "test"; +static int expected_remote_name_length; + +void test_refs_branches_remote__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); + + expected_remote_name_length = (int)strlen(expected_remote_name) + 1; +} + +void test_refs_branches_remote__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_refs_branches_remote__can_get_remote_for_branch(void) +{ + char remotename[1024] = {0}; + + cl_assert_equal_i(expected_remote_name_length, + git_branch_remote_name(NULL, 0, g_repo, remote_tracking_branch_name)); + + cl_assert_equal_i(expected_remote_name_length, + git_branch_remote_name(remotename, expected_remote_name_length, g_repo, + remote_tracking_branch_name)); + + cl_assert_equal_s("test", remotename); +} + +void test_refs_branches_remote__insufficient_buffer_returns_error(void) +{ + char remotename[1024] = {0}; + + cl_assert_equal_i(expected_remote_name_length, + git_branch_remote_name(NULL, 0, g_repo, remote_tracking_branch_name)); + + cl_git_fail_with(git_branch_remote_name(remotename, + expected_remote_name_length - 1, g_repo, remote_tracking_branch_name), + expected_remote_name_length); +} + +void test_refs_branches_remote__no_matching_remote_returns_error(void) +{ + const char *unknown = "refs/remotes/nonexistent/master"; + + giterr_clear(); + cl_git_fail_with(git_branch_remote_name( + NULL, 0, g_repo, unknown), GIT_ENOTFOUND); + cl_assert(giterr_last() != NULL); +} + +void test_refs_branches_remote__local_remote_returns_error(void) +{ + const char *local = "refs/heads/master"; + + giterr_clear(); + cl_git_fail_with(git_branch_remote_name( + NULL, 0, g_repo, local), GIT_ERROR); + cl_assert(giterr_last() != NULL); +} + +void test_refs_branches_remote__ambiguous_remote_returns_error(void) +{ + git_remote *remote; + + /* Create the remote */ + cl_git_pass(git_remote_create(&remote, g_repo, "addtest", "http://github.com/libgit2/libgit2")); + + /* Update the remote fetch spec */ + git_remote_clear_refspecs(remote); + cl_git_pass(git_remote_add_fetch(remote, "refs/heads/*:refs/remotes/test/*")); + cl_git_pass(git_remote_save(remote)); + + git_remote_free(remote); + + giterr_clear(); + cl_git_fail_with(git_branch_remote_name(NULL, 0, g_repo, + remote_tracking_branch_name), GIT_EAMBIGUOUS); + cl_assert(giterr_last() != NULL); +} diff --git a/tests/refs/branches/upstream.c b/tests/refs/branches/upstream.c new file mode 100644 index 000000000..69e55a0c5 --- /dev/null +++ b/tests/refs/branches/upstream.c @@ -0,0 +1,143 @@ +#include "clar_libgit2.h" +#include "refs.h" + +static git_repository *repo; +static git_reference *branch, *upstream; + +void test_refs_branches_upstream__initialize(void) +{ + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + + branch = NULL; + upstream = NULL; +} + +void test_refs_branches_upstream__cleanup(void) +{ + git_reference_free(upstream); + git_reference_free(branch); + branch = NULL; + + git_repository_free(repo); + repo = NULL; +} + +void test_refs_branches_upstream__can_retrieve_the_remote_tracking_reference_of_a_local_branch(void) +{ + cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master")); + + cl_git_pass(git_branch_upstream(&upstream, branch)); + + cl_assert_equal_s("refs/remotes/test/master", git_reference_name(upstream)); +} + +void test_refs_branches_upstream__can_retrieve_the_local_upstream_reference_of_a_local_branch(void) +{ + cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/track-local")); + + cl_git_pass(git_branch_upstream(&upstream, branch)); + + cl_assert_equal_s("refs/heads/master", git_reference_name(upstream)); +} + +void test_refs_branches_upstream__cannot_retrieve_a_remote_upstream_reference_from_a_non_branch(void) +{ + cl_git_pass(git_reference_lookup(&branch, repo, "refs/tags/e90810b")); + + cl_git_fail(git_branch_upstream(&upstream, branch)); +} + +void test_refs_branches_upstream__trying_to_retrieve_a_remote_tracking_reference_from_a_plain_local_branch_returns_GIT_ENOTFOUND(void) +{ + cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/subtrees")); + + cl_assert_equal_i(GIT_ENOTFOUND, git_branch_upstream(&upstream, branch)); +} + +void test_refs_branches_upstream__trying_to_retrieve_a_remote_tracking_reference_from_a_branch_with_no_fetchspec_returns_GIT_ENOTFOUND(void) +{ + cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/cannot-fetch")); + + cl_assert_equal_i(GIT_ENOTFOUND, git_branch_upstream(&upstream, branch)); +} + +static void assert_merge_and_or_remote_key_missing(git_repository *repository, const git_commit *target, const char *entry_name) +{ + git_reference *branch; + + cl_assert_equal_i(GIT_OBJ_COMMIT, git_object_type((git_object*)target)); + cl_git_pass(git_branch_create(&branch, repository, entry_name, (git_commit*)target, 0)); + + cl_assert_equal_i(GIT_ENOTFOUND, git_branch_upstream(&upstream, branch)); + + git_reference_free(branch); +} + +void test_refs_branches_upstream__retrieve_a_remote_tracking_reference_from_a_branch_with_no_remote_returns_GIT_ENOTFOUND(void) +{ + git_reference *head; + git_repository *repository; + git_commit *target; + + repository = cl_git_sandbox_init("testrepo.git"); + + cl_git_pass(git_repository_head(&head, repository)); + cl_git_pass(git_reference_peel(((git_object **)&target), head, GIT_OBJ_COMMIT)); + git_reference_free(head); + + assert_merge_and_or_remote_key_missing(repository, target, "remoteless"); + assert_merge_and_or_remote_key_missing(repository, target, "mergeless"); + assert_merge_and_or_remote_key_missing(repository, target, "mergeandremoteless"); + + git_commit_free(target); + + cl_git_sandbox_cleanup(); +} + +void test_refs_branches_upstream__set_unset_upstream(void) +{ + git_reference *branch; + git_repository *repository; + const char *value; + git_config *config; + + repository = cl_git_sandbox_init("testrepo.git"); + + /* remote */ + cl_git_pass(git_reference_lookup(&branch, repository, "refs/heads/test")); + cl_git_pass(git_branch_set_upstream(branch, "test/master")); + + cl_git_pass(git_repository_config(&config, repository)); + cl_git_pass(git_config_get_string(&value, config, "branch.test.remote")); + cl_assert_equal_s(value, "test"); + cl_git_pass(git_config_get_string(&value, config, "branch.test.merge")); + cl_assert_equal_s(value, "refs/heads/master"); + + git_reference_free(branch); + + /* local */ + cl_git_pass(git_reference_lookup(&branch, repository, "refs/heads/test")); + cl_git_pass(git_branch_set_upstream(branch, "master")); + + cl_git_pass(git_config_get_string(&value, config, "branch.test.remote")); + cl_assert_equal_s(value, "."); + cl_git_pass(git_config_get_string(&value, config, "branch.test.merge")); + cl_assert_equal_s(value, "refs/heads/master"); + + /* unset */ + cl_git_pass(git_branch_set_upstream(branch, NULL)); + cl_git_fail_with(git_config_get_string(&value, config, "branch.test.merge"), GIT_ENOTFOUND); + cl_git_fail_with(git_config_get_string(&value, config, "branch.test.remote"), GIT_ENOTFOUND); + + git_reference_free(branch); + + cl_git_pass(git_reference_lookup(&branch, repository, "refs/heads/master")); + cl_git_pass(git_branch_set_upstream(branch, NULL)); + cl_git_fail_with(git_config_get_string(&value, config, "branch.master.merge"), GIT_ENOTFOUND); + cl_git_fail_with(git_config_get_string(&value, config, "branch.master.remote"), GIT_ENOTFOUND); + + git_reference_free(branch); + + git_config_free(config); + cl_git_sandbox_cleanup(); +} diff --git a/tests/refs/branches/upstreamname.c b/tests/refs/branches/upstreamname.c new file mode 100644 index 000000000..f05607d44 --- /dev/null +++ b/tests/refs/branches/upstreamname.c @@ -0,0 +1,42 @@ +#include "clar_libgit2.h" +#include "branch.h" + +static git_repository *repo; +static git_buf upstream_name; + +void test_refs_branches_upstreamname__initialize(void) +{ + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + + git_buf_init(&upstream_name, 0); +} + +void test_refs_branches_upstreamname__cleanup(void) +{ + git_buf_free(&upstream_name); + + git_repository_free(repo); + repo = NULL; +} + +void test_refs_branches_upstreamname__can_retrieve_the_remote_tracking_reference_name_of_a_local_branch(void) +{ + cl_git_pass(git_branch_upstream__name( + &upstream_name, repo, "refs/heads/master")); + + cl_assert_equal_s("refs/remotes/test/master", git_buf_cstr(&upstream_name)); +} + +void test_refs_branches_upstreamname__can_retrieve_the_local_upstream_reference_name_of_a_local_branch(void) +{ + cl_git_pass(git_branch_upstream__name( + &upstream_name, repo, "refs/heads/track-local")); + + cl_assert_equal_s("refs/heads/master", git_buf_cstr(&upstream_name)); +} + +void test_refs_branches_upstreamname__can_return_the_size_of_thelocal_upstream_reference_name_of_a_local_branch(void) +{ + cl_assert_equal_i((int)strlen("refs/heads/master") + 1, + git_branch_upstream_name(NULL, 0, repo, "refs/heads/track-local")); +} diff --git a/tests/refs/crashes.c b/tests/refs/crashes.c new file mode 100644 index 000000000..5a1885a7a --- /dev/null +++ b/tests/refs/crashes.c @@ -0,0 +1,20 @@ +#include "clar_libgit2.h" + +void test_refs_crashes__double_free(void) +{ + git_repository *repo; + git_reference *ref, *ref2; + const char *REFNAME = "refs/heads/xxx"; + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_reference_symbolic_create(&ref, repo, REFNAME, "refs/heads/master", 0)); + cl_git_pass(git_reference_lookup(&ref2, repo, REFNAME)); + cl_git_pass(git_reference_delete(ref)); + git_reference_free(ref); + git_reference_free(ref2); + + /* reference is gone from disk, so reloading it will fail */ + cl_git_fail(git_reference_lookup(&ref2, repo, REFNAME)); + + git_repository_free(repo); +} diff --git a/tests/refs/create.c b/tests/refs/create.c new file mode 100644 index 000000000..85ff05aa9 --- /dev/null +++ b/tests/refs/create.c @@ -0,0 +1,168 @@ +#include "clar_libgit2.h" + +#include "repository.h" +#include "git2/reflog.h" +#include "reflog.h" +#include "ref_helpers.h" + +static const char *current_master_tip = "099fabac3a9ea935598528c27f866e34089c2eff"; +static const char *current_head_target = "refs/heads/master"; + +static git_repository *g_repo; + +void test_refs_create__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_refs_create__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_refs_create__symbolic(void) +{ + // create a new symbolic reference + git_reference *new_reference, *looked_up_ref, *resolved_ref; + git_repository *repo2; + git_oid id; + + const char *new_head_tracker = "ANOTHER_HEAD_TRACKER"; + + git_oid_fromstr(&id, current_master_tip); + + /* Create and write the new symbolic reference */ + cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0)); + + /* 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); + + /* ...peeled.. */ + cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref)); + cl_assert(git_reference_type(resolved_ref) == GIT_REF_OID); + + /* ...and that it points to the current master tip */ + cl_assert(git_oid_cmp(&id, git_reference_target(resolved_ref)) == 0); + git_reference_free(looked_up_ref); + git_reference_free(resolved_ref); + + /* Similar test with a fresh new repository */ + cl_git_pass(git_repository_open(&repo2, "testrepo")); + + cl_git_pass(git_reference_lookup(&looked_up_ref, repo2, new_head_tracker)); + cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref)); + cl_assert(git_oid_cmp(&id, git_reference_target(resolved_ref)) == 0); + + git_repository_free(repo2); + + git_reference_free(new_reference); + git_reference_free(looked_up_ref); + git_reference_free(resolved_ref); +} + +void test_refs_create__deep_symbolic(void) +{ + // create a deep symbolic reference + git_reference *new_reference, *looked_up_ref, *resolved_ref; + git_oid id; + + const char *new_head_tracker = "deep/rooted/tracker"; + + git_oid_fromstr(&id, current_master_tip); + + cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0)); + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head_tracker)); + cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref)); + cl_assert(git_oid_cmp(&id, git_reference_target(resolved_ref)) == 0); + + git_reference_free(new_reference); + git_reference_free(looked_up_ref); + git_reference_free(resolved_ref); +} + +void test_refs_create__oid(void) +{ + // create a new OID reference + git_reference *new_reference, *looked_up_ref; + git_repository *repo2; + git_oid id; + + const char *new_head = "refs/heads/new-head"; + + git_oid_fromstr(&id, current_master_tip); + + /* Create and write the new object id reference */ + cl_git_pass(git_reference_create(&new_reference, g_repo, new_head, &id, 0)); + + /* Ensure the reference can be looked-up... */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head)); + cl_assert(git_reference_type(looked_up_ref) & GIT_REF_OID); + cl_assert(reference_is_packed(looked_up_ref) == 0); + cl_assert_equal_s(looked_up_ref->name, new_head); + + /* ...and that it points to the current master tip */ + cl_assert(git_oid_cmp(&id, git_reference_target(looked_up_ref)) == 0); + git_reference_free(looked_up_ref); + + /* Similar test with a fresh new repository */ + cl_git_pass(git_repository_open(&repo2, "testrepo")); + + cl_git_pass(git_reference_lookup(&looked_up_ref, repo2, new_head)); + cl_assert(git_oid_cmp(&id, git_reference_target(looked_up_ref)) == 0); + + git_repository_free(repo2); + + git_reference_free(new_reference); + git_reference_free(looked_up_ref); +} + +void test_refs_create__oid_unknown(void) +{ + // Can not create a new OID reference which targets at an unknown id + git_reference *new_reference, *looked_up_ref; + git_oid id; + + const char *new_head = "refs/heads/new-head"; + + git_oid_fromstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644"); + + /* Create and write the new object id reference */ + cl_git_fail(git_reference_create(&new_reference, g_repo, new_head, &id, 0)); + + /* Ensure the reference can't be looked-up... */ + cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, new_head)); +} + +void test_refs_create__propagate_eexists(void) +{ + int error; + git_oid oid; + git_reference *ref; + + /* Make sure it works for oid and for symbolic both */ + git_oid_fromstr(&oid, current_master_tip); + error = git_reference_create(&ref, g_repo, current_head_target, &oid, false); + cl_assert(error == GIT_EEXISTS); + + error = git_reference_symbolic_create(&ref, g_repo, "HEAD", current_head_target, false); + cl_assert(error == GIT_EEXISTS); +} + +void test_refs_create__creating_a_reference_with_an_invalid_name_returns_EINVALIDSPEC(void) +{ + git_reference *new_reference; + git_oid id; + + const char *name = "refs/heads/inv@{id"; + + git_oid_fromstr(&id, current_master_tip); + + cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_create( + &new_reference, g_repo, name, &id, 0)); + + cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_symbolic_create( + &new_reference, g_repo, name, current_head_target, 0)); +} diff --git a/tests/refs/delete.c b/tests/refs/delete.c new file mode 100644 index 000000000..973768aeb --- /dev/null +++ b/tests/refs/delete.c @@ -0,0 +1,93 @@ +#include "clar_libgit2.h" + +#include "fileops.h" +#include "git2/reflog.h" +#include "git2/refdb.h" +#include "reflog.h" +#include "ref_helpers.h" + +static const char *packed_test_head_name = "refs/heads/packed-test"; +static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"; + +static git_repository *g_repo; + + + +void test_refs_delete__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_refs_delete__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + + + +void test_refs_delete__packed_loose(void) +{ + // deleting a ref which is both packed and loose should remove both tracks in the filesystem + git_reference *looked_up_ref, *another_looked_up_ref; + git_buf temp_path = GIT_BUF_INIT; + + /* Ensure the loose reference exists on the file system */ + cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), packed_test_head_name)); + cl_assert(git_path_exists(temp_path.ptr)); + + /* Lookup the reference */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name)); + + /* Ensure it's the loose version that has been found */ + cl_assert(reference_is_packed(looked_up_ref) == 0); + + /* Now that the reference is deleted... */ + cl_git_pass(git_reference_delete(looked_up_ref)); + git_reference_free(looked_up_ref); + + /* Looking up the reference once again should not retrieve it */ + cl_git_fail(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name)); + + /* Ensure the loose reference doesn't exist any longer on the file system */ + cl_assert(!git_path_exists(temp_path.ptr)); + + git_reference_free(another_looked_up_ref); + git_buf_free(&temp_path); +} + +void test_refs_delete__packed_only(void) +{ + // can delete a just packed reference + git_reference *ref; + git_refdb *refdb; + git_oid id; + const char *new_ref = "refs/heads/new_ref"; + + git_oid_fromstr(&id, current_master_tip); + + /* Create and write the new object id reference */ + cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &id, 0)); + git_reference_free(ref); + + /* Lookup the reference */ + cl_git_pass(git_reference_lookup(&ref, g_repo, new_ref)); + + /* Ensure it's a loose reference */ + cl_assert(reference_is_packed(ref) == 0); + + /* Pack all existing references */ + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + + /* Reload the reference from disk */ + git_reference_free(ref); + cl_git_pass(git_reference_lookup(&ref, g_repo, new_ref)); + + /* Ensure it's a packed reference */ + cl_assert(reference_is_packed(ref) == 1); + + /* This should pass */ + cl_git_pass(git_reference_delete(ref)); + git_reference_free(ref); + git_refdb_free(refdb); +} diff --git a/tests/refs/foreachglob.c b/tests/refs/foreachglob.c new file mode 100644 index 000000000..2c458082f --- /dev/null +++ b/tests/refs/foreachglob.c @@ -0,0 +1,95 @@ +#include "clar_libgit2.h" +#include "refs.h" + +static git_repository *repo; +static git_reference *fake_remote; + +void test_refs_foreachglob__initialize(void) +{ + git_oid id; + + cl_fixture_sandbox("testrepo.git"); + cl_git_pass(git_repository_open(&repo, "testrepo.git")); + + cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); + cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0)); +} + +void test_refs_foreachglob__cleanup(void) +{ + git_reference_free(fake_remote); + fake_remote = NULL; + + git_repository_free(repo); + repo = NULL; + + cl_fixture_cleanup("testrepo.git"); +} + +static int count_cb(const char *reference_name, void *payload) +{ + int *count = (int *)payload; + + GIT_UNUSED(reference_name); + + (*count)++; + + return 0; +} + +static void assert_retrieval(const char *glob, int expected_count) +{ + int count = 0; + + cl_git_pass(git_reference_foreach_glob(repo, glob, count_cb, &count)); + + cl_assert_equal_i(expected_count, count); +} + +void test_refs_foreachglob__retrieve_all_refs(void) +{ + /* 12 heads (including one packed head) + 1 note + 2 remotes + 7 tags */ + assert_retrieval("*", 22); +} + +void test_refs_foreachglob__retrieve_remote_branches(void) +{ + assert_retrieval("refs/remotes/*", 2); +} + +void test_refs_foreachglob__retrieve_local_branches(void) +{ + assert_retrieval("refs/heads/*", 12); +} + +void test_refs_foreachglob__retrieve_partially_named_references(void) +{ + /* + * refs/heads/packed-test, refs/heads/test + * refs/remotes/test/master, refs/tags/test + */ + + assert_retrieval("*test*", 4); +} + + +static int interrupt_cb(const char *reference_name, void *payload) +{ + int *count = (int *)payload; + + GIT_UNUSED(reference_name); + + (*count)++; + + return (*count == 11); +} + +void test_refs_foreachglob__can_cancel(void) +{ + int count = 0; + + cl_assert_equal_i(GIT_EUSER, git_reference_foreach_glob( + repo, "*", interrupt_cb, &count) ); + + cl_assert_equal_i(11, count); +} diff --git a/tests/refs/isvalidname.c b/tests/refs/isvalidname.c new file mode 100644 index 000000000..65c70ba4d --- /dev/null +++ b/tests/refs/isvalidname.c @@ -0,0 +1,31 @@ +#include "clar_libgit2.h" + +void test_refs_isvalidname__can_detect_invalid_formats(void) +{ + cl_assert_equal_i(false, git_reference_is_valid_name("refs/tags/0.17.0^{}")); + cl_assert_equal_i(false, git_reference_is_valid_name("TWO/LEVELS")); + cl_assert_equal_i(false, git_reference_is_valid_name("ONE.LEVEL")); + cl_assert_equal_i(false, git_reference_is_valid_name("HEAD/")); + cl_assert_equal_i(false, git_reference_is_valid_name("NO_TRAILING_UNDERSCORE_")); + cl_assert_equal_i(false, git_reference_is_valid_name("_NO_LEADING_UNDERSCORE")); + cl_assert_equal_i(false, git_reference_is_valid_name("HEAD/aa")); + cl_assert_equal_i(false, git_reference_is_valid_name("lower_case")); + cl_assert_equal_i(false, git_reference_is_valid_name("/stupid/name/master")); + cl_assert_equal_i(false, git_reference_is_valid_name("/")); + cl_assert_equal_i(false, git_reference_is_valid_name("//")); + cl_assert_equal_i(false, git_reference_is_valid_name("")); + cl_assert_equal_i(false, git_reference_is_valid_name("refs/heads/sub.lock/webmatrix")); +} + +void test_refs_isvalidname__wont_hopefully_choke_on_valid_formats(void) +{ + cl_assert_equal_i(true, git_reference_is_valid_name("refs/tags/0.17.0")); + cl_assert_equal_i(true, git_reference_is_valid_name("refs/LEVELS")); + cl_assert_equal_i(true, git_reference_is_valid_name("HEAD")); + cl_assert_equal_i(true, git_reference_is_valid_name("ONE_LEVEL")); + cl_assert_equal_i(true, git_reference_is_valid_name("refs/stash")); + cl_assert_equal_i(true, git_reference_is_valid_name("refs/remotes/origin/bim_with_3d@11296")); + cl_assert_equal_i(true, git_reference_is_valid_name("refs/master{yesterday")); + cl_assert_equal_i(true, git_reference_is_valid_name("refs/master}yesterday")); + cl_assert_equal_i(true, git_reference_is_valid_name("refs/master{yesterday}")); +} diff --git a/tests/refs/iterator.c b/tests/refs/iterator.c new file mode 100644 index 000000000..266410fdf --- /dev/null +++ b/tests/refs/iterator.c @@ -0,0 +1,97 @@ +#include "clar_libgit2.h" +#include "refs.h" +#include "vector.h" + +static git_repository *repo; + +void test_refs_iterator__initialize(void) +{ + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); +} + +void test_refs_iterator__cleanup(void) +{ + git_repository_free(repo); +} + +static const char *refnames[] = { + "refs/heads/br2", + "refs/heads/cannot-fetch", + "refs/heads/chomped", + "refs/heads/haacked", + "refs/heads/master", + "refs/heads/not-good", + "refs/heads/packed", + "refs/heads/packed-test", + "refs/heads/subtrees", + "refs/heads/test", + "refs/heads/track-local", + "refs/heads/trailing", + "refs/notes/fanout", + "refs/remotes/test/master", + "refs/tags/annotated_tag_to_blob", + "refs/tags/e90810b", + "refs/tags/hard_tag", + "refs/tags/point_to_blob", + "refs/tags/taggerless", + "refs/tags/test", + "refs/tags/wrapped_tag", +}; + +static int refcmp_cb(const void *a, const void *b) +{ + const git_reference *refa = (const git_reference *)a; + const git_reference *refb = (const git_reference *)b; + + return strcmp(refa->name, refb->name); +} + +void test_refs_iterator__list(void) +{ + git_reference_iterator *iter; + git_vector output; + git_reference *ref; + int error; + size_t i; + + cl_git_pass(git_vector_init(&output, 32, &refcmp_cb)); + cl_git_pass(git_reference_iterator_new(&iter, repo)); + + do { + error = git_reference_next(&ref, iter); + cl_assert(error == 0 || error == GIT_ITEROVER); + if (error != GIT_ITEROVER) { + cl_git_pass(git_vector_insert(&output, ref)); + } + } while (!error); + + git_reference_iterator_free(iter); + cl_assert_equal_sz(output.length, ARRAY_SIZE(refnames)); + + git_vector_sort(&output); + + git_vector_foreach(&output, i, ref) { + cl_assert_equal_s(ref->name, refnames[i]); + git_reference_free(ref); + } + + git_vector_free(&output); +} + +void test_refs_iterator__empty(void) +{ + git_reference_iterator *iter; + git_odb *odb; + git_reference *ref; + git_repository *empty; + + cl_git_pass(git_odb_new(&odb)); + cl_git_pass(git_repository_wrap_odb(&empty, odb)); + + cl_git_pass(git_reference_iterator_new(&iter, empty)); + cl_assert_equal_i(GIT_ITEROVER, git_reference_next(&ref, iter)); + + git_reference_iterator_free(iter); + git_odb_free(odb); + git_repository_free(empty); +} diff --git a/tests/refs/list.c b/tests/refs/list.c new file mode 100644 index 000000000..de5c0fd3d --- /dev/null +++ b/tests/refs/list.c @@ -0,0 +1,57 @@ +#include "clar_libgit2.h" + +#include "repository.h" +#include "git2/reflog.h" +#include "reflog.h" + +static git_repository *g_repo; + + + +void test_refs_list__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_refs_list__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + + + +void test_refs_list__all(void) +{ + // try to list all the references in our test repo + git_strarray ref_list; + + cl_git_pass(git_reference_list(&ref_list, g_repo)); + + /*{ + unsigned short i; + for (i = 0; i < ref_list.count; ++i) + printf("# %s\n", ref_list.strings[i]); + }*/ + + /* 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, 14); + + git_strarray_free(&ref_list); +} + +void test_refs_list__do_not_retrieve_references_which_name_end_with_a_lock_extension(void) +{ + git_strarray ref_list; + + /* Create a fake locked reference */ + cl_git_mkfile( + "./testrepo/.git/refs/heads/hanwen.lock", + "144344043ba4d4a405da03de3844aa829ae8be0e\n"); + + cl_git_pass(git_reference_list(&ref_list, g_repo)); + cl_assert_equal_i((int)ref_list.count, 14); + + git_strarray_free(&ref_list); +} diff --git a/tests/refs/listall.c b/tests/refs/listall.c new file mode 100644 index 000000000..c696fbb2e --- /dev/null +++ b/tests/refs/listall.c @@ -0,0 +1,47 @@ +#include "clar_libgit2.h" +#include "posix.h" + +static git_repository *repo; +static git_strarray ref_list; + +static void ensure_no_refname_starts_with_a_forward_slash(const char *path) +{ + size_t i; + + cl_git_pass(git_repository_open(&repo, path)); + cl_git_pass(git_reference_list(&ref_list, repo)); + + cl_assert(ref_list.count > 0); + + for (i = 0; i < ref_list.count; i++) + cl_assert(git__prefixcmp(ref_list.strings[i], "/") != 0); + + git_strarray_free(&ref_list); + git_repository_free(repo); +} + +void test_refs_listall__from_repository_opened_through_workdir_path(void) +{ + cl_fixture_sandbox("status"); + cl_git_pass(p_rename("status/.gitted", "status/.git")); + + ensure_no_refname_starts_with_a_forward_slash("status"); + + cl_fixture_cleanup("status"); +} + +void test_refs_listall__from_repository_opened_through_gitdir_path(void) +{ + ensure_no_refname_starts_with_a_forward_slash(cl_fixture("testrepo.git")); +} + +void test_refs_listall__from_repository_with_no_trailing_newline(void) +{ + cl_git_pass(git_repository_open(&repo, cl_fixture("bad_tag.git"))); + cl_git_pass(git_reference_list(&ref_list, repo)); + + cl_assert(ref_list.count > 0); + + git_strarray_free(&ref_list); + git_repository_free(repo); +} diff --git a/tests/refs/lookup.c b/tests/refs/lookup.c new file mode 100644 index 000000000..2e31cf0f6 --- /dev/null +++ b/tests/refs/lookup.c @@ -0,0 +1,60 @@ +#include "clar_libgit2.h" +#include "refs.h" + +static git_repository *g_repo; + +void test_refs_lookup__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); +} + +void test_refs_lookup__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_refs_lookup__with_resolve(void) +{ + git_reference *a, *b, *temp; + + cl_git_pass(git_reference_lookup(&temp, g_repo, "HEAD")); + cl_git_pass(git_reference_resolve(&a, temp)); + git_reference_free(temp); + + cl_git_pass(git_reference_lookup_resolved(&b, g_repo, "HEAD", 5)); + cl_assert(git_reference_cmp(a, b) == 0); + git_reference_free(b); + + cl_git_pass(git_reference_lookup_resolved(&b, g_repo, "HEAD_TRACKER", 5)); + cl_assert(git_reference_cmp(a, b) == 0); + git_reference_free(b); + + git_reference_free(a); +} + +void test_refs_lookup__invalid_name(void) +{ + git_oid oid; + cl_git_fail(git_reference_name_to_id(&oid, g_repo, "/refs/tags/point_to_blob")); +} + +void test_refs_lookup__oid(void) +{ + git_oid tag, expected; + + cl_git_pass(git_reference_name_to_id(&tag, g_repo, "refs/tags/point_to_blob")); + cl_git_pass(git_oid_fromstr(&expected, "1385f264afb75a56a5bec74243be9b367ba4ca08")); + cl_assert(git_oid_cmp(&tag, &expected) == 0); +} + +void test_refs_lookup__namespace(void) +{ + int error; + git_reference *ref; + + error = git_reference_lookup(&ref, g_repo, "refs/heads"); + cl_assert_equal_i(error, GIT_ENOTFOUND); + + error = git_reference_lookup(&ref, g_repo, "refs/heads/"); + cl_assert_equal_i(error, GIT_EINVALIDSPEC); +} diff --git a/tests/refs/normalize.c b/tests/refs/normalize.c new file mode 100644 index 000000000..7f313ef38 --- /dev/null +++ b/tests/refs/normalize.c @@ -0,0 +1,403 @@ +#include "clar_libgit2.h" + +#include "repository.h" +#include "git2/reflog.h" +#include "reflog.h" + +// Helpers +static void ensure_refname_normalized( + unsigned int flags, + const char *input_refname, + const char *expected_refname) +{ + char buffer_out[GIT_REFNAME_MAX]; + + cl_git_pass(git_reference_normalize_name(buffer_out, sizeof(buffer_out), input_refname, flags)); + + cl_assert_equal_s(expected_refname, buffer_out); +} + +static void ensure_refname_invalid(unsigned int flags, const char *input_refname) +{ + char buffer_out[GIT_REFNAME_MAX]; + + cl_assert_equal_i( + GIT_EINVALIDSPEC, + git_reference_normalize_name(buffer_out, sizeof(buffer_out), input_refname, flags)); +} + +void test_refs_normalize__can_normalize_a_direct_reference_name(void) +{ + ensure_refname_normalized( + GIT_REF_FORMAT_NORMAL, "refs/dummy/a", "refs/dummy/a"); + ensure_refname_normalized( + GIT_REF_FORMAT_NORMAL, "refs/stash", "refs/stash"); + ensure_refname_normalized( + GIT_REF_FORMAT_NORMAL, "refs/tags/a", "refs/tags/a"); + ensure_refname_normalized( + GIT_REF_FORMAT_NORMAL, "refs/heads/a/b", "refs/heads/a/b"); + ensure_refname_normalized( + GIT_REF_FORMAT_NORMAL, "refs/heads/a./b", "refs/heads/a./b"); + ensure_refname_normalized( + GIT_REF_FORMAT_NORMAL, "refs/heads/v@ation", "refs/heads/v@ation"); + ensure_refname_normalized( + GIT_REF_FORMAT_NORMAL, "refs///heads///a", "refs/heads/a"); +} + +void test_refs_normalize__cannot_normalize_any_direct_reference_name(void) +{ + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "a"); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "/a"); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "//a"); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, ""); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "/refs/heads/a/"); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "refs/heads/a/"); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "refs/heads/a."); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "refs/heads/a.lock"); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "refs/heads/foo?bar"); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "refs/heads\foo"); + ensure_refname_normalized( + GIT_REF_FORMAT_NORMAL, "refs/heads/v@ation", "refs/heads/v@ation"); + ensure_refname_normalized( + GIT_REF_FORMAT_NORMAL, "refs///heads///a", "refs/heads/a"); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "refs/heads/.a/b"); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "refs/heads/foo/../bar"); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "refs/heads/foo..bar"); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "refs/heads/./foo"); + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "refs/heads/v@{ation"); +} + +void test_refs_normalize__symbolic(void) +{ + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, ""); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "heads\foo"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "/"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "///"); + + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "ALL_CAPS_AND_UNDERSCORES", "ALL_CAPS_AND_UNDERSCORES"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/MixedCasing", "refs/MixedCasing"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs///heads///a", "refs/heads/a"); + + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "HEAD", "HEAD"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "MERGE_HEAD", "MERGE_HEAD"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "FETCH_HEAD", "FETCH_HEAD"); +} + +/* Ported from JGit, BSD licence. + * See https://github.com/spearce/JGit/commit/e4bf8f6957bbb29362575d641d1e77a02d906739 + * + * Copyright (C) 2009, Google Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Git Development Community nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +void test_refs_normalize__jgit_suite(void) +{ + // tests borrowed from JGit + +/* EmptyString */ + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, ""); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "/"); + +/* MustHaveTwoComponents */ + ensure_refname_invalid( + GIT_REF_FORMAT_NORMAL, "master"); + ensure_refname_normalized( + GIT_REF_FORMAT_NORMAL, "heads/master", "heads/master"); + +/* ValidHead */ + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master", "refs/heads/master"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/pu", "refs/heads/pu"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/z", "refs/heads/z"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/FoO", "refs/heads/FoO"); + +/* ValidTag */ + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/tags/v1.0", "refs/tags/v1.0"); + +/* NoLockSuffix */ + ensure_refname_invalid(GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master.lock"); + +/* NoDirectorySuffix */ + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master/"); + +/* NoSpace */ + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/i haz space"); + +/* NoAsciiControlCharacters */ + { + char c; + char buffer[GIT_REFNAME_MAX]; + for (c = '\1'; c < ' '; c++) { + strncpy(buffer, "refs/heads/mast", 15); + strncpy(buffer + 15, (const char *)&c, 1); + strncpy(buffer + 16, "er", 2); + buffer[18 - 1] = '\0'; + ensure_refname_invalid(GIT_REF_FORMAT_ALLOW_ONELEVEL, buffer); + } + } + +/* NoBareDot */ + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/."); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/.."); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/./master"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/../master"); + +/* NoLeadingOrTrailingDot */ + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "."); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/.bar"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/..bar"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/bar."); + +/* ContainsDot */ + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/m.a.s.t.e.r", "refs/heads/m.a.s.t.e.r"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master..pu"); + +/* NoMagicRefCharacters */ + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master^"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/^master"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "^refs/heads/master"); + + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master~"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/~master"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "~refs/heads/master"); + + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master:"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/:master"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, ":refs/heads/master"); + +/* ShellGlob */ + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master?"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/?master"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "?refs/heads/master"); + + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master["); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/[master"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "[refs/heads/master"); + + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master*"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/*master"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "*refs/heads/master"); + +/* ValidSpecialCharacters */ + ensure_refname_normalized + (GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/!", "refs/heads/!"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/\"", "refs/heads/\""); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/#", "refs/heads/#"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/$", "refs/heads/$"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/%", "refs/heads/%"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/&", "refs/heads/&"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/'", "refs/heads/'"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/(", "refs/heads/("); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/)", "refs/heads/)"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/+", "refs/heads/+"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/,", "refs/heads/,"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/-", "refs/heads/-"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/;", "refs/heads/;"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/<", "refs/heads/<"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/=", "refs/heads/="); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/>", "refs/heads/>"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/@", "refs/heads/@"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/]", "refs/heads/]"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/_", "refs/heads/_"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/`", "refs/heads/`"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/{", "refs/heads/{"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/|", "refs/heads/|"); + ensure_refname_normalized( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/}", "refs/heads/}"); + + // This is valid on UNIX, but not on Windows + // hence we make in invalid due to non-portability + // + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/\\"); + +/* UnicodeNames */ + /* + * Currently this fails. + * ensure_refname_normalized(GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/\u00e5ngstr\u00f6m", "refs/heads/\u00e5ngstr\u00f6m"); + */ + +/* RefLogQueryIsValidRef */ + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master@{1}"); + ensure_refname_invalid( + GIT_REF_FORMAT_ALLOW_ONELEVEL, "refs/heads/master@{1.hour.ago}"); +} + +void test_refs_normalize__buffer_has_to_be_big_enough_to_hold_the_normalized_version(void) +{ + char buffer_out[21]; + + cl_git_pass(git_reference_normalize_name( + buffer_out, 21, "refs//heads///long///name", GIT_REF_FORMAT_NORMAL)); + cl_git_fail(git_reference_normalize_name( + buffer_out, 20, "refs//heads///long///name", GIT_REF_FORMAT_NORMAL)); +} + +#define ONE_LEVEL_AND_REFSPEC \ + GIT_REF_FORMAT_ALLOW_ONELEVEL \ + | GIT_REF_FORMAT_REFSPEC_PATTERN + +void test_refs_normalize__refspec_pattern(void) +{ + ensure_refname_invalid( + GIT_REF_FORMAT_REFSPEC_PATTERN, "heads/*foo/bar"); + ensure_refname_invalid( + GIT_REF_FORMAT_REFSPEC_PATTERN, "heads/foo*/bar"); + ensure_refname_invalid( + GIT_REF_FORMAT_REFSPEC_PATTERN, "heads/f*o/bar"); + + ensure_refname_invalid( + GIT_REF_FORMAT_REFSPEC_PATTERN, "foo"); + ensure_refname_normalized( + ONE_LEVEL_AND_REFSPEC, "FOO", "FOO"); + + ensure_refname_normalized( + GIT_REF_FORMAT_REFSPEC_PATTERN, "foo/bar", "foo/bar"); + ensure_refname_normalized( + ONE_LEVEL_AND_REFSPEC, "foo/bar", "foo/bar"); + + ensure_refname_normalized( + GIT_REF_FORMAT_REFSPEC_PATTERN, "*/foo", "*/foo"); + ensure_refname_normalized( + ONE_LEVEL_AND_REFSPEC, "*/foo", "*/foo"); + + ensure_refname_normalized( + GIT_REF_FORMAT_REFSPEC_PATTERN, "foo/*/bar", "foo/*/bar"); + ensure_refname_normalized( + ONE_LEVEL_AND_REFSPEC, "foo/*/bar", "foo/*/bar"); + + ensure_refname_invalid( + GIT_REF_FORMAT_REFSPEC_PATTERN, "*"); + ensure_refname_normalized( + ONE_LEVEL_AND_REFSPEC, "*", "*"); + + ensure_refname_invalid( + GIT_REF_FORMAT_REFSPEC_PATTERN, "foo/*/*"); + ensure_refname_invalid( + ONE_LEVEL_AND_REFSPEC, "foo/*/*"); + + ensure_refname_invalid( + GIT_REF_FORMAT_REFSPEC_PATTERN, "*/foo/*"); + ensure_refname_invalid( + ONE_LEVEL_AND_REFSPEC, "*/foo/*"); + + ensure_refname_invalid( + GIT_REF_FORMAT_REFSPEC_PATTERN, "*/*/foo"); + ensure_refname_invalid( + ONE_LEVEL_AND_REFSPEC, "*/*/foo"); +} diff --git a/tests/refs/overwrite.c b/tests/refs/overwrite.c new file mode 100644 index 000000000..ebe72069c --- /dev/null +++ b/tests/refs/overwrite.c @@ -0,0 +1,136 @@ +#include "clar_libgit2.h" + +#include "repository.h" +#include "git2/reflog.h" +#include "reflog.h" + +static const char *ref_name = "refs/heads/other"; +static const char *ref_master_name = "refs/heads/master"; +static const char *ref_branch_name = "refs/heads/branch"; +static const char *ref_test_name = "refs/heads/test"; + +static git_repository *g_repo; + +void test_refs_overwrite__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_refs_overwrite__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_refs_overwrite__symbolic(void) +{ + // Overwrite an existing symbolic reference + git_reference *ref, *branch_ref; + + /* The target needds to exist and we need to check the name has changed */ + cl_git_pass(git_reference_symbolic_create(&branch_ref, g_repo, ref_branch_name, ref_master_name, 0)); + cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_branch_name, 0)); + git_reference_free(ref); + + /* Ensure it points to the right place*/ + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); + cl_assert(git_reference_type(ref) & GIT_REF_SYMBOLIC); + cl_assert_equal_s(git_reference_symbolic_target(ref), ref_branch_name); + git_reference_free(ref); + + /* Ensure we can't create it unless we force it to */ + cl_git_fail(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0)); + cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 1)); + git_reference_free(ref); + + /* Ensure it points to the right place */ + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); + cl_assert(git_reference_type(ref) & GIT_REF_SYMBOLIC); + cl_assert_equal_s(git_reference_symbolic_target(ref), ref_master_name); + + git_reference_free(ref); + git_reference_free(branch_ref); +} + +void test_refs_overwrite__object_id(void) +{ + // Overwrite an existing object id reference + git_reference *ref; + git_oid id; + + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); + cl_assert(git_reference_type(ref) & GIT_REF_OID); + git_oid_cpy(&id, git_reference_target(ref)); + git_reference_free(ref); + + /* Create it */ + cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 0)); + git_reference_free(ref); + + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_test_name)); + cl_assert(git_reference_type(ref) & GIT_REF_OID); + git_oid_cpy(&id, git_reference_target(ref)); + git_reference_free(ref); + + /* Ensure we can't overwrite unless we force it */ + cl_git_fail(git_reference_create(&ref, g_repo, ref_name, &id, 0)); + cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 1)); + git_reference_free(ref); + + /* Ensure it has been overwritten */ + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); + cl_assert(!git_oid_cmp(&id, git_reference_target(ref))); + + git_reference_free(ref); +} + +void test_refs_overwrite__object_id_with_symbolic(void) +{ + // Overwrite an existing object id reference with a symbolic one + git_reference *ref; + git_oid id; + + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); + cl_assert(git_reference_type(ref) & GIT_REF_OID); + git_oid_cpy(&id, git_reference_target(ref)); + git_reference_free(ref); + + cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 0)); + git_reference_free(ref); + cl_git_fail(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0)); + cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 1)); + git_reference_free(ref); + + /* Ensure it points to the right place */ + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); + cl_assert(git_reference_type(ref) & GIT_REF_SYMBOLIC); + cl_assert_equal_s(git_reference_symbolic_target(ref), ref_master_name); + + git_reference_free(ref); +} + +void test_refs_overwrite__symbolic_with_object_id(void) +{ + // Overwrite an existing symbolic reference with an object id one + git_reference *ref; + git_oid id; + + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); + cl_assert(git_reference_type(ref) & GIT_REF_OID); + git_oid_cpy(&id, git_reference_target(ref)); + git_reference_free(ref); + + /* Create the symbolic ref */ + cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0)); + git_reference_free(ref); + /* It shouldn't overwrite unless we tell it to */ + cl_git_fail(git_reference_create(&ref, g_repo, ref_name, &id, 0)); + cl_git_pass(git_reference_create(&ref, g_repo, ref_name, &id, 1)); + git_reference_free(ref); + + /* Ensure it points to the right place */ + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); + cl_assert(git_reference_type(ref) & GIT_REF_OID); + cl_assert(!git_oid_cmp(git_reference_target(ref), &id)); + + git_reference_free(ref); +} diff --git a/tests/refs/pack.c b/tests/refs/pack.c new file mode 100644 index 000000000..849a052aa --- /dev/null +++ b/tests/refs/pack.c @@ -0,0 +1,105 @@ +#include "clar_libgit2.h" + +#include "fileops.h" +#include "git2/reflog.h" +#include "git2/refdb.h" +#include "reflog.h" +#include "refs.h" +#include "ref_helpers.h" + +static const char *loose_tag_ref_name = "refs/tags/e90810b"; + +static git_repository *g_repo; + +void test_refs_pack__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_refs_pack__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void packall(void) +{ + git_refdb *refdb; + + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + git_refdb_free(refdb); +} + +void test_refs_pack__empty(void) +{ + /* create a packfile for an empty folder */ + git_buf temp_path = GIT_BUF_INIT; + + cl_git_pass(git_buf_join_n(&temp_path, '/', 3, git_repository_path(g_repo), GIT_REFS_HEADS_DIR, "empty_dir")); + cl_git_pass(git_futils_mkdir_r(temp_path.ptr, NULL, GIT_REFS_DIR_MODE)); + git_buf_free(&temp_path); + + packall(); +} + +void test_refs_pack__loose(void) +{ + /* create a packfile from all the loose refs in a repo */ + git_reference *reference; + git_buf temp_path = GIT_BUF_INIT; + + /* Ensure a known loose ref can be looked up */ + cl_git_pass(git_reference_lookup(&reference, g_repo, loose_tag_ref_name)); + cl_assert(reference_is_packed(reference) == 0); + cl_assert_equal_s(reference->name, loose_tag_ref_name); + git_reference_free(reference); + + /* + * We are now trying to pack also a loose reference + * called `points_to_blob`, to make sure we can properly + * pack weak tags + */ + packall(); + + /* Ensure the packed-refs file exists */ + cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), GIT_PACKEDREFS_FILE)); + cl_assert(git_path_exists(temp_path.ptr)); + + /* Ensure the known ref can still be looked up but is now packed */ + cl_git_pass(git_reference_lookup(&reference, g_repo, loose_tag_ref_name)); + cl_assert(reference_is_packed(reference)); + cl_assert_equal_s(reference->name, loose_tag_ref_name); + + /* Ensure the known ref has been removed from the loose folder structure */ + cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), loose_tag_ref_name)); + cl_assert(!git_path_exists(temp_path.ptr)); + + git_reference_free(reference); + git_buf_free(&temp_path); +} + +void test_refs_pack__symbolic(void) +{ + /* create a packfile from loose refs skipping symbolic refs */ + int i; + git_oid head; + git_reference *ref; + char name[128]; + + cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); + + /* make a bunch of references */ + + for (i = 0; i < 100; ++i) { + snprintf(name, sizeof(name), "refs/heads/symbolic-%03d", i); + cl_git_pass(git_reference_symbolic_create( + &ref, g_repo, name, "refs/heads/master", 0)); + git_reference_free(ref); + + snprintf(name, sizeof(name), "refs/heads/direct-%03d", i); + cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0)); + git_reference_free(ref); + } + + packall(); +} diff --git a/tests/refs/peel.c b/tests/refs/peel.c new file mode 100644 index 000000000..f2fb6e259 --- /dev/null +++ b/tests/refs/peel.c @@ -0,0 +1,119 @@ +#include "clar_libgit2.h" + +static git_repository *g_repo; +static git_repository *g_peel_repo; + +void test_refs_peel__initialize(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_repository_open(&g_peel_repo, cl_fixture("peeled.git"))); +} + +void test_refs_peel__cleanup(void) +{ + git_repository_free(g_repo); + g_repo = NULL; + git_repository_free(g_peel_repo); + g_peel_repo = NULL; +} + +static void assert_peel_generic( + git_repository *repo, + const char *ref_name, + git_otype requested_type, + const char* expected_sha, + git_otype expected_type) +{ + git_oid expected_oid; + git_reference *ref; + git_object *peeled; + + cl_git_pass(git_reference_lookup(&ref, repo, ref_name)); + + cl_git_pass(git_reference_peel(&peeled, ref, requested_type)); + + cl_git_pass(git_oid_fromstr(&expected_oid, expected_sha)); + cl_assert_equal_i(0, git_oid_cmp(&expected_oid, git_object_id(peeled))); + + cl_assert_equal_i(expected_type, git_object_type(peeled)); + + git_object_free(peeled); + git_reference_free(ref); +} + +static void assert_peel( + const char *ref_name, + git_otype requested_type, + const char* expected_sha, + git_otype expected_type) +{ + assert_peel_generic(g_repo, ref_name, requested_type, + expected_sha, expected_type); +} + +static void assert_peel_error(int error, const char *ref_name, git_otype requested_type) +{ + git_reference *ref; + git_object *peeled; + + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); + + cl_assert_equal_i(error, git_reference_peel(&peeled, ref, requested_type)); + + git_reference_free(ref); +} + +void test_refs_peel__can_peel_a_tag(void) +{ + assert_peel("refs/tags/test", GIT_OBJ_TAG, + "b25fa35b38051e4ae45d4222e795f9df2e43f1d1", GIT_OBJ_TAG); + assert_peel("refs/tags/test", GIT_OBJ_COMMIT, + "e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_COMMIT); + assert_peel("refs/tags/test", GIT_OBJ_TREE, + "53fc32d17276939fc79ed05badaef2db09990016", GIT_OBJ_TREE); + assert_peel("refs/tags/point_to_blob", GIT_OBJ_BLOB, + "1385f264afb75a56a5bec74243be9b367ba4ca08", GIT_OBJ_BLOB); +} + +void test_refs_peel__can_peel_a_branch(void) +{ + assert_peel("refs/heads/master", GIT_OBJ_COMMIT, + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", GIT_OBJ_COMMIT); + assert_peel("refs/heads/master", GIT_OBJ_TREE, + "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162", GIT_OBJ_TREE); +} + +void test_refs_peel__can_peel_a_symbolic_reference(void) +{ + assert_peel("HEAD", GIT_OBJ_COMMIT, + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", GIT_OBJ_COMMIT); + assert_peel("HEAD", GIT_OBJ_TREE, + "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162", GIT_OBJ_TREE); +} + +void test_refs_peel__cannot_peel_into_a_non_existing_target(void) +{ + assert_peel_error(GIT_ENOTFOUND, "refs/tags/point_to_blob", GIT_OBJ_TAG); +} + +void test_refs_peel__can_peel_into_any_non_tag_object(void) +{ + assert_peel("refs/heads/master", GIT_OBJ_ANY, + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", GIT_OBJ_COMMIT); + assert_peel("refs/tags/point_to_blob", GIT_OBJ_ANY, + "1385f264afb75a56a5bec74243be9b367ba4ca08", GIT_OBJ_BLOB); + assert_peel("refs/tags/test", GIT_OBJ_ANY, + "e90810b8df3e80c413d903f631643c716887138d", GIT_OBJ_COMMIT); +} + +void test_refs_peel__can_peel_fully_peeled_packed_refs(void) +{ + assert_peel_generic(g_peel_repo, + "refs/tags/tag-inside-tags", GIT_OBJ_ANY, + "0df1a5865c8abfc09f1f2182e6a31be550e99f07", + GIT_OBJ_COMMIT); + assert_peel_generic(g_peel_repo, + "refs/foo/tag-outside-tags", GIT_OBJ_ANY, + "0df1a5865c8abfc09f1f2182e6a31be550e99f07", + GIT_OBJ_COMMIT); +} diff --git a/tests/refs/read.c b/tests/refs/read.c new file mode 100644 index 000000000..35cf17e9e --- /dev/null +++ b/tests/refs/read.c @@ -0,0 +1,284 @@ +#include "clar_libgit2.h" + +#include "repository.h" +#include "git2/reflog.h" +#include "reflog.h" +#include "ref_helpers.h" + +static const char *loose_tag_ref_name = "refs/tags/e90810b"; +static const char *non_existing_tag_ref_name = "refs/tags/i-do-not-exist"; +static const char *head_tracker_sym_ref_name = "HEAD_TRACKER"; +static const char *current_head_target = "refs/heads/master"; +static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"; +static const char *packed_head_name = "refs/heads/packed"; +static const char *packed_test_head_name = "refs/heads/packed-test"; + +static git_repository *g_repo; + +void test_refs_read__initialize(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); +} + +void test_refs_read__cleanup(void) +{ + git_repository_free(g_repo); + g_repo = NULL; +} + +void test_refs_read__loose_tag(void) +{ + // lookup a loose tag reference + git_reference *reference; + git_object *object; + git_buf ref_name_from_tag_name = GIT_BUF_INIT; + + cl_git_pass(git_reference_lookup(&reference, g_repo, loose_tag_ref_name)); + cl_assert(git_reference_type(reference) & GIT_REF_OID); + cl_assert(reference_is_packed(reference) == 0); + cl_assert_equal_s(reference->name, loose_tag_ref_name); + + cl_git_pass(git_object_lookup(&object, g_repo, git_reference_target(reference), GIT_OBJ_ANY)); + cl_assert(object != NULL); + cl_assert(git_object_type(object) == GIT_OBJ_TAG); + + /* Ensure the name of the tag matches the name of the reference */ + cl_git_pass(git_buf_joinpath(&ref_name_from_tag_name, GIT_REFS_TAGS_DIR, git_tag_name((git_tag *)object))); + cl_assert_equal_s(ref_name_from_tag_name.ptr, loose_tag_ref_name); + git_buf_free(&ref_name_from_tag_name); + + git_object_free(object); + + git_reference_free(reference); +} + +void test_refs_read__nonexisting_tag(void) +{ + // lookup a loose tag reference that doesn't exist + git_reference *reference; + + cl_git_fail(git_reference_lookup(&reference, g_repo, non_existing_tag_ref_name)); + + git_reference_free(reference); +} + + +void test_refs_read__symbolic(void) +{ + // lookup a symbolic reference + git_reference *reference, *resolved_ref; + git_object *object; + git_oid id; + + cl_git_pass(git_reference_lookup(&reference, g_repo, GIT_HEAD_FILE)); + cl_assert(git_reference_type(reference) & GIT_REF_SYMBOLIC); + cl_assert(reference_is_packed(reference) == 0); + cl_assert_equal_s(reference->name, GIT_HEAD_FILE); + + cl_git_pass(git_reference_resolve(&resolved_ref, reference)); + cl_assert(git_reference_type(resolved_ref) == GIT_REF_OID); + + cl_git_pass(git_object_lookup(&object, g_repo, git_reference_target(resolved_ref), GIT_OBJ_ANY)); + cl_assert(object != NULL); + cl_assert(git_object_type(object) == GIT_OBJ_COMMIT); + + git_oid_fromstr(&id, current_master_tip); + cl_assert(git_oid_cmp(&id, git_object_id(object)) == 0); + + git_object_free(object); + + git_reference_free(reference); + git_reference_free(resolved_ref); +} + +void test_refs_read__nested_symbolic(void) +{ + // lookup a nested symbolic reference + git_reference *reference, *resolved_ref; + git_object *object; + git_oid id; + + cl_git_pass(git_reference_lookup(&reference, g_repo, head_tracker_sym_ref_name)); + cl_assert(git_reference_type(reference) & GIT_REF_SYMBOLIC); + cl_assert(reference_is_packed(reference) == 0); + cl_assert_equal_s(reference->name, head_tracker_sym_ref_name); + + cl_git_pass(git_reference_resolve(&resolved_ref, reference)); + cl_assert(git_reference_type(resolved_ref) == GIT_REF_OID); + + cl_git_pass(git_object_lookup(&object, g_repo, git_reference_target(resolved_ref), GIT_OBJ_ANY)); + cl_assert(object != NULL); + cl_assert(git_object_type(object) == GIT_OBJ_COMMIT); + + git_oid_fromstr(&id, current_master_tip); + cl_assert(git_oid_cmp(&id, git_object_id(object)) == 0); + + git_object_free(object); + + git_reference_free(reference); + git_reference_free(resolved_ref); +} + +void test_refs_read__head_then_master(void) +{ + // lookup the HEAD and resolve the master branch + git_reference *reference, *resolved_ref, *comp_base_ref; + + cl_git_pass(git_reference_lookup(&reference, g_repo, head_tracker_sym_ref_name)); + cl_git_pass(git_reference_resolve(&comp_base_ref, reference)); + git_reference_free(reference); + + cl_git_pass(git_reference_lookup(&reference, g_repo, GIT_HEAD_FILE)); + cl_git_pass(git_reference_resolve(&resolved_ref, reference)); + cl_git_pass(git_oid_cmp(git_reference_target(comp_base_ref), git_reference_target(resolved_ref))); + git_reference_free(reference); + git_reference_free(resolved_ref); + + cl_git_pass(git_reference_lookup(&reference, g_repo, current_head_target)); + cl_git_pass(git_reference_resolve(&resolved_ref, reference)); + cl_git_pass(git_oid_cmp(git_reference_target(comp_base_ref), git_reference_target(resolved_ref))); + git_reference_free(reference); + git_reference_free(resolved_ref); + + git_reference_free(comp_base_ref); +} + +void test_refs_read__master_then_head(void) +{ + // lookup the master branch and then the HEAD + git_reference *reference, *master_ref, *resolved_ref; + + cl_git_pass(git_reference_lookup(&master_ref, g_repo, current_head_target)); + cl_git_pass(git_reference_lookup(&reference, g_repo, GIT_HEAD_FILE)); + + cl_git_pass(git_reference_resolve(&resolved_ref, reference)); + cl_git_pass(git_oid_cmp(git_reference_target(master_ref), git_reference_target(resolved_ref))); + + git_reference_free(reference); + git_reference_free(resolved_ref); + git_reference_free(master_ref); +} + + +void test_refs_read__packed(void) +{ + // lookup a packed reference + git_reference *reference; + git_object *object; + + cl_git_pass(git_reference_lookup(&reference, g_repo, packed_head_name)); + cl_assert(git_reference_type(reference) & GIT_REF_OID); + cl_assert(reference_is_packed(reference)); + cl_assert_equal_s(reference->name, packed_head_name); + + cl_git_pass(git_object_lookup(&object, g_repo, git_reference_target(reference), GIT_OBJ_ANY)); + cl_assert(object != NULL); + cl_assert(git_object_type(object) == GIT_OBJ_COMMIT); + + git_object_free(object); + + git_reference_free(reference); +} + +void test_refs_read__loose_first(void) +{ + // assure that a loose reference is looked up before a packed reference + git_reference *reference; + + cl_git_pass(git_reference_lookup(&reference, g_repo, packed_head_name)); + git_reference_free(reference); + cl_git_pass(git_reference_lookup(&reference, g_repo, packed_test_head_name)); + cl_assert(git_reference_type(reference) & GIT_REF_OID); + cl_assert(reference_is_packed(reference) == 0); + cl_assert_equal_s(reference->name, packed_test_head_name); + + git_reference_free(reference); +} + +void test_refs_read__chomped(void) +{ + git_reference *test, *chomped; + + cl_git_pass(git_reference_lookup(&test, g_repo, "refs/heads/test")); + cl_git_pass(git_reference_lookup(&chomped, g_repo, "refs/heads/chomped")); + cl_git_pass(git_oid_cmp(git_reference_target(test), git_reference_target(chomped))); + + git_reference_free(test); + git_reference_free(chomped); +} + +void test_refs_read__trailing(void) +{ + git_reference *test, *trailing; + + cl_git_pass(git_reference_lookup(&test, g_repo, "refs/heads/test")); + cl_git_pass(git_reference_lookup(&trailing, g_repo, "refs/heads/trailing")); + cl_git_pass(git_oid_cmp(git_reference_target(test), git_reference_target(trailing))); + git_reference_free(trailing); + cl_git_pass(git_reference_lookup(&trailing, g_repo, "FETCH_HEAD")); + + git_reference_free(test); + git_reference_free(trailing); +} + +void test_refs_read__unfound_return_ENOTFOUND(void) +{ + git_reference *reference; + git_oid id; + + cl_assert_equal_i(GIT_ENOTFOUND, + git_reference_lookup(&reference, g_repo, "TEST_MASTER")); + cl_assert_equal_i(GIT_ENOTFOUND, + git_reference_lookup(&reference, g_repo, "refs/test/master")); + cl_assert_equal_i(GIT_ENOTFOUND, + git_reference_lookup(&reference, g_repo, "refs/tags/test/master")); + cl_assert_equal_i(GIT_ENOTFOUND, + git_reference_lookup(&reference, g_repo, "refs/tags/test/farther/master")); + + cl_assert_equal_i(GIT_ENOTFOUND, + git_reference_name_to_id(&id, g_repo, "refs/tags/test/farther/master")); +} + +static void assert_is_branch(const char *name, bool expected_branchness) +{ + git_reference *reference; + cl_git_pass(git_reference_lookup(&reference, g_repo, name)); + cl_assert_equal_i(expected_branchness, git_reference_is_branch(reference)); + git_reference_free(reference); +} + +void test_refs_read__can_determine_if_a_reference_is_a_local_branch(void) +{ + assert_is_branch("refs/heads/master", true); + assert_is_branch("refs/heads/packed", true); + assert_is_branch("refs/remotes/test/master", false); + assert_is_branch("refs/tags/e90810b", false); +} + +static void assert_is_tag(const char *name, bool expected_tagness) +{ + git_reference *reference; + cl_git_pass(git_reference_lookup(&reference, g_repo, name)); + cl_assert_equal_i(expected_tagness, git_reference_is_tag(reference)); + git_reference_free(reference); +} + +void test_refs_read__can_determine_if_a_reference_is_a_tag(void) +{ + assert_is_tag("refs/tags/e90810b", true); + assert_is_tag("refs/tags/test", true); + assert_is_tag("refs/heads/packed", false); + assert_is_tag("refs/remotes/test/master", false); +} + +void test_refs_read__invalid_name_returns_EINVALIDSPEC(void) +{ + git_reference *reference; + git_oid id; + + cl_assert_equal_i(GIT_EINVALIDSPEC, + git_reference_lookup(&reference, g_repo, "refs/heads/Inv@{id")); + + cl_assert_equal_i(GIT_EINVALIDSPEC, + git_reference_name_to_id(&id, g_repo, "refs/heads/Inv@{id")); +} diff --git a/tests/refs/ref_helpers.c b/tests/refs/ref_helpers.c new file mode 100644 index 000000000..7676e65a7 --- /dev/null +++ b/tests/refs/ref_helpers.c @@ -0,0 +1,25 @@ +#include "git2/repository.h" +#include "git2/refs.h" +#include "common.h" +#include "util.h" +#include "buffer.h" +#include "path.h" + +int reference_is_packed(git_reference *ref) +{ + git_buf ref_path = GIT_BUF_INIT; + int packed; + + assert(ref); + + if (git_buf_joinpath(&ref_path, + git_repository_path(git_reference_owner(ref)), + git_reference_name(ref)) < 0) + return -1; + + packed = !git_path_isfile(ref_path.ptr); + + git_buf_free(&ref_path); + + return packed; +} diff --git a/tests/refs/ref_helpers.h b/tests/refs/ref_helpers.h new file mode 100644 index 000000000..0ef55bfce --- /dev/null +++ b/tests/refs/ref_helpers.h @@ -0,0 +1 @@ +int reference_is_packed(git_reference *ref); diff --git a/tests/refs/reflog/drop.c b/tests/refs/reflog/drop.c new file mode 100644 index 000000000..916bd9933 --- /dev/null +++ b/tests/refs/reflog/drop.c @@ -0,0 +1,115 @@ +#include "clar_libgit2.h" + +#include "reflog.h" + +static git_repository *g_repo; +static git_reflog *g_reflog; +static size_t entrycount; + +void test_refs_reflog_drop__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); + + git_reflog_read(&g_reflog, g_repo, "HEAD"); + entrycount = git_reflog_entrycount(g_reflog); +} + +void test_refs_reflog_drop__cleanup(void) +{ + git_reflog_free(g_reflog); + g_reflog = NULL; + + cl_git_sandbox_cleanup(); +} + +void test_refs_reflog_drop__dropping_a_non_exisiting_entry_from_the_log_returns_ENOTFOUND(void) +{ + cl_assert_equal_i(GIT_ENOTFOUND, git_reflog_drop(g_reflog, entrycount, 0)); + + cl_assert_equal_sz(entrycount, git_reflog_entrycount(g_reflog)); +} + +void test_refs_reflog_drop__can_drop_an_entry(void) +{ + cl_assert(entrycount > 4); + + cl_git_pass(git_reflog_drop(g_reflog, 2, 0)); + cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); +} + +void test_refs_reflog_drop__can_drop_an_entry_and_rewrite_the_log_history(void) +{ + const git_reflog_entry *before_current; + const git_reflog_entry *after_current; + git_oid before_current_old_oid, before_current_cur_oid; + + cl_assert(entrycount > 4); + + before_current = git_reflog_entry_byindex(g_reflog, 1); + + git_oid_cpy(&before_current_old_oid, &before_current->oid_old); + git_oid_cpy(&before_current_cur_oid, &before_current->oid_cur); + + cl_git_pass(git_reflog_drop(g_reflog, 1, 1)); + + cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); + + after_current = git_reflog_entry_byindex(g_reflog, 0); + + cl_assert_equal_i(0, git_oid_cmp(&before_current_old_oid, &after_current->oid_old)); + cl_assert(0 != git_oid_cmp(&before_current_cur_oid, &after_current->oid_cur)); +} + +void test_refs_reflog_drop__can_drop_the_oldest_entry(void) +{ + const git_reflog_entry *entry; + + cl_assert(entrycount > 2); + + cl_git_pass(git_reflog_drop(g_reflog, entrycount - 1, 0)); + cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); + + entry = git_reflog_entry_byindex(g_reflog, entrycount - 2); + cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) != 0); +} + +void test_refs_reflog_drop__can_drop_the_oldest_entry_and_rewrite_the_log_history(void) +{ + const git_reflog_entry *entry; + + cl_assert(entrycount > 2); + + cl_git_pass(git_reflog_drop(g_reflog, entrycount - 1, 1)); + cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); + + entry = git_reflog_entry_byindex(g_reflog, entrycount - 2); + cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) == 0); +} + +void test_refs_reflog_drop__can_drop_all_the_entries(void) +{ + cl_assert(--entrycount > 0); + + do { + cl_git_pass(git_reflog_drop(g_reflog, 0, 1)); + } while (--entrycount > 0); + + cl_git_pass(git_reflog_drop(g_reflog, 0, 1)); + + cl_assert_equal_i(0, (int)git_reflog_entrycount(g_reflog)); +} + +void test_refs_reflog_drop__can_persist_deletion_on_disk(void) +{ + cl_assert(entrycount > 2); + + cl_git_pass(git_reflog_drop(g_reflog, 0, 1)); + cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); + cl_git_pass(git_reflog_write(g_reflog)); + + git_reflog_free(g_reflog); + + git_reflog_read(&g_reflog, g_repo, "HEAD"); + + cl_assert_equal_sz(entrycount - 1, git_reflog_entrycount(g_reflog)); +} diff --git a/tests/refs/reflog/reflog.c b/tests/refs/reflog/reflog.c new file mode 100644 index 000000000..bcd224270 --- /dev/null +++ b/tests/refs/reflog/reflog.c @@ -0,0 +1,209 @@ +#include "clar_libgit2.h" + +#include "fileops.h" +#include "git2/reflog.h" +#include "reflog.h" + + +static const char *new_ref = "refs/heads/test-reflog"; +static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"; +#define commit_msg "commit: bla bla" + +static git_repository *g_repo; + + +// helpers +static void assert_signature(const git_signature *expected, const git_signature *actual) +{ + cl_assert(actual); + cl_assert_equal_s(expected->name, actual->name); + cl_assert_equal_s(expected->email, actual->email); + cl_assert(expected->when.offset == actual->when.offset); + cl_assert(expected->when.time == actual->when.time); +} + + +// Fixture setup and teardown +void test_refs_reflog_reflog__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); +} + +void test_refs_reflog_reflog__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void assert_appends(const git_signature *committer, const git_oid *oid) +{ + git_repository *repo2; + git_reference *lookedup_ref; + git_reflog *reflog; + const git_reflog_entry *entry; + + /* Reopen a new instance of the repository */ + cl_git_pass(git_repository_open(&repo2, "testrepo.git")); + + /* Lookup the previously created branch */ + cl_git_pass(git_reference_lookup(&lookedup_ref, repo2, new_ref)); + + /* Read and parse the reflog for this branch */ + cl_git_pass(git_reflog_read(&reflog, repo2, new_ref)); + cl_assert_equal_i(2, (int)git_reflog_entrycount(reflog)); + + entry = git_reflog_entry_byindex(reflog, 1); + assert_signature(committer, entry->committer); + cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) == 0); + cl_assert(git_oid_cmp(oid, &entry->oid_cur) == 0); + cl_assert(entry->msg == NULL); + + entry = git_reflog_entry_byindex(reflog, 0); + assert_signature(committer, entry->committer); + cl_assert(git_oid_cmp(oid, &entry->oid_old) == 0); + cl_assert(git_oid_cmp(oid, &entry->oid_cur) == 0); + cl_assert_equal_s(commit_msg, entry->msg); + + git_reflog_free(reflog); + git_repository_free(repo2); + + git_reference_free(lookedup_ref); +} + +void test_refs_reflog_reflog__append_then_read(void) +{ + /* write a reflog for a given reference and ensure it can be read back */ + git_reference *ref; + git_oid oid; + git_signature *committer; + git_reflog *reflog; + + /* Create a new branch pointing at the HEAD */ + git_oid_fromstr(&oid, current_master_tip); + cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &oid, 0)); + git_reference_free(ref); + + cl_git_pass(git_signature_now(&committer, "foo", "foo@bar")); + + cl_git_pass(git_reflog_read(&reflog, g_repo, new_ref)); + + cl_git_fail(git_reflog_append(reflog, &oid, committer, "no inner\nnewline")); + cl_git_pass(git_reflog_append(reflog, &oid, committer, NULL)); + cl_git_pass(git_reflog_append(reflog, &oid, committer, commit_msg "\n")); + cl_git_pass(git_reflog_write(reflog)); + git_reflog_free(reflog); + + assert_appends(committer, &oid); + + git_signature_free(committer); +} + +void test_refs_reflog_reflog__append_to_then_read(void) +{ + /* write a reflog for a given reference and ensure it can be read back */ + git_reference *ref; + git_oid oid; + git_signature *committer; + + /* Create a new branch pointing at the HEAD */ + git_oid_fromstr(&oid, current_master_tip); + cl_git_pass(git_reference_create(&ref, g_repo, new_ref, &oid, 0)); + git_reference_free(ref); + + cl_git_pass(git_signature_now(&committer, "foo", "foo@bar")); + + cl_git_fail(git_reflog_append_to(g_repo, new_ref, &oid, committer, "no inner\nnewline")); + cl_git_pass(git_reflog_append_to(g_repo, new_ref, &oid, committer, NULL)); + cl_git_pass(git_reflog_append_to(g_repo, new_ref, &oid, committer, commit_msg "\n")); + + assert_appends(committer, &oid); + + git_signature_free(committer); +} + +void test_refs_reflog_reflog__renaming_the_reference_moves_the_reflog(void) +{ + git_reference *master, *new_master; + git_buf master_log_path = GIT_BUF_INIT, moved_log_path = GIT_BUF_INIT; + + git_buf_joinpath(&master_log_path, git_repository_path(g_repo), GIT_REFLOG_DIR); + git_buf_puts(&moved_log_path, git_buf_cstr(&master_log_path)); + git_buf_joinpath(&master_log_path, git_buf_cstr(&master_log_path), "refs/heads/master"); + git_buf_joinpath(&moved_log_path, git_buf_cstr(&moved_log_path), "refs/moved"); + + cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&master_log_path))); + cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&moved_log_path))); + + cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master")); + cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0)); + git_reference_free(master); + + cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&master_log_path))); + cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&moved_log_path))); + + git_reference_free(new_master); + git_buf_free(&moved_log_path); + git_buf_free(&master_log_path); +} + +static void assert_has_reflog(bool expected_result, const char *name) +{ + git_reference *ref; + + cl_git_pass(git_reference_lookup(&ref, g_repo, name)); + + cl_assert_equal_i(expected_result, git_reference_has_log(ref)); + + git_reference_free(ref); +} + +void test_refs_reflog_reflog__reference_has_reflog(void) +{ + assert_has_reflog(true, "HEAD"); + assert_has_reflog(true, "refs/heads/master"); + assert_has_reflog(false, "refs/heads/subtrees"); +} + +void test_refs_reflog_reflog__reading_the_reflog_from_a_reference_with_no_log_returns_an_empty_one(void) +{ + git_reflog *reflog; + const char *refname = "refs/heads/subtrees"; + git_buf subtrees_log_path = GIT_BUF_INIT; + + git_buf_join_n(&subtrees_log_path, '/', 3, git_repository_path(g_repo), GIT_REFLOG_DIR, refname); + cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&subtrees_log_path))); + + cl_git_pass(git_reflog_read(&reflog, g_repo, refname)); + + cl_assert_equal_i(0, (int)git_reflog_entrycount(reflog)); + + git_reflog_free(reflog); + git_buf_free(&subtrees_log_path); +} + +void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void) +{ + git_reference *master, *new_master; + git_buf master_log_path = GIT_BUF_INIT, moved_log_path = GIT_BUF_INIT; + git_reflog *reflog; + + cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master")); + cl_git_pass(git_reflog_read(&reflog, g_repo, "refs/heads/master")); + + cl_git_pass(git_reflog_write(reflog)); + + cl_git_pass(git_reference_rename(&new_master, master, "refs/moved", 0)); + git_reference_free(master); + + cl_git_fail(git_reflog_write(reflog)); + + git_reflog_free(reflog); + git_reference_free(new_master); + git_buf_free(&moved_log_path); + git_buf_free(&master_log_path); +} + +void test_refs_reflog_reflog__renaming_with_an_invalid_name_returns_EINVALIDSPEC(void) +{ + cl_assert_equal_i(GIT_EINVALIDSPEC, + git_reflog_rename(g_repo, "refs/heads/master", "refs/heads/Inv@{id")); +} diff --git a/tests/refs/rename.c b/tests/refs/rename.c new file mode 100644 index 000000000..543bc4d62 --- /dev/null +++ b/tests/refs/rename.c @@ -0,0 +1,367 @@ +#include "clar_libgit2.h" + +#include "fileops.h" +#include "git2/reflog.h" +#include "reflog.h" +#include "refs.h" +#include "ref_helpers.h" + +static const char *loose_tag_ref_name = "refs/tags/e90810b"; +static const char *packed_head_name = "refs/heads/packed"; +static const char *packed_test_head_name = "refs/heads/packed-test"; +static const char *ref_one_name = "refs/heads/one/branch"; +static const char *ref_one_name_new = "refs/heads/two/branch"; +static const char *ref_two_name = "refs/heads/two"; +static const char *ref_master_name = "refs/heads/master"; +static const char *ref_two_name_new = "refs/heads/two/two"; + +static git_repository *g_repo; + + + +void test_refs_rename__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_refs_rename__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + + + +void test_refs_rename__loose(void) +{ + // rename a loose reference + git_reference *looked_up_ref, *new_ref, *another_looked_up_ref; + git_buf temp_path = GIT_BUF_INIT; + const char *new_name = "refs/tags/Nemo/knows/refs.kung-fu"; + + /* Ensure the ref doesn't exist on the file system */ + cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), new_name)); + cl_assert(!git_path_exists(temp_path.ptr)); + + /* Retrieval of the reference to rename */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, loose_tag_ref_name)); + + /* ... which is indeed loose */ + cl_assert(reference_is_packed(looked_up_ref) == 0); + + /* Now that the reference is renamed... */ + cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, new_name, 0)); + cl_assert_equal_s(new_ref->name, new_name); + git_reference_free(looked_up_ref); + + /* ...It can't be looked-up with the old name... */ + cl_git_fail(git_reference_lookup(&another_looked_up_ref, g_repo, loose_tag_ref_name)); + + /* ...but the new name works ok... */ + cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, new_name)); + cl_assert_equal_s(new_ref->name, new_name); + + /* .. the new ref is loose... */ + cl_assert(reference_is_packed(another_looked_up_ref) == 0); + cl_assert(reference_is_packed(new_ref) == 0); + + /* ...and the ref can be found in the file system */ + cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), new_name)); + cl_assert(git_path_exists(temp_path.ptr)); + + git_reference_free(new_ref); + git_reference_free(another_looked_up_ref); + git_buf_free(&temp_path); +} + +void test_refs_rename__packed(void) +{ + // rename a packed reference (should make it loose) + git_reference *looked_up_ref, *new_ref, *another_looked_up_ref; + git_buf temp_path = GIT_BUF_INIT; + const char *brand_new_name = "refs/heads/brand_new_name"; + + /* Ensure the ref doesn't exist on the file system */ + cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), packed_head_name)); + cl_assert(!git_path_exists(temp_path.ptr)); + + /* The reference can however be looked-up... */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name)); + + /* .. and it's packed */ + cl_assert(reference_is_packed(looked_up_ref) != 0); + + /* Now that the reference is renamed... */ + cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, brand_new_name, 0)); + cl_assert_equal_s(new_ref->name, brand_new_name); + git_reference_free(looked_up_ref); + + /* ...It can't be looked-up with the old name... */ + cl_git_fail(git_reference_lookup(&another_looked_up_ref, g_repo, packed_head_name)); + + /* ...but the new name works ok... */ + cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, brand_new_name)); + cl_assert_equal_s(another_looked_up_ref->name, brand_new_name); + + /* .. the ref is no longer packed... */ + cl_assert(reference_is_packed(another_looked_up_ref) == 0); + cl_assert(reference_is_packed(new_ref) == 0); + + /* ...and the ref now happily lives in the file system */ + cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), brand_new_name)); + cl_assert(git_path_exists(temp_path.ptr)); + + git_reference_free(new_ref); + git_reference_free(another_looked_up_ref); + git_buf_free(&temp_path); +} + +void test_refs_rename__packed_doesnt_pack_others(void) +{ + // renaming a packed reference does not pack another reference which happens to be in both loose and pack state + git_reference *looked_up_ref, *another_looked_up_ref, *renamed_ref; + git_buf temp_path = GIT_BUF_INIT; + const char *brand_new_name = "refs/heads/brand_new_name"; + + /* Ensure the other reference exists on the file system */ + cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), packed_test_head_name)); + cl_assert(git_path_exists(temp_path.ptr)); + + /* Lookup the other reference */ + cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name)); + + /* Ensure it's loose */ + cl_assert(reference_is_packed(another_looked_up_ref) == 0); + git_reference_free(another_looked_up_ref); + + /* Lookup the reference to rename */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name)); + + /* Ensure it's packed */ + cl_assert(reference_is_packed(looked_up_ref) != 0); + + /* Now that the reference is renamed... */ + cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, brand_new_name, 0)); + git_reference_free(looked_up_ref); + + /* Lookup the other reference */ + cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name)); + + /* Ensure it's loose */ + cl_assert(reference_is_packed(another_looked_up_ref) == 0); + + /* Ensure the other ref still exists on the file system */ + cl_assert(git_path_exists(temp_path.ptr)); + + git_reference_free(renamed_ref); + git_reference_free(another_looked_up_ref); + git_buf_free(&temp_path); +} + +void test_refs_rename__name_collision(void) +{ + // can not rename a reference with the name of an existing reference + git_reference *looked_up_ref, *renamed_ref; + + /* An existing reference... */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name)); + + /* Can not be renamed to the name of another existing reference. */ + cl_git_fail(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 0)); + git_reference_free(looked_up_ref); + + /* Failure to rename it hasn't corrupted its state */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name)); + cl_assert_equal_s(looked_up_ref->name, packed_head_name); + + git_reference_free(looked_up_ref); +} + +void test_refs_rename__invalid_name(void) +{ + // can not rename a reference with an invalid name + git_reference *looked_up_ref, *renamed_ref; + + /* An existing oid reference... */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name)); + + /* Can not be renamed with an invalid name. */ + cl_assert_equal_i( + GIT_EINVALIDSPEC, + git_reference_rename(&renamed_ref, looked_up_ref, "Hello! I'm a very invalid name.", 0)); + + /* Can not be renamed outside of the refs hierarchy + * unless it's ALL_CAPS_AND_UNDERSCORES. + */ + cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_rename(&renamed_ref, looked_up_ref, "i-will-sudo-you", 0)); + + /* Failure to rename it hasn't corrupted its state */ + git_reference_free(looked_up_ref); + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name)); + cl_assert_equal_s(looked_up_ref->name, packed_test_head_name); + + git_reference_free(looked_up_ref); +} + +void test_refs_rename__force_loose_packed(void) +{ + // can force-rename a packed reference with the name of an existing loose and packed reference + git_reference *looked_up_ref, *renamed_ref; + git_oid oid; + + /* An existing reference... */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name)); + git_oid_cpy(&oid, git_reference_target(looked_up_ref)); + + /* Can be force-renamed to the name of another existing reference. */ + cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 1)); + git_reference_free(looked_up_ref); + git_reference_free(renamed_ref); + + /* Check we actually renamed it */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name)); + cl_assert_equal_s(looked_up_ref->name, packed_test_head_name); + cl_assert(!git_oid_cmp(&oid, git_reference_target(looked_up_ref))); + git_reference_free(looked_up_ref); + + /* And that the previous one doesn't exist any longer */ + cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name)); +} + +void test_refs_rename__force_loose(void) +{ + // can force-rename a loose reference with the name of an existing loose reference + git_reference *looked_up_ref, *renamed_ref; + git_oid oid; + + /* An existing reference... */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/br2")); + git_oid_cpy(&oid, git_reference_target(looked_up_ref)); + + /* Can be force-renamed to the name of another existing reference. */ + cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, "refs/heads/test", 1)); + git_reference_free(looked_up_ref); + git_reference_free(renamed_ref); + + /* Check we actually renamed it */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/test")); + cl_assert_equal_s(looked_up_ref->name, "refs/heads/test"); + cl_assert(!git_oid_cmp(&oid, git_reference_target(looked_up_ref))); + git_reference_free(looked_up_ref); + + /* And that the previous one doesn't exist any longer */ + cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/br2")); + + git_reference_free(looked_up_ref); +} + + +void test_refs_rename__overwrite(void) +{ + // can not overwrite name of existing reference + git_reference *ref, *ref_one, *ref_one_new, *ref_two; + git_refdb *refdb; + git_oid id; + + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); + cl_assert(git_reference_type(ref) & GIT_REF_OID); + + git_oid_cpy(&id, git_reference_target(ref)); + + /* Create loose references */ + cl_git_pass(git_reference_create(&ref_one, g_repo, ref_one_name, &id, 0)); + cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name, &id, 0)); + + /* Pack everything */ + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + + /* Attempt to create illegal reference */ + cl_git_fail(git_reference_create(&ref_one_new, g_repo, ref_one_name_new, &id, 0)); + + /* Illegal reference couldn't be created so this is supposed to fail */ + cl_git_fail(git_reference_lookup(&ref_one_new, g_repo, ref_one_name_new)); + + git_reference_free(ref); + git_reference_free(ref_one); + git_reference_free(ref_one_new); + git_reference_free(ref_two); + git_refdb_free(refdb); +} + + +void test_refs_rename__prefix(void) +{ + // can be renamed to a new name prefixed with the old name + git_reference *ref, *ref_two, *looked_up_ref, *renamed_ref; + git_oid id; + + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); + cl_assert(git_reference_type(ref) & GIT_REF_OID); + + git_oid_cpy(&id, git_reference_target(ref)); + + /* Create loose references */ + cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name, &id, 0)); + + /* An existing reference... */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name)); + + /* Can be rename to a new name starting with the old name. */ + cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name_new, 0)); + git_reference_free(looked_up_ref); + git_reference_free(renamed_ref); + + /* Check we actually renamed it */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new)); + cl_assert_equal_s(looked_up_ref->name, ref_two_name_new); + git_reference_free(looked_up_ref); + cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name)); + + git_reference_free(ref); + git_reference_free(ref_two); + git_reference_free(looked_up_ref); +} + +void test_refs_rename__move_up(void) +{ + // can move a reference to a upper reference hierarchy + git_reference *ref, *ref_two, *looked_up_ref, *renamed_ref; + git_oid id; + + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); + cl_assert(git_reference_type(ref) & GIT_REF_OID); + + git_oid_cpy(&id, git_reference_target(ref)); + + /* Create loose references */ + cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name_new, &id, 0)); + git_reference_free(ref_two); + + /* An existing reference... */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new)); + + /* Can be renamed upward the reference tree. */ + cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name, 0)); + git_reference_free(looked_up_ref); + git_reference_free(renamed_ref); + + /* Check we actually renamed it */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name)); + cl_assert_equal_s(looked_up_ref->name, ref_two_name); + git_reference_free(looked_up_ref); + + cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new)); + git_reference_free(ref); + git_reference_free(looked_up_ref); +} + +void test_refs_rename__propagate_eexists(void) +{ + git_reference *ref, *new_ref; + + cl_git_pass(git_reference_lookup(&ref, g_repo, packed_head_name)); + + cl_assert_equal_i(GIT_EEXISTS, git_reference_rename(&new_ref, ref, packed_test_head_name, 0)); + + git_reference_free(ref); +} diff --git a/tests/refs/revparse.c b/tests/refs/revparse.c new file mode 100644 index 000000000..37d3981bb --- /dev/null +++ b/tests/refs/revparse.c @@ -0,0 +1,813 @@ +#include "clar_libgit2.h" + +#include "git2/revparse.h" +#include "buffer.h" +#include "refs.h" +#include "path.h" + +static git_repository *g_repo; +static git_object *g_obj; + +/* Helpers */ +static void test_object_and_ref_inrepo( + const char *spec, + const char *expected_oid, + const char *expected_refname, + git_repository *repo, + bool assert_reference_retrieval) +{ + char objstr[64] = {0}; + git_object *obj = NULL; + git_reference *ref = NULL; + int error; + + error = git_revparse_ext(&obj, &ref, repo, spec); + + if (expected_oid != NULL) { + cl_assert_equal_i(0, error); + git_oid_fmt(objstr, git_object_id(obj)); + cl_assert_equal_s(objstr, expected_oid); + } else + cl_assert_equal_i(GIT_ENOTFOUND, error); + + if (assert_reference_retrieval) { + if (expected_refname == NULL) + cl_assert(NULL == ref); + else + cl_assert_equal_s(expected_refname, git_reference_name(ref)); + } + + git_object_free(obj); + git_reference_free(ref); +} + +static void test_object_inrepo(const char *spec, const char *expected_oid, git_repository *repo) +{ + test_object_and_ref_inrepo(spec, expected_oid, NULL, repo, false); +} + +static void test_id_inrepo( + const char *spec, + const char *expected_left, + const char *expected_right, + git_revparse_mode_t expected_flags, + git_repository *repo) +{ + git_revspec revspec; + int error = git_revparse(&revspec, repo, spec); + + if (expected_left) { + char str[64] = {0}; + cl_assert_equal_i(0, error); + git_oid_fmt(str, git_object_id(revspec.from)); + cl_assert_equal_s(str, expected_left); + git_object_free(revspec.from); + } else { + cl_assert_equal_i(GIT_ENOTFOUND, error); + } + + if (expected_right) { + char str[64] = {0}; + git_oid_fmt(str, git_object_id(revspec.to)); + cl_assert_equal_s(str, expected_right); + git_object_free(revspec.to); + } + + if (expected_flags) + cl_assert_equal_i(expected_flags, revspec.flags); +} + +static void test_object(const char *spec, const char *expected_oid) +{ + test_object_inrepo(spec, expected_oid, g_repo); +} + +static void test_object_and_ref(const char *spec, const char *expected_oid, const char *expected_refname) +{ + test_object_and_ref_inrepo(spec, expected_oid, expected_refname, g_repo, true); +} + +static void test_rangelike(const char *rangelike, + const char *expected_left, + const char *expected_right, + git_revparse_mode_t expected_revparseflags) +{ + char objstr[64] = {0}; + git_revspec revspec; + int error; + + error = git_revparse(&revspec, g_repo, rangelike); + + if (expected_left != NULL) { + cl_assert_equal_i(0, error); + cl_assert_equal_i(revspec.flags, expected_revparseflags); + git_oid_fmt(objstr, git_object_id(revspec.from)); + cl_assert_equal_s(objstr, expected_left); + git_oid_fmt(objstr, git_object_id(revspec.to)); + cl_assert_equal_s(objstr, expected_right); + } else + cl_assert(error != 0); + + git_object_free(revspec.from); + git_object_free(revspec.to); +} + + +static void test_id( + const char *spec, + const char *expected_left, + const char *expected_right, + git_revparse_mode_t expected_flags) +{ + test_id_inrepo(spec, expected_left, expected_right, expected_flags, g_repo); +} + +void test_refs_revparse__initialize(void) +{ + cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); +} + +void test_refs_revparse__cleanup(void) +{ + git_repository_free(g_repo); +} + +void test_refs_revparse__nonexistant_object(void) +{ + test_object("this-does-not-exist", NULL); + test_object("this-does-not-exist^1", NULL); + test_object("this-does-not-exist~2", NULL); +} + +static void assert_invalid_single_spec(const char *invalid_spec) +{ + cl_assert_equal_i( + GIT_EINVALIDSPEC, git_revparse_single(&g_obj, g_repo, invalid_spec)); +} + +void test_refs_revparse__invalid_reference_name(void) +{ + assert_invalid_single_spec("this doesn't make sense"); + assert_invalid_single_spec("Inv@{id"); + assert_invalid_single_spec(""); +} + +void test_refs_revparse__shas(void) +{ + test_object("c47800c7266a2be04c571c04d5a6614691ea99bd", "c47800c7266a2be04c571c04d5a6614691ea99bd"); + test_object("c47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd"); +} + +void test_refs_revparse__head(void) +{ + test_object("HEAD", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("HEAD^0", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("HEAD~0", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("master", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); +} + +void test_refs_revparse__full_refs(void) +{ + test_object("refs/heads/master", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("refs/heads/test", "e90810b8df3e80c413d903f631643c716887138d"); + test_object("refs/tags/test", "b25fa35b38051e4ae45d4222e795f9df2e43f1d1"); +} + +void test_refs_revparse__partial_refs(void) +{ + test_object("point_to_blob", "1385f264afb75a56a5bec74243be9b367ba4ca08"); + test_object("packed-test", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045"); + test_object("br2", "a4a7dce85cf63874e984719f4fdd239f5145052f"); +} + +void test_refs_revparse__describe_output(void) +{ + test_object("blah-7-gc47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd"); + test_object("not-good", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); +} + +void test_refs_revparse__nth_parent(void) +{ + assert_invalid_single_spec("be3563a^-1"); + assert_invalid_single_spec("^"); + assert_invalid_single_spec("be3563a^{tree}^"); + assert_invalid_single_spec("point_to_blob^{blob}^"); + assert_invalid_single_spec("this doesn't make sense^1"); + + test_object("be3563a^1", "9fd738e8f7967c078dceed8190330fc8648ee56a"); + test_object("be3563a^", "9fd738e8f7967c078dceed8190330fc8648ee56a"); + test_object("be3563a^2", "c47800c7266a2be04c571c04d5a6614691ea99bd"); + test_object("be3563a^1^1", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045"); + test_object("be3563a^^", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045"); + test_object("be3563a^2^1", "5b5b025afb0b4c913b4c338a42934a3863bf3644"); + test_object("be3563a^0", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + test_object("be3563a^{commit}^", "9fd738e8f7967c078dceed8190330fc8648ee56a"); + + test_object("be3563a^42", NULL); +} + +void test_refs_revparse__not_tag(void) +{ + test_object("point_to_blob^{}", "1385f264afb75a56a5bec74243be9b367ba4ca08"); + test_object("wrapped_tag^{}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("master^{}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("master^{tree}^{}", "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"); + test_object("e90810b^{}", "e90810b8df3e80c413d903f631643c716887138d"); + test_object("tags/e90810b^{}", "e90810b8df3e80c413d903f631643c716887138d"); + test_object("e908^{}", "e90810b8df3e80c413d903f631643c716887138d"); +} + +void test_refs_revparse__to_type(void) +{ + assert_invalid_single_spec("wrapped_tag^{trip}"); + test_object("point_to_blob^{commit}", NULL); + cl_assert_equal_i( + GIT_EAMBIGUOUS, git_revparse_single(&g_obj, g_repo, "wrapped_tag^{blob}")); + + test_object("wrapped_tag^{commit}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("wrapped_tag^{tree}", "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"); + test_object("point_to_blob^{blob}", "1385f264afb75a56a5bec74243be9b367ba4ca08"); + test_object("master^{commit}^{commit}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); +} + +void test_refs_revparse__linear_history(void) +{ + assert_invalid_single_spec("~"); + test_object("foo~bar", NULL); + + assert_invalid_single_spec("master~bar"); + assert_invalid_single_spec("master~-1"); + assert_invalid_single_spec("master~0bar"); + assert_invalid_single_spec("this doesn't make sense~2"); + assert_invalid_single_spec("be3563a^{tree}~"); + assert_invalid_single_spec("point_to_blob^{blob}~"); + + test_object("master~0", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("master~1", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + test_object("master~2", "9fd738e8f7967c078dceed8190330fc8648ee56a"); + test_object("master~1~1", "9fd738e8f7967c078dceed8190330fc8648ee56a"); + test_object("master~~", "9fd738e8f7967c078dceed8190330fc8648ee56a"); +} + +void test_refs_revparse__chaining(void) +{ + assert_invalid_single_spec("master@{0}@{0}"); + assert_invalid_single_spec("@{u}@{-1}"); + assert_invalid_single_spec("@{-1}@{-1}"); + assert_invalid_single_spec("@{-3}@{0}"); + + test_object("master@{0}~1^1", "9fd738e8f7967c078dceed8190330fc8648ee56a"); + test_object("@{u}@{0}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + test_object("@{-1}@{0}", "a4a7dce85cf63874e984719f4fdd239f5145052f"); + test_object("@{-4}@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + test_object("master~1^1", "9fd738e8f7967c078dceed8190330fc8648ee56a"); + test_object("master~1^2", "c47800c7266a2be04c571c04d5a6614691ea99bd"); + test_object("master^1^2~1", "5b5b025afb0b4c913b4c338a42934a3863bf3644"); + test_object("master^^2^", "5b5b025afb0b4c913b4c338a42934a3863bf3644"); + test_object("master^1^1^1^1^1", "8496071c1b46c854b31185ea97743be6a8774479"); + test_object("master^^1^2^1", NULL); +} + +void test_refs_revparse__upstream(void) +{ + assert_invalid_single_spec("e90810b@{u}"); + assert_invalid_single_spec("refs/tags/e90810b@{u}"); + test_object("refs/heads/e90810b@{u}", NULL); + + test_object("master@{upstream}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + test_object("@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + test_object("master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + test_object("heads/master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + test_object("refs/heads/master@{u}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); +} + +void test_refs_revparse__ordinal(void) +{ + assert_invalid_single_spec("master@{-2}"); + + /* TODO: make the test below actually fail + * cl_git_fail(git_revparse_single(&g_obj, g_repo, "master@{1a}")); + */ + + test_object("nope@{0}", NULL); + test_object("master@{31415}", NULL); + test_object("@{1000}", NULL); + test_object("@{2}", NULL); + + test_object("@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + + test_object("master@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("master@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + test_object("heads/master@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + test_object("refs/heads/master@{1}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); +} + +void test_refs_revparse__previous_head(void) +{ + assert_invalid_single_spec("@{-xyz}"); + assert_invalid_single_spec("@{-0}"); + assert_invalid_single_spec("@{-1b}"); + + test_object("@{-42}", NULL); + + test_object("@{-2}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("@{-1}", "a4a7dce85cf63874e984719f4fdd239f5145052f"); +} + +static void create_fake_stash_reference_and_reflog(git_repository *repo) +{ + git_reference *master, *new_master; + git_buf log_path = GIT_BUF_INIT; + + git_buf_joinpath(&log_path, git_repository_path(repo), "logs/refs/fakestash"); + + cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&log_path))); + + cl_git_pass(git_reference_lookup(&master, repo, "refs/heads/master")); + cl_git_pass(git_reference_rename(&new_master, master, "refs/fakestash", 0)); + git_reference_free(master); + + cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&log_path))); + + git_buf_free(&log_path); + git_reference_free(new_master); +} + +void test_refs_revparse__reflog_of_a_ref_under_refs(void) +{ + git_repository *repo = cl_git_sandbox_init("testrepo.git"); + + test_object_inrepo("refs/fakestash", NULL, repo); + + create_fake_stash_reference_and_reflog(repo); + + /* + * $ git reflog -1 refs/fakestash + * a65fedf refs/fakestash@{0}: commit: checking in + * + * $ git reflog -1 refs/fakestash@{0} + * a65fedf refs/fakestash@{0}: commit: checking in + * + * $ git reflog -1 fakestash + * a65fedf fakestash@{0}: commit: checking in + * + * $ git reflog -1 fakestash@{0} + * a65fedf fakestash@{0}: commit: checking in + */ + test_object_inrepo("refs/fakestash", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); + test_object_inrepo("refs/fakestash@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); + test_object_inrepo("fakestash", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); + test_object_inrepo("fakestash@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); + + cl_git_sandbox_cleanup(); +} + +void test_refs_revparse__revwalk(void) +{ + test_object("master^{/not found in any commit}", NULL); + test_object("master^{/merge}", NULL); + assert_invalid_single_spec("master^{/((}"); + + test_object("master^{/anoth}", "5b5b025afb0b4c913b4c338a42934a3863bf3644"); + test_object("master^{/Merge}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + test_object("br2^{/Merge}", "a4a7dce85cf63874e984719f4fdd239f5145052f"); + test_object("master^{/fo.rth}", "9fd738e8f7967c078dceed8190330fc8648ee56a"); +} + +void test_refs_revparse__date(void) +{ + /* + * $ git reflog HEAD --date=iso + * a65fedf HEAD@{2012-04-30 08:23:41 -0900}: checkout: moving from br2 to master + * a4a7dce HEAD@{2012-04-30 08:23:37 -0900}: commit: checking in + * c47800c HEAD@{2012-04-30 08:23:28 -0900}: checkout: moving from master to br2 + * a65fedf HEAD@{2012-04-30 08:23:23 -0900}: commit: + * be3563a HEAD@{2012-04-30 10:22:43 -0700}: clone: from /Users/ben/src/libgit2/tes + * + * $ git reflog HEAD --date=raw + * a65fedf HEAD@{1335806621 -0900}: checkout: moving from br2 to master + * a4a7dce HEAD@{1335806617 -0900}: commit: checking in + * c47800c HEAD@{1335806608 -0900}: checkout: moving from master to br2 + * a65fedf HEAD@{1335806603 -0900}: commit: + * be3563a HEAD@{1335806563 -0700}: clone: from /Users/ben/src/libgit2/tests/resour + */ + test_object("HEAD@{10 years ago}", NULL); + + test_object("HEAD@{1 second}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("HEAD@{1 second ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("HEAD@{2 days ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + + /* + * $ git reflog master --date=iso + * a65fedf master@{2012-04-30 09:23:23 -0800}: commit: checking in + * be3563a master@{2012-04-30 09:22:43 -0800}: clone: from /Users/ben/src... + * + * $ git reflog master --date=raw + * a65fedf master@{1335806603 -0800}: commit: checking in + * be3563a master@{1335806563 -0800}: clone: from /Users/ben/src/libgit2/tests/reso + */ + + + /* + * $ git reflog -1 "master@{2012-04-30 17:22:42 +0000}" + * warning: Log for 'master' only goes back to Mon, 30 Apr 2012 09:22:43 -0800. + */ + test_object("master@{2012-04-30 17:22:42 +0000}", NULL); + test_object("master@{2012-04-30 09:22:42 -0800}", NULL); + + /* + * $ git reflog -1 "master@{2012-04-30 17:22:43 +0000}" + * be3563a master@{Mon Apr 30 09:22:43 2012 -0800}: clone: from /Users/ben/src/libg + */ + test_object("master@{2012-04-30 17:22:43 +0000}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + test_object("master@{2012-04-30 09:22:43 -0800}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); + + /* + * $ git reflog -1 "master@{2012-4-30 09:23:27 -0800}" + * a65fedf master@{Mon Apr 30 09:23:23 2012 -0800}: commit: checking in + */ + test_object("master@{2012-4-30 09:23:27 -0800}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + + /* + * $ git reflog -1 master@{2012-05-03} + * a65fedf master@{Mon Apr 30 09:23:23 2012 -0800}: commit: checking in + */ + test_object("master@{2012-05-03}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + + /* + * $ git reflog -1 "master@{1335806603}" + * a65fedf + * + * $ git reflog -1 "master@{1335806602}" + * be3563a + */ + test_object("master@{1335806603}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + test_object("master@{1335806602}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); +} + +void test_refs_revparse__colon(void) +{ + assert_invalid_single_spec(":/"); + assert_invalid_single_spec("point_to_blob:readme.txt"); + cl_git_fail(git_revparse_single(&g_obj, g_repo, ":2:README")); /* Not implemented */ + + test_object(":/not found in any commit", NULL); + test_object("subtrees:ab/42.txt", NULL); + test_object("subtrees:ab/4.txt/nope", NULL); + test_object("subtrees:nope", NULL); + test_object("test/master^1:branch_file.txt", NULL); + + /* From tags */ + test_object("test:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf"); + test_object("tags/test:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf"); + test_object("e90810b:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf"); + test_object("tags/e90810b:readme.txt", "0266163a49e280c4f5ed1e08facd36a2bd716bcf"); + + /* From commits */ + test_object("a65f:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc"); + + /* From trees */ + test_object("a65f^{tree}:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc"); + test_object("944c:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc"); + + /* Retrieving trees */ + test_object("master:", "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"); + test_object("subtrees:", "ae90f12eea699729ed24555e40b9fd669da12a12"); + test_object("subtrees:ab", "f1425cef211cc08caa31e7b545ffb232acb098c3"); + test_object("subtrees:ab/", "f1425cef211cc08caa31e7b545ffb232acb098c3"); + + /* Retrieving blobs */ + test_object("subtrees:ab/4.txt", "d6c93164c249c8000205dd4ec5cbca1b516d487f"); + test_object("subtrees:ab/de/fgh/1.txt", "1f67fc4386b2d171e0d21be1c447e12660561f9b"); + test_object("master:README", "a8233120f6ad708f843d861ce2b7228ec4e3dec6"); + test_object("master:new.txt", "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd"); + test_object(":/Merge", "a4a7dce85cf63874e984719f4fdd239f5145052f"); + test_object(":/one", "c47800c7266a2be04c571c04d5a6614691ea99bd"); + test_object(":/packed commit t", "41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9"); + test_object("test/master^2:branch_file.txt", "45b983be36b73c0788dc9cbcb76cbb80fc7bb057"); + test_object("test/master@{1}:branch_file.txt", "3697d64be941a53d4ae8f6a271e4e3fa56b022cc"); +} + +void test_refs_revparse__disambiguation(void) +{ + /* + * $ git show e90810b + * tag e90810b + * Tagger: Vicent Marti + * Date: Thu Aug 12 03:59:17 2010 +0200 + * + * This is a very simple tag. + * + * commit e90810b8df3e80c413d903f631643c716887138d + * Author: Vicent Marti + * Date: Thu Aug 5 18:42:20 2010 +0200 + * + * Test commit 2 + * + * diff --git a/readme.txt b/readme.txt + * index 6336846..0266163 100644 + * --- a/readme.txt + * +++ b/readme.txt + * @@ -1 +1,2 @@ + * Testing a readme.txt + * +Now we add a single line here + * + * $ git show-ref e90810b + * 7b4384978d2493e851f9cca7858815fac9b10980 refs/tags/e90810b + * + */ + test_object("e90810b", "7b4384978d2493e851f9cca7858815fac9b10980"); + + /* + * $ git show e90810 + * commit e90810b8df3e80c413d903f631643c716887138d + * Author: Vicent Marti + * Date: Thu Aug 5 18:42:20 2010 +0200 + * + * Test commit 2 + * + * diff --git a/readme.txt b/readme.txt + * index 6336846..0266163 100644 + * --- a/readme.txt + * +++ b/readme.txt + * @@ -1 +1,2 @@ + * Testing a readme.txt + * +Now we add a single line here + */ + test_object("e90810", "e90810b8df3e80c413d903f631643c716887138d"); +} + +void test_refs_revparse__a_too_short_objectid_returns_EAMBIGUOUS(void) +{ + cl_assert_equal_i( + GIT_EAMBIGUOUS, git_revparse_single(&g_obj, g_repo, "e90")); +} + +/* + * $ echo "aabqhq" | git hash-object -t blob --stdin + * dea509d0b3cb8ee0650f6ca210bc83f4678851ba + * + * $ echo "aaazvc" | git hash-object -t blob --stdin + * dea509d097ce692e167dfc6a48a7a280cc5e877e + */ +void test_refs_revparse__a_not_precise_enough_objectid_returns_EAMBIGUOUS(void) +{ + git_repository *repo; + git_index *index; + git_object *obj; + + repo = cl_git_sandbox_init("testrepo"); + + cl_git_mkfile("testrepo/one.txt", "aabqhq\n"); + cl_git_mkfile("testrepo/two.txt", "aaazvc\n"); + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_bypath(index, "one.txt")); + cl_git_pass(git_index_add_bypath(index, "two.txt")); + + cl_git_fail_with(git_revparse_single(&obj, repo, "dea509d0"), GIT_EAMBIGUOUS); + + cl_git_pass(git_revparse_single(&obj, repo, "dea509d09")); + + git_object_free(obj); + git_index_free(index); + cl_git_sandbox_cleanup(); +} + +void test_refs_revparse__issue_994(void) +{ + git_repository *repo; + git_reference *head, *with_at; + git_object *target; + + repo = cl_git_sandbox_init("testrepo.git"); + + cl_assert_equal_i(GIT_ENOTFOUND, + git_revparse_single(&target, repo, "origin/bim_with_3d@11296")); + + cl_assert_equal_i(GIT_ENOTFOUND, + git_revparse_single(&target, repo, "refs/remotes/origin/bim_with_3d@11296")); + + + cl_git_pass(git_repository_head(&head, repo)); + cl_git_pass(git_reference_create( + &with_at, + repo, + "refs/remotes/origin/bim_with_3d@11296", + git_reference_target(head), + 0)); + + cl_git_pass(git_revparse_single(&target, repo, "origin/bim_with_3d@11296")); + git_object_free(target); + + cl_git_pass(git_revparse_single(&target, repo, "refs/remotes/origin/bim_with_3d@11296")); + git_object_free(target); + + git_reference_free(with_at); + git_reference_free(head); + cl_git_sandbox_cleanup(); +} + +/** + * $ git rev-parse blah-7-gc47800c + * c47800c7266a2be04c571c04d5a6614691ea99bd + * + * $ git rev-parse HEAD~3 + * 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 + * + * $ git branch blah-7-gc47800c HEAD~3 + * + * $ git rev-parse blah-7-gc47800c + * 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 + */ +void test_refs_revparse__try_to_retrieve_branch_before_described_tag(void) +{ + git_repository *repo; + git_reference *branch; + git_object *target; + char sha[GIT_OID_HEXSZ + 1]; + + repo = cl_git_sandbox_init("testrepo.git"); + + test_object_inrepo("blah-7-gc47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd", repo); + + cl_git_pass(git_revparse_single(&target, repo, "HEAD~3")); + cl_git_pass(git_branch_create(&branch, repo, "blah-7-gc47800c", (git_commit *)target, 0)); + + git_oid_tostr(sha, GIT_OID_HEXSZ + 1, git_object_id(target)); + + test_object_inrepo("blah-7-gc47800c", sha, repo); + + git_reference_free(branch); + git_object_free(target); + cl_git_sandbox_cleanup(); +} + +/** + * $ git rev-parse a65fedf39aefe402d3bb6e24df4d4f5fe4547750 + * a65fedf39aefe402d3bb6e24df4d4f5fe4547750 + * + * $ git rev-parse HEAD~3 + * 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 + * + * $ git branch a65fedf39aefe402d3bb6e24df4d4f5fe4547750 HEAD~3 + * + * $ git rev-parse a65fedf39aefe402d3bb6e24df4d4f5fe4547750 + * a65fedf39aefe402d3bb6e24df4d4f5fe4547750 + * + * $ git rev-parse heads/a65fedf39aefe402d3bb6e24df4d4f5fe4547750 + * 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 + */ +void test_refs_revparse__try_to_retrieve_sha_before_branch(void) +{ + git_repository *repo; + git_reference *branch; + git_object *target; + char sha[GIT_OID_HEXSZ + 1]; + + repo = cl_git_sandbox_init("testrepo.git"); + + test_object_inrepo("a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); + + cl_git_pass(git_revparse_single(&target, repo, "HEAD~3")); + cl_git_pass(git_branch_create(&branch, repo, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", (git_commit *)target, 0)); + + git_oid_tostr(sha, GIT_OID_HEXSZ + 1, git_object_id(target)); + + test_object_inrepo("a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); + test_object_inrepo("heads/a65fedf39aefe402d3bb6e24df4d4f5fe4547750", sha, repo); + + git_reference_free(branch); + git_object_free(target); + cl_git_sandbox_cleanup(); +} + +/** + * $ git rev-parse c47800 + * c47800c7266a2be04c571c04d5a6614691ea99bd + * + * $ git rev-parse HEAD~3 + * 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 + * + * $ git branch c47800 HEAD~3 + * + * $ git rev-parse c47800 + * 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 + */ +void test_refs_revparse__try_to_retrieve_branch_before_abbrev_sha(void) +{ + git_repository *repo; + git_reference *branch; + git_object *target; + char sha[GIT_OID_HEXSZ + 1]; + + repo = cl_git_sandbox_init("testrepo.git"); + + test_object_inrepo("c47800", "c47800c7266a2be04c571c04d5a6614691ea99bd", repo); + + cl_git_pass(git_revparse_single(&target, repo, "HEAD~3")); + cl_git_pass(git_branch_create(&branch, repo, "c47800", (git_commit *)target, 0)); + + git_oid_tostr(sha, GIT_OID_HEXSZ + 1, git_object_id(target)); + + test_object_inrepo("c47800", sha, repo); + + git_reference_free(branch); + git_object_free(target); + cl_git_sandbox_cleanup(); +} + + +void test_refs_revparse__range(void) +{ + assert_invalid_single_spec("be3563a^1..be3563a"); + + test_rangelike("be3563a^1..be3563a", + "9fd738e8f7967c078dceed8190330fc8648ee56a", + "be3563ae3f795b2b4353bcce3a527ad0a4f7f644", + GIT_REVPARSE_RANGE); + + test_rangelike("be3563a^1...be3563a", + "9fd738e8f7967c078dceed8190330fc8648ee56a", + "be3563ae3f795b2b4353bcce3a527ad0a4f7f644", + GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE); + + test_rangelike("be3563a^1.be3563a", NULL, NULL, 0); +} + +void test_refs_revparse__parses_range_operator(void) +{ + test_id("HEAD", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", NULL, GIT_REVPARSE_SINGLE); + test_id("HEAD~3..HEAD", + "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", + GIT_REVPARSE_RANGE); + + test_id("HEAD~3...HEAD", + "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", + GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE); +} + +void test_refs_revparse__ext_retrieves_both_the_reference_and_its_target(void) +{ + test_object_and_ref( + "master@{upstream}", + "be3563ae3f795b2b4353bcce3a527ad0a4f7f644", + "refs/remotes/test/master"); + + test_object_and_ref( + "@{-1}", + "a4a7dce85cf63874e984719f4fdd239f5145052f", + "refs/heads/br2"); +} + +void test_refs_revparse__ext_can_expand_short_reference_names(void) +{ + test_object_and_ref( + "master", + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", + "refs/heads/master"); + + test_object_and_ref( + "HEAD", + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", + "refs/heads/master"); + + test_object_and_ref( + "tags/test", + "b25fa35b38051e4ae45d4222e795f9df2e43f1d1", + "refs/tags/test"); +} + +void test_refs_revparse__ext_returns_NULL_reference_when_expression_points_at_a_revision(void) +{ + test_object_and_ref( + "HEAD~3", + "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", + NULL); + + test_object_and_ref( + "HEAD~0", + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", + NULL); + + test_object_and_ref( + "HEAD^0", + "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", + NULL); + + test_object_and_ref( + "@{-1}@{0}", + "a4a7dce85cf63874e984719f4fdd239f5145052f", + NULL); +} + +void test_refs_revparse__ext_returns_NULL_reference_when_expression_points_at_a_tree_content(void) +{ + test_object_and_ref( + "tags/test:readme.txt", + "0266163a49e280c4f5ed1e08facd36a2bd716bcf", + NULL); +} diff --git a/tests/refs/setter.c b/tests/refs/setter.c new file mode 100644 index 000000000..6d875f9b6 --- /dev/null +++ b/tests/refs/setter.c @@ -0,0 +1,99 @@ +#include "clar_libgit2.h" + +#include "repository.h" +#include "git2/reflog.h" +#include "reflog.h" +#include "git2/refs.h" + +static const char *ref_name = "refs/heads/other"; +static const char *ref_master_name = "refs/heads/master"; +static const char *ref_test_name = "refs/heads/test"; + +static git_repository *g_repo; + +void test_refs_setter__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_refs_setter__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_refs_setter__update_direct(void) +{ + git_reference *ref, *test_ref, *new_ref; + git_oid id; + + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); + cl_assert(git_reference_type(ref) == GIT_REF_OID); + git_oid_cpy(&id, git_reference_target(ref)); + git_reference_free(ref); + + cl_git_pass(git_reference_lookup(&test_ref, g_repo, ref_test_name)); + cl_assert(git_reference_type(test_ref) == GIT_REF_OID); + + cl_git_pass(git_reference_set_target(&new_ref, test_ref, &id)); + + git_reference_free(test_ref); + git_reference_free(new_ref); + + cl_git_pass(git_reference_lookup(&test_ref, g_repo, ref_test_name)); + cl_assert(git_reference_type(test_ref) == GIT_REF_OID); + cl_assert(git_oid_cmp(&id, git_reference_target(test_ref)) == 0); + git_reference_free(test_ref); +} + +void test_refs_setter__update_symbolic(void) +{ + git_reference *head, *new_head; + + cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); + cl_assert(git_reference_type(head) == GIT_REF_SYMBOLIC); + cl_assert(strcmp(git_reference_symbolic_target(head), ref_master_name) == 0); + + cl_git_pass(git_reference_symbolic_set_target(&new_head, head, ref_test_name)); + git_reference_free(new_head); + git_reference_free(head); + + cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); + cl_assert(git_reference_type(head) == GIT_REF_SYMBOLIC); + cl_assert(strcmp(git_reference_symbolic_target(head), ref_test_name) == 0); + git_reference_free(head); +} + +void test_refs_setter__cant_update_direct_with_symbolic(void) +{ + // Overwrite an existing object id reference with a symbolic one + git_reference *ref, *new; + git_oid id; + + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); + cl_assert(git_reference_type(ref) == GIT_REF_OID); + git_oid_cpy(&id, git_reference_target(ref)); + + cl_git_fail(git_reference_symbolic_set_target(&new, ref, ref_name)); + + git_reference_free(ref); +} + +void test_refs_setter__cant_update_symbolic_with_direct(void) +{ + // Overwrite an existing symbolic reference with an object id one + git_reference *ref, *new; + git_oid id; + + cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name)); + cl_assert(git_reference_type(ref) == GIT_REF_OID); + git_oid_cpy(&id, git_reference_target(ref)); + git_reference_free(ref); + + /* Create the symbolic ref */ + cl_git_pass(git_reference_symbolic_create(&ref, g_repo, ref_name, ref_master_name, 0)); + + /* Can't set an OID on a direct ref */ + cl_git_fail(git_reference_set_target(&new, ref, &id)); + + git_reference_free(ref); +} diff --git a/tests/refs/shorthand.c b/tests/refs/shorthand.c new file mode 100644 index 000000000..f995d26ca --- /dev/null +++ b/tests/refs/shorthand.c @@ -0,0 +1,27 @@ +#include "clar_libgit2.h" + +#include "repository.h" + +void assert_shorthand(git_repository *repo, const char *refname, const char *shorthand) +{ + git_reference *ref; + + cl_git_pass(git_reference_lookup(&ref, repo, refname)); + cl_assert_equal_s(git_reference_shorthand(ref), shorthand); + git_reference_free(ref); +} + +void test_refs_shorthand__0(void) +{ + git_repository *repo; + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + + + assert_shorthand(repo, "refs/heads/master", "master"); + assert_shorthand(repo, "refs/tags/test", "test"); + assert_shorthand(repo, "refs/remotes/test/master", "test/master"); + assert_shorthand(repo, "refs/notes/fanout", "notes/fanout"); + + git_repository_free(repo); +} diff --git a/tests/refs/unicode.c b/tests/refs/unicode.c new file mode 100644 index 000000000..b56012869 --- /dev/null +++ b/tests/refs/unicode.c @@ -0,0 +1,56 @@ +#include "clar_libgit2.h" + +static git_repository *repo; + +void test_refs_unicode__initialize(void) +{ + repo = cl_git_sandbox_init("testrepo.git"); +} + +void test_refs_unicode__cleanup(void) +{ + cl_git_sandbox_cleanup(); + repo = NULL; +} + +void test_refs_unicode__create_and_lookup(void) +{ + git_reference *ref0, *ref1, *ref2; + git_repository *repo2; + + const char *REFNAME = "refs/heads/" "\303\205" "ngstr" "\303\266" "m"; + const char *master = "refs/heads/master"; + + /* Create the reference */ + cl_git_pass(git_reference_lookup(&ref0, repo, master)); + cl_git_pass(git_reference_create( + &ref1, repo, REFNAME, git_reference_target(ref0), 0)); + cl_assert_equal_s(REFNAME, git_reference_name(ref1)); + git_reference_free(ref0); + + /* Lookup the reference in a different instance of the repository */ + cl_git_pass(git_repository_open(&repo2, "testrepo.git")); + + cl_git_pass(git_reference_lookup(&ref2, repo2, REFNAME)); + cl_assert_equal_i( + 0, git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2))); + cl_assert_equal_s(REFNAME, git_reference_name(ref2)); + git_reference_free(ref2); + +#if GIT_USE_ICONV + /* Lookup reference by decomposed unicode name */ + +#define REFNAME_DECOMPOSED "refs/heads/" "A" "\314\212" "ngstro" "\314\210" "m" + + cl_git_pass(git_reference_lookup(&ref2, repo2, REFNAME_DECOMPOSED)); + cl_assert_equal_i( + 0, git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2))); + cl_assert_equal_s(REFNAME, git_reference_name(ref2)); + git_reference_free(ref2); +#endif + + /* Cleanup */ + + git_reference_free(ref1); + git_repository_free(repo2); +} diff --git a/tests/refs/update.c b/tests/refs/update.c new file mode 100644 index 000000000..205b526a2 --- /dev/null +++ b/tests/refs/update.c @@ -0,0 +1,26 @@ +#include "clar_libgit2.h" + +#include "refs.h" + +static git_repository *g_repo; + +void test_refs_update__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); +} + +void test_refs_update__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_refs_update__updating_the_target_of_a_symref_with_an_invalid_name_returns_EINVALIDSPEC(void) +{ + git_reference *head; + + cl_git_pass(git_reference_lookup(&head, g_repo, GIT_HEAD_FILE)); + cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); + git_reference_free(head); + + cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_symbolic_create(&head, g_repo, GIT_HEAD_FILE, "refs/heads/inv@{id", 1)); +} diff --git a/tests/repo/config.c b/tests/repo/config.c new file mode 100644 index 000000000..e77acc8c5 --- /dev/null +++ b/tests/repo/config.c @@ -0,0 +1,208 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include + +static git_buf path = GIT_BUF_INIT; + +void test_repo_config__initialize(void) +{ + cl_fixture_sandbox("empty_standard_repo"); + cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git")); + + git_buf_clear(&path); + + cl_must_pass(p_mkdir("alternate", 0777)); + cl_git_pass(git_path_prettify(&path, "alternate", NULL)); +} + +void test_repo_config__cleanup(void) +{ + cl_git_pass(git_path_prettify(&path, "alternate", NULL)); + cl_git_pass(git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)); + git_buf_free(&path); + cl_assert(!git_path_isdir("alternate")); + + cl_fixture_cleanup("empty_standard_repo"); +} + +void test_repo_config__open_missing_global(void) +{ + git_repository *repo; + git_config *config, *global; + + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_config_open_level(&global, config, GIT_CONFIG_LEVEL_GLOBAL)); + + cl_git_pass(git_config_set_string(global, "test.set", "42")); + + git_config_free(global); + git_config_free(config); + git_repository_free(repo); + + git_futils_dirs_global_shutdown(); +} + +void test_repo_config__open_missing_global_with_separators(void) +{ + git_repository *repo; + git_config *config, *global; + + cl_git_pass(git_buf_printf(&path, "%c%s", GIT_PATH_LIST_SEPARATOR, "dummy")); + + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); + + git_buf_free(&path); + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + cl_git_pass(git_repository_config(&config, repo)); + cl_git_pass(git_config_open_level(&global, config, GIT_CONFIG_LEVEL_GLOBAL)); + + cl_git_pass(git_config_set_string(global, "test.set", "42")); + + git_config_free(global); + git_config_free(config); + git_repository_free(repo); + + git_futils_dirs_global_shutdown(); +} + +#include "repository.h" + +void test_repo_config__read_no_configs(void) +{ + git_repository *repo; + int val; + + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); + + /* with none */ + + cl_must_pass(p_unlink("empty_standard_repo/.git/config")); + cl_assert(!git_path_isfile("empty_standard_repo/.git/config")); + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + git_repository__cvar_cache_clear(repo); + val = -1; + cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_assert_equal_i(GIT_ABBREV_DEFAULT, val); + git_repository_free(repo); + + git_futils_dirs_global_shutdown(); + + /* with just system */ + + cl_must_pass(p_mkdir("alternate/1", 0777)); + cl_git_pass(git_buf_joinpath(&path, path.ptr, "1")); + cl_git_rewritefile("alternate/1/gitconfig", "[core]\n\tabbrev = 10\n"); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + git_repository__cvar_cache_clear(repo); + val = -1; + cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_assert_equal_i(10, val); + git_repository_free(repo); + + /* with xdg + system */ + + cl_must_pass(p_mkdir("alternate/2", 0777)); + path.ptr[path.size - 1] = '2'; + cl_git_rewritefile("alternate/2/config", "[core]\n\tabbrev = 20\n"); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + git_repository__cvar_cache_clear(repo); + val = -1; + cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_assert_equal_i(20, val); + git_repository_free(repo); + + /* with global + xdg + system */ + + cl_must_pass(p_mkdir("alternate/3", 0777)); + path.ptr[path.size - 1] = '3'; + cl_git_rewritefile("alternate/3/.gitconfig", "[core]\n\tabbrev = 30\n"); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + git_repository__cvar_cache_clear(repo); + val = -1; + cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_assert_equal_i(30, val); + git_repository_free(repo); + + /* with all configs */ + + cl_git_rewritefile("empty_standard_repo/.git/config", "[core]\n\tabbrev = 40\n"); + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + git_repository__cvar_cache_clear(repo); + val = -1; + cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_assert_equal_i(40, val); + git_repository_free(repo); + + /* with all configs but delete the files ? */ + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + git_repository__cvar_cache_clear(repo); + val = -1; + cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_assert_equal_i(40, val); + + cl_must_pass(p_unlink("empty_standard_repo/.git/config")); + cl_assert(!git_path_isfile("empty_standard_repo/.git/config")); + + cl_must_pass(p_unlink("alternate/1/gitconfig")); + cl_assert(!git_path_isfile("alternate/1/gitconfig")); + + cl_must_pass(p_unlink("alternate/2/config")); + cl_assert(!git_path_isfile("alternate/2/config")); + + cl_must_pass(p_unlink("alternate/3/.gitconfig")); + cl_assert(!git_path_isfile("alternate/3/.gitconfig")); + + git_repository__cvar_cache_clear(repo); + val = -1; + cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_assert_equal_i(40, val); + git_repository_free(repo); + + /* reopen */ + + cl_assert(!git_path_isfile("empty_standard_repo/.git/config")); + cl_assert(!git_path_isfile("alternate/3/.gitconfig")); + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + git_repository__cvar_cache_clear(repo); + val = -1; + cl_git_pass(git_repository__cvar(&val, repo, GIT_CVAR_ABBREV)); + cl_assert_equal_i(7, val); + git_repository_free(repo); + + cl_assert(!git_path_exists("empty_standard_repo/.git/config")); + cl_assert(!git_path_exists("alternate/3/.gitconfig")); + + git_futils_dirs_global_shutdown(); +} diff --git a/tests/repo/discover.c b/tests/repo/discover.c new file mode 100644 index 000000000..f93ff2462 --- /dev/null +++ b/tests/repo/discover.c @@ -0,0 +1,142 @@ +#include "clar_libgit2.h" + +#include "odb.h" +#include "fileops.h" +#include "repository.h" + +#define TEMP_REPO_FOLDER "temprepo/" +#define DISCOVER_FOLDER TEMP_REPO_FOLDER "discover.git" + +#define SUB_REPOSITORY_FOLDER_NAME "sub_repo" +#define SUB_REPOSITORY_FOLDER DISCOVER_FOLDER "/" SUB_REPOSITORY_FOLDER_NAME +#define SUB_REPOSITORY_FOLDER_SUB SUB_REPOSITORY_FOLDER "/sub" +#define SUB_REPOSITORY_FOLDER_SUB_SUB SUB_REPOSITORY_FOLDER_SUB "/subsub" +#define SUB_REPOSITORY_FOLDER_SUB_SUB_SUB SUB_REPOSITORY_FOLDER_SUB_SUB "/subsubsub" + +#define REPOSITORY_ALTERNATE_FOLDER DISCOVER_FOLDER "/alternate_sub_repo" +#define REPOSITORY_ALTERNATE_FOLDER_SUB REPOSITORY_ALTERNATE_FOLDER "/sub" +#define REPOSITORY_ALTERNATE_FOLDER_SUB_SUB REPOSITORY_ALTERNATE_FOLDER_SUB "/subsub" +#define REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/subsubsub" + +#define ALTERNATE_MALFORMED_FOLDER1 DISCOVER_FOLDER "/alternate_malformed_repo1" +#define ALTERNATE_MALFORMED_FOLDER2 DISCOVER_FOLDER "/alternate_malformed_repo2" +#define ALTERNATE_MALFORMED_FOLDER3 DISCOVER_FOLDER "/alternate_malformed_repo3" +#define ALTERNATE_NOT_FOUND_FOLDER DISCOVER_FOLDER "/alternate_not_found_repo" + +static void ensure_repository_discover(const char *start_path, + const char *ceiling_dirs, + const char *expected_path) +{ + char found_path[GIT_PATH_MAX]; + cl_git_pass(git_repository_discover(found_path, sizeof(found_path), start_path, 0, ceiling_dirs)); + //across_fs is always 0 as we can't automate the filesystem change tests + cl_assert_equal_s(found_path, expected_path); +} + +static void write_file(const char *path, const char *content) +{ + git_file file; + int error; + + if (git_path_exists(path)) { + cl_git_pass(p_unlink(path)); + } + + file = git_futils_creat_withpath(path, 0777, 0666); + cl_assert(file >= 0); + + error = p_write(file, content, strlen(content) * sizeof(char)); + p_close(file); + cl_git_pass(error); +} + +//no check is performed on ceiling_dirs length, so be sure it's long enough +static void append_ceiling_dir(git_buf *ceiling_dirs, const char *path) +{ + git_buf pretty_path = GIT_BUF_INIT; + char ceiling_separator[2] = { GIT_PATH_LIST_SEPARATOR, '\0' }; + + cl_git_pass(git_path_prettify_dir(&pretty_path, path, NULL)); + + if (ceiling_dirs->size > 0) + git_buf_puts(ceiling_dirs, ceiling_separator); + + git_buf_puts(ceiling_dirs, pretty_path.ptr); + + git_buf_free(&pretty_path); + cl_assert(git_buf_oom(ceiling_dirs) == 0); +} + +void test_repo_discover__0(void) +{ + // test discover + git_repository *repo; + git_buf ceiling_dirs_buf = GIT_BUF_INIT; + const char *ceiling_dirs; + char repository_path[GIT_PATH_MAX]; + char sub_repository_path[GIT_PATH_MAX]; + char found_path[GIT_PATH_MAX]; + const mode_t mode = 0777; + + git_futils_mkdir_r(DISCOVER_FOLDER, NULL, mode); + append_ceiling_dir(&ceiling_dirs_buf, TEMP_REPO_FOLDER); + ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf); + + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs)); + + cl_git_pass(git_repository_init(&repo, DISCOVER_FOLDER, 1)); + cl_git_pass(git_repository_discover(repository_path, sizeof(repository_path), DISCOVER_FOLDER, 0, ceiling_dirs)); + git_repository_free(repo); + + cl_git_pass(git_repository_init(&repo, SUB_REPOSITORY_FOLDER, 0)); + cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode)); + cl_git_pass(git_repository_discover(sub_repository_path, sizeof(sub_repository_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs)); + + cl_git_pass(git_futils_mkdir_r(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, NULL, mode)); + ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB, ceiling_dirs, sub_repository_path); + ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path); + ensure_repository_discover(SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, ceiling_dirs, sub_repository_path); + + cl_git_pass(git_futils_mkdir_r(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, NULL, mode)); + write_file(REPOSITORY_ALTERNATE_FOLDER "/" DOT_GIT, "gitdir: ../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT); + write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB "/" DOT_GIT, "gitdir: ../../../" SUB_REPOSITORY_FOLDER_NAME "/" DOT_GIT); + write_file(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB "/" DOT_GIT, "gitdir: ../../../../"); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path); + + cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER1, NULL, mode)); + write_file(ALTERNATE_MALFORMED_FOLDER1 "/" DOT_GIT, "Anything but not gitdir:"); + cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER2, NULL, mode)); + write_file(ALTERNATE_MALFORMED_FOLDER2 "/" DOT_GIT, "gitdir:"); + cl_git_pass(git_futils_mkdir_r(ALTERNATE_MALFORMED_FOLDER3, NULL, mode)); + write_file(ALTERNATE_MALFORMED_FOLDER3 "/" DOT_GIT, "gitdir: \n\n\n"); + cl_git_pass(git_futils_mkdir_r(ALTERNATE_NOT_FOUND_FOLDER, NULL, mode)); + write_file(ALTERNATE_NOT_FOUND_FOLDER "/" DOT_GIT, "gitdir: a_repository_that_surely_does_not_exist"); + cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER1, 0, ceiling_dirs)); + cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER2, 0, ceiling_dirs)); + cl_git_fail(git_repository_discover(found_path, sizeof(found_path), ALTERNATE_MALFORMED_FOLDER3, 0, ceiling_dirs)); + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), ALTERNATE_NOT_FOUND_FOLDER, 0, ceiling_dirs)); + + append_ceiling_dir(&ceiling_dirs_buf, SUB_REPOSITORY_FOLDER); + ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf); + + //this must pass as ceiling_directories cannot predent the current + //working directory to be checked + cl_git_pass(git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER, 0, ceiling_dirs)); + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB, 0, ceiling_dirs)); + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB, 0, ceiling_dirs)); + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_discover(found_path, sizeof(found_path), SUB_REPOSITORY_FOLDER_SUB_SUB_SUB, 0, ceiling_dirs)); + + //.gitfile redirection should not be affected by ceiling directories + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER, ceiling_dirs, sub_repository_path); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB, ceiling_dirs, sub_repository_path); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB, ceiling_dirs, sub_repository_path); + ensure_repository_discover(REPOSITORY_ALTERNATE_FOLDER_SUB_SUB_SUB, ceiling_dirs, repository_path); + + cl_git_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, NULL, GIT_RMDIR_REMOVE_FILES)); + git_repository_free(repo); + git_buf_free(&ceiling_dirs_buf); +} + diff --git a/tests/repo/getters.c b/tests/repo/getters.c new file mode 100644 index 000000000..b8ede126c --- /dev/null +++ b/tests/repo/getters.c @@ -0,0 +1,40 @@ +#include "clar_libgit2.h" + +void test_repo_getters__is_empty_correctly_deals_with_pristine_looking_repos(void) +{ + git_repository *repo; + + repo = cl_git_sandbox_init("empty_bare.git"); + cl_git_remove_placeholders(git_repository_path(repo), "dummy-marker.txt"); + + cl_assert_equal_i(true, git_repository_is_empty(repo)); + + cl_git_sandbox_cleanup(); +} + +void test_repo_getters__is_empty_can_detect_used_repositories(void) +{ + git_repository *repo; + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + + cl_assert_equal_i(false, git_repository_is_empty(repo)); + + git_repository_free(repo); +} + +void test_repo_getters__retrieving_the_odb_honors_the_refcount(void) +{ + git_odb *odb; + git_repository *repo; + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + + cl_git_pass(git_repository_odb(&odb, repo)); + cl_assert(((git_refcount *)odb)->refcount.val == 2); + + git_repository_free(repo); + cl_assert(((git_refcount *)odb)->refcount.val == 1); + + git_odb_free(odb); +} diff --git a/tests/repo/hashfile.c b/tests/repo/hashfile.c new file mode 100644 index 000000000..4cc9f18b4 --- /dev/null +++ b/tests/repo/hashfile.c @@ -0,0 +1,85 @@ +#include "clar_libgit2.h" +#include "buffer.h" + +static git_repository *_repo; + +void test_repo_hashfile__initialize(void) +{ + _repo = cl_git_sandbox_init("status"); +} + +void test_repo_hashfile__cleanup(void) +{ + cl_git_sandbox_cleanup(); + _repo = NULL; +} + +void test_repo_hashfile__simple(void) +{ + git_oid a, b; + git_buf full = GIT_BUF_INIT; + + /* hash with repo relative path */ + cl_git_pass(git_odb_hashfile(&a, "status/current_file", GIT_OBJ_BLOB)); + cl_git_pass(git_repository_hashfile(&b, _repo, "current_file", GIT_OBJ_BLOB, NULL)); + cl_assert(git_oid_equal(&a, &b)); + + cl_git_pass(git_buf_joinpath(&full, git_repository_workdir(_repo), "current_file")); + + /* hash with full path */ + cl_git_pass(git_odb_hashfile(&a, full.ptr, GIT_OBJ_BLOB)); + cl_git_pass(git_repository_hashfile(&b, _repo, full.ptr, GIT_OBJ_BLOB, NULL)); + cl_assert(git_oid_equal(&a, &b)); + + /* hash with invalid type */ + cl_git_fail(git_odb_hashfile(&a, full.ptr, GIT_OBJ_ANY)); + cl_git_fail(git_repository_hashfile(&b, _repo, full.ptr, GIT_OBJ_OFS_DELTA, NULL)); + + git_buf_free(&full); +} + +void test_repo_hashfile__filtered(void) +{ + git_oid a, b; + + cl_repo_set_bool(_repo, "core.autocrlf", true); + + cl_git_append2file("status/.gitattributes", "*.txt text\n*.bin binary\n\n"); + + /* create some sample content with CRLF in it */ + cl_git_mkfile("status/testfile.txt", "content\r\n"); + cl_git_mkfile("status/testfile.bin", "other\r\nstuff\r\n"); + + /* not equal hashes because of filtering */ + cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJ_BLOB)); + cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_BLOB, NULL)); + cl_assert(git_oid_cmp(&a, &b)); + + /* equal hashes because filter is binary */ + cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJ_BLOB)); + cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJ_BLOB, NULL)); + cl_assert(git_oid_equal(&a, &b)); + + /* equal hashes when 'as_file' points to binary filtering */ + cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJ_BLOB)); + cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_BLOB, "foo.bin")); + cl_assert(git_oid_equal(&a, &b)); + + /* not equal hashes when 'as_file' points to text filtering */ + cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJ_BLOB)); + cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJ_BLOB, "foo.txt")); + cl_assert(git_oid_cmp(&a, &b)); + + /* equal hashes when 'as_file' is empty and turns off filtering */ + cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJ_BLOB)); + cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_BLOB, "")); + cl_assert(git_oid_equal(&a, &b)); + + cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJ_BLOB)); + cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJ_BLOB, "")); + cl_assert(git_oid_equal(&a, &b)); + + /* some hash type failures */ + cl_git_fail(git_odb_hashfile(&a, "status/testfile.txt", 0)); + cl_git_fail(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_ANY, NULL)); +} diff --git a/tests/repo/head.c b/tests/repo/head.c new file mode 100644 index 000000000..5a55984bd --- /dev/null +++ b/tests/repo/head.c @@ -0,0 +1,196 @@ +#include "clar_libgit2.h" +#include "refs.h" +#include "repo_helpers.h" +#include "posix.h" + +static git_repository *repo; + +void test_repo_head__initialize(void) +{ + repo = cl_git_sandbox_init("testrepo.git"); +} + +void test_repo_head__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_repo_head__head_detached(void) +{ + git_reference *ref; + + cl_git_pass(git_repository_head_detached(repo)); + + cl_git_pass(git_repository_detach_head(repo)); + + cl_assert_equal_i(true, git_repository_head_detached(repo)); + + /* take the reop back to it's original state */ + cl_git_pass(git_reference_symbolic_create(&ref, repo, "HEAD", "refs/heads/master", 1)); + git_reference_free(ref); + + cl_assert_equal_i(false, git_repository_head_detached(repo)); +} + +void test_repo_head__unborn_head(void) +{ + git_reference *ref; + + cl_git_pass(git_repository_head_detached(repo)); + + make_head_unborn(repo, NON_EXISTING_HEAD); + + cl_assert(git_repository_head_unborn(repo) == 1); + + + /* take the repo back to it's original state */ + cl_git_pass(git_reference_symbolic_create(&ref, repo, "HEAD", "refs/heads/master", 1)); + cl_assert(git_repository_head_unborn(repo) == 0); + + git_reference_free(ref); +} + +void test_repo_head__set_head_Attaches_HEAD_to_un_unborn_branch_when_the_branch_doesnt_exist(void) +{ + git_reference *head; + + cl_git_pass(git_repository_set_head(repo, "refs/heads/doesnt/exist/yet")); + + cl_assert_equal_i(false, git_repository_head_detached(repo)); + + cl_assert_equal_i(GIT_EUNBORNBRANCH, git_repository_head(&head, repo)); +} + +void test_repo_head__set_head_Returns_ENOTFOUND_when_the_reference_doesnt_exist(void) +{ + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head(repo, "refs/tags/doesnt/exist/yet")); +} + +void test_repo_head__set_head_Fails_when_the_reference_points_to_a_non_commitish(void) +{ + cl_git_fail(git_repository_set_head(repo, "refs/tags/point_to_blob")); +} + +void test_repo_head__set_head_Attaches_HEAD_when_the_reference_points_to_a_branch(void) +{ + git_reference *head; + + cl_git_pass(git_repository_set_head(repo, "refs/heads/br2")); + + cl_assert_equal_i(false, git_repository_head_detached(repo)); + + cl_git_pass(git_repository_head(&head, repo)); + cl_assert_equal_s("refs/heads/br2", git_reference_name(head)); + + git_reference_free(head); +} + +static void assert_head_is_correctly_detached(void) +{ + git_reference *head; + git_object *commit; + + cl_assert_equal_i(true, git_repository_head_detached(repo)); + + cl_git_pass(git_repository_head(&head, repo)); + + cl_git_pass(git_object_lookup(&commit, repo, git_reference_target(head), GIT_OBJ_COMMIT)); + + git_object_free(commit); + git_reference_free(head); +} + +void test_repo_head__set_head_Detaches_HEAD_when_the_reference_doesnt_point_to_a_branch(void) +{ + cl_git_pass(git_repository_set_head(repo, "refs/tags/test")); + + cl_assert_equal_i(true, git_repository_head_detached(repo)); + + assert_head_is_correctly_detached(); +} + +void test_repo_head__set_head_detached_Return_ENOTFOUND_when_the_object_doesnt_exist(void) +{ + git_oid oid; + + cl_git_pass(git_oid_fromstr(&oid, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")); + + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head_detached(repo, &oid)); +} + +void test_repo_head__set_head_detached_Fails_when_the_object_isnt_a_commitish(void) +{ + git_object *blob; + + cl_git_pass(git_revparse_single(&blob, repo, "point_to_blob")); + + cl_git_fail(git_repository_set_head_detached(repo, git_object_id(blob))); + + git_object_free(blob); +} + +void test_repo_head__set_head_detached_Detaches_HEAD_and_make_it_point_to_the_peeled_commit(void) +{ + git_object *tag; + + cl_git_pass(git_revparse_single(&tag, repo, "tags/test")); + cl_assert_equal_i(GIT_OBJ_TAG, git_object_type(tag)); + + cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag))); + + assert_head_is_correctly_detached(); + + git_object_free(tag); +} + +void test_repo_head__detach_head_Detaches_HEAD_and_make_it_point_to_the_peeled_commit(void) +{ + cl_assert_equal_i(false, git_repository_head_detached(repo)); + + cl_git_pass(git_repository_detach_head(repo)); + + assert_head_is_correctly_detached(); +} + +void test_repo_head__detach_head_Fails_if_HEAD_and_point_to_a_non_commitish(void) +{ + git_reference *head; + + cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, "refs/tags/point_to_blob", 1)); + + cl_git_fail(git_repository_detach_head(repo)); + + git_reference_free(head); +} + +void test_repo_head__detaching_an_unborn_branch_returns_GIT_EUNBORNBRANCH(void) +{ + make_head_unborn(repo, NON_EXISTING_HEAD); + + cl_assert_equal_i(GIT_EUNBORNBRANCH, git_repository_detach_head(repo)); +} + +void test_repo_head__retrieving_an_unborn_branch_returns_GIT_EUNBORNBRANCH(void) +{ + git_reference *head; + + make_head_unborn(repo, NON_EXISTING_HEAD); + + cl_assert_equal_i(GIT_EUNBORNBRANCH, git_repository_head(&head, repo)); +} + +void test_repo_head__retrieving_a_missing_head_returns_GIT_ENOTFOUND(void) +{ + git_reference *head; + + delete_head(repo); + + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_head(&head, repo)); +} + +void test_repo_head__can_tell_if_an_unborn_head_is_detached(void) +{ + make_head_unborn(repo, NON_EXISTING_HEAD); + + cl_assert_equal_i(false, git_repository_head_detached(repo)); +} diff --git a/tests/repo/headtree.c b/tests/repo/headtree.c new file mode 100644 index 000000000..e899ac399 --- /dev/null +++ b/tests/repo/headtree.c @@ -0,0 +1,53 @@ +#include "clar_libgit2.h" +#include "repository.h" +#include "repo_helpers.h" +#include "posix.h" + +static git_repository *repo; +static git_tree *tree; + +void test_repo_headtree__initialize(void) +{ + repo = cl_git_sandbox_init("testrepo.git"); + tree = NULL; +} + +void test_repo_headtree__cleanup(void) +{ + git_tree_free(tree); + cl_git_sandbox_cleanup(); +} + +void test_repo_headtree__can_retrieve_the_root_tree_from_a_detached_head(void) +{ + cl_git_pass(git_repository_detach_head(repo)); + + cl_git_pass(git_repository_head_tree(&tree, repo)); + + cl_assert(git_oid_streq(git_tree_id(tree), "az")); +} + +void test_repo_headtree__can_retrieve_the_root_tree_from_a_non_detached_head(void) +{ + cl_assert_equal_i(false, git_repository_head_detached(repo)); + + cl_git_pass(git_repository_head_tree(&tree, repo)); + + cl_assert(git_oid_streq(git_tree_id(tree), "az")); +} + +void test_repo_headtree__when_head_is_unborn_returns_EUNBORNBRANCH(void) +{ + make_head_unborn(repo, NON_EXISTING_HEAD); + + cl_assert_equal_i(true, git_repository_head_unborn(repo)); + + cl_assert_equal_i(GIT_EUNBORNBRANCH, git_repository_head_tree(&tree, repo)); +} + +void test_repo_headtree__when_head_is_missing_returns_ENOTFOUND(void) +{ + delete_head(repo); + + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_head_tree(&tree, repo)); +} diff --git a/tests/repo/init.c b/tests/repo/init.c new file mode 100644 index 000000000..aea383c64 --- /dev/null +++ b/tests/repo/init.c @@ -0,0 +1,606 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "repository.h" +#include "config.h" +#include "path.h" + +enum repo_mode { + STANDARD_REPOSITORY = 0, + BARE_REPOSITORY = 1 +}; + +static git_repository *_repo = NULL; +static mode_t g_umask = 0; + +void test_repo_init__initialize(void) +{ + _repo = NULL; + + /* load umask if not already loaded */ + if (!g_umask) { + g_umask = p_umask(022); + (void)p_umask(g_umask); + } +} + +static void cleanup_repository(void *path) +{ + git_repository_free(_repo); + _repo = NULL; + + cl_fixture_cleanup((const char *)path); +} + +static void ensure_repository_init( + const char *working_directory, + int is_bare, + const char *expected_path_repository, + const char *expected_working_directory) +{ + const char *workdir; + + cl_assert(!git_path_isdir(working_directory)); + + cl_git_pass(git_repository_init(&_repo, working_directory, is_bare)); + + workdir = git_repository_workdir(_repo); + if (workdir != NULL || expected_working_directory != NULL) { + cl_assert( + git__suffixcmp(workdir, expected_working_directory) == 0 + ); + } + + cl_assert( + git__suffixcmp(git_repository_path(_repo), expected_path_repository) == 0 + ); + + cl_assert(git_repository_is_bare(_repo) == is_bare); + +#ifdef GIT_WIN32 + if (!is_bare) { + DWORD fattrs = GetFileAttributes(git_repository_path(_repo)); + cl_assert((fattrs & FILE_ATTRIBUTE_HIDDEN) != 0); + } +#endif + + cl_assert(git_repository_is_empty(_repo)); +} + +void test_repo_init__standard_repo(void) +{ + cl_set_cleanup(&cleanup_repository, "testrepo"); + ensure_repository_init("testrepo/", 0, "testrepo/.git/", "testrepo/"); +} + +void test_repo_init__standard_repo_noslash(void) +{ + cl_set_cleanup(&cleanup_repository, "testrepo"); + ensure_repository_init("testrepo", 0, "testrepo/.git/", "testrepo/"); +} + +void test_repo_init__bare_repo(void) +{ + cl_set_cleanup(&cleanup_repository, "testrepo.git"); + ensure_repository_init("testrepo.git/", 1, "testrepo.git/", NULL); +} + +void test_repo_init__bare_repo_noslash(void) +{ + cl_set_cleanup(&cleanup_repository, "testrepo.git"); + ensure_repository_init("testrepo.git", 1, "testrepo.git/", NULL); +} + +void test_repo_init__bare_repo_escaping_current_workdir(void) +{ + git_buf path_repository = GIT_BUF_INIT; + git_buf path_current_workdir = GIT_BUF_INIT; + + cl_git_pass(git_path_prettify_dir(&path_current_workdir, ".", NULL)); + + cl_git_pass(git_buf_joinpath(&path_repository, git_buf_cstr(&path_current_workdir), "a/b/c")); + cl_git_pass(git_futils_mkdir_r(git_buf_cstr(&path_repository), NULL, GIT_DIR_MODE)); + + /* Change the current working directory */ + cl_git_pass(chdir(git_buf_cstr(&path_repository))); + + /* Initialize a bare repo with a relative path escaping out of the current working directory */ + cl_git_pass(git_repository_init(&_repo, "../d/e.git", 1)); + cl_git_pass(git__suffixcmp(git_repository_path(_repo), "/a/b/d/e.git/")); + + git_repository_free(_repo); + + /* Open a bare repo with a relative path escaping out of the current working directory */ + cl_git_pass(git_repository_open(&_repo, "../d/e.git")); + + cl_git_pass(chdir(git_buf_cstr(&path_current_workdir))); + + git_buf_free(&path_current_workdir); + git_buf_free(&path_repository); + + cleanup_repository("a"); +} + +void test_repo_init__reinit_bare_repo(void) +{ + cl_set_cleanup(&cleanup_repository, "reinit.git"); + + /* Initialize the repository */ + cl_git_pass(git_repository_init(&_repo, "reinit.git", 1)); + git_repository_free(_repo); + + /* Reinitialize the repository */ + cl_git_pass(git_repository_init(&_repo, "reinit.git", 1)); +} + +void test_repo_init__reinit_too_recent_bare_repo(void) +{ + git_config *config; + + /* Initialize the repository */ + cl_git_pass(git_repository_init(&_repo, "reinit.git", 1)); + git_repository_config(&config, _repo); + + /* + * Hack the config of the repository to make it look like it has + * been created by a recenter version of git/libgit2 + */ + cl_git_pass(git_config_set_int32(config, "core.repositoryformatversion", 42)); + + git_config_free(config); + git_repository_free(_repo); + + /* Try to reinitialize the repository */ + cl_git_fail(git_repository_init(&_repo, "reinit.git", 1)); + + cl_fixture_cleanup("reinit.git"); +} + +void test_repo_init__additional_templates(void) +{ + git_buf path = GIT_BUF_INIT; + + cl_set_cleanup(&cleanup_repository, "tester"); + + ensure_repository_init("tester", 0, "tester/.git/", "tester/"); + + cl_git_pass( + git_buf_joinpath(&path, git_repository_path(_repo), "description")); + cl_assert(git_path_isfile(git_buf_cstr(&path))); + + cl_git_pass( + git_buf_joinpath(&path, git_repository_path(_repo), "info/exclude")); + cl_assert(git_path_isfile(git_buf_cstr(&path))); + + cl_git_pass( + git_buf_joinpath(&path, git_repository_path(_repo), "hooks")); + cl_assert(git_path_isdir(git_buf_cstr(&path))); + /* won't confirm specific contents of hooks dir since it may vary */ + + git_buf_free(&path); +} + +static void assert_config_entry_on_init_bytype( + const char *config_key, int expected_value, bool is_bare) +{ + git_config *config; + int error, current_value; + const char *repo_path = is_bare ? + "config_entry/test.bare.git" : "config_entry/test.non.bare.git"; + + cl_set_cleanup(&cleanup_repository, "config_entry"); + + cl_git_pass(git_repository_init(&_repo, repo_path, is_bare)); + + cl_git_pass(git_repository_config(&config, _repo)); + error = git_config_get_bool(¤t_value, config, config_key); + git_config_free(config); + + if (expected_value >= 0) { + cl_assert_equal_i(0, error); + cl_assert_equal_i(expected_value, current_value); + } else { + cl_assert_equal_i(expected_value, error); + } +} + +static void assert_config_entry_on_init( + const char *config_key, int expected_value) +{ + assert_config_entry_on_init_bytype(config_key, expected_value, true); + git_repository_free(_repo); + + assert_config_entry_on_init_bytype(config_key, expected_value, false); +} + +void test_repo_init__detect_filemode(void) +{ + assert_config_entry_on_init("core.filemode", cl_is_chmod_supported()); +} + +void test_repo_init__detect_ignorecase(void) +{ + struct stat st; + bool found_without_match; + + cl_git_write2file("testCAPS", "whatever\n", 0, O_CREAT | O_WRONLY, 0666); + found_without_match = (p_stat("Testcaps", &st) == 0); + cl_must_pass(p_unlink("testCAPS")); + + assert_config_entry_on_init( + "core.ignorecase", found_without_match ? true : GIT_ENOTFOUND); +} + +void test_repo_init__detect_precompose_unicode_required(void) +{ +#ifdef GIT_USE_ICONV + char *composed = "ḱṷṓn", *decomposed = "ḱṷṓn"; + struct stat st; + bool found_with_nfd; + + cl_git_write2file(composed, "whatever\n", 0, O_CREAT | O_WRONLY, 0666); + found_with_nfd = (p_stat(decomposed, &st) == 0); + cl_must_pass(p_unlink(composed)); + + assert_config_entry_on_init("core.precomposeunicode", found_with_nfd); +#else + assert_config_entry_on_init("core.precomposeunicode", GIT_ENOTFOUND); +#endif +} + +void test_repo_init__reinit_doesnot_overwrite_ignorecase(void) +{ + git_config *config; + int current_value; + + /* Init a new repo */ + cl_set_cleanup(&cleanup_repository, "not.overwrite.git"); + cl_git_pass(git_repository_init(&_repo, "not.overwrite.git", 1)); + + /* Change the "core.ignorecase" config value to something unlikely */ + git_repository_config(&config, _repo); + git_config_set_int32(config, "core.ignorecase", 42); + git_config_free(config); + git_repository_free(_repo); + _repo = NULL; + + /* Reinit the repository */ + cl_git_pass(git_repository_init(&_repo, "not.overwrite.git", 1)); + git_repository_config(&config, _repo); + + /* Ensure the "core.ignorecase" config value hasn't been updated */ + cl_git_pass(git_config_get_int32(¤t_value, config, "core.ignorecase")); + cl_assert_equal_i(42, current_value); + + git_config_free(config); +} + +void test_repo_init__reinit_overwrites_filemode(void) +{ + int expected = cl_is_chmod_supported(), current_value; + + /* Init a new repo */ + cl_set_cleanup(&cleanup_repository, "overwrite.git"); + cl_git_pass(git_repository_init(&_repo, "overwrite.git", 1)); + + /* Change the "core.filemode" config value to something unlikely */ + cl_repo_set_bool(_repo, "core.filemode", !expected); + + git_repository_free(_repo); + _repo = NULL; + + /* Reinit the repository */ + cl_git_pass(git_repository_init(&_repo, "overwrite.git", 1)); + + /* Ensure the "core.filemode" config value has been reset */ + current_value = cl_repo_get_bool(_repo, "core.filemode"); + cl_assert_equal_i(expected, current_value); +} + +void test_repo_init__sets_logAllRefUpdates_according_to_type_of_repository(void) +{ + assert_config_entry_on_init_bytype("core.logallrefupdates", GIT_ENOTFOUND, true); + git_repository_free(_repo); + assert_config_entry_on_init_bytype("core.logallrefupdates", true, false); +} + +void test_repo_init__extended_0(void) +{ + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + + /* without MKDIR this should fail */ + cl_git_fail(git_repository_init_ext(&_repo, "extended", &opts)); + + /* make the directory first, then it should succeed */ + cl_git_pass(git_futils_mkdir("extended", NULL, 0775, 0)); + cl_git_pass(git_repository_init_ext(&_repo, "extended", &opts)); + + cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "/extended/")); + cl_assert(!git__suffixcmp(git_repository_path(_repo), "/extended/.git/")); + cl_assert(!git_repository_is_bare(_repo)); + cl_assert(git_repository_is_empty(_repo)); + + cleanup_repository("extended"); +} + +void test_repo_init__extended_1(void) +{ + git_reference *ref; + git_remote *remote; + struct stat st; + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + + opts.flags = GIT_REPOSITORY_INIT_MKPATH | + GIT_REPOSITORY_INIT_NO_DOTGIT_DIR; + opts.mode = GIT_REPOSITORY_INIT_SHARED_GROUP; + opts.workdir_path = "../c_wd"; + opts.description = "Awesomest test repository evah"; + opts.initial_head = "development"; + opts.origin_url = "https://github.com/libgit2/libgit2.git"; + + cl_git_pass(git_repository_init_ext(&_repo, "root/b/c.git", &opts)); + + cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "/c_wd/")); + cl_assert(!git__suffixcmp(git_repository_path(_repo), "/c.git/")); + cl_assert(git_path_isfile("root/b/c_wd/.git")); + cl_assert(!git_repository_is_bare(_repo)); + /* repo will not be counted as empty because we set head to "development" */ + cl_assert(!git_repository_is_empty(_repo)); + + cl_git_pass(git_path_lstat(git_repository_path(_repo), &st)); + cl_assert(S_ISDIR(st.st_mode)); + if (cl_is_chmod_supported()) + cl_assert((S_ISGID & st.st_mode) == S_ISGID); + else + cl_assert((S_ISGID & st.st_mode) == 0); + + cl_git_pass(git_reference_lookup(&ref, _repo, "HEAD")); + cl_assert(git_reference_type(ref) == GIT_REF_SYMBOLIC); + cl_assert_equal_s("refs/heads/development", git_reference_symbolic_target(ref)); + git_reference_free(ref); + + cl_git_pass(git_remote_load(&remote, _repo, "origin")); + cl_assert_equal_s("origin", git_remote_name(remote)); + cl_assert_equal_s(opts.origin_url, git_remote_url(remote)); + git_remote_free(remote); + + git_repository_free(_repo); + cl_fixture_cleanup("root"); +} + +#define CLEAR_FOR_CORE_FILEMODE(M) ((M) &= ~0177) + +static void assert_hooks_match( + const char *template_dir, + const char *repo_dir, + const char *hook_path, + bool core_filemode) +{ + git_buf expected = GIT_BUF_INIT; + git_buf actual = GIT_BUF_INIT; + struct stat expected_st, st; + + cl_git_pass(git_buf_joinpath(&expected, template_dir, hook_path)); + cl_git_pass(git_path_lstat(expected.ptr, &expected_st)); + + cl_git_pass(git_buf_joinpath(&actual, repo_dir, hook_path)); + cl_git_pass(git_path_lstat(actual.ptr, &st)); + + cl_assert(expected_st.st_size == st.st_size); + + if (GIT_MODE_TYPE(expected_st.st_mode) != GIT_FILEMODE_LINK) { + mode_t expected_mode = + GIT_MODE_TYPE(expected_st.st_mode) | + (GIT_PERMS_FOR_WRITE(expected_st.st_mode) & ~g_umask); + + if (!core_filemode) { + CLEAR_FOR_CORE_FILEMODE(expected_mode); + CLEAR_FOR_CORE_FILEMODE(st.st_mode); + } + + cl_assert_equal_i_fmt(expected_mode, st.st_mode, "%07o"); + } + + git_buf_free(&expected); + git_buf_free(&actual); +} + +static void assert_mode_seems_okay( + const char *base, const char *path, + git_filemode_t expect_mode, bool expect_setgid, bool core_filemode) +{ + git_buf full = GIT_BUF_INIT; + struct stat st; + + cl_git_pass(git_buf_joinpath(&full, base, path)); + cl_git_pass(git_path_lstat(full.ptr, &st)); + git_buf_free(&full); + + if (!core_filemode) { + CLEAR_FOR_CORE_FILEMODE(expect_mode); + CLEAR_FOR_CORE_FILEMODE(st.st_mode); + expect_setgid = false; + } + + if (S_ISGID != 0) + cl_assert_equal_b(expect_setgid, (st.st_mode & S_ISGID) != 0); + + cl_assert_equal_b( + GIT_PERMS_IS_EXEC(expect_mode), GIT_PERMS_IS_EXEC(st.st_mode)); + + cl_assert_equal_i_fmt( + GIT_MODE_TYPE(expect_mode), GIT_MODE_TYPE(st.st_mode), "%07o"); +} + +void test_repo_init__extended_with_template(void) +{ + git_buf expected = GIT_BUF_INIT; + git_buf actual = GIT_BUF_INIT; + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + int filemode; + + cl_set_cleanup(&cleanup_repository, "templated.git"); + + opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE | + GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; + opts.template_path = cl_fixture("template"); + + cl_git_pass(git_repository_init_ext(&_repo, "templated.git", &opts)); + + cl_assert(git_repository_is_bare(_repo)); + + cl_assert(!git__suffixcmp(git_repository_path(_repo), "/templated.git/")); + + cl_git_pass(git_futils_readbuffer( + &expected, cl_fixture("template/description"))); + cl_git_pass(git_futils_readbuffer( + &actual, "templated.git/description")); + + cl_assert_equal_s(expected.ptr, actual.ptr); + + git_buf_free(&expected); + git_buf_free(&actual); + + filemode = cl_repo_get_bool(_repo, "core.filemode"); + + assert_hooks_match( + cl_fixture("template"), git_repository_path(_repo), + "hooks/update.sample", filemode); + + assert_hooks_match( + cl_fixture("template"), git_repository_path(_repo), + "hooks/link.sample", filemode); +} + +void test_repo_init__extended_with_template_and_shared_mode(void) +{ + git_buf expected = GIT_BUF_INIT; + git_buf actual = GIT_BUF_INIT; + git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + int filemode = true; + const char *repo_path = NULL; + + cl_set_cleanup(&cleanup_repository, "init_shared_from_tpl"); + + opts.flags = GIT_REPOSITORY_INIT_MKPATH | + GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE; + opts.template_path = cl_fixture("template"); + opts.mode = GIT_REPOSITORY_INIT_SHARED_GROUP; + + cl_git_pass(git_repository_init_ext(&_repo, "init_shared_from_tpl", &opts)); + + cl_assert(!git_repository_is_bare(_repo)); + cl_assert(!git__suffixcmp(git_repository_path(_repo), "/init_shared_from_tpl/.git/")); + + filemode = cl_repo_get_bool(_repo, "core.filemode"); + + cl_git_pass(git_futils_readbuffer( + &expected, cl_fixture("template/description"))); + cl_git_pass(git_futils_readbuffer( + &actual, "init_shared_from_tpl/.git/description")); + + cl_assert_equal_s(expected.ptr, actual.ptr); + + git_buf_free(&expected); + git_buf_free(&actual); + + repo_path = git_repository_path(_repo); + assert_mode_seems_okay(repo_path, "hooks", + GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode); + assert_mode_seems_okay(repo_path, "info", + GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode); + assert_mode_seems_okay(repo_path, "description", + GIT_FILEMODE_BLOB, false, filemode); + + /* for a non-symlinked hook, it should have shared permissions now */ + assert_hooks_match( + cl_fixture("template"), git_repository_path(_repo), + "hooks/update.sample", filemode); + + /* for a symlinked hook, the permissions still should match the + * source link, not the GIT_REPOSITORY_INIT_SHARED_GROUP value + */ + assert_hooks_match( + cl_fixture("template"), git_repository_path(_repo), + "hooks/link.sample", filemode); +} + +void test_repo_init__can_reinit_an_initialized_repository(void) +{ + git_repository *reinit; + + cl_set_cleanup(&cleanup_repository, "extended"); + + cl_git_pass(git_futils_mkdir("extended", NULL, 0775, 0)); + cl_git_pass(git_repository_init(&_repo, "extended", false)); + + cl_git_pass(git_repository_init(&reinit, "extended", false)); + + cl_assert_equal_s(git_repository_path(_repo), git_repository_path(reinit)); + + git_repository_free(reinit); +} + +void test_repo_init__init_with_initial_commit(void) +{ + git_index *index; + + cl_set_cleanup(&cleanup_repository, "committed"); + + /* Initialize the repository */ + cl_git_pass(git_repository_init(&_repo, "committed", 0)); + + /* Init will be automatically created when requested for a new repo */ + cl_git_pass(git_repository_index(&index, _repo)); + + /* Create a file so we can commit it + * + * If you are writing code outside the test suite, you can create this + * file any way that you like, such as: + * FILE *fp = fopen("committed/file.txt", "w"); + * fputs("some stuff\n", fp); + * fclose(fp); + * We like to use the help functions because they do error detection + * in a way that's easily compatible with our test suite. + */ + cl_git_mkfile("committed/file.txt", "some stuff\n"); + + /* Add file to the index */ + cl_git_pass(git_index_add_bypath(index, "file.txt")); + cl_git_pass(git_index_write(index)); + + /* Intentionally not using cl_repo_commit_from_index here so this code + * can be used as an example of how an initial commit is typically + * made to a repository... + */ + + /* Make sure we're ready to use git_signature_default :-) */ + { + git_config *cfg, *local; + cl_git_pass(git_repository_config(&cfg, _repo)); + cl_git_pass(git_config_open_level(&local, cfg, GIT_CONFIG_LEVEL_LOCAL)); + cl_git_pass(git_config_set_string(local, "user.name", "Test User")); + cl_git_pass(git_config_set_string(local, "user.email", "t@example.com")); + git_config_free(local); + git_config_free(cfg); + } + + /* Create a commit with the new contents of the index */ + { + git_signature *sig; + git_oid tree_id, commit_id; + git_tree *tree; + + cl_git_pass(git_signature_default(&sig, _repo)); + cl_git_pass(git_index_write_tree(&tree_id, index)); + cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id)); + + cl_git_pass(git_commit_create_v( + &commit_id, _repo, "HEAD", sig, sig, + NULL, "First", tree, 0)); + + git_tree_free(tree); + git_signature_free(sig); + } + + git_index_free(index); +} diff --git a/tests/repo/iterator.c b/tests/repo/iterator.c new file mode 100644 index 000000000..56b51852c --- /dev/null +++ b/tests/repo/iterator.c @@ -0,0 +1,962 @@ +#include "clar_libgit2.h" +#include "iterator.h" +#include "repository.h" +#include "fileops.h" +#include + +static git_repository *g_repo; + +void test_repo_iterator__initialize(void) +{ +} + +void test_repo_iterator__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +static void expect_iterator_items( + git_iterator *i, + int expected_flat, + const char **expected_flat_paths, + int expected_total, + const char **expected_total_paths) +{ + const git_index_entry *entry; + int count, error; + int no_trees = !(git_iterator_flags(i) & GIT_ITERATOR_INCLUDE_TREES); + bool v = false; + + if (expected_flat < 0) { v = true; expected_flat = -expected_flat; } + if (expected_total < 0) { v = true; expected_total = -expected_total; } + + if (v) fprintf(stderr, "== %s ==\n", no_trees ? "notrees" : "trees"); + + count = 0; + + while (!git_iterator_advance(&entry, i)) { + if (v) fprintf(stderr, " %s %07o\n", entry->path, (int)entry->mode); + + if (no_trees) + cl_assert(entry->mode != GIT_FILEMODE_TREE); + + if (expected_flat_paths) { + const char *expect_path = expected_flat_paths[count]; + size_t expect_len = strlen(expect_path); + + cl_assert_equal_s(expect_path, entry->path); + + if (expect_path[expect_len - 1] == '/') + cl_assert_equal_i(GIT_FILEMODE_TREE, entry->mode); + else + cl_assert(entry->mode != GIT_FILEMODE_TREE); + } + + if (++count > expected_flat) + break; + } + + cl_assert_equal_i(expected_flat, count); + + cl_git_pass(git_iterator_reset(i, NULL, NULL)); + + count = 0; + cl_git_pass(git_iterator_current(&entry, i)); + + if (v) fprintf(stderr, "-- %s --\n", no_trees ? "notrees" : "trees"); + + while (entry != NULL) { + if (v) fprintf(stderr, " %s %07o\n", entry->path, (int)entry->mode); + + if (no_trees) + cl_assert(entry->mode != GIT_FILEMODE_TREE); + + if (expected_total_paths) { + const char *expect_path = expected_total_paths[count]; + size_t expect_len = strlen(expect_path); + + cl_assert_equal_s(expect_path, entry->path); + + if (expect_path[expect_len - 1] == '/') + cl_assert_equal_i(GIT_FILEMODE_TREE, entry->mode); + else + cl_assert(entry->mode != GIT_FILEMODE_TREE); + } + + if (entry->mode == GIT_FILEMODE_TREE) { + error = git_iterator_advance_into(&entry, i); + + /* could return NOTFOUND if directory is empty */ + cl_assert(!error || error == GIT_ENOTFOUND); + + if (error == GIT_ENOTFOUND) { + error = git_iterator_advance(&entry, i); + cl_assert(!error || error == GIT_ITEROVER); + } + } else { + error = git_iterator_advance(&entry, i); + cl_assert(!error || error == GIT_ITEROVER); + } + + if (++count > expected_total) + break; + } + + cl_assert_equal_i(expected_total, count); +} + +/* Index contents (including pseudotrees): + * + * 0: a 5: F 10: k/ 16: L/ + * 1: B 6: g 11: k/1 17: L/1 + * 2: c 7: H 12: k/a 18: L/a + * 3: D 8: i 13: k/B 19: L/B + * 4: e 9: J 14: k/c 20: L/c + * 15: k/D 21: L/D + * + * 0: B 5: L/ 11: a 16: k/ + * 1: D 6: L/1 12: c 17: k/1 + * 2: F 7: L/B 13: e 18: k/B + * 3: H 8: L/D 14: g 19: k/D + * 4: J 9: L/a 15: i 20: k/a + * 10: L/c 21: k/c + */ + +void test_repo_iterator__index(void) +{ + git_iterator *i; + git_index *index; + + g_repo = cl_git_sandbox_init("icase"); + + cl_git_pass(git_repository_index(&index, g_repo)); + + /* autoexpand with no tree entries for index */ + cl_git_pass(git_iterator_for_index(&i, index, 0, NULL, NULL)); + expect_iterator_items(i, 20, NULL, 20, NULL); + git_iterator_free(i); + + /* auto expand with tree entries */ + cl_git_pass(git_iterator_for_index( + &i, index, GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + expect_iterator_items(i, 22, NULL, 22, NULL); + git_iterator_free(i); + + /* no auto expand (implies trees included) */ + cl_git_pass(git_iterator_for_index( + &i, index, GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); + expect_iterator_items(i, 12, NULL, 22, NULL); + git_iterator_free(i); + + git_index_free(index); +} + +void test_repo_iterator__index_icase(void) +{ + git_iterator *i; + git_index *index; + unsigned int caps; + + g_repo = cl_git_sandbox_init("icase"); + + cl_git_pass(git_repository_index(&index, g_repo)); + caps = git_index_caps(index); + + /* force case sensitivity */ + cl_git_pass(git_index_set_caps(index, caps & ~GIT_INDEXCAP_IGNORE_CASE)); + + /* autoexpand with no tree entries over range */ + cl_git_pass(git_iterator_for_index(&i, index, 0, "c", "k/D")); + expect_iterator_items(i, 7, NULL, 7, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_index(&i, index, 0, "k", "k/Z")); + expect_iterator_items(i, 3, NULL, 3, NULL); + git_iterator_free(i); + + /* auto expand with tree entries */ + cl_git_pass(git_iterator_for_index( + &i, index, GIT_ITERATOR_INCLUDE_TREES, "c", "k/D")); + expect_iterator_items(i, 8, NULL, 8, NULL); + git_iterator_free(i); + cl_git_pass(git_iterator_for_index( + &i, index, GIT_ITERATOR_INCLUDE_TREES, "k", "k/Z")); + expect_iterator_items(i, 4, NULL, 4, NULL); + git_iterator_free(i); + + /* no auto expand (implies trees included) */ + cl_git_pass(git_iterator_for_index( + &i, index, GIT_ITERATOR_DONT_AUTOEXPAND, "c", "k/D")); + expect_iterator_items(i, 5, NULL, 8, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_index( + &i, index, GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); + expect_iterator_items(i, 1, NULL, 4, NULL); + git_iterator_free(i); + + /* force case insensitivity */ + cl_git_pass(git_index_set_caps(index, caps | GIT_INDEXCAP_IGNORE_CASE)); + + /* autoexpand with no tree entries over range */ + cl_git_pass(git_iterator_for_index(&i, index, 0, "c", "k/D")); + expect_iterator_items(i, 13, NULL, 13, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_index(&i, index, 0, "k", "k/Z")); + expect_iterator_items(i, 5, NULL, 5, NULL); + git_iterator_free(i); + + /* auto expand with tree entries */ + cl_git_pass(git_iterator_for_index( + &i, index, GIT_ITERATOR_INCLUDE_TREES, "c", "k/D")); + expect_iterator_items(i, 14, NULL, 14, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_index( + &i, index, GIT_ITERATOR_INCLUDE_TREES, "k", "k/Z")); + expect_iterator_items(i, 6, NULL, 6, NULL); + git_iterator_free(i); + + /* no auto expand (implies trees included) */ + cl_git_pass(git_iterator_for_index( + &i, index, GIT_ITERATOR_DONT_AUTOEXPAND, "c", "k/D")); + expect_iterator_items(i, 9, NULL, 14, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_index( + &i, index, GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); + expect_iterator_items(i, 1, NULL, 6, NULL); + git_iterator_free(i); + + cl_git_pass(git_index_set_caps(index, caps)); + git_index_free(index); +} + +void test_repo_iterator__tree(void) +{ + git_iterator *i; + git_tree *head; + + g_repo = cl_git_sandbox_init("icase"); + + cl_git_pass(git_repository_head_tree(&head, g_repo)); + + /* auto expand with no tree entries */ + cl_git_pass(git_iterator_for_tree(&i, head, 0, NULL, NULL)); + expect_iterator_items(i, 20, NULL, 20, NULL); + git_iterator_free(i); + + /* auto expand with tree entries */ + cl_git_pass(git_iterator_for_tree( + &i, head, GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + expect_iterator_items(i, 22, NULL, 22, NULL); + git_iterator_free(i); + + /* no auto expand (implies trees included) */ + cl_git_pass(git_iterator_for_tree( + &i, head, GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); + expect_iterator_items(i, 12, NULL, 22, NULL); + git_iterator_free(i); + + git_tree_free(head); +} + +void test_repo_iterator__tree_icase(void) +{ + git_iterator *i; + git_tree *head; + git_iterator_flag_t flag; + + g_repo = cl_git_sandbox_init("icase"); + + cl_git_pass(git_repository_head_tree(&head, g_repo)); + + flag = GIT_ITERATOR_DONT_IGNORE_CASE; + + /* auto expand with no tree entries */ + cl_git_pass(git_iterator_for_tree(&i, head, flag, "c", "k/D")); + expect_iterator_items(i, 7, NULL, 7, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree(&i, head, flag, "k", "k/Z")); + expect_iterator_items(i, 3, NULL, 3, NULL); + git_iterator_free(i); + + /* auto expand with tree entries */ + cl_git_pass(git_iterator_for_tree( + &i, head, flag | GIT_ITERATOR_INCLUDE_TREES, "c", "k/D")); + expect_iterator_items(i, 8, NULL, 8, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree( + &i, head, flag | GIT_ITERATOR_INCLUDE_TREES, "k", "k/Z")); + expect_iterator_items(i, 4, NULL, 4, NULL); + git_iterator_free(i); + + /* no auto expand (implies trees included) */ + cl_git_pass(git_iterator_for_tree( + &i, head, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "c", "k/D")); + expect_iterator_items(i, 5, NULL, 8, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree( + &i, head, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); + expect_iterator_items(i, 1, NULL, 4, NULL); + git_iterator_free(i); + + flag = GIT_ITERATOR_IGNORE_CASE; + + /* auto expand with no tree entries */ + cl_git_pass(git_iterator_for_tree(&i, head, flag, "c", "k/D")); + expect_iterator_items(i, 13, NULL, 13, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree(&i, head, flag, "k", "k/Z")); + expect_iterator_items(i, 5, NULL, 5, NULL); + git_iterator_free(i); + + /* auto expand with tree entries */ + cl_git_pass(git_iterator_for_tree( + &i, head, flag | GIT_ITERATOR_INCLUDE_TREES, "c", "k/D")); + expect_iterator_items(i, 14, NULL, 14, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree( + &i, head, flag | GIT_ITERATOR_INCLUDE_TREES, "k", "k/Z")); + expect_iterator_items(i, 6, NULL, 6, NULL); + git_iterator_free(i); + + /* no auto expand (implies trees included) */ + cl_git_pass(git_iterator_for_tree( + &i, head, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "c", "k/D")); + expect_iterator_items(i, 9, NULL, 14, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree( + &i, head, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); + expect_iterator_items(i, 1, NULL, 6, NULL); + git_iterator_free(i); + + git_tree_free(head); +} + +void test_repo_iterator__tree_more(void) +{ + git_iterator *i; + git_tree *head; + static const char *expect_basic[] = { + "current_file", + "file_deleted", + "modified_file", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "subdir.txt", + "subdir/current_file", + "subdir/deleted_file", + "subdir/modified_file", + NULL, + }; + static const char *expect_trees[] = { + "current_file", + "file_deleted", + "modified_file", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "subdir.txt", + "subdir/", + "subdir/current_file", + "subdir/deleted_file", + "subdir/modified_file", + NULL, + }; + static const char *expect_noauto[] = { + "current_file", + "file_deleted", + "modified_file", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "subdir.txt", + "subdir/", + NULL + }; + + g_repo = cl_git_sandbox_init("status"); + + cl_git_pass(git_repository_head_tree(&head, g_repo)); + + /* auto expand with no tree entries */ + cl_git_pass(git_iterator_for_tree(&i, head, 0, NULL, NULL)); + expect_iterator_items(i, 12, expect_basic, 12, expect_basic); + git_iterator_free(i); + + /* auto expand with tree entries */ + cl_git_pass(git_iterator_for_tree( + &i, head, GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + expect_iterator_items(i, 13, expect_trees, 13, expect_trees); + git_iterator_free(i); + + /* no auto expand (implies trees included) */ + cl_git_pass(git_iterator_for_tree( + &i, head, GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); + expect_iterator_items(i, 10, expect_noauto, 13, expect_trees); + git_iterator_free(i); + + git_tree_free(head); +} + +/* "b=name,t=name", blob_id, tree_id */ +static void build_test_tree( + git_oid *out, git_repository *repo, const char *fmt, ...) +{ + git_oid *id; + git_treebuilder *builder; + const char *scan = fmt, *next; + char type, delimiter; + git_filemode_t mode = GIT_FILEMODE_BLOB; + git_buf name = GIT_BUF_INIT; + va_list arglist; + + cl_git_pass(git_treebuilder_create(&builder, NULL)); /* start builder */ + + va_start(arglist, fmt); + while (*scan) { + switch (type = *scan++) { + case 't': case 'T': mode = GIT_FILEMODE_TREE; break; + case 'b': case 'B': mode = GIT_FILEMODE_BLOB; break; + default: + cl_assert(type == 't' || type == 'T' || type == 'b' || type == 'B'); + } + + delimiter = *scan++; /* read and skip delimiter */ + for (next = scan; *next && *next != delimiter; ++next) + /* seek end */; + cl_git_pass(git_buf_set(&name, scan, (size_t)(next - scan))); + for (scan = next; *scan && (*scan == delimiter || *scan == ','); ++scan) + /* skip delimiter and optional comma */; + + id = va_arg(arglist, git_oid *); + + cl_git_pass(git_treebuilder_insert(NULL, builder, name.ptr, id, mode)); + } + va_end(arglist); + + cl_git_pass(git_treebuilder_write(out, repo, builder)); + + git_treebuilder_free(builder); + git_buf_free(&name); +} + +void test_repo_iterator__tree_case_conflicts_0(void) +{ + const char *blob_sha = "d44e18fb93b7107b5cd1b95d601591d77869a1b6"; + git_tree *tree; + git_oid blob_id, biga_id, littlea_id, tree_id; + git_iterator *i; + const char *expect_cs[] = { + "A/1.file", "A/3.file", "a/2.file", "a/4.file" }; + const char *expect_ci[] = { + "A/1.file", "a/2.file", "A/3.file", "a/4.file" }; + const char *expect_cs_trees[] = { + "A/", "A/1.file", "A/3.file", "a/", "a/2.file", "a/4.file" }; + const char *expect_ci_trees[] = { + "A/", "A/1.file", "a/2.file", "A/3.file", "a/4.file" }; + + g_repo = cl_git_sandbox_init("icase"); + + cl_git_pass(git_oid_fromstr(&blob_id, blob_sha)); /* lookup blob */ + + /* create tree with: A/1.file, A/3.file, a/2.file, a/4.file */ + build_test_tree( + &biga_id, g_repo, "b|1.file|,b|3.file|", &blob_id, &blob_id); + build_test_tree( + &littlea_id, g_repo, "b|2.file|,b|4.file|", &blob_id, &blob_id); + build_test_tree( + &tree_id, g_repo, "t|A|,t|a|", &biga_id, &littlea_id); + + cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); + + cl_git_pass(git_iterator_for_tree( + &i, tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)); + expect_iterator_items(i, 4, expect_cs, 4, expect_cs); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree( + &i, tree, GIT_ITERATOR_IGNORE_CASE, NULL, NULL)); + expect_iterator_items(i, 4, expect_ci, 4, expect_ci); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree( + &i, tree, GIT_ITERATOR_DONT_IGNORE_CASE | + GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + expect_iterator_items(i, 6, expect_cs_trees, 6, expect_cs_trees); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree( + &i, tree, GIT_ITERATOR_IGNORE_CASE | + GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + expect_iterator_items(i, 5, expect_ci_trees, 5, expect_ci_trees); + git_iterator_free(i); + + git_tree_free(tree); +} + +void test_repo_iterator__tree_case_conflicts_1(void) +{ + const char *blob_sha = "d44e18fb93b7107b5cd1b95d601591d77869a1b6"; + git_tree *tree; + git_oid blob_id, Ab_id, biga_id, littlea_id, tree_id; + git_iterator *i; + const char *expect_cs[] = { + "A/a", "A/b/1", "A/c", "a/C", "a/a", "a/b" }; + const char *expect_ci[] = { + "A/a", "a/b", "A/b/1", "A/c" }; + const char *expect_cs_trees[] = { + "A/", "A/a", "A/b/", "A/b/1", "A/c", "a/", "a/C", "a/a", "a/b" }; + const char *expect_ci_trees[] = { + "A/", "A/a", "a/b", "A/b/", "A/b/1", "A/c" }; + + g_repo = cl_git_sandbox_init("icase"); + + cl_git_pass(git_oid_fromstr(&blob_id, blob_sha)); /* lookup blob */ + + /* create: A/a A/b/1 A/c a/a a/b a/C */ + build_test_tree(&Ab_id, g_repo, "b|1|", &blob_id); + build_test_tree( + &biga_id, g_repo, "b|a|,t|b|,b|c|", &blob_id, &Ab_id, &blob_id); + build_test_tree( + &littlea_id, g_repo, "b|a|,b|b|,b|C|", &blob_id, &blob_id, &blob_id); + build_test_tree( + &tree_id, g_repo, "t|A|,t|a|", &biga_id, &littlea_id); + + cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); + + cl_git_pass(git_iterator_for_tree( + &i, tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)); + expect_iterator_items(i, 6, expect_cs, 6, expect_cs); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree( + &i, tree, GIT_ITERATOR_IGNORE_CASE, NULL, NULL)); + expect_iterator_items(i, 4, expect_ci, 4, expect_ci); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree( + &i, tree, GIT_ITERATOR_DONT_IGNORE_CASE | + GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + expect_iterator_items(i, 9, expect_cs_trees, 9, expect_cs_trees); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree( + &i, tree, GIT_ITERATOR_IGNORE_CASE | + GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + expect_iterator_items(i, 6, expect_ci_trees, 6, expect_ci_trees); + git_iterator_free(i); + + git_tree_free(tree); +} + +void test_repo_iterator__tree_case_conflicts_2(void) +{ + const char *blob_sha = "d44e18fb93b7107b5cd1b95d601591d77869a1b6"; + git_tree *tree; + git_oid blob_id, d1, d2, c1, c2, b1, b2, a1, a2, tree_id; + git_iterator *i; + const char *expect_cs[] = { + "A/B/C/D/16", "A/B/C/D/foo", "A/B/C/d/15", "A/B/C/d/FOO", + "A/B/c/D/14", "A/B/c/D/foo", "A/B/c/d/13", "A/B/c/d/FOO", + "A/b/C/D/12", "A/b/C/D/foo", "A/b/C/d/11", "A/b/C/d/FOO", + "A/b/c/D/10", "A/b/c/D/foo", "A/b/c/d/09", "A/b/c/d/FOO", + "a/B/C/D/08", "a/B/C/D/foo", "a/B/C/d/07", "a/B/C/d/FOO", + "a/B/c/D/06", "a/B/c/D/foo", "a/B/c/d/05", "a/B/c/d/FOO", + "a/b/C/D/04", "a/b/C/D/foo", "a/b/C/d/03", "a/b/C/d/FOO", + "a/b/c/D/02", "a/b/c/D/foo", "a/b/c/d/01", "a/b/c/d/FOO", }; + const char *expect_ci[] = { + "a/b/c/d/01", "a/b/c/D/02", "a/b/C/d/03", "a/b/C/D/04", + "a/B/c/d/05", "a/B/c/D/06", "a/B/C/d/07", "a/B/C/D/08", + "A/b/c/d/09", "A/b/c/D/10", "A/b/C/d/11", "A/b/C/D/12", + "A/B/c/d/13", "A/B/c/D/14", "A/B/C/d/15", "A/B/C/D/16", + "A/B/C/D/foo", }; + const char *expect_ci_trees[] = { + "A/", "A/B/", "A/B/C/", "A/B/C/D/", + "a/b/c/d/01", "a/b/c/D/02", "a/b/C/d/03", "a/b/C/D/04", + "a/B/c/d/05", "a/B/c/D/06", "a/B/C/d/07", "a/B/C/D/08", + "A/b/c/d/09", "A/b/c/D/10", "A/b/C/d/11", "A/b/C/D/12", + "A/B/c/d/13", "A/B/c/D/14", "A/B/C/d/15", "A/B/C/D/16", + "A/B/C/D/foo", }; + + g_repo = cl_git_sandbox_init("icase"); + + cl_git_pass(git_oid_fromstr(&blob_id, blob_sha)); /* lookup blob */ + + build_test_tree(&d1, g_repo, "b|16|,b|foo|", &blob_id, &blob_id); + build_test_tree(&d2, g_repo, "b|15|,b|FOO|", &blob_id, &blob_id); + build_test_tree(&c1, g_repo, "t|D|,t|d|", &d1, &d2); + build_test_tree(&d1, g_repo, "b|14|,b|foo|", &blob_id, &blob_id); + build_test_tree(&d2, g_repo, "b|13|,b|FOO|", &blob_id, &blob_id); + build_test_tree(&c2, g_repo, "t|D|,t|d|", &d1, &d2); + build_test_tree(&b1, g_repo, "t|C|,t|c|", &c1, &c2); + + build_test_tree(&d1, g_repo, "b|12|,b|foo|", &blob_id, &blob_id); + build_test_tree(&d2, g_repo, "b|11|,b|FOO|", &blob_id, &blob_id); + build_test_tree(&c1, g_repo, "t|D|,t|d|", &d1, &d2); + build_test_tree(&d1, g_repo, "b|10|,b|foo|", &blob_id, &blob_id); + build_test_tree(&d2, g_repo, "b|09|,b|FOO|", &blob_id, &blob_id); + build_test_tree(&c2, g_repo, "t|D|,t|d|", &d1, &d2); + build_test_tree(&b2, g_repo, "t|C|,t|c|", &c1, &c2); + + build_test_tree(&a1, g_repo, "t|B|,t|b|", &b1, &b2); + + build_test_tree(&d1, g_repo, "b|08|,b|foo|", &blob_id, &blob_id); + build_test_tree(&d2, g_repo, "b|07|,b|FOO|", &blob_id, &blob_id); + build_test_tree(&c1, g_repo, "t|D|,t|d|", &d1, &d2); + build_test_tree(&d1, g_repo, "b|06|,b|foo|", &blob_id, &blob_id); + build_test_tree(&d2, g_repo, "b|05|,b|FOO|", &blob_id, &blob_id); + build_test_tree(&c2, g_repo, "t|D|,t|d|", &d1, &d2); + build_test_tree(&b1, g_repo, "t|C|,t|c|", &c1, &c2); + + build_test_tree(&d1, g_repo, "b|04|,b|foo|", &blob_id, &blob_id); + build_test_tree(&d2, g_repo, "b|03|,b|FOO|", &blob_id, &blob_id); + build_test_tree(&c1, g_repo, "t|D|,t|d|", &d1, &d2); + build_test_tree(&d1, g_repo, "b|02|,b|foo|", &blob_id, &blob_id); + build_test_tree(&d2, g_repo, "b|01|,b|FOO|", &blob_id, &blob_id); + build_test_tree(&c2, g_repo, "t|D|,t|d|", &d1, &d2); + build_test_tree(&b2, g_repo, "t|C|,t|c|", &c1, &c2); + + build_test_tree(&a2, g_repo, "t|B|,t|b|", &b1, &b2); + + build_test_tree(&tree_id, g_repo, "t/A/,t/a/", &a1, &a2); + + cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id)); + + cl_git_pass(git_iterator_for_tree( + &i, tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)); + expect_iterator_items(i, 32, expect_cs, 32, expect_cs); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree( + &i, tree, GIT_ITERATOR_IGNORE_CASE, NULL, NULL)); + expect_iterator_items(i, 17, expect_ci, 17, expect_ci); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_tree( + &i, tree, GIT_ITERATOR_IGNORE_CASE | + GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + expect_iterator_items(i, 21, expect_ci_trees, 21, expect_ci_trees); + git_iterator_free(i); + + git_tree_free(tree); +} + +void test_repo_iterator__workdir(void) +{ + git_iterator *i; + + g_repo = cl_git_sandbox_init("icase"); + + /* auto expand with no tree entries */ + cl_git_pass(git_iterator_for_workdir(&i, g_repo, 0, NULL, NULL)); + expect_iterator_items(i, 20, NULL, 20, NULL); + git_iterator_free(i); + + /* auto expand with tree entries */ + cl_git_pass(git_iterator_for_workdir( + &i, g_repo, GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + expect_iterator_items(i, 22, NULL, 22, NULL); + git_iterator_free(i); + + /* no auto expand (implies trees included) */ + cl_git_pass(git_iterator_for_workdir( + &i, g_repo, GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); + expect_iterator_items(i, 12, NULL, 22, NULL); + git_iterator_free(i); +} + +void test_repo_iterator__workdir_icase(void) +{ + git_iterator *i; + git_iterator_flag_t flag; + + g_repo = cl_git_sandbox_init("icase"); + + flag = GIT_ITERATOR_DONT_IGNORE_CASE; + + /* auto expand with no tree entries */ + cl_git_pass(git_iterator_for_workdir(&i, g_repo, flag, "c", "k/D")); + expect_iterator_items(i, 7, NULL, 7, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_workdir(&i, g_repo, flag, "k", "k/Z")); + expect_iterator_items(i, 3, NULL, 3, NULL); + git_iterator_free(i); + + /* auto expand with tree entries */ + cl_git_pass(git_iterator_for_workdir( + &i, g_repo, flag | GIT_ITERATOR_INCLUDE_TREES, "c", "k/D")); + expect_iterator_items(i, 8, NULL, 8, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_workdir( + &i, g_repo, flag | GIT_ITERATOR_INCLUDE_TREES, "k", "k/Z")); + expect_iterator_items(i, 4, NULL, 4, NULL); + git_iterator_free(i); + + /* no auto expand (implies trees included) */ + cl_git_pass(git_iterator_for_workdir( + &i, g_repo, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "c", "k/D")); + expect_iterator_items(i, 5, NULL, 8, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_workdir( + &i, g_repo, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); + expect_iterator_items(i, 1, NULL, 4, NULL); + git_iterator_free(i); + + flag = GIT_ITERATOR_IGNORE_CASE; + + /* auto expand with no tree entries */ + cl_git_pass(git_iterator_for_workdir(&i, g_repo, flag, "c", "k/D")); + expect_iterator_items(i, 13, NULL, 13, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_workdir(&i, g_repo, flag, "k", "k/Z")); + expect_iterator_items(i, 5, NULL, 5, NULL); + git_iterator_free(i); + + /* auto expand with tree entries */ + cl_git_pass(git_iterator_for_workdir( + &i, g_repo, flag | GIT_ITERATOR_INCLUDE_TREES, "c", "k/D")); + expect_iterator_items(i, 14, NULL, 14, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_workdir( + &i, g_repo, flag | GIT_ITERATOR_INCLUDE_TREES, "k", "k/Z")); + expect_iterator_items(i, 6, NULL, 6, NULL); + git_iterator_free(i); + + /* no auto expand (implies trees included) */ + cl_git_pass(git_iterator_for_workdir( + &i, g_repo, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "c", "k/D")); + expect_iterator_items(i, 9, NULL, 14, NULL); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_workdir( + &i, g_repo, flag | GIT_ITERATOR_DONT_AUTOEXPAND, "k", "k/Z")); + expect_iterator_items(i, 1, NULL, 6, NULL); + git_iterator_free(i); +} + +static void build_workdir_tree(const char *root, int dirs, int subs) +{ + int i, j; + char buf[64], sub[64]; + + for (i = 0; i < dirs; ++i) { + if (i % 2 == 0) { + p_snprintf(buf, sizeof(buf), "%s/dir%02d", root, i); + cl_git_pass(git_futils_mkdir(buf, NULL, 0775, GIT_MKDIR_PATH)); + + p_snprintf(buf, sizeof(buf), "%s/dir%02d/file", root, i); + cl_git_mkfile(buf, buf); + buf[strlen(buf) - 5] = '\0'; + } else { + p_snprintf(buf, sizeof(buf), "%s/DIR%02d", root, i); + cl_git_pass(git_futils_mkdir(buf, NULL, 0775, GIT_MKDIR_PATH)); + } + + for (j = 0; j < subs; ++j) { + switch (j % 4) { + case 0: p_snprintf(sub, sizeof(sub), "%s/sub%02d", buf, j); break; + case 1: p_snprintf(sub, sizeof(sub), "%s/sUB%02d", buf, j); break; + case 2: p_snprintf(sub, sizeof(sub), "%s/Sub%02d", buf, j); break; + case 3: p_snprintf(sub, sizeof(sub), "%s/SUB%02d", buf, j); break; + } + cl_git_pass(git_futils_mkdir(sub, NULL, 0775, GIT_MKDIR_PATH)); + + if (j % 2 == 0) { + size_t sublen = strlen(sub); + memcpy(&sub[sublen], "/file", sizeof("/file")); + cl_git_mkfile(sub, sub); + sub[sublen] = '\0'; + } + } + } +} + +void test_repo_iterator__workdir_depth(void) +{ + git_iterator *iter; + + g_repo = cl_git_sandbox_init("icase"); + + build_workdir_tree("icase", 10, 10); + build_workdir_tree("icase/DIR01/sUB01", 50, 0); + build_workdir_tree("icase/dir02/sUB01", 50, 0); + + /* auto expand with no tree entries */ + cl_git_pass(git_iterator_for_workdir(&iter, g_repo, 0, NULL, NULL)); + expect_iterator_items(iter, 125, NULL, 125, NULL); + git_iterator_free(iter); + + /* auto expand with tree entries (empty dirs silently skipped) */ + cl_git_pass(git_iterator_for_workdir( + &iter, g_repo, GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + expect_iterator_items(iter, 337, NULL, 337, NULL); + git_iterator_free(iter); +} + +void test_repo_iterator__fs(void) +{ + git_iterator *i; + static const char *expect_base[] = { + "DIR01/Sub02/file", + "DIR01/sub00/file", + "current_file", + "dir00/Sub02/file", + "dir00/file", + "dir00/sub00/file", + "modified_file", + "new_file", + NULL, + }; + static const char *expect_trees[] = { + "DIR01/", + "DIR01/SUB03/", + "DIR01/Sub02/", + "DIR01/Sub02/file", + "DIR01/sUB01/", + "DIR01/sub00/", + "DIR01/sub00/file", + "current_file", + "dir00/", + "dir00/SUB03/", + "dir00/Sub02/", + "dir00/Sub02/file", + "dir00/file", + "dir00/sUB01/", + "dir00/sub00/", + "dir00/sub00/file", + "modified_file", + "new_file", + NULL, + }; + static const char *expect_noauto[] = { + "DIR01/", + "current_file", + "dir00/", + "modified_file", + "new_file", + NULL, + }; + + g_repo = cl_git_sandbox_init("status"); + + build_workdir_tree("status/subdir", 2, 4); + + cl_git_pass(git_iterator_for_filesystem( + &i, "status/subdir", 0, NULL, NULL)); + expect_iterator_items(i, 8, expect_base, 8, expect_base); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_filesystem( + &i, "status/subdir", GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + expect_iterator_items(i, 18, expect_trees, 18, expect_trees); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_filesystem( + &i, "status/subdir", GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); + expect_iterator_items(i, 5, expect_noauto, 18, expect_trees); + git_iterator_free(i); + + git__tsort((void **)expect_base, 8, (git__tsort_cmp)git__strcasecmp); + git__tsort((void **)expect_trees, 18, (git__tsort_cmp)git__strcasecmp); + git__tsort((void **)expect_noauto, 5, (git__tsort_cmp)git__strcasecmp); + + cl_git_pass(git_iterator_for_filesystem( + &i, "status/subdir", GIT_ITERATOR_IGNORE_CASE, NULL, NULL)); + expect_iterator_items(i, 8, expect_base, 8, expect_base); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_filesystem( + &i, "status/subdir", GIT_ITERATOR_IGNORE_CASE | + GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + expect_iterator_items(i, 18, expect_trees, 18, expect_trees); + git_iterator_free(i); + + cl_git_pass(git_iterator_for_filesystem( + &i, "status/subdir", GIT_ITERATOR_IGNORE_CASE | + GIT_ITERATOR_DONT_AUTOEXPAND, NULL, NULL)); + expect_iterator_items(i, 5, expect_noauto, 18, expect_trees); + git_iterator_free(i); +} + +void test_repo_iterator__fs2(void) +{ + git_iterator *i; + static const char *expect_base[] = { + "heads/br2", + "heads/dir", + "heads/long-file-name", + "heads/master", + "heads/packed-test", + "heads/subtrees", + "heads/test", + "tags/e90810b", + "tags/foo/bar", + "tags/foo/foo/bar", + "tags/point_to_blob", + "tags/test", + NULL, + }; + + g_repo = cl_git_sandbox_init("testrepo"); + + cl_git_pass(git_iterator_for_filesystem( + &i, "testrepo/.git/refs", 0, NULL, NULL)); + expect_iterator_items(i, 12, expect_base, 12, expect_base); + git_iterator_free(i); +} + +void test_repo_iterator__fs_preserves_error(void) +{ + git_iterator *i; + const git_index_entry *e; + + if (!cl_is_chmod_supported()) + return; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_must_pass(p_mkdir("empty_standard_repo/r", 0777)); + cl_git_mkfile("empty_standard_repo/r/a", "hello"); + cl_must_pass(p_mkdir("empty_standard_repo/r/b", 0777)); + cl_git_mkfile("empty_standard_repo/r/b/problem", "not me"); + cl_must_pass(p_chmod("empty_standard_repo/r/b", 0000)); + cl_must_pass(p_mkdir("empty_standard_repo/r/c", 0777)); + cl_git_mkfile("empty_standard_repo/r/d", "final"); + + cl_git_pass(git_iterator_for_filesystem( + &i, "empty_standard_repo/r", 0, NULL, NULL)); + + cl_git_pass(git_iterator_advance(&e, i)); /* a */ + cl_git_fail(git_iterator_advance(&e, i)); /* b */ + cl_assert(giterr_last()); + cl_assert(giterr_last()->message != NULL); + /* skip 'c/' empty directory */ + cl_git_pass(git_iterator_advance(&e, i)); /* d */ + cl_assert_equal_i(GIT_ITEROVER, git_iterator_advance(&e, i)); + + cl_must_pass(p_chmod("empty_standard_repo/r/b", 0777)); + + git_iterator_free(i); +} diff --git a/tests/repo/message.c b/tests/repo/message.c new file mode 100644 index 000000000..629d40c12 --- /dev/null +++ b/tests/repo/message.c @@ -0,0 +1,52 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "refs.h" +#include "posix.h" + +static git_repository *_repo; +static git_buf _path; +static char *_actual; + +void test_repo_message__initialize(void) +{ + _repo = cl_git_sandbox_init("testrepo.git"); +} + +void test_repo_message__cleanup(void) +{ + cl_git_sandbox_cleanup(); + git_buf_free(&_path); + git__free(_actual); + _actual = NULL; +} + +void test_repo_message__none(void) +{ + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(NULL, 0, _repo)); +} + +void test_repo_message__message(void) +{ + const char expected[] = "Test\n\nThis is a test of the emergency broadcast system\n"; + ssize_t len; + + cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), "MERGE_MSG")); + cl_git_mkfile(git_buf_cstr(&_path), expected); + + len = git_repository_message(NULL, 0, _repo); + cl_assert(len > 0); + + _actual = git__malloc(len + 1); + cl_assert(_actual != NULL); + + /* Test non truncation */ + cl_assert(git_repository_message(_actual, len, _repo) > 0); + cl_assert_equal_s(expected, _actual); + + /* Test truncation and that trailing NUL is inserted */ + cl_assert(git_repository_message(_actual, 6, _repo) > 0); + cl_assert_equal_s("Test\n", _actual); + + cl_git_pass(p_unlink(git_buf_cstr(&_path))); + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_message(NULL, 0, _repo)); +} diff --git a/tests/repo/open.c b/tests/repo/open.c new file mode 100644 index 000000000..7cfe041c2 --- /dev/null +++ b/tests/repo/open.c @@ -0,0 +1,376 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include + +void test_repo_open__cleanup(void) +{ + cl_git_sandbox_cleanup(); + + if (git_path_isdir("alternate")) + git_futils_rmdir_r("alternate", NULL, GIT_RMDIR_REMOVE_FILES); +} + +void test_repo_open__bare_empty_repo(void) +{ + git_repository *repo = cl_git_sandbox_init("empty_bare.git"); + + cl_assert(git_repository_path(repo) != NULL); + cl_assert(git__suffixcmp(git_repository_path(repo), "/") == 0); + cl_assert(git_repository_workdir(repo) == NULL); +} + +void test_repo_open__standard_empty_repo_through_gitdir(void) +{ + git_repository *repo; + + cl_git_pass(git_repository_open(&repo, cl_fixture("empty_standard_repo/.gitted"))); + + cl_assert(git_repository_path(repo) != NULL); + cl_assert(git__suffixcmp(git_repository_path(repo), "/") == 0); + + cl_assert(git_repository_workdir(repo) != NULL); + cl_assert(git__suffixcmp(git_repository_workdir(repo), "/") == 0); + + git_repository_free(repo); +} + +void test_repo_open__standard_empty_repo_through_workdir(void) +{ + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_assert(git_repository_path(repo) != NULL); + cl_assert(git__suffixcmp(git_repository_path(repo), "/") == 0); + + cl_assert(git_repository_workdir(repo) != NULL); + cl_assert(git__suffixcmp(git_repository_workdir(repo), "/") == 0); +} + + +void test_repo_open__open_with_discover(void) +{ + static const char *variants[] = { + "attr", "attr/", "attr/.git", "attr/.git/", + "attr/sub", "attr/sub/", "attr/sub/sub", "attr/sub/sub/", + NULL + }; + git_repository *repo; + const char **scan; + + cl_fixture_sandbox("attr"); + cl_git_pass(p_rename("attr/.gitted", "attr/.git")); + + for (scan = variants; *scan != NULL; scan++) { + cl_git_pass(git_repository_open_ext(&repo, *scan, 0, NULL)); + cl_assert(git__suffixcmp(git_repository_path(repo), "attr/.git/") == 0); + cl_assert(git__suffixcmp(git_repository_workdir(repo), "attr/") == 0); + git_repository_free(repo); + } + + cl_fixture_cleanup("attr"); +} + +static void make_gitlink_dir(const char *dir, const char *linktext) +{ + git_buf path = GIT_BUF_INIT; + + cl_git_pass(git_futils_mkdir(dir, NULL, 0777, GIT_MKDIR_VERIFY_DIR)); + cl_git_pass(git_buf_joinpath(&path, dir, ".git")); + cl_git_rewritefile(path.ptr, linktext); + git_buf_free(&path); +} + +void test_repo_open__gitlinked(void) +{ + /* need to have both repo dir and workdir set up correctly */ + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + git_repository *repo2; + + make_gitlink_dir("alternate", "gitdir: ../empty_standard_repo/.git"); + + cl_git_pass(git_repository_open(&repo2, "alternate")); + + cl_assert(git_repository_path(repo2) != NULL); + cl_assert_(git__suffixcmp(git_repository_path(repo2), "empty_standard_repo/.git/") == 0, git_repository_path(repo2)); + cl_assert_equal_s(git_repository_path(repo), git_repository_path(repo2)); + + cl_assert(git_repository_workdir(repo2) != NULL); + cl_assert_(git__suffixcmp(git_repository_workdir(repo2), "alternate/") == 0, git_repository_workdir(repo2)); + + git_repository_free(repo2); +} + +void test_repo_open__from_git_new_workdir(void) +{ + /* The git-new-workdir script that ships with git sets up a bunch of + * symlinks to create a second workdir that shares the object db with + * another checkout. Libgit2 can open a repo that has been configured + * this way. + */ + cl_git_sandbox_init("empty_standard_repo"); + +#ifndef GIT_WIN32 + git_repository *repo2; + git_buf link_tgt = GIT_BUF_INIT, link = GIT_BUF_INIT, body = GIT_BUF_INIT; + const char **scan; + int link_fd; + static const char *links[] = { + "config", "refs", "logs/refs", "objects", "info", "hooks", + "packed-refs", "remotes", "rr-cache", "svn", NULL + }; + static const char *copies[] = { + "HEAD", NULL + }; + + cl_git_pass(p_mkdir("alternate", 0777)); + cl_git_pass(p_mkdir("alternate/.git", 0777)); + + for (scan = links; *scan != NULL; scan++) { + git_buf_joinpath(&link_tgt, "empty_standard_repo/.git", *scan); + if (git_path_exists(link_tgt.ptr)) { + git_buf_joinpath(&link_tgt, "../../empty_standard_repo/.git", *scan); + git_buf_joinpath(&link, "alternate/.git", *scan); + if (strchr(*scan, '/')) + git_futils_mkpath2file(link.ptr, 0777); + cl_assert_(symlink(link_tgt.ptr, link.ptr) == 0, strerror(errno)); + } + } + for (scan = copies; *scan != NULL; scan++) { + git_buf_joinpath(&link_tgt, "empty_standard_repo/.git", *scan); + if (git_path_exists(link_tgt.ptr)) { + git_buf_joinpath(&link, "alternate/.git", *scan); + cl_git_pass(git_futils_readbuffer(&body, link_tgt.ptr)); + + cl_assert((link_fd = git_futils_creat_withpath(link.ptr, 0777, 0666)) >= 0); + cl_must_pass(p_write(link_fd, body.ptr, body.size)); + p_close(link_fd); + } + } + + git_buf_free(&link_tgt); + git_buf_free(&link); + git_buf_free(&body); + + + cl_git_pass(git_repository_open(&repo2, "alternate")); + + cl_assert(git_repository_path(repo2) != NULL); + cl_assert_(git__suffixcmp(git_repository_path(repo2), "alternate/.git/") == 0, git_repository_path(repo2)); + + cl_assert(git_repository_workdir(repo2) != NULL); + cl_assert_(git__suffixcmp(git_repository_workdir(repo2), "alternate/") == 0, git_repository_workdir(repo2)); + + git_repository_free(repo2); +#endif +} + +void test_repo_open__failures(void) +{ + git_repository *base, *repo; + git_buf ceiling = GIT_BUF_INIT; + + base = cl_git_sandbox_init("attr"); + cl_git_pass(git_buf_sets(&ceiling, git_repository_workdir(base))); + + /* fail with no searching */ + cl_git_fail(git_repository_open(&repo, "attr/sub")); + cl_git_fail(git_repository_open_ext( + &repo, "attr/sub", GIT_REPOSITORY_OPEN_NO_SEARCH, NULL)); + + /* fail with ceiling too low */ + cl_git_pass(git_buf_joinpath(&ceiling, ceiling.ptr, "sub")); + cl_git_fail(git_repository_open_ext(&repo, "attr/sub", 0, ceiling.ptr)); + + /* fail with no repo */ + cl_git_pass(p_mkdir("alternate", 0777)); + cl_git_pass(p_mkdir("alternate/.git", 0777)); + cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL)); + cl_git_fail(git_repository_open_ext(&repo, "alternate/.git", 0, NULL)); + + git_buf_free(&ceiling); +} + +void test_repo_open__bad_gitlinks(void) +{ + git_repository *repo; + static const char *bad_links[] = { + "garbage\n", "gitdir", "gitdir:\n", "gitdir: foobar", + "gitdir: ../invalid", "gitdir: ../invalid2", + "gitdir: ../attr/.git with extra stuff", + NULL + }; + const char **scan; + + cl_git_sandbox_init("attr"); + + cl_git_pass(p_mkdir("invalid", 0777)); + cl_git_pass(git_futils_mkdir_r("invalid2/.git", NULL, 0777)); + + for (scan = bad_links; *scan != NULL; scan++) { + make_gitlink_dir("alternate", *scan); + cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL)); + } + + git_futils_rmdir_r("invalid", NULL, GIT_RMDIR_REMOVE_FILES); + git_futils_rmdir_r("invalid2", NULL, GIT_RMDIR_REMOVE_FILES); +} + +#ifdef GIT_WIN32 +static void unposix_path(git_buf *path) +{ + char *src, *tgt; + + src = tgt = path->ptr; + + /* convert "/d/..." to "d:\..." */ + if (src[0] == '/' && isalpha(src[1]) && src[2] == '/') { + *tgt++ = src[1]; + *tgt++ = ':'; + *tgt++ = '\\'; + src += 3; + } + + while (*src) { + *tgt++ = (*src == '/') ? '\\' : *src; + src++; + } + + *tgt = '\0'; +} +#endif + +void test_repo_open__win32_path(void) +{ +#ifdef GIT_WIN32 + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"), *repo2; + git_buf winpath = GIT_BUF_INIT; + static const char *repo_path = "empty_standard_repo/.git/"; + static const char *repo_wd = "empty_standard_repo/"; + + cl_assert(git__suffixcmp(git_repository_path(repo), repo_path) == 0); + cl_assert(git__suffixcmp(git_repository_workdir(repo), repo_wd) == 0); + + cl_git_pass(git_buf_sets(&winpath, git_repository_path(repo))); + unposix_path(&winpath); + cl_git_pass(git_repository_open(&repo2, winpath.ptr)); + cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0); + cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0); + git_repository_free(repo2); + + cl_git_pass(git_buf_sets(&winpath, git_repository_path(repo))); + git_buf_truncate(&winpath, winpath.size - 1); /* remove trailing '/' */ + unposix_path(&winpath); + cl_git_pass(git_repository_open(&repo2, winpath.ptr)); + cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0); + cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0); + git_repository_free(repo2); + + cl_git_pass(git_buf_sets(&winpath, git_repository_workdir(repo))); + unposix_path(&winpath); + cl_git_pass(git_repository_open(&repo2, winpath.ptr)); + cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0); + cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0); + git_repository_free(repo2); + + cl_git_pass(git_buf_sets(&winpath, git_repository_workdir(repo))); + git_buf_truncate(&winpath, winpath.size - 1); /* remove trailing '/' */ + unposix_path(&winpath); + cl_git_pass(git_repository_open(&repo2, winpath.ptr)); + cl_assert(git__suffixcmp(git_repository_path(repo2), repo_path) == 0); + cl_assert(git__suffixcmp(git_repository_workdir(repo2), repo_wd) == 0); + git_repository_free(repo2); + + git_buf_free(&winpath); +#endif +} + +void test_repo_open__opening_a_non_existing_repository_returns_ENOTFOUND(void) +{ + git_repository *repo; + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_open(&repo, "i-do-not/exist")); +} + +void test_repo_open__no_config(void) +{ + git_buf path = GIT_BUF_INIT; + git_repository *repo; + git_config *config; + + cl_fixture_sandbox("empty_standard_repo"); + cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git")); + + /* remove local config */ + cl_git_pass(git_futils_rmdir_r( + "empty_standard_repo/.git/config", NULL, GIT_RMDIR_REMOVE_FILES)); + + /* isolate from system level configs */ + cl_must_pass(p_mkdir("alternate", 0777)); + cl_git_pass(git_path_prettify(&path, "alternate", NULL)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, path.ptr)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_XDG, path.ptr)); + + git_buf_free(&path); + + cl_git_pass(git_repository_open(&repo, "empty_standard_repo")); + cl_git_pass(git_repository_config(&config, repo)); + + cl_git_pass(git_config_set_string(config, "test.set", "42")); + + git_config_free(config); + git_repository_free(repo); + cl_fixture_cleanup("empty_standard_repo"); + + git_futils_dirs_global_shutdown(); +} + +void test_repo_open__force_bare(void) +{ + /* need to have both repo dir and workdir set up correctly */ + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + git_repository *barerepo; + + make_gitlink_dir("alternate", "gitdir: ../empty_standard_repo/.git"); + + cl_assert(!git_repository_is_bare(repo)); + + cl_git_pass(git_repository_open(&barerepo, "alternate")); + cl_assert(!git_repository_is_bare(barerepo)); + git_repository_free(barerepo); + + cl_git_pass(git_repository_open_bare( + &barerepo, "empty_standard_repo/.git")); + cl_assert(git_repository_is_bare(barerepo)); + git_repository_free(barerepo); + + cl_git_fail(git_repository_open_bare(&barerepo, "alternate/.git")); + + cl_git_pass(git_repository_open_ext( + &barerepo, "alternate/.git", GIT_REPOSITORY_OPEN_BARE, NULL)); + cl_assert(git_repository_is_bare(barerepo)); + git_repository_free(barerepo); + + cl_git_pass(p_mkdir("empty_standard_repo/subdir", 0777)); + cl_git_mkfile("empty_standard_repo/subdir/something.txt", "something"); + + cl_git_fail(git_repository_open_bare( + &barerepo, "empty_standard_repo/subdir")); + + cl_git_pass(git_repository_open_ext( + &barerepo, "empty_standard_repo/subdir", GIT_REPOSITORY_OPEN_BARE, NULL)); + cl_assert(git_repository_is_bare(barerepo)); + git_repository_free(barerepo); + + cl_git_pass(p_mkdir("alternate/subdir", 0777)); + cl_git_pass(p_mkdir("alternate/subdir/sub2", 0777)); + cl_git_mkfile("alternate/subdir/sub2/something.txt", "something"); + + cl_git_fail(git_repository_open_bare(&barerepo, "alternate/subdir/sub2")); + + cl_git_pass(git_repository_open_ext( + &barerepo, "alternate/subdir/sub2", GIT_REPOSITORY_OPEN_BARE, NULL)); + cl_assert(git_repository_is_bare(barerepo)); + git_repository_free(barerepo); +} diff --git a/tests/repo/pathspec.c b/tests/repo/pathspec.c new file mode 100644 index 000000000..334066b67 --- /dev/null +++ b/tests/repo/pathspec.c @@ -0,0 +1,385 @@ +#include "clar_libgit2.h" +#include "git2/pathspec.h" + +static git_repository *g_repo; + +void test_repo_pathspec__initialize(void) +{ + g_repo = cl_git_sandbox_init("status"); +} + +void test_repo_pathspec__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +static char *str0[] = { "*_file", "new_file", "garbage" }; +static char *str1[] = { "*_FILE", "NEW_FILE", "GARBAGE" }; +static char *str2[] = { "staged_*" }; +static char *str3[] = { "!subdir", "*_file", "new_file" }; +static char *str4[] = { "*" }; +static char *str5[] = { "S*" }; + +void test_repo_pathspec__workdir0(void) +{ + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "*_file", "new_file", "garbage" } */ + s.strings = str0; s.count = ARRAY_SIZE(str0); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, 0, ps)); + cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); + cl_assert_equal_s("garbage", git_pathspec_match_list_failed_entry(m, 0)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_FIND_FAILURES | GIT_PATHSPEC_FAILURES_ONLY, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); +} + +void test_repo_pathspec__workdir1(void) +{ + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "*_FILE", "NEW_FILE", "GARBAGE" } */ + s.strings = str1; s.count = ARRAY_SIZE(str1); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_IGNORE_CASE, ps)); + cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_USE_CASE, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_fail(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_USE_CASE | GIT_PATHSPEC_NO_MATCH_ERROR, ps)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_IGNORE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_USE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(3, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); +} + +void test_repo_pathspec__workdir2(void) +{ + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "staged_*" } */ + s.strings = str2; s.count = ARRAY_SIZE(str2); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, 0, ps)); + cl_assert_equal_sz(5, git_pathspec_match_list_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(5, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_fail(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_NO_GLOB | GIT_PATHSPEC_NO_MATCH_ERROR, ps)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_NO_GLOB | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); +} + +void test_repo_pathspec__workdir3(void) +{ + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "!subdir", "*_file", "new_file" } */ + s.strings = str3; s.count = ARRAY_SIZE(str3); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, 0, ps)); + cl_assert_equal_sz(7, git_pathspec_match_list_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, + GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(7, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + + cl_assert_equal_s("current_file", git_pathspec_match_list_entry(m, 0)); + cl_assert_equal_s("modified_file", git_pathspec_match_list_entry(m, 1)); + cl_assert_equal_s("new_file", git_pathspec_match_list_entry(m, 2)); + cl_assert_equal_s("staged_changes_modified_file", git_pathspec_match_list_entry(m, 3)); + cl_assert_equal_s("staged_delete_modified_file", git_pathspec_match_list_entry(m, 4)); + cl_assert_equal_s("staged_new_file", git_pathspec_match_list_entry(m, 5)); + cl_assert_equal_s("staged_new_file_modified_file", git_pathspec_match_list_entry(m, 6)); + cl_assert_equal_s(NULL, git_pathspec_match_list_entry(m, 7)); + + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); +} + +void test_repo_pathspec__workdir4(void) +{ + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "*" } */ + s.strings = str4; s.count = ARRAY_SIZE(str4); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_workdir(&m, g_repo, 0, ps)); + cl_assert_equal_sz(13, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_s("这", git_pathspec_match_list_entry(m, 12)); + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); +} + + +void test_repo_pathspec__index0(void) +{ + git_index *idx; + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + cl_git_pass(git_repository_index(&idx, g_repo)); + + /* { "*_file", "new_file", "garbage" } */ + s.strings = str0; s.count = ARRAY_SIZE(str0); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_index(&m, idx, 0, ps)); + cl_assert_equal_sz(9, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + cl_assert_equal_s("current_file", git_pathspec_match_list_entry(m, 0)); + cl_assert_equal_s("modified_file", git_pathspec_match_list_entry(m, 1)); + cl_assert_equal_s("staged_changes_modified_file", git_pathspec_match_list_entry(m, 2)); + cl_assert_equal_s("staged_new_file", git_pathspec_match_list_entry(m, 3)); + cl_assert_equal_s("staged_new_file_deleted_file", git_pathspec_match_list_entry(m, 4)); + cl_assert_equal_s("staged_new_file_modified_file", git_pathspec_match_list_entry(m, 5)); + cl_assert_equal_s("subdir/current_file", git_pathspec_match_list_entry(m, 6)); + cl_assert_equal_s("subdir/deleted_file", git_pathspec_match_list_entry(m, 7)); + cl_assert_equal_s("subdir/modified_file", git_pathspec_match_list_entry(m, 8)); + cl_assert_equal_s(NULL, git_pathspec_match_list_entry(m, 9)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_index(&m, idx, + GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(9, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(2, git_pathspec_match_list_failed_entrycount(m)); + cl_assert_equal_s("new_file", git_pathspec_match_list_failed_entry(m, 0)); + cl_assert_equal_s("garbage", git_pathspec_match_list_failed_entry(m, 1)); + cl_assert_equal_s(NULL, git_pathspec_match_list_failed_entry(m, 2)); + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); + git_index_free(idx); +} + +void test_repo_pathspec__index1(void) +{ + /* Currently the USE_CASE and IGNORE_CASE flags don't work on the + * index because the index sort order for the index iterator is + * set by the index itself. I think the correct fix is for the + * index not to embed a global sort order but to support traversal + * in either case sensitive or insensitive order in a stateless + * manner. + * + * Anyhow, as it is, there is no point in doing this test. + */ +#if 0 + git_index *idx; + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + cl_git_pass(git_repository_index(&idx, g_repo)); + + /* { "*_FILE", "NEW_FILE", "GARBAGE" } */ + s.strings = str1; s.count = ARRAY_SIZE(str1); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_pathspec_match_index(&m, idx, + GIT_PATHSPEC_USE_CASE, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_index(&m, idx, + GIT_PATHSPEC_USE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(3, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_index(&m, idx, + GIT_PATHSPEC_IGNORE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(10, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(2, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + git_pathspec_free(ps); + git_index_free(idx); +#endif +} + +void test_repo_pathspec__tree0(void) +{ + git_object *tree; + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "*_file", "new_file", "garbage" } */ + s.strings = str0; s.count = ARRAY_SIZE(str0); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_revparse_single(&tree, g_repo, "HEAD~2^{tree}")); + + cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, + GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(4, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_s("current_file", git_pathspec_match_list_entry(m, 0)); + cl_assert_equal_s("modified_file", git_pathspec_match_list_entry(m, 1)); + cl_assert_equal_s("staged_changes_modified_file", git_pathspec_match_list_entry(m, 2)); + cl_assert_equal_s("staged_delete_modified_file", git_pathspec_match_list_entry(m, 3)); + cl_assert_equal_s(NULL, git_pathspec_match_list_entry(m, 4)); + cl_assert_equal_sz(2, git_pathspec_match_list_failed_entrycount(m)); + cl_assert_equal_s("new_file", git_pathspec_match_list_failed_entry(m, 0)); + cl_assert_equal_s("garbage", git_pathspec_match_list_failed_entry(m, 1)); + cl_assert_equal_s(NULL, git_pathspec_match_list_failed_entry(m, 2)); + git_pathspec_match_list_free(m); + + git_object_free(tree); + + cl_git_pass(git_revparse_single(&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, + GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(7, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_s("current_file", git_pathspec_match_list_entry(m, 0)); + cl_assert_equal_s("modified_file", git_pathspec_match_list_entry(m, 1)); + cl_assert_equal_s("staged_changes_modified_file", git_pathspec_match_list_entry(m, 2)); + cl_assert_equal_s("staged_delete_modified_file", git_pathspec_match_list_entry(m, 3)); + cl_assert_equal_s("subdir/current_file", git_pathspec_match_list_entry(m, 4)); + cl_assert_equal_s("subdir/deleted_file", git_pathspec_match_list_entry(m, 5)); + cl_assert_equal_s("subdir/modified_file", git_pathspec_match_list_entry(m, 6)); + cl_assert_equal_s(NULL, git_pathspec_match_list_entry(m, 7)); + cl_assert_equal_sz(2, git_pathspec_match_list_failed_entrycount(m)); + cl_assert_equal_s("new_file", git_pathspec_match_list_failed_entry(m, 0)); + cl_assert_equal_s("garbage", git_pathspec_match_list_failed_entry(m, 1)); + cl_assert_equal_s(NULL, git_pathspec_match_list_failed_entry(m, 2)); + git_pathspec_match_list_free(m); + + git_object_free(tree); + + git_pathspec_free(ps); +} + +void test_repo_pathspec__tree5(void) +{ + git_object *tree; + git_strarray s; + git_pathspec *ps; + git_pathspec_match_list *m; + + /* { "S*" } */ + s.strings = str5; s.count = ARRAY_SIZE(str5); + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_git_pass(git_revparse_single(&tree, g_repo, "HEAD~2^{tree}")); + + cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, + GIT_PATHSPEC_USE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(0, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_sz(1, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, + GIT_PATHSPEC_IGNORE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(5, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_s("staged_changes", git_pathspec_match_list_entry(m, 0)); + cl_assert_equal_s("staged_delete_modified_file", git_pathspec_match_list_entry(m, 4)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + git_object_free(tree); + + cl_git_pass(git_revparse_single(&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(git_pathspec_match_tree(&m, (git_tree *)tree, + GIT_PATHSPEC_IGNORE_CASE | GIT_PATHSPEC_FIND_FAILURES, ps)); + cl_assert_equal_sz(9, git_pathspec_match_list_entrycount(m)); + cl_assert_equal_s("staged_changes", git_pathspec_match_list_entry(m, 0)); + cl_assert_equal_s("subdir.txt", git_pathspec_match_list_entry(m, 5)); + cl_assert_equal_s("subdir/current_file", git_pathspec_match_list_entry(m, 6)); + cl_assert_equal_sz(0, git_pathspec_match_list_failed_entrycount(m)); + git_pathspec_match_list_free(m); + + git_object_free(tree); + + git_pathspec_free(ps); +} + +void test_repo_pathspec__in_memory(void) +{ + static char *strings[] = { "one", "two*", "!three*", "*four" }; + git_strarray s = { strings, ARRAY_SIZE(strings) }; + git_pathspec *ps; + + cl_git_pass(git_pathspec_new(&ps, &s)); + + cl_assert(git_pathspec_matches_path(ps, 0, "one")); + cl_assert(!git_pathspec_matches_path(ps, 0, "ONE")); + cl_assert(git_pathspec_matches_path(ps, GIT_PATHSPEC_IGNORE_CASE, "ONE")); + cl_assert(git_pathspec_matches_path(ps, 0, "two")); + cl_assert(git_pathspec_matches_path(ps, 0, "two.txt")); + cl_assert(!git_pathspec_matches_path(ps, 0, "three.txt")); + cl_assert(git_pathspec_matches_path(ps, 0, "anything.four")); + cl_assert(!git_pathspec_matches_path(ps, 0, "three.four")); + cl_assert(!git_pathspec_matches_path(ps, 0, "nomatch")); + cl_assert(!git_pathspec_matches_path(ps, GIT_PATHSPEC_NO_GLOB, "two")); + cl_assert(git_pathspec_matches_path(ps, GIT_PATHSPEC_NO_GLOB, "two*")); + cl_assert(!git_pathspec_matches_path(ps, GIT_PATHSPEC_NO_GLOB, "anyfour")); + cl_assert(git_pathspec_matches_path(ps, GIT_PATHSPEC_NO_GLOB, "*four")); + + git_pathspec_free(ps); +} diff --git a/tests/repo/repo_helpers.c b/tests/repo/repo_helpers.c new file mode 100644 index 000000000..3d477ff42 --- /dev/null +++ b/tests/repo/repo_helpers.c @@ -0,0 +1,22 @@ +#include "clar_libgit2.h" +#include "refs.h" +#include "repo_helpers.h" +#include "posix.h" + +void make_head_unborn(git_repository* repo, const char *target) +{ + git_reference *head; + + cl_git_pass(git_reference_symbolic_create(&head, repo, GIT_HEAD_FILE, target, 1)); + git_reference_free(head); +} + +void delete_head(git_repository* repo) +{ + git_buf head_path = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&head_path, git_repository_path(repo), GIT_HEAD_FILE)); + cl_git_pass(p_unlink(git_buf_cstr(&head_path))); + + git_buf_free(&head_path); +} diff --git a/tests/repo/repo_helpers.h b/tests/repo/repo_helpers.h new file mode 100644 index 000000000..6783d5701 --- /dev/null +++ b/tests/repo/repo_helpers.h @@ -0,0 +1,6 @@ +#include "common.h" + +#define NON_EXISTING_HEAD "refs/heads/hide/and/seek" + +extern void make_head_unborn(git_repository* repo, const char *target); +extern void delete_head(git_repository* repo); diff --git a/tests/repo/setters.c b/tests/repo/setters.c new file mode 100644 index 000000000..f34f1e471 --- /dev/null +++ b/tests/repo/setters.c @@ -0,0 +1,107 @@ +#include "clar_libgit2.h" +#include "git2/sys/repository.h" + +#include "buffer.h" +#include "posix.h" +#include "util.h" +#include "path.h" +#include "fileops.h" + +static git_repository *repo; + +void test_repo_setters__initialize(void) +{ + cl_fixture_sandbox("testrepo.git"); + cl_git_pass(git_repository_open(&repo, "testrepo.git")); + cl_must_pass(p_mkdir("new_workdir", 0777)); +} + +void test_repo_setters__cleanup(void) +{ + git_repository_free(repo); + repo = NULL; + + cl_fixture_cleanup("testrepo.git"); + cl_fixture_cleanup("new_workdir"); +} + +void test_repo_setters__setting_a_workdir_turns_a_bare_repository_into_a_standard_one(void) +{ + cl_assert(git_repository_is_bare(repo) == 1); + + cl_assert(git_repository_workdir(repo) == NULL); + cl_git_pass(git_repository_set_workdir(repo, "./new_workdir", false)); + + cl_assert(git_repository_workdir(repo) != NULL); + cl_assert(git_repository_is_bare(repo) == 0); +} + +void test_repo_setters__setting_a_workdir_prettifies_its_path(void) +{ + cl_git_pass(git_repository_set_workdir(repo, "./new_workdir", false)); + + cl_assert(git__suffixcmp(git_repository_workdir(repo), "new_workdir/") == 0); +} + +void test_repo_setters__setting_a_workdir_creates_a_gitlink(void) +{ + git_config *cfg; + const char *val; + git_buf content = GIT_BUF_INIT; + + cl_git_pass(git_repository_set_workdir(repo, "./new_workdir", true)); + + cl_assert(git_path_isfile("./new_workdir/.git")); + + cl_git_pass(git_futils_readbuffer(&content, "./new_workdir/.git")); + cl_assert(git__prefixcmp(git_buf_cstr(&content), "gitdir: ") == 0); + cl_assert(git__suffixcmp(git_buf_cstr(&content), "testrepo.git/") == 0); + git_buf_free(&content); + + cl_git_pass(git_repository_config(&cfg, repo)); + cl_git_pass(git_config_get_string(&val, cfg, "core.worktree")); + cl_assert(git__suffixcmp(val, "new_workdir/") == 0); + git_config_free(cfg); +} + +void test_repo_setters__setting_a_new_index_on_a_repo_which_has_already_loaded_one_properly_honors_the_refcount(void) +{ + git_index *new_index; + + cl_git_pass(git_index_open(&new_index, "./my-index")); + cl_assert(((git_refcount *)new_index)->refcount.val == 1); + + git_repository_set_index(repo, new_index); + cl_assert(((git_refcount *)new_index)->refcount.val == 2); + + git_repository_free(repo); + cl_assert(((git_refcount *)new_index)->refcount.val == 1); + + git_index_free(new_index); + + /* + * Ensure the cleanup method won't try to free the repo as it's already been taken care of + */ + repo = NULL; +} + +void test_repo_setters__setting_a_new_odb_on_a_repo_which_already_loaded_one_properly_honors_the_refcount(void) +{ + git_odb *new_odb; + + cl_git_pass(git_odb_open(&new_odb, "./testrepo.git/objects")); + cl_assert(((git_refcount *)new_odb)->refcount.val == 1); + + git_repository_set_odb(repo, new_odb); + cl_assert(((git_refcount *)new_odb)->refcount.val == 2); + + git_repository_free(repo); + cl_assert(((git_refcount *)new_odb)->refcount.val == 1); + + git_odb_free(new_odb); + + /* + * Ensure the cleanup method won't try to free the repo as it's already been taken care of + */ + repo = NULL; +} diff --git a/tests/repo/shallow.c b/tests/repo/shallow.c new file mode 100644 index 000000000..1cc66ae40 --- /dev/null +++ b/tests/repo/shallow.c @@ -0,0 +1,33 @@ +#include "clar_libgit2.h" +#include "fileops.h" + +static git_repository *g_repo; + +void test_repo_shallow__initialize(void) +{ +} + +void test_repo_shallow__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_repo_shallow__no_shallow_file(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); +} + +void test_repo_shallow__empty_shallow_file(void) +{ + g_repo = cl_git_sandbox_init("testrepo.git"); + cl_git_mkfile("testrepo.git/shallow", ""); + cl_assert_equal_i(0, git_repository_is_shallow(g_repo)); +} + +void test_repo_shallow__shallow_repo(void) +{ + g_repo = cl_git_sandbox_init("shallow.git"); + cl_assert_equal_i(1, git_repository_is_shallow(g_repo)); +} + diff --git a/tests/repo/state.c b/tests/repo/state.c new file mode 100644 index 000000000..5a0a5f360 --- /dev/null +++ b/tests/repo/state.c @@ -0,0 +1,96 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "refs.h" +#include "posix.h" +#include "fileops.h" + +static git_repository *_repo; +static git_buf _path; + +void test_repo_state__initialize(void) +{ + _repo = cl_git_sandbox_init("testrepo.git"); +} + +void test_repo_state__cleanup(void) +{ + cl_git_sandbox_cleanup(); + git_buf_free(&_path); +} + +static void setup_simple_state(const char *filename) +{ + cl_git_pass(git_buf_joinpath(&_path, git_repository_path(_repo), filename)); + git_futils_mkpath2file(git_buf_cstr(&_path), 0777); + cl_git_mkfile(git_buf_cstr(&_path), "dummy"); +} + +static void assert_repo_state(git_repository_state_t state) +{ + cl_assert_equal_i(state, git_repository_state(_repo)); +} + +void test_repo_state__none_with_HEAD_attached(void) +{ + assert_repo_state(GIT_REPOSITORY_STATE_NONE); +} + +void test_repo_state__none_with_HEAD_detached(void) +{ + cl_git_pass(git_repository_detach_head(_repo)); + assert_repo_state(GIT_REPOSITORY_STATE_NONE); +} + +void test_repo_state__merge(void) +{ + setup_simple_state(GIT_MERGE_HEAD_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_MERGE); +} + +void test_repo_state__revert(void) +{ + setup_simple_state(GIT_REVERT_HEAD_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_REVERT); +} + +void test_repo_state__cherry_pick(void) +{ + setup_simple_state(GIT_CHERRY_PICK_HEAD_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_CHERRY_PICK); +} + +void test_repo_state__bisect(void) +{ + setup_simple_state(GIT_BISECT_LOG_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_BISECT); +} + +void test_repo_state__rebase_interactive(void) +{ + setup_simple_state(GIT_REBASE_MERGE_INTERACTIVE_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_REBASE_INTERACTIVE); +} + +void test_repo_state__rebase_merge(void) +{ + setup_simple_state(GIT_REBASE_MERGE_DIR "whatever"); + assert_repo_state(GIT_REPOSITORY_STATE_REBASE_MERGE); +} + +void test_repo_state__rebase(void) +{ + setup_simple_state(GIT_REBASE_APPLY_REBASING_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_REBASE); +} + +void test_repo_state__apply_mailbox(void) +{ + setup_simple_state(GIT_REBASE_APPLY_APPLYING_FILE); + assert_repo_state(GIT_REPOSITORY_STATE_APPLY_MAILBOX); +} + +void test_repo_state__apply_mailbox_or_rebase(void) +{ + setup_simple_state(GIT_REBASE_APPLY_DIR "whatever"); + assert_repo_state(GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE); +} diff --git a/tests/reset/default.c b/tests/reset/default.c new file mode 100644 index 000000000..e29e63550 --- /dev/null +++ b/tests/reset/default.c @@ -0,0 +1,180 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "reset_helpers.h" +#include "path.h" + +static git_repository *_repo; +static git_object *_target; +static git_strarray _pathspecs; +static git_index *_index; + +static void initialize(const char *repo_name) +{ + _repo = cl_git_sandbox_init(repo_name); + cl_git_pass(git_repository_index(&_index, _repo)); + + _target = NULL; + + _pathspecs.strings = NULL; + _pathspecs.count = 0; +} + +void test_reset_default__initialize(void) +{ + initialize("status"); +} + +void test_reset_default__cleanup(void) +{ + git_object_free(_target); + _target = NULL; + + git_index_free(_index); + _index = NULL; + + cl_git_sandbox_cleanup(); +} + +static void assert_content_in_index( + git_strarray *pathspecs, + bool should_exist, + git_strarray *expected_shas) +{ + size_t i, pos; + int error; + + for (i = 0; i < pathspecs->count; i++) { + error = git_index_find(&pos, _index, pathspecs->strings[i]); + + if (should_exist) { + const git_index_entry *entry; + + cl_assert(error != GIT_ENOTFOUND); + + entry = git_index_get_byindex(_index, pos); + cl_assert(entry != NULL); + + if (!expected_shas) + continue; + + cl_git_pass(git_oid_streq(&entry->oid, expected_shas->strings[i])); + } else + cl_assert_equal_i(should_exist, error != GIT_ENOTFOUND); + } +} + +void test_reset_default__resetting_filepaths_against_a_null_target_removes_them_from_the_index(void) +{ + char *paths[] = { "staged_changes", "staged_new_file" }; + + _pathspecs.strings = paths; + _pathspecs.count = 2; + + assert_content_in_index(&_pathspecs, true, NULL); + + cl_git_pass(git_reset_default(_repo, NULL, &_pathspecs)); + + assert_content_in_index(&_pathspecs, false, NULL); +} + +/* + * $ git ls-files --cached -s --abbrev=7 -- "staged*" + * 100644 55d316c 0 staged_changes + * 100644 a6be623 0 staged_changes_file_deleted + * ... + * + * $ git reset 0017bd4 -- staged_changes staged_changes_file_deleted + * Unstaged changes after reset: + * ... + * + * $ git ls-files --cached -s --abbrev=7 -- "staged*" + * 100644 32504b7 0 staged_changes + * 100644 061d42a 0 staged_changes_file_deleted + * ... + */ +void test_reset_default__resetting_filepaths_replaces_their_corresponding_index_entries(void) +{ + git_strarray before, after; + + char *paths[] = { "staged_changes", "staged_changes_file_deleted" }; + char *before_shas[] = { "55d316c9ba708999f1918e9677d01dfcae69c6b9", + "a6be623522ce87a1d862128ac42672604f7b468b" }; + char *after_shas[] = { "32504b727382542f9f089e24fddac5e78533e96c", + "061d42a44cacde5726057b67558821d95db96f19" }; + + _pathspecs.strings = paths; + _pathspecs.count = 2; + before.strings = before_shas; + before.count = 2; + after.strings = after_shas; + after.count = 2; + + cl_git_pass(git_revparse_single(&_target, _repo, "0017bd4")); + assert_content_in_index(&_pathspecs, true, &before); + + cl_git_pass(git_reset_default(_repo, _target, &_pathspecs)); + + assert_content_in_index(&_pathspecs, true, &after); +} + +/* + * $ git ls-files --cached -s --abbrev=7 -- conflicts-one.txt + * 100644 1f85ca5 1 conflicts-one.txt + * 100644 6aea5f2 2 conflicts-one.txt + * 100644 516bd85 3 conflicts-one.txt + * + * $ git reset 9a05ccb -- conflicts-one.txt + * Unstaged changes after reset: + * ... + * + * $ git ls-files --cached -s --abbrev=7 -- conflicts-one.txt + * 100644 1f85ca5 0 conflicts-one.txt + * + */ +void test_reset_default__resetting_filepaths_clears_previous_conflicts(void) +{ + const git_index_entry *conflict_entry[3]; + git_strarray after; + + char *paths[] = { "conflicts-one.txt" }; + char *after_shas[] = { "1f85ca51b8e0aac893a621b61a9c2661d6aa6d81" }; + + test_reset_default__cleanup(); + initialize("mergedrepo"); + + _pathspecs.strings = paths; + _pathspecs.count = 1; + after.strings = after_shas; + after.count = 1; + + cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], + &conflict_entry[2], _index, "conflicts-one.txt")); + + cl_git_pass(git_revparse_single(&_target, _repo, "9a05ccb")); + cl_git_pass(git_reset_default(_repo, _target, &_pathspecs)); + + assert_content_in_index(&_pathspecs, true, &after); + + cl_assert_equal_i(GIT_ENOTFOUND, git_index_conflict_get(&conflict_entry[0], + &conflict_entry[1], &conflict_entry[2], _index, "conflicts-one.txt")); +} + +/* +$ git reset HEAD -- "I_am_not_there.txt" "me_neither.txt" +Unstaged changes after reset: +... +*/ +void test_reset_default__resetting_unknown_filepaths_does_not_fail(void) +{ + char *paths[] = { "I_am_not_there.txt", "me_neither.txt" }; + + _pathspecs.strings = paths; + _pathspecs.count = 2; + + assert_content_in_index(&_pathspecs, false, NULL); + + cl_git_pass(git_revparse_single(&_target, _repo, "HEAD")); + cl_git_pass(git_reset_default(_repo, _target, &_pathspecs)); + + assert_content_in_index(&_pathspecs, false, NULL); +} diff --git a/tests/reset/hard.c b/tests/reset/hard.c new file mode 100644 index 000000000..1c0c84135 --- /dev/null +++ b/tests/reset/hard.c @@ -0,0 +1,200 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "reset_helpers.h" +#include "path.h" +#include "fileops.h" + +static git_repository *repo; +static git_object *target; + +void test_reset_hard__initialize(void) +{ + repo = cl_git_sandbox_init("status"); + target = NULL; +} + +void test_reset_hard__cleanup(void) +{ + if (target != NULL) { + git_object_free(target); + target = NULL; + } + + cl_git_sandbox_cleanup(); +} + +static int strequal_ignore_eol(const char *exp, const char *str) +{ + while (*exp && *str) { + if (*exp != *str) { + while (*exp == '\r' || *exp == '\n') ++exp; + while (*str == '\r' || *str == '\n') ++str; + if (*exp != *str) + return false; + } else { + exp++; str++; + } + } + return (!*exp && !*str); +} + +void test_reset_hard__resetting_reverts_modified_files(void) +{ + git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT; + int i; + static const char *files[4] = { + "current_file", + "modified_file", + "staged_new_file", + "staged_changes_modified_file" }; + static const char *before[4] = { + "current_file\n", + "modified_file\nmodified_file\n", + "staged_new_file\n", + "staged_changes_modified_file\nstaged_changes_modified_file\nstaged_changes_modified_file\n" + }; + static const char *after[4] = { + "current_file\n", + "modified_file\n", + NULL, + "staged_changes_modified_file\n" + }; + const char *wd = git_repository_workdir(repo); + + cl_assert(wd); + + for (i = 0; i < 4; ++i) { + cl_git_pass(git_buf_joinpath(&path, wd, files[i])); + cl_git_pass(git_futils_readbuffer(&content, path.ptr)); + cl_assert_equal_s(before[i], content.ptr); + } + + retrieve_target_from_oid( + &target, repo, "26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f"); + + cl_git_pass(git_reset(repo, target, GIT_RESET_HARD)); + + for (i = 0; i < 4; ++i) { + cl_git_pass(git_buf_joinpath(&path, wd, files[i])); + if (after[i]) { + cl_git_pass(git_futils_readbuffer(&content, path.ptr)); + cl_assert(strequal_ignore_eol(after[i], content.ptr)); + } else { + cl_assert(!git_path_exists(path.ptr)); + } + } + + git_buf_free(&content); + git_buf_free(&path); +} + +void test_reset_hard__cannot_reset_in_a_bare_repository(void) +{ + git_repository *bare; + + cl_git_pass(git_repository_open(&bare, cl_fixture("testrepo.git"))); + cl_assert(git_repository_is_bare(bare) == true); + + retrieve_target_from_oid(&target, bare, KNOWN_COMMIT_IN_BARE_REPO); + + cl_assert_equal_i(GIT_EBAREREPO, git_reset(bare, target, GIT_RESET_HARD)); + + git_repository_free(bare); +} + +static void index_entry_init(git_index *index, int side, git_oid *oid) +{ + git_index_entry entry; + + memset(&entry, 0x0, sizeof(git_index_entry)); + + entry.path = "conflicting_file"; + entry.flags = (side << GIT_IDXENTRY_STAGESHIFT); + entry.mode = 0100644; + git_oid_cpy(&entry.oid, oid); + + cl_git_pass(git_index_add(index, &entry)); +} + +static void unmerged_index_init(git_index *index, int entries) +{ + int write_ancestor = 1; + int write_ours = 2; + int write_theirs = 4; + git_oid ancestor, ours, theirs; + + git_oid_fromstr(&ancestor, "6bb0d9f700543ba3d318ba7075fc3bd696b4287b"); + git_oid_fromstr(&ours, "b19a1e93bec1317dc6097229e12afaffbfa74dc2"); + git_oid_fromstr(&theirs, "950b81b7eee953d050aa05a641f8e056c85dd1bd"); + + cl_git_rewritefile("status/conflicting_file", "conflicting file\n"); + + if (entries & write_ancestor) + index_entry_init(index, 1, &ancestor); + + if (entries & write_ours) + index_entry_init(index, 2, &ours); + + if (entries & write_theirs) + index_entry_init(index, 3, &theirs); +} + +void test_reset_hard__resetting_reverts_unmerged(void) +{ + git_index *index; + int entries; + + /* Ensure every permutation of non-zero stage entries results in the + * path being cleaned up. */ + for (entries = 1; entries < 8; entries++) { + cl_git_pass(git_repository_index(&index, repo)); + + unmerged_index_init(index, entries); + cl_git_pass(git_index_write(index)); + + retrieve_target_from_oid(&target, repo, "26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f"); + cl_git_pass(git_reset(repo, target, GIT_RESET_HARD)); + + cl_assert(git_path_exists("status/conflicting_file") == 0); + + git_object_free(target); + target = NULL; + + git_index_free(index); + } +} + +void test_reset_hard__cleans_up_merge(void) +{ + git_buf merge_head_path = GIT_BUF_INIT, + merge_msg_path = GIT_BUF_INIT, + merge_mode_path = GIT_BUF_INIT, + orig_head_path = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD")); + cl_git_mkfile(git_buf_cstr(&merge_head_path), "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef\n"); + + cl_git_pass(git_buf_joinpath(&merge_msg_path, git_repository_path(repo), "MERGE_MSG")); + cl_git_mkfile(git_buf_cstr(&merge_msg_path), "Merge commit 0017bd4ab1ec30440b17bae1680cff124ab5f1f6\n"); + + cl_git_pass(git_buf_joinpath(&merge_mode_path, git_repository_path(repo), "MERGE_MODE")); + cl_git_mkfile(git_buf_cstr(&merge_mode_path), ""); + + cl_git_pass(git_buf_joinpath(&orig_head_path, git_repository_path(repo), "ORIG_HEAD")); + cl_git_mkfile(git_buf_cstr(&orig_head_path), "0017bd4ab1ec30440b17bae1680cff124ab5f1f6"); + + retrieve_target_from_oid(&target, repo, "0017bd4ab1ec30440b17bae1680cff124ab5f1f6"); + cl_git_pass(git_reset(repo, target, GIT_RESET_HARD)); + + cl_assert(!git_path_exists(git_buf_cstr(&merge_head_path))); + cl_assert(!git_path_exists(git_buf_cstr(&merge_msg_path))); + cl_assert(!git_path_exists(git_buf_cstr(&merge_mode_path))); + + cl_assert(git_path_exists(git_buf_cstr(&orig_head_path))); + cl_git_pass(p_unlink(git_buf_cstr(&orig_head_path))); + + git_buf_free(&merge_head_path); + git_buf_free(&merge_msg_path); + git_buf_free(&merge_mode_path); + git_buf_free(&orig_head_path); +} diff --git a/tests/reset/mixed.c b/tests/reset/mixed.c new file mode 100644 index 000000000..7b90c23f1 --- /dev/null +++ b/tests/reset/mixed.c @@ -0,0 +1,49 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "reset_helpers.h" +#include "path.h" + +static git_repository *repo; +static git_object *target; + +void test_reset_mixed__initialize(void) +{ + repo = cl_git_sandbox_init("attr"); + target = NULL; +} + +void test_reset_mixed__cleanup(void) +{ + git_object_free(target); + target = NULL; + + cl_git_sandbox_cleanup(); +} + +void test_reset_mixed__cannot_reset_in_a_bare_repository(void) +{ + git_repository *bare; + + cl_git_pass(git_repository_open(&bare, cl_fixture("testrepo.git"))); + cl_assert(git_repository_is_bare(bare) == true); + + retrieve_target_from_oid(&target, bare, KNOWN_COMMIT_IN_BARE_REPO); + + cl_assert_equal_i(GIT_EBAREREPO, git_reset(bare, target, GIT_RESET_MIXED)); + + git_repository_free(bare); +} + +void test_reset_mixed__resetting_refreshes_the_index_to_the_commit_tree(void) +{ + unsigned int status; + + cl_git_pass(git_status_file(&status, repo, "macro_bad")); + cl_assert(status == GIT_STATUS_CURRENT); + retrieve_target_from_oid(&target, repo, "605812ab7fe421fdd325a935d35cb06a9234a7d7"); + + cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED)); + + cl_git_pass(git_status_file(&status, repo, "macro_bad")); + cl_assert(status == GIT_STATUS_WT_NEW); +} diff --git a/tests/reset/reset_helpers.c b/tests/reset/reset_helpers.c new file mode 100644 index 000000000..17edca4e9 --- /dev/null +++ b/tests/reset/reset_helpers.c @@ -0,0 +1,10 @@ +#include "clar_libgit2.h" +#include "reset_helpers.h" + +void retrieve_target_from_oid(git_object **object_out, git_repository *repo, const char *sha) +{ + git_oid oid; + + cl_git_pass(git_oid_fromstr(&oid, sha)); + cl_git_pass(git_object_lookup(object_out, repo, &oid, GIT_OBJ_ANY)); +} diff --git a/tests/reset/reset_helpers.h b/tests/reset/reset_helpers.h new file mode 100644 index 000000000..5dbe9d2c7 --- /dev/null +++ b/tests/reset/reset_helpers.h @@ -0,0 +1,6 @@ +#include "common.h" + +#define KNOWN_COMMIT_IN_BARE_REPO "e90810b8df3e80c413d903f631643c716887138d" +#define KNOWN_COMMIT_IN_ATTR_REPO "217878ab49e1314388ea2e32dc6fdb58a1b969e0" + +extern void retrieve_target_from_oid(git_object **object_out, git_repository *repo, const char *sha); diff --git a/tests/reset/soft.c b/tests/reset/soft.c new file mode 100644 index 000000000..bd6fcc205 --- /dev/null +++ b/tests/reset/soft.c @@ -0,0 +1,157 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "reset_helpers.h" +#include "path.h" +#include "repo/repo_helpers.h" + +static git_repository *repo; +static git_object *target; + +void test_reset_soft__initialize(void) +{ + repo = cl_git_sandbox_init("testrepo.git"); +} + +void test_reset_soft__cleanup(void) +{ + git_object_free(target); + target = NULL; + + cl_git_sandbox_cleanup(); +} + +static void assert_reset_soft(bool should_be_detached) +{ + git_oid oid; + + cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); + cl_git_fail(git_oid_streq(&oid, KNOWN_COMMIT_IN_BARE_REPO)); + + retrieve_target_from_oid(&target, repo, KNOWN_COMMIT_IN_BARE_REPO); + + cl_assert(git_repository_head_detached(repo) == should_be_detached); + + cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT)); + + cl_assert(git_repository_head_detached(repo) == should_be_detached); + + cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); + cl_git_pass(git_oid_streq(&oid, KNOWN_COMMIT_IN_BARE_REPO)); +} + +void test_reset_soft__can_reset_the_non_detached_Head_to_the_specified_commit(void) +{ + assert_reset_soft(false); +} + +void test_reset_soft__can_reset_the_detached_Head_to_the_specified_commit(void) +{ + git_repository_detach_head(repo); + + assert_reset_soft(true); +} + +void test_reset_soft__resetting_to_the_commit_pointed_at_by_the_Head_does_not_change_the_target_of_the_Head(void) +{ + git_oid oid; + char raw_head_oid[GIT_OID_HEXSZ + 1]; + + cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); + git_oid_fmt(raw_head_oid, &oid); + raw_head_oid[GIT_OID_HEXSZ] = '\0'; + + retrieve_target_from_oid(&target, repo, raw_head_oid); + + cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT)); + + cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); + cl_git_pass(git_oid_streq(&oid, raw_head_oid)); +} + +void test_reset_soft__resetting_to_a_tag_sets_the_Head_to_the_peeled_commit(void) +{ + git_oid oid; + + /* b25fa35 is a tag, pointing to another tag which points to commit e90810b */ + retrieve_target_from_oid(&target, repo, "b25fa35b38051e4ae45d4222e795f9df2e43f1d1"); + + cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT)); + + cl_assert(git_repository_head_detached(repo) == false); + cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); + cl_git_pass(git_oid_streq(&oid, KNOWN_COMMIT_IN_BARE_REPO)); +} + +void test_reset_soft__cannot_reset_to_a_tag_not_pointing_at_a_commit(void) +{ + /* 53fc32d is the tree of commit e90810b */ + retrieve_target_from_oid(&target, repo, "53fc32d17276939fc79ed05badaef2db09990016"); + + cl_git_fail(git_reset(repo, target, GIT_RESET_SOFT)); + git_object_free(target); + + /* 521d87c is an annotated tag pointing to a blob */ + retrieve_target_from_oid(&target, repo, "521d87c1ec3aef9824daf6d96cc0ae3710766d91"); + cl_git_fail(git_reset(repo, target, GIT_RESET_SOFT)); +} + +void test_reset_soft__resetting_against_an_unborn_head_repo_makes_the_head_no_longer_unborn(void) +{ + git_reference *head; + + retrieve_target_from_oid(&target, repo, KNOWN_COMMIT_IN_BARE_REPO); + + make_head_unborn(repo, NON_EXISTING_HEAD); + + cl_assert_equal_i(true, git_repository_head_unborn(repo)); + + cl_git_pass(git_reset(repo, target, GIT_RESET_SOFT)); + + cl_assert_equal_i(false, git_repository_head_unborn(repo)); + + cl_git_pass(git_reference_lookup(&head, repo, NON_EXISTING_HEAD)); + cl_assert_equal_i(0, git_oid_streq(git_reference_target(head), KNOWN_COMMIT_IN_BARE_REPO)); + + git_reference_free(head); +} + +void test_reset_soft__fails_when_merging(void) +{ + git_buf merge_head_path = GIT_BUF_INIT; + + cl_git_pass(git_repository_detach_head(repo)); + cl_git_pass(git_buf_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD")); + cl_git_mkfile(git_buf_cstr(&merge_head_path), "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef\n"); + + retrieve_target_from_oid(&target, repo, KNOWN_COMMIT_IN_BARE_REPO); + + cl_assert_equal_i(GIT_EUNMERGED, git_reset(repo, target, GIT_RESET_SOFT)); + cl_git_pass(p_unlink(git_buf_cstr(&merge_head_path))); + + git_buf_free(&merge_head_path); +} + +void test_reset_soft__fails_when_index_contains_conflicts_independently_of_MERGE_HEAD_file_existence(void) +{ + git_index *index; + git_reference *head; + git_buf merge_head_path = GIT_BUF_INIT; + + cl_git_sandbox_cleanup(); + + repo = cl_git_sandbox_init("mergedrepo"); + + cl_git_pass(git_buf_joinpath(&merge_head_path, git_repository_path(repo), "MERGE_HEAD")); + cl_git_pass(p_unlink(git_buf_cstr(&merge_head_path))); + git_buf_free(&merge_head_path); + + cl_git_pass(git_repository_index(&index, repo)); + cl_assert_equal_i(true, git_index_has_conflicts(index)); + git_index_free(index); + + cl_git_pass(git_repository_head(&head, repo)); + cl_git_pass(git_reference_peel(&target, head, GIT_OBJ_COMMIT)); + git_reference_free(head); + + cl_assert_equal_i(GIT_EUNMERGED, git_reset(repo, target, GIT_RESET_SOFT)); +} diff --git a/tests/resources/.gitattributes b/tests/resources/.gitattributes new file mode 100644 index 000000000..556f8c827 --- /dev/null +++ b/tests/resources/.gitattributes @@ -0,0 +1 @@ +* binary diff --git a/tests/resources/.gitignore b/tests/resources/.gitignore new file mode 100644 index 000000000..43a19cc9d --- /dev/null +++ b/tests/resources/.gitignore @@ -0,0 +1 @@ +discover.git diff --git a/tests/resources/attr/.gitted/HEAD b/tests/resources/attr/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/attr/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/attr/.gitted/config b/tests/resources/attr/.gitted/config new file mode 100644 index 000000000..af107929f --- /dev/null +++ b/tests/resources/attr/.gitted/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true diff --git a/tests/resources/attr/.gitted/description b/tests/resources/attr/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/attr/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/attr/.gitted/index b/tests/resources/attr/.gitted/index new file mode 100644 index 000000000..439ffb151 Binary files /dev/null and b/tests/resources/attr/.gitted/index differ diff --git a/tests/resources/attr/.gitted/info/attributes b/tests/resources/attr/.gitted/info/attributes new file mode 100644 index 000000000..5fe62a37a --- /dev/null +++ b/tests/resources/attr/.gitted/info/attributes @@ -0,0 +1,4 @@ +* repoattr +a* foo !bar -baz +sub/*.txt reposub +sub/sub/*.txt reposubsub diff --git a/tests/resources/attr/.gitted/info/exclude b/tests/resources/attr/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/attr/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/attr/.gitted/logs/HEAD b/tests/resources/attr/.gitted/logs/HEAD new file mode 100644 index 000000000..8ece39f37 --- /dev/null +++ b/tests/resources/attr/.gitted/logs/HEAD @@ -0,0 +1,9 @@ +0000000000000000000000000000000000000000 6bab5c79cd5140d0f800917f550eb2a3dc32b0da Russell Belfer 1324416995 -0800 commit (initial): initial test data +6bab5c79cd5140d0f800917f550eb2a3dc32b0da 605812ab7fe421fdd325a935d35cb06a9234a7d7 Russell Belfer 1325143098 -0800 commit: latest test updates +605812ab7fe421fdd325a935d35cb06a9234a7d7 a5d76cad53f66f1312bd995909a5bab3c0820770 Russell Belfer 1325281762 -0800 commit: more macro tests +a5d76cad53f66f1312bd995909a5bab3c0820770 370fe9ec224ce33e71f9e5ec2bd1142ce9937a6a Russell Belfer 1327611749 -0800 commit: Updating files so we can do diffs +370fe9ec224ce33e71f9e5ec2bd1142ce9937a6a f5b0af1fb4f5c0cd7aad880711d368a07333c307 Russell Belfer 1327621027 -0800 commit: Updating test data +f5b0af1fb4f5c0cd7aad880711d368a07333c307 a97cc019851d401a4f1d091cb91a15890a0dd1ba Russell Belfer 1328653313 -0800 commit: Some whitespace only changes for testing purposes +a97cc019851d401a4f1d091cb91a15890a0dd1ba 217878ab49e1314388ea2e32dc6fdb58a1b969e0 Russell Belfer 1332734901 -0700 commit: added files in sub/sub +217878ab49e1314388ea2e32dc6fdb58a1b969e0 24fa9a9fc4e202313e24b648087495441dab432b Russell Belfer 1332735555 -0700 commit: adding more files in sub for tree status +24fa9a9fc4e202313e24b648087495441dab432b 8d0b9df9bd30be7910ddda60548d485bc302b911 yorah 1341230701 +0200 commit: Updating test data so we can test inter-hunk-context diff --git a/tests/resources/attr/.gitted/logs/refs/heads/master b/tests/resources/attr/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..8ece39f37 --- /dev/null +++ b/tests/resources/attr/.gitted/logs/refs/heads/master @@ -0,0 +1,9 @@ +0000000000000000000000000000000000000000 6bab5c79cd5140d0f800917f550eb2a3dc32b0da Russell Belfer 1324416995 -0800 commit (initial): initial test data +6bab5c79cd5140d0f800917f550eb2a3dc32b0da 605812ab7fe421fdd325a935d35cb06a9234a7d7 Russell Belfer 1325143098 -0800 commit: latest test updates +605812ab7fe421fdd325a935d35cb06a9234a7d7 a5d76cad53f66f1312bd995909a5bab3c0820770 Russell Belfer 1325281762 -0800 commit: more macro tests +a5d76cad53f66f1312bd995909a5bab3c0820770 370fe9ec224ce33e71f9e5ec2bd1142ce9937a6a Russell Belfer 1327611749 -0800 commit: Updating files so we can do diffs +370fe9ec224ce33e71f9e5ec2bd1142ce9937a6a f5b0af1fb4f5c0cd7aad880711d368a07333c307 Russell Belfer 1327621027 -0800 commit: Updating test data +f5b0af1fb4f5c0cd7aad880711d368a07333c307 a97cc019851d401a4f1d091cb91a15890a0dd1ba Russell Belfer 1328653313 -0800 commit: Some whitespace only changes for testing purposes +a97cc019851d401a4f1d091cb91a15890a0dd1ba 217878ab49e1314388ea2e32dc6fdb58a1b969e0 Russell Belfer 1332734901 -0700 commit: added files in sub/sub +217878ab49e1314388ea2e32dc6fdb58a1b969e0 24fa9a9fc4e202313e24b648087495441dab432b Russell Belfer 1332735555 -0700 commit: adding more files in sub for tree status +24fa9a9fc4e202313e24b648087495441dab432b 8d0b9df9bd30be7910ddda60548d485bc302b911 yorah 1341230701 +0200 commit: Updating test data so we can test inter-hunk-context diff --git a/tests/resources/attr/.gitted/objects/10/8bb4e7fd7b16490dc33ff7d972151e73d7166e b/tests/resources/attr/.gitted/objects/10/8bb4e7fd7b16490dc33ff7d972151e73d7166e new file mode 100644 index 000000000..edcf7520c Binary files /dev/null and b/tests/resources/attr/.gitted/objects/10/8bb4e7fd7b16490dc33ff7d972151e73d7166e differ diff --git a/tests/resources/attr/.gitted/objects/16/983da6643656bb44c43965ecb6855c6d574512 b/tests/resources/attr/.gitted/objects/16/983da6643656bb44c43965ecb6855c6d574512 new file mode 100644 index 000000000..e49c94acd Binary files /dev/null and b/tests/resources/attr/.gitted/objects/16/983da6643656bb44c43965ecb6855c6d574512 differ diff --git a/tests/resources/attr/.gitted/objects/21/7878ab49e1314388ea2e32dc6fdb58a1b969e0 b/tests/resources/attr/.gitted/objects/21/7878ab49e1314388ea2e32dc6fdb58a1b969e0 new file mode 100644 index 000000000..b537899f2 --- /dev/null +++ b/tests/resources/attr/.gitted/objects/21/7878ab49e1314388ea2e32dc6fdb58a1b969e0 @@ -0,0 +1,4 @@ +xQ +0D)nD#xmvJ߀7cx0Iۺ -+e"v☝pwcJH1x%HL>Dd xC\ʤzᔶd0Z#mغڰ +y +>{qK \ No newline at end of file diff --git a/tests/resources/attr/.gitted/objects/24/fa9a9fc4e202313e24b648087495441dab432b b/tests/resources/attr/.gitted/objects/24/fa9a9fc4e202313e24b648087495441dab432b new file mode 100644 index 000000000..e7099bbaa Binary files /dev/null and b/tests/resources/attr/.gitted/objects/24/fa9a9fc4e202313e24b648087495441dab432b differ diff --git a/tests/resources/attr/.gitted/objects/29/29de282ce999e95183aedac6451d3384559c4b b/tests/resources/attr/.gitted/objects/29/29de282ce999e95183aedac6451d3384559c4b new file mode 100644 index 000000000..ad84f0854 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/29/29de282ce999e95183aedac6451d3384559c4b differ diff --git a/tests/resources/attr/.gitted/objects/2b/40c5aca159b04ea8d20ffe36cdf8b09369b14a b/tests/resources/attr/.gitted/objects/2b/40c5aca159b04ea8d20ffe36cdf8b09369b14a new file mode 100644 index 000000000..0e2368069 --- /dev/null +++ b/tests/resources/attr/.gitted/objects/2b/40c5aca159b04ea8d20ffe36cdf8b09369b14a @@ -0,0 +1 @@ +xmPj0=P8ZSc hR6{=ob"afv#3ά=7P%[8 yNlͣ>c;gӐkYX9b|D~Vؗ)vܕ \ No newline at end of file diff --git a/tests/resources/attr/.gitted/objects/2c/66e14f77196ea763fb1e41612c1aa2bc2d8ed2 b/tests/resources/attr/.gitted/objects/2c/66e14f77196ea763fb1e41612c1aa2bc2d8ed2 new file mode 100644 index 000000000..4b75d50eb Binary files /dev/null and b/tests/resources/attr/.gitted/objects/2c/66e14f77196ea763fb1e41612c1aa2bc2d8ed2 differ diff --git a/tests/resources/attr/.gitted/objects/2d/e7dfe3588f3c7e9ad59e7d50ba90e3329df9d9 b/tests/resources/attr/.gitted/objects/2d/e7dfe3588f3c7e9ad59e7d50ba90e3329df9d9 new file mode 100644 index 000000000..e0fd0468e Binary files /dev/null and b/tests/resources/attr/.gitted/objects/2d/e7dfe3588f3c7e9ad59e7d50ba90e3329df9d9 differ diff --git a/tests/resources/attr/.gitted/objects/37/0fe9ec224ce33e71f9e5ec2bd1142ce9937a6a b/tests/resources/attr/.gitted/objects/37/0fe9ec224ce33e71f9e5ec2bd1142ce9937a6a new file mode 100644 index 000000000..9c37c5946 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/37/0fe9ec224ce33e71f9e5ec2bd1142ce9937a6a differ diff --git a/tests/resources/attr/.gitted/objects/3a/6df026462ebafe455af9867d27eda20a9e0974 b/tests/resources/attr/.gitted/objects/3a/6df026462ebafe455af9867d27eda20a9e0974 new file mode 100644 index 000000000..c74add826 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/3a/6df026462ebafe455af9867d27eda20a9e0974 differ diff --git a/tests/resources/attr/.gitted/objects/3b/74db7ab381105dc0d28f8295a77f6a82989292 b/tests/resources/attr/.gitted/objects/3b/74db7ab381105dc0d28f8295a77f6a82989292 new file mode 100644 index 000000000..e5cef35fa Binary files /dev/null and b/tests/resources/attr/.gitted/objects/3b/74db7ab381105dc0d28f8295a77f6a82989292 differ diff --git a/tests/resources/attr/.gitted/objects/3e/42ffc54a663f9401cc25843d6c0e71a33e4249 b/tests/resources/attr/.gitted/objects/3e/42ffc54a663f9401cc25843d6c0e71a33e4249 new file mode 100644 index 000000000..091d79b14 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/3e/42ffc54a663f9401cc25843d6c0e71a33e4249 differ diff --git a/tests/resources/attr/.gitted/objects/45/141a79a77842c59a63229403220a4e4be74e3d b/tests/resources/attr/.gitted/objects/45/141a79a77842c59a63229403220a4e4be74e3d new file mode 100644 index 000000000..5b58ef024 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/45/141a79a77842c59a63229403220a4e4be74e3d differ diff --git a/tests/resources/attr/.gitted/objects/45/5a314fa848d52ae1f11d254da4f60858fc97f4 b/tests/resources/attr/.gitted/objects/45/5a314fa848d52ae1f11d254da4f60858fc97f4 new file mode 100644 index 000000000..f90f0d79c Binary files /dev/null and b/tests/resources/attr/.gitted/objects/45/5a314fa848d52ae1f11d254da4f60858fc97f4 differ diff --git a/tests/resources/attr/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests/resources/attr/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 new file mode 100644 index 000000000..7ca4ceed5 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 differ diff --git a/tests/resources/attr/.gitted/objects/4d/713dc48e6b1bd75b0d61ad078ba9ca3a56745d b/tests/resources/attr/.gitted/objects/4d/713dc48e6b1bd75b0d61ad078ba9ca3a56745d new file mode 100644 index 000000000..eb1e8d0c5 --- /dev/null +++ b/tests/resources/attr/.gitted/objects/4d/713dc48e6b1bd75b0d61ad078ba9ca3a56745d @@ -0,0 +1,2 @@ +x @WŶ +|k 9n$}g:;51e4\k_]ރ٭hDk'~ \ No newline at end of file diff --git a/tests/resources/attr/.gitted/objects/4e/49ba8c5b6c32ff28cd9dcb60be34df50fcc485 b/tests/resources/attr/.gitted/objects/4e/49ba8c5b6c32ff28cd9dcb60be34df50fcc485 new file mode 100644 index 000000000..6fcc549b4 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/4e/49ba8c5b6c32ff28cd9dcb60be34df50fcc485 differ diff --git a/tests/resources/attr/.gitted/objects/55/6f8c827b8e4a02ad5cab77dca2bcb3e226b0b3 b/tests/resources/attr/.gitted/objects/55/6f8c827b8e4a02ad5cab77dca2bcb3e226b0b3 new file mode 100644 index 000000000..4bcff1faa Binary files /dev/null and b/tests/resources/attr/.gitted/objects/55/6f8c827b8e4a02ad5cab77dca2bcb3e226b0b3 differ diff --git a/tests/resources/attr/.gitted/objects/58/19a185d77b03325aaf87cafc771db36f6ddca7 b/tests/resources/attr/.gitted/objects/58/19a185d77b03325aaf87cafc771db36f6ddca7 new file mode 100644 index 000000000..fe34eb63a Binary files /dev/null and b/tests/resources/attr/.gitted/objects/58/19a185d77b03325aaf87cafc771db36f6ddca7 differ diff --git a/tests/resources/attr/.gitted/objects/60/5812ab7fe421fdd325a935d35cb06a9234a7d7 b/tests/resources/attr/.gitted/objects/60/5812ab7fe421fdd325a935d35cb06a9234a7d7 new file mode 100644 index 000000000..b0cc51ee6 --- /dev/null +++ b/tests/resources/attr/.gitted/objects/60/5812ab7fe421fdd325a935d35cb06a9234a7d7 @@ -0,0 +1,2 @@ +xN 0;S˻BU J ?lٖygcáU RbacG;l㠝Dq֠ZʫAH<Ǒ3N=J2d3[0= +}ۤI™jM"x/[TwU&[/k(tJL \ No newline at end of file diff --git a/tests/resources/attr/.gitted/objects/6b/ab5c79cd5140d0f800917f550eb2a3dc32b0da b/tests/resources/attr/.gitted/objects/6b/ab5c79cd5140d0f800917f550eb2a3dc32b0da new file mode 100644 index 000000000..f51e11ccc --- /dev/null +++ b/tests/resources/attr/.gitted/objects/6b/ab5c79cd5140d0f800917f550eb2a3dc32b0da @@ -0,0 +1,3 @@ +x 0 E)@d'~@(#tQiQn޷(Pm"Ř2hs L+d{"{Z`u +O4Y[޷;@>MSOmʧh +* <- \ No newline at end of file diff --git a/tests/resources/attr/.gitted/objects/6d/968d62c89c7d9ea23a4c9a7b665d017c3d8ffd b/tests/resources/attr/.gitted/objects/6d/968d62c89c7d9ea23a4c9a7b665d017c3d8ffd new file mode 100644 index 000000000..e832241c9 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/6d/968d62c89c7d9ea23a4c9a7b665d017c3d8ffd differ diff --git a/tests/resources/attr/.gitted/objects/71/7fc31f6b84f9d6fc3a4edbca259d7fc92beee2 b/tests/resources/attr/.gitted/objects/71/7fc31f6b84f9d6fc3a4edbca259d7fc92beee2 new file mode 100644 index 000000000..a80265cac Binary files /dev/null and b/tests/resources/attr/.gitted/objects/71/7fc31f6b84f9d6fc3a4edbca259d7fc92beee2 differ diff --git a/tests/resources/attr/.gitted/objects/8d/0b9df9bd30be7910ddda60548d485bc302b911 b/tests/resources/attr/.gitted/objects/8d/0b9df9bd30be7910ddda60548d485bc302b911 new file mode 100644 index 000000000..3dcf088e4 --- /dev/null +++ b/tests/resources/attr/.gitted/objects/8d/0b9df9bd30be7910ddda60548d485bc302b911 @@ -0,0 +1 @@ +xKj1D)zoli _"hiK2LG!7ȪJ,EPXDS ] /)}/UwR. jp##:?:|;F9܋r=_ )ơN/A[l!q}<Lfx4H\\q֏cjT \ No newline at end of file diff --git a/tests/resources/attr/.gitted/objects/93/61f40bb97239cf55811892e14de2e344168ba1 b/tests/resources/attr/.gitted/objects/93/61f40bb97239cf55811892e14de2e344168ba1 new file mode 100644 index 000000000..4b57836cd Binary files /dev/null and b/tests/resources/attr/.gitted/objects/93/61f40bb97239cf55811892e14de2e344168ba1 differ diff --git a/tests/resources/attr/.gitted/objects/94/da4faa0a6bfb8ee6ccf7153801a69202b31857 b/tests/resources/attr/.gitted/objects/94/da4faa0a6bfb8ee6ccf7153801a69202b31857 new file mode 100644 index 000000000..a9ddf5d20 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/94/da4faa0a6bfb8ee6ccf7153801a69202b31857 differ diff --git a/tests/resources/attr/.gitted/objects/96/089fd31ce1d3ee2afb0ba09ba063066932f027 b/tests/resources/attr/.gitted/objects/96/089fd31ce1d3ee2afb0ba09ba063066932f027 new file mode 100644 index 000000000..efa62f912 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/96/089fd31ce1d3ee2afb0ba09ba063066932f027 differ diff --git a/tests/resources/attr/.gitted/objects/99/eae476896f4907224978b88e5ecaa6c5bb67a9 b/tests/resources/attr/.gitted/objects/99/eae476896f4907224978b88e5ecaa6c5bb67a9 new file mode 100644 index 000000000..8f5acc70a Binary files /dev/null and b/tests/resources/attr/.gitted/objects/99/eae476896f4907224978b88e5ecaa6c5bb67a9 differ diff --git a/tests/resources/attr/.gitted/objects/9e/5bdc47d6a80f2be0ea3049ad74231b94609242 b/tests/resources/attr/.gitted/objects/9e/5bdc47d6a80f2be0ea3049ad74231b94609242 new file mode 100644 index 000000000..d6385ec8d Binary files /dev/null and b/tests/resources/attr/.gitted/objects/9e/5bdc47d6a80f2be0ea3049ad74231b94609242 differ diff --git a/tests/resources/attr/.gitted/objects/9f/b40b6675dde60b5697afceae91b66d908c02d9 b/tests/resources/attr/.gitted/objects/9f/b40b6675dde60b5697afceae91b66d908c02d9 new file mode 100644 index 000000000..7663ad0ad Binary files /dev/null and b/tests/resources/attr/.gitted/objects/9f/b40b6675dde60b5697afceae91b66d908c02d9 differ diff --git a/tests/resources/attr/.gitted/objects/a0/f7217ae99f5ac3e88534f5cea267febc5fa85b b/tests/resources/attr/.gitted/objects/a0/f7217ae99f5ac3e88534f5cea267febc5fa85b new file mode 100644 index 000000000..985c2e281 --- /dev/null +++ b/tests/resources/attr/.gitted/objects/a0/f7217ae99f5ac3e88534f5cea267febc5fa85b @@ -0,0 +1 @@ +x510 E}?΀;S␈Ԯۓv8O'F:2r)( &޷9ZAѹr9l %3Eo.Vi!"ZB;u3Cm {.7Z4avfgBLEeP;NQڬBLAnŲI 5I)M6ZQ[ +h3e: + }u};|)z&pbq?3TJ13JX \ No newline at end of file diff --git a/tests/resources/attr/.gitted/objects/a9/7cc019851d401a4f1d091cb91a15890a0dd1ba b/tests/resources/attr/.gitted/objects/a9/7cc019851d401a4f1d091cb91a15890a0dd1ba new file mode 100644 index 000000000..1a7ec0c55 --- /dev/null +++ b/tests/resources/attr/.gitted/objects/a9/7cc019851d401a4f1d091cb91a15890a0dd1ba @@ -0,0 +1,2 @@ +xQj0 DS[hc;PJ( $q޾ޠ_3oIK+BtI|Lgƈ ŐR4'=qFN64 +J1FrzW[rV6-i7.eVW;X, mwl|]ṬMɢdRwC[W9sj~Wy \ No newline at end of file diff --git a/tests/resources/attr/.gitted/objects/b4/35cd5689a0fb54afbeda4ac20368aa480e8f04 b/tests/resources/attr/.gitted/objects/b4/35cd5689a0fb54afbeda4ac20368aa480e8f04 new file mode 100644 index 000000000..ffe3473f4 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/b4/35cd5689a0fb54afbeda4ac20368aa480e8f04 differ diff --git a/tests/resources/attr/.gitted/objects/c0/091889c0c77142b87a1fa5123a6398a61d33e7 b/tests/resources/attr/.gitted/objects/c0/091889c0c77142b87a1fa5123a6398a61d33e7 new file mode 100644 index 000000000..11dc63c79 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/c0/091889c0c77142b87a1fa5123a6398a61d33e7 differ diff --git a/tests/resources/attr/.gitted/objects/c4/85abe35abd4aa6fd83b076a78bbea9e2e7e06c b/tests/resources/attr/.gitted/objects/c4/85abe35abd4aa6fd83b076a78bbea9e2e7e06c new file mode 100644 index 000000000..58569ca0e Binary files /dev/null and b/tests/resources/attr/.gitted/objects/c4/85abe35abd4aa6fd83b076a78bbea9e2e7e06c differ diff --git a/tests/resources/attr/.gitted/objects/c7/aadd770d5907a8475c29e9ee21a27b88bf675d b/tests/resources/attr/.gitted/objects/c7/aadd770d5907a8475c29e9ee21a27b88bf675d new file mode 100644 index 000000000..39aedb7d9 Binary files /dev/null and b/tests/resources/attr/.gitted/objects/c7/aadd770d5907a8475c29e9ee21a27b88bf675d differ diff --git a/tests/resources/attr/.gitted/objects/c9/6bbb2c2557a8325ae1559e3ba79cdcecb23076 b/tests/resources/attr/.gitted/objects/c9/6bbb2c2557a8325ae1559e3ba79cdcecb23076 new file mode 100644 index 000000000..589f9ad31 --- /dev/null +++ b/tests/resources/attr/.gitted/objects/c9/6bbb2c2557a8325ae1559e3ba79cdcecb23076 @@ -0,0 +1,2 @@ +x5A +0D]SεouJ~L0ͯ)xcfp]OOΊcB 6!뢘ó{,U 1335817070 -0700 commit (initial): Initial commit +67c1640e91ccbaf0793591be09bf572cf40c9a53 d441d7d88f52c28c2b23940ce4c33756748425f9 Russell Belfer 1335817296 -0700 commit: Adding some files in subtrees +d441d7d88f52c28c2b23940ce4c33756748425f9 67c1640e91ccbaf0793591be09bf572cf40c9a53 Russell Belfer 1335817353 -0700 HEAD^: updating HEAD +67c1640e91ccbaf0793591be09bf572cf40c9a53 58f7cf825b553ef7c26e5b9f8a23599c1a9ca296 Russell Belfer 1335817372 -0700 commit: Adding subtree data diff --git a/tests/resources/attr_index/.gitted/logs/refs/heads/master b/tests/resources/attr_index/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..ffd298c04 --- /dev/null +++ b/tests/resources/attr_index/.gitted/logs/refs/heads/master @@ -0,0 +1,4 @@ +0000000000000000000000000000000000000000 67c1640e91ccbaf0793591be09bf572cf40c9a53 Russell Belfer 1335817070 -0700 commit (initial): Initial commit +67c1640e91ccbaf0793591be09bf572cf40c9a53 d441d7d88f52c28c2b23940ce4c33756748425f9 Russell Belfer 1335817296 -0700 commit: Adding some files in subtrees +d441d7d88f52c28c2b23940ce4c33756748425f9 67c1640e91ccbaf0793591be09bf572cf40c9a53 Russell Belfer 1335817353 -0700 HEAD^: updating HEAD +67c1640e91ccbaf0793591be09bf572cf40c9a53 58f7cf825b553ef7c26e5b9f8a23599c1a9ca296 Russell Belfer 1335817372 -0700 commit: Adding subtree data diff --git a/tests/resources/attr_index/.gitted/objects/38/12cfef36615db1788d4e63f90028007e17a348 b/tests/resources/attr_index/.gitted/objects/38/12cfef36615db1788d4e63f90028007e17a348 new file mode 100644 index 000000000..ee2991571 --- /dev/null +++ b/tests/resources/attr_index/.gitted/objects/38/12cfef36615db1788d4e63f90028007e17a348 @@ -0,0 +1,3 @@ +x[ + E*@PJ +]&`w 'oMKDq45DF#!!=VZD.L:%L}!dCg*qв-LUkz~6閷W}}>g˾{f% G \ No newline at end of file diff --git a/tests/resources/attr_index/.gitted/objects/59/d942b8be2784bc96db9b22202c10815c9a077b b/tests/resources/attr_index/.gitted/objects/59/d942b8be2784bc96db9b22202c10815c9a077b new file mode 100644 index 000000000..ff33737db --- /dev/null +++ b/tests/resources/attr_index/.gitted/objects/59/d942b8be2784bc96db9b22202c10815c9a077b @@ -0,0 +1 @@ +x 0 @@kR@]m)49d-#mgwTK@ \ No newline at end of file diff --git a/tests/resources/blametest.git/objects/63/eb57322e363e18d460da5ea8284f3cd2340b36 b/tests/resources/blametest.git/objects/63/eb57322e363e18d460da5ea8284f3cd2340b36 new file mode 100644 index 000000000..c6c285eeb Binary files /dev/null and b/tests/resources/blametest.git/objects/63/eb57322e363e18d460da5ea8284f3cd2340b36 differ diff --git a/tests/resources/blametest.git/objects/8b/137891791fe96927ad78e64b0aad7bded08bdc b/tests/resources/blametest.git/objects/8b/137891791fe96927ad78e64b0aad7bded08bdc new file mode 100644 index 000000000..9d8f60531 Binary files /dev/null and b/tests/resources/blametest.git/objects/8b/137891791fe96927ad78e64b0aad7bded08bdc differ diff --git a/tests/resources/blametest.git/objects/96/679d59cf9f74d69b3c920f258559b5e8c9a18a b/tests/resources/blametest.git/objects/96/679d59cf9f74d69b3c920f258559b5e8c9a18a new file mode 100644 index 000000000..d716e3b03 Binary files /dev/null and b/tests/resources/blametest.git/objects/96/679d59cf9f74d69b3c920f258559b5e8c9a18a differ diff --git a/tests/resources/blametest.git/objects/98/89d6e5557761aa8e3607e80c874a6dc51ada7c b/tests/resources/blametest.git/objects/98/89d6e5557761aa8e3607e80c874a6dc51ada7c new file mode 100644 index 000000000..12407f662 Binary files /dev/null and b/tests/resources/blametest.git/objects/98/89d6e5557761aa8e3607e80c874a6dc51ada7c differ diff --git a/tests/resources/blametest.git/objects/aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 b/tests/resources/blametest.git/objects/aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 new file mode 100644 index 000000000..bc13badb1 --- /dev/null +++ b/tests/resources/blametest.git/objects/aa/06ecca6c4ad6432ab9313e556ca92ba4bcf9e9 @@ -0,0 +1 @@ +xK0 DYu6I%P9'ǡ]ޟ"NI#3L vo{R-e1#B0}s9xR6d1SZx#dj&F #AGK?Kg2r \ No newline at end of file diff --git a/tests/resources/blametest.git/objects/bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 b/tests/resources/blametest.git/objects/bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 new file mode 100644 index 000000000..4e6ad159e --- /dev/null +++ b/tests/resources/blametest.git/objects/bc/7c5ac2bafe828a68e9d1d460343718d6fbe136 @@ -0,0 +1,3 @@ +xAn0 {+t))JA3<^Gn@$H\;MoѬƤ \ No newline at end of file diff --git a/tests/resources/blametest.git/objects/da/237394e6132d20d30f175b9b73c8638fddddda b/tests/resources/blametest.git/objects/da/237394e6132d20d30f175b9b73c8638fddddda new file mode 100644 index 000000000..e9e13833f --- /dev/null +++ b/tests/resources/blametest.git/objects/da/237394e6132d20d30f175b9b73c8638fddddda @@ -0,0 +1,4 @@ +xK +0@]J|'"$vVbz :Sj)ifёDNS dObs[ޱAb( +Y;f([ +ո%85qK'Y (zF8b@vKc?S \ No newline at end of file diff --git a/tests/resources/blametest.git/objects/e5/b41c1ea533f87388ab69b13baf0b5a562d6243 b/tests/resources/blametest.git/objects/e5/b41c1ea533f87388ab69b13baf0b5a562d6243 new file mode 100644 index 000000000..7e5586c2b Binary files /dev/null and b/tests/resources/blametest.git/objects/e5/b41c1ea533f87388ab69b13baf0b5a562d6243 differ diff --git a/tests/resources/blametest.git/objects/ef/32df4d259143933715c74951f932d9892364d1 b/tests/resources/blametest.git/objects/ef/32df4d259143933715c74951f932d9892364d1 new file mode 100644 index 000000000..d021ccfde Binary files /dev/null and b/tests/resources/blametest.git/objects/ef/32df4d259143933715c74951f932d9892364d1 differ diff --git a/tests/resources/blametest.git/refs/heads/master b/tests/resources/blametest.git/refs/heads/master new file mode 100644 index 000000000..b763025d8 --- /dev/null +++ b/tests/resources/blametest.git/refs/heads/master @@ -0,0 +1 @@ +bc7c5ac2bafe828a68e9d1d460343718d6fbe136 diff --git a/tests/resources/config/.gitconfig b/tests/resources/config/.gitconfig new file mode 100644 index 000000000..fa72bddfc --- /dev/null +++ b/tests/resources/config/.gitconfig @@ -0,0 +1,3 @@ +[core] + repositoryformatversion = 5 + something = 2 \ No newline at end of file diff --git a/tests/resources/config/config-include b/tests/resources/config/config-include new file mode 100644 index 000000000..6b5e79de7 --- /dev/null +++ b/tests/resources/config/config-include @@ -0,0 +1,2 @@ +[include] + path = config-included diff --git a/tests/resources/config/config-included b/tests/resources/config/config-included new file mode 100644 index 000000000..089ca08a7 --- /dev/null +++ b/tests/resources/config/config-included @@ -0,0 +1,2 @@ +[foo "bar"] + baz = huzzah diff --git a/tests/resources/config/config0 b/tests/resources/config/config0 new file mode 100644 index 000000000..85235c501 --- /dev/null +++ b/tests/resources/config/config0 @@ -0,0 +1,7 @@ +# This is a test +; of different comments +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true \ No newline at end of file diff --git a/tests/resources/config/config1 b/tests/resources/config/config1 new file mode 100644 index 000000000..211dc9e7d --- /dev/null +++ b/tests/resources/config/config1 @@ -0,0 +1,5 @@ +# This one checks for case sensitivity +[this "that"] + other = true +[this "That"] + other = yes diff --git a/tests/resources/config/config10 b/tests/resources/config/config10 new file mode 100644 index 000000000..dde17911b --- /dev/null +++ b/tests/resources/config/config10 @@ -0,0 +1 @@ +[empty] diff --git a/tests/resources/config/config11 b/tests/resources/config/config11 new file mode 100644 index 000000000..1d8a74470 --- /dev/null +++ b/tests/resources/config/config11 @@ -0,0 +1,5 @@ +[remote "ab"] + url = git://github.com/libgit2/libgit2 + url = git://git.example.com/libgit2 + + diff --git a/tests/resources/config/config12 b/tests/resources/config/config12 new file mode 100644 index 000000000..b57a81b08 --- /dev/null +++ b/tests/resources/config/config12 @@ -0,0 +1,7 @@ +[some "section"] + test = hi ; comment + other = "hello! \" ; ; ; " ; more test + multi = "hi, this is a ; \ +multiline comment # with ;\n special chars \ +and other stuff !@#" + back = "this is \ba phrase" diff --git a/tests/resources/config/config13 b/tests/resources/config/config13 new file mode 100644 index 000000000..c1e0c5647 --- /dev/null +++ b/tests/resources/config/config13 @@ -0,0 +1,2 @@ +[core] + editor = \"C:/Program Files/Nonsense/bah.exe\" \"--some option\" diff --git a/tests/resources/config/config14 b/tests/resources/config/config14 new file mode 100644 index 000000000..ef2198c45 --- /dev/null +++ b/tests/resources/config/config14 @@ -0,0 +1,4 @@ +[a] + b=c +[d] + e = f diff --git a/tests/resources/config/config15 b/tests/resources/config/config15 new file mode 100644 index 000000000..6d34f817b --- /dev/null +++ b/tests/resources/config/config15 @@ -0,0 +1,3 @@ +[core] + dummy2 = 7 + global = 17 diff --git a/tests/resources/config/config16 b/tests/resources/config/config16 new file mode 100644 index 000000000..f25cdb728 --- /dev/null +++ b/tests/resources/config/config16 @@ -0,0 +1,3 @@ +[core] + dummy2 = 28 + system = 11 diff --git a/tests/resources/config/config17 b/tests/resources/config/config17 new file mode 100644 index 000000000..ca25a86af --- /dev/null +++ b/tests/resources/config/config17 @@ -0,0 +1,3 @@ +[core] + dummy2 = 7 + global = 17 \ No newline at end of file diff --git a/tests/resources/config/config18 b/tests/resources/config/config18 new file mode 100644 index 000000000..cb6fd5ebc --- /dev/null +++ b/tests/resources/config/config18 @@ -0,0 +1,5 @@ +[core] + int32global = 28 + int64global = 9223372036854775803 + boolglobal = true + stringglobal = I'm a global config value! \ No newline at end of file diff --git a/tests/resources/config/config19 b/tests/resources/config/config19 new file mode 100644 index 000000000..f3ae5a640 --- /dev/null +++ b/tests/resources/config/config19 @@ -0,0 +1,5 @@ +[core] + int32global = -1 + int64global = -2 + boolglobal = false + stringglobal = don't find me! \ No newline at end of file diff --git a/tests/resources/config/config2 b/tests/resources/config/config2 new file mode 100644 index 000000000..60a389827 --- /dev/null +++ b/tests/resources/config/config2 @@ -0,0 +1,5 @@ +; This one tests for multiline values +[this "That"] + and = one one one \ +two two \ +three three \ No newline at end of file diff --git a/tests/resources/config/config20 b/tests/resources/config/config20 new file mode 100644 index 000000000..8f0f12c4c --- /dev/null +++ b/tests/resources/config/config20 @@ -0,0 +1,11 @@ +[valid "[subsection]"] + something = a +; we don't allow anything after closing " +[sec "[subsec]/child"] + parent = grand +[sec2 "[subsec2]/child2"] + type = dvcs +[sec3 "escape\"quote"] + vcs = git +[sec4 "escaping\\slash"] + lib = git2 diff --git a/tests/resources/config/config3 b/tests/resources/config/config3 new file mode 100644 index 000000000..44a5e50ea --- /dev/null +++ b/tests/resources/config/config3 @@ -0,0 +1,3 @@ +# A [section.subsection] header is case-insensitive +[section.SuBsection] + var = hello diff --git a/tests/resources/config/config4 b/tests/resources/config/config4 new file mode 100644 index 000000000..9dd40419e --- /dev/null +++ b/tests/resources/config/config4 @@ -0,0 +1,5 @@ +# A variable name on its own is valid +[some.section] + variable +# A variable and '=' is accepted, but it's not considered true + variableeq = diff --git a/tests/resources/config/config5 b/tests/resources/config/config5 new file mode 100644 index 000000000..8ab60ccec --- /dev/null +++ b/tests/resources/config/config5 @@ -0,0 +1,9 @@ +# Test for number suffixes +[number] + simple = 1 + k = 1k + kk = 1K + m = 1m + mm = 1M + g = 1g + gg = 1G diff --git a/tests/resources/config/config6 b/tests/resources/config/config6 new file mode 100644 index 000000000..0f8f90ac9 --- /dev/null +++ b/tests/resources/config/config6 @@ -0,0 +1,5 @@ +[valid "subsection"] + something = true + +[something "else"] + something = false diff --git a/tests/resources/config/config7 b/tests/resources/config/config7 new file mode 100644 index 000000000..6af6fcf25 --- /dev/null +++ b/tests/resources/config/config7 @@ -0,0 +1,5 @@ +[valid "subsection"] + something = a +; we don't allow anything after closing " +[sec "subsec"x] + bleh = blah diff --git a/tests/resources/config/config8 b/tests/resources/config/config8 new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/config/config9 b/tests/resources/config/config9 new file mode 100644 index 000000000..fcaac424e --- /dev/null +++ b/tests/resources/config/config9 @@ -0,0 +1,9 @@ +[core] + dummy2 = 42 + verylong = 1 + dummy = 1 + +[remote "ab"] + url = http://example.com/git/ab +[remote "abba"] + url = http://example.com/git/abba diff --git a/tests/resources/crlf/.gitted/HEAD b/tests/resources/crlf/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/crlf/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/crlf/.gitted/config b/tests/resources/crlf/.gitted/config new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/crlf/.gitted/objects/04/de00b358f13389948756732158eaaaefa1448c b/tests/resources/crlf/.gitted/objects/04/de00b358f13389948756732158eaaaefa1448c new file mode 100644 index 000000000..c3b7598c0 Binary files /dev/null and b/tests/resources/crlf/.gitted/objects/04/de00b358f13389948756732158eaaaefa1448c differ diff --git a/tests/resources/crlf/.gitted/objects/0a/a76e474d259bd7c13eb726a1396c381db55c88 b/tests/resources/crlf/.gitted/objects/0a/a76e474d259bd7c13eb726a1396c381db55c88 new file mode 100644 index 000000000..e118d6656 Binary files /dev/null and b/tests/resources/crlf/.gitted/objects/0a/a76e474d259bd7c13eb726a1396c381db55c88 differ diff --git a/tests/resources/crlf/.gitted/objects/0d/06894e14df22e066763ae906e0ed3eb79c205f b/tests/resources/crlf/.gitted/objects/0d/06894e14df22e066763ae906e0ed3eb79c205f new file mode 100644 index 000000000..b7a1f3290 Binary files /dev/null and b/tests/resources/crlf/.gitted/objects/0d/06894e14df22e066763ae906e0ed3eb79c205f differ diff --git a/tests/resources/crlf/.gitted/objects/0f/f5a53f19bfd2b5eea1ba550295c47515678987 b/tests/resources/crlf/.gitted/objects/0f/f5a53f19bfd2b5eea1ba550295c47515678987 new file mode 100644 index 000000000..5366acd8c Binary files /dev/null and b/tests/resources/crlf/.gitted/objects/0f/f5a53f19bfd2b5eea1ba550295c47515678987 differ diff --git a/tests/resources/crlf/.gitted/objects/12/faf3c1ea55f572473cec9052fca468c3584ccb b/tests/resources/crlf/.gitted/objects/12/faf3c1ea55f572473cec9052fca468c3584ccb new file mode 100644 index 000000000..96d5b2f91 --- /dev/null +++ b/tests/resources/crlf/.gitted/objects/12/faf3c1ea55f572473cec9052fca468c3584ccb @@ -0,0 +1 @@ +x 1}Nۀ,b6K6`.ؾQoab-A0dXbtnr:0cy(*Y 1347559804 -0700 commit (initial): initial commit +d70d245ed97ed2aa596dd1af6536e4bfdb047b69 7a9e0b02e63179929fed24f0a3e0f19168114d10 Russell Belfer 1347560491 -0700 commit: some changes diff --git a/tests/resources/diff/.gitted/logs/refs/heads/master b/tests/resources/diff/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..8c6f6fd18 --- /dev/null +++ b/tests/resources/diff/.gitted/logs/refs/heads/master @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 d70d245ed97ed2aa596dd1af6536e4bfdb047b69 Russell Belfer 1347559804 -0700 commit (initial): initial commit +d70d245ed97ed2aa596dd1af6536e4bfdb047b69 7a9e0b02e63179929fed24f0a3e0f19168114d10 Russell Belfer 1347560491 -0700 commit: some changes diff --git a/tests/resources/diff/.gitted/objects/29/ab7053bb4dde0298e03e2c179e890b7dd465a7 b/tests/resources/diff/.gitted/objects/29/ab7053bb4dde0298e03e2c179e890b7dd465a7 new file mode 100644 index 000000000..94f9a676d Binary files /dev/null and b/tests/resources/diff/.gitted/objects/29/ab7053bb4dde0298e03e2c179e890b7dd465a7 differ diff --git a/tests/resources/diff/.gitted/objects/3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847 b/tests/resources/diff/.gitted/objects/3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847 new file mode 100644 index 000000000..9fed523dc Binary files /dev/null and b/tests/resources/diff/.gitted/objects/3e/5bcbad2a68e5bc60a53b8388eea53a1a7ab847 differ diff --git a/tests/resources/diff/.gitted/objects/54/6c735f16a3b44d9784075c2c0dab2ac9bf1989 b/tests/resources/diff/.gitted/objects/54/6c735f16a3b44d9784075c2c0dab2ac9bf1989 new file mode 100644 index 000000000..d7df4d6a1 Binary files /dev/null and b/tests/resources/diff/.gitted/objects/54/6c735f16a3b44d9784075c2c0dab2ac9bf1989 differ diff --git a/tests/resources/diff/.gitted/objects/7a/9e0b02e63179929fed24f0a3e0f19168114d10 b/tests/resources/diff/.gitted/objects/7a/9e0b02e63179929fed24f0a3e0f19168114d10 new file mode 100644 index 000000000..9bc25eb34 Binary files /dev/null and b/tests/resources/diff/.gitted/objects/7a/9e0b02e63179929fed24f0a3e0f19168114d10 differ diff --git a/tests/resources/diff/.gitted/objects/7b/808f723a8ca90df319682c221187235af76693 b/tests/resources/diff/.gitted/objects/7b/808f723a8ca90df319682c221187235af76693 new file mode 100644 index 000000000..2fd266be6 Binary files /dev/null and b/tests/resources/diff/.gitted/objects/7b/808f723a8ca90df319682c221187235af76693 differ diff --git a/tests/resources/diff/.gitted/objects/88/789109439c1e1c3cd45224001edee5304ed53c b/tests/resources/diff/.gitted/objects/88/789109439c1e1c3cd45224001edee5304ed53c new file mode 100644 index 000000000..7598b5914 --- /dev/null +++ b/tests/resources/diff/.gitted/objects/88/789109439c1e1c3cd45224001edee5304ed53c @@ -0,0 +1 @@ +x+)JMU07g040031QH/H-+(a)[wz {j%;ʊRSrS4W4そN+a \ No newline at end of file diff --git a/tests/resources/diff/.gitted/objects/cb/8294e696339863df760b2ff5d1e275bee72455 b/tests/resources/diff/.gitted/objects/cb/8294e696339863df760b2ff5d1e275bee72455 new file mode 100644 index 000000000..86ebe04fe Binary files /dev/null and b/tests/resources/diff/.gitted/objects/cb/8294e696339863df760b2ff5d1e275bee72455 differ diff --git a/tests/resources/diff/.gitted/objects/d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69 b/tests/resources/diff/.gitted/objects/d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69 new file mode 100644 index 000000000..99304c4aa --- /dev/null +++ b/tests/resources/diff/.gitted/objects/d7/0d245ed97ed2aa596dd1af6536e4bfdb047b69 @@ -0,0 +1 @@ +x !m_RB:XkVpWp 9{ ,^z#7JygԚA i1Y2VyR)𢒨'm[;-lO_#%v8 \ No newline at end of file diff --git a/tests/resources/diff/.gitted/refs/heads/master b/tests/resources/diff/.gitted/refs/heads/master new file mode 100644 index 000000000..a83afc38b --- /dev/null +++ b/tests/resources/diff/.gitted/refs/heads/master @@ -0,0 +1 @@ +7a9e0b02e63179929fed24f0a3e0f19168114d10 diff --git a/tests/resources/diff/another.txt b/tests/resources/diff/another.txt new file mode 100644 index 000000000..d0e0bae4d --- /dev/null +++ b/tests/resources/diff/another.txt @@ -0,0 +1,38 @@ +Git is fast. With Git, nearly all operations are performed locally, giving +it an huge speed advantage on centralized systems that constantly have to +communicate with a server somewh3r3. + +For testing, large AWS instances were set up in the same availability +zone. Git and SVN were installed on both machines, the Ruby repository was +copied to both Git and SVN servers, and common operations were performed on +both. + +In some cases the commands don't match up exactly. Here, matching on the +lowest common denominator was attempted. For example, the 'commit' tests +also include the time to push for Git, though most of the time you would not +actually be pushing to the server immediately after a commit where the two +commands cannot be separated in SVN. + +Note that this is the best case scenario for SVN - a server with no load +with an 80MB/s bandwidth connection to the client machine. Nearly all of +these times would be even worse for SVN if that connection was slower, while +many of the Git times would not be affected. + +Clearly, in many of these common version control operations, Git is one or +two orders of magnitude faster than SVN, even under ideal conditions for +SVN. + +Let's see how common operations stack up against Subversion, a common +centralized version control system that is similar to CVS or +Perforce. Smaller is faster. + +One place where Git is slower is in the initial clone operation. Here, Git +One place where Git is slower is in the initial clone operation. Here, Git +One place where Git is slower is in the initial clone operation. Here, Git +seen in the above charts, it's not considerably slower for an operation that +is only performed once. + +It's also interesting to note that the size of the data on the client side +is very similar even though Git also has every version of every file for the +entire history of the project. This illustrates how efficient it is at +compressing and storing data on the client side. \ No newline at end of file diff --git a/tests/resources/diff/readme.txt b/tests/resources/diff/readme.txt new file mode 100644 index 000000000..beedf288d --- /dev/null +++ b/tests/resources/diff/readme.txt @@ -0,0 +1,36 @@ +The Git feature that r3ally mak3s it stand apart from n3arly 3v3ry other SCM +out there is its branching model. + +Git allows and encourages you to have multiple local branches that can be +entirely independent of each other. The creation, merging, and deletion of +those lines of development takes seconds. + +Git allows and encourages you to have multiple local branches that can be +entirely independent of each other. The creation, merging, and deletion of +those lines of development takes seconds. + +This means that you can do things like: + +Role-Bas3d Codelin3s. Have a branch that always contains only what goes to +production, another that you merge work into for testing, and several +smaller ones for day to day work. + +Feature Based Workflow. Create new branches for each new feature you're +working on so you can seamlessly switch back and forth between them, then +delete each branch when that feature gets merged into your main line. + +Disposable Experimentation. Create a branch to experiment in, realize it's +not going to work, and just delete it - abandoning the work—with nobody else +ever seeing it (even if you've pushed other branches in the meantime). + +Notably, when you push to a remote repository, you do not have to push all +share it with others. + +Git allows and encourages you to have multiple local branches that can be +entirely independent of each other. The creation, merging, and deletion of +those lines of development takes seconds. + +There are ways to accomplish some of this with other systems, but the work +involved is much more difficult and error-prone. Git makes this process +incredibly easy and it changes the way most developers work when they learn +it.! diff --git a/tests/resources/duplicate.git/COMMIT_EDITMSG b/tests/resources/duplicate.git/COMMIT_EDITMSG new file mode 100644 index 000000000..01f9a2aac --- /dev/null +++ b/tests/resources/duplicate.git/COMMIT_EDITMSG @@ -0,0 +1 @@ +commit diff --git a/tests/resources/duplicate.git/HEAD b/tests/resources/duplicate.git/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/duplicate.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/duplicate.git/config b/tests/resources/duplicate.git/config new file mode 100644 index 000000000..a4ef456cb --- /dev/null +++ b/tests/resources/duplicate.git/config @@ -0,0 +1,5 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true + logallrefupdates = true diff --git a/tests/resources/duplicate.git/description b/tests/resources/duplicate.git/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/duplicate.git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/duplicate.git/index b/tests/resources/duplicate.git/index new file mode 100644 index 000000000..a61e1c5ca Binary files /dev/null and b/tests/resources/duplicate.git/index differ diff --git a/tests/resources/duplicate.git/info/exclude b/tests/resources/duplicate.git/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/duplicate.git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/duplicate.git/info/refs b/tests/resources/duplicate.git/info/refs new file mode 100644 index 000000000..3b5bb03be --- /dev/null +++ b/tests/resources/duplicate.git/info/refs @@ -0,0 +1 @@ +8d2f05c97ef29a4697b37c30fe81c248ef411a23 refs/heads/master diff --git a/tests/resources/duplicate.git/logs/HEAD b/tests/resources/duplicate.git/logs/HEAD new file mode 100644 index 000000000..be9b4c6cb --- /dev/null +++ b/tests/resources/duplicate.git/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 8d2f05c97ef29a4697b37c30fe81c248ef411a23 Han-Wen Nienhuys 1336844322 -0300 commit (initial): commit diff --git a/tests/resources/duplicate.git/logs/refs/heads/master b/tests/resources/duplicate.git/logs/refs/heads/master new file mode 100644 index 000000000..be9b4c6cb --- /dev/null +++ b/tests/resources/duplicate.git/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 8d2f05c97ef29a4697b37c30fe81c248ef411a23 Han-Wen Nienhuys 1336844322 -0300 commit (initial): commit diff --git a/tests/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea b/tests/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea new file mode 100644 index 000000000..47c2a631a Binary files /dev/null and b/tests/resources/duplicate.git/objects/0d/deadede9e6d6ccddce0ee1e5749eed0485e5ea differ diff --git a/tests/resources/duplicate.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a b/tests/resources/duplicate.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a new file mode 100644 index 000000000..6802d4949 Binary files /dev/null and b/tests/resources/duplicate.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a differ diff --git a/tests/resources/duplicate.git/objects/info/packs b/tests/resources/duplicate.git/objects/info/packs new file mode 100644 index 000000000..d0fdf905e --- /dev/null +++ b/tests/resources/duplicate.git/objects/info/packs @@ -0,0 +1,3 @@ +P pack-e87994ad581c9af946de0eb890175c08cd005f38.pack +P pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack + diff --git a/tests/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx b/tests/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx new file mode 100644 index 000000000..acbed82b6 Binary files /dev/null and b/tests/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.idx differ diff --git a/tests/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack b/tests/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack new file mode 100644 index 000000000..652b0c91f Binary files /dev/null and b/tests/resources/duplicate.git/objects/pack/pack-29a4896f0a0b9c9947b0927c57a5c03dcae052e3.pack differ diff --git a/tests/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx b/tests/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx new file mode 100644 index 000000000..fff685554 Binary files /dev/null and b/tests/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.idx differ diff --git a/tests/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack b/tests/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack new file mode 100644 index 000000000..e3e5f0e09 Binary files /dev/null and b/tests/resources/duplicate.git/objects/pack/pack-b18eeacbd65cbd30a365d7564b45a468e8bd43d6.pack differ diff --git a/tests/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.idx b/tests/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.idx new file mode 100644 index 000000000..fd8abee98 Binary files /dev/null and b/tests/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.idx differ diff --git a/tests/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.pack b/tests/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.pack new file mode 100644 index 000000000..9879e0869 Binary files /dev/null and b/tests/resources/duplicate.git/objects/pack/pack-e87994ad581c9af946de0eb890175c08cd005f38.pack differ diff --git a/tests/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx b/tests/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx new file mode 100644 index 000000000..9f78f6e0f Binary files /dev/null and b/tests/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.idx differ diff --git a/tests/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack b/tests/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack new file mode 100644 index 000000000..d1dd3b61a Binary files /dev/null and b/tests/resources/duplicate.git/objects/pack/pack-f4ef1aa326265de7d05018ee51acc0a8717fe1ea.pack differ diff --git a/tests/resources/duplicate.git/packed-refs b/tests/resources/duplicate.git/packed-refs new file mode 100644 index 000000000..9f0d4e434 --- /dev/null +++ b/tests/resources/duplicate.git/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +8d2f05c97ef29a4697b37c30fe81c248ef411a23 refs/heads/master diff --git a/tests/resources/duplicate.git/refs/heads/dummy-marker.txt b/tests/resources/duplicate.git/refs/heads/dummy-marker.txt new file mode 100644 index 000000000..421376db9 --- /dev/null +++ b/tests/resources/duplicate.git/refs/heads/dummy-marker.txt @@ -0,0 +1 @@ +dummy diff --git a/tests/resources/empty_bare.git/HEAD b/tests/resources/empty_bare.git/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/empty_bare.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/empty_bare.git/config b/tests/resources/empty_bare.git/config new file mode 100644 index 000000000..90e16477b --- /dev/null +++ b/tests/resources/empty_bare.git/config @@ -0,0 +1,7 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = true + symlinks = false + ignorecase = true + hideDotFiles = dotGitOnly diff --git a/tests/resources/empty_bare.git/description b/tests/resources/empty_bare.git/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/empty_bare.git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/empty_bare.git/info/exclude b/tests/resources/empty_bare.git/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/empty_bare.git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/empty_bare.git/objects/info/dummy-marker.txt b/tests/resources/empty_bare.git/objects/info/dummy-marker.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/empty_bare.git/objects/pack/dummy-marker.txt b/tests/resources/empty_bare.git/objects/pack/dummy-marker.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/empty_bare.git/refs/heads/dummy-marker.txt b/tests/resources/empty_bare.git/refs/heads/dummy-marker.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/empty_bare.git/refs/tags/dummy-marker.txt b/tests/resources/empty_bare.git/refs/tags/dummy-marker.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/empty_standard_repo/.gitted/HEAD b/tests/resources/empty_standard_repo/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/empty_standard_repo/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/empty_standard_repo/.gitted/config b/tests/resources/empty_standard_repo/.gitted/config new file mode 100644 index 000000000..78387c50b --- /dev/null +++ b/tests/resources/empty_standard_repo/.gitted/config @@ -0,0 +1,8 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + symlinks = false + ignorecase = true + hideDotFiles = dotGitOnly diff --git a/tests/resources/empty_standard_repo/.gitted/description b/tests/resources/empty_standard_repo/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/empty_standard_repo/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/empty_standard_repo/.gitted/info/exclude b/tests/resources/empty_standard_repo/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/empty_standard_repo/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/empty_standard_repo/.gitted/objects/info/dummy-marker.txt b/tests/resources/empty_standard_repo/.gitted/objects/info/dummy-marker.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/empty_standard_repo/.gitted/objects/pack/dummy-marker.txt b/tests/resources/empty_standard_repo/.gitted/objects/pack/dummy-marker.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/empty_standard_repo/.gitted/refs/heads/dummy-marker.txt b/tests/resources/empty_standard_repo/.gitted/refs/heads/dummy-marker.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/empty_standard_repo/.gitted/refs/tags/dummy-marker.txt b/tests/resources/empty_standard_repo/.gitted/refs/tags/dummy-marker.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/filemodes/.gitted/HEAD b/tests/resources/filemodes/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/filemodes/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/filemodes/.gitted/config b/tests/resources/filemodes/.gitted/config new file mode 100644 index 000000000..af107929f --- /dev/null +++ b/tests/resources/filemodes/.gitted/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true diff --git a/tests/resources/filemodes/.gitted/description b/tests/resources/filemodes/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/filemodes/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/filemodes/.gitted/index b/tests/resources/filemodes/.gitted/index new file mode 100644 index 000000000..b1b175a9b Binary files /dev/null and b/tests/resources/filemodes/.gitted/index differ diff --git a/tests/resources/filemodes/.gitted/info/exclude b/tests/resources/filemodes/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/filemodes/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/filemodes/.gitted/logs/HEAD b/tests/resources/filemodes/.gitted/logs/HEAD new file mode 100644 index 000000000..1cb6a84c1 --- /dev/null +++ b/tests/resources/filemodes/.gitted/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 9962c8453ba6f0cf8dac7c5dcc2fa2897fa9964a Russell Belfer 1338847682 -0700 commit (initial): Initial commit of test data diff --git a/tests/resources/filemodes/.gitted/logs/refs/heads/master b/tests/resources/filemodes/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..1cb6a84c1 --- /dev/null +++ b/tests/resources/filemodes/.gitted/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 9962c8453ba6f0cf8dac7c5dcc2fa2897fa9964a Russell Belfer 1338847682 -0700 commit (initial): Initial commit of test data diff --git a/tests/resources/filemodes/.gitted/objects/99/62c8453ba6f0cf8dac7c5dcc2fa2897fa9964a b/tests/resources/filemodes/.gitted/objects/99/62c8453ba6f0cf8dac7c5dcc2fa2897fa9964a new file mode 100644 index 000000000..cbd2b557a Binary files /dev/null and b/tests/resources/filemodes/.gitted/objects/99/62c8453ba6f0cf8dac7c5dcc2fa2897fa9964a differ diff --git a/tests/resources/filemodes/.gitted/objects/a5/c5dd0fc6c313159a69b1d19d7f61a9f978e8f1 b/tests/resources/filemodes/.gitted/objects/a5/c5dd0fc6c313159a69b1d19d7f61a9f978e8f1 new file mode 100644 index 000000000..a9eaf2cba Binary files /dev/null and b/tests/resources/filemodes/.gitted/objects/a5/c5dd0fc6c313159a69b1d19d7f61a9f978e8f1 differ diff --git a/tests/resources/filemodes/.gitted/objects/e7/48d196331bcb20267eaaee4ff3326cb73b8182 b/tests/resources/filemodes/.gitted/objects/e7/48d196331bcb20267eaaee4ff3326cb73b8182 new file mode 100644 index 000000000..98066029c Binary files /dev/null and b/tests/resources/filemodes/.gitted/objects/e7/48d196331bcb20267eaaee4ff3326cb73b8182 differ diff --git a/tests/resources/filemodes/.gitted/refs/heads/master b/tests/resources/filemodes/.gitted/refs/heads/master new file mode 100644 index 000000000..9822d2d3f --- /dev/null +++ b/tests/resources/filemodes/.gitted/refs/heads/master @@ -0,0 +1 @@ +9962c8453ba6f0cf8dac7c5dcc2fa2897fa9964a diff --git a/tests/resources/filemodes/exec_off b/tests/resources/filemodes/exec_off new file mode 100644 index 000000000..a5c5dd0fc --- /dev/null +++ b/tests/resources/filemodes/exec_off @@ -0,0 +1 @@ +Howdy diff --git a/tests/resources/filemodes/exec_off2on_staged b/tests/resources/filemodes/exec_off2on_staged new file mode 100755 index 000000000..a5c5dd0fc --- /dev/null +++ b/tests/resources/filemodes/exec_off2on_staged @@ -0,0 +1 @@ +Howdy diff --git a/tests/resources/filemodes/exec_off2on_workdir b/tests/resources/filemodes/exec_off2on_workdir new file mode 100755 index 000000000..a5c5dd0fc --- /dev/null +++ b/tests/resources/filemodes/exec_off2on_workdir @@ -0,0 +1 @@ +Howdy diff --git a/tests/resources/filemodes/exec_off_untracked b/tests/resources/filemodes/exec_off_untracked new file mode 100644 index 000000000..a5c5dd0fc --- /dev/null +++ b/tests/resources/filemodes/exec_off_untracked @@ -0,0 +1 @@ +Howdy diff --git a/tests/resources/filemodes/exec_on b/tests/resources/filemodes/exec_on new file mode 100755 index 000000000..a5c5dd0fc --- /dev/null +++ b/tests/resources/filemodes/exec_on @@ -0,0 +1 @@ +Howdy diff --git a/tests/resources/filemodes/exec_on2off_staged b/tests/resources/filemodes/exec_on2off_staged new file mode 100644 index 000000000..a5c5dd0fc --- /dev/null +++ b/tests/resources/filemodes/exec_on2off_staged @@ -0,0 +1 @@ +Howdy diff --git a/tests/resources/filemodes/exec_on2off_workdir b/tests/resources/filemodes/exec_on2off_workdir new file mode 100644 index 000000000..a5c5dd0fc --- /dev/null +++ b/tests/resources/filemodes/exec_on2off_workdir @@ -0,0 +1 @@ +Howdy diff --git a/tests/resources/filemodes/exec_on_untracked b/tests/resources/filemodes/exec_on_untracked new file mode 100755 index 000000000..a5c5dd0fc --- /dev/null +++ b/tests/resources/filemodes/exec_on_untracked @@ -0,0 +1 @@ +Howdy diff --git a/tests/resources/gitgit.index b/tests/resources/gitgit.index new file mode 100644 index 000000000..215da649e Binary files /dev/null and b/tests/resources/gitgit.index differ diff --git a/tests/resources/icase/.gitted/HEAD b/tests/resources/icase/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/icase/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/icase/.gitted/config b/tests/resources/icase/.gitted/config new file mode 100644 index 000000000..bb4d11c1f --- /dev/null +++ b/tests/resources/icase/.gitted/config @@ -0,0 +1,7 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true + precomposeunicode = false diff --git a/tests/resources/icase/.gitted/description b/tests/resources/icase/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/icase/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/icase/.gitted/index b/tests/resources/icase/.gitted/index new file mode 100644 index 000000000..f8288ec13 Binary files /dev/null and b/tests/resources/icase/.gitted/index differ diff --git a/tests/resources/icase/.gitted/info/exclude b/tests/resources/icase/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/icase/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/icase/.gitted/logs/HEAD b/tests/resources/icase/.gitted/logs/HEAD new file mode 100644 index 000000000..3b16bd163 --- /dev/null +++ b/tests/resources/icase/.gitted/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 76d6e1d231b1085fcce151427e9899335de74be6 Russell Belfer 1359157123 -0800 commit (initial): initial commit diff --git a/tests/resources/icase/.gitted/logs/refs/heads/master b/tests/resources/icase/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..3b16bd163 --- /dev/null +++ b/tests/resources/icase/.gitted/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 76d6e1d231b1085fcce151427e9899335de74be6 Russell Belfer 1359157123 -0800 commit (initial): initial commit diff --git a/tests/resources/icase/.gitted/objects/3e/257c57f136a1cb8f2b8e9a2e5bc8ec0258bdce b/tests/resources/icase/.gitted/objects/3e/257c57f136a1cb8f2b8e9a2e5bc8ec0258bdce new file mode 100644 index 000000000..10691c788 Binary files /dev/null and b/tests/resources/icase/.gitted/objects/3e/257c57f136a1cb8f2b8e9a2e5bc8ec0258bdce differ diff --git a/tests/resources/icase/.gitted/objects/4d/d6027d083575c7431396dc2a3174afeb393c93 b/tests/resources/icase/.gitted/objects/4d/d6027d083575c7431396dc2a3174afeb393c93 new file mode 100644 index 000000000..8ca70df17 Binary files /dev/null and b/tests/resources/icase/.gitted/objects/4d/d6027d083575c7431396dc2a3174afeb393c93 differ diff --git a/tests/resources/icase/.gitted/objects/62/e0af52c199ec731fe4ad230041cd3286192d49 b/tests/resources/icase/.gitted/objects/62/e0af52c199ec731fe4ad230041cd3286192d49 new file mode 100644 index 000000000..e264aeab3 Binary files /dev/null and b/tests/resources/icase/.gitted/objects/62/e0af52c199ec731fe4ad230041cd3286192d49 differ diff --git a/tests/resources/icase/.gitted/objects/76/d6e1d231b1085fcce151427e9899335de74be6 b/tests/resources/icase/.gitted/objects/76/d6e1d231b1085fcce151427e9899335de74be6 new file mode 100644 index 000000000..24a4b3ee3 --- /dev/null +++ b/tests/resources/icase/.gitted/objects/76/d6e1d231b1085fcce151427e9899335de74be6 @@ -0,0 +1,3 @@ +x 1ENӀc XdƉ&/usԛ8}2 SH, +am1ЋEѷ9CJ$ nܷA +bଃjO_SO9%)9 \ No newline at end of file diff --git a/tests/resources/icase/.gitted/objects/d4/4e18fb93b7107b5cd1b95d601591d77869a1b6 b/tests/resources/icase/.gitted/objects/d4/4e18fb93b7107b5cd1b95d601591d77869a1b6 new file mode 100644 index 000000000..32d8c499f Binary files /dev/null and b/tests/resources/icase/.gitted/objects/d4/4e18fb93b7107b5cd1b95d601591d77869a1b6 differ diff --git a/tests/resources/icase/.gitted/refs/heads/master b/tests/resources/icase/.gitted/refs/heads/master new file mode 100644 index 000000000..37410ec2a --- /dev/null +++ b/tests/resources/icase/.gitted/refs/heads/master @@ -0,0 +1 @@ +76d6e1d231b1085fcce151427e9899335de74be6 diff --git a/tests/resources/icase/B b/tests/resources/icase/B new file mode 100644 index 000000000..d44e18fb9 --- /dev/null +++ b/tests/resources/icase/B @@ -0,0 +1 @@ +start diff --git a/tests/resources/icase/D b/tests/resources/icase/D new file mode 100644 index 000000000..d44e18fb9 --- /dev/null +++ b/tests/resources/icase/D @@ -0,0 +1 @@ +start diff --git a/tests/resources/icase/F b/tests/resources/icase/F new file mode 100644 index 000000000..d44e18fb9 --- /dev/null +++ b/tests/resources/icase/F @@ -0,0 +1 @@ +start diff --git a/tests/resources/icase/H b/tests/resources/icase/H new file mode 100644 index 000000000..d44e18fb9 --- /dev/null +++ b/tests/resources/icase/H @@ -0,0 +1 @@ +start diff --git a/tests/resources/icase/J b/tests/resources/icase/J new file mode 100644 index 000000000..d44e18fb9 --- /dev/null +++ b/tests/resources/icase/J @@ -0,0 +1 @@ +start diff --git a/tests/resources/icase/L/1 b/tests/resources/icase/L/1 new file mode 100644 index 000000000..62e0af52c --- /dev/null +++ b/tests/resources/icase/L/1 @@ -0,0 +1 @@ +sub diff --git a/tests/resources/icase/L/B b/tests/resources/icase/L/B new file mode 100644 index 000000000..62e0af52c --- /dev/null +++ b/tests/resources/icase/L/B @@ -0,0 +1 @@ +sub diff --git a/tests/resources/icase/L/D b/tests/resources/icase/L/D new file mode 100644 index 000000000..62e0af52c --- /dev/null +++ b/tests/resources/icase/L/D @@ -0,0 +1 @@ +sub diff --git a/tests/resources/icase/L/a b/tests/resources/icase/L/a new file mode 100644 index 000000000..62e0af52c --- /dev/null +++ b/tests/resources/icase/L/a @@ -0,0 +1 @@ +sub diff --git a/tests/resources/icase/L/c b/tests/resources/icase/L/c new file mode 100644 index 000000000..62e0af52c --- /dev/null +++ b/tests/resources/icase/L/c @@ -0,0 +1 @@ +sub diff --git a/tests/resources/icase/a b/tests/resources/icase/a new file mode 100644 index 000000000..d44e18fb9 --- /dev/null +++ b/tests/resources/icase/a @@ -0,0 +1 @@ +start diff --git a/tests/resources/icase/c b/tests/resources/icase/c new file mode 100644 index 000000000..d44e18fb9 --- /dev/null +++ b/tests/resources/icase/c @@ -0,0 +1 @@ +start diff --git a/tests/resources/icase/e b/tests/resources/icase/e new file mode 100644 index 000000000..d44e18fb9 --- /dev/null +++ b/tests/resources/icase/e @@ -0,0 +1 @@ +start diff --git a/tests/resources/icase/g b/tests/resources/icase/g new file mode 100644 index 000000000..d44e18fb9 --- /dev/null +++ b/tests/resources/icase/g @@ -0,0 +1 @@ +start diff --git a/tests/resources/icase/i b/tests/resources/icase/i new file mode 100644 index 000000000..d44e18fb9 --- /dev/null +++ b/tests/resources/icase/i @@ -0,0 +1 @@ +start diff --git a/tests/resources/icase/k/1 b/tests/resources/icase/k/1 new file mode 100644 index 000000000..62e0af52c --- /dev/null +++ b/tests/resources/icase/k/1 @@ -0,0 +1 @@ +sub diff --git a/tests/resources/icase/k/B b/tests/resources/icase/k/B new file mode 100644 index 000000000..62e0af52c --- /dev/null +++ b/tests/resources/icase/k/B @@ -0,0 +1 @@ +sub diff --git a/tests/resources/icase/k/D b/tests/resources/icase/k/D new file mode 100644 index 000000000..62e0af52c --- /dev/null +++ b/tests/resources/icase/k/D @@ -0,0 +1 @@ +sub diff --git a/tests/resources/icase/k/a b/tests/resources/icase/k/a new file mode 100644 index 000000000..62e0af52c --- /dev/null +++ b/tests/resources/icase/k/a @@ -0,0 +1 @@ +sub diff --git a/tests/resources/icase/k/c b/tests/resources/icase/k/c new file mode 100644 index 000000000..62e0af52c --- /dev/null +++ b/tests/resources/icase/k/c @@ -0,0 +1 @@ +sub diff --git a/tests/resources/issue_1397/.gitted/HEAD b/tests/resources/issue_1397/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/issue_1397/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/issue_1397/.gitted/config b/tests/resources/issue_1397/.gitted/config new file mode 100644 index 000000000..ba5bbde24 --- /dev/null +++ b/tests/resources/issue_1397/.gitted/config @@ -0,0 +1,6 @@ +[core] + bare = false + repositoryformatversion = 0 + filemode = false + logallrefupdates = true + ignorecase = true diff --git a/tests/resources/issue_1397/.gitted/index b/tests/resources/issue_1397/.gitted/index new file mode 100644 index 000000000..fa0f541d6 Binary files /dev/null and b/tests/resources/issue_1397/.gitted/index differ diff --git a/tests/resources/issue_1397/.gitted/objects/7f/483a738f867e5b21c8f377d70311f011eb48b5 b/tests/resources/issue_1397/.gitted/objects/7f/483a738f867e5b21c8f377d70311f011eb48b5 new file mode 100644 index 000000000..63bcb5d76 --- /dev/null +++ b/tests/resources/issue_1397/.gitted/objects/7f/483a738f867e5b21c8f377d70311f011eb48b5 @@ -0,0 +1,3 @@ +xQN0 as +!'nTBC+e\vӯǾofPPL8FΆ%_ċb4IܗtkULdeId<3/|0j1֣\Gcwe]~ߊS +)GxEqsUڇ8mk~yI \ No newline at end of file diff --git a/tests/resources/issue_1397/.gitted/objects/83/12e0889a9cbab77c732b6bc39b51a683e3a318 b/tests/resources/issue_1397/.gitted/objects/83/12e0889a9cbab77c732b6bc39b51a683e3a318 new file mode 100644 index 000000000..06b59fede Binary files /dev/null and b/tests/resources/issue_1397/.gitted/objects/83/12e0889a9cbab77c732b6bc39b51a683e3a318 differ diff --git a/tests/resources/issue_1397/.gitted/objects/8a/7ef047fc933edb62e84e7977b0612ec3f6f283 b/tests/resources/issue_1397/.gitted/objects/8a/7ef047fc933edb62e84e7977b0612ec3f6f283 new file mode 100644 index 000000000..19cfbeae2 Binary files /dev/null and b/tests/resources/issue_1397/.gitted/objects/8a/7ef047fc933edb62e84e7977b0612ec3f6f283 differ diff --git a/tests/resources/issue_1397/.gitted/objects/8e/8f80088a9274fd23584992f587083ca1bcbbac b/tests/resources/issue_1397/.gitted/objects/8e/8f80088a9274fd23584992f587083ca1bcbbac new file mode 100644 index 000000000..f5c776b17 Binary files /dev/null and b/tests/resources/issue_1397/.gitted/objects/8e/8f80088a9274fd23584992f587083ca1bcbbac differ diff --git a/tests/resources/issue_1397/.gitted/objects/f2/c62dea0372a0578e053697d5c1ba1ac05e774a b/tests/resources/issue_1397/.gitted/objects/f2/c62dea0372a0578e053697d5c1ba1ac05e774a new file mode 100644 index 000000000..f932f3618 Binary files /dev/null and b/tests/resources/issue_1397/.gitted/objects/f2/c62dea0372a0578e053697d5c1ba1ac05e774a differ diff --git a/tests/resources/issue_1397/.gitted/objects/ff/3578d64d199d5b48d92bbb569e0a273e411741 b/tests/resources/issue_1397/.gitted/objects/ff/3578d64d199d5b48d92bbb569e0a273e411741 new file mode 100644 index 000000000..fbd731727 Binary files /dev/null and b/tests/resources/issue_1397/.gitted/objects/ff/3578d64d199d5b48d92bbb569e0a273e411741 differ diff --git a/tests/resources/issue_1397/.gitted/refs/heads/master b/tests/resources/issue_1397/.gitted/refs/heads/master new file mode 100644 index 000000000..285bc08ff --- /dev/null +++ b/tests/resources/issue_1397/.gitted/refs/heads/master @@ -0,0 +1 @@ +7f483a738f867e5b21c8f377d70311f011eb48b5 diff --git a/tests/resources/issue_1397/crlf_file.txt b/tests/resources/issue_1397/crlf_file.txt new file mode 100644 index 000000000..8312e0889 --- /dev/null +++ b/tests/resources/issue_1397/crlf_file.txt @@ -0,0 +1,3 @@ +first line +second line +both with crlf \ No newline at end of file diff --git a/tests/resources/issue_1397/some_other_crlf_file.txt b/tests/resources/issue_1397/some_other_crlf_file.txt new file mode 100644 index 000000000..8e8f80088 --- /dev/null +++ b/tests/resources/issue_1397/some_other_crlf_file.txt @@ -0,0 +1,3 @@ +first line +second line with some change +both with crlf \ No newline at end of file diff --git a/tests/resources/issue_592/.gitted/COMMIT_EDITMSG b/tests/resources/issue_592/.gitted/COMMIT_EDITMSG new file mode 100644 index 000000000..5852f4463 --- /dev/null +++ b/tests/resources/issue_592/.gitted/COMMIT_EDITMSG @@ -0,0 +1 @@ +Initial commit diff --git a/tests/resources/issue_592/.gitted/HEAD b/tests/resources/issue_592/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/issue_592/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/issue_592/.gitted/config b/tests/resources/issue_592/.gitted/config new file mode 100644 index 000000000..78387c50b --- /dev/null +++ b/tests/resources/issue_592/.gitted/config @@ -0,0 +1,8 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + symlinks = false + ignorecase = true + hideDotFiles = dotGitOnly diff --git a/tests/resources/issue_592/.gitted/index b/tests/resources/issue_592/.gitted/index new file mode 100644 index 000000000..be7a29d99 Binary files /dev/null and b/tests/resources/issue_592/.gitted/index differ diff --git a/tests/resources/issue_592/.gitted/info/exclude b/tests/resources/issue_592/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/issue_592/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/issue_592/.gitted/logs/HEAD b/tests/resources/issue_592/.gitted/logs/HEAD new file mode 100644 index 000000000..f19fe35a6 --- /dev/null +++ b/tests/resources/issue_592/.gitted/logs/HEAD @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 4d383e87f0371ba8fa353f3912db6862b2625e85 nulltoken 1331989635 +0100 commit (initial): Initial commit +4d383e87f0371ba8fa353f3912db6862b2625e85 e38fcc7a6060f5eb5b876e836b52ae4769363f21 nulltoken 1332227062 +0100 commit (amend): Initial commit diff --git a/tests/resources/issue_592/.gitted/logs/refs/heads/master b/tests/resources/issue_592/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..f19fe35a6 --- /dev/null +++ b/tests/resources/issue_592/.gitted/logs/refs/heads/master @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 4d383e87f0371ba8fa353f3912db6862b2625e85 nulltoken 1331989635 +0100 commit (initial): Initial commit +4d383e87f0371ba8fa353f3912db6862b2625e85 e38fcc7a6060f5eb5b876e836b52ae4769363f21 nulltoken 1332227062 +0100 commit (amend): Initial commit diff --git a/tests/resources/issue_592/.gitted/objects/06/07ee9d4ccce8e4c4fa13c2c7d727e7faba4e0e b/tests/resources/issue_592/.gitted/objects/06/07ee9d4ccce8e4c4fa13c2c7d727e7faba4e0e new file mode 100644 index 000000000..05dec10f7 Binary files /dev/null and b/tests/resources/issue_592/.gitted/objects/06/07ee9d4ccce8e4c4fa13c2c7d727e7faba4e0e differ diff --git a/tests/resources/issue_592/.gitted/objects/49/363a72a90d9424240258cd3759f23788ecf1d8 b/tests/resources/issue_592/.gitted/objects/49/363a72a90d9424240258cd3759f23788ecf1d8 new file mode 100644 index 000000000..e997e1b49 Binary files /dev/null and b/tests/resources/issue_592/.gitted/objects/49/363a72a90d9424240258cd3759f23788ecf1d8 differ diff --git a/tests/resources/issue_592/.gitted/objects/4d/383e87f0371ba8fa353f3912db6862b2625e85 b/tests/resources/issue_592/.gitted/objects/4d/383e87f0371ba8fa353f3912db6862b2625e85 new file mode 100644 index 000000000..c49a8be58 --- /dev/null +++ b/tests/resources/issue_592/.gitted/objects/4d/383e87f0371ba8fa353f3912db6862b2625e85 @@ -0,0 +1,2 @@ +xM +0]o/IDz bz H9v2t =k,p+͏>4U=^(tAF2̟3sL|%cYuZv{=r_G}K> \ No newline at end of file diff --git a/tests/resources/issue_592/.gitted/objects/71/44be264b61825fbff68046fe999bdfe96a1792 b/tests/resources/issue_592/.gitted/objects/71/44be264b61825fbff68046fe999bdfe96a1792 new file mode 100644 index 000000000..25d44d938 Binary files /dev/null and b/tests/resources/issue_592/.gitted/objects/71/44be264b61825fbff68046fe999bdfe96a1792 differ diff --git a/tests/resources/issue_592/.gitted/objects/be/de83ee10b5b3f00239660b00acec2d55fd0b84 b/tests/resources/issue_592/.gitted/objects/be/de83ee10b5b3f00239660b00acec2d55fd0b84 new file mode 100644 index 000000000..1d6e38d37 Binary files /dev/null and b/tests/resources/issue_592/.gitted/objects/be/de83ee10b5b3f00239660b00acec2d55fd0b84 differ diff --git a/tests/resources/issue_592/.gitted/objects/e3/8fcc7a6060f5eb5b876e836b52ae4769363f21 b/tests/resources/issue_592/.gitted/objects/e3/8fcc7a6060f5eb5b876e836b52ae4769363f21 new file mode 100644 index 000000000..36c5b9aab Binary files /dev/null and b/tests/resources/issue_592/.gitted/objects/e3/8fcc7a6060f5eb5b876e836b52ae4769363f21 differ diff --git a/tests/resources/issue_592/.gitted/objects/f1/adef63cb08891a0942b76fc4b9c50c6c494bc7 b/tests/resources/issue_592/.gitted/objects/f1/adef63cb08891a0942b76fc4b9c50c6c494bc7 new file mode 100644 index 000000000..c08ecd5ed Binary files /dev/null and b/tests/resources/issue_592/.gitted/objects/f1/adef63cb08891a0942b76fc4b9c50c6c494bc7 differ diff --git a/tests/resources/issue_592/.gitted/refs/heads/master b/tests/resources/issue_592/.gitted/refs/heads/master new file mode 100644 index 000000000..1f6669628 --- /dev/null +++ b/tests/resources/issue_592/.gitted/refs/heads/master @@ -0,0 +1 @@ +e38fcc7a6060f5eb5b876e836b52ae4769363f21 diff --git a/tests/resources/issue_592/a.txt b/tests/resources/issue_592/a.txt new file mode 100644 index 000000000..f1adef63c --- /dev/null +++ b/tests/resources/issue_592/a.txt @@ -0,0 +1 @@ +nothing here diff --git a/tests/resources/issue_592/c/a.txt b/tests/resources/issue_592/c/a.txt new file mode 100644 index 000000000..f1adef63c --- /dev/null +++ b/tests/resources/issue_592/c/a.txt @@ -0,0 +1 @@ +nothing here diff --git a/tests/resources/issue_592/l.txt b/tests/resources/issue_592/l.txt new file mode 100644 index 000000000..f1adef63c --- /dev/null +++ b/tests/resources/issue_592/l.txt @@ -0,0 +1 @@ +nothing here diff --git a/tests/resources/issue_592/t/a.txt b/tests/resources/issue_592/t/a.txt new file mode 100644 index 000000000..f1adef63c --- /dev/null +++ b/tests/resources/issue_592/t/a.txt @@ -0,0 +1 @@ +nothing here diff --git a/tests/resources/issue_592/t/b.txt b/tests/resources/issue_592/t/b.txt new file mode 100644 index 000000000..f1adef63c --- /dev/null +++ b/tests/resources/issue_592/t/b.txt @@ -0,0 +1 @@ +nothing here diff --git a/tests/resources/issue_592b/.gitted/HEAD b/tests/resources/issue_592b/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/issue_592b/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/issue_592b/.gitted/config b/tests/resources/issue_592b/.gitted/config new file mode 100644 index 000000000..af107929f --- /dev/null +++ b/tests/resources/issue_592b/.gitted/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true diff --git a/tests/resources/issue_592b/.gitted/description b/tests/resources/issue_592b/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/issue_592b/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/issue_592b/.gitted/index b/tests/resources/issue_592b/.gitted/index new file mode 100644 index 000000000..596438216 Binary files /dev/null and b/tests/resources/issue_592b/.gitted/index differ diff --git a/tests/resources/issue_592b/.gitted/info/exclude b/tests/resources/issue_592b/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/issue_592b/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/issue_592b/.gitted/logs/HEAD b/tests/resources/issue_592b/.gitted/logs/HEAD new file mode 100644 index 000000000..6f3ba90cc --- /dev/null +++ b/tests/resources/issue_592b/.gitted/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 3fbf1852f72fd268e36457b13a18cdd9a4c9ea35 Russell Belfer 1337205933 -0700 commit (initial): Initial commit diff --git a/tests/resources/issue_592b/.gitted/logs/refs/heads/master b/tests/resources/issue_592b/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..6f3ba90cc --- /dev/null +++ b/tests/resources/issue_592b/.gitted/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 3fbf1852f72fd268e36457b13a18cdd9a4c9ea35 Russell Belfer 1337205933 -0700 commit (initial): Initial commit diff --git a/tests/resources/issue_592b/.gitted/objects/3f/bf1852f72fd268e36457b13a18cdd9a4c9ea35 b/tests/resources/issue_592b/.gitted/objects/3f/bf1852f72fd268e36457b13a18cdd9a4c9ea35 new file mode 100644 index 000000000..6eaf64b46 --- /dev/null +++ b/tests/resources/issue_592b/.gitted/objects/3f/bf1852f72fd268e36457b13a18cdd9a4c9ea35 @@ -0,0 +1,2 @@ +xK +1]}%BwnAq xzVƃv ɂc&%9@9xdu.]".=EבO+ۘBEk\N_<>E U%9 \ No newline at end of file diff --git a/tests/resources/issue_592b/.gitted/objects/6f/a891d3e578c83e1c03bdb9e0fdd8e6e934157f b/tests/resources/issue_592b/.gitted/objects/6f/a891d3e578c83e1c03bdb9e0fdd8e6e934157f new file mode 100644 index 000000000..c4becfe2f Binary files /dev/null and b/tests/resources/issue_592b/.gitted/objects/6f/a891d3e578c83e1c03bdb9e0fdd8e6e934157f differ diff --git a/tests/resources/issue_592b/.gitted/objects/80/07d41d5794e6ce4d4d2c97e370d5a9aa6d5213 b/tests/resources/issue_592b/.gitted/objects/80/07d41d5794e6ce4d4d2c97e370d5a9aa6d5213 new file mode 100644 index 000000000..aea14f2af Binary files /dev/null and b/tests/resources/issue_592b/.gitted/objects/80/07d41d5794e6ce4d4d2c97e370d5a9aa6d5213 differ diff --git a/tests/resources/issue_592b/.gitted/objects/a6/5fb6583a7c425284142f285bc359a2d6565513 b/tests/resources/issue_592b/.gitted/objects/a6/5fb6583a7c425284142f285bc359a2d6565513 new file mode 100644 index 000000000..9b7407221 Binary files /dev/null and b/tests/resources/issue_592b/.gitted/objects/a6/5fb6583a7c425284142f285bc359a2d6565513 differ diff --git a/tests/resources/issue_592b/.gitted/objects/ae/be7a55922c7097ef91ca3a7bc327a901d87c2c b/tests/resources/issue_592b/.gitted/objects/ae/be7a55922c7097ef91ca3a7bc327a901d87c2c new file mode 100644 index 000000000..1494ed822 Binary files /dev/null and b/tests/resources/issue_592b/.gitted/objects/ae/be7a55922c7097ef91ca3a7bc327a901d87c2c differ diff --git a/tests/resources/issue_592b/.gitted/objects/b3/44b055867fcdc1f01eaa75056a43e868eb4fbc b/tests/resources/issue_592b/.gitted/objects/b3/44b055867fcdc1f01eaa75056a43e868eb4fbc new file mode 100644 index 000000000..7a6626636 Binary files /dev/null and b/tests/resources/issue_592b/.gitted/objects/b3/44b055867fcdc1f01eaa75056a43e868eb4fbc differ diff --git a/tests/resources/issue_592b/.gitted/objects/f7/d75fbfad8b1d2e307ced287ea78aad403cdce3 b/tests/resources/issue_592b/.gitted/objects/f7/d75fbfad8b1d2e307ced287ea78aad403cdce3 new file mode 100644 index 000000000..65a1fd0d0 Binary files /dev/null and b/tests/resources/issue_592b/.gitted/objects/f7/d75fbfad8b1d2e307ced287ea78aad403cdce3 differ diff --git a/tests/resources/issue_592b/.gitted/refs/heads/master b/tests/resources/issue_592b/.gitted/refs/heads/master new file mode 100644 index 000000000..c0a9ab495 --- /dev/null +++ b/tests/resources/issue_592b/.gitted/refs/heads/master @@ -0,0 +1 @@ +3fbf1852f72fd268e36457b13a18cdd9a4c9ea35 diff --git a/tests/resources/issue_592b/gitignore b/tests/resources/issue_592b/gitignore new file mode 100644 index 000000000..8007d41d5 --- /dev/null +++ b/tests/resources/issue_592b/gitignore @@ -0,0 +1 @@ +ignored/ diff --git a/tests/resources/issue_592b/ignored/contained/ignored3.txt b/tests/resources/issue_592b/ignored/contained/ignored3.txt new file mode 100644 index 000000000..b5dc7b073 --- /dev/null +++ b/tests/resources/issue_592b/ignored/contained/ignored3.txt @@ -0,0 +1 @@ +I'm ignored diff --git a/tests/resources/issue_592b/ignored/contained/tracked3.txt b/tests/resources/issue_592b/ignored/contained/tracked3.txt new file mode 100644 index 000000000..b344b0558 --- /dev/null +++ b/tests/resources/issue_592b/ignored/contained/tracked3.txt @@ -0,0 +1 @@ +You added me anyhow diff --git a/tests/resources/issue_592b/ignored/ignored2.txt b/tests/resources/issue_592b/ignored/ignored2.txt new file mode 100644 index 000000000..b5dc7b073 --- /dev/null +++ b/tests/resources/issue_592b/ignored/ignored2.txt @@ -0,0 +1 @@ +I'm ignored diff --git a/tests/resources/issue_592b/ignored/tracked2.txt b/tests/resources/issue_592b/ignored/tracked2.txt new file mode 100644 index 000000000..6fa891d3e --- /dev/null +++ b/tests/resources/issue_592b/ignored/tracked2.txt @@ -0,0 +1 @@ +You like me diff --git a/tests/resources/issue_592b/ignored1.txt b/tests/resources/issue_592b/ignored1.txt new file mode 100644 index 000000000..b5dc7b073 --- /dev/null +++ b/tests/resources/issue_592b/ignored1.txt @@ -0,0 +1 @@ +I'm ignored diff --git a/tests/resources/issue_592b/tracked1.txt b/tests/resources/issue_592b/tracked1.txt new file mode 100644 index 000000000..6fa891d3e --- /dev/null +++ b/tests/resources/issue_592b/tracked1.txt @@ -0,0 +1 @@ +You like me diff --git a/tests/resources/merge-resolve/.gitted/COMMIT_EDITMSG b/tests/resources/merge-resolve/.gitted/COMMIT_EDITMSG new file mode 100644 index 000000000..245b18a2c --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/COMMIT_EDITMSG @@ -0,0 +1 @@ +rename conflict theirs diff --git a/tests/resources/merge-resolve/.gitted/HEAD b/tests/resources/merge-resolve/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/merge-resolve/.gitted/ORIG_HEAD b/tests/resources/merge-resolve/.gitted/ORIG_HEAD new file mode 100644 index 000000000..4092d428f --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/ORIG_HEAD @@ -0,0 +1 @@ +2392a2dacc9efb562b8635d6579fb458751c7c5b diff --git a/tests/resources/merge-resolve/.gitted/config b/tests/resources/merge-resolve/.gitted/config new file mode 100644 index 000000000..af107929f --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true diff --git a/tests/resources/merge-resolve/.gitted/description b/tests/resources/merge-resolve/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/merge-resolve/.gitted/index b/tests/resources/merge-resolve/.gitted/index new file mode 100644 index 000000000..230eba9eb Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/index differ diff --git a/tests/resources/merge-resolve/.gitted/logs/HEAD b/tests/resources/merge-resolve/.gitted/logs/HEAD new file mode 100644 index 000000000..96cdb337e --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/HEAD @@ -0,0 +1,236 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351563869 -0500 commit (initial): initial +c607fc30883e335def28cd686b51f6cfa02b06ec c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351563886 -0500 checkout: moving from master to branch +c607fc30883e335def28cd686b51f6cfa02b06ec 7cb63eed597130ba4abb87b3e544b85021905520 Edward Thomson 1351563965 -0500 commit: branch +7cb63eed597130ba4abb87b3e544b85021905520 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351563968 -0500 checkout: moving from branch to master +c607fc30883e335def28cd686b51f6cfa02b06ec 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351564033 -0500 commit: master +977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351605785 -0500 checkout: moving from master to ff_branch +977c696519c5a3004c5f1d15d60c89dbeb8f235f 33d500f588fbbe65901d82b4e6b008e549064be0 Edward Thomson 1351605830 -0500 commit: fastforward +33d500f588fbbe65901d82b4e6b008e549064be0 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351605889 -0500 checkout: moving from ff_branch to master +977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874933 -0500 checkout: moving from master to octo1 +977c696519c5a3004c5f1d15d60c89dbeb8f235f 16f825815cfd20a07a75c71554e82d8eede0b061 Edward Thomson 1351874954 -0500 commit: octo1 +16f825815cfd20a07a75c71554e82d8eede0b061 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874957 -0500 checkout: moving from octo1 to master +977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874960 -0500 checkout: moving from master to octo2 +977c696519c5a3004c5f1d15d60c89dbeb8f235f 158dc7bedb202f5b26502bf3574faa7f4238d56c Edward Thomson 1351874974 -0500 commit: octo2 +158dc7bedb202f5b26502bf3574faa7f4238d56c 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874976 -0500 checkout: moving from octo2 to master +977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874980 -0500 checkout: moving from master to octo3 +977c696519c5a3004c5f1d15d60c89dbeb8f235f 50ce7d7d01217679e26c55939eef119e0c93e272 Edward Thomson 1351874998 -0500 commit: octo3 +50ce7d7d01217679e26c55939eef119e0c93e272 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875006 -0500 checkout: moving from octo3 to master +977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875010 -0500 checkout: moving from master to octo4 +977c696519c5a3004c5f1d15d60c89dbeb8f235f 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae Edward Thomson 1351875023 -0500 commit: octo4 +54269b3f6ec3d7d4ede24dd350dd5d605495c3ae 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875031 -0500 checkout: moving from octo4 to master +977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875031 -0500 checkout: moving from master to octo5 +977c696519c5a3004c5f1d15d60c89dbeb8f235f e4f618a2c3ed0669308735727df5ebf2447f022f Edward Thomson 1351875041 -0500 commit: octo5 +e4f618a2c3ed0669308735727df5ebf2447f022f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875046 -0500 checkout: moving from octo5 to master +977c696519c5a3004c5f1d15d60c89dbeb8f235f 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875046 -0500 checkout: moving from master to octo6 +977c696519c5a3004c5f1d15d60c89dbeb8f235f 4ca408a8c88655f7586a1b580be6fad138121e98 Edward Thomson 1351875057 -0500 commit: octo5 +4ca408a8c88655f7586a1b580be6fad138121e98 b6f610aef53bd343e6c96227de874c66f00ee8e8 Edward Thomson 1351875065 -0500 commit (amend): octo6 +b6f610aef53bd343e6c96227de874c66f00ee8e8 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875071 -0500 checkout: moving from octo6 to master +977c696519c5a3004c5f1d15d60c89dbeb8f235f 4e0d9401aee78eb345a8685a859d37c8c3c0bbed Edward Thomson 1351875091 -0500 merge octo1 octo2 octo3 octo4: Merge made by the 'octopus' strategy. +4e0d9401aee78eb345a8685a859d37c8c3c0bbed 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae Edward Thomson 1351875108 -0500 reset: moving to 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae +54269b3f6ec3d7d4ede24dd350dd5d605495c3ae 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875584 -0500 reset: moving to 977c696519c5a3004c5f1d15d60c89dbeb8f235f +bd593285fc7fe4ca18ccdbabf027f5d689101452 33d500f588fbbe65901d82b4e6b008e549064be0 Edward Thomson 1351990193 -0500 checkout: moving from master to ff_branch +33d500f588fbbe65901d82b4e6b008e549064be0 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351990202 -0500 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1351990205 -0500 merge master: Fast-forward +bd593285fc7fe4ca18ccdbabf027f5d689101452 fd89f8cffb663ac89095a0f9764902e93ceaca6a Edward Thomson 1351990229 -0500 commit: fastforward +fd89f8cffb663ac89095a0f9764902e93ceaca6a bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1351990233 -0500 checkout: moving from ff_branch to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352091703 -0600 checkout: moving from master to trivial-2alt +c607fc30883e335def28cd686b51f6cfa02b06ec c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352092411 -0600 checkout: moving from trivial-2alt to trivial-2alt-branch +c607fc30883e335def28cd686b51f6cfa02b06ec c9174cef549ec94ecbc43ef03cdc775b4950becb Edward Thomson 1352092434 -0600 commit: 2alt-branch +c9174cef549ec94ecbc43ef03cdc775b4950becb c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352092440 -0600 checkout: moving from trivial-2alt-branch to trivial-2alt +c607fc30883e335def28cd686b51f6cfa02b06ec 566ab53c220a2eafc1212af1a024513230280ab9 Edward Thomson 1352092452 -0600 commit: 2alt +bd593285fc7fe4ca18ccdbabf027f5d689101452 566ab53c220a2eafc1212af1a024513230280ab9 Edward Thomson 1352094476 -0600 checkout: moving from master to trivial-3alt +566ab53c220a2eafc1212af1a024513230280ab9 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094547 -0600 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 5459c89aa0026d543ce8343bd89871bce543f9c2 Edward Thomson 1352094580 -0600 commit: 3alt +5459c89aa0026d543ce8343bd89871bce543f9c2 4c9fac0707f8d4195037ae5a681aa48626491541 Edward Thomson 1352094610 -0600 commit: 3alt-branch +4c9fac0707f8d4195037ae5a681aa48626491541 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352094620 -0600 checkout: moving from trivial-3alt to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 566ab53c220a2eafc1212af1a024513230280ab9 Edward Thomson 1352094752 -0600 checkout: moving from master to trivial-4 +566ab53c220a2eafc1212af1a024513230280ab9 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094764 -0600 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec cc3e3009134cb88014129fc8858d1101359e5e2f Edward Thomson 1352094815 -0600 commit: trivial-4 +cc3e3009134cb88014129fc8858d1101359e5e2f c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094843 -0600 checkout: moving from trivial-4 to trivial-4-branch +c607fc30883e335def28cd686b51f6cfa02b06ec 183310e30fb1499af8c619108ffea4d300b5e778 Edward Thomson 1352094856 -0600 commit: trivial-4-branch +183310e30fb1499af8c619108ffea4d300b5e778 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352094860 -0600 checkout: moving from trivial-4-branch to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 cc3e3009134cb88014129fc8858d1101359e5e2f Edward Thomson 1352096588 -0600 checkout: moving from master to trivial-4 +cc3e3009134cb88014129fc8858d1101359e5e2f c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096612 -0600 checkout: moving from trivial-4 to trivial-5alt-1 +c607fc30883e335def28cd686b51f6cfa02b06ec 4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 Edward Thomson 1352096643 -0600 commit: 5alt-1 +4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096661 -0600 checkout: moving from trivial-5alt-1 to trivial-5alt-1-branch +c607fc30883e335def28cd686b51f6cfa02b06ec 4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 Edward Thomson 1352096671 -0600 checkout: moving from trivial-5alt-1-branch to trivial-5alt-1 +4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096678 -0600 checkout: moving from trivial-5alt-1 to trivial-5alt-1-branch +c607fc30883e335def28cd686b51f6cfa02b06ec 478172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 Edward Thomson 1352096689 -0600 commit: 5alt-1-branch +478172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 Edward Thomson 1352096701 -0600 checkout: moving from trivial-5alt-1-branch to trivial-5alt-1 +4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096715 -0600 checkout: moving from trivial-5alt-1 to trivial-5alt-2 +c607fc30883e335def28cd686b51f6cfa02b06ec ebc09d0137cfb0c26697aed0109fb943ad906f3f Edward Thomson 1352096764 -0600 commit: existing file +ebc09d0137cfb0c26697aed0109fb943ad906f3f 3b47b031b3e55ae11e14a05260b1c3ffd6838d55 Edward Thomson 1352096815 -0600 commit: 5alt-2 +3b47b031b3e55ae11e14a05260b1c3ffd6838d55 ebc09d0137cfb0c26697aed0109fb943ad906f3f Edward Thomson 1352096840 -0600 checkout: moving from trivial-5alt-2 to trivial-5alt-2-branch +ebc09d0137cfb0c26697aed0109fb943ad906f3f f48097eb340dc5a7cae55aabcf1faf4548aa821f Edward Thomson 1352096855 -0600 commit: 5alt-2-branch +f48097eb340dc5a7cae55aabcf1faf4548aa821f bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352096858 -0600 checkout: moving from trivial-5alt-2-branch to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352097377 -0600 checkout: moving from master to trivial-6 +c607fc30883e335def28cd686b51f6cfa02b06ec f7c332bd4d4d4b777366cae4d24d1687477576bf Edward Thomson 1352097389 -0600 commit: 6 +f7c332bd4d4d4b777366cae4d24d1687477576bf 99b4f7e4f24470fa06b980bc21f1095c2a9425c0 Edward Thomson 1352097404 -0600 commit: trivial-6 +99b4f7e4f24470fa06b980bc21f1095c2a9425c0 f7c332bd4d4d4b777366cae4d24d1687477576bf Edward Thomson 1352097420 -0600 checkout: moving from trivial-6 to trivial-6-branch +f7c332bd4d4d4b777366cae4d24d1687477576bf a43150a738849c59376cf30bb2a68348a83c8f48 Edward Thomson 1352097431 -0600 commit: 6-branch +a43150a738849c59376cf30bb2a68348a83c8f48 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352097442 -0600 checkout: moving from trivial-6-branch to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 99b4f7e4f24470fa06b980bc21f1095c2a9425c0 Edward Thomson 1352098040 -0600 checkout: moving from master to trivial-6 +99b4f7e4f24470fa06b980bc21f1095c2a9425c0 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352098057 -0600 checkout: moving from trivial-6 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 cc3e3009134cb88014129fc8858d1101359e5e2f Edward Thomson 1352098792 -0600 checkout: moving from master to trivial-4 +cc3e3009134cb88014129fc8858d1101359e5e2f c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352098818 -0600 checkout: moving from trivial-4 to trivial-8 +c607fc30883e335def28cd686b51f6cfa02b06ec 75a811bf6bc57694adb3fe604786f3a4efd1cd1b Edward Thomson 1352098884 -0600 commit: trivial-8 +75a811bf6bc57694adb3fe604786f3a4efd1cd1b 75a811bf6bc57694adb3fe604786f3a4efd1cd1b Edward Thomson 1352098947 -0600 checkout: moving from trivial-8 to trivial-8-branch +75a811bf6bc57694adb3fe604786f3a4efd1cd1b 52d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 Edward Thomson 1352098979 -0600 commit: trivial-8-branch +52d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 75a811bf6bc57694adb3fe604786f3a4efd1cd1b Edward Thomson 1352098982 -0600 checkout: moving from trivial-8-branch to trivial-8 +75a811bf6bc57694adb3fe604786f3a4efd1cd1b 3575826c96a975031d2c14368529cc5c4353a8fd Edward Thomson 1352099000 -0600 commit: trivial-8 +3575826c96a975031d2c14368529cc5c4353a8fd bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352099008 -0600 checkout: moving from trivial-8 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352099776 -0600 checkout: moving from master to trivial-7 +c607fc30883e335def28cd686b51f6cfa02b06ec 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099790 -0600 commit: trivial-7 +092ce8682d7f3a2a3a769a6daca58950168ba5c4 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099799 -0600 checkout: moving from trivial-7 to trivial-7-branch +092ce8682d7f3a2a3a769a6daca58950168ba5c4 73cbfdc4fe843169e5b2af8dcad03cbf3acf306c Edward Thomson 1352099812 -0600 commit: trivial-7-branch +73cbfdc4fe843169e5b2af8dcad03cbf3acf306c 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099815 -0600 checkout: moving from trivial-7-branch to trivial-7 +092ce8682d7f3a2a3a769a6daca58950168ba5c4 73cbfdc4fe843169e5b2af8dcad03cbf3acf306c Edward Thomson 1352099838 -0600 checkout: moving from trivial-7 to trivial-7-branch +73cbfdc4fe843169e5b2af8dcad03cbf3acf306c 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099874 -0600 reset: moving to 092ce8682d7f3a2a3a769a6daca58950168ba5c4 +092ce8682d7f3a2a3a769a6daca58950168ba5c4 009b9cab6fdac02915a88ecd078b7a792ed802d8 Edward Thomson 1352099921 -0600 commit: removed in 7 +009b9cab6fdac02915a88ecd078b7a792ed802d8 5195a1b480f66691b667f10a9e41e70115a78351 Edward Thomson 1352099927 -0600 commit (amend): trivial-7-branch +5195a1b480f66691b667f10a9e41e70115a78351 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099937 -0600 checkout: moving from trivial-7-branch to trivial-7 +092ce8682d7f3a2a3a769a6daca58950168ba5c4 d874671ef5b20184836cb983bb273e5280384d0b Edward Thomson 1352099947 -0600 commit: trivial-7 +d874671ef5b20184836cb983bb273e5280384d0b bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352099949 -0600 checkout: moving from trivial-7 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100174 -0600 checkout: moving from master to trivial-10 +c607fc30883e335def28cd686b51f6cfa02b06ec 53825f41ac8d640612f9423a2f03a69f3d96809a Edward Thomson 1352100193 -0600 commit: trivial-10 +53825f41ac8d640612f9423a2f03a69f3d96809a 53825f41ac8d640612f9423a2f03a69f3d96809a Edward Thomson 1352100200 -0600 checkout: moving from trivial-10 to trivial-10-branch +53825f41ac8d640612f9423a2f03a69f3d96809a 11f4f3c08b737f5fd896cbefa1425ee63b21b2fa Edward Thomson 1352100211 -0600 commit: trivial-10-branch +11f4f3c08b737f5fd896cbefa1425ee63b21b2fa 53825f41ac8d640612f9423a2f03a69f3d96809a Edward Thomson 1352100214 -0600 checkout: moving from trivial-10-branch to trivial-10 +53825f41ac8d640612f9423a2f03a69f3d96809a 0ec5f433959cd46177f745903353efb5be08d151 Edward Thomson 1352100223 -0600 commit: trivial-10 +0ec5f433959cd46177f745903353efb5be08d151 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352100225 -0600 checkout: moving from trivial-10 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100270 -0600 checkout: moving from master to trivial-9 +c607fc30883e335def28cd686b51f6cfa02b06ec f0053b8060bb3f0be5cbcc3147a07ece26bf097e Edward Thomson 1352100304 -0600 commit: trivial-9 +f0053b8060bb3f0be5cbcc3147a07ece26bf097e f0053b8060bb3f0be5cbcc3147a07ece26bf097e Edward Thomson 1352100310 -0600 checkout: moving from trivial-9 to trivial-9-branch +f0053b8060bb3f0be5cbcc3147a07ece26bf097e 13d1be4ea52a6ced1d7a1d832f0ee3c399348e5e Edward Thomson 1352100317 -0600 commit: trivial-9-branch +13d1be4ea52a6ced1d7a1d832f0ee3c399348e5e f0053b8060bb3f0be5cbcc3147a07ece26bf097e Edward Thomson 1352100319 -0600 checkout: moving from trivial-9-branch to trivial-9 +f0053b8060bb3f0be5cbcc3147a07ece26bf097e c35dee9bcc0e989f3b0c40f68372a9a51b6c4e6a Edward Thomson 1352100333 -0600 commit: trivial-9 +c35dee9bcc0e989f3b0c40f68372a9a51b6c4e6a bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352100335 -0600 checkout: moving from trivial-9 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100576 -0600 checkout: moving from master to trivial-13 +c607fc30883e335def28cd686b51f6cfa02b06ec 8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa Edward Thomson 1352100589 -0600 commit: trivial-13 +8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa 8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa Edward Thomson 1352100604 -0600 checkout: moving from trivial-13 to trivial-13-branch +8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa 05f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c Edward Thomson 1352100610 -0600 commit: trivial-13-branch +05f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c 8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa Edward Thomson 1352100612 -0600 checkout: moving from trivial-13-branch to trivial-13 +8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa a3fabece9eb8748da810e1e08266fef9b7136ad4 Edward Thomson 1352100625 -0600 commit: trivial-13 +a3fabece9eb8748da810e1e08266fef9b7136ad4 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352100627 -0600 checkout: moving from trivial-13 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100936 -0600 checkout: moving from master to trivial-11 +c607fc30883e335def28cd686b51f6cfa02b06ec 35632e43612c06a3ea924bfbacd48333da874c29 Edward Thomson 1352100958 -0600 commit: trivial-11 +35632e43612c06a3ea924bfbacd48333da874c29 35632e43612c06a3ea924bfbacd48333da874c29 Edward Thomson 1352100964 -0600 checkout: moving from trivial-11 to trivial-11-branch +35632e43612c06a3ea924bfbacd48333da874c29 6718a45909532d1fcf5600d0877f7fe7e78f0b86 Edward Thomson 1352100978 -0600 commit: trivial-11-branch +6718a45909532d1fcf5600d0877f7fe7e78f0b86 35632e43612c06a3ea924bfbacd48333da874c29 Edward Thomson 1352100981 -0600 checkout: moving from trivial-11-branch to trivial-11 +35632e43612c06a3ea924bfbacd48333da874c29 3168dca1a561889b045a6441909f4c56145e666d Edward Thomson 1352100992 -0600 commit: trivial-11 +3168dca1a561889b045a6441909f4c56145e666d bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352100996 -0600 checkout: moving from trivial-11 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352101098 -0600 checkout: moving from master to trivial-14 +c607fc30883e335def28cd686b51f6cfa02b06ec 596803b523203a4851c824c07366906f8353f4ad Edward Thomson 1352101113 -0600 commit: trivial-14 +596803b523203a4851c824c07366906f8353f4ad 596803b523203a4851c824c07366906f8353f4ad Edward Thomson 1352101117 -0600 checkout: moving from trivial-14 to trivial-14-branch +596803b523203a4851c824c07366906f8353f4ad 8187117062b750eed4f93fd7e899f17b52ce554d Edward Thomson 1352101132 -0600 commit: trivial-14-branch +8187117062b750eed4f93fd7e899f17b52ce554d 596803b523203a4851c824c07366906f8353f4ad Edward Thomson 1352101135 -0600 checkout: moving from trivial-14-branch to trivial-14 +596803b523203a4851c824c07366906f8353f4ad 7e2d058d5fedf8329db44db4fac610d6b1a89159 Edward Thomson 1352101141 -0600 commit: trivial-14 +7e2d058d5fedf8329db44db4fac610d6b1a89159 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1352101145 -0600 checkout: moving from trivial-14 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1353177749 -0600 checkout: moving from master to renames1 +c607fc30883e335def28cd686b51f6cfa02b06ec 412b32fb66137366147f1801ecc962452757d48a Edward Thomson 1353177886 -0600 commit: renames +412b32fb66137366147f1801ecc962452757d48a bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1353794607 -0600 checkout: moving from renames1 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1353794647 -0600 checkout: moving from master to renames2 +bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1353794677 -0600 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec ab40af3cb8a3ed2e2843e96d9aa7871336b94573 Edward Thomson 1353794852 -0600 commit: renames2 +ab40af3cb8a3ed2e2843e96d9aa7871336b94573 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1353794883 -0600 checkout: moving from renames2 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1354574697 -0600 checkout: moving from master to df_side1 +bd593285fc7fe4ca18ccdbabf027f5d689101452 d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1354574962 -0600 commit: df_ancestor +d4207f77243500bec335ab477f9227fcdb1e271a c94b27e41064c521120627e07e2035cca1d24ffa Edward Thomson 1354575027 -0600 commit: df_side1 +c94b27e41064c521120627e07e2035cca1d24ffa d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1354575070 -0600 checkout: moving from df_side1 to df_side2 +d4207f77243500bec335ab477f9227fcdb1e271a f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 Edward Thomson 1354575206 -0600 commit: df_side2 +f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1354575381 -0600 checkout: moving from df_side2 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 c94b27e41064c521120627e07e2035cca1d24ffa Edward Thomson 1355017614 -0600 checkout: moving from master to df_side1 +c94b27e41064c521120627e07e2035cca1d24ffa a90bc3fb6f15181972a2959a921429efbd81a473 Edward Thomson 1355017650 -0600 commit: df_added +a90bc3fb6f15181972a2959a921429efbd81a473 c94b27e41064c521120627e07e2035cca1d24ffa Edward Thomson 1355017673 -0600 checkout: moving from df_side1 to c94b27e +c94b27e41064c521120627e07e2035cca1d24ffa d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355017673 -0600 rebase -i (squash): updating HEAD +d4207f77243500bec335ab477f9227fcdb1e271a 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355017673 -0600 rebase -i (squash): df_side1 +005b6fcc8fec71d2550bef8462d169b3c26aa14b 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355017676 -0600 rebase -i (finish): returning to refs/heads/df_side1 +005b6fcc8fec71d2550bef8462d169b3c26aa14b f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 Edward Thomson 1355017715 -0600 reset: moving to df_side2 +f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 8c749d9968d4b10dcfb06c9f97d0e5d92d337071 Edward Thomson 1355017744 -0600 commit: df_added +8c749d9968d4b10dcfb06c9f97d0e5d92d337071 f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 Edward Thomson 1355017754 -0600 checkout: moving from df_side1 to f8958bd +f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355017754 -0600 rebase -i (squash): updating HEAD +d4207f77243500bec335ab477f9227fcdb1e271a 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355017754 -0600 rebase -i (squash): df_side2 +0204a84f822acbf6386b36d33f1f6bc68bbbf858 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355017756 -0600 rebase -i (finish): returning to refs/heads/df_side1 +0204a84f822acbf6386b36d33f1f6bc68bbbf858 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355017793 -0600 reset: moving to 005b6fcc8fec71d2550bef8462d169b3c26aa14b +005b6fcc8fec71d2550bef8462d169b3c26aa14b 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355017826 -0600 reset: moving to 0204a84 +0204a84f822acbf6386b36d33f1f6bc68bbbf858 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1355017847 -0600 checkout: moving from df_side1 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355168677 -0600 checkout: moving from master to df_side1 +005b6fcc8fec71d2550bef8462d169b3c26aa14b 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355168829 -0600 checkout: moving from df_side1 to df_side1 +005b6fcc8fec71d2550bef8462d169b3c26aa14b 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355168838 -0600 checkout: moving from df_side1 to df_side1 +005b6fcc8fec71d2550bef8462d169b3c26aa14b e8107f24196736b870a318a0e28f048e29f6feff Edward Thomson 1355169065 -0600 commit: df_side1 +e8107f24196736b870a318a0e28f048e29f6feff 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355169081 -0600 checkout: moving from df_side1 to 005b6fc +005b6fcc8fec71d2550bef8462d169b3c26aa14b d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355169081 -0600 rebase -i (squash): updating HEAD +d4207f77243500bec335ab477f9227fcdb1e271a 80a8fbb3abb1ba423d554e9630b8fc2e5698f86b Edward Thomson 1355169081 -0600 rebase -i (squash): df_side1 +80a8fbb3abb1ba423d554e9630b8fc2e5698f86b 80a8fbb3abb1ba423d554e9630b8fc2e5698f86b Edward Thomson 1355169084 -0600 rebase -i (finish): returning to refs/heads/df_side1 +80a8fbb3abb1ba423d554e9630b8fc2e5698f86b 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355169141 -0600 checkout: moving from df_side1 to df_side2 +0204a84f822acbf6386b36d33f1f6bc68bbbf858 944f5dd1a867cab4c2bbcb896493435cae1dcc1a Edward Thomson 1355169174 -0600 commit: both +944f5dd1a867cab4c2bbcb896493435cae1dcc1a 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355169182 -0600 checkout: moving from df_side2 to 0204a84 +0204a84f822acbf6386b36d33f1f6bc68bbbf858 d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355169182 -0600 rebase -i (squash): updating HEAD +d4207f77243500bec335ab477f9227fcdb1e271a 57079a46233ae2b6df62e9ade71c4948512abefb Edward Thomson 1355169182 -0600 rebase -i (squash): df_side2 +57079a46233ae2b6df62e9ade71c4948512abefb 57079a46233ae2b6df62e9ade71c4948512abefb Edward Thomson 1355169185 -0600 rebase -i (finish): returning to refs/heads/df_side2 +57079a46233ae2b6df62e9ade71c4948512abefb 80a8fbb3abb1ba423d554e9630b8fc2e5698f86b Edward Thomson 1355169241 -0600 checkout: moving from df_side2 to df_side1 +80a8fbb3abb1ba423d554e9630b8fc2e5698f86b e65a9bb2af9f4c2d1c375dd0f8f8a46cf9c68812 Edward Thomson 1355169419 -0600 commit: side1 +e65a9bb2af9f4c2d1c375dd0f8f8a46cf9c68812 80a8fbb3abb1ba423d554e9630b8fc2e5698f86b Edward Thomson 1355169431 -0600 checkout: moving from df_side1 to 80a8fbb +80a8fbb3abb1ba423d554e9630b8fc2e5698f86b d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355169431 -0600 rebase -i (squash): updating HEAD +d4207f77243500bec335ab477f9227fcdb1e271a 5dc1018e90b19654bee986b7a0c268804d39659d Edward Thomson 1355169431 -0600 rebase -i (squash): df_side1 +5dc1018e90b19654bee986b7a0c268804d39659d 5dc1018e90b19654bee986b7a0c268804d39659d Edward Thomson 1355169435 -0600 rebase -i (finish): returning to refs/heads/df_side1 +5dc1018e90b19654bee986b7a0c268804d39659d 57079a46233ae2b6df62e9ade71c4948512abefb Edward Thomson 1355169439 -0600 checkout: moving from df_side1 to df_side2 +57079a46233ae2b6df62e9ade71c4948512abefb 58e853f66699fd02629fd50bde08082bc005933a Edward Thomson 1355169460 -0600 commit: side2 +58e853f66699fd02629fd50bde08082bc005933a 57079a46233ae2b6df62e9ade71c4948512abefb Edward Thomson 1355169469 -0600 checkout: moving from df_side2 to 57079a4 +57079a46233ae2b6df62e9ade71c4948512abefb d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355169469 -0600 rebase -i (squash): updating HEAD +d4207f77243500bec335ab477f9227fcdb1e271a fada9356aa3f74622327a3038ae9c6f92e1c5c1d Edward Thomson 1355169469 -0600 rebase -i (squash): df_side2 +fada9356aa3f74622327a3038ae9c6f92e1c5c1d fada9356aa3f74622327a3038ae9c6f92e1c5c1d Edward Thomson 1355169471 -0600 rebase -i (finish): returning to refs/heads/df_side2 +fada9356aa3f74622327a3038ae9c6f92e1c5c1d 5dc1018e90b19654bee986b7a0c268804d39659d Edward Thomson 1355169494 -0600 checkout: moving from df_side2 to df_side1 +5dc1018e90b19654bee986b7a0c268804d39659d d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355169663 -0600 checkout: moving from df_side1 to d4207f77243500bec335ab477f9227fcdb1e271a +d4207f77243500bec335ab477f9227fcdb1e271a 849619b03ae540acee4d1edec96b86993da6b497 Edward Thomson 1355169683 -0600 commit: both_dirs +849619b03ae540acee4d1edec96b86993da6b497 d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1355169691 -0600 checkout: moving from 849619b03ae540acee4d1edec96b86993da6b497 to d4207f7 +d4207f77243500bec335ab477f9227fcdb1e271a bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1355169691 -0600 rebase -i (squash): updating HEAD +bd593285fc7fe4ca18ccdbabf027f5d689101452 a765fb87eb2f7a1920b73b2d5a057f8f8476a42b Edward Thomson 1355169691 -0600 rebase -i (squash): df_ancestor +a765fb87eb2f7a1920b73b2d5a057f8f8476a42b 5dc1018e90b19654bee986b7a0c268804d39659d Edward Thomson 1355169706 -0600 checkout: moving from a765fb87eb2f7a1920b73b2d5a057f8f8476a42b to df_side1 +5dc1018e90b19654bee986b7a0c268804d39659d a765fb87eb2f7a1920b73b2d5a057f8f8476a42b Edward Thomson 1355169715 -0600 checkout: moving from df_side1 to a765fb87eb2f7a1920b73b2d5a057f8f8476a42b^0 +a765fb87eb2f7a1920b73b2d5a057f8f8476a42b bc744705e1d8a019993cf88f62bc4020f1b80919 Edward Thomson 1355169801 -0600 commit: df_side1 +bc744705e1d8a019993cf88f62bc4020f1b80919 bc744705e1d8a019993cf88f62bc4020f1b80919 Edward Thomson 1355169822 -0600 checkout: moving from bc744705e1d8a019993cf88f62bc4020f1b80919 to df_side1 +bc744705e1d8a019993cf88f62bc4020f1b80919 fada9356aa3f74622327a3038ae9c6f92e1c5c1d Edward Thomson 1355169826 -0600 checkout: moving from df_side1 to df_side2 +fada9356aa3f74622327a3038ae9c6f92e1c5c1d a765fb87eb2f7a1920b73b2d5a057f8f8476a42b Edward Thomson 1355169866 -0600 checkout: moving from df_side2 to a765fb87eb2f7a1920b73b2d5a057f8f8476a42b^0 +a765fb87eb2f7a1920b73b2d5a057f8f8476a42b 95646149ab6b6ba6edc83cff678582538b457b2b Edward Thomson 1355169897 -0600 rebase: df_side2 +95646149ab6b6ba6edc83cff678582538b457b2b 95646149ab6b6ba6edc83cff678582538b457b2b Edward Thomson 1355169897 -0600 rebase finished: returning to refs/heads/df_side2 +95646149ab6b6ba6edc83cff678582538b457b2b bc744705e1d8a019993cf88f62bc4020f1b80919 Edward Thomson 1355169949 -0600 checkout: moving from df_side2 to df_side1 +bc744705e1d8a019993cf88f62bc4020f1b80919 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1355170046 -0600 checkout: moving from df_side1 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1355181639 -0600 checkout: moving from master to df_ancestor +bd593285fc7fe4ca18ccdbabf027f5d689101452 2da538570bc1e5b2c3e855bf702f35248ad0735f Edward Thomson 1355181673 -0600 commit: df_ancestor +2da538570bc1e5b2c3e855bf702f35248ad0735f a7dbfcbfc1a60709cb80b5ca24539008456531d0 Edward Thomson 1355181715 -0600 commit: df_side1 +a7dbfcbfc1a60709cb80b5ca24539008456531d0 a7dbfcbfc1a60709cb80b5ca24539008456531d0 Edward Thomson 1355181743 -0600 checkout: moving from df_ancestor to df_ancestor +a7dbfcbfc1a60709cb80b5ca24539008456531d0 9a301fbe6fada7dcb74fcd7c20269b5c743459a7 Edward Thomson 1355181775 -0600 commit: df_side2 +9a301fbe6fada7dcb74fcd7c20269b5c743459a7 a7dbfcbfc1a60709cb80b5ca24539008456531d0 Edward Thomson 1355181793 -0600 checkout: moving from df_ancestor to df_side1 +a7dbfcbfc1a60709cb80b5ca24539008456531d0 9a301fbe6fada7dcb74fcd7c20269b5c743459a7 Edward Thomson 1355181797 -0600 checkout: moving from df_side1 to df_side2 +9a301fbe6fada7dcb74fcd7c20269b5c743459a7 9a301fbe6fada7dcb74fcd7c20269b5c743459a7 Edward Thomson 1355182062 -0600 checkout: moving from df_side2 to df_ancestor +9a301fbe6fada7dcb74fcd7c20269b5c743459a7 2da538570bc1e5b2c3e855bf702f35248ad0735f Edward Thomson 1355182067 -0600 reset: moving to 2da538570bc1e5b2c3e855bf702f35248ad0735f +2da538570bc1e5b2c3e855bf702f35248ad0735f 2da538570bc1e5b2c3e855bf702f35248ad0735f Edward Thomson 1355182087 -0600 checkout: moving from df_ancestor to df_side2 +2da538570bc1e5b2c3e855bf702f35248ad0735f fc90237dc4891fa6c69827fc465632225e391618 Edward Thomson 1355182104 -0600 commit: df_side2 +fc90237dc4891fa6c69827fc465632225e391618 a7dbfcbfc1a60709cb80b5ca24539008456531d0 Edward Thomson 1355182111 -0600 checkout: moving from df_side2 to df_side1 +a7dbfcbfc1a60709cb80b5ca24539008456531d0 fc90237dc4891fa6c69827fc465632225e391618 Edward Thomson 1355182115 -0600 checkout: moving from df_side1 to df_side2 +fc90237dc4891fa6c69827fc465632225e391618 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1355182122 -0600 checkout: moving from df_side2 to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 d6cf6c7741b3316826af1314042550c97ded1d50 Edward Thomson 1358997543 -0600 checkout: moving from master to unrelated +d6cf6c7741b3316826af1314042550c97ded1d50 55b4e4687e7a0d9ca367016ed930f385d4022e6f Edward Thomson 1358997664 -0600 commit: conflicting changes +55b4e4687e7a0d9ca367016ed930f385d4022e6f bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1358997675 -0600 checkout: moving from unrelated to master +bd593285fc7fe4ca18ccdbabf027f5d689101452 88e185910a15cd13bdf44854ad037f4842b03b29 Edward Thomson 1365714471 -0500 checkout: moving from master to rename_conflict_ours +88e185910a15cd13bdf44854ad037f4842b03b29 bef6e37b3ee632ba74159168836f382fed21d77d Edward Thomson 1365714516 -0500 checkout: moving from rename_conflict_ours to bef6e37b3ee632ba74159168836f382fed21d77d +bef6e37b3ee632ba74159168836f382fed21d77d 01f149e1b8f84bd8896aaff6d6b22af88459ded0 Edward Thomson 1365714831 -0500 commit: rename ancestor +0000000000000000000000000000000000000000 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365714958 -0500 commit (initial): rename conflict ancestor +2392a2dacc9efb562b8635d6579fb458751c7c5b 88e185910a15cd13bdf44854ad037f4842b03b29 Edward Thomson 1365714980 -0500 checkout: moving from rename_conflict_ancestor to rename_conflict_ours +88e185910a15cd13bdf44854ad037f4842b03b29 7c2c5228c9e90170d4a35e6558e47163daf092e5 Edward Thomson 1365715250 -0500 commit: rename conflict ours +7c2c5228c9e90170d4a35e6558e47163daf092e5 2f4024ce528d36d8670c289cce5a7963e625bb0c Edward Thomson 1365715274 -0500 checkout: moving from rename_conflict_ours to rename_conflict_theirs +2f4024ce528d36d8670c289cce5a7963e625bb0c 56a638b76b75e068590ac999c2f8621e7f3e264c Edward Thomson 1365715362 -0500 commit: rename conflict theirs +56a638b76b75e068590ac999c2f8621e7f3e264c 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715368 -0500 checkout: moving from rename_conflict_theirs to rename_conflict_ancestor +2392a2dacc9efb562b8635d6579fb458751c7c5b 56a638b76b75e068590ac999c2f8621e7f3e264c Edward Thomson 1365715371 -0500 checkout: moving from rename_conflict_ancestor to rename_conflict_theirs +56a638b76b75e068590ac999c2f8621e7f3e264c 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715404 -0500 checkout: moving from rename_conflict_theirs to rename_conflict_ancestor +2392a2dacc9efb562b8635d6579fb458751c7c5b 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715438 -0500 checkout: moving from rename_conflict_ancestor to rename_conflict_ours +2392a2dacc9efb562b8635d6579fb458751c7c5b 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715480 -0500 checkout: moving from rename_conflict_ours to rename_conflict_ancestor +2392a2dacc9efb562b8635d6579fb458751c7c5b 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715486 -0500 checkout: moving from rename_conflict_ancestor to rename_conflict_ours +2392a2dacc9efb562b8635d6579fb458751c7c5b f3293571dcd708b6a3faf03818cd2844d000e198 Edward Thomson 1365715538 -0500 commit: rename conflict ours +f3293571dcd708b6a3faf03818cd2844d000e198 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715546 -0500 checkout: moving from rename_conflict_ours to rename_conflict_ancestor +2392a2dacc9efb562b8635d6579fb458751c7c5b 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715550 -0500 checkout: moving from rename_conflict_ancestor to rename_conflict_thiers +2392a2dacc9efb562b8635d6579fb458751c7c5b 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715554 -0500 checkout: moving from rename_conflict_thiers to rename_conflict_ancestor +2392a2dacc9efb562b8635d6579fb458751c7c5b 2392a2dacc9efb562b8635d6579fb458751c7c5b Edward Thomson 1365715557 -0500 checkout: moving from rename_conflict_ancestor to rename_conflict_theirs +2392a2dacc9efb562b8635d6579fb458751c7c5b a802e06f1782a9645b9851bc7202cee74a8a4972 Edward Thomson 1365715572 -0500 commit: rename conflict theirs +a802e06f1782a9645b9851bc7202cee74a8a4972 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1365715620 -0500 checkout: moving from rename_conflict_theirs to master diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/branch new file mode 100644 index 000000000..8b0acb702 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351563886 -0500 branch: Created from HEAD +c607fc30883e335def28cd686b51f6cfa02b06ec 7cb63eed597130ba4abb87b3e544b85021905520 Edward Thomson 1351563965 -0500 commit: branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/df_ancestor b/tests/resources/merge-resolve/.gitted/logs/refs/heads/df_ancestor new file mode 100644 index 000000000..df7695a66 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/df_ancestor @@ -0,0 +1,5 @@ +0000000000000000000000000000000000000000 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1355181639 -0600 branch: Created from HEAD +bd593285fc7fe4ca18ccdbabf027f5d689101452 2da538570bc1e5b2c3e855bf702f35248ad0735f Edward Thomson 1355181673 -0600 commit: df_ancestor +2da538570bc1e5b2c3e855bf702f35248ad0735f a7dbfcbfc1a60709cb80b5ca24539008456531d0 Edward Thomson 1355181715 -0600 commit: df_side1 +a7dbfcbfc1a60709cb80b5ca24539008456531d0 9a301fbe6fada7dcb74fcd7c20269b5c743459a7 Edward Thomson 1355181775 -0600 commit: df_side2 +9a301fbe6fada7dcb74fcd7c20269b5c743459a7 2da538570bc1e5b2c3e855bf702f35248ad0735f Edward Thomson 1355182067 -0600 reset: moving to 2da538570bc1e5b2c3e855bf702f35248ad0735f diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/df_side1 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/df_side1 new file mode 100644 index 000000000..a504ad610 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/df_side1 @@ -0,0 +1,14 @@ +0000000000000000000000000000000000000000 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1354574697 -0600 branch: Created from HEAD +bd593285fc7fe4ca18ccdbabf027f5d689101452 d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1354574962 -0600 commit: df_ancestor +d4207f77243500bec335ab477f9227fcdb1e271a c94b27e41064c521120627e07e2035cca1d24ffa Edward Thomson 1354575027 -0600 commit: df_side1 +c94b27e41064c521120627e07e2035cca1d24ffa a90bc3fb6f15181972a2959a921429efbd81a473 Edward Thomson 1355017650 -0600 commit: df_added +a90bc3fb6f15181972a2959a921429efbd81a473 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355017676 -0600 rebase -i (finish): refs/heads/df_side1 onto c94b27e +005b6fcc8fec71d2550bef8462d169b3c26aa14b f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 Edward Thomson 1355017715 -0600 reset: moving to df_side2 +f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 8c749d9968d4b10dcfb06c9f97d0e5d92d337071 Edward Thomson 1355017744 -0600 commit: df_added +8c749d9968d4b10dcfb06c9f97d0e5d92d337071 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355017756 -0600 rebase -i (finish): refs/heads/df_side1 onto f8958bd +0204a84f822acbf6386b36d33f1f6bc68bbbf858 005b6fcc8fec71d2550bef8462d169b3c26aa14b Edward Thomson 1355017793 -0600 reset: moving to 005b6fcc8fec71d2550bef8462d169b3c26aa14b +005b6fcc8fec71d2550bef8462d169b3c26aa14b 0204a84f822acbf6386b36d33f1f6bc68bbbf858 Edward Thomson 1355017826 -0600 reset: moving to 0204a84 +005b6fcc8fec71d2550bef8462d169b3c26aa14b e8107f24196736b870a318a0e28f048e29f6feff Edward Thomson 1355169065 -0600 commit: df_side1 +e8107f24196736b870a318a0e28f048e29f6feff 80a8fbb3abb1ba423d554e9630b8fc2e5698f86b Edward Thomson 1355169084 -0600 rebase -i (finish): refs/heads/df_side1 onto 005b6fc +80a8fbb3abb1ba423d554e9630b8fc2e5698f86b e65a9bb2af9f4c2d1c375dd0f8f8a46cf9c68812 Edward Thomson 1355169419 -0600 commit: side1 +e65a9bb2af9f4c2d1c375dd0f8f8a46cf9c68812 5dc1018e90b19654bee986b7a0c268804d39659d Edward Thomson 1355169435 -0600 rebase -i (finish): refs/heads/df_side1 onto 80a8fbb diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/df_side2 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/df_side2 new file mode 100644 index 000000000..27d833eda --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/df_side2 @@ -0,0 +1,9 @@ +0000000000000000000000000000000000000000 d4207f77243500bec335ab477f9227fcdb1e271a Edward Thomson 1354575051 -0600 branch: Created from d4207f77243500bec335ab477f9227fcdb1e271a +d4207f77243500bec335ab477f9227fcdb1e271a f8958bdf4d365a84a9a178b1f5f35ff1dacbd884 Edward Thomson 1354575206 -0600 commit: df_side2 +0204a84f822acbf6386b36d33f1f6bc68bbbf858 944f5dd1a867cab4c2bbcb896493435cae1dcc1a Edward Thomson 1355169174 -0600 commit: both +944f5dd1a867cab4c2bbcb896493435cae1dcc1a 57079a46233ae2b6df62e9ade71c4948512abefb Edward Thomson 1355169185 -0600 rebase -i (finish): refs/heads/df_side2 onto 0204a84 +57079a46233ae2b6df62e9ade71c4948512abefb 58e853f66699fd02629fd50bde08082bc005933a Edward Thomson 1355169460 -0600 commit: side2 +58e853f66699fd02629fd50bde08082bc005933a fada9356aa3f74622327a3038ae9c6f92e1c5c1d Edward Thomson 1355169471 -0600 rebase -i (finish): refs/heads/df_side2 onto 57079a4 +fada9356aa3f74622327a3038ae9c6f92e1c5c1d 95646149ab6b6ba6edc83cff678582538b457b2b Edward Thomson 1355169897 -0600 rebase finished: refs/heads/df_side2 onto a765fb87eb2f7a1920b73b2d5a057f8f8476a42b +0000000000000000000000000000000000000000 2da538570bc1e5b2c3e855bf702f35248ad0735f Edward Thomson 1355182087 -0600 branch: Created from HEAD +2da538570bc1e5b2c3e855bf702f35248ad0735f fc90237dc4891fa6c69827fc465632225e391618 Edward Thomson 1355182104 -0600 commit: df_side2 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/ff_branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/ff_branch new file mode 100644 index 000000000..c4706175d --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/ff_branch @@ -0,0 +1,5 @@ +0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351605785 -0500 branch: Created from HEAD +977c696519c5a3004c5f1d15d60c89dbeb8f235f 33d500f588fbbe65901d82b4e6b008e549064be0 Edward Thomson 1351605830 -0500 commit: fastforward +33d500f588fbbe65901d82b4e6b008e549064be0 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351990202 -0500 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1351990205 -0500 merge master: Fast-forward +bd593285fc7fe4ca18ccdbabf027f5d689101452 fd89f8cffb663ac89095a0f9764902e93ceaca6a Edward Thomson 1351990229 -0500 commit: fastforward diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/master b/tests/resources/merge-resolve/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..60475992a --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/master @@ -0,0 +1,5 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1351563869 -0500 commit (initial): initial +c607fc30883e335def28cd686b51f6cfa02b06ec 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351564033 -0500 commit: master +977c696519c5a3004c5f1d15d60c89dbeb8f235f 4e0d9401aee78eb345a8685a859d37c8c3c0bbed Edward Thomson 1351875091 -0500 merge octo1 octo2 octo3 octo4: Merge made by the 'octopus' strategy. +4e0d9401aee78eb345a8685a859d37c8c3c0bbed 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae Edward Thomson 1351875108 -0500 reset: moving to 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae +54269b3f6ec3d7d4ede24dd350dd5d605495c3ae 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875584 -0500 reset: moving to 977c696519c5a3004c5f1d15d60c89dbeb8f235f diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo1 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo1 new file mode 100644 index 000000000..0b6c9214a --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo1 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874933 -0500 branch: Created from HEAD +977c696519c5a3004c5f1d15d60c89dbeb8f235f 16f825815cfd20a07a75c71554e82d8eede0b061 Edward Thomson 1351874954 -0500 commit: octo1 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo2 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo2 new file mode 100644 index 000000000..5392a4f86 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo2 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874960 -0500 branch: Created from HEAD +977c696519c5a3004c5f1d15d60c89dbeb8f235f 158dc7bedb202f5b26502bf3574faa7f4238d56c Edward Thomson 1351874974 -0500 commit: octo2 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo3 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo3 new file mode 100644 index 000000000..7db5617c8 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo3 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351874980 -0500 branch: Created from HEAD +977c696519c5a3004c5f1d15d60c89dbeb8f235f 50ce7d7d01217679e26c55939eef119e0c93e272 Edward Thomson 1351874998 -0500 commit: octo3 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo4 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo4 new file mode 100644 index 000000000..b0f9e42ef --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo4 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875010 -0500 branch: Created from HEAD +977c696519c5a3004c5f1d15d60c89dbeb8f235f 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae Edward Thomson 1351875023 -0500 commit: octo4 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo5 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo5 new file mode 100644 index 000000000..614563edf --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo5 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875031 -0500 branch: Created from HEAD +977c696519c5a3004c5f1d15d60c89dbeb8f235f e4f618a2c3ed0669308735727df5ebf2447f022f Edward Thomson 1351875041 -0500 commit: octo5 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo6 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo6 new file mode 100644 index 000000000..4c812eacc --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/octo6 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 977c696519c5a3004c5f1d15d60c89dbeb8f235f Edward Thomson 1351875046 -0500 branch: Created from HEAD +977c696519c5a3004c5f1d15d60c89dbeb8f235f 4ca408a8c88655f7586a1b580be6fad138121e98 Edward Thomson 1351875057 -0500 commit: octo5 +4ca408a8c88655f7586a1b580be6fad138121e98 b6f610aef53bd343e6c96227de874c66f00ee8e8 Edward Thomson 1351875065 -0500 commit (amend): octo6 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/renames1 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/renames1 new file mode 100644 index 000000000..58a7e0565 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/renames1 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1353177745 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 412b32fb66137366147f1801ecc962452757d48a Edward Thomson 1353177886 -0600 commit: renames diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/renames2 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/renames2 new file mode 100644 index 000000000..5645ecee7 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/renames2 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 bd593285fc7fe4ca18ccdbabf027f5d689101452 Edward Thomson 1353794647 -0600 branch: Created from HEAD +bd593285fc7fe4ca18ccdbabf027f5d689101452 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1353794677 -0600 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec ab40af3cb8a3ed2e2843e96d9aa7871336b94573 Edward Thomson 1353794852 -0600 commit: renames2 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10 new file mode 100644 index 000000000..b6bd247e7 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100171 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 53825f41ac8d640612f9423a2f03a69f3d96809a Edward Thomson 1352100193 -0600 commit: trivial-10 +53825f41ac8d640612f9423a2f03a69f3d96809a 0ec5f433959cd46177f745903353efb5be08d151 Edward Thomson 1352100223 -0600 commit: trivial-10 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10-branch new file mode 100644 index 000000000..14ce9e545 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-10-branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 53825f41ac8d640612f9423a2f03a69f3d96809a Edward Thomson 1352100200 -0600 branch: Created from HEAD +53825f41ac8d640612f9423a2f03a69f3d96809a 11f4f3c08b737f5fd896cbefa1425ee63b21b2fa Edward Thomson 1352100211 -0600 commit: trivial-10-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11 new file mode 100644 index 000000000..3e6b77437 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100930 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 35632e43612c06a3ea924bfbacd48333da874c29 Edward Thomson 1352100958 -0600 commit: trivial-11 +35632e43612c06a3ea924bfbacd48333da874c29 3168dca1a561889b045a6441909f4c56145e666d Edward Thomson 1352100992 -0600 commit: trivial-11 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11-branch new file mode 100644 index 000000000..30d5ec7a3 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-11-branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 35632e43612c06a3ea924bfbacd48333da874c29 Edward Thomson 1352100964 -0600 branch: Created from HEAD +35632e43612c06a3ea924bfbacd48333da874c29 6718a45909532d1fcf5600d0877f7fe7e78f0b86 Edward Thomson 1352100978 -0600 commit: trivial-11-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13 new file mode 100644 index 000000000..3a7302dea --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100559 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa Edward Thomson 1352100589 -0600 commit: trivial-13 +8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa a3fabece9eb8748da810e1e08266fef9b7136ad4 Edward Thomson 1352100625 -0600 commit: trivial-13 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13-branch new file mode 100644 index 000000000..bb2604244 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-13-branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa Edward Thomson 1352100604 -0600 branch: Created from HEAD +8f4433f8593ddd65b7dd43dd4564d841f4d9c8aa 05f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c Edward Thomson 1352100610 -0600 commit: trivial-13-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14 new file mode 100644 index 000000000..4b70d2898 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352101083 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 596803b523203a4851c824c07366906f8353f4ad Edward Thomson 1352101113 -0600 commit: trivial-14 +596803b523203a4851c824c07366906f8353f4ad 7e2d058d5fedf8329db44db4fac610d6b1a89159 Edward Thomson 1352101141 -0600 commit: trivial-14 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14-branch new file mode 100644 index 000000000..8e491ca68 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-14-branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 596803b523203a4851c824c07366906f8353f4ad Edward Thomson 1352101117 -0600 branch: Created from HEAD +596803b523203a4851c824c07366906f8353f4ad 8187117062b750eed4f93fd7e899f17b52ce554d Edward Thomson 1352101132 -0600 commit: trivial-14-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt new file mode 100644 index 000000000..a2a28d401 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352091695 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 566ab53c220a2eafc1212af1a024513230280ab9 Edward Thomson 1352092452 -0600 commit: 2alt diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt-branch new file mode 100644 index 000000000..a0a48ae35 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-2alt-branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352092411 -0600 branch: Created from HEAD +c607fc30883e335def28cd686b51f6cfa02b06ec c9174cef549ec94ecbc43ef03cdc775b4950becb Edward Thomson 1352092434 -0600 commit: 2alt-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt new file mode 100644 index 000000000..4374d3888 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt @@ -0,0 +1,3 @@ +566ab53c220a2eafc1212af1a024513230280ab9 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094547 -0600 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 5459c89aa0026d543ce8343bd89871bce543f9c2 Edward Thomson 1352094580 -0600 commit: 3alt +5459c89aa0026d543ce8343bd89871bce543f9c2 4c9fac0707f8d4195037ae5a681aa48626491541 Edward Thomson 1352094610 -0600 commit: 3alt-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt-branch new file mode 100644 index 000000000..7a2e6f822 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-3alt-branch @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094594 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4 new file mode 100644 index 000000000..3ee6d2503 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4 @@ -0,0 +1,2 @@ +566ab53c220a2eafc1212af1a024513230280ab9 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094764 -0600 reset: moving to c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec cc3e3009134cb88014129fc8858d1101359e5e2f Edward Thomson 1352094815 -0600 commit: trivial-4 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4-branch new file mode 100644 index 000000000..51f8a9290 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-4-branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352094830 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 183310e30fb1499af8c619108ffea4d300b5e778 Edward Thomson 1352094856 -0600 commit: trivial-4-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1 new file mode 100644 index 000000000..14497029a --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096606 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 Edward Thomson 1352096643 -0600 commit: 5alt-1 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1-branch new file mode 100644 index 000000000..4cff83526 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-1-branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096657 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 478172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 Edward Thomson 1352096689 -0600 commit: 5alt-1-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2 new file mode 100644 index 000000000..3ca077b29 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352096711 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec ebc09d0137cfb0c26697aed0109fb943ad906f3f Edward Thomson 1352096764 -0600 commit: existing file +ebc09d0137cfb0c26697aed0109fb943ad906f3f 3b47b031b3e55ae11e14a05260b1c3ffd6838d55 Edward Thomson 1352096815 -0600 commit: 5alt-2 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2-branch new file mode 100644 index 000000000..e7bb901f2 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-5alt-2-branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 ebc09d0137cfb0c26697aed0109fb943ad906f3f Edward Thomson 1352096833 -0600 branch: Created from ebc09d0 +ebc09d0137cfb0c26697aed0109fb943ad906f3f f48097eb340dc5a7cae55aabcf1faf4548aa821f Edward Thomson 1352096855 -0600 commit: 5alt-2-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6 new file mode 100644 index 000000000..7c717a210 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352097371 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec f7c332bd4d4d4b777366cae4d24d1687477576bf Edward Thomson 1352097389 -0600 commit: 6 +f7c332bd4d4d4b777366cae4d24d1687477576bf 99b4f7e4f24470fa06b980bc21f1095c2a9425c0 Edward Thomson 1352097404 -0600 commit: trivial-6 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6-branch new file mode 100644 index 000000000..715f3ae1c --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-6-branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 f7c332bd4d4d4b777366cae4d24d1687477576bf Edward Thomson 1352097414 -0600 branch: Created from f7c332bd4d4d4b777366cae4d24d1687477576bf +f7c332bd4d4d4b777366cae4d24d1687477576bf a43150a738849c59376cf30bb2a68348a83c8f48 Edward Thomson 1352097431 -0600 commit: 6-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7 new file mode 100644 index 000000000..a014f1722 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352099765 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099790 -0600 commit: trivial-7 +092ce8682d7f3a2a3a769a6daca58950168ba5c4 d874671ef5b20184836cb983bb273e5280384d0b Edward Thomson 1352099947 -0600 commit: trivial-7 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7-branch new file mode 100644 index 000000000..22331d78c --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-7-branch @@ -0,0 +1,5 @@ +0000000000000000000000000000000000000000 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099799 -0600 branch: Created from HEAD +092ce8682d7f3a2a3a769a6daca58950168ba5c4 73cbfdc4fe843169e5b2af8dcad03cbf3acf306c Edward Thomson 1352099812 -0600 commit: trivial-7-branch +73cbfdc4fe843169e5b2af8dcad03cbf3acf306c 092ce8682d7f3a2a3a769a6daca58950168ba5c4 Edward Thomson 1352099874 -0600 reset: moving to 092ce8682d7f3a2a3a769a6daca58950168ba5c4 +092ce8682d7f3a2a3a769a6daca58950168ba5c4 009b9cab6fdac02915a88ecd078b7a792ed802d8 Edward Thomson 1352099921 -0600 commit: removed in 7 +009b9cab6fdac02915a88ecd078b7a792ed802d8 5195a1b480f66691b667f10a9e41e70115a78351 Edward Thomson 1352099927 -0600 commit (amend): trivial-7-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8 new file mode 100644 index 000000000..7670c3506 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352098816 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec 75a811bf6bc57694adb3fe604786f3a4efd1cd1b Edward Thomson 1352098884 -0600 commit: trivial-8 +75a811bf6bc57694adb3fe604786f3a4efd1cd1b 3575826c96a975031d2c14368529cc5c4353a8fd Edward Thomson 1352099000 -0600 commit: trivial-8 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8-branch new file mode 100644 index 000000000..c4d68edcf --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-8-branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 75a811bf6bc57694adb3fe604786f3a4efd1cd1b Edward Thomson 1352098947 -0600 branch: Created from HEAD +75a811bf6bc57694adb3fe604786f3a4efd1cd1b 52d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 Edward Thomson 1352098979 -0600 commit: trivial-8-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9 b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9 new file mode 100644 index 000000000..09a343bdb --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 c607fc30883e335def28cd686b51f6cfa02b06ec Edward Thomson 1352100268 -0600 branch: Created from c607fc30883e335def28cd686b51f6cfa02b06ec +c607fc30883e335def28cd686b51f6cfa02b06ec f0053b8060bb3f0be5cbcc3147a07ece26bf097e Edward Thomson 1352100304 -0600 commit: trivial-9 +f0053b8060bb3f0be5cbcc3147a07ece26bf097e c35dee9bcc0e989f3b0c40f68372a9a51b6c4e6a Edward Thomson 1352100333 -0600 commit: trivial-9 diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9-branch b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9-branch new file mode 100644 index 000000000..1b126fb7b --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/trivial-9-branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 f0053b8060bb3f0be5cbcc3147a07ece26bf097e Edward Thomson 1352100310 -0600 branch: Created from HEAD +f0053b8060bb3f0be5cbcc3147a07ece26bf097e 13d1be4ea52a6ced1d7a1d832f0ee3c399348e5e Edward Thomson 1352100317 -0600 commit: trivial-9-branch diff --git a/tests/resources/merge-resolve/.gitted/logs/refs/heads/unrelated b/tests/resources/merge-resolve/.gitted/logs/refs/heads/unrelated new file mode 100644 index 000000000..a83ffc26a --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/logs/refs/heads/unrelated @@ -0,0 +1 @@ +d6cf6c7741b3316826af1314042550c97ded1d50 55b4e4687e7a0d9ca367016ed930f385d4022e6f Edward Thomson 1358997664 -0600 commit: conflicting changes diff --git a/tests/resources/merge-resolve/.gitted/objects/00/5b6fcc8fec71d2550bef8462d169b3c26aa14b b/tests/resources/merge-resolve/.gitted/objects/00/5b6fcc8fec71d2550bef8462d169b3c26aa14b new file mode 100644 index 000000000..82a8da597 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/00/5b6fcc8fec71d2550bef8462d169b3c26aa14b differ diff --git a/tests/resources/merge-resolve/.gitted/objects/00/9b9cab6fdac02915a88ecd078b7a792ed802d8 b/tests/resources/merge-resolve/.gitted/objects/00/9b9cab6fdac02915a88ecd078b7a792ed802d8 new file mode 100644 index 000000000..f663a3c51 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/00/9b9cab6fdac02915a88ecd078b7a792ed802d8 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/00/c7d33f1ffa79d19c2272b370fcaeaadba49c08 b/tests/resources/merge-resolve/.gitted/objects/00/c7d33f1ffa79d19c2272b370fcaeaadba49c08 new file mode 100644 index 000000000..72698dc3d Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/00/c7d33f1ffa79d19c2272b370fcaeaadba49c08 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/01/f149e1b8f84bd8896aaff6d6b22af88459ded0 b/tests/resources/merge-resolve/.gitted/objects/01/f149e1b8f84bd8896aaff6d6b22af88459ded0 new file mode 100644 index 000000000..aa6336d3f Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/01/f149e1b8f84bd8896aaff6d6b22af88459ded0 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/02/04a84f822acbf6386b36d33f1f6bc68bbbf858 b/tests/resources/merge-resolve/.gitted/objects/02/04a84f822acbf6386b36d33f1f6bc68bbbf858 new file mode 100644 index 000000000..2f0a0e1bb Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/02/04a84f822acbf6386b36d33f1f6bc68bbbf858 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/02/251f990ca8e92e7ae61d3426163fa821c64001 b/tests/resources/merge-resolve/.gitted/objects/02/251f990ca8e92e7ae61d3426163fa821c64001 new file mode 100644 index 000000000..d623117c5 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/02/251f990ca8e92e7ae61d3426163fa821c64001 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/03/21415405cb906c46869919af56d51dbbe5e85c b/tests/resources/merge-resolve/.gitted/objects/03/21415405cb906c46869919af56d51dbbe5e85c new file mode 100644 index 000000000..277bdcff5 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/03/21415405cb906c46869919af56d51dbbe5e85c differ diff --git a/tests/resources/merge-resolve/.gitted/objects/03/2ebc5ab85d9553bb187d3cd40875ff23a63ed0 b/tests/resources/merge-resolve/.gitted/objects/03/2ebc5ab85d9553bb187d3cd40875ff23a63ed0 new file mode 100644 index 000000000..e5404d838 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/03/2ebc5ab85d9553bb187d3cd40875ff23a63ed0 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/03/b87706555accbf874ccd410dbda01e8e70a67f b/tests/resources/merge-resolve/.gitted/objects/03/b87706555accbf874ccd410dbda01e8e70a67f new file mode 100644 index 000000000..0befcd735 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/03/b87706555accbf874ccd410dbda01e8e70a67f differ diff --git a/tests/resources/merge-resolve/.gitted/objects/03/dad1005e5d06d418f50b12e0bcd48ff2306a03 b/tests/resources/merge-resolve/.gitted/objects/03/dad1005e5d06d418f50b12e0bcd48ff2306a03 new file mode 100644 index 000000000..04011a2ce Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/03/dad1005e5d06d418f50b12e0bcd48ff2306a03 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/05/1ffd7901a442faf56b226161649074f15c7c47 b/tests/resources/merge-resolve/.gitted/objects/05/1ffd7901a442faf56b226161649074f15c7c47 new file mode 100644 index 000000000..65fa6894f --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/05/1ffd7901a442faf56b226161649074f15c7c47 @@ -0,0 +1 @@ +x+)JMU06`040031QH,-M-JOMLI+(aH:,:C: o>ZC'g$楧f&%%g5qYeZokM2ԐX\ZDPC~^ZNfrIf^:XZHي1O(_,' jvn~JfZ&5&ؽ +gz43^2 I{| 2mg˾15ӿ,\})TC)0Xvz֛9MՅ'6b# \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/05/8541fc37114bfc1dddf6bd6bffc7fae5c2e6fe b/tests/resources/merge-resolve/.gitted/objects/05/8541fc37114bfc1dddf6bd6bffc7fae5c2e6fe new file mode 100644 index 000000000..d79dc30ba Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/05/8541fc37114bfc1dddf6bd6bffc7fae5c2e6fe differ diff --git a/tests/resources/merge-resolve/.gitted/objects/05/f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c b/tests/resources/merge-resolve/.gitted/objects/05/f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c new file mode 100644 index 000000000..7b4b152f3 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/05/f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c differ diff --git a/tests/resources/merge-resolve/.gitted/objects/07/a759da919f737221791d542f176ab49c88837f b/tests/resources/merge-resolve/.gitted/objects/07/a759da919f737221791d542f176ab49c88837f new file mode 100644 index 000000000..a34b6c235 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/07/a759da919f737221791d542f176ab49c88837f differ diff --git a/tests/resources/merge-resolve/.gitted/objects/07/c514b04698e068892b31c8d352b85813b99c6e b/tests/resources/merge-resolve/.gitted/objects/07/c514b04698e068892b31c8d352b85813b99c6e new file mode 100644 index 000000000..23ab92171 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/07/c514b04698e068892b31c8d352b85813b99c6e differ diff --git a/tests/resources/merge-resolve/.gitted/objects/09/055301463b7f2f8ee5d368f8ed5c0a40ad8515 b/tests/resources/merge-resolve/.gitted/objects/09/055301463b7f2f8ee5d368f8ed5c0a40ad8515 new file mode 100644 index 000000000..bf5b0fcc5 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/09/055301463b7f2f8ee5d368f8ed5c0a40ad8515 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/09/17bb159596aea4d295f4857da77e8f96b3c7dc b/tests/resources/merge-resolve/.gitted/objects/09/17bb159596aea4d295f4857da77e8f96b3c7dc new file mode 100644 index 000000000..9fb640dd5 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/09/17bb159596aea4d295f4857da77e8f96b3c7dc differ diff --git a/tests/resources/merge-resolve/.gitted/objects/09/2ce8682d7f3a2a3a769a6daca58950168ba5c4 b/tests/resources/merge-resolve/.gitted/objects/09/2ce8682d7f3a2a3a769a6daca58950168ba5c4 new file mode 100644 index 000000000..b709cf461 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/09/2ce8682d7f3a2a3a769a6daca58950168ba5c4 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/09/3bebf072dd4bbba88833667d6ffe454df199e1 b/tests/resources/merge-resolve/.gitted/objects/09/3bebf072dd4bbba88833667d6ffe454df199e1 new file mode 100644 index 000000000..ae13207d7 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/09/3bebf072dd4bbba88833667d6ffe454df199e1 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/09/768bed22680cdb0859683fa9677ccc8d5a25c1 b/tests/resources/merge-resolve/.gitted/objects/09/768bed22680cdb0859683fa9677ccc8d5a25c1 new file mode 100644 index 000000000..5f4b4dab1 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/09/768bed22680cdb0859683fa9677ccc8d5a25c1 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/0a/75d9aac1dc84fb5aa51f7325c0ab53242ddef7 b/tests/resources/merge-resolve/.gitted/objects/0a/75d9aac1dc84fb5aa51f7325c0ab53242ddef7 new file mode 100644 index 000000000..d5377341a Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/0a/75d9aac1dc84fb5aa51f7325c0ab53242ddef7 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/0c/fd6c54ef6532d862408f562309dc9c74a401e8 b/tests/resources/merge-resolve/.gitted/objects/0c/fd6c54ef6532d862408f562309dc9c74a401e8 new file mode 100644 index 000000000..40f628f89 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/0c/fd6c54ef6532d862408f562309dc9c74a401e8 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/0d/52e3a556e189ba0948ae56780918011c1b167d b/tests/resources/merge-resolve/.gitted/objects/0d/52e3a556e189ba0948ae56780918011c1b167d new file mode 100644 index 000000000..4b633e504 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/0d/52e3a556e189ba0948ae56780918011c1b167d differ diff --git a/tests/resources/merge-resolve/.gitted/objects/0d/872f8e871a30208305978ecbf9e66d864f1638 b/tests/resources/merge-resolve/.gitted/objects/0d/872f8e871a30208305978ecbf9e66d864f1638 new file mode 100644 index 000000000..4cbc18e84 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/0d/872f8e871a30208305978ecbf9e66d864f1638 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/0e/c5f433959cd46177f745903353efb5be08d151 b/tests/resources/merge-resolve/.gitted/objects/0e/c5f433959cd46177f745903353efb5be08d151 new file mode 100644 index 000000000..1bee56c14 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/0e/c5f433959cd46177f745903353efb5be08d151 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/11/deab00b2d3a6f5a3073988ac050c2d7b6655e2 b/tests/resources/merge-resolve/.gitted/objects/11/deab00b2d3a6f5a3073988ac050c2d7b6655e2 new file mode 100644 index 000000000..857b23686 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/11/deab00b2d3a6f5a3073988ac050c2d7b6655e2 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/11/f4f3c08b737f5fd896cbefa1425ee63b21b2fa b/tests/resources/merge-resolve/.gitted/objects/11/f4f3c08b737f5fd896cbefa1425ee63b21b2fa new file mode 100644 index 000000000..6555194cb --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/11/f4f3c08b737f5fd896cbefa1425ee63b21b2fa @@ -0,0 +1 @@ +xQ D\fw)c^` ۴-Q/ơdb^ץjEDC$u> , z@8qjk<٩G>z2Lva2)Veŏ:%˜{A|Ǽ5K@mg9jY _;n,YyP \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/13/d1be4ea52a6ced1d7a1d832f0ee3c399348e5e b/tests/resources/merge-resolve/.gitted/objects/13/d1be4ea52a6ced1d7a1d832f0ee3c399348e5e new file mode 100644 index 000000000..4e4e175e8 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/13/d1be4ea52a6ced1d7a1d832f0ee3c399348e5e differ diff --git a/tests/resources/merge-resolve/.gitted/objects/14/39088f509b79b1535b64193137d3ce4b240734 b/tests/resources/merge-resolve/.gitted/objects/14/39088f509b79b1535b64193137d3ce4b240734 new file mode 100644 index 000000000..51ddf6dcb Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/14/39088f509b79b1535b64193137d3ce4b240734 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/15/8dc7bedb202f5b26502bf3574faa7f4238d56c b/tests/resources/merge-resolve/.gitted/objects/15/8dc7bedb202f5b26502bf3574faa7f4238d56c new file mode 100644 index 000000000..064423d0c --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/15/8dc7bedb202f5b26502bf3574faa7f4238d56c @@ -0,0 +1,2 @@ +xK!D]sCboi2. bK*Eep73UӾ*NYYIԔ)jL:8<{NޓH6iDC"mqH!9Tm9>R^i.= +G'+~@@j+7أENsFt]7bN) \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/16/f825815cfd20a07a75c71554e82d8eede0b061 b/tests/resources/merge-resolve/.gitted/objects/16/f825815cfd20a07a75c71554e82d8eede0b061 new file mode 100644 index 000000000..82d65253b --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/16/f825815cfd20a07a75c71554e82d8eede0b061 @@ -0,0 +1 @@ +xK!D]sObo hJqo6AJـT1h3'Lՠ.{ec,a`ZJT1#e+هJUi">\+ ץG_X6IvN;^bYgGMM \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/17/8940b450f238a56c0d75b7955cb57b38191982 b/tests/resources/merge-resolve/.gitted/objects/17/8940b450f238a56c0d75b7955cb57b38191982 new file mode 100644 index 000000000..94e571e65 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/17/8940b450f238a56c0d75b7955cb57b38191982 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/18/3310e30fb1499af8c619108ffea4d300b5e778 b/tests/resources/merge-resolve/.gitted/objects/18/3310e30fb1499af8c619108ffea4d300b5e778 new file mode 100644 index 000000000..1c4010d04 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/18/3310e30fb1499af8c619108ffea4d300b5e778 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/18/cb316b1cefa0f8a6946f0e201a8e1a6f845ab9 b/tests/resources/merge-resolve/.gitted/objects/18/cb316b1cefa0f8a6946f0e201a8e1a6f845ab9 new file mode 100644 index 000000000..30f3110f1 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/18/cb316b1cefa0f8a6946f0e201a8e1a6f845ab9 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/19/b7ac485269b672a101060894de3ba9c2a24dd1 b/tests/resources/merge-resolve/.gitted/objects/19/b7ac485269b672a101060894de3ba9c2a24dd1 new file mode 100644 index 000000000..e34ccb855 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/19/b7ac485269b672a101060894de3ba9c2a24dd1 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/1a/010b1c0f081b2e8901d55307a15c29ff30af0e b/tests/resources/merge-resolve/.gitted/objects/1a/010b1c0f081b2e8901d55307a15c29ff30af0e new file mode 100644 index 000000000..6039df00e Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/1a/010b1c0f081b2e8901d55307a15c29ff30af0e differ diff --git a/tests/resources/merge-resolve/.gitted/objects/1c/ff9ec6a47a537380dedfdd17c9e76d74259a2b b/tests/resources/merge-resolve/.gitted/objects/1c/ff9ec6a47a537380dedfdd17c9e76d74259a2b new file mode 100644 index 000000000..30802bcec Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/1c/ff9ec6a47a537380dedfdd17c9e76d74259a2b differ diff --git a/tests/resources/merge-resolve/.gitted/objects/1e/4ff029aee68d0d69ef9eb6efa6cbf1ec732f99 b/tests/resources/merge-resolve/.gitted/objects/1e/4ff029aee68d0d69ef9eb6efa6cbf1ec732f99 new file mode 100644 index 000000000..5183b8360 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/1e/4ff029aee68d0d69ef9eb6efa6cbf1ec732f99 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/1f/81433e3161efbf250576c58fede7f6b836f3d3 b/tests/resources/merge-resolve/.gitted/objects/1f/81433e3161efbf250576c58fede7f6b836f3d3 new file mode 100644 index 000000000..970855675 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/1f/81433e3161efbf250576c58fede7f6b836f3d3 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/20/91d94c8bd3eb0835dc5220de5e8bb310fa1513 b/tests/resources/merge-resolve/.gitted/objects/20/91d94c8bd3eb0835dc5220de5e8bb310fa1513 new file mode 100644 index 000000000..a843890c0 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/20/91d94c8bd3eb0835dc5220de5e8bb310fa1513 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/21/671e290278286fb2ce4c63d01699b67adce331 b/tests/resources/merge-resolve/.gitted/objects/21/671e290278286fb2ce4c63d01699b67adce331 new file mode 100644 index 000000000..b656d0001 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/21/671e290278286fb2ce4c63d01699b67adce331 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/22/7792b52aaa0b238bea00ec7e509b02623f168c b/tests/resources/merge-resolve/.gitted/objects/22/7792b52aaa0b238bea00ec7e509b02623f168c new file mode 100644 index 000000000..3bb19bb77 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/22/7792b52aaa0b238bea00ec7e509b02623f168c differ diff --git a/tests/resources/merge-resolve/.gitted/objects/23/3c0919c998ed110a4b6ff36f353aec8b713487 b/tests/resources/merge-resolve/.gitted/objects/23/3c0919c998ed110a4b6ff36f353aec8b713487 new file mode 100644 index 000000000..d0c8c9e1d Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/23/3c0919c998ed110a4b6ff36f353aec8b713487 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/23/92a2dacc9efb562b8635d6579fb458751c7c5b b/tests/resources/merge-resolve/.gitted/objects/23/92a2dacc9efb562b8635d6579fb458751c7c5b new file mode 100644 index 000000000..86127a344 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/23/92a2dacc9efb562b8635d6579fb458751c7c5b differ diff --git a/tests/resources/merge-resolve/.gitted/objects/24/1a1005cd9b980732741b74385b891142bcba28 b/tests/resources/merge-resolve/.gitted/objects/24/1a1005cd9b980732741b74385b891142bcba28 new file mode 100644 index 000000000..9b65f666f Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/24/1a1005cd9b980732741b74385b891142bcba28 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/24/2591eb280ee9eeb2ce63524b9a8b9bc4cb515d b/tests/resources/merge-resolve/.gitted/objects/24/2591eb280ee9eeb2ce63524b9a8b9bc4cb515d new file mode 100644 index 000000000..74a01373f Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/24/2591eb280ee9eeb2ce63524b9a8b9bc4cb515d differ diff --git a/tests/resources/merge-resolve/.gitted/objects/24/90b9f1a079420870027deefb49f51d6656cf74 b/tests/resources/merge-resolve/.gitted/objects/24/90b9f1a079420870027deefb49f51d6656cf74 new file mode 100644 index 000000000..60497caa5 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/24/90b9f1a079420870027deefb49f51d6656cf74 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/25/9d08ca43af9200e9ea9a098e44a5a350ebd9b3 b/tests/resources/merge-resolve/.gitted/objects/25/9d08ca43af9200e9ea9a098e44a5a350ebd9b3 new file mode 100644 index 000000000..2bae66998 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/25/9d08ca43af9200e9ea9a098e44a5a350ebd9b3 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/25/c40b7660c08c8fb581f770312f41b9b03119d1 b/tests/resources/merge-resolve/.gitted/objects/25/c40b7660c08c8fb581f770312f41b9b03119d1 new file mode 100644 index 000000000..185214727 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/25/c40b7660c08c8fb581f770312f41b9b03119d1 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/26/153a3ff3649b6c2bb652d3f06878c6e0a172f9 b/tests/resources/merge-resolve/.gitted/objects/26/153a3ff3649b6c2bb652d3f06878c6e0a172f9 new file mode 100644 index 000000000..4fcaa07e2 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/26/153a3ff3649b6c2bb652d3f06878c6e0a172f9 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/27/133da702ba3c60af2a01e96c2555ff4045d692 b/tests/resources/merge-resolve/.gitted/objects/27/133da702ba3c60af2a01e96c2555ff4045d692 new file mode 100644 index 000000000..08e61f844 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/27/133da702ba3c60af2a01e96c2555ff4045d692 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/2b/0de5dc27505dcdd83a75c8bf1fcd9462cd7add b/tests/resources/merge-resolve/.gitted/objects/2b/0de5dc27505dcdd83a75c8bf1fcd9462cd7add new file mode 100644 index 000000000..a95f926f8 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/2b/0de5dc27505dcdd83a75c8bf1fcd9462cd7add differ diff --git a/tests/resources/merge-resolve/.gitted/objects/2b/5f1f181ee3b58ea751f5dd5d8f9b445520a136 b/tests/resources/merge-resolve/.gitted/objects/2b/5f1f181ee3b58ea751f5dd5d8f9b445520a136 new file mode 100644 index 000000000..d24231eda Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/2b/5f1f181ee3b58ea751f5dd5d8f9b445520a136 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/2b/d0a343aeef7a2cf0d158478966a6e587ff3863 b/tests/resources/merge-resolve/.gitted/objects/2b/d0a343aeef7a2cf0d158478966a6e587ff3863 new file mode 100644 index 000000000..d10ca636b Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/2b/d0a343aeef7a2cf0d158478966a6e587ff3863 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/2d/a538570bc1e5b2c3e855bf702f35248ad0735f b/tests/resources/merge-resolve/.gitted/objects/2d/a538570bc1e5b2c3e855bf702f35248ad0735f new file mode 100644 index 000000000..83253f81c --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/2d/a538570bc1e5b2c3e855bf702f35248ad0735f @@ -0,0 +1,2 @@ +xK +1D]N"n{t:L$ UEQ>~7:L D [5ɇ,y2eT@z*.([žunum_|Št@ +apg%haJYծA8թ훠fN4;h[%cOuJWyΏ \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/2f/598248eeccfc27e5ca44d9d96383f6dfea7b16 b/tests/resources/merge-resolve/.gitted/objects/2f/598248eeccfc27e5ca44d9d96383f6dfea7b16 new file mode 100644 index 000000000..1d9f226e2 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/2f/598248eeccfc27e5ca44d9d96383f6dfea7b16 @@ -0,0 +1 @@ +x+)JMU067c040031QH,-M-JOMLI+(aH:,:C: o>ZC'g$楧f&%%g5qYeZokM2ԐX\ZDPC~^ZNfrIf^:XZHي1O(_,' jvQjn~13zדm9Wu]:$I{| 2mg˾15ӿ,\})TC)0Pavz֛9MՅ'6b \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/31/68dca1a561889b045a6441909f4c56145e666d b/tests/resources/merge-resolve/.gitted/objects/31/68dca1a561889b045a6441909f4c56145e666d new file mode 100644 index 000000000..2de1c5a79 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/31/68dca1a561889b045a6441909f4c56145e666d @@ -0,0 +1,2 @@ +xQ +0D)rJMxMHz}xfރaRYipkUD $1fQ2q-=Y3R76ġg9e7 bw GJe*˽ |ůSY"5&Нƨng9Z3_;kdO \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/31/d5472536041a83d986829240bbbdc897c6f8a6 b/tests/resources/merge-resolve/.gitted/objects/31/d5472536041a83d986829240bbbdc897c6f8a6 new file mode 100644 index 000000000..5ec5acb59 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/31/d5472536041a83d986829240bbbdc897c6f8a6 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/32/21dd512b7e2dc4b5bd03046df6c81b2ab2070b b/tests/resources/merge-resolve/.gitted/objects/32/21dd512b7e2dc4b5bd03046df6c81b2ab2070b new file mode 100644 index 000000000..d36138d79 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/32/21dd512b7e2dc4b5bd03046df6c81b2ab2070b differ diff --git a/tests/resources/merge-resolve/.gitted/objects/33/46d64325b39e5323733492cd55f808994a2475 b/tests/resources/merge-resolve/.gitted/objects/33/46d64325b39e5323733492cd55f808994a2475 new file mode 100644 index 000000000..11546cea4 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/33/46d64325b39e5323733492cd55f808994a2475 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/33/d500f588fbbe65901d82b4e6b008e549064be0 b/tests/resources/merge-resolve/.gitted/objects/33/d500f588fbbe65901d82b4e6b008e549064be0 new file mode 100644 index 000000000..061a031b6 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/33/d500f588fbbe65901d82b4e6b008e549064be0 @@ -0,0 +1,2 @@ +xA E]s +.hbo.Z x}[ ~kCA<:km`d̑d,!:𦐳P1P qHccHEO[zsK>y>隿ïm6*Rn>O \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/34/bfafff88eaf118402b44e6f3e2dbbf1a582b05 b/tests/resources/merge-resolve/.gitted/objects/34/bfafff88eaf118402b44e6f3e2dbbf1a582b05 new file mode 100644 index 000000000..c653cec50 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/34/bfafff88eaf118402b44e6f3e2dbbf1a582b05 @@ -0,0 +1 @@ +xKj1D) >`7A. $<`Morlm4G&dVd[j2JCъgu_Gu%2:3XزQ'";?wpkm׾&Pf! %QJ%:Cez=6q;iO \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/35/0c6eb3010efc403a6bed682332635314e9ed58 b/tests/resources/merge-resolve/.gitted/objects/35/0c6eb3010efc403a6bed682332635314e9ed58 new file mode 100644 index 000000000..2eee60233 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/35/0c6eb3010efc403a6bed682332635314e9ed58 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/35/411bfb77cd2cc431f3a03a2b4976ed94b5d241 b/tests/resources/merge-resolve/.gitted/objects/35/411bfb77cd2cc431f3a03a2b4976ed94b5d241 new file mode 100644 index 000000000..ea024ccd9 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/35/411bfb77cd2cc431f3a03a2b4976ed94b5d241 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/35/4704d3613ad4228e4786fc76656b11e98236c4 b/tests/resources/merge-resolve/.gitted/objects/35/4704d3613ad4228e4786fc76656b11e98236c4 new file mode 100644 index 000000000..1dd13c44a Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/35/4704d3613ad4228e4786fc76656b11e98236c4 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/35/632e43612c06a3ea924bfbacd48333da874c29 b/tests/resources/merge-resolve/.gitted/objects/35/632e43612c06a3ea924bfbacd48333da874c29 new file mode 100644 index 000000000..be7684f19 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/35/632e43612c06a3ea924bfbacd48333da874c29 @@ -0,0 +1 @@ +xN !LdMb60^,40;iUFf+)1vB939fG(DIݸʵA$sk]l|L{Ig$m.N5y.\a/]|Ʋ@[g4< Hl?gTsˠzCP \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/35/75826c96a975031d2c14368529cc5c4353a8fd b/tests/resources/merge-resolve/.gitted/objects/35/75826c96a975031d2c14368529cc5c4353a8fd new file mode 100644 index 000000000..24e33bc41 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/35/75826c96a975031d2c14368529cc5c4353a8fd differ diff --git a/tests/resources/merge-resolve/.gitted/objects/36/219b49367146cb2e6a1555b5a9ebd4d0328495 b/tests/resources/merge-resolve/.gitted/objects/36/219b49367146cb2e6a1555b5a9ebd4d0328495 new file mode 100644 index 000000000..7f8044372 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/36/219b49367146cb2e6a1555b5a9ebd4d0328495 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/36/4bbe4ce80c7bd31e6307dce77d46e3e1759fb3 b/tests/resources/merge-resolve/.gitted/objects/36/4bbe4ce80c7bd31e6307dce77d46e3e1759fb3 new file mode 100644 index 000000000..90fd9651f Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/36/4bbe4ce80c7bd31e6307dce77d46e3e1759fb3 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/37/48859b001c6e627e712a07951aee40afd19b41 b/tests/resources/merge-resolve/.gitted/objects/37/48859b001c6e627e712a07951aee40afd19b41 new file mode 100644 index 000000000..6a0c389e4 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/37/48859b001c6e627e712a07951aee40afd19b41 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/38/5c8a0f26ddf79e9041e15e17dc352ed2c4cced b/tests/resources/merge-resolve/.gitted/objects/38/5c8a0f26ddf79e9041e15e17dc352ed2c4cced new file mode 100644 index 000000000..e95ff3a88 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/38/5c8a0f26ddf79e9041e15e17dc352ed2c4cced @@ -0,0 +1,2 @@ +x-MK +1 uSYRą6C6뛪oknYt Ep iDCddLB+8%qk +e6fHB1J4F1l \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/3b/47b031b3e55ae11e14a05260b1c3ffd6838d55 b/tests/resources/merge-resolve/.gitted/objects/3b/47b031b3e55ae11e14a05260b1c3ffd6838d55 new file mode 100644 index 000000000..82086466f Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/3b/47b031b3e55ae11e14a05260b1c3ffd6838d55 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/3b/bf0bf59b20df5d5fc58b9fc1dc07be637c301f b/tests/resources/merge-resolve/.gitted/objects/3b/bf0bf59b20df5d5fc58b9fc1dc07be637c301f new file mode 100644 index 000000000..723a9ae4c Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/3b/bf0bf59b20df5d5fc58b9fc1dc07be637c301f differ diff --git a/tests/resources/merge-resolve/.gitted/objects/3e/f4d30382ca33fdeba9fda895a99e0891ba37aa b/tests/resources/merge-resolve/.gitted/objects/3e/f4d30382ca33fdeba9fda895a99e0891ba37aa new file mode 100644 index 000000000..49ee15239 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/3e/f4d30382ca33fdeba9fda895a99e0891ba37aa differ diff --git a/tests/resources/merge-resolve/.gitted/objects/3e/f9bfe82f9635518ae89152322f3b46fd4ba25b b/tests/resources/merge-resolve/.gitted/objects/3e/f9bfe82f9635518ae89152322f3b46fd4ba25b new file mode 100644 index 000000000..3b5998ca6 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/3e/f9bfe82f9635518ae89152322f3b46fd4ba25b differ diff --git a/tests/resources/merge-resolve/.gitted/objects/40/2784a46a4a3982294231594cbeb431f506d22c b/tests/resources/merge-resolve/.gitted/objects/40/2784a46a4a3982294231594cbeb431f506d22c new file mode 100644 index 000000000..a17e05d0f Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/40/2784a46a4a3982294231594cbeb431f506d22c differ diff --git a/tests/resources/merge-resolve/.gitted/objects/41/2b32fb66137366147f1801ecc962452757d48a b/tests/resources/merge-resolve/.gitted/objects/41/2b32fb66137366147f1801ecc962452757d48a new file mode 100644 index 000000000..b183dd782 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/41/2b32fb66137366147f1801ecc962452757d48a @@ -0,0 +1,2 @@ +xK +1D]IO>"nt:x}xwUxjum'뫈.9=y 6$@T8&Lhf4Aܻf0B(.K>9S< +z_f}]Z]eO:wzރP.ިaNU6O \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/43/aafd43bea779ec74317dc361f45ae3f532a505 b/tests/resources/merge-resolve/.gitted/objects/43/aafd43bea779ec74317dc361f45ae3f532a505 new file mode 100644 index 000000000..ac86823b6 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/43/aafd43bea779ec74317dc361f45ae3f532a505 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/43/c338656342227a3a3cd3aa85cbf784061f5425 b/tests/resources/merge-resolve/.gitted/objects/43/c338656342227a3a3cd3aa85cbf784061f5425 new file mode 100644 index 000000000..d9773118b Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/43/c338656342227a3a3cd3aa85cbf784061f5425 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/45/299c1ca5e07bba1fd90843056fb559f96b1f5a b/tests/resources/merge-resolve/.gitted/objects/45/299c1ca5e07bba1fd90843056fb559f96b1f5a new file mode 100644 index 000000000..2093b4410 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/45/299c1ca5e07bba1fd90843056fb559f96b1f5a differ diff --git a/tests/resources/merge-resolve/.gitted/objects/46/6daf8552b891e5c22bc58c9d7fc1a2eb8f0289 b/tests/resources/merge-resolve/.gitted/objects/46/6daf8552b891e5c22bc58c9d7fc1a2eb8f0289 new file mode 100644 index 000000000..c39b53aa8 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/46/6daf8552b891e5c22bc58c9d7fc1a2eb8f0289 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/47/6dbb3e207313d1d8aaa120c6ad204bf1295e53 b/tests/resources/merge-resolve/.gitted/objects/47/6dbb3e207313d1d8aaa120c6ad204bf1295e53 new file mode 100644 index 000000000..3e5f66e55 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/47/6dbb3e207313d1d8aaa120c6ad204bf1295e53 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/47/8172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 b/tests/resources/merge-resolve/.gitted/objects/47/8172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 new file mode 100644 index 000000000..d9e250e66 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/47/8172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/49/130a28ef567af9a6a6104c38773fedfa5f9742 b/tests/resources/merge-resolve/.gitted/objects/49/130a28ef567af9a6a6104c38773fedfa5f9742 new file mode 100644 index 000000000..e2c49f5c4 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/49/130a28ef567af9a6a6104c38773fedfa5f9742 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/49/9df817155e4bdd3c6ee192a72c52f481818230 b/tests/resources/merge-resolve/.gitted/objects/49/9df817155e4bdd3c6ee192a72c52f481818230 new file mode 100644 index 000000000..9c7e471dd Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/49/9df817155e4bdd3c6ee192a72c52f481818230 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/4a/9550ebcc97ce22b22f45af7b829bb030d003f5 b/tests/resources/merge-resolve/.gitted/objects/4a/9550ebcc97ce22b22f45af7b829bb030d003f5 new file mode 100644 index 000000000..6ec674adc Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/4a/9550ebcc97ce22b22f45af7b829bb030d003f5 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/4b/253da36a0ae8bfce63aeabd8c5b58429925594 b/tests/resources/merge-resolve/.gitted/objects/4b/253da36a0ae8bfce63aeabd8c5b58429925594 new file mode 100644 index 000000000..1a4072794 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/4b/253da36a0ae8bfce63aeabd8c5b58429925594 @@ -0,0 +1,2 @@ +x A +0 @AAILm l׹vGx#63tW B6%h \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/4b/48deed3a433909bfd6b6ab3d4b91348b6af464 b/tests/resources/merge-resolve/.gitted/objects/4b/48deed3a433909bfd6b6ab3d4b91348b6af464 new file mode 100644 index 000000000..328c8506e Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/4b/48deed3a433909bfd6b6ab3d4b91348b6af464 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 b/tests/resources/merge-resolve/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 new file mode 100644 index 000000000..adf64119a Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/4c/9fac0707f8d4195037ae5a681aa48626491541 b/tests/resources/merge-resolve/.gitted/objects/4c/9fac0707f8d4195037ae5a681aa48626491541 new file mode 100644 index 000000000..6b8c85e2b Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/4c/9fac0707f8d4195037ae5a681aa48626491541 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/4c/a408a8c88655f7586a1b580be6fad138121e98 b/tests/resources/merge-resolve/.gitted/objects/4c/a408a8c88655f7586a1b580be6fad138121e98 new file mode 100644 index 000000000..15cb7f29a Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/4c/a408a8c88655f7586a1b580be6fad138121e98 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/4e/0d9401aee78eb345a8685a859d37c8c3c0bbed b/tests/resources/merge-resolve/.gitted/objects/4e/0d9401aee78eb345a8685a859d37c8c3c0bbed new file mode 100644 index 000000000..57f7eb68c Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/4e/0d9401aee78eb345a8685a859d37c8c3c0bbed differ diff --git a/tests/resources/merge-resolve/.gitted/objects/4e/886e602529caa9ab11d71f86634bd1b6e0de10 b/tests/resources/merge-resolve/.gitted/objects/4e/886e602529caa9ab11d71f86634bd1b6e0de10 new file mode 100644 index 000000000..53168a038 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/4e/886e602529caa9ab11d71f86634bd1b6e0de10 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/4e/b04c9e79e88f6640d01ff5b25ca2a60764f216 b/tests/resources/merge-resolve/.gitted/objects/4e/b04c9e79e88f6640d01ff5b25ca2a60764f216 new file mode 100644 index 000000000..f4ec0efec Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/4e/b04c9e79e88f6640d01ff5b25ca2a60764f216 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/4f/e93c0ec83eb6305cbace3dace88ecee1b63cb6 b/tests/resources/merge-resolve/.gitted/objects/4f/e93c0ec83eb6305cbace3dace88ecee1b63cb6 new file mode 100644 index 000000000..67dc6842f Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/4f/e93c0ec83eb6305cbace3dace88ecee1b63cb6 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/50/12fd565b1393bdfda1805d4ec38ce6619e1fd1 b/tests/resources/merge-resolve/.gitted/objects/50/12fd565b1393bdfda1805d4ec38ce6619e1fd1 new file mode 100644 index 000000000..d629a23a1 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/50/12fd565b1393bdfda1805d4ec38ce6619e1fd1 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/50/4f75ac95a71ef98051817618576a68505b92f9 b/tests/resources/merge-resolve/.gitted/objects/50/4f75ac95a71ef98051817618576a68505b92f9 new file mode 100644 index 000000000..1b24c721a Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/50/4f75ac95a71ef98051817618576a68505b92f9 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/50/84fc2a88b6bdba8db93bd3953a8f4fdb470238 b/tests/resources/merge-resolve/.gitted/objects/50/84fc2a88b6bdba8db93bd3953a8f4fdb470238 new file mode 100644 index 000000000..84c9987ce Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/50/84fc2a88b6bdba8db93bd3953a8f4fdb470238 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/50/ce7d7d01217679e26c55939eef119e0c93e272 b/tests/resources/merge-resolve/.gitted/objects/50/ce7d7d01217679e26c55939eef119e0c93e272 new file mode 100644 index 000000000..e2f9f67fd Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/50/ce7d7d01217679e26c55939eef119e0c93e272 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/51/95a1b480f66691b667f10a9e41e70115a78351 b/tests/resources/merge-resolve/.gitted/objects/51/95a1b480f66691b667f10a9e41e70115a78351 new file mode 100644 index 000000000..088ee5498 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/51/95a1b480f66691b667f10a9e41e70115a78351 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/52/d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 b/tests/resources/merge-resolve/.gitted/objects/52/d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 new file mode 100644 index 000000000..6522209bd --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/52/d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 @@ -0,0 +1,3 @@ +x] +0})rnD|^`Ђm$FUo3ä,sӽ]" #b"1 9cThS//SYe'+~mrh\cQwFMQϙ]b5M R \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/53/825f41ac8d640612f9423a2f03a69f3d96809a b/tests/resources/merge-resolve/.gitted/objects/53/825f41ac8d640612f9423a2f03a69f3d96809a new file mode 100644 index 000000000..08cb0b66f Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/53/825f41ac8d640612f9423a2f03a69f3d96809a differ diff --git a/tests/resources/merge-resolve/.gitted/objects/54/269b3f6ec3d7d4ede24dd350dd5d605495c3ae b/tests/resources/merge-resolve/.gitted/objects/54/269b3f6ec3d7d4ede24dd350dd5d605495c3ae new file mode 100644 index 000000000..4a2415339 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/54/269b3f6ec3d7d4ede24dd350dd5d605495c3ae @@ -0,0 +1,2 @@ +xK +1D]I7 LӌL$FxwUAQj m'؍^v9 d- Ɯ \ ϽC'&`"Ĺ(֡9_sg}]Z}UF?\I&@mt;;ʟ3hzN \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/54/59c89aa0026d543ce8343bd89871bce543f9c2 b/tests/resources/merge-resolve/.gitted/objects/54/59c89aa0026d543ce8343bd89871bce543f9c2 new file mode 100644 index 000000000..178b833e8 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/54/59c89aa0026d543ce8343bd89871bce543f9c2 @@ -0,0 +1,3 @@ +x !D +,,,,9O bl؁3%mY.C[LEtd`\ %aBH%TvB G%Qphq]nCgP3B(H14yS)W;IVsT^܋>myJ?(_kܖ6-$#-Zzvȟ3 +:NqMB \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/54/7607c690372fe81fab8e3bb44c530e129118fd b/tests/resources/merge-resolve/.gitted/objects/54/7607c690372fe81fab8e3bb44c530e129118fd new file mode 100644 index 000000000..dccd22006 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/54/7607c690372fe81fab8e3bb44c530e129118fd differ diff --git a/tests/resources/merge-resolve/.gitted/objects/55/b4e4687e7a0d9ca367016ed930f385d4022e6f b/tests/resources/merge-resolve/.gitted/objects/55/b4e4687e7a0d9ca367016ed930f385d4022e6f new file mode 100644 index 000000000..fb157a214 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/55/b4e4687e7a0d9ca367016ed930f385d4022e6f @@ -0,0 +1 @@ +xQj0DSZvJ \N 7㷱d-{LX' vm*{Z`$U9-TN{,}Kyuۣ78A_Sv.EQgSsxZZX MNRi \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/56/6ab53c220a2eafc1212af1a024513230280ab9 b/tests/resources/merge-resolve/.gitted/objects/56/6ab53c220a2eafc1212af1a024513230280ab9 new file mode 100644 index 000000000..a8855ae67 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/56/6ab53c220a2eafc1212af1a024513230280ab9 @@ -0,0 +1,3 @@ +x !D +,˱1؁ ,LD bl؁3%Ihft ١XvY`L2М՝܆NsIbRЧL3Ra$Is,S~qh7~QvՃ6!-Zzvȟ3 +:9M& \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/56/a638b76b75e068590ac999c2f8621e7f3e264c b/tests/resources/merge-resolve/.gitted/objects/56/a638b76b75e068590ac999c2f8621e7f3e264c new file mode 100644 index 000000000..36289bf7a --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/56/a638b76b75e068590ac999c2f8621e7f3e264c @@ -0,0 +1 @@ +xAj!Eu vuWB6s%6qΐ$^Rb[{=coj'|褯UjeKLnn5СPY|2`zzQ{ \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/57/079a46233ae2b6df62e9ade71c4948512abefb b/tests/resources/merge-resolve/.gitted/objects/57/079a46233ae2b6df62e9ade71c4948512abefb new file mode 100644 index 000000000..c7eabc46b Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/57/079a46233ae2b6df62e9ade71c4948512abefb differ diff --git a/tests/resources/merge-resolve/.gitted/objects/58/43febcb23480df0b5edb22a21c59c772bb8e29 b/tests/resources/merge-resolve/.gitted/objects/58/43febcb23480df0b5edb22a21c59c772bb8e29 new file mode 100644 index 000000000..f6b2a2bfe Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/58/43febcb23480df0b5edb22a21c59c772bb8e29 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/58/e853f66699fd02629fd50bde08082bc005933a b/tests/resources/merge-resolve/.gitted/objects/58/e853f66699fd02629fd50bde08082bc005933a new file mode 100644 index 000000000..cf6db633c Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/58/e853f66699fd02629fd50bde08082bc005933a differ diff --git a/tests/resources/merge-resolve/.gitted/objects/59/6803b523203a4851c824c07366906f8353f4ad b/tests/resources/merge-resolve/.gitted/objects/59/6803b523203a4851c824c07366906f8353f4ad new file mode 100644 index 000000000..cbc8cbef3 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/59/6803b523203a4851c824c07366906f8353f4ad differ diff --git a/tests/resources/merge-resolve/.gitted/objects/5c/2411f8075f48a6b2fdb85ebc0d371747c4df15 b/tests/resources/merge-resolve/.gitted/objects/5c/2411f8075f48a6b2fdb85ebc0d371747c4df15 new file mode 100644 index 000000000..7b41413da Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/5c/2411f8075f48a6b2fdb85ebc0d371747c4df15 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/5c/341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d b/tests/resources/merge-resolve/.gitted/objects/5c/341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d new file mode 100644 index 000000000..63c86bd33 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/5c/341ead2ba6f2af98ce5ec3fe84f6b6d2899c0d differ diff --git a/tests/resources/merge-resolve/.gitted/objects/5c/3b68a71fc4fa5d362fd3875e53137c6a5ab7a5 b/tests/resources/merge-resolve/.gitted/objects/5c/3b68a71fc4fa5d362fd3875e53137c6a5ab7a5 new file mode 100644 index 000000000..541001456 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/5c/3b68a71fc4fa5d362fd3875e53137c6a5ab7a5 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/5d/c1018e90b19654bee986b7a0c268804d39659d b/tests/resources/merge-resolve/.gitted/objects/5d/c1018e90b19654bee986b7a0c268804d39659d new file mode 100644 index 000000000..7500b9914 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/5d/c1018e90b19654bee986b7a0c268804d39659d differ diff --git a/tests/resources/merge-resolve/.gitted/objects/5d/dd0fe66f990dc0e5cf9fec6d9b465240e9537f b/tests/resources/merge-resolve/.gitted/objects/5d/dd0fe66f990dc0e5cf9fec6d9b465240e9537f new file mode 100644 index 000000000..9d8691eb2 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/5d/dd0fe66f990dc0e5cf9fec6d9b465240e9537f differ diff --git a/tests/resources/merge-resolve/.gitted/objects/5e/b7bb6a146eb3c7fd3990b240a2308eceb1cf8d b/tests/resources/merge-resolve/.gitted/objects/5e/b7bb6a146eb3c7fd3990b240a2308eceb1cf8d new file mode 100644 index 000000000..aca2666cf Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/5e/b7bb6a146eb3c7fd3990b240a2308eceb1cf8d differ diff --git a/tests/resources/merge-resolve/.gitted/objects/5f/bfbdc04b4eca46f54f4853a3c5a1dce28f5165 b/tests/resources/merge-resolve/.gitted/objects/5f/bfbdc04b4eca46f54f4853a3c5a1dce28f5165 new file mode 100644 index 000000000..aec3867c8 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/5f/bfbdc04b4eca46f54f4853a3c5a1dce28f5165 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/60/91fc2c036a382a69489e3f518ee5aae9a4e567 b/tests/resources/merge-resolve/.gitted/objects/60/91fc2c036a382a69489e3f518ee5aae9a4e567 new file mode 100644 index 000000000..fa63afba1 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/60/91fc2c036a382a69489e3f518ee5aae9a4e567 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/61/340eeed7340fa6a8792def9a5938bb5d4434bb b/tests/resources/merge-resolve/.gitted/objects/61/340eeed7340fa6a8792def9a5938bb5d4434bb new file mode 100644 index 000000000..e830cafe5 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/61/340eeed7340fa6a8792def9a5938bb5d4434bb differ diff --git a/tests/resources/merge-resolve/.gitted/objects/61/78885b38fe96e825ac0f492c0a941f288b37f6 b/tests/resources/merge-resolve/.gitted/objects/61/78885b38fe96e825ac0f492c0a941f288b37f6 new file mode 100644 index 000000000..bedc5f27e Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/61/78885b38fe96e825ac0f492c0a941f288b37f6 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/62/12c31dab5e482247d7977e4f0dd3601decf13b b/tests/resources/merge-resolve/.gitted/objects/62/12c31dab5e482247d7977e4f0dd3601decf13b new file mode 100644 index 000000000..b6f0607bb Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/62/12c31dab5e482247d7977e4f0dd3601decf13b differ diff --git a/tests/resources/merge-resolve/.gitted/objects/62/269111c3b02a9355badcb9da8678b1bf41787b b/tests/resources/merge-resolve/.gitted/objects/62/269111c3b02a9355badcb9da8678b1bf41787b new file mode 100644 index 000000000..0edf65994 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/62/269111c3b02a9355badcb9da8678b1bf41787b differ diff --git a/tests/resources/merge-resolve/.gitted/objects/62/c4f6533c9a3894191fdcb96a3be935ade63f1a b/tests/resources/merge-resolve/.gitted/objects/62/c4f6533c9a3894191fdcb96a3be935ade63f1a new file mode 100644 index 000000000..c0f822d2c Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/62/c4f6533c9a3894191fdcb96a3be935ade63f1a differ diff --git a/tests/resources/merge-resolve/.gitted/objects/63/247125386de9ec90a27ad36169307bf8a11a38 b/tests/resources/merge-resolve/.gitted/objects/63/247125386de9ec90a27ad36169307bf8a11a38 new file mode 100644 index 000000000..bc2d7384d --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/63/247125386de9ec90a27ad36169307bf8a11a38 @@ -0,0 +1 @@ +xݏ;1 D}AV\8HIVp|?LyOuN7C] ͥlt:iA(xip,O;o7 UYZ Bý]dUmyk[cͥ)!X{Z \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/67/18a45909532d1fcf5600d0877f7fe7e78f0b86 b/tests/resources/merge-resolve/.gitted/objects/67/18a45909532d1fcf5600d0877f7fe7e78f0b86 new file mode 100644 index 000000000..ffda698f0 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/67/18a45909532d1fcf5600d0877f7fe7e78f0b86 @@ -0,0 +1 @@ +xM1 DNi`ǹDB~ǧ]ݠY74M8J?$_k[Q,"Zz˟39 LO \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/76/63fce0130db092936b137cabd693ec234eb060 b/tests/resources/merge-resolve/.gitted/objects/76/63fce0130db092936b137cabd693ec234eb060 new file mode 100644 index 000000000..f578a4a68 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/76/63fce0130db092936b137cabd693ec234eb060 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/76/ab0e2868197ec158ddd6c78d8a0d2fd73d38f9 b/tests/resources/merge-resolve/.gitted/objects/76/ab0e2868197ec158ddd6c78d8a0d2fd73d38f9 new file mode 100644 index 000000000..4d41ad8cd Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/76/ab0e2868197ec158ddd6c78d8a0d2fd73d38f9 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/7a/a3edf2bcfee22398e6b55295aa56366b7aaf76 b/tests/resources/merge-resolve/.gitted/objects/7a/a3edf2bcfee22398e6b55295aa56366b7aaf76 new file mode 100644 index 000000000..09f1e4d3a Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/7a/a3edf2bcfee22398e6b55295aa56366b7aaf76 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/7c/2c5228c9e90170d4a35e6558e47163daf092e5 b/tests/resources/merge-resolve/.gitted/objects/7c/2c5228c9e90170d4a35e6558e47163daf092e5 new file mode 100644 index 000000000..52fde92a1 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/7c/2c5228c9e90170d4a35e6558e47163daf092e5 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/7c/b63eed597130ba4abb87b3e544b85021905520 b/tests/resources/merge-resolve/.gitted/objects/7c/b63eed597130ba4abb87b3e544b85021905520 new file mode 100644 index 000000000..769f29c6e --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/7c/b63eed597130ba4abb87b3e544b85021905520 @@ -0,0 +1,3 @@ +xK +1D]t'"nH:L$FxwUAQܖ6f7IT*zJ +1#;@rX]ꞺC3A F'aj#Tf acn]_+s[mG'+~m9i PFCQge"N \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/7e/2d058d5fedf8329db44db4fac610d6b1a89159 b/tests/resources/merge-resolve/.gitted/objects/7e/2d058d5fedf8329db44db4fac610d6b1a89159 new file mode 100644 index 000000000..d12d7b4a7 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/7e/2d058d5fedf8329db44db4fac610d6b1a89159 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/7f/7a2da58126226986d71c6ddfab4afba693280d b/tests/resources/merge-resolve/.gitted/objects/7f/7a2da58126226986d71c6ddfab4afba693280d new file mode 100644 index 000000000..2f833c292 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/7f/7a2da58126226986d71c6ddfab4afba693280d differ diff --git a/tests/resources/merge-resolve/.gitted/objects/80/a8fbb3abb1ba423d554e9630b8fc2e5698f86b b/tests/resources/merge-resolve/.gitted/objects/80/a8fbb3abb1ba423d554e9630b8fc2e5698f86b new file mode 100644 index 000000000..3daf6c3e0 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/80/a8fbb3abb1ba423d554e9630b8fc2e5698f86b differ diff --git a/tests/resources/merge-resolve/.gitted/objects/81/87117062b750eed4f93fd7e899f17b52ce554d b/tests/resources/merge-resolve/.gitted/objects/81/87117062b750eed4f93fd7e899f17b52ce554d new file mode 100644 index 000000000..19cac9faf Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/81/87117062b750eed4f93fd7e899f17b52ce554d differ diff --git a/tests/resources/merge-resolve/.gitted/objects/83/07d93a155903a5c49576583f0ce1f6ff897c0e b/tests/resources/merge-resolve/.gitted/objects/83/07d93a155903a5c49576583f0ce1f6ff897c0e new file mode 100644 index 000000000..5a96a4e4e Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/83/07d93a155903a5c49576583f0ce1f6ff897c0e differ diff --git a/tests/resources/merge-resolve/.gitted/objects/83/824a8c6658768e2013905219cc8c64cc3d9a2e b/tests/resources/merge-resolve/.gitted/objects/83/824a8c6658768e2013905219cc8c64cc3d9a2e new file mode 100644 index 000000000..066190fb8 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/83/824a8c6658768e2013905219cc8c64cc3d9a2e differ diff --git a/tests/resources/merge-resolve/.gitted/objects/84/9619b03ae540acee4d1edec96b86993da6b497 b/tests/resources/merge-resolve/.gitted/objects/84/9619b03ae540acee4d1edec96b86993da6b497 new file mode 100644 index 000000000..67271ac50 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/84/9619b03ae540acee4d1edec96b86993da6b497 @@ -0,0 +1,3 @@ +xK +1D]v7t3L$ UEVZC'g$楧f&%%g5qYeZokM2ԐX\ZDPC~^ZNfrIf^:XZHي1O(_,' jv^j9!Ɖ9%`<sBާHrS3d Ң2 wI{| 2mg˾15ӿ,\})TC)00avʉz֛9MՅ'6bG \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/8b/095d8fd01594f4d14454d073e3ac57b9ce485f b/tests/resources/merge-resolve/.gitted/objects/8b/095d8fd01594f4d14454d073e3ac57b9ce485f new file mode 100644 index 000000000..4ec013881 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/8b/095d8fd01594f4d14454d073e3ac57b9ce485f differ diff --git a/tests/resources/merge-resolve/.gitted/objects/8b/5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a b/tests/resources/merge-resolve/.gitted/objects/8b/5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a new file mode 100644 index 000000000..f4249c23d --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/8b/5b53cb2aa9ceb1139f5312fcfa3cc3c5a47c9a @@ -0,0 +1 @@ +x퐱 0 S{"2d,0^?&SH[8눪E`фrZ*drl, cbF/'gв \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/8b/fb012a6d809e499bd8d3e194a3929bc8995b93 b/tests/resources/merge-resolve/.gitted/objects/8b/fb012a6d809e499bd8d3e194a3929bc8995b93 new file mode 100644 index 000000000..a90ee08ce Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/8b/fb012a6d809e499bd8d3e194a3929bc8995b93 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/8c/749d9968d4b10dcfb06c9f97d0e5d92d337071 b/tests/resources/merge-resolve/.gitted/objects/8c/749d9968d4b10dcfb06c9f97d0e5d92d337071 new file mode 100644 index 000000000..e42393cf7 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/8c/749d9968d4b10dcfb06c9f97d0e5d92d337071 @@ -0,0 +1,2 @@ +xAB!C]s +.acxf`|_ bh5m^mzL`}$26#"8`s.`ԝܺ.!bH\< i",K8ٗ_X>MeЏ:7]AC40뭙Q]Q\.,VO \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/8f/4433f8593ddd65b7dd43dd4564d841f4d9c8aa b/tests/resources/merge-resolve/.gitted/objects/8f/4433f8593ddd65b7dd43dd4564d841f4d9c8aa new file mode 100644 index 000000000..d2de777cc Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/8f/4433f8593ddd65b7dd43dd4564d841f4d9c8aa differ diff --git a/tests/resources/merge-resolve/.gitted/objects/90/a336c7dacbe295159413559b0043b8bdc60d57 b/tests/resources/merge-resolve/.gitted/objects/90/a336c7dacbe295159413559b0043b8bdc60d57 new file mode 100644 index 000000000..35453ebfd Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/90/a336c7dacbe295159413559b0043b8bdc60d57 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/91/2b2d7819cf9c1029e414883857ed61d597a1a5 b/tests/resources/merge-resolve/.gitted/objects/91/2b2d7819cf9c1029e414883857ed61d597a1a5 new file mode 100644 index 000000000..d5df393e9 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/91/2b2d7819cf9c1029e414883857ed61d597a1a5 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/91/8bb3e09090a9995d48af9a2a6296d7e6088d1c b/tests/resources/merge-resolve/.gitted/objects/91/8bb3e09090a9995d48af9a2a6296d7e6088d1c new file mode 100644 index 000000000..c214ab206 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/91/8bb3e09090a9995d48af9a2a6296d7e6088d1c differ diff --git a/tests/resources/merge-resolve/.gitted/objects/92/7d4943cdbdc9a667db8e62cfd0a41870235c51 b/tests/resources/merge-resolve/.gitted/objects/92/7d4943cdbdc9a667db8e62cfd0a41870235c51 new file mode 100644 index 000000000..b6b92c842 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/92/7d4943cdbdc9a667db8e62cfd0a41870235c51 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/93/77fccdb210540b8c0520cc6e80eb632c20bd25 b/tests/resources/merge-resolve/.gitted/objects/93/77fccdb210540b8c0520cc6e80eb632c20bd25 new file mode 100644 index 000000000..4b2d93b07 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/93/77fccdb210540b8c0520cc6e80eb632c20bd25 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/94/4f5dd1a867cab4c2bbcb896493435cae1dcc1a b/tests/resources/merge-resolve/.gitted/objects/94/4f5dd1a867cab4c2bbcb896493435cae1dcc1a new file mode 100644 index 000000000..143093831 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/94/4f5dd1a867cab4c2bbcb896493435cae1dcc1a @@ -0,0 +1,2 @@ +xK!D]s +.z7 |2. bhWKVmH0~7z"P9`:Qi)QLEyq=oC*P6-"4l0StAHZC'g$楧f&%%g5qYeZokM2ԐX\ZDPC~^ZNfrIf^:XZHي1O(_,' jv^jnb^nJfZZjQj^ X#3|>^U:'A2R2 I{| 2mg˾15ӿ,\})TC)0H!vʉz֛9MՅ'6bGx \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/a9/0bc3fb6f15181972a2959a921429efbd81a473 b/tests/resources/merge-resolve/.gitted/objects/a9/0bc3fb6f15181972a2959a921429efbd81a473 new file mode 100644 index 000000000..91113ee8e --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/a9/0bc3fb6f15181972a2959a921429efbd81a473 @@ -0,0 +1,2 @@ +xK +1D]};7d=oo^UQT\;hk6@g 5rѓ]uOMndgz&c圈'} NJ7p?(G\8CآGTg9x$faxN" \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/ab/40af3cb8a3ed2e2843e96d9aa7871336b94573 b/tests/resources/merge-resolve/.gitted/objects/ab/40af3cb8a3ed2e2843e96d9aa7871336b94573 new file mode 100644 index 000000000..7da1da656 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/ab/40af3cb8a3ed2e2843e96d9aa7871336b94573 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/ab/6c44a2e84492ad4b41bb6bac87353e9d02ac8b b/tests/resources/merge-resolve/.gitted/objects/ab/6c44a2e84492ad4b41bb6bac87353e9d02ac8b new file mode 100644 index 000000000..d840c1a57 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/ab/6c44a2e84492ad4b41bb6bac87353e9d02ac8b differ diff --git a/tests/resources/merge-resolve/.gitted/objects/ab/929391ac42572f92110f3deeb4f0844a951e22 b/tests/resources/merge-resolve/.gitted/objects/ab/929391ac42572f92110f3deeb4f0844a951e22 new file mode 100644 index 000000000..8840d00c5 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/ab/929391ac42572f92110f3deeb4f0844a951e22 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/ac/4045f965119e6998f4340ed0f411decfb3ec05 b/tests/resources/merge-resolve/.gitted/objects/ac/4045f965119e6998f4340ed0f411decfb3ec05 new file mode 100644 index 000000000..4c32d63f8 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/ac/4045f965119e6998f4340ed0f411decfb3ec05 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/ad/a14492498136771f69dd451866cabcb0e9ef9a b/tests/resources/merge-resolve/.gitted/objects/ad/a14492498136771f69dd451866cabcb0e9ef9a new file mode 100644 index 000000000..71023de39 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/ad/a14492498136771f69dd451866cabcb0e9ef9a differ diff --git a/tests/resources/merge-resolve/.gitted/objects/ad/a55a45d14527dc3dfc714ea1c65d2e1e6fbe87 b/tests/resources/merge-resolve/.gitted/objects/ad/a55a45d14527dc3dfc714ea1c65d2e1e6fbe87 new file mode 100644 index 000000000..3091b8f3d --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/ad/a55a45d14527dc3dfc714ea1c65d2e1e6fbe87 @@ -0,0 +1 @@ +x+)JMU067d040031QH,-M-JOMLI+(aH:,:C: o>ZC'g$楧f&%%g5qYeZokM2ԐX\ZDPC~^ZNfrIf^:XZHي1O(_,' jvn~JfZ&5`nלU7 V.6t6L/R2 I{| 2mg˾15ӿ,\})TC)0<vʉz֛9MՅ'6bN* \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/b2/d399ae15224e1d58066e3c8df70ce37de7a656 b/tests/resources/merge-resolve/.gitted/objects/b2/d399ae15224e1d58066e3c8df70ce37de7a656 new file mode 100644 index 000000000..20fa838f2 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/b2/d399ae15224e1d58066e3c8df70ce37de7a656 @@ -0,0 +1,2 @@ +xQA1+xċϡ-kI*5f/z af!^/WJcܤ5Lƛ;+B6HZP|`h>\($sX@75}57K ++= ;g @!4!,\$\ \b/Hs#aQ \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/b4/2712cfe99a1a500b2a51fe984e0b8a7702ba11 b/tests/resources/merge-resolve/.gitted/objects/b4/2712cfe99a1a500b2a51fe984e0b8a7702ba11 new file mode 100644 index 000000000..2820b46cc --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/b4/2712cfe99a1a500b2a51fe984e0b8a7702ba11 @@ -0,0 +1,5 @@ +xA + {B{M1 ߯>P3F֎7E02 X0̒,)$;:ܷ(: \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/b6/f610aef53bd343e6c96227de874c66f00ee8e8 b/tests/resources/merge-resolve/.gitted/objects/b6/f610aef53bd343e6c96227de874c66f00ee8e8 new file mode 100644 index 000000000..fb102f15d Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/b6/f610aef53bd343e6c96227de874c66f00ee8e8 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/b7/a2576f9fc20024ac9ef17cb134acbd1ac73127 b/tests/resources/merge-resolve/.gitted/objects/b7/a2576f9fc20024ac9ef17cb134acbd1ac73127 new file mode 100644 index 000000000..22f2d137d Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/b7/a2576f9fc20024ac9ef17cb134acbd1ac73127 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/b8/a3a806d3950e8c0a03a34f234a92eff0e2c68d b/tests/resources/merge-resolve/.gitted/objects/b8/a3a806d3950e8c0a03a34f234a92eff0e2c68d new file mode 100644 index 000000000..24f029900 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/b8/a3a806d3950e8c0a03a34f234a92eff0e2c68d differ diff --git a/tests/resources/merge-resolve/.gitted/objects/ba/cac9b3493509aa15e1730e1545fc0919d1dae0 b/tests/resources/merge-resolve/.gitted/objects/ba/cac9b3493509aa15e1730e1545fc0919d1dae0 new file mode 100644 index 000000000..f35586f7f Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/ba/cac9b3493509aa15e1730e1545fc0919d1dae0 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/bc/744705e1d8a019993cf88f62bc4020f1b80919 b/tests/resources/merge-resolve/.gitted/objects/bc/744705e1d8a019993cf88f62bc4020f1b80919 new file mode 100644 index 000000000..0d4bdb323 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/bc/744705e1d8a019993cf88f62bc4020f1b80919 @@ -0,0 +1,2 @@ +xK +1D]}%%tYH& UJuj7:P(#F̄ģ1+k#vΚS8W|٨%Kpɯ3\Vv#MQg?wH@(c s9t 嶭{kO \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/bc/95c75d59386147d1e79a87c33068d8dbfd71f2 b/tests/resources/merge-resolve/.gitted/objects/bc/95c75d59386147d1e79a87c33068d8dbfd71f2 new file mode 100644 index 000000000..436d5a076 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/bc/95c75d59386147d1e79a87c33068d8dbfd71f2 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/bd/593285fc7fe4ca18ccdbabf027f5d689101452 b/tests/resources/merge-resolve/.gitted/objects/bd/593285fc7fe4ca18ccdbabf027f5d689101452 new file mode 100644 index 000000000..75ab1f0f3 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/bd/593285fc7fe4ca18ccdbabf027f5d689101452 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/bd/867fbae2faa80b920b002b80b1c91bcade7784 b/tests/resources/merge-resolve/.gitted/objects/bd/867fbae2faa80b920b002b80b1c91bcade7784 new file mode 100644 index 000000000..0f7421963 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/bd/867fbae2faa80b920b002b80b1c91bcade7784 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/bd/9cb4cd0a770cb9adcb5fce212142ef40ea1c35 b/tests/resources/merge-resolve/.gitted/objects/bd/9cb4cd0a770cb9adcb5fce212142ef40ea1c35 new file mode 100644 index 000000000..2aafdc64f Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/bd/9cb4cd0a770cb9adcb5fce212142ef40ea1c35 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/be/f6e37b3ee632ba74159168836f382fed21d77d b/tests/resources/merge-resolve/.gitted/objects/be/f6e37b3ee632ba74159168836f382fed21d77d new file mode 100644 index 000000000..6c243150d --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/be/f6e37b3ee632ba74159168836f382fed21d77d @@ -0,0 +1,2 @@ +xK +1D]}3?Ač7p?$=`Ґx}Gރ`)+0ѮUh.NWޓ!Idlj-f 9UV61:̸ !>Z.P0x hhQ+t`1NZe,X[ =vyI_vJ^2$?I7o4{K>V!~|U= \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/c5/bbe550b9f09444bdddd3ecf3d97c0b42aa786c b/tests/resources/merge-resolve/.gitted/objects/c5/bbe550b9f09444bdddd3ecf3d97c0b42aa786c new file mode 100644 index 000000000..2f2ada732 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/c5/bbe550b9f09444bdddd3ecf3d97c0b42aa786c differ diff --git a/tests/resources/merge-resolve/.gitted/objects/c6/07fc30883e335def28cd686b51f6cfa02b06ec b/tests/resources/merge-resolve/.gitted/objects/c6/07fc30883e335def28cd686b51f6cfa02b06ec new file mode 100644 index 000000000..475b87ef9 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/c6/07fc30883e335def28cd686b51f6cfa02b06ec @@ -0,0 +1,2 @@ +xQ +1 D)r%n "x/m[[oo{0k)iכ*`ZavJ>,af<EZȳ5%<'.v,;]=2tws-,w8@ \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/c6/92ecf62007c0ac9fb26e2aa884de2933de15ed b/tests/resources/merge-resolve/.gitted/objects/c6/92ecf62007c0ac9fb26e2aa884de2933de15ed new file mode 100644 index 000000000..ae430bd4a Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/c6/92ecf62007c0ac9fb26e2aa884de2933de15ed differ diff --git a/tests/resources/merge-resolve/.gitted/objects/c8/f06f2e3bb2964174677e91f0abead0e43c9e5d b/tests/resources/merge-resolve/.gitted/objects/c8/f06f2e3bb2964174677e91f0abead0e43c9e5d new file mode 100644 index 000000000..5dae4c3ac Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/c8/f06f2e3bb2964174677e91f0abead0e43c9e5d differ diff --git a/tests/resources/merge-resolve/.gitted/objects/c9/174cef549ec94ecbc43ef03cdc775b4950becb b/tests/resources/merge-resolve/.gitted/objects/c9/174cef549ec94ecbc43ef03cdc775b4950becb new file mode 100644 index 000000000..da8dba244 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/c9/174cef549ec94ecbc43ef03cdc775b4950becb @@ -0,0 +1,2 @@ +xQ +0D)rfnSxfCHx}xfc,˵Y kUb8pu`%|@r3GtB;W]!z'%QiӐdT ?\=d/sYe';^r#l`6m Z7U^e6oVO \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/c9/4b27e41064c521120627e07e2035cca1d24ffa b/tests/resources/merge-resolve/.gitted/objects/c9/4b27e41064c521120627e07e2035cca1d24ffa new file mode 100644 index 000000000..fd1ec9fab Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/c9/4b27e41064c521120627e07e2035cca1d24ffa differ diff --git a/tests/resources/merge-resolve/.gitted/objects/ca/b2cf23998b40f1af2d9d9a756dc9e285a8df4b b/tests/resources/merge-resolve/.gitted/objects/ca/b2cf23998b40f1af2d9d9a756dc9e285a8df4b new file mode 100644 index 000000000..32ba2aa53 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/ca/b2cf23998b40f1af2d9d9a756dc9e285a8df4b differ diff --git a/tests/resources/merge-resolve/.gitted/objects/cb/491780d82e46dc88a065b965ab307a038f2bc2 b/tests/resources/merge-resolve/.gitted/objects/cb/491780d82e46dc88a065b965ab307a038f2bc2 new file mode 100644 index 000000000..cf9cd7d39 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/cb/491780d82e46dc88a065b965ab307a038f2bc2 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/cb/6693a788715b82440a54e0eacd19ba9f6ec559 b/tests/resources/merge-resolve/.gitted/objects/cb/6693a788715b82440a54e0eacd19ba9f6ec559 new file mode 100644 index 000000000..e11181a96 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/cb/6693a788715b82440a54e0eacd19ba9f6ec559 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/cc/3e3009134cb88014129fc8858d1101359e5e2f b/tests/resources/merge-resolve/.gitted/objects/cc/3e3009134cb88014129fc8858d1101359e5e2f new file mode 100644 index 000000000..9a0cb7a0c --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/cc/3e3009134cb88014129fc8858d1101359e5e2f @@ -0,0 +1,2 @@ +x] +0})&_H -Fb[6}0L2wPzc*sXb Rt#G$[lvH$kf.ʧLF+ QHD|68Wl.S]uoNOu9Va0^ZF9^# Od \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/ce/8860d49e3bea6fd745874a01b7c3e46da8cbc3 b/tests/resources/merge-resolve/.gitted/objects/ce/8860d49e3bea6fd745874a01b7c3e46da8cbc3 new file mode 100644 index 000000000..860f9952f Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/ce/8860d49e3bea6fd745874a01b7c3e46da8cbc3 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/ce/e656c392ad0557b3aae0fb411475c206e2926f b/tests/resources/merge-resolve/.gitted/objects/ce/e656c392ad0557b3aae0fb411475c206e2926f new file mode 100644 index 000000000..ff0624ccb Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/ce/e656c392ad0557b3aae0fb411475c206e2926f differ diff --git a/tests/resources/merge-resolve/.gitted/objects/cf/8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d b/tests/resources/merge-resolve/.gitted/objects/cf/8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d new file mode 100644 index 000000000..36b0289e6 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/cf/8c5cc8a85a1ff5a4ba51e0bc7cf5665669924d differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d0/7ec190c306ec690bac349e87d01c4358e49bb2 b/tests/resources/merge-resolve/.gitted/objects/d0/7ec190c306ec690bac349e87d01c4358e49bb2 new file mode 100644 index 000000000..d52a56ffe --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/d0/7ec190c306ec690bac349e87d01c4358e49bb2 @@ -0,0 +1,2 @@ +xՏ 0 3aOb%ǑS=HT@u:]uYG%LE;u`_?g~0Ҕ. +׋PӜxvXi ӭf! \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/d0/d4594e16f2e19107e3fa7ea63e7aaaff305ffb b/tests/resources/merge-resolve/.gitted/objects/d0/d4594e16f2e19107e3fa7ea63e7aaaff305ffb new file mode 100644 index 000000000..5f7e286ff Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d0/d4594e16f2e19107e3fa7ea63e7aaaff305ffb differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d2/f8637f2eab2507a1e13cbc9df4729ec386627e b/tests/resources/merge-resolve/.gitted/objects/d2/f8637f2eab2507a1e13cbc9df4729ec386627e new file mode 100644 index 000000000..558a8513f Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d2/f8637f2eab2507a1e13cbc9df4729ec386627e differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d3/719a5ae8e4d92276b5313ce976f6ee5af2b436 b/tests/resources/merge-resolve/.gitted/objects/d3/719a5ae8e4d92276b5313ce976f6ee5af2b436 new file mode 100644 index 000000000..930bf5a5e --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/d3/719a5ae8e4d92276b5313ce976f6ee5af2b436 @@ -0,0 +1,2 @@ +x=10 E}uAHب zRHPT Brh/]?a 48,_MdkуTPF!TZQ? +R֧FN_J͆ h{(kLKV1p+Q A \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/d3/7aa3bbfe1c0c49b909781251b956dbabe85f96 b/tests/resources/merge-resolve/.gitted/objects/d3/7aa3bbfe1c0c49b909781251b956dbabe85f96 new file mode 100644 index 000000000..5902e0f32 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d3/7aa3bbfe1c0c49b909781251b956dbabe85f96 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d3/7ad72a2052685fc6201c2af90103ad42d2079b b/tests/resources/merge-resolve/.gitted/objects/d3/7ad72a2052685fc6201c2af90103ad42d2079b new file mode 100644 index 000000000..b2f39bff4 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d3/7ad72a2052685fc6201c2af90103ad42d2079b differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d4/207f77243500bec335ab477f9227fcdb1e271a b/tests/resources/merge-resolve/.gitted/objects/d4/207f77243500bec335ab477f9227fcdb1e271a new file mode 100644 index 000000000..862e4e5bc --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/d4/207f77243500bec335ab477f9227fcdb1e271a @@ -0,0 +1,2 @@ +xK +1D]O'7t:݌H&z:]oZBBXl(昭+d<"6^% A( J,% %5SSmR^؊Nu^뢏O:Wځ| DcFQEn6#Q \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/d4/27e0b2e138501a3d15cc376077a3631e15bd46 b/tests/resources/merge-resolve/.gitted/objects/d4/27e0b2e138501a3d15cc376077a3631e15bd46 new file mode 100644 index 000000000..0b3611ae4 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d4/27e0b2e138501a3d15cc376077a3631e15bd46 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d5/093787ef302b941b6aab081b99fb4880038bd8 b/tests/resources/merge-resolve/.gitted/objects/d5/093787ef302b941b6aab081b99fb4880038bd8 new file mode 100644 index 000000000..7d73449eb Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d5/093787ef302b941b6aab081b99fb4880038bd8 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d5/a61b0b4992a4f0caa887fa08b52431e727bb6f b/tests/resources/merge-resolve/.gitted/objects/d5/a61b0b4992a4f0caa887fa08b52431e727bb6f new file mode 100644 index 000000000..a7921de43 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d5/a61b0b4992a4f0caa887fa08b52431e727bb6f differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d5/b6fc965c926a1bfc9ee456042b94088b5c5d21 b/tests/resources/merge-resolve/.gitted/objects/d5/b6fc965c926a1bfc9ee456042b94088b5c5d21 new file mode 100644 index 000000000..924bdbbb5 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d5/b6fc965c926a1bfc9ee456042b94088b5c5d21 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d5/ec1152fe25e9fec00189eb00b3db71db24c218 b/tests/resources/merge-resolve/.gitted/objects/d5/ec1152fe25e9fec00189eb00b3db71db24c218 new file mode 100644 index 000000000..0d2534bc9 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d5/ec1152fe25e9fec00189eb00b3db71db24c218 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d6/42b9770c66bba94a08df09b5efb095001f76d7 b/tests/resources/merge-resolve/.gitted/objects/d6/42b9770c66bba94a08df09b5efb095001f76d7 new file mode 100644 index 000000000..1671f9f2c Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d6/42b9770c66bba94a08df09b5efb095001f76d7 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d6/462fa3f5292857db599c54aea2bf91616230c5 b/tests/resources/merge-resolve/.gitted/objects/d6/462fa3f5292857db599c54aea2bf91616230c5 new file mode 100644 index 000000000..baae3f0e0 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d6/462fa3f5292857db599c54aea2bf91616230c5 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d6/cf6c7741b3316826af1314042550c97ded1d50 b/tests/resources/merge-resolve/.gitted/objects/d6/cf6c7741b3316826af1314042550c97ded1d50 new file mode 100644 index 000000000..8f9ae1fc6 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/d6/cf6c7741b3316826af1314042550c97ded1d50 @@ -0,0 +1,2 @@ +xQ +1 D)r%i@oje[7̤ZʽMSLBNlm B~>-uY8ꠟt֯]Qa͠3f]>bl(A] \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/d8/74671ef5b20184836cb983bb273e5280384d0b b/tests/resources/merge-resolve/.gitted/objects/d8/74671ef5b20184836cb983bb273e5280384d0b new file mode 100644 index 000000000..1d8037895 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d8/74671ef5b20184836cb983bb273e5280384d0b differ diff --git a/tests/resources/merge-resolve/.gitted/objects/d8/fa77b6833082c1ea36b7828a582d4c43882450 b/tests/resources/merge-resolve/.gitted/objects/d8/fa77b6833082c1ea36b7828a582d4c43882450 new file mode 100644 index 000000000..988145322 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/d8/fa77b6833082c1ea36b7828a582d4c43882450 @@ -0,0 +1 @@ +x1 DQkN1&6%lBknaa1kdI(Ur'7LA,+Wm9 I'U͹_ܰN \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/d9/63979c237d08b6ba39062ee7bf64c7d34a27f8 b/tests/resources/merge-resolve/.gitted/objects/d9/63979c237d08b6ba39062ee7bf64c7d34a27f8 new file mode 100644 index 000000000..5fa10405c Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/d9/63979c237d08b6ba39062ee7bf64c7d34a27f8 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/da/178208145ef585a1bd5ca5f4c9785d738df2cf b/tests/resources/merge-resolve/.gitted/objects/da/178208145ef585a1bd5ca5f4c9785d738df2cf new file mode 100644 index 000000000..6292118e0 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/da/178208145ef585a1bd5ca5f4c9785d738df2cf differ diff --git a/tests/resources/merge-resolve/.gitted/objects/db/6261a7c65c7fd678520c9bb6f2c47582ab9ed5 b/tests/resources/merge-resolve/.gitted/objects/db/6261a7c65c7fd678520c9bb6f2c47582ab9ed5 new file mode 100644 index 000000000..b82e7fcaf Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/db/6261a7c65c7fd678520c9bb6f2c47582ab9ed5 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/dd/9a570c3400e6e07bc4d7651d6e20b08926b3d9 b/tests/resources/merge-resolve/.gitted/objects/dd/9a570c3400e6e07bc4d7651d6e20b08926b3d9 new file mode 100644 index 000000000..8fd60cbe8 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/dd/9a570c3400e6e07bc4d7651d6e20b08926b3d9 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/de/872ee3618b894992e9d1e18ba2ebe256a112f9 b/tests/resources/merge-resolve/.gitted/objects/de/872ee3618b894992e9d1e18ba2ebe256a112f9 new file mode 100644 index 000000000..04dda4a75 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/de/872ee3618b894992e9d1e18ba2ebe256a112f9 @@ -0,0 +1 @@ +x퐱 S3ŏlKAB4Wb T5:8Sc ԻP`KIˆO3Z&ؐ \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/df/e3f22baa1f6fce5447901c3086bae368de6bdd b/tests/resources/merge-resolve/.gitted/objects/df/e3f22baa1f6fce5447901c3086bae368de6bdd new file mode 100644 index 000000000..e13569440 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/df/e3f22baa1f6fce5447901c3086bae368de6bdd differ diff --git a/tests/resources/merge-resolve/.gitted/objects/e0/67f9361140f19391472df8a82d6610813c73b7 b/tests/resources/merge-resolve/.gitted/objects/e0/67f9361140f19391472df8a82d6610813c73b7 new file mode 100644 index 000000000..955431dd7 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/e0/67f9361140f19391472df8a82d6610813c73b7 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/e1/129b3cfb5898e0fbd606e0cb80b2755e50d161 b/tests/resources/merge-resolve/.gitted/objects/e1/129b3cfb5898e0fbd606e0cb80b2755e50d161 new file mode 100644 index 000000000..751f1dd33 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/e1/129b3cfb5898e0fbd606e0cb80b2755e50d161 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/e1/7ace1492648c9dc5701bad5c47af9d1b60c4e9 b/tests/resources/merge-resolve/.gitted/objects/e1/7ace1492648c9dc5701bad5c47af9d1b60c4e9 new file mode 100644 index 000000000..4a812e5df Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/e1/7ace1492648c9dc5701bad5c47af9d1b60c4e9 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/e2/c6abbd55fed5ac71a5f2751e29b4a34726a595 b/tests/resources/merge-resolve/.gitted/objects/e2/c6abbd55fed5ac71a5f2751e29b4a34726a595 new file mode 100644 index 000000000..7b84ce966 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/e2/c6abbd55fed5ac71a5f2751e29b4a34726a595 @@ -0,0 +1 @@ +x+)JMU067f040031QH,-M-JOMLI+(aH:,:C: o>ZC'g$楧f&%%g5qYeZokM2ԐX\ZDPC~^ZNfrIf^:XZHي1O(_,' jvn~JfZ&5%\N,5[e2 I{| 2mg˾15ӿ,\})TC)0Dvz֛9MՅ'6b \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/e3/1e7ad3ed298f24e383c4950f4671993ec078e4 b/tests/resources/merge-resolve/.gitted/objects/e3/1e7ad3ed298f24e383c4950f4671993ec078e4 new file mode 100644 index 000000000..a28ded3fb Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/e3/1e7ad3ed298f24e383c4950f4671993ec078e4 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/e3/76fbdd06ebf021c92724da9f26f44212734e3e b/tests/resources/merge-resolve/.gitted/objects/e3/76fbdd06ebf021c92724da9f26f44212734e3e new file mode 100644 index 000000000..8da234114 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/e3/76fbdd06ebf021c92724da9f26f44212734e3e @@ -0,0 +1,3 @@ +xA@E]s +`@ uH)M=Scz:ʊ(N+6ޛDFe𭭘Yg$+G&F +pG 4mQ\85#FC~QERu);c6'j \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/e4/9f917b448d1340b31d76e54ba388268fd4c922 b/tests/resources/merge-resolve/.gitted/objects/e4/9f917b448d1340b31d76e54ba388268fd4c922 new file mode 100644 index 000000000..870c3e732 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/e4/9f917b448d1340b31d76e54ba388268fd4c922 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/e4/f618a2c3ed0669308735727df5ebf2447f022f b/tests/resources/merge-resolve/.gitted/objects/e4/f618a2c3ed0669308735727df5ebf2447f022f new file mode 100644 index 000000000..c7e1ee9d7 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/e4/f618a2c3ed0669308735727df5ebf2447f022f @@ -0,0 +1,2 @@ +xK!D]s +.iOboi2. bhJQ6b`7:DN.%4uIQYcm`Q¨ aQYa@>ɗEc9%bhf1x}xwUQv kv@`O;$Kșybh2癈sLA ?R\˷ץ(~Yïb-'Yǎp=Njq˟m[zO+ \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/fa/c03f2c5139618d87d53614c153823bf1f31396 b/tests/resources/merge-resolve/.gitted/objects/fa/c03f2c5139618d87d53614c153823bf1f31396 new file mode 100644 index 000000000..30e07e5b7 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/fa/c03f2c5139618d87d53614c153823bf1f31396 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/fa/da9356aa3f74622327a3038ae9c6f92e1c5c1d b/tests/resources/merge-resolve/.gitted/objects/fa/da9356aa3f74622327a3038ae9c6f92e1c5c1d new file mode 100644 index 000000000..16ce49a1b Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/fa/da9356aa3f74622327a3038ae9c6f92e1c5c1d differ diff --git a/tests/resources/merge-resolve/.gitted/objects/fb/738a106cfd097a4acb96ce132ecb1ad6c46b03 b/tests/resources/merge-resolve/.gitted/objects/fb/738a106cfd097a4acb96ce132ecb1ad6c46b03 new file mode 100644 index 000000000..4f1e72688 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/fb/738a106cfd097a4acb96ce132ecb1ad6c46b03 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/fc/4c636d6515e9e261f9260dbcf3cc6eca97ea08 b/tests/resources/merge-resolve/.gitted/objects/fc/4c636d6515e9e261f9260dbcf3cc6eca97ea08 new file mode 100644 index 000000000..be8a810cd Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/fc/4c636d6515e9e261f9260dbcf3cc6eca97ea08 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/fc/7d7b805f7a9428574f4f802b2e34cd20ab9d99 b/tests/resources/merge-resolve/.gitted/objects/fc/7d7b805f7a9428574f4f802b2e34cd20ab9d99 new file mode 100644 index 000000000..20493e68c Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/fc/7d7b805f7a9428574f4f802b2e34cd20ab9d99 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/fc/90237dc4891fa6c69827fc465632225e391618 b/tests/resources/merge-resolve/.gitted/objects/fc/90237dc4891fa6c69827fc465632225e391618 new file mode 100644 index 000000000..961814bae Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/fc/90237dc4891fa6c69827fc465632225e391618 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/fd/57d2d6770fad8e9959124793a17f441b571e66 b/tests/resources/merge-resolve/.gitted/objects/fd/57d2d6770fad8e9959124793a17f441b571e66 new file mode 100644 index 000000000..21e6b2c55 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/fd/57d2d6770fad8e9959124793a17f441b571e66 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/fd/89f8cffb663ac89095a0f9764902e93ceaca6a b/tests/resources/merge-resolve/.gitted/objects/fd/89f8cffb663ac89095a0f9764902e93ceaca6a new file mode 100644 index 000000000..2f9d83b26 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/objects/fd/89f8cffb663ac89095a0f9764902e93ceaca6a @@ -0,0 +1,2 @@ +xK!D]s +.{`cx/ɸ`0 oURy|Y`dPA!4C2d=x#e`BgrubLffG@՗-}KԲUy=];)r0 R$(%o=׶OPw \ No newline at end of file diff --git a/tests/resources/merge-resolve/.gitted/objects/fe/5407fc50a53aecb41d1a6e9ea7b612e581af87 b/tests/resources/merge-resolve/.gitted/objects/fe/5407fc50a53aecb41d1a6e9ea7b612e581af87 new file mode 100644 index 000000000..4ce7d2297 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/fe/5407fc50a53aecb41d1a6e9ea7b612e581af87 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/ff/49d07869831ad761bbdaea026086f8789bcb00 b/tests/resources/merge-resolve/.gitted/objects/ff/49d07869831ad761bbdaea026086f8789bcb00 new file mode 100644 index 000000000..eada39b77 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/ff/49d07869831ad761bbdaea026086f8789bcb00 differ diff --git a/tests/resources/merge-resolve/.gitted/objects/ff/b312248d607284c290023f9502eea010d34efd b/tests/resources/merge-resolve/.gitted/objects/ff/b312248d607284c290023f9502eea010d34efd new file mode 100644 index 000000000..7e46c4fe3 Binary files /dev/null and b/tests/resources/merge-resolve/.gitted/objects/ff/b312248d607284c290023f9502eea010d34efd differ diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/branch b/tests/resources/merge-resolve/.gitted/refs/heads/branch new file mode 100644 index 000000000..03f79a3dc --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/branch @@ -0,0 +1 @@ +7cb63eed597130ba4abb87b3e544b85021905520 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/df_ancestor b/tests/resources/merge-resolve/.gitted/refs/heads/df_ancestor new file mode 100644 index 000000000..4bc37ac60 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/df_ancestor @@ -0,0 +1 @@ +2da538570bc1e5b2c3e855bf702f35248ad0735f diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/df_side1 b/tests/resources/merge-resolve/.gitted/refs/heads/df_side1 new file mode 100644 index 000000000..ca6dd679d --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/df_side1 @@ -0,0 +1 @@ +a7dbfcbfc1a60709cb80b5ca24539008456531d0 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/df_side2 b/tests/resources/merge-resolve/.gitted/refs/heads/df_side2 new file mode 100644 index 000000000..b8160f80e --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/df_side2 @@ -0,0 +1 @@ +fc90237dc4891fa6c69827fc465632225e391618 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/ff_branch b/tests/resources/merge-resolve/.gitted/refs/heads/ff_branch new file mode 100644 index 000000000..e9e90512f --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/ff_branch @@ -0,0 +1 @@ +fd89f8cffb663ac89095a0f9764902e93ceaca6a diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/master b/tests/resources/merge-resolve/.gitted/refs/heads/master new file mode 100644 index 000000000..8a329ae5f --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/master @@ -0,0 +1 @@ +bd593285fc7fe4ca18ccdbabf027f5d689101452 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/octo1 b/tests/resources/merge-resolve/.gitted/refs/heads/octo1 new file mode 100644 index 000000000..4d2c66902 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/octo1 @@ -0,0 +1 @@ +16f825815cfd20a07a75c71554e82d8eede0b061 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/octo2 b/tests/resources/merge-resolve/.gitted/refs/heads/octo2 new file mode 100644 index 000000000..f503977a7 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/octo2 @@ -0,0 +1 @@ +158dc7bedb202f5b26502bf3574faa7f4238d56c diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/octo3 b/tests/resources/merge-resolve/.gitted/refs/heads/octo3 new file mode 100644 index 000000000..b92994f10 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/octo3 @@ -0,0 +1 @@ +50ce7d7d01217679e26c55939eef119e0c93e272 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/octo4 b/tests/resources/merge-resolve/.gitted/refs/heads/octo4 new file mode 100644 index 000000000..f33d57cbc --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/octo4 @@ -0,0 +1 @@ +54269b3f6ec3d7d4ede24dd350dd5d605495c3ae diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/octo5 b/tests/resources/merge-resolve/.gitted/refs/heads/octo5 new file mode 100644 index 000000000..e9f943385 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/octo5 @@ -0,0 +1 @@ +e4f618a2c3ed0669308735727df5ebf2447f022f diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/octo6 b/tests/resources/merge-resolve/.gitted/refs/heads/octo6 new file mode 100644 index 000000000..4c5a98ad9 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/octo6 @@ -0,0 +1 @@ +b6f610aef53bd343e6c96227de874c66f00ee8e8 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ancestor b/tests/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ancestor new file mode 100644 index 000000000..4092d428f --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ancestor @@ -0,0 +1 @@ +2392a2dacc9efb562b8635d6579fb458751c7c5b diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ours b/tests/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ours new file mode 100644 index 000000000..a1c50dce8 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/rename_conflict_ours @@ -0,0 +1 @@ +34bfafff88eaf118402b44e6f3e2dbbf1a582b05 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/rename_conflict_theirs b/tests/resources/merge-resolve/.gitted/refs/heads/rename_conflict_theirs new file mode 100644 index 000000000..130989399 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/rename_conflict_theirs @@ -0,0 +1 @@ +a802e06f1782a9645b9851bc7202cee74a8a4972 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/renames1 b/tests/resources/merge-resolve/.gitted/refs/heads/renames1 new file mode 100644 index 000000000..3d248102c --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/renames1 @@ -0,0 +1 @@ +412b32fb66137366147f1801ecc962452757d48a diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/renames2 b/tests/resources/merge-resolve/.gitted/refs/heads/renames2 new file mode 100644 index 000000000..d22621561 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/renames2 @@ -0,0 +1 @@ +ab40af3cb8a3ed2e2843e96d9aa7871336b94573 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-10 b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-10 new file mode 100644 index 000000000..5b378cd88 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-10 @@ -0,0 +1 @@ +0ec5f433959cd46177f745903353efb5be08d151 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-10-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-10-branch new file mode 100644 index 000000000..b3db6c892 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-10-branch @@ -0,0 +1 @@ +11f4f3c08b737f5fd896cbefa1425ee63b21b2fa diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-11 b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-11 new file mode 100644 index 000000000..154de9a64 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-11 @@ -0,0 +1 @@ +3168dca1a561889b045a6441909f4c56145e666d diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-11-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-11-branch new file mode 100644 index 000000000..2e4118029 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-11-branch @@ -0,0 +1 @@ +6718a45909532d1fcf5600d0877f7fe7e78f0b86 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-13 b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-13 new file mode 100644 index 000000000..297573a57 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-13 @@ -0,0 +1 @@ +a3fabece9eb8748da810e1e08266fef9b7136ad4 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-13-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-13-branch new file mode 100644 index 000000000..22e429a61 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-13-branch @@ -0,0 +1 @@ +05f3c1a2a56ca95c3d2ef28dc9ddf32b5cd6c91c diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-14 b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-14 new file mode 100644 index 000000000..89051853a --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-14 @@ -0,0 +1 @@ +7e2d058d5fedf8329db44db4fac610d6b1a89159 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-14-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-14-branch new file mode 100644 index 000000000..0158f950c --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-14-branch @@ -0,0 +1 @@ +8187117062b750eed4f93fd7e899f17b52ce554d diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-2alt b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-2alt new file mode 100644 index 000000000..474074120 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-2alt @@ -0,0 +1 @@ +566ab53c220a2eafc1212af1a024513230280ab9 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-2alt-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-2alt-branch new file mode 100644 index 000000000..2f5f1a4af --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-2alt-branch @@ -0,0 +1 @@ +c9174cef549ec94ecbc43ef03cdc775b4950becb diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-3alt b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-3alt new file mode 100644 index 000000000..18e50ae12 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-3alt @@ -0,0 +1 @@ +4c9fac0707f8d4195037ae5a681aa48626491541 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-3alt-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-3alt-branch new file mode 100644 index 000000000..7bc1a8d15 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-3alt-branch @@ -0,0 +1 @@ +c607fc30883e335def28cd686b51f6cfa02b06ec diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-4 b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-4 new file mode 100644 index 000000000..f49bbf956 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-4 @@ -0,0 +1 @@ +cc3e3009134cb88014129fc8858d1101359e5e2f diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-4-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-4-branch new file mode 100644 index 000000000..bff519ef1 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-4-branch @@ -0,0 +1 @@ +183310e30fb1499af8c619108ffea4d300b5e778 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1 b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1 new file mode 100644 index 000000000..963a7b336 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1 @@ -0,0 +1 @@ +4fe93c0ec83eb6305cbace3dace88ecee1b63cb6 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1-branch new file mode 100644 index 000000000..4a22138e7 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-1-branch @@ -0,0 +1 @@ +478172cb2f5ff9b514bc9d04d3bd5ef5840cb3b2 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2 b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2 new file mode 100644 index 000000000..aa4ada17e --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2 @@ -0,0 +1 @@ +3b47b031b3e55ae11e14a05260b1c3ffd6838d55 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2-branch new file mode 100644 index 000000000..5553cdba1 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-5alt-2-branch @@ -0,0 +1 @@ +f48097eb340dc5a7cae55aabcf1faf4548aa821f diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-6 b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-6 new file mode 100644 index 000000000..fb685bb63 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-6 @@ -0,0 +1 @@ +99b4f7e4f24470fa06b980bc21f1095c2a9425c0 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-6-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-6-branch new file mode 100644 index 000000000..efc4c55ac --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-6-branch @@ -0,0 +1 @@ +a43150a738849c59376cf30bb2a68348a83c8f48 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-7 b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-7 new file mode 100644 index 000000000..9c9424346 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-7 @@ -0,0 +1 @@ +d874671ef5b20184836cb983bb273e5280384d0b diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-7-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-7-branch new file mode 100644 index 000000000..1762bb5db --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-7-branch @@ -0,0 +1 @@ +5195a1b480f66691b667f10a9e41e70115a78351 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-8 b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-8 new file mode 100644 index 000000000..837c4915a --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-8 @@ -0,0 +1 @@ +3575826c96a975031d2c14368529cc5c4353a8fd diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-8-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-8-branch new file mode 100644 index 000000000..874230eff --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-8-branch @@ -0,0 +1 @@ +52d8bc572af2b6d4ee0d5e62ed5d1fbad92210a9 diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-9 b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-9 new file mode 100644 index 000000000..b968a3efb --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-9 @@ -0,0 +1 @@ +c35dee9bcc0e989f3b0c40f68372a9a51b6c4e6a diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/trivial-9-branch b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-9-branch new file mode 100644 index 000000000..7f3097b69 --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/trivial-9-branch @@ -0,0 +1 @@ +13d1be4ea52a6ced1d7a1d832f0ee3c399348e5e diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/unrelated b/tests/resources/merge-resolve/.gitted/refs/heads/unrelated new file mode 100644 index 000000000..bb877be2e --- /dev/null +++ b/tests/resources/merge-resolve/.gitted/refs/heads/unrelated @@ -0,0 +1 @@ +55b4e4687e7a0d9ca367016ed930f385d4022e6f diff --git a/tests/resources/merge-resolve/added-in-master.txt b/tests/resources/merge-resolve/added-in-master.txt new file mode 100644 index 000000000..233c0919c --- /dev/null +++ b/tests/resources/merge-resolve/added-in-master.txt @@ -0,0 +1 @@ +this file is added in master diff --git a/tests/resources/merge-resolve/automergeable.txt b/tests/resources/merge-resolve/automergeable.txt new file mode 100644 index 000000000..ee3fa1b8c --- /dev/null +++ b/tests/resources/merge-resolve/automergeable.txt @@ -0,0 +1,9 @@ +this file is changed in master +this file is automergeable +this file is automergeable +this file is automergeable +this file is automergeable +this file is automergeable +this file is automergeable +this file is automergeable +this file is automergeable diff --git a/tests/resources/merge-resolve/changed-in-branch.txt b/tests/resources/merge-resolve/changed-in-branch.txt new file mode 100644 index 000000000..ab6c44a2e --- /dev/null +++ b/tests/resources/merge-resolve/changed-in-branch.txt @@ -0,0 +1 @@ +initial revision diff --git a/tests/resources/merge-resolve/changed-in-master.txt b/tests/resources/merge-resolve/changed-in-master.txt new file mode 100644 index 000000000..11deab00b --- /dev/null +++ b/tests/resources/merge-resolve/changed-in-master.txt @@ -0,0 +1 @@ +changed in master diff --git a/tests/resources/merge-resolve/conflicting.txt b/tests/resources/merge-resolve/conflicting.txt new file mode 100644 index 000000000..4e886e602 --- /dev/null +++ b/tests/resources/merge-resolve/conflicting.txt @@ -0,0 +1 @@ +this file is changed in master and branch diff --git a/tests/resources/merge-resolve/removed-in-branch.txt b/tests/resources/merge-resolve/removed-in-branch.txt new file mode 100644 index 000000000..dfe3f22ba --- /dev/null +++ b/tests/resources/merge-resolve/removed-in-branch.txt @@ -0,0 +1 @@ +this is removed in branch diff --git a/tests/resources/merge-resolve/unchanged.txt b/tests/resources/merge-resolve/unchanged.txt new file mode 100644 index 000000000..c8f06f2e3 --- /dev/null +++ b/tests/resources/merge-resolve/unchanged.txt @@ -0,0 +1 @@ +this file is unchanged in both diff --git a/tests/resources/mergedrepo/.gitted/COMMIT_EDITMSG b/tests/resources/mergedrepo/.gitted/COMMIT_EDITMSG new file mode 100644 index 000000000..1f7391f92 --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/COMMIT_EDITMSG @@ -0,0 +1 @@ +master diff --git a/tests/resources/mergedrepo/.gitted/HEAD b/tests/resources/mergedrepo/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/mergedrepo/.gitted/MERGE_HEAD b/tests/resources/mergedrepo/.gitted/MERGE_HEAD new file mode 100644 index 000000000..a5bdf6e40 --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/MERGE_HEAD @@ -0,0 +1 @@ +e2809157a7766f272e4cfe26e61ef2678a5357ff diff --git a/tests/resources/mergedrepo/.gitted/MERGE_MODE b/tests/resources/mergedrepo/.gitted/MERGE_MODE new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/mergedrepo/.gitted/MERGE_MSG b/tests/resources/mergedrepo/.gitted/MERGE_MSG new file mode 100644 index 000000000..7c4d1f5a9 --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/MERGE_MSG @@ -0,0 +1,5 @@ +Merge branch 'branch' + +Conflicts: + conflicts-one.txt + conflicts-two.txt diff --git a/tests/resources/mergedrepo/.gitted/ORIG_HEAD b/tests/resources/mergedrepo/.gitted/ORIG_HEAD new file mode 100644 index 000000000..13d4d6721 --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/ORIG_HEAD @@ -0,0 +1 @@ +3a34580a35add43a4cf361e8e9a30060a905c876 diff --git a/tests/resources/mergedrepo/.gitted/config b/tests/resources/mergedrepo/.gitted/config new file mode 100644 index 000000000..af107929f --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true diff --git a/tests/resources/mergedrepo/.gitted/description b/tests/resources/mergedrepo/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/mergedrepo/.gitted/index b/tests/resources/mergedrepo/.gitted/index new file mode 100644 index 000000000..3d29f78e7 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/index differ diff --git a/tests/resources/mergedrepo/.gitted/info/exclude b/tests/resources/mergedrepo/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/mergedrepo/.gitted/logs/HEAD b/tests/resources/mergedrepo/.gitted/logs/HEAD new file mode 100644 index 000000000..a385da67b --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/logs/HEAD @@ -0,0 +1,5 @@ +0000000000000000000000000000000000000000 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371828 -0500 commit (initial): initial +9a05ccb4e0f948de03128e095f39dae6976751c5 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371835 -0500 checkout: moving from master to branch +9a05ccb4e0f948de03128e095f39dae6976751c5 e2809157a7766f272e4cfe26e61ef2678a5357ff Edward Thomson 1351371872 -0500 commit: branch +e2809157a7766f272e4cfe26e61ef2678a5357ff 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371873 -0500 checkout: moving from branch to master +9a05ccb4e0f948de03128e095f39dae6976751c5 3a34580a35add43a4cf361e8e9a30060a905c876 Edward Thomson 1351372106 -0500 commit: master diff --git a/tests/resources/mergedrepo/.gitted/logs/refs/heads/branch b/tests/resources/mergedrepo/.gitted/logs/refs/heads/branch new file mode 100644 index 000000000..26a5e8dc5 --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/logs/refs/heads/branch @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371835 -0500 branch: Created from HEAD +9a05ccb4e0f948de03128e095f39dae6976751c5 e2809157a7766f272e4cfe26e61ef2678a5357ff Edward Thomson 1351371872 -0500 commit: branch diff --git a/tests/resources/mergedrepo/.gitted/logs/refs/heads/master b/tests/resources/mergedrepo/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..425f7bd89 --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/logs/refs/heads/master @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 9a05ccb4e0f948de03128e095f39dae6976751c5 Edward Thomson 1351371828 -0500 commit (initial): initial +9a05ccb4e0f948de03128e095f39dae6976751c5 3a34580a35add43a4cf361e8e9a30060a905c876 Edward Thomson 1351372106 -0500 commit: master diff --git a/tests/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712 b/tests/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712 new file mode 100644 index 000000000..9232f79d9 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/03/db1d37504ca0c4f7c26d7776b0e28bdea08712 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91 b/tests/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91 new file mode 100644 index 000000000..3e124d9a4 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/17/0efc1023e0ed2390150bb4469c8456b63e8f91 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 b/tests/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 new file mode 100644 index 000000000..7bb19c873 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/1f/85ca51b8e0aac893a621b61a9c2661d6aa6d81 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211e b/tests/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211e new file mode 100644 index 000000000..487bcffb1 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/22/0bd62631c8cf7a83ef39c6b94595f00517211e differ diff --git a/tests/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6 b/tests/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6 new file mode 100644 index 000000000..2eb3954fc Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/32/d55d59265db86dd690f0a7fc563db43e2bc6a6 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534 b/tests/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534 new file mode 100644 index 000000000..ebe83ccb2 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/38/e2d82b9065a237904af4b780b4d68da6950534 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/3a/34580a35add43a4cf361e8e9a30060a905c876 b/tests/resources/mergedrepo/.gitted/objects/3a/34580a35add43a4cf361e8e9a30060a905c876 new file mode 100644 index 000000000..0d4095ffc --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/objects/3a/34580a35add43a4cf361e8e9a30060a905c876 @@ -0,0 +1,2 @@ +xK +1D]}Dx/O"F2oo<*ZoљuIhhrl"r YT8'#vm0.¨.:.#+9R^nG~[=VjR"IjD۔7|N` \ No newline at end of file diff --git a/tests/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8c b/tests/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8c new file mode 100644 index 000000000..33389c302 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/44/58b8bc9e72b6c8755ae456f60e9844d0538d8c differ diff --git a/tests/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3 b/tests/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3 new file mode 100644 index 000000000..5361ea685 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/47/8871385b9cd03908c5383acfd568bef023c6b3 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52da b/tests/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52da new file mode 100644 index 000000000..a60da877c Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/51/6bd85f78061e09ccc714561d7b504672cb52da differ diff --git a/tests/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46ad b/tests/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46ad new file mode 100644 index 000000000..85e84d71e Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/53/c1d95a01f4514b162066fc98564500c96c46ad differ diff --git a/tests/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399 b/tests/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399 new file mode 100644 index 000000000..b16b521e6 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/6a/ea5f295304c36144ad6e9247a291b7f8112399 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 b/tests/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 new file mode 100644 index 000000000..7c4e85ffb Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/70/68e30a7f0090ae32db35dfa1e4189d8780fcb8 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 b/tests/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 new file mode 100644 index 000000000..65173fc4d Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/75/938de1e367098b3e9a7b1ec3c4ac4548afffe4 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71 b/tests/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71 new file mode 100644 index 000000000..162fa4455 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/7b/26923aaf452b1977eb08617c59475fb3f74b71 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038c b/tests/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038c new file mode 100644 index 000000000..77a519f55 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/84/af62840be1b1c47b778a8a249f3ff45155038c differ diff --git a/tests/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda b/tests/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda new file mode 100644 index 000000000..f624cd4f1 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/88/71f7a2ee3addfc4ba39fbd0783c8e738d04cda differ diff --git a/tests/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673 b/tests/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673 new file mode 100644 index 000000000..096474c03 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/88/7b153b165d32409c70163e0f734c090f12f673 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735a b/tests/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735a new file mode 100644 index 000000000..a413bc6b0 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/8a/ad34cc83733590e74b93d0f7cf00375e2a735a differ diff --git a/tests/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2 b/tests/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2 new file mode 100644 index 000000000..3ac8f6018 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/8b/3f43d2402825c200f835ca1762413e386fd0b2 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8 b/tests/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8 new file mode 100644 index 000000000..589a5ae9b Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/8b/72416545c7e761b64cecad4f1686eae4078aa8 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 b/tests/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 new file mode 100644 index 000000000..6503985e3 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/8f/3c06cff9a83757cec40c80bc9bf31a2582bde9 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50 b/tests/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50 new file mode 100644 index 000000000..2eaa80838 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/8f/fcc405925511824a2240a6d3686aa7f8c7ac50 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/9a/05ccb4e0f948de03128e095f39dae6976751c5 b/tests/resources/mergedrepo/.gitted/objects/9a/05ccb4e0f948de03128e095f39dae6976751c5 new file mode 100644 index 000000000..7373a80d8 --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/objects/9a/05ccb4e0f948de03128e095f39dae6976751c5 @@ -0,0 +1 @@ +x !Dm@ c6q##Ay/ ܁:#$ltH:闄*DXhV} ˷n[-K_;Z@J GԈbq3"go@I \ No newline at end of file diff --git a/tests/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092c b/tests/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092c new file mode 100644 index 000000000..c5a651f97 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/9d/81f82fccc7dcd7de7a1ffead1815294c2e092c differ diff --git a/tests/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d b/tests/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d new file mode 100644 index 000000000..3e14b5dc8 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/b7/cedb8ad4cbb22b6363f9578cbd749797f7ef0d differ diff --git a/tests/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51 b/tests/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51 new file mode 100644 index 000000000..a641adc2e Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/d0/1885ea594926eae9ba5b54ad76692af5969f51 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/e2/809157a7766f272e4cfe26e61ef2678a5357ff b/tests/resources/mergedrepo/.gitted/objects/e2/809157a7766f272e4cfe26e61ef2678a5357ff new file mode 100644 index 000000000..fa86662e0 --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/objects/e2/809157a7766f272e4cfe26e61ef2678a5357ff @@ -0,0 +1,3 @@ +xK +1D]t> xNq1(]{Pe mٍ.S0[Dcd +ŅbMԝCgd@>glX].$!0*zu})/E_<ڪO:WځrơqѤh@mt;;5uZyVo\M \ No newline at end of file diff --git a/tests/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478 b/tests/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478 new file mode 100644 index 000000000..c9841c698 Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/e6/2cac5c88b9928f2695b934c70efa4285324478 differ diff --git a/tests/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406 b/tests/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406 new file mode 100644 index 000000000..cd587dbec Binary files /dev/null and b/tests/resources/mergedrepo/.gitted/objects/f7/2784290c151092abf04ce6b875068547f70406 differ diff --git a/tests/resources/mergedrepo/.gitted/refs/heads/branch b/tests/resources/mergedrepo/.gitted/refs/heads/branch new file mode 100644 index 000000000..a5bdf6e40 --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/refs/heads/branch @@ -0,0 +1 @@ +e2809157a7766f272e4cfe26e61ef2678a5357ff diff --git a/tests/resources/mergedrepo/.gitted/refs/heads/master b/tests/resources/mergedrepo/.gitted/refs/heads/master new file mode 100644 index 000000000..13d4d6721 --- /dev/null +++ b/tests/resources/mergedrepo/.gitted/refs/heads/master @@ -0,0 +1 @@ +3a34580a35add43a4cf361e8e9a30060a905c876 diff --git a/tests/resources/mergedrepo/conflicts-one.txt b/tests/resources/mergedrepo/conflicts-one.txt new file mode 100644 index 000000000..8aad34cc8 --- /dev/null +++ b/tests/resources/mergedrepo/conflicts-one.txt @@ -0,0 +1,5 @@ +<<<<<<< HEAD +This is most certainly a conflict! +======= +This is a conflict!!! +>>>>>>> branch diff --git a/tests/resources/mergedrepo/conflicts-two.txt b/tests/resources/mergedrepo/conflicts-two.txt new file mode 100644 index 000000000..e62cac5c8 --- /dev/null +++ b/tests/resources/mergedrepo/conflicts-two.txt @@ -0,0 +1,5 @@ +<<<<<<< HEAD +This is without question another conflict! +======= +This is another conflict!!! +>>>>>>> branch diff --git a/tests/resources/mergedrepo/one.txt b/tests/resources/mergedrepo/one.txt new file mode 100644 index 000000000..75938de1e --- /dev/null +++ b/tests/resources/mergedrepo/one.txt @@ -0,0 +1,10 @@ +This is file one! +This is file one. +This is file one. +This is file one. +This is file one. +This is file one. +This is file one. +This is file one. +This is file one. +This is file one! diff --git a/tests/resources/mergedrepo/two.txt b/tests/resources/mergedrepo/two.txt new file mode 100644 index 000000000..7b26923aa --- /dev/null +++ b/tests/resources/mergedrepo/two.txt @@ -0,0 +1,12 @@ +This is file two! +This is file two. +This is file two. +This is file two. +This is file two. +This is file two. +This is file two. +This is file two. +This is file two. +This is file two. +This is file two. +This is file two! diff --git a/tests/resources/partial-testrepo/.gitted/HEAD b/tests/resources/partial-testrepo/.gitted/HEAD new file mode 100644 index 000000000..4bfb9c93f --- /dev/null +++ b/tests/resources/partial-testrepo/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/dir diff --git a/tests/resources/partial-testrepo/.gitted/config b/tests/resources/partial-testrepo/.gitted/config new file mode 100644 index 000000000..99abaab97 --- /dev/null +++ b/tests/resources/partial-testrepo/.gitted/config @@ -0,0 +1,7 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true +[branch "dir"] diff --git a/tests/resources/partial-testrepo/.gitted/index b/tests/resources/partial-testrepo/.gitted/index new file mode 100644 index 000000000..4f241f914 Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/index differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 b/tests/resources/partial-testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 new file mode 100644 index 000000000..cedb2a22e Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e b/tests/resources/partial-testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e new file mode 100644 index 000000000..b7d944fa1 Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/16/8e4ebd1c667499548ae12403b19b22a5c5e925 b/tests/resources/partial-testrepo/.gitted/objects/16/8e4ebd1c667499548ae12403b19b22a5c5e925 new file mode 100644 index 000000000..d37b93e4f Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/16/8e4ebd1c667499548ae12403b19b22a5c5e925 differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 b/tests/resources/partial-testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 new file mode 100644 index 000000000..93a16f146 Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd b/tests/resources/partial-testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd new file mode 100644 index 000000000..ba0bfb30c Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests/resources/partial-testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 new file mode 100644 index 000000000..7ca4ceed5 Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 b/tests/resources/partial-testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 new file mode 100644 index 000000000..8953b6cef --- /dev/null +++ b/tests/resources/partial-testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 @@ -0,0 +1,2 @@ +xQ +0D)6ͦ "xO-FbEo0 Ǥ,ske[Pn8R,EpD?g}^3 <GhYK8ЖDA);gݧjp4-r;sGA4ۺ=(in7IKFE \ No newline at end of file diff --git a/tests/resources/partial-testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 b/tests/resources/partial-testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 new file mode 100644 index 000000000..e9150214b Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 b/tests/resources/partial-testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 new file mode 100644 index 000000000..c1f22c54f --- /dev/null +++ b/tests/resources/partial-testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 @@ -0,0 +1,2 @@ +x 1ENi@k2 "X$YW0YcÅszMD08!s Xgd::@X0Pw"F/RUzmZZV}|/o5I!1z:vUim}/> +F- \ No newline at end of file diff --git a/tests/resources/partial-testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc b/tests/resources/partial-testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc new file mode 100644 index 000000000..b669961d8 Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 b/tests/resources/partial-testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 new file mode 100644 index 000000000..9ff5eb2b5 Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests/resources/partial-testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a new file mode 100644 index 000000000..2ef4faa0f Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests/resources/partial-testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d new file mode 100644 index 000000000..2f9b6b6e3 Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests/resources/partial-testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 new file mode 100644 index 000000000..5df58dda5 Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests/resources/partial-testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a new file mode 100644 index 000000000..a79612435 --- /dev/null +++ b/tests/resources/partial-testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a @@ -0,0 +1,3 @@ +x[ +0E*fդ "W0-Ft݁pS[Yx^ +Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests/resources/partial-testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests/resources/partial-testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f new file mode 100644 index 000000000..f8588696b --- /dev/null +++ b/tests/resources/partial-testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f @@ -0,0 +1,2 @@ +x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S + U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests/resources/partial-testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd b/tests/resources/partial-testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd new file mode 100644 index 000000000..d0d7e736e Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 b/tests/resources/partial-testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 new file mode 100644 index 000000000..18a7f61c2 Binary files /dev/null and b/tests/resources/partial-testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 differ diff --git a/tests/resources/partial-testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd b/tests/resources/partial-testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd new file mode 100644 index 000000000..75f541f10 --- /dev/null +++ b/tests/resources/partial-testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd @@ -0,0 +1,3 @@ +xQ +0D)ʦI<'lR+FjEo0 a.txt + git add . + git commit -m 'added a.txt' + + mkdir fold + echo b > fold/b.txt + git add . + git commit -m 'added fold and fold/b.txt' + + git branch b1 #b1 and b2 are the same + git branch b2 + + git checkout -b b3 + echo edit >> a.txt + git add . + git commit -m 'edited a.txt' + + git checkout -b b4 master + echo edit >> fold\b.txt + git add . + git commit -m 'edited fold\b.txt' + + git checkout -b b5 master + git submodule add ../testrepo.git submodule + git commit -m "added submodule named 'submodule' pointing to '../testrepo.git'" + + git checkout master + git merge -m "merge b3, b4, and b5 to master" b3 b4 b5 + + #Log commits to include in testcase + git log --format=oneline --decorate --graph + #*-. 951bbbb90e2259a4c8950db78946784fb53fcbce (HEAD, master) merge b3, b4, and b5 to master + #|\ \ + #| | * fa38b91f199934685819bea316186d8b008c52a2 (b5) added submodule named 'submodule' pointing to '../testrepo.git' + #| * | 27b7ce66243eb1403862d05f958c002312df173d (b4) edited fold\b.txt + #| |/ + #* | d9b63a88223d8367516f50bd131a5f7349b7f3e4 (b3) edited a.txt + #|/ + #* a78705c3b2725f931d3ee05348d83cc26700f247 (b2, b1) added fold and fold/b.txt + #* 5c0bb3d1b9449d1cc69d7519fd05166f01840915 added a.txt + + #fix paths so that we can add repo folders under libgit2 repo + #rename .git to .gitted + find . -name .git -exec mv -i '{}' '{}ted' \; + mv -i .gitmodules gitmodules +popd diff --git a/tests/resources/push_src/.gitted/COMMIT_EDITMSG b/tests/resources/push_src/.gitted/COMMIT_EDITMSG new file mode 100644 index 000000000..b1295084c --- /dev/null +++ b/tests/resources/push_src/.gitted/COMMIT_EDITMSG @@ -0,0 +1 @@ +added submodule named 'submodule' pointing to '../testrepo.git' diff --git a/tests/resources/push_src/.gitted/HEAD b/tests/resources/push_src/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/push_src/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/push_src/.gitted/ORIG_HEAD b/tests/resources/push_src/.gitted/ORIG_HEAD new file mode 100644 index 000000000..afadf9d26 --- /dev/null +++ b/tests/resources/push_src/.gitted/ORIG_HEAD @@ -0,0 +1 @@ +a78705c3b2725f931d3ee05348d83cc26700f247 diff --git a/tests/resources/push_src/.gitted/config b/tests/resources/push_src/.gitted/config new file mode 100644 index 000000000..51de0311b --- /dev/null +++ b/tests/resources/push_src/.gitted/config @@ -0,0 +1,10 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + symlinks = false + ignorecase = true + hideDotFiles = dotGitOnly +[submodule "submodule"] + url = m:/dd/libgit2/tests-clar/resources/testrepo.git diff --git a/tests/resources/push_src/.gitted/description b/tests/resources/push_src/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/push_src/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/push_src/.gitted/index b/tests/resources/push_src/.gitted/index new file mode 100644 index 000000000..0ef6594b3 Binary files /dev/null and b/tests/resources/push_src/.gitted/index differ diff --git a/tests/resources/push_src/.gitted/info/exclude b/tests/resources/push_src/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/push_src/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/push_src/.gitted/logs/HEAD b/tests/resources/push_src/.gitted/logs/HEAD new file mode 100644 index 000000000..4ef336f84 --- /dev/null +++ b/tests/resources/push_src/.gitted/logs/HEAD @@ -0,0 +1,10 @@ +0000000000000000000000000000000000000000 5c0bb3d1b9449d1cc69d7519fd05166f01840915 Congyi Wu 1352923200 -0500 commit (initial): added a.txt +5c0bb3d1b9449d1cc69d7519fd05166f01840915 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923200 -0500 commit: added fold and fold/b.txt +a78705c3b2725f931d3ee05348d83cc26700f247 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923201 -0500 checkout: moving from master to b3 +a78705c3b2725f931d3ee05348d83cc26700f247 d9b63a88223d8367516f50bd131a5f7349b7f3e4 Congyi Wu 1352923201 -0500 commit: edited a.txt +d9b63a88223d8367516f50bd131a5f7349b7f3e4 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923201 -0500 checkout: moving from b3 to b4 +a78705c3b2725f931d3ee05348d83cc26700f247 27b7ce66243eb1403862d05f958c002312df173d Congyi Wu 1352923201 -0500 commit: edited fold\b.txt +27b7ce66243eb1403862d05f958c002312df173d a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923201 -0500 checkout: moving from b4 to b5 +a78705c3b2725f931d3ee05348d83cc26700f247 fa38b91f199934685819bea316186d8b008c52a2 Congyi Wu 1352923206 -0500 commit: added submodule named 'submodule' pointing to '../testrepo.git' +fa38b91f199934685819bea316186d8b008c52a2 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923207 -0500 checkout: moving from b5 to master +a78705c3b2725f931d3ee05348d83cc26700f247 951bbbb90e2259a4c8950db78946784fb53fcbce Congyi Wu 1352923207 -0500 merge b3 b4 b5: Merge made by the 'octopus' strategy. diff --git a/tests/resources/push_src/.gitted/logs/refs/heads/b1 b/tests/resources/push_src/.gitted/logs/refs/heads/b1 new file mode 100644 index 000000000..390a03d5c --- /dev/null +++ b/tests/resources/push_src/.gitted/logs/refs/heads/b1 @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923200 -0500 branch: Created from master diff --git a/tests/resources/push_src/.gitted/logs/refs/heads/b2 b/tests/resources/push_src/.gitted/logs/refs/heads/b2 new file mode 100644 index 000000000..390a03d5c --- /dev/null +++ b/tests/resources/push_src/.gitted/logs/refs/heads/b2 @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923200 -0500 branch: Created from master diff --git a/tests/resources/push_src/.gitted/logs/refs/heads/b3 b/tests/resources/push_src/.gitted/logs/refs/heads/b3 new file mode 100644 index 000000000..01e302c44 --- /dev/null +++ b/tests/resources/push_src/.gitted/logs/refs/heads/b3 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923201 -0500 branch: Created from HEAD +a78705c3b2725f931d3ee05348d83cc26700f247 d9b63a88223d8367516f50bd131a5f7349b7f3e4 Congyi Wu 1352923201 -0500 commit: edited a.txt diff --git a/tests/resources/push_src/.gitted/logs/refs/heads/b4 b/tests/resources/push_src/.gitted/logs/refs/heads/b4 new file mode 100644 index 000000000..7afddc54e --- /dev/null +++ b/tests/resources/push_src/.gitted/logs/refs/heads/b4 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923201 -0500 branch: Created from master +a78705c3b2725f931d3ee05348d83cc26700f247 27b7ce66243eb1403862d05f958c002312df173d Congyi Wu 1352923201 -0500 commit: edited fold\b.txt diff --git a/tests/resources/push_src/.gitted/logs/refs/heads/b5 b/tests/resources/push_src/.gitted/logs/refs/heads/b5 new file mode 100644 index 000000000..bc22567f7 --- /dev/null +++ b/tests/resources/push_src/.gitted/logs/refs/heads/b5 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923201 -0500 branch: Created from master +a78705c3b2725f931d3ee05348d83cc26700f247 fa38b91f199934685819bea316186d8b008c52a2 Congyi Wu 1352923206 -0500 commit: added submodule named 'submodule' pointing to '../testrepo.git' diff --git a/tests/resources/push_src/.gitted/logs/refs/heads/master b/tests/resources/push_src/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..8aafa9ca4 --- /dev/null +++ b/tests/resources/push_src/.gitted/logs/refs/heads/master @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 5c0bb3d1b9449d1cc69d7519fd05166f01840915 Congyi Wu 1352923200 -0500 commit (initial): added a.txt +5c0bb3d1b9449d1cc69d7519fd05166f01840915 a78705c3b2725f931d3ee05348d83cc26700f247 Congyi Wu 1352923200 -0500 commit: added fold and fold/b.txt +a78705c3b2725f931d3ee05348d83cc26700f247 951bbbb90e2259a4c8950db78946784fb53fcbce Congyi Wu 1352923207 -0500 merge b3 b4 b5: Merge made by the 'octopus' strategy. diff --git a/tests/resources/push_src/.gitted/modules/submodule/HEAD b/tests/resources/push_src/.gitted/modules/submodule/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/push_src/.gitted/modules/submodule/config b/tests/resources/push_src/.gitted/modules/submodule/config new file mode 100644 index 000000000..59810077d --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/config @@ -0,0 +1,15 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + worktree = ../../../submodule + symlinks = false + ignorecase = true + hideDotFiles = dotGitOnly +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = m:/dd/libgit2/tests-clar/resources/testrepo.git +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/tests/resources/push_src/.gitted/modules/submodule/description b/tests/resources/push_src/.gitted/modules/submodule/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/push_src/.gitted/modules/submodule/index b/tests/resources/push_src/.gitted/modules/submodule/index new file mode 100644 index 000000000..8e44080f3 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/index differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/info/exclude b/tests/resources/push_src/.gitted/modules/submodule/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/push_src/.gitted/modules/submodule/logs/HEAD b/tests/resources/push_src/.gitted/modules/submodule/logs/HEAD new file mode 100644 index 000000000..aedcdf295 --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Congyi Wu 1352923205 -0500 clone: from m:/dd/libgit2/tests-clar/resources/testrepo.git diff --git a/tests/resources/push_src/.gitted/modules/submodule/logs/refs/heads/master b/tests/resources/push_src/.gitted/modules/submodule/logs/refs/heads/master new file mode 100644 index 000000000..aedcdf295 --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Congyi Wu 1352923205 -0500 clone: from m:/dd/libgit2/tests-clar/resources/testrepo.git diff --git a/tests/resources/push_src/.gitted/modules/submodule/logs/refs/remotes/origin/HEAD b/tests/resources/push_src/.gitted/modules/submodule/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..aedcdf295 --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Congyi Wu 1352923205 -0500 clone: from m:/dd/libgit2/tests-clar/resources/testrepo.git diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 b/tests/resources/push_src/.gitted/modules/submodule/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 new file mode 100644 index 000000000..d1c032fce Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 b/tests/resources/push_src/.gitted/modules/submodule/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 new file mode 100644 index 000000000..cedb2a22e Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 b/tests/resources/push_src/.gitted/modules/submodule/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 new file mode 100644 index 000000000..93a16f146 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/18/10dff58d8a660512d4832e740f692884338ccd b/tests/resources/push_src/.gitted/modules/submodule/objects/18/10dff58d8a660512d4832e740f692884338ccd new file mode 100644 index 000000000..ba0bfb30c Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/18/10dff58d8a660512d4832e740f692884338ccd differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd b/tests/resources/push_src/.gitted/modules/submodule/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd new file mode 100644 index 000000000..3ec541288 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/1b/8cbad43e867676df601306689fe7c3def5e689 b/tests/resources/push_src/.gitted/modules/submodule/objects/1b/8cbad43e867676df601306689fe7c3def5e689 new file mode 100644 index 000000000..6048d4bad Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/1b/8cbad43e867676df601306689fe7c3def5e689 differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b b/tests/resources/push_src/.gitted/modules/submodule/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b new file mode 100644 index 000000000..225c45734 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 b/tests/resources/push_src/.gitted/modules/submodule/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 new file mode 100644 index 000000000..cb1ed5712 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d b/tests/resources/push_src/.gitted/modules/submodule/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d new file mode 100644 index 000000000..df40d99af Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 b/tests/resources/push_src/.gitted/modules/submodule/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 new file mode 100644 index 000000000..0a1500a6f Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 b/tests/resources/push_src/.gitted/modules/submodule/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 new file mode 100644 index 000000000..321eaa867 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc b/tests/resources/push_src/.gitted/modules/submodule/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc new file mode 100644 index 000000000..9bb5b623b Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests/resources/push_src/.gitted/modules/submodule/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 new file mode 100644 index 000000000..7ca4ceed5 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 b/tests/resources/push_src/.gitted/modules/submodule/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 new file mode 100644 index 000000000..8953b6cef --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 @@ -0,0 +1,2 @@ +xQ +0D)6ͦ "xO-FbEo0 Ǥ,ske[Pn8R,EpD?g}^3 <GhYK8ЖDA);gݧjp4-r;sGA4ۺ=(in7IKFE \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea b/tests/resources/push_src/.gitted/modules/submodule/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea new file mode 100644 index 000000000..b4e5aa186 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 b/tests/resources/push_src/.gitted/modules/submodule/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 new file mode 100644 index 000000000..351cff823 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 b/tests/resources/push_src/.gitted/modules/submodule/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 new file mode 100644 index 000000000..c1f22c54f --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 @@ -0,0 +1,2 @@ +x 1ENi@k2 "X$YW0YcÅszMD08!s Xgd::@X0Pw"F/RUzmZZV}|/o5I!1z:vUim}/> +F- \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests/resources/push_src/.gitted/modules/submodule/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a new file mode 100644 index 000000000..2ef4faa0f Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af b/tests/resources/push_src/.gitted/modules/submodule/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af new file mode 100644 index 000000000..716b0c64b --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af @@ -0,0 +1 @@ +xAj!?009o}H6}jUPPZ&Y AԛpFdpz[fYPqLJ.,Z`Ů.`v q $5+9Ot>/DE/龡W*eVdf1>覭ěʙFThk.i^0?PR, \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/7b/4384978d2493e851f9cca7858815fac9b10980 b/tests/resources/push_src/.gitted/modules/submodule/objects/7b/4384978d2493e851f9cca7858815fac9b10980 new file mode 100644 index 000000000..23c462f34 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/7b/4384978d2493e851f9cca7858815fac9b10980 differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests/resources/push_src/.gitted/modules/submodule/objects/81/4889a078c031f61ed08ab5fa863aea9314344d new file mode 100644 index 000000000..2f9b6b6e3 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/81/4889a078c031f61ed08ab5fa863aea9314344d differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests/resources/push_src/.gitted/modules/submodule/objects/84/96071c1b46c854b31185ea97743be6a8774479 new file mode 100644 index 000000000..5df58dda5 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/84/96071c1b46c854b31185ea97743be6a8774479 differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe b/tests/resources/push_src/.gitted/modules/submodule/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe new file mode 100644 index 000000000..71019a636 --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe @@ -0,0 +1,2 @@ +xM F]s41x(IKݽ/_P@!8)es + N&FGSƄh{+CZzvF7Z-kx\[P8GK/^ l>.4 \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 b/tests/resources/push_src/.gitted/modules/submodule/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 new file mode 100644 index 000000000..4cc3f4dff --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 @@ -0,0 +1 @@ +x+)JMU044b040031QrutueXlmmAṃJ}G;UTWRQ`6Kǥ^/-*|W3Py`%E\&g|0{Ӎ1X \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 b/tests/resources/push_src/.gitted/modules/submodule/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 new file mode 100644 index 000000000..bf7b2bb68 Binary files /dev/null and b/tests/resources/push_src/.gitted/modules/submodule/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 differ diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 b/tests/resources/push_src/.gitted/modules/submodule/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 new file mode 100644 index 000000000..7f1cfb23c --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 @@ -0,0 +1,2 @@ +xM +0F]d2;XEȎ5R AE &n}ZA \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests/resources/push_src/.gitted/modules/submodule/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a new file mode 100644 index 000000000..a79612435 --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a @@ -0,0 +1,3 @@ +x[ +0E*fդ "W0-Ft݁pS[Yx^ +Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests/resources/push_src/.gitted/modules/submodule/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f new file mode 100644 index 000000000..f8588696b --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f @@ -0,0 +1,2 @@ +x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S + U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/modules/submodule/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 b/tests/resources/push_src/.gitted/modules/submodule/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 new file mode 100644 index 000000000..29c8e824d --- /dev/null +++ b/tests/resources/push_src/.gitted/modules/submodule/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 @@ -0,0 +1,3 @@ +xQ +!@sBQ" ٱ r{RȞyE + mH&Er7S!*u΄2>#\V8|Gt-ybhFU/J-|M}W+GK \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/objects/28/905c54ea45a4bed8d7b90f51bd8bd81eec8840 b/tests/resources/push_src/.gitted/objects/28/905c54ea45a4bed8d7b90f51bd8bd81eec8840 new file mode 100644 index 000000000..dc10f6831 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/28/905c54ea45a4bed8d7b90f51bd8bd81eec8840 differ diff --git a/tests/resources/push_src/.gitted/objects/36/6226fb970ac0caa9d3f55967ab01334a548f60 b/tests/resources/push_src/.gitted/objects/36/6226fb970ac0caa9d3f55967ab01334a548f60 new file mode 100644 index 000000000..45c4d9208 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/36/6226fb970ac0caa9d3f55967ab01334a548f60 differ diff --git a/tests/resources/push_src/.gitted/objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 b/tests/resources/push_src/.gitted/objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 new file mode 100644 index 000000000..0bc57f266 --- /dev/null +++ b/tests/resources/push_src/.gitted/objects/36/f79b2846017d3761e0a02d0bccd573e0f90c57 @@ -0,0 +1,2 @@ +x%] +0S͏B)} @bnf`f`>3(nibC0hQ6BMv2&-M0Q)+ tNsE*;}JϲN픹(th@#B˺C?TÅoyk7 \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/objects/5c/0bb3d1b9449d1cc69d7519fd05166f01840915 b/tests/resources/push_src/.gitted/objects/5c/0bb3d1b9449d1cc69d7519fd05166f01840915 new file mode 100644 index 000000000..883182138 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/5c/0bb3d1b9449d1cc69d7519fd05166f01840915 differ diff --git a/tests/resources/push_src/.gitted/objects/61/780798228d17af2d34fce4cfbdf35556832472 b/tests/resources/push_src/.gitted/objects/61/780798228d17af2d34fce4cfbdf35556832472 new file mode 100644 index 000000000..586bf17a4 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/61/780798228d17af2d34fce4cfbdf35556832472 differ diff --git a/tests/resources/push_src/.gitted/objects/64/fd55f9b6390202db5e5666fd1fb339089fba4d b/tests/resources/push_src/.gitted/objects/64/fd55f9b6390202db5e5666fd1fb339089fba4d new file mode 100644 index 000000000..bcaaa91c2 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/64/fd55f9b6390202db5e5666fd1fb339089fba4d differ diff --git a/tests/resources/push_src/.gitted/objects/78/981922613b2afb6025042ff6bd878ac1994e85 b/tests/resources/push_src/.gitted/objects/78/981922613b2afb6025042ff6bd878ac1994e85 new file mode 100644 index 000000000..e814d07b0 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/78/981922613b2afb6025042ff6bd878ac1994e85 differ diff --git a/tests/resources/push_src/.gitted/objects/80/5c54522e614f29f70d2413a0470247d8b424ac b/tests/resources/push_src/.gitted/objects/80/5c54522e614f29f70d2413a0470247d8b424ac new file mode 100644 index 000000000..552670c06 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/80/5c54522e614f29f70d2413a0470247d8b424ac differ diff --git a/tests/resources/push_src/.gitted/objects/95/1bbbb90e2259a4c8950db78946784fb53fcbce b/tests/resources/push_src/.gitted/objects/95/1bbbb90e2259a4c8950db78946784fb53fcbce new file mode 100644 index 000000000..596cd43de --- /dev/null +++ b/tests/resources/push_src/.gitted/objects/95/1bbbb90e2259a4c8950db78946784fb53fcbce @@ -0,0 +1,2 @@ +x[J0}*f2$Eim +\8:DfZ &65^,%lm١~;KJRXT蕄(!{¯DZqPqsPӈB\;EEgs`IeoE(YMFC9uu>|#?i.׻qD90FEENzܶ<\,\a_a.gd \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/objects/a7/8705c3b2725f931d3ee05348d83cc26700f247 b/tests/resources/push_src/.gitted/objects/a7/8705c3b2725f931d3ee05348d83cc26700f247 new file mode 100644 index 000000000..6ad835e86 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/a7/8705c3b2725f931d3ee05348d83cc26700f247 differ diff --git a/tests/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498 b/tests/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498 new file mode 100644 index 000000000..1e0bd3b05 --- /dev/null +++ b/tests/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498 @@ -0,0 +1,3 @@ +x5K +1D];1i"^'|d`d ooqQEͫ*Pݢ+ + 3$, }%Rw+s9y輨r`+ܦ2p/[mp~u8-Sr=,?Z+g \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/objects/b4/e1f2b375a64c1ccd40c5ff6aa8bc96839ba4fd b/tests/resources/push_src/.gitted/objects/b4/e1f2b375a64c1ccd40c5ff6aa8bc96839ba4fd new file mode 100644 index 000000000..4e650aaa1 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/b4/e1f2b375a64c1ccd40c5ff6aa8bc96839ba4fd differ diff --git a/tests/resources/push_src/.gitted/objects/c1/0409136a7a75e025fa502a1b2fd7b62b77d279 b/tests/resources/push_src/.gitted/objects/c1/0409136a7a75e025fa502a1b2fd7b62b77d279 new file mode 100644 index 000000000..fcb2b32f3 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/c1/0409136a7a75e025fa502a1b2fd7b62b77d279 differ diff --git a/tests/resources/push_src/.gitted/objects/cd/881f90f2933db2e4cc26b8c71fe6037ac7fe4c b/tests/resources/push_src/.gitted/objects/cd/881f90f2933db2e4cc26b8c71fe6037ac7fe4c new file mode 100644 index 000000000..ad4272638 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/cd/881f90f2933db2e4cc26b8c71fe6037ac7fe4c differ diff --git a/tests/resources/push_src/.gitted/objects/d9/b63a88223d8367516f50bd131a5f7349b7f3e4 b/tests/resources/push_src/.gitted/objects/d9/b63a88223d8367516f50bd131a5f7349b7f3e4 new file mode 100644 index 000000000..b471e2155 --- /dev/null +++ b/tests/resources/push_src/.gitted/objects/d9/b63a88223d8367516f50bd131a5f7349b7f3e4 @@ -0,0 +1,2 @@ +xA +0E]sd$ "xi2ՂmzwSErgj ![͎%wbY(zC/G\tw({r$C`Y[=DCu&V8!s=]8ޛT#|;ltWhfM}UQDM \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/objects/dc/ab83249f6f9d1ed735d651352a80519339b591 b/tests/resources/push_src/.gitted/objects/dc/ab83249f6f9d1ed735d651352a80519339b591 new file mode 100644 index 000000000..9f6b1502f Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/dc/ab83249f6f9d1ed735d651352a80519339b591 differ diff --git a/tests/resources/push_src/.gitted/objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 b/tests/resources/push_src/.gitted/objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 new file mode 100644 index 000000000..b7b81d5e3 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/ee/a4f2705eeec2db3813f2430829afce99cd00b5 differ diff --git a/tests/resources/push_src/.gitted/objects/f7/8a3106c85fb549c65198b2a2086276c6174928 b/tests/resources/push_src/.gitted/objects/f7/8a3106c85fb549c65198b2a2086276c6174928 new file mode 100644 index 000000000..b9813576d Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/f7/8a3106c85fb549c65198b2a2086276c6174928 differ diff --git a/tests/resources/push_src/.gitted/objects/f8/f7aefc2900a3d737cea9eee45729fd55761e1a b/tests/resources/push_src/.gitted/objects/f8/f7aefc2900a3d737cea9eee45729fd55761e1a new file mode 100644 index 000000000..888354fc2 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/f8/f7aefc2900a3d737cea9eee45729fd55761e1a differ diff --git a/tests/resources/push_src/.gitted/objects/fa/38b91f199934685819bea316186d8b008c52a2 b/tests/resources/push_src/.gitted/objects/fa/38b91f199934685819bea316186d8b008c52a2 new file mode 100644 index 000000000..13d9bca20 --- /dev/null +++ b/tests/resources/push_src/.gitted/objects/fa/38b91f199934685819bea316186d8b008c52a2 @@ -0,0 +1,2 @@ +xJ15>urrneo {f[)_DmIi7 +7Ĩ8ꔌ.n܃W)_T;x,(li[D\K墓XΓP?>W~|_Wؤxs6IcJNP}~ -מ/󄳭G X \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/objects/ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e b/tests/resources/push_src/.gitted/objects/ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e new file mode 100644 index 000000000..10f25eb7c --- /dev/null +++ b/tests/resources/push_src/.gitted/objects/ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e @@ -0,0 +1,4 @@ +x5M +1 `=E4NA H ooq{/G@5=$+SO) nx[@4y +h1ڄvmSyz' +Wk-ziQc<ޢfS~pv+ \ No newline at end of file diff --git a/tests/resources/push_src/.gitted/objects/ff/fe95c7fd0a37fa2ed702f8f93b56b2196b3925 b/tests/resources/push_src/.gitted/objects/ff/fe95c7fd0a37fa2ed702f8f93b56b2196b3925 new file mode 100644 index 000000000..1cdc048c0 Binary files /dev/null and b/tests/resources/push_src/.gitted/objects/ff/fe95c7fd0a37fa2ed702f8f93b56b2196b3925 differ diff --git a/tests/resources/push_src/.gitted/objects/pack/dummy b/tests/resources/push_src/.gitted/objects/pack/dummy new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/push_src/.gitted/refs/heads/b1 b/tests/resources/push_src/.gitted/refs/heads/b1 new file mode 100644 index 000000000..afadf9d26 --- /dev/null +++ b/tests/resources/push_src/.gitted/refs/heads/b1 @@ -0,0 +1 @@ +a78705c3b2725f931d3ee05348d83cc26700f247 diff --git a/tests/resources/push_src/.gitted/refs/heads/b2 b/tests/resources/push_src/.gitted/refs/heads/b2 new file mode 100644 index 000000000..afadf9d26 --- /dev/null +++ b/tests/resources/push_src/.gitted/refs/heads/b2 @@ -0,0 +1 @@ +a78705c3b2725f931d3ee05348d83cc26700f247 diff --git a/tests/resources/push_src/.gitted/refs/heads/b3 b/tests/resources/push_src/.gitted/refs/heads/b3 new file mode 100644 index 000000000..3056bb436 --- /dev/null +++ b/tests/resources/push_src/.gitted/refs/heads/b3 @@ -0,0 +1 @@ +d9b63a88223d8367516f50bd131a5f7349b7f3e4 diff --git a/tests/resources/push_src/.gitted/refs/heads/b4 b/tests/resources/push_src/.gitted/refs/heads/b4 new file mode 100644 index 000000000..efed6f064 --- /dev/null +++ b/tests/resources/push_src/.gitted/refs/heads/b4 @@ -0,0 +1 @@ +27b7ce66243eb1403862d05f958c002312df173d diff --git a/tests/resources/push_src/.gitted/refs/heads/b5 b/tests/resources/push_src/.gitted/refs/heads/b5 new file mode 100644 index 000000000..cf313ad05 --- /dev/null +++ b/tests/resources/push_src/.gitted/refs/heads/b5 @@ -0,0 +1 @@ +fa38b91f199934685819bea316186d8b008c52a2 diff --git a/tests/resources/push_src/.gitted/refs/heads/b6 b/tests/resources/push_src/.gitted/refs/heads/b6 new file mode 100644 index 000000000..711e466ae --- /dev/null +++ b/tests/resources/push_src/.gitted/refs/heads/b6 @@ -0,0 +1 @@ +951bbbb90e2259a4c8950db78946784fb53fcbce diff --git a/tests/resources/push_src/.gitted/refs/tags/tag-blob b/tests/resources/push_src/.gitted/refs/tags/tag-blob new file mode 100644 index 000000000..abfebf22e --- /dev/null +++ b/tests/resources/push_src/.gitted/refs/tags/tag-blob @@ -0,0 +1 @@ +b483ae7ba66decee9aee971f501221dea84b1498 diff --git a/tests/resources/push_src/.gitted/refs/tags/tag-commit b/tests/resources/push_src/.gitted/refs/tags/tag-commit new file mode 100644 index 000000000..c023b8452 --- /dev/null +++ b/tests/resources/push_src/.gitted/refs/tags/tag-commit @@ -0,0 +1 @@ +805c54522e614f29f70d2413a0470247d8b424ac diff --git a/tests/resources/push_src/.gitted/refs/tags/tag-commit-two b/tests/resources/push_src/.gitted/refs/tags/tag-commit-two new file mode 100644 index 000000000..abb365080 --- /dev/null +++ b/tests/resources/push_src/.gitted/refs/tags/tag-commit-two @@ -0,0 +1 @@ +36f79b2846017d3761e0a02d0bccd573e0f90c57 diff --git a/tests/resources/push_src/.gitted/refs/tags/tag-lightweight b/tests/resources/push_src/.gitted/refs/tags/tag-lightweight new file mode 100644 index 000000000..711e466ae --- /dev/null +++ b/tests/resources/push_src/.gitted/refs/tags/tag-lightweight @@ -0,0 +1 @@ +951bbbb90e2259a4c8950db78946784fb53fcbce diff --git a/tests/resources/push_src/.gitted/refs/tags/tag-tag b/tests/resources/push_src/.gitted/refs/tags/tag-tag new file mode 100644 index 000000000..d6cd74804 --- /dev/null +++ b/tests/resources/push_src/.gitted/refs/tags/tag-tag @@ -0,0 +1 @@ +eea4f2705eeec2db3813f2430829afce99cd00b5 diff --git a/tests/resources/push_src/.gitted/refs/tags/tag-tree b/tests/resources/push_src/.gitted/refs/tags/tag-tree new file mode 100644 index 000000000..7a530d381 --- /dev/null +++ b/tests/resources/push_src/.gitted/refs/tags/tag-tree @@ -0,0 +1 @@ +ff83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e diff --git a/tests/resources/push_src/a.txt b/tests/resources/push_src/a.txt new file mode 100644 index 000000000..f7eac1c51 --- /dev/null +++ b/tests/resources/push_src/a.txt @@ -0,0 +1,2 @@ +a +edit diff --git a/tests/resources/push_src/fold/b.txt b/tests/resources/push_src/fold/b.txt new file mode 100644 index 000000000..617807982 --- /dev/null +++ b/tests/resources/push_src/fold/b.txt @@ -0,0 +1 @@ +b diff --git a/tests/resources/push_src/foldb.txt b/tests/resources/push_src/foldb.txt new file mode 100644 index 000000000..5b38718be --- /dev/null +++ b/tests/resources/push_src/foldb.txt @@ -0,0 +1 @@ +edit diff --git a/tests/resources/push_src/gitmodules b/tests/resources/push_src/gitmodules new file mode 100644 index 000000000..f1734dfc1 --- /dev/null +++ b/tests/resources/push_src/gitmodules @@ -0,0 +1,3 @@ +[submodule "submodule"] + path = submodule + url = ../testrepo.git diff --git a/tests/resources/push_src/submodule/.gitted b/tests/resources/push_src/submodule/.gitted new file mode 100644 index 000000000..3ffcf960a --- /dev/null +++ b/tests/resources/push_src/submodule/.gitted @@ -0,0 +1 @@ +gitdir: ../.git/modules/submodule diff --git a/tests/resources/push_src/submodule/README b/tests/resources/push_src/submodule/README new file mode 100644 index 000000000..ca8c64728 --- /dev/null +++ b/tests/resources/push_src/submodule/README @@ -0,0 +1 @@ +hey there diff --git a/tests/resources/push_src/submodule/branch_file.txt b/tests/resources/push_src/submodule/branch_file.txt new file mode 100644 index 000000000..a26902575 --- /dev/null +++ b/tests/resources/push_src/submodule/branch_file.txt @@ -0,0 +1,2 @@ +hi +bye! diff --git a/tests/resources/push_src/submodule/new.txt b/tests/resources/push_src/submodule/new.txt new file mode 100644 index 000000000..8e0884e36 --- /dev/null +++ b/tests/resources/push_src/submodule/new.txt @@ -0,0 +1 @@ +my new file diff --git a/tests/resources/renames/.gitted/HEAD b/tests/resources/renames/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/renames/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/renames/.gitted/config b/tests/resources/renames/.gitted/config new file mode 100644 index 000000000..bb4d11c1f --- /dev/null +++ b/tests/resources/renames/.gitted/config @@ -0,0 +1,7 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true + precomposeunicode = false diff --git a/tests/resources/renames/.gitted/description b/tests/resources/renames/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/renames/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/renames/.gitted/index b/tests/resources/renames/.gitted/index new file mode 100644 index 000000000..72363c0f5 Binary files /dev/null and b/tests/resources/renames/.gitted/index differ diff --git a/tests/resources/renames/.gitted/info/exclude b/tests/resources/renames/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/renames/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/renames/.gitted/logs/HEAD b/tests/resources/renames/.gitted/logs/HEAD new file mode 100644 index 000000000..e69792263 --- /dev/null +++ b/tests/resources/renames/.gitted/logs/HEAD @@ -0,0 +1,4 @@ +0000000000000000000000000000000000000000 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 Russell Belfer 1351024687 -0700 commit (initial): Initial commit +31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 2bc7f351d20b53f1c72c16c4b036e491c478c49a Russell Belfer 1351024817 -0700 commit: copy and rename with no change +2bc7f351d20b53f1c72c16c4b036e491c478c49a 1c068dee5790ef1580cfc4cd670915b48d790084 Russell Belfer 1361485758 -0800 commit: rewrites, copies with changes, etc. +1c068dee5790ef1580cfc4cd670915b48d790084 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 Russell Belfer 1361486360 -0800 commit: more renames and smallish modifications diff --git a/tests/resources/renames/.gitted/logs/refs/heads/master b/tests/resources/renames/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..e69792263 --- /dev/null +++ b/tests/resources/renames/.gitted/logs/refs/heads/master @@ -0,0 +1,4 @@ +0000000000000000000000000000000000000000 31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 Russell Belfer 1351024687 -0700 commit (initial): Initial commit +31e47d8c1fa36d7f8d537b96158e3f024de0a9f2 2bc7f351d20b53f1c72c16c4b036e491c478c49a Russell Belfer 1351024817 -0700 commit: copy and rename with no change +2bc7f351d20b53f1c72c16c4b036e491c478c49a 1c068dee5790ef1580cfc4cd670915b48d790084 Russell Belfer 1361485758 -0800 commit: rewrites, copies with changes, etc. +1c068dee5790ef1580cfc4cd670915b48d790084 19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 Russell Belfer 1361486360 -0800 commit: more renames and smallish modifications diff --git a/tests/resources/renames/.gitted/objects/03/da7ad872536bd448da8d88eb7165338bf923a7 b/tests/resources/renames/.gitted/objects/03/da7ad872536bd448da8d88eb7165338bf923a7 new file mode 100644 index 000000000..2ee86444d Binary files /dev/null and b/tests/resources/renames/.gitted/objects/03/da7ad872536bd448da8d88eb7165338bf923a7 differ diff --git a/tests/resources/renames/.gitted/objects/17/58bdd7c16a72ff7c17d8de0c957ced3ccad645 b/tests/resources/renames/.gitted/objects/17/58bdd7c16a72ff7c17d8de0c957ced3ccad645 new file mode 100644 index 000000000..01801ed11 --- /dev/null +++ b/tests/resources/renames/.gitted/objects/17/58bdd7c16a72ff7c17d8de0c957ced3ccad645 @@ -0,0 +1,5 @@ +xEͱ @QbWq H_&{]yYX`='흶=ZohzF + + + +MhBЄ&4 MhB3ьf4hF3юKx \ No newline at end of file diff --git a/tests/resources/renames/.gitted/objects/19/dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 b/tests/resources/renames/.gitted/objects/19/dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 new file mode 100644 index 000000000..4be4c6952 --- /dev/null +++ b/tests/resources/renames/.gitted/objects/19/dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 @@ -0,0 +1 @@ +xM!Ei@3ސc,\X K {Nrbo,xzYC<h[&?=fcvyCWm 䮔~*D \ No newline at end of file diff --git a/tests/resources/renames/.gitted/objects/5e/26abc56a5a84d89790f45416648899cbe13109 b/tests/resources/renames/.gitted/objects/5e/26abc56a5a84d89790f45416648899cbe13109 new file mode 100644 index 000000000..2acd3d583 Binary files /dev/null and b/tests/resources/renames/.gitted/objects/5e/26abc56a5a84d89790f45416648899cbe13109 differ diff --git a/tests/resources/renames/.gitted/objects/61/8c6f2f8740bd6049b2fb9eb93fc15726462745 b/tests/resources/renames/.gitted/objects/61/8c6f2f8740bd6049b2fb9eb93fc15726462745 new file mode 100644 index 000000000..24eac54c5 Binary files /dev/null and b/tests/resources/renames/.gitted/objects/61/8c6f2f8740bd6049b2fb9eb93fc15726462745 differ diff --git a/tests/resources/renames/.gitted/objects/66/311f5cfbe7836c27510a3ba2f43e282e2c8bba b/tests/resources/renames/.gitted/objects/66/311f5cfbe7836c27510a3ba2f43e282e2c8bba new file mode 100644 index 000000000..5ee28a76a Binary files /dev/null and b/tests/resources/renames/.gitted/objects/66/311f5cfbe7836c27510a3ba2f43e282e2c8bba differ diff --git a/tests/resources/renames/.gitted/objects/93/f538c45a57a87eb4c1e86f91c6ee41d66c7ba7 b/tests/resources/renames/.gitted/objects/93/f538c45a57a87eb4c1e86f91c6ee41d66c7ba7 new file mode 100644 index 000000000..39105f94d Binary files /dev/null and b/tests/resources/renames/.gitted/objects/93/f538c45a57a87eb4c1e86f91c6ee41d66c7ba7 differ diff --git a/tests/resources/renames/.gitted/objects/9a/69d960ae94b060f56c2a8702545e2bb1abb935 b/tests/resources/renames/.gitted/objects/9a/69d960ae94b060f56c2a8702545e2bb1abb935 new file mode 100644 index 000000000..f75178c59 Binary files /dev/null and b/tests/resources/renames/.gitted/objects/9a/69d960ae94b060f56c2a8702545e2bb1abb935 differ diff --git a/tests/resources/renames/.gitted/objects/ad/0a8e55a104ac54a8a29ed4b84b49e76837a113 b/tests/resources/renames/.gitted/objects/ad/0a8e55a104ac54a8a29ed4b84b49e76837a113 new file mode 100644 index 000000000..440b7bec3 Binary files /dev/null and b/tests/resources/renames/.gitted/objects/ad/0a8e55a104ac54a8a29ed4b84b49e76837a113 differ diff --git a/tests/resources/renames/.gitted/objects/b9/25b224cc91f897001a9993fbce169fdaa8858f b/tests/resources/renames/.gitted/objects/b9/25b224cc91f897001a9993fbce169fdaa8858f new file mode 100644 index 000000000..90e107fa2 Binary files /dev/null and b/tests/resources/renames/.gitted/objects/b9/25b224cc91f897001a9993fbce169fdaa8858f differ diff --git a/tests/resources/renames/.gitted/objects/d7/9b202de198fa61b02424b9e25e840dc75e1323 b/tests/resources/renames/.gitted/objects/d7/9b202de198fa61b02424b9e25e840dc75e1323 new file mode 100644 index 000000000..daa2b3997 Binary files /dev/null and b/tests/resources/renames/.gitted/objects/d7/9b202de198fa61b02424b9e25e840dc75e1323 differ diff --git a/tests/resources/renames/.gitted/objects/ea/c43f5195a2cee53b7458d8dad16aedde10711b b/tests/resources/renames/.gitted/objects/ea/c43f5195a2cee53b7458d8dad16aedde10711b new file mode 100644 index 000000000..2fb025080 Binary files /dev/null and b/tests/resources/renames/.gitted/objects/ea/c43f5195a2cee53b7458d8dad16aedde10711b differ diff --git a/tests/resources/renames/.gitted/objects/ea/f4a3e3bfe68585e90cada20736ace491cd100b b/tests/resources/renames/.gitted/objects/ea/f4a3e3bfe68585e90cada20736ace491cd100b new file mode 100644 index 000000000..f72df8d82 --- /dev/null +++ b/tests/resources/renames/.gitted/objects/ea/f4a3e3bfe68585e90cada20736ace491cd100b @@ -0,0 +1,5 @@ +x}R@<_QT.A[ +{t2Cez%L'!aj!x{'+;$)Ξ#yǘ#q#hc QDXmR|aD*O+^ZI~i>3a!,R!-EaI>yo*4戁Rf m&eIA*!;dݬ +Ho +OUDyTVHpwqH7Ʒ.ts6{Z+X\)C5Q9 +%t*&&v;|'4 Du[7he!NK*"C-=`#؎$Ee2T|@NBsslW|/0¬aȥJNv)-ڡiۤ3bbO:uWMNX7T \ No newline at end of file diff --git a/tests/resources/renames/.gitted/objects/f9/0d4fc20ecddf21eebe6a37e9225d244339d2b5 b/tests/resources/renames/.gitted/objects/f9/0d4fc20ecddf21eebe6a37e9225d244339d2b5 new file mode 100644 index 000000000..f6d933be9 Binary files /dev/null and b/tests/resources/renames/.gitted/objects/f9/0d4fc20ecddf21eebe6a37e9225d244339d2b5 differ diff --git a/tests/resources/renames/.gitted/refs/heads/master b/tests/resources/renames/.gitted/refs/heads/master new file mode 100644 index 000000000..642c3198d --- /dev/null +++ b/tests/resources/renames/.gitted/refs/heads/master @@ -0,0 +1 @@ +19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13 diff --git a/tests/resources/renames/.gitted/refs/heads/renames_similar b/tests/resources/renames/.gitted/refs/heads/renames_similar new file mode 100644 index 000000000..8ffb6d94b --- /dev/null +++ b/tests/resources/renames/.gitted/refs/heads/renames_similar @@ -0,0 +1 @@ +444a76ed3e45b183753f49376af30da8c3fe276a diff --git a/tests/resources/renames/.gitted/refs/heads/renames_similar_two b/tests/resources/renames/.gitted/refs/heads/renames_similar_two new file mode 100644 index 000000000..4ee5d04e1 --- /dev/null +++ b/tests/resources/renames/.gitted/refs/heads/renames_similar_two @@ -0,0 +1 @@ +50e90273af7d826ff0a95865bcd3ba8412c447d9 diff --git a/tests/resources/renames/ikeepsix.txt b/tests/resources/renames/ikeepsix.txt new file mode 100644 index 000000000..eaf4a3e3b --- /dev/null +++ b/tests/resources/renames/ikeepsix.txt @@ -0,0 +1,27 @@ +I Keep Six Honest Serving-Men +============================= + +She sends'em abroad on her own affairs, + From the second she opens her eyes— +One million Hows, two million Wheres, +And seven million Whys! + +I let them rest from nine till five, + For I am busy then, +As well as breakfast, lunch, and tea, + For they are hungry men. +But different folk have different views; +I know a person small— +She keeps ten million serving-men, +Who get no rest at all! + + -- Rudyard Kipling + +I KEEP six honest serving-men + (They taught me all I knew); +Their names are What and Why and When + And How and Where and Who. +I send them over land and sea, + I send them east and west; +But after they have worked for me, + I give them all a rest. diff --git a/tests/resources/renames/sixserving.txt b/tests/resources/renames/sixserving.txt new file mode 100644 index 000000000..f90d4fc20 --- /dev/null +++ b/tests/resources/renames/sixserving.txt @@ -0,0 +1,25 @@ +I KEEP six honest serving-men + (They taught me all I knew); +Their names are What and Why and When + And How and Where and Who. +I send them over land and sea, + I send them east and west; +But after they have worked for me, + I give them all a rest. + +I let them rest from nine till five, + For I am busy then, +As well as breakfast, lunch, and tea, + For they are hungry men. +But different folk have different views; +I know a person small— +She keeps ten million serving-men, +Who get no rest at all! + +She sends'em abroad on her own affairs, + From the second she opens her eyes— +One million Hows, two million Wheres, +And seven million Whys! + + -- Rudyard Kipling + diff --git a/tests/resources/renames/songof7cities.txt b/tests/resources/renames/songof7cities.txt new file mode 100644 index 000000000..4210ffd5c --- /dev/null +++ b/tests/resources/renames/songof7cities.txt @@ -0,0 +1,49 @@ +The Song of Seven Cities +------------------------ + +I WAS Lord of Cities very sumptuously builded. +Seven roaring Cities paid me tribute from afar. +Ivory their outposts were--the guardrooms of them gilded, +And garrisoned with Amazons invincible in war. + +All the world went softly when it walked before my Cities-- +Neither King nor Army vexed my peoples at their toil, +Never horse nor chariot irked or overbore my Cities, +Never Mob nor Ruler questioned whence they drew their spoil. + +Banded, mailed and arrogant from sunrise unto sunset; +Singing while they sacked it, they possessed the land at large. +Yet when men would rob them, they resisted, they made onset +And pierced the smoke of battle with a thousand-sabred charge. + +So they warred and trafficked only yesterday, my Cities. +To-day there is no mark or mound of where my Cities stood. +For the River rose at midnight and it washed away my Cities. +They are evened with Atlantis and the towns before the Flood. + +Rain on rain-gorged channels raised the water-levels round them, +Freshet backed on freshet swelled and swept their world from sight, +Till the emboldened floods linked arms and, flashing forward, drowned them-- +Drowned my Seven Cities and their peoples in one night! + +Low among the alders lie their derelict foundations, +The beams wherein they trusted and the plinths whereon they built-- +My rulers and their treasure and their unborn populations, +Dead, destroyed, aborted, and defiled with mud and silt! + +The Daughters of the Palace whom they cherished in my Cities, +My silver-tongued Princesses, and the promise of their May-- +Their bridegrooms of the June-tide--all have perished in my Cities, +With the harsh envenomed virgins that can neither love nor play. + +I was Lord of Cities--I will build anew my Cities, +Seven, set on rocks, above the wrath of any flood. +Nor will I rest from search till I have filled anew my Cities +With peoples undefeated of the dark, enduring blood. + +To the sound of trumpets shall their seed restore my Cities +Wealthy and well-weaponed, that once more may I behold +All the world go softly when it walks before my Cities, +And the horses and the chariots fleeing from them as of old! + + -- Rudyard Kipling diff --git a/tests/resources/renames/untimely.txt b/tests/resources/renames/untimely.txt new file mode 100644 index 000000000..9a69d960a --- /dev/null +++ b/tests/resources/renames/untimely.txt @@ -0,0 +1,24 @@ +Untimely +======== + +Nothing in life has been made by man for man's using +But it was shown long since to man in ages +Lost as the name of the maker of it, +Who received oppression and shame for his wages-- +Hate, avoidance, and scorn in his daily dealings-- +Until he perished, wholly confounded + +More to be pitied than he are the wise +Souls which foresaw the evil of loosing +Knowledge or Art before time, and aborted +Noble devices and deep-wrought healings, +Lest offense should arise. + +Heaven delivers on earth the Hour that cannot be + thwarted, +Neither advanced, at the price of a world nor a soul, + and its Prophet +Comes through the blood of the vanguards who + dreamed--too soon--it had sounded. + + -- Rudyard Kipling diff --git a/tests/resources/shallow.git/HEAD b/tests/resources/shallow.git/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/shallow.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/shallow.git/config b/tests/resources/shallow.git/config new file mode 100644 index 000000000..a88b74b69 --- /dev/null +++ b/tests/resources/shallow.git/config @@ -0,0 +1,8 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true + ignorecase = true + precomposeunicode = false +[remote "origin"] + url = file://testrepo.git diff --git a/tests/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.idx b/tests/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.idx new file mode 100644 index 000000000..bfc7d24ff Binary files /dev/null and b/tests/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.idx differ diff --git a/tests/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.pack b/tests/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.pack new file mode 100644 index 000000000..ccc6932fc Binary files /dev/null and b/tests/resources/shallow.git/objects/pack/pack-706e49b161700946489570d96153e5be4dc31ad4.pack differ diff --git a/tests/resources/shallow.git/packed-refs b/tests/resources/shallow.git/packed-refs new file mode 100644 index 000000000..97eed743b --- /dev/null +++ b/tests/resources/shallow.git/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +a65fedf39aefe402d3bb6e24df4d4f5fe4547750 refs/heads/master diff --git a/tests/resources/shallow.git/refs/.gitkeep b/tests/resources/shallow.git/refs/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/shallow.git/shallow b/tests/resources/shallow.git/shallow new file mode 100644 index 000000000..9536ad89c --- /dev/null +++ b/tests/resources/shallow.git/shallow @@ -0,0 +1 @@ +be3563ae3f795b2b4353bcce3a527ad0a4f7f644 diff --git a/tests/resources/short_tag.git/HEAD b/tests/resources/short_tag.git/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/short_tag.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/short_tag.git/config b/tests/resources/short_tag.git/config new file mode 100644 index 000000000..a4ef456cb --- /dev/null +++ b/tests/resources/short_tag.git/config @@ -0,0 +1,5 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true + logallrefupdates = true diff --git a/tests/resources/short_tag.git/index b/tests/resources/short_tag.git/index new file mode 100644 index 000000000..87fef7847 Binary files /dev/null and b/tests/resources/short_tag.git/index differ diff --git a/tests/resources/short_tag.git/objects/4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c b/tests/resources/short_tag.git/objects/4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c new file mode 100644 index 000000000..aeb4e4b0b Binary files /dev/null and b/tests/resources/short_tag.git/objects/4a/5ed60bafcf4638b7c8356bd4ce1916bfede93c differ diff --git a/tests/resources/short_tag.git/objects/4d/5fcadc293a348e88f777dc0920f11e7d71441c b/tests/resources/short_tag.git/objects/4d/5fcadc293a348e88f777dc0920f11e7d71441c new file mode 100644 index 000000000..806ce71a5 Binary files /dev/null and b/tests/resources/short_tag.git/objects/4d/5fcadc293a348e88f777dc0920f11e7d71441c differ diff --git a/tests/resources/short_tag.git/objects/5d/a7760512a953e3c7c4e47e4392c7a4338fb729 b/tests/resources/short_tag.git/objects/5d/a7760512a953e3c7c4e47e4392c7a4338fb729 new file mode 100644 index 000000000..1192707c9 --- /dev/null +++ b/tests/resources/short_tag.git/objects/5d/a7760512a953e3c7c4e47e4392c7a4338fb729 @@ -0,0 +1 @@ +xM0@aלb. i%1ƍpc@--6&B E+pVСSƆd/m(RJ% R^vʩ,Giǖ <Ӵ3\ncinRSg u1 \ No newline at end of file diff --git a/tests/resources/short_tag.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/tests/resources/short_tag.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 new file mode 100644 index 000000000..711223894 Binary files /dev/null and b/tests/resources/short_tag.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 differ diff --git a/tests/resources/short_tag.git/packed-refs b/tests/resources/short_tag.git/packed-refs new file mode 100644 index 000000000..ca5197e3c --- /dev/null +++ b/tests/resources/short_tag.git/packed-refs @@ -0,0 +1 @@ +5da7760512a953e3c7c4e47e4392c7a4338fb729 refs/tags/no_description diff --git a/tests/resources/short_tag.git/refs/heads/master b/tests/resources/short_tag.git/refs/heads/master new file mode 100644 index 000000000..fcefd1ef0 --- /dev/null +++ b/tests/resources/short_tag.git/refs/heads/master @@ -0,0 +1 @@ +4a5ed60bafcf4638b7c8356bd4ce1916bfede93c diff --git a/tests/resources/status/.gitted/COMMIT_EDITMSG b/tests/resources/status/.gitted/COMMIT_EDITMSG new file mode 100644 index 000000000..1a25cd4a6 --- /dev/null +++ b/tests/resources/status/.gitted/COMMIT_EDITMSG @@ -0,0 +1 @@ +Add a file which name should appear before the "subdir/" folder while being dealt with by the treewalker diff --git a/tests/resources/status/.gitted/HEAD b/tests/resources/status/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/status/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/status/.gitted/ORIG_HEAD b/tests/resources/status/.gitted/ORIG_HEAD new file mode 100644 index 000000000..b46871fd6 --- /dev/null +++ b/tests/resources/status/.gitted/ORIG_HEAD @@ -0,0 +1 @@ +735b6a258cd196a8f7c9428419b02c1dca93fd75 diff --git a/tests/resources/status/.gitted/config b/tests/resources/status/.gitted/config new file mode 100644 index 000000000..af107929f --- /dev/null +++ b/tests/resources/status/.gitted/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true diff --git a/tests/resources/status/.gitted/description b/tests/resources/status/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/status/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/status/.gitted/index b/tests/resources/status/.gitted/index new file mode 100644 index 000000000..2af99a183 Binary files /dev/null and b/tests/resources/status/.gitted/index differ diff --git a/tests/resources/status/.gitted/info/exclude b/tests/resources/status/.gitted/info/exclude new file mode 100644 index 000000000..0c4042a6a --- /dev/null +++ b/tests/resources/status/.gitted/info/exclude @@ -0,0 +1,8 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ +ignored* + diff --git a/tests/resources/status/.gitted/logs/HEAD b/tests/resources/status/.gitted/logs/HEAD new file mode 100644 index 000000000..7b95b3cf1 --- /dev/null +++ b/tests/resources/status/.gitted/logs/HEAD @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 0017bd4ab1ec30440b17bae1680cff124ab5f1f6 Jason Penny 1308050070 -0400 commit (initial): initial +0017bd4ab1ec30440b17bae1680cff124ab5f1f6 735b6a258cd196a8f7c9428419b02c1dca93fd75 Jason Penny 1308954538 -0400 commit: add subdir +735b6a258cd196a8f7c9428419b02c1dca93fd75 26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f nulltoken 1319911544 +0200 commit: Add a file which name should appear before the "subdir/" folder while being dealt with by the treewalker diff --git a/tests/resources/status/.gitted/logs/refs/heads/master b/tests/resources/status/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..7b95b3cf1 --- /dev/null +++ b/tests/resources/status/.gitted/logs/refs/heads/master @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 0017bd4ab1ec30440b17bae1680cff124ab5f1f6 Jason Penny 1308050070 -0400 commit (initial): initial +0017bd4ab1ec30440b17bae1680cff124ab5f1f6 735b6a258cd196a8f7c9428419b02c1dca93fd75 Jason Penny 1308954538 -0400 commit: add subdir +735b6a258cd196a8f7c9428419b02c1dca93fd75 26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f nulltoken 1319911544 +0200 commit: Add a file which name should appear before the "subdir/" folder while being dealt with by the treewalker diff --git a/tests/resources/status/.gitted/objects/00/17bd4ab1ec30440b17bae1680cff124ab5f1f6 b/tests/resources/status/.gitted/objects/00/17bd4ab1ec30440b17bae1680cff124ab5f1f6 new file mode 100644 index 000000000..b256d95a3 --- /dev/null +++ b/tests/resources/status/.gitted/objects/00/17bd4ab1ec30440b17bae1680cff124ab5f1f6 @@ -0,0 +1,2 @@ +xA E]sfh)1] +#STWpK^~9ܡ-"C'؅)Fvbv "wEk{nRί6#sO pD663WxV?9 \ No newline at end of file diff --git a/tests/resources/status/.gitted/objects/06/1d42a44cacde5726057b67558821d95db96f19 b/tests/resources/status/.gitted/objects/06/1d42a44cacde5726057b67558821d95db96f19 new file mode 100644 index 000000000..82e02cb0e Binary files /dev/null and b/tests/resources/status/.gitted/objects/06/1d42a44cacde5726057b67558821d95db96f19 differ diff --git a/tests/resources/status/.gitted/objects/18/88c805345ba265b0ee9449b8877b6064592058 b/tests/resources/status/.gitted/objects/18/88c805345ba265b0ee9449b8877b6064592058 new file mode 100644 index 000000000..e3cad2f02 Binary files /dev/null and b/tests/resources/status/.gitted/objects/18/88c805345ba265b0ee9449b8877b6064592058 differ diff --git a/tests/resources/status/.gitted/objects/19/d9cc8584ac2c7dcf57d2680375e80f099dc481 b/tests/resources/status/.gitted/objects/19/d9cc8584ac2c7dcf57d2680375e80f099dc481 new file mode 100644 index 000000000..2d5e711b9 Binary files /dev/null and b/tests/resources/status/.gitted/objects/19/d9cc8584ac2c7dcf57d2680375e80f099dc481 differ diff --git a/tests/resources/status/.gitted/objects/26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f b/tests/resources/status/.gitted/objects/26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f new file mode 100644 index 000000000..f7dddc4ff --- /dev/null +++ b/tests/resources/status/.gitted/objects/26/a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f @@ -0,0 +1,2 @@ +xMn )V (̀BD޾LЍRȷވ@,9̜tNj6f`M6Z;h Zp ڙY,37/;42x&gϟۉIm|j \ No newline at end of file diff --git a/tests/resources/status/.gitted/objects/32/504b727382542f9f089e24fddac5e78533e96c b/tests/resources/status/.gitted/objects/32/504b727382542f9f089e24fddac5e78533e96c new file mode 100644 index 000000000..7fca67be8 Binary files /dev/null and b/tests/resources/status/.gitted/objects/32/504b727382542f9f089e24fddac5e78533e96c differ diff --git a/tests/resources/status/.gitted/objects/37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0 b/tests/resources/status/.gitted/objects/37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0 new file mode 100644 index 000000000..b75481b51 Binary files /dev/null and b/tests/resources/status/.gitted/objects/37/fcb02ccc1a85d1941e7f106d52dc3702dcf0d0 differ diff --git a/tests/resources/status/.gitted/objects/45/2e4244b5d083ddf0460acf1ecc74db9dcfa11a b/tests/resources/status/.gitted/objects/45/2e4244b5d083ddf0460acf1ecc74db9dcfa11a new file mode 100644 index 000000000..5b47461e9 Binary files /dev/null and b/tests/resources/status/.gitted/objects/45/2e4244b5d083ddf0460acf1ecc74db9dcfa11a differ diff --git a/tests/resources/status/.gitted/objects/52/9a16e8e762d4acb7b9636ff540a00831f9155a b/tests/resources/status/.gitted/objects/52/9a16e8e762d4acb7b9636ff540a00831f9155a new file mode 100644 index 000000000..615009ad0 Binary files /dev/null and b/tests/resources/status/.gitted/objects/52/9a16e8e762d4acb7b9636ff540a00831f9155a differ diff --git a/tests/resources/status/.gitted/objects/53/ace0d1cc1145a5f4fe4f78a186a60263190733 b/tests/resources/status/.gitted/objects/53/ace0d1cc1145a5f4fe4f78a186a60263190733 new file mode 100644 index 000000000..cdb7e961a Binary files /dev/null and b/tests/resources/status/.gitted/objects/53/ace0d1cc1145a5f4fe4f78a186a60263190733 differ diff --git a/tests/resources/status/.gitted/objects/54/52d32f1dd538eb0405e8a83cc185f79e25e80f b/tests/resources/status/.gitted/objects/54/52d32f1dd538eb0405e8a83cc185f79e25e80f new file mode 100644 index 000000000..a72dff646 Binary files /dev/null and b/tests/resources/status/.gitted/objects/54/52d32f1dd538eb0405e8a83cc185f79e25e80f differ diff --git a/tests/resources/status/.gitted/objects/55/d316c9ba708999f1918e9677d01dfcae69c6b9 b/tests/resources/status/.gitted/objects/55/d316c9ba708999f1918e9677d01dfcae69c6b9 new file mode 100644 index 000000000..72807f3d0 Binary files /dev/null and b/tests/resources/status/.gitted/objects/55/d316c9ba708999f1918e9677d01dfcae69c6b9 differ diff --git a/tests/resources/status/.gitted/objects/70/bd9443ada07063e7fbf0b3ff5c13f7494d89c2 b/tests/resources/status/.gitted/objects/70/bd9443ada07063e7fbf0b3ff5c13f7494d89c2 new file mode 100644 index 000000000..3665a8f7c Binary files /dev/null and b/tests/resources/status/.gitted/objects/70/bd9443ada07063e7fbf0b3ff5c13f7494d89c2 differ diff --git a/tests/resources/status/.gitted/objects/73/5b6a258cd196a8f7c9428419b02c1dca93fd75 b/tests/resources/status/.gitted/objects/73/5b6a258cd196a8f7c9428419b02c1dca93fd75 new file mode 100644 index 000000000..08e6fd246 Binary files /dev/null and b/tests/resources/status/.gitted/objects/73/5b6a258cd196a8f7c9428419b02c1dca93fd75 differ diff --git a/tests/resources/status/.gitted/objects/75/6e27627e67bfbc048d01ece5819c6de733d7ea b/tests/resources/status/.gitted/objects/75/6e27627e67bfbc048d01ece5819c6de733d7ea new file mode 100644 index 000000000..8f3fa89e5 Binary files /dev/null and b/tests/resources/status/.gitted/objects/75/6e27627e67bfbc048d01ece5819c6de733d7ea differ diff --git a/tests/resources/status/.gitted/objects/90/6ee7711f4f4928ddcb2a5f8fbc500deba0d2a8 b/tests/resources/status/.gitted/objects/90/6ee7711f4f4928ddcb2a5f8fbc500deba0d2a8 new file mode 100644 index 000000000..bb732b08e Binary files /dev/null and b/tests/resources/status/.gitted/objects/90/6ee7711f4f4928ddcb2a5f8fbc500deba0d2a8 differ diff --git a/tests/resources/status/.gitted/objects/90/b8c29d8ba39434d1c63e1b093daaa26e5bd972 b/tests/resources/status/.gitted/objects/90/b8c29d8ba39434d1c63e1b093daaa26e5bd972 new file mode 100644 index 000000000..7a96618ff Binary files /dev/null and b/tests/resources/status/.gitted/objects/90/b8c29d8ba39434d1c63e1b093daaa26e5bd972 differ diff --git a/tests/resources/status/.gitted/objects/9c/2e02cdffa8d73e6c189074594477a6baf87960 b/tests/resources/status/.gitted/objects/9c/2e02cdffa8d73e6c189074594477a6baf87960 new file mode 100644 index 000000000..20a3c497e Binary files /dev/null and b/tests/resources/status/.gitted/objects/9c/2e02cdffa8d73e6c189074594477a6baf87960 differ diff --git a/tests/resources/status/.gitted/objects/a0/de7e0ac200c489c41c59dfa910154a70264e6e b/tests/resources/status/.gitted/objects/a0/de7e0ac200c489c41c59dfa910154a70264e6e new file mode 100644 index 000000000..a1789c9a6 Binary files /dev/null and b/tests/resources/status/.gitted/objects/a0/de7e0ac200c489c41c59dfa910154a70264e6e differ diff --git a/tests/resources/status/.gitted/objects/a6/191982709b746d5650e93c2acf34ef74e11504 b/tests/resources/status/.gitted/objects/a6/191982709b746d5650e93c2acf34ef74e11504 new file mode 100644 index 000000000..cc1f377b3 Binary files /dev/null and b/tests/resources/status/.gitted/objects/a6/191982709b746d5650e93c2acf34ef74e11504 differ diff --git a/tests/resources/status/.gitted/objects/a6/be623522ce87a1d862128ac42672604f7b468b b/tests/resources/status/.gitted/objects/a6/be623522ce87a1d862128ac42672604f7b468b new file mode 100644 index 000000000..c47298347 Binary files /dev/null and b/tests/resources/status/.gitted/objects/a6/be623522ce87a1d862128ac42672604f7b468b differ diff --git a/tests/resources/status/.gitted/objects/aa/27a641456848200fdb7f7c99ba36f8a0952877 b/tests/resources/status/.gitted/objects/aa/27a641456848200fdb7f7c99ba36f8a0952877 new file mode 100644 index 000000000..a4669ccbb Binary files /dev/null and b/tests/resources/status/.gitted/objects/aa/27a641456848200fdb7f7c99ba36f8a0952877 differ diff --git a/tests/resources/status/.gitted/objects/da/bc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 b/tests/resources/status/.gitted/objects/da/bc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 new file mode 100644 index 000000000..3e3c03c96 Binary files /dev/null and b/tests/resources/status/.gitted/objects/da/bc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 differ diff --git a/tests/resources/status/.gitted/objects/e8/ee89e15bbe9b20137715232387b3de5b28972e b/tests/resources/status/.gitted/objects/e8/ee89e15bbe9b20137715232387b3de5b28972e new file mode 100644 index 000000000..cfc2413d5 Binary files /dev/null and b/tests/resources/status/.gitted/objects/e8/ee89e15bbe9b20137715232387b3de5b28972e differ diff --git a/tests/resources/status/.gitted/objects/e9/b9107f290627c04d097733a10055af941f6bca b/tests/resources/status/.gitted/objects/e9/b9107f290627c04d097733a10055af941f6bca new file mode 100644 index 000000000..1266d3eac Binary files /dev/null and b/tests/resources/status/.gitted/objects/e9/b9107f290627c04d097733a10055af941f6bca differ diff --git a/tests/resources/status/.gitted/objects/ed/062903b8f6f3dccb2fa81117ba6590944ef9bd b/tests/resources/status/.gitted/objects/ed/062903b8f6f3dccb2fa81117ba6590944ef9bd new file mode 100644 index 000000000..8fa8c1707 Binary files /dev/null and b/tests/resources/status/.gitted/objects/ed/062903b8f6f3dccb2fa81117ba6590944ef9bd differ diff --git a/tests/resources/status/.gitted/refs/heads/master b/tests/resources/status/.gitted/refs/heads/master new file mode 100644 index 000000000..3e2e2a07a --- /dev/null +++ b/tests/resources/status/.gitted/refs/heads/master @@ -0,0 +1 @@ +26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f diff --git a/tests/resources/status/current_file b/tests/resources/status/current_file new file mode 100644 index 000000000..a0de7e0ac --- /dev/null +++ b/tests/resources/status/current_file @@ -0,0 +1 @@ +current_file diff --git a/tests/resources/status/ignored_file b/tests/resources/status/ignored_file new file mode 100644 index 000000000..6a79f808a --- /dev/null +++ b/tests/resources/status/ignored_file @@ -0,0 +1 @@ +ignored_file diff --git a/tests/resources/status/modified_file b/tests/resources/status/modified_file new file mode 100644 index 000000000..0a5396305 --- /dev/null +++ b/tests/resources/status/modified_file @@ -0,0 +1,2 @@ +modified_file +modified_file diff --git a/tests/resources/status/new_file b/tests/resources/status/new_file new file mode 100644 index 000000000..d4fa8600b --- /dev/null +++ b/tests/resources/status/new_file @@ -0,0 +1 @@ +new_file diff --git a/tests/resources/status/staged_changes b/tests/resources/status/staged_changes new file mode 100644 index 000000000..55d316c9b --- /dev/null +++ b/tests/resources/status/staged_changes @@ -0,0 +1,2 @@ +staged_changes +staged_changes diff --git a/tests/resources/status/staged_changes_modified_file b/tests/resources/status/staged_changes_modified_file new file mode 100644 index 000000000..011c3440d --- /dev/null +++ b/tests/resources/status/staged_changes_modified_file @@ -0,0 +1,3 @@ +staged_changes_modified_file +staged_changes_modified_file +staged_changes_modified_file diff --git a/tests/resources/status/staged_delete_modified_file b/tests/resources/status/staged_delete_modified_file new file mode 100644 index 000000000..dabc8af9b --- /dev/null +++ b/tests/resources/status/staged_delete_modified_file @@ -0,0 +1 @@ +staged_delete_modified_file diff --git a/tests/resources/status/staged_new_file b/tests/resources/status/staged_new_file new file mode 100644 index 000000000..529a16e8e --- /dev/null +++ b/tests/resources/status/staged_new_file @@ -0,0 +1 @@ +staged_new_file diff --git a/tests/resources/status/staged_new_file_modified_file b/tests/resources/status/staged_new_file_modified_file new file mode 100644 index 000000000..8b090c06d --- /dev/null +++ b/tests/resources/status/staged_new_file_modified_file @@ -0,0 +1,2 @@ +staged_new_file_modified_file +staged_new_file_modified_file diff --git a/tests/resources/status/subdir.txt b/tests/resources/status/subdir.txt new file mode 100644 index 000000000..e8ee89e15 --- /dev/null +++ b/tests/resources/status/subdir.txt @@ -0,0 +1,2 @@ +Is it a bird? +Is it a plane? diff --git a/tests/resources/status/subdir/current_file b/tests/resources/status/subdir/current_file new file mode 100644 index 000000000..53ace0d1c --- /dev/null +++ b/tests/resources/status/subdir/current_file @@ -0,0 +1 @@ +subdir/current_file diff --git a/tests/resources/status/subdir/modified_file b/tests/resources/status/subdir/modified_file new file mode 100644 index 000000000..57274b75e --- /dev/null +++ b/tests/resources/status/subdir/modified_file @@ -0,0 +1,2 @@ +subdir/modified_file +subdir/modified_file diff --git a/tests/resources/status/subdir/new_file b/tests/resources/status/subdir/new_file new file mode 100644 index 000000000..80a86a693 --- /dev/null +++ b/tests/resources/status/subdir/new_file @@ -0,0 +1 @@ +subdir/new_file diff --git "a/tests/resources/status/\350\277\231" "b/tests/resources/status/\350\277\231" new file mode 100644 index 000000000..f0ff9a197 --- /dev/null +++ "b/tests/resources/status/\350\277\231" @@ -0,0 +1 @@ +This diff --git a/tests/resources/submod2/.gitted/HEAD b/tests/resources/submod2/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/submod2/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/submod2/.gitted/config b/tests/resources/submod2/.gitted/config new file mode 100644 index 000000000..abc420734 --- /dev/null +++ b/tests/resources/submod2/.gitted/config @@ -0,0 +1,20 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true +[submodule "sm_missing_commits"] + url = ../submod2_target +[submodule "sm_unchanged"] + url = ../submod2_target +[submodule "sm_changed_file"] + url = ../submod2_target +[submodule "sm_changed_index"] + url = ../submod2_target +[submodule "sm_changed_head"] + url = ../submod2_target +[submodule "sm_changed_untracked_file"] + url = ../submod2_target +[submodule "sm_added_and_uncommited"] + url = ../submod2_target diff --git a/tests/resources/submod2/.gitted/description b/tests/resources/submod2/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/submod2/.gitted/index b/tests/resources/submod2/.gitted/index new file mode 100644 index 000000000..0c17e8629 Binary files /dev/null and b/tests/resources/submod2/.gitted/index differ diff --git a/tests/resources/submod2/.gitted/info/exclude b/tests/resources/submod2/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/submod2/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/submod2/.gitted/logs/HEAD b/tests/resources/submod2/.gitted/logs/HEAD new file mode 100644 index 000000000..2cf2ca74d --- /dev/null +++ b/tests/resources/submod2/.gitted/logs/HEAD @@ -0,0 +1,4 @@ +0000000000000000000000000000000000000000 14fe9ccf104058df25e0a08361c4494e167ef243 Russell Belfer 1342559771 -0700 commit (initial): Initial commit +14fe9ccf104058df25e0a08361c4494e167ef243 a9104bf89e911387244ef499413960ba472066d9 Russell Belfer 1342559831 -0700 commit: Adding a submodule +a9104bf89e911387244ef499413960ba472066d9 5901da4f1c67756eeadc5121d206bec2431f253b Russell Belfer 1342560036 -0700 commit: Updating submodule +5901da4f1c67756eeadc5121d206bec2431f253b 7484482eb8db738cafa696993664607500a3f2b9 Russell Belfer 1342560288 -0700 commit: Adding a bunch more test content diff --git a/tests/resources/submod2/.gitted/logs/refs/heads/master b/tests/resources/submod2/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..2cf2ca74d --- /dev/null +++ b/tests/resources/submod2/.gitted/logs/refs/heads/master @@ -0,0 +1,4 @@ +0000000000000000000000000000000000000000 14fe9ccf104058df25e0a08361c4494e167ef243 Russell Belfer 1342559771 -0700 commit (initial): Initial commit +14fe9ccf104058df25e0a08361c4494e167ef243 a9104bf89e911387244ef499413960ba472066d9 Russell Belfer 1342559831 -0700 commit: Adding a submodule +a9104bf89e911387244ef499413960ba472066d9 5901da4f1c67756eeadc5121d206bec2431f253b Russell Belfer 1342560036 -0700 commit: Updating submodule +5901da4f1c67756eeadc5121d206bec2431f253b 7484482eb8db738cafa696993664607500a3f2b9 Russell Belfer 1342560288 -0700 commit: Adding a bunch more test content diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/HEAD b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/config b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/config new file mode 100644 index 000000000..2d0583e99 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + worktree = ../../../sm_added_and_uncommited + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/description b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/index b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/index new file mode 100644 index 000000000..65140a510 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/index differ diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/info/exclude b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/HEAD b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/HEAD new file mode 100644 index 000000000..53753e7dd --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560316 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/heads/master new file mode 100644 index 000000000..53753e7dd --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560316 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..53753e7dd --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560316 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 new file mode 100644 index 000000000..f4b7094c5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 new file mode 100644 index 000000000..56c845e49 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 new file mode 100644 index 000000000..bd179b5f5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/41/bd4bc3df978de695f67ace64c560913da11653 new file mode 100644 index 000000000..ccf49bd15 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/41/bd4bc3df978de695f67ace64c560913da11653 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 new file mode 100644 index 000000000..53029069a Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/5e/4963595a9774b90524d35a807169049de8ccad new file mode 100644 index 000000000..38c791eba Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/5e/4963595a9774b90524d35a807169049de8ccad differ diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/6b/31c659545507c381e9cd34ec508f16c04e149e new file mode 100644 index 000000000..a26d29993 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/6b/31c659545507c381e9cd34ec508f16c04e149e @@ -0,0 +1,2 @@ +xQ +!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/73/ba924a80437097795ae839e66e187c55d3babf new file mode 100644 index 000000000..83d1ba481 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/73/ba924a80437097795ae839e66e187c55d3babf differ diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a new file mode 100644 index 000000000..6d27af8a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a @@ -0,0 +1,2 @@ +x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x +uxt(+ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/9efbdadaa4a582778d4584385495559ea0994b new file mode 100644 index 000000000..17458840b --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/78/9efbdadaa4a582778d4584385495559ea0994b @@ -0,0 +1,2 @@ +x 0 )?= NlOkj8&r +qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e new file mode 100644 index 000000000..83cc29fb1 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e differ diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 new file mode 100644 index 000000000..55bda40ef Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/packed-refs b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/packed-refs new file mode 100644 index 000000000..5a4ebc47c --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/heads/master new file mode 100644 index 000000000..e12c44d7a --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/heads/master @@ -0,0 +1 @@ +480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/remotes/origin/HEAD new file mode 100644 index 000000000..6efe28fff --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_added_and_uncommited/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_file/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/config b/tests/resources/submod2/.gitted/modules/sm_changed_file/config new file mode 100644 index 000000000..10cc2508e --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + worktree = ../../../sm_changed_file + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/description b/tests/resources/submod2/.gitted/modules/sm_changed_file/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/index b/tests/resources/submod2/.gitted/modules/sm_changed_file/index new file mode 100644 index 000000000..6914a3b6e Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_file/index differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/info/exclude b/tests/resources/submod2/.gitted/modules/sm_changed_file/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/logs/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_file/logs/HEAD new file mode 100644 index 000000000..e5cb63f8d --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560173 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/heads/master new file mode 100644 index 000000000..e5cb63f8d --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560173 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..e5cb63f8d --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560173 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 new file mode 100644 index 000000000..f4b7094c5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 new file mode 100644 index 000000000..56c845e49 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 new file mode 100644 index 000000000..bd179b5f5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 new file mode 100644 index 000000000..ccf49bd15 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 new file mode 100644 index 000000000..53029069a Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/5e/4963595a9774b90524d35a807169049de8ccad new file mode 100644 index 000000000..38c791eba Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/5e/4963595a9774b90524d35a807169049de8ccad differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e new file mode 100644 index 000000000..a26d29993 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e @@ -0,0 +1,2 @@ +xQ +!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/73/ba924a80437097795ae839e66e187c55d3babf new file mode 100644 index 000000000..83d1ba481 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/73/ba924a80437097795ae839e66e187c55d3babf differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a new file mode 100644 index 000000000..6d27af8a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a @@ -0,0 +1,2 @@ +x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x +uxt(+ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b new file mode 100644 index 000000000..17458840b --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b @@ -0,0 +1,2 @@ +x 0 )?= NlOkj8&r +qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e new file mode 100644 index 000000000..83cc29fb1 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 new file mode 100644 index 000000000..55bda40ef Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/packed-refs b/tests/resources/submod2/.gitted/modules/sm_changed_file/packed-refs new file mode 100644 index 000000000..5a4ebc47c --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_changed_file/refs/heads/master new file mode 100644 index 000000000..e12c44d7a --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/refs/heads/master @@ -0,0 +1 @@ +480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_file/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_file/refs/remotes/origin/HEAD new file mode 100644 index 000000000..6efe28fff --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_file/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/COMMIT_EDITMSG b/tests/resources/submod2/.gitted/modules/sm_changed_head/COMMIT_EDITMSG new file mode 100644 index 000000000..6b8d1e3fc --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/COMMIT_EDITMSG @@ -0,0 +1 @@ +Making a change in a submodule diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_head/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/config b/tests/resources/submod2/.gitted/modules/sm_changed_head/config new file mode 100644 index 000000000..7d002536a --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + worktree = ../../../sm_changed_head + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/description b/tests/resources/submod2/.gitted/modules/sm_changed_head/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/index b/tests/resources/submod2/.gitted/modules/sm_changed_head/index new file mode 100644 index 000000000..728fa292f Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_head/index differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/info/exclude b/tests/resources/submod2/.gitted/modules/sm_changed_head/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/logs/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_head/logs/HEAD new file mode 100644 index 000000000..cabdeb2b5 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/logs/HEAD @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560179 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target +480095882d281ed676fe5b863569520e54a7d5c0 3d9386c507f6b093471a3e324085657a3c2b4247 Russell Belfer 1342560431 -0700 commit: Making a change in a submodule diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/heads/master new file mode 100644 index 000000000..cabdeb2b5 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/heads/master @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560179 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target +480095882d281ed676fe5b863569520e54a7d5c0 3d9386c507f6b093471a3e324085657a3c2b4247 Russell Belfer 1342560431 -0700 commit: Making a change in a submodule diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..257ca21d1 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560179 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 new file mode 100644 index 000000000..f4b7094c5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 new file mode 100644 index 000000000..56c845e49 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 new file mode 100644 index 000000000..bd179b5f5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/3d/9386c507f6b093471a3e324085657a3c2b4247 b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/3d/9386c507f6b093471a3e324085657a3c2b4247 new file mode 100644 index 000000000..a2c371642 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/3d/9386c507f6b093471a3e324085657a3c2b4247 @@ -0,0 +1,3 @@ +xKj!E3vj#<<@Ouq .)ql osFa#v )g#{':Tl`b40 ;fr4 + +zU-/glm\'LjrhXG_+l ʚE`;=]J \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/41/bd4bc3df978de695f67ace64c560913da11653 new file mode 100644 index 000000000..ccf49bd15 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/41/bd4bc3df978de695f67ace64c560913da11653 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 new file mode 100644 index 000000000..53029069a Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/5e/4963595a9774b90524d35a807169049de8ccad new file mode 100644 index 000000000..38c791eba Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/5e/4963595a9774b90524d35a807169049de8ccad differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/6b/31c659545507c381e9cd34ec508f16c04e149e new file mode 100644 index 000000000..a26d29993 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/6b/31c659545507c381e9cd34ec508f16c04e149e @@ -0,0 +1,2 @@ +xQ +!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/73/ba924a80437097795ae839e66e187c55d3babf new file mode 100644 index 000000000..83d1ba481 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/73/ba924a80437097795ae839e66e187c55d3babf differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/77/fb0ed3e58568d6ad362c78de08ab8649d76e29 b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/77/fb0ed3e58568d6ad362c78de08ab8649d76e29 new file mode 100644 index 000000000..f8a236f3d Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/77/fb0ed3e58568d6ad362c78de08ab8649d76e29 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a new file mode 100644 index 000000000..6d27af8a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a @@ -0,0 +1,2 @@ +x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x +uxt(+ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/78/9efbdadaa4a582778d4584385495559ea0994b new file mode 100644 index 000000000..17458840b --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/78/9efbdadaa4a582778d4584385495559ea0994b @@ -0,0 +1,2 @@ +x 0 )?= NlOkj8&r +qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e new file mode 100644 index 000000000..83cc29fb1 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/8e/b1e637ed9fc8e5454fa20d38f809091f9395f4 b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/8e/b1e637ed9fc8e5454fa20d38f809091f9395f4 new file mode 100644 index 000000000..8155b3e87 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/8e/b1e637ed9fc8e5454fa20d38f809091f9395f4 @@ -0,0 +1,2 @@ +xMM; +1) ZPr3k lEnl!crz ,e +lEZxuPYx QC*fuLcfR3T0'үj~G^s1b2zVk]5<v'> \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 new file mode 100644 index 000000000..55bda40ef Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_head/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/packed-refs b/tests/resources/submod2/.gitted/modules/sm_changed_head/packed-refs new file mode 100644 index 000000000..5a4ebc47c --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_changed_head/refs/heads/master new file mode 100644 index 000000000..ae079bd79 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/refs/heads/master @@ -0,0 +1 @@ +3d9386c507f6b093471a3e324085657a3c2b4247 diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_head/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_head/refs/remotes/origin/HEAD new file mode 100644 index 000000000..6efe28fff --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_head/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_index/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/config b/tests/resources/submod2/.gitted/modules/sm_changed_index/config new file mode 100644 index 000000000..0274ff7e3 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + worktree = ../../../sm_changed_index + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/description b/tests/resources/submod2/.gitted/modules/sm_changed_index/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/index b/tests/resources/submod2/.gitted/modules/sm_changed_index/index new file mode 100644 index 000000000..6fad3b43e Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_index/index differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/info/exclude b/tests/resources/submod2/.gitted/modules/sm_changed_index/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/logs/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_index/logs/HEAD new file mode 100644 index 000000000..80eb54102 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560175 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/heads/master new file mode 100644 index 000000000..80eb54102 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560175 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..80eb54102 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560175 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 new file mode 100644 index 000000000..f4b7094c5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 new file mode 100644 index 000000000..56c845e49 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 new file mode 100644 index 000000000..bd179b5f5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/41/bd4bc3df978de695f67ace64c560913da11653 new file mode 100644 index 000000000..ccf49bd15 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/41/bd4bc3df978de695f67ace64c560913da11653 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 new file mode 100644 index 000000000..53029069a Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/5e/4963595a9774b90524d35a807169049de8ccad new file mode 100644 index 000000000..38c791eba Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/5e/4963595a9774b90524d35a807169049de8ccad differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/6b/31c659545507c381e9cd34ec508f16c04e149e new file mode 100644 index 000000000..a26d29993 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/6b/31c659545507c381e9cd34ec508f16c04e149e @@ -0,0 +1,2 @@ +xQ +!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/73/ba924a80437097795ae839e66e187c55d3babf new file mode 100644 index 000000000..83d1ba481 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/73/ba924a80437097795ae839e66e187c55d3babf differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a new file mode 100644 index 000000000..6d27af8a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a @@ -0,0 +1,2 @@ +x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x +uxt(+ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/78/9efbdadaa4a582778d4584385495559ea0994b new file mode 100644 index 000000000..17458840b --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/78/9efbdadaa4a582778d4584385495559ea0994b @@ -0,0 +1,2 @@ +x 0 )?= NlOkj8&r +qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e new file mode 100644 index 000000000..83cc29fb1 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/a0/2d31770687965547ab7a04cee199b29ee458d6 b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/a0/2d31770687965547ab7a04cee199b29ee458d6 new file mode 100644 index 000000000..cb3f5a002 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/a0/2d31770687965547ab7a04cee199b29ee458d6 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 new file mode 100644 index 000000000..55bda40ef Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_index/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/packed-refs b/tests/resources/submod2/.gitted/modules/sm_changed_index/packed-refs new file mode 100644 index 000000000..5a4ebc47c --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_changed_index/refs/heads/master new file mode 100644 index 000000000..e12c44d7a --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/refs/heads/master @@ -0,0 +1 @@ +480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_index/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_index/refs/remotes/origin/HEAD new file mode 100644 index 000000000..6efe28fff --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_index/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/config b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/config new file mode 100644 index 000000000..7f2584476 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + worktree = ../../../sm_changed_untracked_file + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/description b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/index b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/index new file mode 100644 index 000000000..598e30a32 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/index differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/info/exclude b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/HEAD new file mode 100644 index 000000000..d1beafbd6 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560186 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/heads/master new file mode 100644 index 000000000..d1beafbd6 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560186 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..d1beafbd6 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560186 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 new file mode 100644 index 000000000..f4b7094c5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 new file mode 100644 index 000000000..56c845e49 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 new file mode 100644 index 000000000..bd179b5f5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 new file mode 100644 index 000000000..ccf49bd15 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/41/bd4bc3df978de695f67ace64c560913da11653 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 new file mode 100644 index 000000000..53029069a Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/5e/4963595a9774b90524d35a807169049de8ccad new file mode 100644 index 000000000..38c791eba Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/5e/4963595a9774b90524d35a807169049de8ccad differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e new file mode 100644 index 000000000..a26d29993 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/6b/31c659545507c381e9cd34ec508f16c04e149e @@ -0,0 +1,2 @@ +xQ +!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/73/ba924a80437097795ae839e66e187c55d3babf new file mode 100644 index 000000000..83d1ba481 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/73/ba924a80437097795ae839e66e187c55d3babf differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a new file mode 100644 index 000000000..6d27af8a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a @@ -0,0 +1,2 @@ +x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x +uxt(+ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b new file mode 100644 index 000000000..17458840b --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/78/9efbdadaa4a582778d4584385495559ea0994b @@ -0,0 +1,2 @@ +x 0 )?= NlOkj8&r +qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e new file mode 100644 index 000000000..83cc29fb1 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 new file mode 100644 index 000000000..55bda40ef Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/packed-refs b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/packed-refs new file mode 100644 index 000000000..5a4ebc47c --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/heads/master new file mode 100644 index 000000000..e12c44d7a --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/heads/master @@ -0,0 +1 @@ +480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/remotes/origin/HEAD new file mode 100644 index 000000000..6efe28fff --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_changed_untracked_file/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/HEAD b/tests/resources/submod2/.gitted/modules/sm_missing_commits/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_missing_commits/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/config b/tests/resources/submod2/.gitted/modules/sm_missing_commits/config new file mode 100644 index 000000000..45fbb30cf --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_missing_commits/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + worktree = ../../../sm_missing_commits + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/description b/tests/resources/submod2/.gitted/modules/sm_missing_commits/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_missing_commits/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/index b/tests/resources/submod2/.gitted/modules/sm_missing_commits/index new file mode 100644 index 000000000..490356524 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_missing_commits/index differ diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/info/exclude b/tests/resources/submod2/.gitted/modules/sm_missing_commits/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_missing_commits/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/logs/HEAD b/tests/resources/submod2/.gitted/modules/sm_missing_commits/logs/HEAD new file mode 100644 index 000000000..ee08c9706 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_missing_commits/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 5e4963595a9774b90524d35a807169049de8ccad Russell Belfer 1342559796 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/heads/master new file mode 100644 index 000000000..ee08c9706 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 5e4963595a9774b90524d35a807169049de8ccad Russell Belfer 1342559796 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..ee08c9706 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_missing_commits/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 5e4963595a9774b90524d35a807169049de8ccad Russell Belfer 1342559796 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 new file mode 100644 index 000000000..f4b7094c5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 new file mode 100644 index 000000000..56c845e49 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 new file mode 100644 index 000000000..bd179b5f5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/41/bd4bc3df978de695f67ace64c560913da11653 new file mode 100644 index 000000000..ccf49bd15 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/41/bd4bc3df978de695f67ace64c560913da11653 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/5e/4963595a9774b90524d35a807169049de8ccad new file mode 100644 index 000000000..38c791eba Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/5e/4963595a9774b90524d35a807169049de8ccad differ diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/6b/31c659545507c381e9cd34ec508f16c04e149e new file mode 100644 index 000000000..a26d29993 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/6b/31c659545507c381e9cd34ec508f16c04e149e @@ -0,0 +1,2 @@ +xQ +!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a new file mode 100644 index 000000000..6d27af8a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a @@ -0,0 +1,2 @@ +x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x +uxt(+ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e new file mode 100644 index 000000000..83cc29fb1 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e differ diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 new file mode 100644 index 000000000..55bda40ef Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_missing_commits/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/packed-refs b/tests/resources/submod2/.gitted/modules/sm_missing_commits/packed-refs new file mode 100644 index 000000000..66fbf5daf --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_missing_commits/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +5e4963595a9774b90524d35a807169049de8ccad refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_missing_commits/refs/heads/master new file mode 100644 index 000000000..3913aca5d --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_missing_commits/refs/heads/master @@ -0,0 +1 @@ +5e4963595a9774b90524d35a807169049de8ccad diff --git a/tests/resources/submod2/.gitted/modules/sm_missing_commits/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_missing_commits/refs/remotes/origin/HEAD new file mode 100644 index 000000000..6efe28fff --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_missing_commits/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/HEAD b/tests/resources/submod2/.gitted/modules/sm_unchanged/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/config b/tests/resources/submod2/.gitted/modules/sm_unchanged/config new file mode 100644 index 000000000..fc706c9dd --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + worktree = ../../../sm_unchanged + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/description b/tests/resources/submod2/.gitted/modules/sm_unchanged/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/index b/tests/resources/submod2/.gitted/modules/sm_unchanged/index new file mode 100644 index 000000000..629c849ec Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_unchanged/index differ diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/info/exclude b/tests/resources/submod2/.gitted/modules/sm_unchanged/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/logs/HEAD b/tests/resources/submod2/.gitted/modules/sm_unchanged/logs/HEAD new file mode 100644 index 000000000..72653286a --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560169 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/heads/master new file mode 100644 index 000000000..72653286a --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560169 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..72653286a --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342560169 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/submod2_target diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 new file mode 100644 index 000000000..f4b7094c5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 new file mode 100644 index 000000000..56c845e49 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 new file mode 100644 index 000000000..bd179b5f5 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/41/bd4bc3df978de695f67ace64c560913da11653 new file mode 100644 index 000000000..ccf49bd15 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/41/bd4bc3df978de695f67ace64c560913da11653 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 new file mode 100644 index 000000000..53029069a Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/5e/4963595a9774b90524d35a807169049de8ccad new file mode 100644 index 000000000..38c791eba Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/5e/4963595a9774b90524d35a807169049de8ccad differ diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/6b/31c659545507c381e9cd34ec508f16c04e149e new file mode 100644 index 000000000..a26d29993 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/6b/31c659545507c381e9cd34ec508f16c04e149e @@ -0,0 +1,2 @@ +xQ +!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/73/ba924a80437097795ae839e66e187c55d3babf new file mode 100644 index 000000000..83d1ba481 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/73/ba924a80437097795ae839e66e187c55d3babf differ diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a new file mode 100644 index 000000000..6d27af8a8 --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a @@ -0,0 +1,2 @@ +x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x +uxt(+ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/78/9efbdadaa4a582778d4584385495559ea0994b new file mode 100644 index 000000000..17458840b --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/78/9efbdadaa4a582778d4584385495559ea0994b @@ -0,0 +1,2 @@ +x 0 )?= NlOkj8&r +qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e new file mode 100644 index 000000000..83cc29fb1 Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e differ diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 new file mode 100644 index 000000000..55bda40ef Binary files /dev/null and b/tests/resources/submod2/.gitted/modules/sm_unchanged/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 differ diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/packed-refs b/tests/resources/submod2/.gitted/modules/sm_unchanged/packed-refs new file mode 100644 index 000000000..5a4ebc47c --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/refs/heads/master b/tests/resources/submod2/.gitted/modules/sm_unchanged/refs/heads/master new file mode 100644 index 000000000..e12c44d7a --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/refs/heads/master @@ -0,0 +1 @@ +480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests/resources/submod2/.gitted/modules/sm_unchanged/refs/remotes/origin/HEAD b/tests/resources/submod2/.gitted/modules/sm_unchanged/refs/remotes/origin/HEAD new file mode 100644 index 000000000..6efe28fff --- /dev/null +++ b/tests/resources/submod2/.gitted/modules/sm_unchanged/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/tests/resources/submod2/.gitted/objects/09/460e5b6cbcb05a3e404593c32a3aa7221eca0e b/tests/resources/submod2/.gitted/objects/09/460e5b6cbcb05a3e404593c32a3aa7221eca0e new file mode 100644 index 000000000..f1ea5f4c8 Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/09/460e5b6cbcb05a3e404593c32a3aa7221eca0e differ diff --git a/tests/resources/submod2/.gitted/objects/14/fe9ccf104058df25e0a08361c4494e167ef243 b/tests/resources/submod2/.gitted/objects/14/fe9ccf104058df25e0a08361c4494e167ef243 new file mode 100644 index 000000000..d3c8582e3 --- /dev/null +++ b/tests/resources/submod2/.gitted/objects/14/fe9ccf104058df25e0a08361c4494e167ef243 @@ -0,0 +1 @@ +xM F]sfhcc;ހ@I(_O{s%@> ^!F'!諲l_q4E޶RݏS'n>>m^\w^$X_迦xE_.9} \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/objects/22/ce3e0311dda73a5992d54a4a595518d3876ea7 b/tests/resources/submod2/.gitted/objects/22/ce3e0311dda73a5992d54a4a595518d3876ea7 new file mode 100644 index 000000000..fce6a94b5 --- /dev/null +++ b/tests/resources/submod2/.gitted/objects/22/ce3e0311dda73a5992d54a4a595518d3876ea7 @@ -0,0 +1,4 @@ +x +0Eݶ_Q. +. W"!1 !3 >+.9=3W(n-:;j[" W{ޕQZW,2 iviyh T/={ !@b(bJcSPrŌ +{`|%imp콡=IÿW26B@)|)g \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/objects/25/5546424b0efb847b1bfc91dbf7348b277f8970 b/tests/resources/submod2/.gitted/objects/25/5546424b0efb847b1bfc91dbf7348b277f8970 new file mode 100644 index 000000000..2965becf6 Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/25/5546424b0efb847b1bfc91dbf7348b277f8970 differ diff --git a/tests/resources/submod2/.gitted/objects/2a/30f1e6f94b20917005a21273f65b406d0f8bad b/tests/resources/submod2/.gitted/objects/2a/30f1e6f94b20917005a21273f65b406d0f8bad new file mode 100644 index 000000000..08faf0fa8 Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/2a/30f1e6f94b20917005a21273f65b406d0f8bad differ diff --git a/tests/resources/submod2/.gitted/objects/42/cfb95cd01bf9225b659b5ee3edcc78e8eeb478 b/tests/resources/submod2/.gitted/objects/42/cfb95cd01bf9225b659b5ee3edcc78e8eeb478 new file mode 100644 index 000000000..ee7848ae6 Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/42/cfb95cd01bf9225b659b5ee3edcc78e8eeb478 differ diff --git a/tests/resources/submod2/.gitted/objects/57/958699c2dc394f81cfc76950e9c3ac3025c398 b/tests/resources/submod2/.gitted/objects/57/958699c2dc394f81cfc76950e9c3ac3025c398 new file mode 100644 index 000000000..ca9203a6e Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/57/958699c2dc394f81cfc76950e9c3ac3025c398 differ diff --git a/tests/resources/submod2/.gitted/objects/59/01da4f1c67756eeadc5121d206bec2431f253b b/tests/resources/submod2/.gitted/objects/59/01da4f1c67756eeadc5121d206bec2431f253b new file mode 100644 index 000000000..9f88f6bdf --- /dev/null +++ b/tests/resources/submod2/.gitted/objects/59/01da4f1c67756eeadc5121d206bec2431f253b @@ -0,0 +1,2 @@ +x 1ENӀ2yg@D,A$;YE6m{΁e(/2d#jȚL 2Yd:fʞ =V^DhR $^a+tn {n8xs +Ծ=<@jCŹک[>6#=-g?,F \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/objects/60/7d96653d4d0a4f733107f7890c2e67b55b620d b/tests/resources/submod2/.gitted/objects/60/7d96653d4d0a4f733107f7890c2e67b55b620d new file mode 100644 index 000000000..30bee40e9 Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/60/7d96653d4d0a4f733107f7890c2e67b55b620d differ diff --git a/tests/resources/submod2/.gitted/objects/74/84482eb8db738cafa696993664607500a3f2b9 b/tests/resources/submod2/.gitted/objects/74/84482eb8db738cafa696993664607500a3f2b9 new file mode 100644 index 000000000..79018042d Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/74/84482eb8db738cafa696993664607500a3f2b9 differ diff --git a/tests/resources/submod2/.gitted/objects/7b/a4c5c3561daa5ab1a86215cfb0587e96d404d6 b/tests/resources/submod2/.gitted/objects/7b/a4c5c3561daa5ab1a86215cfb0587e96d404d6 new file mode 100644 index 000000000..cde89e5bb Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/7b/a4c5c3561daa5ab1a86215cfb0587e96d404d6 differ diff --git a/tests/resources/submod2/.gitted/objects/87/3585b94bdeabccea991ea5e3ec1a277895b698 b/tests/resources/submod2/.gitted/objects/87/3585b94bdeabccea991ea5e3ec1a277895b698 new file mode 100644 index 000000000..41af98aa9 Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/87/3585b94bdeabccea991ea5e3ec1a277895b698 differ diff --git a/tests/resources/submod2/.gitted/objects/97/4cf7c73de336b0c4e019f918f3cee367d72e84 b/tests/resources/submod2/.gitted/objects/97/4cf7c73de336b0c4e019f918f3cee367d72e84 new file mode 100644 index 000000000..160f1caf4 --- /dev/null +++ b/tests/resources/submod2/.gitted/objects/97/4cf7c73de336b0c4e019f918f3cee367d72e84 @@ -0,0 +1,2 @@ +x +0Eݶ_Bqg yi IYUp!΁s|R7=)XCAG:25:<-uU_IY\Ϥ%AF f{G qTPsu(Z{RA #̉0mŲ.8b?{vʌ \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/objects/9d/bc299bc013ea253583b40bf327b5a6e4037b89 b/tests/resources/submod2/.gitted/objects/9d/bc299bc013ea253583b40bf327b5a6e4037b89 new file mode 100644 index 000000000..1ee52218d Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/9d/bc299bc013ea253583b40bf327b5a6e4037b89 differ diff --git a/tests/resources/submod2/.gitted/objects/a9/104bf89e911387244ef499413960ba472066d9 b/tests/resources/submod2/.gitted/objects/a9/104bf89e911387244ef499413960ba472066d9 new file mode 100644 index 000000000..2239e14a8 Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/a9/104bf89e911387244ef499413960ba472066d9 differ diff --git a/tests/resources/submod2/.gitted/objects/b6/14088620bbdc1d29549d223ceba0f4419fd4cb b/tests/resources/submod2/.gitted/objects/b6/14088620bbdc1d29549d223ceba0f4419fd4cb new file mode 100644 index 000000000..a03ea66e4 Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/b6/14088620bbdc1d29549d223ceba0f4419fd4cb differ diff --git a/tests/resources/submod2/.gitted/objects/d4/07f19e50c1da1ff584beafe0d6dac7237c5d06 b/tests/resources/submod2/.gitted/objects/d4/07f19e50c1da1ff584beafe0d6dac7237c5d06 new file mode 100644 index 000000000..292303eb9 Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/d4/07f19e50c1da1ff584beafe0d6dac7237c5d06 differ diff --git a/tests/resources/submod2/.gitted/objects/d9/3e95571d92cceb5de28c205f1d5f3cc8b88bc8 b/tests/resources/submod2/.gitted/objects/d9/3e95571d92cceb5de28c205f1d5f3cc8b88bc8 new file mode 100644 index 000000000..b92c7eebd --- /dev/null +++ b/tests/resources/submod2/.gitted/objects/d9/3e95571d92cceb5de28c205f1d5f3cc8b88bc8 @@ -0,0 +1,2 @@ +x +!nק} ".zuRCx}Αہt .׫6,is&%9S#IW=aߐf2ABYsНa{c^K3gwM͠Fߥ4s'NI \ No newline at end of file diff --git a/tests/resources/submod2/.gitted/objects/e3/b83bf274ee065eee48734cf8c6dfaf5e81471c b/tests/resources/submod2/.gitted/objects/e3/b83bf274ee065eee48734cf8c6dfaf5e81471c new file mode 100644 index 000000000..3c7750b12 Binary files /dev/null and b/tests/resources/submod2/.gitted/objects/e3/b83bf274ee065eee48734cf8c6dfaf5e81471c differ diff --git a/tests/resources/submod2/.gitted/objects/f5/4414c25e6d24fe39f5c3f128d7c8a17bc23833 b/tests/resources/submod2/.gitted/objects/f5/4414c25e6d24fe39f5c3f128d7c8a17bc23833 new file mode 100644 index 000000000..219620b25 --- /dev/null +++ b/tests/resources/submod2/.gitted/objects/f5/4414c25e6d24fe39f5c3f128d7c8a17bc23833 @@ -0,0 +1,2 @@ +xe +0aSbOz12 1342560358 -0700 commit (initial): Initial commit diff --git a/tests/resources/submod2/not-submodule/.gitted/logs/refs/heads/master b/tests/resources/submod2/not-submodule/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..1749e7dff --- /dev/null +++ b/tests/resources/submod2/not-submodule/.gitted/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 68e92c611b80ee1ed8f38314ff9577f0d15b2444 Russell Belfer 1342560358 -0700 commit (initial): Initial commit diff --git a/tests/resources/submod2/not-submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 b/tests/resources/submod2/not-submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 new file mode 100644 index 000000000..8892531a7 Binary files /dev/null and b/tests/resources/submod2/not-submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 differ diff --git a/tests/resources/submod2/not-submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 b/tests/resources/submod2/not-submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 new file mode 100644 index 000000000..c4e1a77d7 Binary files /dev/null and b/tests/resources/submod2/not-submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 differ diff --git a/tests/resources/submod2/not-submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e b/tests/resources/submod2/not-submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e new file mode 100644 index 000000000..e9f1942a9 Binary files /dev/null and b/tests/resources/submod2/not-submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e differ diff --git a/tests/resources/submod2/not-submodule/.gitted/refs/heads/master b/tests/resources/submod2/not-submodule/.gitted/refs/heads/master new file mode 100644 index 000000000..0bd8514bd --- /dev/null +++ b/tests/resources/submod2/not-submodule/.gitted/refs/heads/master @@ -0,0 +1 @@ +68e92c611b80ee1ed8f38314ff9577f0d15b2444 diff --git a/tests/resources/submod2/not-submodule/README.txt b/tests/resources/submod2/not-submodule/README.txt new file mode 100644 index 000000000..71ff9927d --- /dev/null +++ b/tests/resources/submod2/not-submodule/README.txt @@ -0,0 +1 @@ +This is a git repo but not a submodule diff --git a/tests/resources/submod2/not/.gitted/notempty b/tests/resources/submod2/not/.gitted/notempty new file mode 100644 index 000000000..9b33ac4e4 --- /dev/null +++ b/tests/resources/submod2/not/.gitted/notempty @@ -0,0 +1 @@ +fooled you diff --git a/tests/resources/submod2/not/README.txt b/tests/resources/submod2/not/README.txt new file mode 100644 index 000000000..4f6935b98 --- /dev/null +++ b/tests/resources/submod2/not/README.txt @@ -0,0 +1 @@ +what am I really diff --git a/tests/resources/submod2/sm_added_and_uncommited/.gitted b/tests/resources/submod2/sm_added_and_uncommited/.gitted new file mode 100644 index 000000000..2b2a4cf90 --- /dev/null +++ b/tests/resources/submod2/sm_added_and_uncommited/.gitted @@ -0,0 +1 @@ +gitdir: ../.git/modules/sm_added_and_uncommited diff --git a/tests/resources/submod2/sm_added_and_uncommited/README.txt b/tests/resources/submod2/sm_added_and_uncommited/README.txt new file mode 100644 index 000000000..780d7397f --- /dev/null +++ b/tests/resources/submod2/sm_added_and_uncommited/README.txt @@ -0,0 +1,3 @@ +This is the target for submod2 submodule links. +Don't add commits casually because you make break tests. + diff --git a/tests/resources/submod2/sm_added_and_uncommited/file_to_modify b/tests/resources/submod2/sm_added_and_uncommited/file_to_modify new file mode 100644 index 000000000..789efbdad --- /dev/null +++ b/tests/resources/submod2/sm_added_and_uncommited/file_to_modify @@ -0,0 +1,3 @@ +This is a file to modify in submodules +It already has some history. +You can add local changes as needed. diff --git a/tests/resources/submod2/sm_changed_file/.gitted b/tests/resources/submod2/sm_changed_file/.gitted new file mode 100644 index 000000000..dc98b1674 --- /dev/null +++ b/tests/resources/submod2/sm_changed_file/.gitted @@ -0,0 +1 @@ +gitdir: ../.git/modules/sm_changed_file diff --git a/tests/resources/submod2/sm_changed_file/README.txt b/tests/resources/submod2/sm_changed_file/README.txt new file mode 100644 index 000000000..780d7397f --- /dev/null +++ b/tests/resources/submod2/sm_changed_file/README.txt @@ -0,0 +1,3 @@ +This is the target for submod2 submodule links. +Don't add commits casually because you make break tests. + diff --git a/tests/resources/submod2/sm_changed_file/file_to_modify b/tests/resources/submod2/sm_changed_file/file_to_modify new file mode 100644 index 000000000..e5ba67168 --- /dev/null +++ b/tests/resources/submod2/sm_changed_file/file_to_modify @@ -0,0 +1,4 @@ +This is a file to modify in submodules +It already has some history. +You can add local changes as needed. +In this case, the file is changed in the workdir diff --git a/tests/resources/submod2/sm_changed_head/.gitted b/tests/resources/submod2/sm_changed_head/.gitted new file mode 100644 index 000000000..d5419b62d --- /dev/null +++ b/tests/resources/submod2/sm_changed_head/.gitted @@ -0,0 +1 @@ +gitdir: ../.git/modules/sm_changed_head diff --git a/tests/resources/submod2/sm_changed_head/README.txt b/tests/resources/submod2/sm_changed_head/README.txt new file mode 100644 index 000000000..780d7397f --- /dev/null +++ b/tests/resources/submod2/sm_changed_head/README.txt @@ -0,0 +1,3 @@ +This is the target for submod2 submodule links. +Don't add commits casually because you make break tests. + diff --git a/tests/resources/submod2/sm_changed_head/file_to_modify b/tests/resources/submod2/sm_changed_head/file_to_modify new file mode 100644 index 000000000..8eb1e637e --- /dev/null +++ b/tests/resources/submod2/sm_changed_head/file_to_modify @@ -0,0 +1,4 @@ +This is a file to modify in submodules +It already has some history. +You can add local changes as needed. +This one has been changed and the change has been committed to HEAD. diff --git a/tests/resources/submod2/sm_changed_index/.gitted b/tests/resources/submod2/sm_changed_index/.gitted new file mode 100644 index 000000000..2c7a5b271 --- /dev/null +++ b/tests/resources/submod2/sm_changed_index/.gitted @@ -0,0 +1 @@ +gitdir: ../.git/modules/sm_changed_index diff --git a/tests/resources/submod2/sm_changed_index/README.txt b/tests/resources/submod2/sm_changed_index/README.txt new file mode 100644 index 000000000..780d7397f --- /dev/null +++ b/tests/resources/submod2/sm_changed_index/README.txt @@ -0,0 +1,3 @@ +This is the target for submod2 submodule links. +Don't add commits casually because you make break tests. + diff --git a/tests/resources/submod2/sm_changed_index/file_to_modify b/tests/resources/submod2/sm_changed_index/file_to_modify new file mode 100644 index 000000000..a02d31770 --- /dev/null +++ b/tests/resources/submod2/sm_changed_index/file_to_modify @@ -0,0 +1,4 @@ +This is a file to modify in submodules +It already has some history. +You can add local changes as needed. +Here the file is changed in the index and the workdir diff --git a/tests/resources/submod2/sm_changed_untracked_file/.gitted b/tests/resources/submod2/sm_changed_untracked_file/.gitted new file mode 100644 index 000000000..9a1070647 --- /dev/null +++ b/tests/resources/submod2/sm_changed_untracked_file/.gitted @@ -0,0 +1 @@ +gitdir: ../.git/modules/sm_changed_untracked_file diff --git a/tests/resources/submod2/sm_changed_untracked_file/README.txt b/tests/resources/submod2/sm_changed_untracked_file/README.txt new file mode 100644 index 000000000..780d7397f --- /dev/null +++ b/tests/resources/submod2/sm_changed_untracked_file/README.txt @@ -0,0 +1,3 @@ +This is the target for submod2 submodule links. +Don't add commits casually because you make break tests. + diff --git a/tests/resources/submod2/sm_changed_untracked_file/file_to_modify b/tests/resources/submod2/sm_changed_untracked_file/file_to_modify new file mode 100644 index 000000000..789efbdad --- /dev/null +++ b/tests/resources/submod2/sm_changed_untracked_file/file_to_modify @@ -0,0 +1,3 @@ +This is a file to modify in submodules +It already has some history. +You can add local changes as needed. diff --git a/tests/resources/submod2/sm_changed_untracked_file/i_am_untracked b/tests/resources/submod2/sm_changed_untracked_file/i_am_untracked new file mode 100644 index 000000000..d2bae6167 --- /dev/null +++ b/tests/resources/submod2/sm_changed_untracked_file/i_am_untracked @@ -0,0 +1 @@ +This file is untracked, but in a submodule diff --git a/tests/resources/submod2/sm_missing_commits/.gitted b/tests/resources/submod2/sm_missing_commits/.gitted new file mode 100644 index 000000000..70193be84 --- /dev/null +++ b/tests/resources/submod2/sm_missing_commits/.gitted @@ -0,0 +1 @@ +gitdir: ../.git/modules/sm_missing_commits diff --git a/tests/resources/submod2/sm_missing_commits/README.txt b/tests/resources/submod2/sm_missing_commits/README.txt new file mode 100644 index 000000000..780d7397f --- /dev/null +++ b/tests/resources/submod2/sm_missing_commits/README.txt @@ -0,0 +1,3 @@ +This is the target for submod2 submodule links. +Don't add commits casually because you make break tests. + diff --git a/tests/resources/submod2/sm_missing_commits/file_to_modify b/tests/resources/submod2/sm_missing_commits/file_to_modify new file mode 100644 index 000000000..8834b635d --- /dev/null +++ b/tests/resources/submod2/sm_missing_commits/file_to_modify @@ -0,0 +1,3 @@ +This is a file to modify in submodules +It already has some history. + diff --git a/tests/resources/submod2/sm_unchanged/.gitted b/tests/resources/submod2/sm_unchanged/.gitted new file mode 100644 index 000000000..51a679c80 --- /dev/null +++ b/tests/resources/submod2/sm_unchanged/.gitted @@ -0,0 +1 @@ +gitdir: ../.git/modules/sm_unchanged diff --git a/tests/resources/submod2/sm_unchanged/README.txt b/tests/resources/submod2/sm_unchanged/README.txt new file mode 100644 index 000000000..780d7397f --- /dev/null +++ b/tests/resources/submod2/sm_unchanged/README.txt @@ -0,0 +1,3 @@ +This is the target for submod2 submodule links. +Don't add commits casually because you make break tests. + diff --git a/tests/resources/submod2/sm_unchanged/file_to_modify b/tests/resources/submod2/sm_unchanged/file_to_modify new file mode 100644 index 000000000..789efbdad --- /dev/null +++ b/tests/resources/submod2/sm_unchanged/file_to_modify @@ -0,0 +1,3 @@ +This is a file to modify in submodules +It already has some history. +You can add local changes as needed. diff --git a/tests/resources/submod2_target/.gitted/HEAD b/tests/resources/submod2_target/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/submod2_target/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/submod2_target/.gitted/config b/tests/resources/submod2_target/.gitted/config new file mode 100644 index 000000000..af107929f --- /dev/null +++ b/tests/resources/submod2_target/.gitted/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true diff --git a/tests/resources/submod2_target/.gitted/description b/tests/resources/submod2_target/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/submod2_target/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/submod2_target/.gitted/index b/tests/resources/submod2_target/.gitted/index new file mode 100644 index 000000000..eb3ff8c10 Binary files /dev/null and b/tests/resources/submod2_target/.gitted/index differ diff --git a/tests/resources/submod2_target/.gitted/info/exclude b/tests/resources/submod2_target/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/submod2_target/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/submod2_target/.gitted/logs/HEAD b/tests/resources/submod2_target/.gitted/logs/HEAD new file mode 100644 index 000000000..0ecd1113f --- /dev/null +++ b/tests/resources/submod2_target/.gitted/logs/HEAD @@ -0,0 +1,4 @@ +0000000000000000000000000000000000000000 6b31c659545507c381e9cd34ec508f16c04e149e Russell Belfer 1342559662 -0700 commit (initial): Initial commit +6b31c659545507c381e9cd34ec508f16c04e149e 41bd4bc3df978de695f67ace64c560913da11653 Russell Belfer 1342559709 -0700 commit: Adding test file +41bd4bc3df978de695f67ace64c560913da11653 5e4963595a9774b90524d35a807169049de8ccad Russell Belfer 1342559726 -0700 commit: Updating test file +5e4963595a9774b90524d35a807169049de8ccad 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342559925 -0700 commit: One more update diff --git a/tests/resources/submod2_target/.gitted/logs/refs/heads/master b/tests/resources/submod2_target/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..0ecd1113f --- /dev/null +++ b/tests/resources/submod2_target/.gitted/logs/refs/heads/master @@ -0,0 +1,4 @@ +0000000000000000000000000000000000000000 6b31c659545507c381e9cd34ec508f16c04e149e Russell Belfer 1342559662 -0700 commit (initial): Initial commit +6b31c659545507c381e9cd34ec508f16c04e149e 41bd4bc3df978de695f67ace64c560913da11653 Russell Belfer 1342559709 -0700 commit: Adding test file +41bd4bc3df978de695f67ace64c560913da11653 5e4963595a9774b90524d35a807169049de8ccad Russell Belfer 1342559726 -0700 commit: Updating test file +5e4963595a9774b90524d35a807169049de8ccad 480095882d281ed676fe5b863569520e54a7d5c0 Russell Belfer 1342559925 -0700 commit: One more update diff --git a/tests/resources/submod2_target/.gitted/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests/resources/submod2_target/.gitted/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 new file mode 100644 index 000000000..f4b7094c5 Binary files /dev/null and b/tests/resources/submod2_target/.gitted/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 differ diff --git a/tests/resources/submod2_target/.gitted/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests/resources/submod2_target/.gitted/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 new file mode 100644 index 000000000..56c845e49 Binary files /dev/null and b/tests/resources/submod2_target/.gitted/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 differ diff --git a/tests/resources/submod2_target/.gitted/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests/resources/submod2_target/.gitted/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 new file mode 100644 index 000000000..bd179b5f5 Binary files /dev/null and b/tests/resources/submod2_target/.gitted/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 differ diff --git a/tests/resources/submod2_target/.gitted/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests/resources/submod2_target/.gitted/objects/41/bd4bc3df978de695f67ace64c560913da11653 new file mode 100644 index 000000000..ccf49bd15 Binary files /dev/null and b/tests/resources/submod2_target/.gitted/objects/41/bd4bc3df978de695f67ace64c560913da11653 differ diff --git a/tests/resources/submod2_target/.gitted/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests/resources/submod2_target/.gitted/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 new file mode 100644 index 000000000..53029069a Binary files /dev/null and b/tests/resources/submod2_target/.gitted/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 differ diff --git a/tests/resources/submod2_target/.gitted/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests/resources/submod2_target/.gitted/objects/5e/4963595a9774b90524d35a807169049de8ccad new file mode 100644 index 000000000..38c791eba Binary files /dev/null and b/tests/resources/submod2_target/.gitted/objects/5e/4963595a9774b90524d35a807169049de8ccad differ diff --git a/tests/resources/submod2_target/.gitted/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests/resources/submod2_target/.gitted/objects/6b/31c659545507c381e9cd34ec508f16c04e149e new file mode 100644 index 000000000..a26d29993 --- /dev/null +++ b/tests/resources/submod2_target/.gitted/objects/6b/31c659545507c381e9cd34ec508f16c04e149e @@ -0,0 +1,2 @@ +xQ +!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests/resources/submod2_target/.gitted/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests/resources/submod2_target/.gitted/objects/73/ba924a80437097795ae839e66e187c55d3babf new file mode 100644 index 000000000..83d1ba481 Binary files /dev/null and b/tests/resources/submod2_target/.gitted/objects/73/ba924a80437097795ae839e66e187c55d3babf differ diff --git a/tests/resources/submod2_target/.gitted/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests/resources/submod2_target/.gitted/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a new file mode 100644 index 000000000..6d27af8a8 --- /dev/null +++ b/tests/resources/submod2_target/.gitted/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a @@ -0,0 +1,2 @@ +x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x +uxt(+ \ No newline at end of file diff --git a/tests/resources/submod2_target/.gitted/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests/resources/submod2_target/.gitted/objects/78/9efbdadaa4a582778d4584385495559ea0994b new file mode 100644 index 000000000..17458840b --- /dev/null +++ b/tests/resources/submod2_target/.gitted/objects/78/9efbdadaa4a582778d4584385495559ea0994b @@ -0,0 +1,2 @@ +x 0 )?= NlOkj8&r +qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests/resources/submod2_target/.gitted/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests/resources/submod2_target/.gitted/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e new file mode 100644 index 000000000..83cc29fb1 Binary files /dev/null and b/tests/resources/submod2_target/.gitted/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e differ diff --git a/tests/resources/submod2_target/.gitted/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests/resources/submod2_target/.gitted/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 new file mode 100644 index 000000000..55bda40ef Binary files /dev/null and b/tests/resources/submod2_target/.gitted/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 differ diff --git a/tests/resources/submod2_target/.gitted/refs/heads/master b/tests/resources/submod2_target/.gitted/refs/heads/master new file mode 100644 index 000000000..e12c44d7a --- /dev/null +++ b/tests/resources/submod2_target/.gitted/refs/heads/master @@ -0,0 +1 @@ +480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests/resources/submod2_target/README.txt b/tests/resources/submod2_target/README.txt new file mode 100644 index 000000000..780d7397f --- /dev/null +++ b/tests/resources/submod2_target/README.txt @@ -0,0 +1,3 @@ +This is the target for submod2 submodule links. +Don't add commits casually because you make break tests. + diff --git a/tests/resources/submod2_target/file_to_modify b/tests/resources/submod2_target/file_to_modify new file mode 100644 index 000000000..789efbdad --- /dev/null +++ b/tests/resources/submod2_target/file_to_modify @@ -0,0 +1,3 @@ +This is a file to modify in submodules +It already has some history. +You can add local changes as needed. diff --git a/tests/resources/submodules/.gitted/HEAD b/tests/resources/submodules/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/submodules/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/submodules/.gitted/config b/tests/resources/submodules/.gitted/config new file mode 100644 index 000000000..af107929f --- /dev/null +++ b/tests/resources/submodules/.gitted/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true diff --git a/tests/resources/submodules/.gitted/description b/tests/resources/submodules/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/submodules/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/submodules/.gitted/index b/tests/resources/submodules/.gitted/index new file mode 100644 index 000000000..97bf8ef51 Binary files /dev/null and b/tests/resources/submodules/.gitted/index differ diff --git a/tests/resources/submodules/.gitted/info/exclude b/tests/resources/submodules/.gitted/info/exclude new file mode 100644 index 000000000..dfc411579 --- /dev/null +++ b/tests/resources/submodules/.gitted/info/exclude @@ -0,0 +1,8 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ +ignored + diff --git a/tests/resources/submodules/.gitted/info/refs b/tests/resources/submodules/.gitted/info/refs new file mode 100644 index 000000000..ba17abdde --- /dev/null +++ b/tests/resources/submodules/.gitted/info/refs @@ -0,0 +1 @@ +09176a980273d801a3e37cc45c84af1366501ed9 refs/heads/master diff --git a/tests/resources/submodules/.gitted/logs/HEAD b/tests/resources/submodules/.gitted/logs/HEAD new file mode 100644 index 000000000..87a7bdafc --- /dev/null +++ b/tests/resources/submodules/.gitted/logs/HEAD @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 09176a980273d801a3e37cc45c84af1366501ed9 Russell Belfer 1332365253 -0700 commit (initial): initial commit +09176a980273d801a3e37cc45c84af1366501ed9 97896810b3210244a62a82458b8e0819ecfc6850 Russell Belfer 1332780781 -0700 commit: Setting up gitmodules diff --git a/tests/resources/submodules/.gitted/logs/refs/heads/master b/tests/resources/submodules/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..87a7bdafc --- /dev/null +++ b/tests/resources/submodules/.gitted/logs/refs/heads/master @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 09176a980273d801a3e37cc45c84af1366501ed9 Russell Belfer 1332365253 -0700 commit (initial): initial commit +09176a980273d801a3e37cc45c84af1366501ed9 97896810b3210244a62a82458b8e0819ecfc6850 Russell Belfer 1332780781 -0700 commit: Setting up gitmodules diff --git a/tests/resources/submodules/.gitted/objects/26/a3b32a9b7d97486c5557f5902e8ac94638145e b/tests/resources/submodules/.gitted/objects/26/a3b32a9b7d97486c5557f5902e8ac94638145e new file mode 100644 index 000000000..2c3c2cb61 --- /dev/null +++ b/tests/resources/submodules/.gitted/objects/26/a3b32a9b7d97486c5557f5902e8ac94638145e @@ -0,0 +1,2 @@ +x%= +0 F])0"I*|-t{?2ilV8$mvkk*F DA=(=|=6 DAv=A}&'O$= \ No newline at end of file diff --git a/tests/resources/submodules/.gitted/objects/78/308c9251cf4eee8b25a76c7d2790c73d797357 b/tests/resources/submodules/.gitted/objects/78/308c9251cf4eee8b25a76c7d2790c73d797357 new file mode 100644 index 000000000..c85fb5512 Binary files /dev/null and b/tests/resources/submodules/.gitted/objects/78/308c9251cf4eee8b25a76c7d2790c73d797357 differ diff --git a/tests/resources/submodules/.gitted/objects/97/896810b3210244a62a82458b8e0819ecfc6850 b/tests/resources/submodules/.gitted/objects/97/896810b3210244a62a82458b8e0819ecfc6850 new file mode 100644 index 000000000..1c8dbdf9f --- /dev/null +++ b/tests/resources/submodules/.gitted/objects/97/896810b3210244a62a82458b8e0819ecfc6850 @@ -0,0 +1,3 @@ +x[ +0E*fʤS K4ݿwׅ9p2MCFP @u..p!OYdiYU'̕8XbPn6 +ħԞ1[q}0qc[W#1fR:SZ+Y+{tdlvOmu_}5i` K \ No newline at end of file diff --git a/tests/resources/submodules/.gitted/objects/b6/0fd986699ba4e9e68bea07cf8e793f323ef888 b/tests/resources/submodules/.gitted/objects/b6/0fd986699ba4e9e68bea07cf8e793f323ef888 new file mode 100644 index 000000000..3d78bd6be Binary files /dev/null and b/tests/resources/submodules/.gitted/objects/b6/0fd986699ba4e9e68bea07cf8e793f323ef888 differ diff --git a/tests/resources/submodules/.gitted/objects/d5/f7fc3f74f7dec08280f370a975b112e8f60818 b/tests/resources/submodules/.gitted/objects/d5/f7fc3f74f7dec08280f370a975b112e8f60818 new file mode 100644 index 000000000..6e0b49e86 Binary files /dev/null and b/tests/resources/submodules/.gitted/objects/d5/f7fc3f74f7dec08280f370a975b112e8f60818 differ diff --git a/tests/resources/submodules/.gitted/objects/e3/50052cc767cd1fcb37e84e9a89e701925be4ae b/tests/resources/submodules/.gitted/objects/e3/50052cc767cd1fcb37e84e9a89e701925be4ae new file mode 100644 index 000000000..082a58941 Binary files /dev/null and b/tests/resources/submodules/.gitted/objects/e3/50052cc767cd1fcb37e84e9a89e701925be4ae differ diff --git a/tests/resources/submodules/.gitted/objects/info/packs b/tests/resources/submodules/.gitted/objects/info/packs new file mode 100644 index 000000000..0785ef698 --- /dev/null +++ b/tests/resources/submodules/.gitted/objects/info/packs @@ -0,0 +1,2 @@ +P pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack + diff --git a/tests/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx b/tests/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx new file mode 100644 index 000000000..810fc3181 Binary files /dev/null and b/tests/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.idx differ diff --git a/tests/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack b/tests/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack new file mode 100644 index 000000000..c25c4a73f Binary files /dev/null and b/tests/resources/submodules/.gitted/objects/pack/pack-b69d04bb39ac274669e2184e45bd90015d02ef5b.pack differ diff --git a/tests/resources/submodules/.gitted/packed-refs b/tests/resources/submodules/.gitted/packed-refs new file mode 100644 index 000000000..a6450691e --- /dev/null +++ b/tests/resources/submodules/.gitted/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +09176a980273d801a3e37cc45c84af1366501ed9 refs/heads/master diff --git a/tests/resources/submodules/.gitted/refs/heads/master b/tests/resources/submodules/.gitted/refs/heads/master new file mode 100644 index 000000000..32b935853 --- /dev/null +++ b/tests/resources/submodules/.gitted/refs/heads/master @@ -0,0 +1 @@ +97896810b3210244a62a82458b8e0819ecfc6850 diff --git a/tests/resources/submodules/added b/tests/resources/submodules/added new file mode 100644 index 000000000..d5f7fc3f7 --- /dev/null +++ b/tests/resources/submodules/added @@ -0,0 +1 @@ +added diff --git a/tests/resources/submodules/gitmodules b/tests/resources/submodules/gitmodules new file mode 100644 index 000000000..2798b696c --- /dev/null +++ b/tests/resources/submodules/gitmodules @@ -0,0 +1,6 @@ +[submodule "testrepo"] + path = testrepo + url = +[submodule ""] + path = testrepo + url = \ No newline at end of file diff --git a/tests/resources/submodules/ignored b/tests/resources/submodules/ignored new file mode 100644 index 000000000..092bfb9bd --- /dev/null +++ b/tests/resources/submodules/ignored @@ -0,0 +1 @@ +yo diff --git a/tests/resources/submodules/modified b/tests/resources/submodules/modified new file mode 100644 index 000000000..452216e1d --- /dev/null +++ b/tests/resources/submodules/modified @@ -0,0 +1,2 @@ +changed + diff --git a/tests/resources/submodules/testrepo/.gitted/HEAD b/tests/resources/submodules/testrepo/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/submodules/testrepo/.gitted/config b/tests/resources/submodules/testrepo/.gitted/config new file mode 100644 index 000000000..d6dcad12b --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/config @@ -0,0 +1,12 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = /Users/rb/src/libgit2/tests/resources/testrepo.git +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/tests/resources/submodules/testrepo/.gitted/description b/tests/resources/submodules/testrepo/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/submodules/testrepo/.gitted/index b/tests/resources/submodules/testrepo/.gitted/index new file mode 100644 index 000000000..3eb8d84fe Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/index differ diff --git a/tests/resources/submodules/testrepo/.gitted/info/exclude b/tests/resources/submodules/testrepo/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/submodules/testrepo/.gitted/logs/HEAD b/tests/resources/submodules/testrepo/.gitted/logs/HEAD new file mode 100644 index 000000000..147643a30 --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Russell Belfer 1332366307 -0700 clone: from /Users/rb/src/libgit2/tests/resources/testrepo.git diff --git a/tests/resources/submodules/testrepo/.gitted/logs/refs/heads/master b/tests/resources/submodules/testrepo/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..147643a30 --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Russell Belfer 1332366307 -0700 clone: from /Users/rb/src/libgit2/tests/resources/testrepo.git diff --git a/tests/resources/submodules/testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 b/tests/resources/submodules/testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 new file mode 100644 index 000000000..cedb2a22e Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 b/tests/resources/submodules/testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 new file mode 100644 index 000000000..93a16f146 Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd b/tests/resources/submodules/testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd new file mode 100644 index 000000000..ba0bfb30c Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b b/tests/resources/submodules/testrepo/.gitted/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b new file mode 100644 index 000000000..225c45734 Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d b/tests/resources/submodules/testrepo/.gitted/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d new file mode 100644 index 000000000..df40d99af Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 b/tests/resources/submodules/testrepo/.gitted/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 new file mode 100644 index 000000000..321eaa867 Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc b/tests/resources/submodules/testrepo/.gitted/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc new file mode 100644 index 000000000..9bb5b623b Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests/resources/submodules/testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 new file mode 100644 index 000000000..7ca4ceed5 Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 b/tests/resources/submodules/testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 new file mode 100644 index 000000000..8953b6cef --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 @@ -0,0 +1,2 @@ +xQ +0D)6ͦ "xO-FbEo0 Ǥ,ske[Pn8R,EpD?g}^3 <GhYK8ЖDA);gݧjp4-r;sGA4ۺ=(in7IKFE \ No newline at end of file diff --git a/tests/resources/submodules/testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 b/tests/resources/submodules/testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 new file mode 100644 index 000000000..c1f22c54f --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 @@ -0,0 +1,2 @@ +x 1ENi@k2 "X$YW0YcÅszMD08!s Xgd::@X0Pw"F/RUzmZZV}|/o5I!1z:vUim}/> +F- \ No newline at end of file diff --git a/tests/resources/submodules/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests/resources/submodules/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a new file mode 100644 index 000000000..2ef4faa0f Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af b/tests/resources/submodules/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af new file mode 100644 index 000000000..716b0c64b --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af @@ -0,0 +1 @@ +xAj!?009o}H6}jUPPZ&Y AԛpFdpz[fYPqLJ.,Z`Ů.`v q $5+9Ot>/DE/龡W*eVdf1>覭ěʙFThk.i^0?PR, \ No newline at end of file diff --git a/tests/resources/submodules/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 b/tests/resources/submodules/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 new file mode 100644 index 000000000..23c462f34 Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests/resources/submodules/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d new file mode 100644 index 000000000..2f9b6b6e3 Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests/resources/submodules/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 new file mode 100644 index 000000000..5df58dda5 Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 b/tests/resources/submodules/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 new file mode 100644 index 000000000..4cc3f4dff --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 @@ -0,0 +1 @@ +x+)JMU044b040031QrutueXlmmAṃJ}G;UTWRQ`6Kǥ^/-*|W3Py`%E\&g|0{Ӎ1X \ No newline at end of file diff --git a/tests/resources/submodules/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 b/tests/resources/submodules/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 new file mode 100644 index 000000000..bf7b2bb68 Binary files /dev/null and b/tests/resources/submodules/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 differ diff --git a/tests/resources/submodules/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests/resources/submodules/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a new file mode 100644 index 000000000..a79612435 --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a @@ -0,0 +1,3 @@ +x[ +0E*fդ "W0-Ft݁pS[Yx^ +Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests/resources/submodules/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests/resources/submodules/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f new file mode 100644 index 000000000..f8588696b --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f @@ -0,0 +1,2 @@ +x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S + U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests/resources/submodules/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 b/tests/resources/submodules/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 new file mode 100644 index 000000000..29c8e824d --- /dev/null +++ b/tests/resources/submodules/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 @@ -0,0 +1,3 @@ +xQ +!@sBQ" ٱ r{ 1335806563 -0700 clone: from /Users/ben/src/libgit2/tests/resources/testrepo.git +be3563ae3f795b2b4353bcce3a527ad0a4f7f644 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub 1335806603 -0900 commit: +a65fedf39aefe402d3bb6e24df4d4f5fe4547750 5b5b025afb0b4c913b4c338a42934a3863bf3644 Ben Straub 1335806604 -0900 checkout: moving from master to 5b5b025 +5b5b025afb0b4c913b4c338a42934a3863bf3644 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub 1335806605 -0900 checkout: moving from 5b5b025 to master +a65fedf39aefe402d3bb6e24df4d4f5fe4547750 c47800c7266a2be04c571c04d5a6614691ea99bd Ben Straub 1335806608 -0900 checkout: moving from master to br2 +c47800c7266a2be04c571c04d5a6614691ea99bd a4a7dce85cf63874e984719f4fdd239f5145052f Ben Straub 1335806617 -0900 commit: checking in +a4a7dce85cf63874e984719f4fdd239f5145052f a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub 1335806621 -0900 checkout: moving from br2 to master diff --git a/tests/resources/testrepo.git/logs/refs/heads/br2 b/tests/resources/testrepo.git/logs/refs/heads/br2 new file mode 100644 index 000000000..4e27f6b8d --- /dev/null +++ b/tests/resources/testrepo.git/logs/refs/heads/br2 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 c47800c7266a2be04c571c04d5a6614691ea99bd Ben Straub 1335806608 -0700 branch: Created from refs/remotes/origin/br2 +a4a7dce85cf63874e984719f4fdd239f5145052f a4a7dce85cf63874e984719f4fdd239f5145052f Ben Straub 1335806617 -0700 commit: checking in diff --git a/tests/resources/testrepo.git/logs/refs/heads/master b/tests/resources/testrepo.git/logs/refs/heads/master new file mode 100644 index 000000000..e1c729a45 --- /dev/null +++ b/tests/resources/testrepo.git/logs/refs/heads/master @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 be3563ae3f795b2b4353bcce3a527ad0a4f7f644 Ben Straub 1335806563 -0800 clone: from /Users/ben/src/libgit2/tests/resources/testrepo.git +be3563ae3f795b2b4353bcce3a527ad0a4f7f644 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub 1335806603 -0800 commit: checking in diff --git a/tests/resources/testrepo.git/logs/refs/heads/not-good b/tests/resources/testrepo.git/logs/refs/heads/not-good new file mode 100644 index 000000000..bfbeacb8a --- /dev/null +++ b/tests/resources/testrepo.git/logs/refs/heads/not-good @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub 1336761944 -0700 branch: Created from master diff --git a/tests/resources/testrepo.git/logs/refs/remotes/origin/HEAD b/tests/resources/testrepo.git/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..f1aac6d0f --- /dev/null +++ b/tests/resources/testrepo.git/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 be3563ae3f795b2b4353bcce3a527ad0a4f7f644 Ben Straub 1335806563 -0700 clone: from /Users/ben/src/libgit2/tests/resources/testrepo.git diff --git a/tests/resources/testrepo.git/logs/refs/remotes/test/master b/tests/resources/testrepo.git/logs/refs/remotes/test/master new file mode 100644 index 000000000..8d49ba3e0 --- /dev/null +++ b/tests/resources/testrepo.git/logs/refs/remotes/test/master @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 a65fedf39aefe402d3bb6e24df4d4f5fe4547750 Ben Straub 1335806565 -0800 update by push +a65fedf39aefe402d3bb6e24df4d4f5fe4547750 be3563ae3f795b2b4353bcce3a527ad0a4f7f644 Ben Straub 1335806688 -0800 update by push diff --git a/tests/resources/testrepo.git/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 b/tests/resources/testrepo.git/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 new file mode 100644 index 000000000..d1c032fce Binary files /dev/null and b/tests/resources/testrepo.git/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 differ diff --git a/tests/resources/testrepo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 b/tests/resources/testrepo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 new file mode 100644 index 000000000..cedb2a22e Binary files /dev/null and b/tests/resources/testrepo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 differ diff --git a/tests/resources/testrepo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 b/tests/resources/testrepo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 new file mode 100644 index 000000000..93a16f146 Binary files /dev/null and b/tests/resources/testrepo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 differ diff --git a/tests/resources/testrepo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd b/tests/resources/testrepo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd new file mode 100644 index 000000000..ba0bfb30c Binary files /dev/null and b/tests/resources/testrepo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd differ diff --git a/tests/resources/testrepo.git/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd b/tests/resources/testrepo.git/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd new file mode 100644 index 000000000..3ec541288 Binary files /dev/null and b/tests/resources/testrepo.git/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd differ diff --git a/tests/resources/testrepo.git/objects/1b/8cbad43e867676df601306689fe7c3def5e689 b/tests/resources/testrepo.git/objects/1b/8cbad43e867676df601306689fe7c3def5e689 new file mode 100644 index 000000000..6048d4bad Binary files /dev/null and b/tests/resources/testrepo.git/objects/1b/8cbad43e867676df601306689fe7c3def5e689 differ diff --git a/tests/resources/testrepo.git/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b b/tests/resources/testrepo.git/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b new file mode 100644 index 000000000..225c45734 Binary files /dev/null and b/tests/resources/testrepo.git/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b differ diff --git a/tests/resources/testrepo.git/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 b/tests/resources/testrepo.git/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 new file mode 100644 index 000000000..cb1ed5712 Binary files /dev/null and b/tests/resources/testrepo.git/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 differ diff --git a/tests/resources/testrepo.git/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d b/tests/resources/testrepo.git/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d new file mode 100644 index 000000000..df40d99af Binary files /dev/null and b/tests/resources/testrepo.git/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d differ diff --git a/tests/resources/testrepo.git/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 b/tests/resources/testrepo.git/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 new file mode 100644 index 000000000..0a1500a6f Binary files /dev/null and b/tests/resources/testrepo.git/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 differ diff --git a/tests/resources/testrepo.git/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 b/tests/resources/testrepo.git/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 new file mode 100644 index 000000000..321eaa867 Binary files /dev/null and b/tests/resources/testrepo.git/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 differ diff --git a/tests/resources/testrepo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc b/tests/resources/testrepo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc new file mode 100644 index 000000000..9bb5b623b Binary files /dev/null and b/tests/resources/testrepo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc differ diff --git a/tests/resources/testrepo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests/resources/testrepo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 new file mode 100644 index 000000000..7ca4ceed5 Binary files /dev/null and b/tests/resources/testrepo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 differ diff --git a/tests/resources/testrepo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 b/tests/resources/testrepo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 new file mode 100644 index 000000000..8953b6cef --- /dev/null +++ b/tests/resources/testrepo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 @@ -0,0 +1,2 @@ +xQ +0D)6ͦ "xO-FbEo0 Ǥ,ske[Pn8R,EpD?g}^3 <GhYK8ЖDA);gݧjp4-r;sGA4ۺ=(in7IKFE \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/4a/23e2e65ad4e31c4c9db7dc746650bfad082679 b/tests/resources/testrepo.git/objects/4a/23e2e65ad4e31c4c9db7dc746650bfad082679 new file mode 100644 index 000000000..18e3964b3 Binary files /dev/null and b/tests/resources/testrepo.git/objects/4a/23e2e65ad4e31c4c9db7dc746650bfad082679 differ diff --git a/tests/resources/testrepo.git/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea b/tests/resources/testrepo.git/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea new file mode 100644 index 000000000..b4e5aa186 Binary files /dev/null and b/tests/resources/testrepo.git/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea differ diff --git a/tests/resources/testrepo.git/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 b/tests/resources/testrepo.git/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 new file mode 100644 index 000000000..351cff823 Binary files /dev/null and b/tests/resources/testrepo.git/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 differ diff --git a/tests/resources/testrepo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 b/tests/resources/testrepo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 new file mode 100644 index 000000000..c1f22c54f --- /dev/null +++ b/tests/resources/testrepo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 @@ -0,0 +1,2 @@ +x 1ENi@k2 "X$YW0YcÅszMD08!s Xgd::@X0Pw"F/RUzmZZV}|/o5I!1z:vUim}/> +F- \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests/resources/testrepo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a new file mode 100644 index 000000000..2ef4faa0f Binary files /dev/null and b/tests/resources/testrepo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a differ diff --git a/tests/resources/testrepo.git/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af b/tests/resources/testrepo.git/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af new file mode 100644 index 000000000..716b0c64b --- /dev/null +++ b/tests/resources/testrepo.git/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af @@ -0,0 +1 @@ +xAj!?009o}H6}jUPPZ&Y AԛpFdpz[fYPqLJ.,Z`Ů.`v q $5+9Ot>/DE/龡W*eVdf1>覭ěʙFThk.i^0?PR, \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/7b/4384978d2493e851f9cca7858815fac9b10980 b/tests/resources/testrepo.git/objects/7b/4384978d2493e851f9cca7858815fac9b10980 new file mode 100644 index 000000000..23c462f34 Binary files /dev/null and b/tests/resources/testrepo.git/objects/7b/4384978d2493e851f9cca7858815fac9b10980 differ diff --git a/tests/resources/testrepo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests/resources/testrepo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d new file mode 100644 index 000000000..2f9b6b6e3 Binary files /dev/null and b/tests/resources/testrepo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d differ diff --git a/tests/resources/testrepo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests/resources/testrepo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 new file mode 100644 index 000000000..5df58dda5 Binary files /dev/null and b/tests/resources/testrepo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 differ diff --git a/tests/resources/testrepo.git/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe b/tests/resources/testrepo.git/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe new file mode 100644 index 000000000..71019a636 --- /dev/null +++ b/tests/resources/testrepo.git/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe @@ -0,0 +1,2 @@ +xM F]s41x(IKݽ/_P@!8)es + N&FGSƄh{+CZzvF7Z-kx\[P8GK/^ l>.4 \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 b/tests/resources/testrepo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 new file mode 100644 index 000000000..4cc3f4dff --- /dev/null +++ b/tests/resources/testrepo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 @@ -0,0 +1 @@ +x+)JMU044b040031QrutueXlmmAṃJ}G;UTWRQ`6Kǥ^/-*|W3Py`%E\&g|0{Ӎ1X \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 b/tests/resources/testrepo.git/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 new file mode 100644 index 000000000..bf7b2bb68 Binary files /dev/null and b/tests/resources/testrepo.git/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 differ diff --git a/tests/resources/testrepo.git/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 b/tests/resources/testrepo.git/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 new file mode 100644 index 000000000..7f1cfb23c --- /dev/null +++ b/tests/resources/testrepo.git/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 @@ -0,0 +1,2 @@ +xM +0F]d2;XEȎ5R AE &n}ZA \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests/resources/testrepo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a new file mode 100644 index 000000000..a79612435 --- /dev/null +++ b/tests/resources/testrepo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a @@ -0,0 +1,3 @@ +x[ +0E*fդ "W0-Ft݁pS[Yx^ +Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests/resources/testrepo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f new file mode 100644 index 000000000..f8588696b --- /dev/null +++ b/tests/resources/testrepo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f @@ -0,0 +1,2 @@ +x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S + U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests/resources/testrepo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 b/tests/resources/testrepo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 new file mode 100644 index 000000000..29c8e824d --- /dev/null +++ b/tests/resources/testrepo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 @@ -0,0 +1,3 @@ +xQ +!@sBQ" ٱ r{ +F- \ No newline at end of file diff --git a/tests/resources/testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc b/tests/resources/testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc new file mode 100644 index 000000000..b669961d8 Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc differ diff --git a/tests/resources/testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 b/tests/resources/testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 new file mode 100644 index 000000000..9ff5eb2b5 Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 differ diff --git a/tests/resources/testrepo/.gitted/objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 b/tests/resources/testrepo/.gitted/objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 new file mode 100644 index 000000000..ee7c78174 Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/6b/377958d8c6a4906e8573b53672a1a23a4e8ce6 differ diff --git a/tests/resources/testrepo/.gitted/objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e b/tests/resources/testrepo/.gitted/objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e new file mode 100644 index 000000000..197685b86 Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/6b/9b767af9992b4abad5e24ffb1ba2d688ca602e differ diff --git a/tests/resources/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests/resources/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a new file mode 100644 index 000000000..2ef4faa0f Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a differ diff --git a/tests/resources/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af b/tests/resources/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af new file mode 100644 index 000000000..716b0c64b --- /dev/null +++ b/tests/resources/testrepo/.gitted/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af @@ -0,0 +1 @@ +xAj!?009o}H6}jUPPZ&Y AԛpFdpz[fYPqLJ.,Z`Ů.`v q $5+9Ot>/DE/龡W*eVdf1>覭ěʙFThk.i^0?PR, \ No newline at end of file diff --git a/tests/resources/testrepo/.gitted/objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a b/tests/resources/testrepo/.gitted/objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a new file mode 100644 index 000000000..db778aaae Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/7b/2417a23b63e1fdde88c80e14b33247c6e5785a differ diff --git a/tests/resources/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 b/tests/resources/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 new file mode 100644 index 000000000..23c462f34 Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/7b/4384978d2493e851f9cca7858815fac9b10980 differ diff --git a/tests/resources/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests/resources/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d new file mode 100644 index 000000000..2f9b6b6e3 Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d differ diff --git a/tests/resources/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests/resources/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 new file mode 100644 index 000000000..5df58dda5 Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 differ diff --git a/tests/resources/testrepo/.gitted/objects/87/380ae84009e9c503506c2f6143a4fc6c60bf80 b/tests/resources/testrepo/.gitted/objects/87/380ae84009e9c503506c2f6143a4fc6c60bf80 new file mode 100644 index 000000000..3042f5790 Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/87/380ae84009e9c503506c2f6143a4fc6c60bf80 differ diff --git a/tests/resources/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 b/tests/resources/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 new file mode 100644 index 000000000..4cc3f4dff --- /dev/null +++ b/tests/resources/testrepo/.gitted/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 @@ -0,0 +1 @@ +x+)JMU044b040031QrutueXlmmAṃJ}G;UTWRQ`6Kǥ^/-*|W3Py`%E\&g|0{Ӎ1X \ No newline at end of file diff --git a/tests/resources/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 b/tests/resources/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 new file mode 100644 index 000000000..bf7b2bb68 Binary files /dev/null and b/tests/resources/testrepo/.gitted/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 differ diff --git a/tests/resources/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests/resources/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a new file mode 100644 index 000000000..a79612435 --- /dev/null +++ b/tests/resources/testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a @@ -0,0 +1,3 @@ +x[ +0E*fդ "W0-Ft݁pS[Yx^ +Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests/resources/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests/resources/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f new file mode 100644 index 000000000..f8588696b --- /dev/null +++ b/tests/resources/testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f @@ -0,0 +1,2 @@ +x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S + U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests/resources/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 b/tests/resources/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 new file mode 100644 index 000000000..29c8e824d --- /dev/null +++ b/tests/resources/testrepo/.gitted/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 @@ -0,0 +1,3 @@ +xQ +!@sBQ" ٱ r{ 1368278260 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/../../../rugged/test/fixtures/testrepo.git diff --git a/tests/resources/testrepo2/.gitted/logs/refs/heads/master b/tests/resources/testrepo2/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..4e80c69fa --- /dev/null +++ b/tests/resources/testrepo2/.gitted/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 36060c58702ed4c2a40832c51758d5344201d89a Russell Belfer 1368278260 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/../../../rugged/test/fixtures/testrepo.git diff --git a/tests/resources/testrepo2/.gitted/logs/refs/remotes/origin/HEAD b/tests/resources/testrepo2/.gitted/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..4e80c69fa --- /dev/null +++ b/tests/resources/testrepo2/.gitted/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 36060c58702ed4c2a40832c51758d5344201d89a Russell Belfer 1368278260 -0700 clone: from /Users/rb/src/libgit2/tests-clar/resources/../../../rugged/test/fixtures/testrepo.git diff --git a/tests/resources/testrepo2/.gitted/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d b/tests/resources/testrepo2/.gitted/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d new file mode 100644 index 000000000..bfe146a5a Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d differ diff --git a/tests/resources/testrepo2/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 b/tests/resources/testrepo2/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 new file mode 100644 index 000000000..cedb2a22e Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 differ diff --git a/tests/resources/testrepo2/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 b/tests/resources/testrepo2/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 new file mode 100644 index 000000000..93a16f146 Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 differ diff --git a/tests/resources/testrepo2/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd b/tests/resources/testrepo2/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd new file mode 100644 index 000000000..ba0bfb30c Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd differ diff --git a/tests/resources/testrepo2/.gitted/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 b/tests/resources/testrepo2/.gitted/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 new file mode 100644 index 000000000..3cd240db5 Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 differ diff --git a/tests/resources/testrepo2/.gitted/objects/36/060c58702ed4c2a40832c51758d5344201d89a b/tests/resources/testrepo2/.gitted/objects/36/060c58702ed4c2a40832c51758d5344201d89a new file mode 100644 index 000000000..0c6246061 --- /dev/null +++ b/tests/resources/testrepo2/.gitted/objects/36/060c58702ed4c2a40832c51758d5344201d89a @@ -0,0 +1,2 @@ +xQ +0)reݴ $ۭ-F-00𸖲?iL#HSS#q2D據jC|HSL8$)a#2i׹6js?JZftΞUiͶqiZ"_/H6 \ No newline at end of file diff --git a/tests/resources/testrepo2/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests/resources/testrepo2/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 new file mode 100644 index 000000000..7ca4ceed5 Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 differ diff --git a/tests/resources/testrepo2/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 b/tests/resources/testrepo2/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 new file mode 100644 index 000000000..8953b6cef --- /dev/null +++ b/tests/resources/testrepo2/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 @@ -0,0 +1,2 @@ +xQ +0D)6ͦ "xO-FbEo0 Ǥ,ske[Pn8R,EpD?g}^3 <GhYK8ЖDA);gݧjp4-r;sGA4ۺ=(in7IKFE \ No newline at end of file diff --git a/tests/resources/testrepo2/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 b/tests/resources/testrepo2/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 new file mode 100644 index 000000000..c1f22c54f --- /dev/null +++ b/tests/resources/testrepo2/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 @@ -0,0 +1,2 @@ +x 1ENi@k2 "X$YW0YcÅszMD08!s Xgd::@X0Pw"F/RUzmZZV}|/o5I!1z:vUim}/> +F- \ No newline at end of file diff --git a/tests/resources/testrepo2/.gitted/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 b/tests/resources/testrepo2/.gitted/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 new file mode 100644 index 000000000..1fd79b477 Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 differ diff --git a/tests/resources/testrepo2/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a b/tests/resources/testrepo2/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a new file mode 100644 index 000000000..2ef4faa0f Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a differ diff --git a/tests/resources/testrepo2/.gitted/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 b/tests/resources/testrepo2/.gitted/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 new file mode 100644 index 000000000..3d1016daa Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 differ diff --git a/tests/resources/testrepo2/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests/resources/testrepo2/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d new file mode 100644 index 000000000..2f9b6b6e3 Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d differ diff --git a/tests/resources/testrepo2/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests/resources/testrepo2/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 new file mode 100644 index 000000000..5df58dda5 Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 differ diff --git a/tests/resources/testrepo2/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests/resources/testrepo2/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a new file mode 100644 index 000000000..a79612435 --- /dev/null +++ b/tests/resources/testrepo2/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a @@ -0,0 +1,3 @@ +x[ +0E*fդ "W0-Ft݁pS[Yx^ +Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests/resources/testrepo2/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests/resources/testrepo2/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f new file mode 100644 index 000000000..f8588696b --- /dev/null +++ b/tests/resources/testrepo2/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f @@ -0,0 +1,2 @@ +x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S + U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests/resources/testrepo2/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd b/tests/resources/testrepo2/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd new file mode 100644 index 000000000..d0d7e736e Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd differ diff --git a/tests/resources/testrepo2/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 b/tests/resources/testrepo2/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 new file mode 100644 index 000000000..18a7f61c2 Binary files /dev/null and b/tests/resources/testrepo2/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 differ diff --git a/tests/resources/testrepo2/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 b/tests/resources/testrepo2/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 new file mode 100644 index 000000000..0817229bc --- /dev/null +++ b/tests/resources/testrepo2/.gitted/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 @@ -0,0 +1,3 @@ +xKj1D)zUB-0uV9<#+WTKy4`6 ,y9jGJ8b\f5/ ^8v'˜`SƝ%[ +T[[,psL6oK5;n-=D \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/1f/4c0311a24b63f6fc209a59a1e404942d4a5006 b/tests/resources/twowaymerge.git/objects/1f/4c0311a24b63f6fc209a59a1e404942d4a5006 new file mode 100644 index 000000000..99288fdd7 --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/1f/4c0311a24b63f6fc209a59a1e404942d4a5006 @@ -0,0 +1,2 @@ +x=0 @aM6BlH m!RqO7[ r5gNXű)Eg]DY2c R8x7 +TRo8~Ӣ[#uj;`7 \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 b/tests/resources/twowaymerge.git/objects/22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 new file mode 100644 index 000000000..48466ea51 --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/22/24e191514cb4bd8c566d80dac22dfcb1e9bb83 @@ -0,0 +1,3 @@ +xK +0@]sK& z4HMobY1t[JblɈ4vɡL '՛V`B . +Im 1ZǠxcKh^^+\>?2a.M,tTBp^kucjV_sFh \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/29/6e56023cdc034d2735fee8c0d85a659d1b07f4 b/tests/resources/twowaymerge.git/objects/29/6e56023cdc034d2735fee8c0d85a659d1b07f4 new file mode 100644 index 000000000..aa3fccdf0 Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/29/6e56023cdc034d2735fee8c0d85a659d1b07f4 differ diff --git a/tests/resources/twowaymerge.git/objects/31/51880ae2b363f1c262cf98b750c1f169a0d432 b/tests/resources/twowaymerge.git/objects/31/51880ae2b363f1c262cf98b750c1f169a0d432 new file mode 100644 index 000000000..235d42bff Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/31/51880ae2b363f1c262cf98b750c1f169a0d432 differ diff --git a/tests/resources/twowaymerge.git/objects/3b/287f8730c81d0b763c2d294618a5e32b67b4f8 b/tests/resources/twowaymerge.git/objects/3b/287f8730c81d0b763c2d294618a5e32b67b4f8 new file mode 100644 index 000000000..56ddac5ee Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/3b/287f8730c81d0b763c2d294618a5e32b67b4f8 differ diff --git a/tests/resources/twowaymerge.git/objects/42/b7311aa626e712891940c1ec5d5cba201946a4 b/tests/resources/twowaymerge.git/objects/42/b7311aa626e712891940c1ec5d5cba201946a4 new file mode 100644 index 000000000..a8e6581f8 --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/42/b7311aa626e712891940c1ec5d5cba201946a4 @@ -0,0 +1,3 @@ +xν 0@ajOq c"!DDK1 +h_ZʣAC[saȞpI#lBq׼4Z"(yGFd#y[ +X[[J/psL6oAXሂo7ԸEc \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/49/6d6428b9cf92981dc9495211e6e1120fb6f2ba b/tests/resources/twowaymerge.git/objects/49/6d6428b9cf92981dc9495211e6e1120fb6f2ba new file mode 100644 index 000000000..978bc3448 Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/49/6d6428b9cf92981dc9495211e6e1120fb6f2ba differ diff --git a/tests/resources/twowaymerge.git/objects/59/b0cf7d74659e1cdb13305319d6d4ce2733c118 b/tests/resources/twowaymerge.git/objects/59/b0cf7d74659e1cdb13305319d6d4ce2733c118 new file mode 100644 index 000000000..30b507c06 Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/59/b0cf7d74659e1cdb13305319d6d4ce2733c118 differ diff --git a/tests/resources/twowaymerge.git/objects/6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f b/tests/resources/twowaymerge.git/objects/6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f new file mode 100644 index 000000000..ff6a386ac --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/6a/b5d28acbf3c3bdff276f7ccfdf29c1520e542f @@ -0,0 +1 @@ +xM0@a=\@2cܙeRܾŗǵRԶ@(i$uO 19Ro" 9x- @cc3;-KvH+9Fe{O{]b +\>oܦ}踖+Hm z(zl7 F- \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 b/tests/resources/twowaymerge.git/objects/6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 new file mode 100644 index 000000000..9a969a279 Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/6c/fca542b55b8b37017e6125a4b8f59a6eae6f11 differ diff --git a/tests/resources/twowaymerge.git/objects/76/5b32c65d38f04c4f287abda055818ec0f26912 b/tests/resources/twowaymerge.git/objects/76/5b32c65d38f04c4f287abda055818ec0f26912 new file mode 100644 index 000000000..493bbc076 Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/76/5b32c65d38f04c4f287abda055818ec0f26912 differ diff --git a/tests/resources/twowaymerge.git/objects/7b/8c336c45fc6895c1c60827260fe5d798e5d247 b/tests/resources/twowaymerge.git/objects/7b/8c336c45fc6895c1c60827260fe5d798e5d247 new file mode 100644 index 000000000..19e7ef463 --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/7b/8c336c45fc6895c1c60827260fe5d798e5d247 @@ -0,0 +1,3 @@ +xA @Qלb.`3 S(1LzB[TzܾϏe +D|kJC3fȵu L>YGMVeMK9Z5H#{EJ: +ϲp:ne>6-sH GծfMS}ZE \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/82/bf9a1a10a4b25c1f14c9607b60970705e92545 b/tests/resources/twowaymerge.git/objects/82/bf9a1a10a4b25c1f14c9607b60970705e92545 new file mode 100644 index 000000000..89b0b9f9b --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/82/bf9a1a10a4b25c1f14c9607b60970705e92545 @@ -0,0 +1 @@ +x 09mh_BܐRןc1-pyPKy4RږDGFJvFE>1#q joimbvSYSbErQ"e{+ޖ=6b+>?/-;3hC#gXyF \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 b/tests/resources/twowaymerge.git/objects/8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 new file mode 100644 index 000000000..8e9b758ea --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/8b/82fb1794cb1c8c7f172ec730a4c2db0ae3e650 @@ -0,0 +1,3 @@ +xν 0@ajOq 7BtHLp%A8FٟW<= x"ʎ$%1dcDNL:Yv=7yic +l$\b{DbOd9x+ +6T[{ ??yqnӖ:cQZ]͖7H \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/9a/40a2f11c191f180c47e54b11567cb3c1e89b30 b/tests/resources/twowaymerge.git/objects/9a/40a2f11c191f180c47e54b11567cb3c1e89b30 new file mode 100644 index 000000000..1de1224f7 Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/9a/40a2f11c191f180c47e54b11567cb3c1e89b30 differ diff --git a/tests/resources/twowaymerge.git/objects/9b/219343610c88a1187c996d0dc58330b55cee28 b/tests/resources/twowaymerge.git/objects/9b/219343610c88a1187c996d0dc58330b55cee28 new file mode 100644 index 000000000..8b64b4381 --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/9b/219343610c88a1187c996d0dc58330b55cee28 @@ -0,0 +1,2 @@ +xKj1ЬFj}Z3 VdFA#?\ zu]FSo"J& ^,9$GEd)7|&[6(FU"&h< Fc4Aƿ>"ZQ;m9\;KP%1b9k93Gkwni[uZ h"RYC[]=0IrKpO: +pʯ _(c \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/9f/e06a50f4d1634d6c6879854d01d80857388706 b/tests/resources/twowaymerge.git/objects/9f/e06a50f4d1634d6c6879854d01d80857388706 new file mode 100644 index 000000000..055de0158 Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/9f/e06a50f4d1634d6c6879854d01d80857388706 differ diff --git a/tests/resources/twowaymerge.git/objects/a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 b/tests/resources/twowaymerge.git/objects/a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 new file mode 100644 index 000000000..cb4d34e77 --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/a4/1a49f8f5cd9b6cb14a076bf8394881ed0b4d19 @@ -0,0 +1,3 @@ +xν 0@ajOq 7'!DD A$FٟW<=<5Z +8N(CzDž$'2!>[):#Dzǵ, z M d=tNŭ= +wk}9.p9^Ʃ=I@Y =ulD \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 b/tests/resources/twowaymerge.git/objects/a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 new file mode 100644 index 000000000..8235f1839 --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/a9/53a018c5b10b20c86e69fef55ebc8ad4c5a417 @@ -0,0 +1 @@ +xJ0])nV3$is"ONŶɼ\|8!dz dXG/ޫϹp*CX@Z8|f[V0HDHE]6gI#g*9UEHH!MḦhRuo.{zSײ|үwȾ>14C8;rn8qۿ7kNui~M^ \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c b/tests/resources/twowaymerge.git/objects/a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c new file mode 100644 index 000000000..4da7e826a --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/a9/cce3cd1b3efbda5b1f4a6dcc3f1570b2d3d74c @@ -0,0 +1 @@ +x+)JMU044c040031QHdx6M9{wk+qIODd6>|X%>9j \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 b/tests/resources/twowaymerge.git/objects/bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 new file mode 100644 index 000000000..b9b60122d Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/bd/1732c43c68d712ad09e1d872b9be6d4b9efdc4 differ diff --git a/tests/resources/twowaymerge.git/objects/c3/7a783c20d92ac92362a78a32860f7eebf938ef b/tests/resources/twowaymerge.git/objects/c3/7a783c20d92ac92362a78a32860f7eebf938ef new file mode 100644 index 000000000..041e890ab Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/c3/7a783c20d92ac92362a78a32860f7eebf938ef differ diff --git a/tests/resources/twowaymerge.git/objects/cb/dd40facab1682754eb67f7a43f29e672903cf6 b/tests/resources/twowaymerge.git/objects/cb/dd40facab1682754eb67f7a43f29e672903cf6 new file mode 100644 index 000000000..ccb156d88 Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/cb/dd40facab1682754eb67f7a43f29e672903cf6 differ diff --git a/tests/resources/twowaymerge.git/objects/cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 b/tests/resources/twowaymerge.git/objects/cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 new file mode 100644 index 000000000..0e028dc01 Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/cd/f97fd3bb48eb3827638bb33d208f5fd32d0aa6 differ diff --git a/tests/resources/twowaymerge.git/objects/d6/f10d549cb335b9e6d38afc1f0088be69b50494 b/tests/resources/twowaymerge.git/objects/d6/f10d549cb335b9e6d38afc1f0088be69b50494 new file mode 100644 index 000000000..b298c520e Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/d6/f10d549cb335b9e6d38afc1f0088be69b50494 differ diff --git a/tests/resources/twowaymerge.git/objects/d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e b/tests/resources/twowaymerge.git/objects/d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e new file mode 100644 index 000000000..de94528a4 --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/d9/acdc7ae7632adfeec67fa73c1e343cf4d1f47e @@ -0,0 +1 @@ +x+)JMU044c040031QHdx6M9{wk+qIODd>4|X%:79U \ No newline at end of file diff --git a/tests/resources/twowaymerge.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/tests/resources/twowaymerge.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 new file mode 100644 index 000000000..711223894 Binary files /dev/null and b/tests/resources/twowaymerge.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 differ diff --git a/tests/resources/twowaymerge.git/objects/ef/0488f0b722f0be8bcb90a7730ac7efafd1d694 b/tests/resources/twowaymerge.git/objects/ef/0488f0b722f0be8bcb90a7730ac7efafd1d694 new file mode 100644 index 000000000..00f7d3615 --- /dev/null +++ b/tests/resources/twowaymerge.git/objects/ef/0488f0b722f0be8bcb90a7730ac7efafd1d694 @@ -0,0 +1 @@ +xM F]s0_cܙ@H1_ۗ}yh@mK 8Y4Ѩt^'`lPىڠks*? |m“i@mV'`).-1 x +uxt(+ \ No newline at end of file diff --git a/tests/resources/typechanges/.gitted/modules/b/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests/resources/typechanges/.gitted/modules/b/objects/78/9efbdadaa4a582778d4584385495559ea0994b new file mode 100644 index 000000000..17458840b --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/b/objects/78/9efbdadaa4a582778d4584385495559ea0994b @@ -0,0 +1,2 @@ +x 0 )?= NlOkj8&r +qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests/resources/typechanges/.gitted/modules/b/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests/resources/typechanges/.gitted/modules/b/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e new file mode 100644 index 000000000..83cc29fb1 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/b/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e differ diff --git a/tests/resources/typechanges/.gitted/modules/b/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests/resources/typechanges/.gitted/modules/b/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 new file mode 100644 index 000000000..55bda40ef Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/b/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 differ diff --git a/tests/resources/typechanges/.gitted/modules/b/packed-refs b/tests/resources/typechanges/.gitted/modules/b/packed-refs new file mode 100644 index 000000000..5a4ebc47c --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/b/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests/resources/typechanges/.gitted/modules/b/refs/heads/master b/tests/resources/typechanges/.gitted/modules/b/refs/heads/master new file mode 100644 index 000000000..e12c44d7a --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/b/refs/heads/master @@ -0,0 +1 @@ +480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests/resources/typechanges/.gitted/modules/b/refs/remotes/origin/HEAD b/tests/resources/typechanges/.gitted/modules/b/refs/remotes/origin/HEAD new file mode 100644 index 000000000..6efe28fff --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/b/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/tests/resources/typechanges/.gitted/modules/d/HEAD b/tests/resources/typechanges/.gitted/modules/d/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/d/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/typechanges/.gitted/modules/d/config b/tests/resources/typechanges/.gitted/modules/d/config new file mode 100644 index 000000000..42e1bddda --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/d/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + worktree = ../../../d + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target/.git +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/tests/resources/typechanges/.gitted/modules/d/description b/tests/resources/typechanges/.gitted/modules/d/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/d/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/typechanges/.gitted/modules/d/index b/tests/resources/typechanges/.gitted/modules/d/index new file mode 100644 index 000000000..86d0266e8 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/d/index differ diff --git a/tests/resources/typechanges/.gitted/modules/d/info/exclude b/tests/resources/typechanges/.gitted/modules/d/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/d/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/typechanges/.gitted/modules/d/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests/resources/typechanges/.gitted/modules/d/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 new file mode 100644 index 000000000..f4b7094c5 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/d/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 differ diff --git a/tests/resources/typechanges/.gitted/modules/d/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests/resources/typechanges/.gitted/modules/d/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 new file mode 100644 index 000000000..56c845e49 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/d/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 differ diff --git a/tests/resources/typechanges/.gitted/modules/d/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests/resources/typechanges/.gitted/modules/d/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 new file mode 100644 index 000000000..bd179b5f5 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/d/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 differ diff --git a/tests/resources/typechanges/.gitted/modules/d/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests/resources/typechanges/.gitted/modules/d/objects/41/bd4bc3df978de695f67ace64c560913da11653 new file mode 100644 index 000000000..ccf49bd15 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/d/objects/41/bd4bc3df978de695f67ace64c560913da11653 differ diff --git a/tests/resources/typechanges/.gitted/modules/d/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests/resources/typechanges/.gitted/modules/d/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 new file mode 100644 index 000000000..53029069a Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/d/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 differ diff --git a/tests/resources/typechanges/.gitted/modules/d/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests/resources/typechanges/.gitted/modules/d/objects/5e/4963595a9774b90524d35a807169049de8ccad new file mode 100644 index 000000000..38c791eba Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/d/objects/5e/4963595a9774b90524d35a807169049de8ccad differ diff --git a/tests/resources/typechanges/.gitted/modules/d/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests/resources/typechanges/.gitted/modules/d/objects/6b/31c659545507c381e9cd34ec508f16c04e149e new file mode 100644 index 000000000..a26d29993 --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/d/objects/6b/31c659545507c381e9cd34ec508f16c04e149e @@ -0,0 +1,2 @@ +xQ +!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests/resources/typechanges/.gitted/modules/d/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests/resources/typechanges/.gitted/modules/d/objects/73/ba924a80437097795ae839e66e187c55d3babf new file mode 100644 index 000000000..83d1ba481 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/d/objects/73/ba924a80437097795ae839e66e187c55d3babf differ diff --git a/tests/resources/typechanges/.gitted/modules/d/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests/resources/typechanges/.gitted/modules/d/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a new file mode 100644 index 000000000..6d27af8a8 --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/d/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a @@ -0,0 +1,2 @@ +x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x +uxt(+ \ No newline at end of file diff --git a/tests/resources/typechanges/.gitted/modules/d/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests/resources/typechanges/.gitted/modules/d/objects/78/9efbdadaa4a582778d4584385495559ea0994b new file mode 100644 index 000000000..17458840b --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/d/objects/78/9efbdadaa4a582778d4584385495559ea0994b @@ -0,0 +1,2 @@ +x 0 )?= NlOkj8&r +qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests/resources/typechanges/.gitted/modules/d/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests/resources/typechanges/.gitted/modules/d/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e new file mode 100644 index 000000000..83cc29fb1 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/d/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e differ diff --git a/tests/resources/typechanges/.gitted/modules/d/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests/resources/typechanges/.gitted/modules/d/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 new file mode 100644 index 000000000..55bda40ef Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/d/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 differ diff --git a/tests/resources/typechanges/.gitted/modules/d/packed-refs b/tests/resources/typechanges/.gitted/modules/d/packed-refs new file mode 100644 index 000000000..5a4ebc47c --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/d/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests/resources/typechanges/.gitted/modules/d/refs/heads/master b/tests/resources/typechanges/.gitted/modules/d/refs/heads/master new file mode 100644 index 000000000..e12c44d7a --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/d/refs/heads/master @@ -0,0 +1 @@ +480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests/resources/typechanges/.gitted/modules/d/refs/remotes/origin/HEAD b/tests/resources/typechanges/.gitted/modules/d/refs/remotes/origin/HEAD new file mode 100644 index 000000000..6efe28fff --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/d/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/tests/resources/typechanges/.gitted/modules/e/HEAD b/tests/resources/typechanges/.gitted/modules/e/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/e/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/typechanges/.gitted/modules/e/config b/tests/resources/typechanges/.gitted/modules/e/config new file mode 100644 index 000000000..89b3b9b4f --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/e/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + worktree = ../../../e + ignorecase = true +[remote "origin"] + fetch = +refs/heads/*:refs/remotes/origin/* + url = /Users/rb/src/libgit2/tests-clar/resources/submod2_target/.git +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/tests/resources/typechanges/.gitted/modules/e/description b/tests/resources/typechanges/.gitted/modules/e/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/e/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/typechanges/.gitted/modules/e/index b/tests/resources/typechanges/.gitted/modules/e/index new file mode 100644 index 000000000..cd6e2da6c Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/e/index differ diff --git a/tests/resources/typechanges/.gitted/modules/e/info/exclude b/tests/resources/typechanges/.gitted/modules/e/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/e/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/typechanges/.gitted/modules/e/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 b/tests/resources/typechanges/.gitted/modules/e/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 new file mode 100644 index 000000000..f4b7094c5 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/e/objects/06/362fe2fdb7010d0e447b4fb450d405420479a1 differ diff --git a/tests/resources/typechanges/.gitted/modules/e/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 b/tests/resources/typechanges/.gitted/modules/e/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 new file mode 100644 index 000000000..56c845e49 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/e/objects/0e/6a3ca48bd47cfe67681acf39aa0b10a0b92484 differ diff --git a/tests/resources/typechanges/.gitted/modules/e/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 b/tests/resources/typechanges/.gitted/modules/e/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 new file mode 100644 index 000000000..bd179b5f5 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/e/objects/17/d0ece6e96460a06592d9d9d000de37ba4232c5 differ diff --git a/tests/resources/typechanges/.gitted/modules/e/objects/41/bd4bc3df978de695f67ace64c560913da11653 b/tests/resources/typechanges/.gitted/modules/e/objects/41/bd4bc3df978de695f67ace64c560913da11653 new file mode 100644 index 000000000..ccf49bd15 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/e/objects/41/bd4bc3df978de695f67ace64c560913da11653 differ diff --git a/tests/resources/typechanges/.gitted/modules/e/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 b/tests/resources/typechanges/.gitted/modules/e/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 new file mode 100644 index 000000000..53029069a Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/e/objects/48/0095882d281ed676fe5b863569520e54a7d5c0 differ diff --git a/tests/resources/typechanges/.gitted/modules/e/objects/5e/4963595a9774b90524d35a807169049de8ccad b/tests/resources/typechanges/.gitted/modules/e/objects/5e/4963595a9774b90524d35a807169049de8ccad new file mode 100644 index 000000000..38c791eba Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/e/objects/5e/4963595a9774b90524d35a807169049de8ccad differ diff --git a/tests/resources/typechanges/.gitted/modules/e/objects/6b/31c659545507c381e9cd34ec508f16c04e149e b/tests/resources/typechanges/.gitted/modules/e/objects/6b/31c659545507c381e9cd34ec508f16c04e149e new file mode 100644 index 000000000..a26d29993 --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/e/objects/6b/31c659545507c381e9cd34ec508f16c04e149e @@ -0,0 +1,2 @@ +xQ +!Evoy*_@g#hOh^9wSòf1*[Ic Ԥpk Α\S߇l@.^QpF(:D5zr~ en8 \ No newline at end of file diff --git a/tests/resources/typechanges/.gitted/modules/e/objects/73/ba924a80437097795ae839e66e187c55d3babf b/tests/resources/typechanges/.gitted/modules/e/objects/73/ba924a80437097795ae839e66e187c55d3babf new file mode 100644 index 000000000..83d1ba481 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/e/objects/73/ba924a80437097795ae839e66e187c55d3babf differ diff --git a/tests/resources/typechanges/.gitted/modules/e/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a b/tests/resources/typechanges/.gitted/modules/e/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a new file mode 100644 index 000000000..6d27af8a8 --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/e/objects/78/0d7397f5e8f8f477fb55b7af3accc2154b2d4a @@ -0,0 +1,2 @@ +x-10 Fa0p(N-ӡғq]>ks*? |m“i@mV'`).-1 x +uxt(+ \ No newline at end of file diff --git a/tests/resources/typechanges/.gitted/modules/e/objects/78/9efbdadaa4a582778d4584385495559ea0994b b/tests/resources/typechanges/.gitted/modules/e/objects/78/9efbdadaa4a582778d4584385495559ea0994b new file mode 100644 index 000000000..17458840b --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/e/objects/78/9efbdadaa4a582778d4584385495559ea0994b @@ -0,0 +1,2 @@ +x 0 )?= NlOkj8&r +qJW7B<fK8#Q1C-"e̫>'@ \ No newline at end of file diff --git a/tests/resources/typechanges/.gitted/modules/e/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e b/tests/resources/typechanges/.gitted/modules/e/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e new file mode 100644 index 000000000..83cc29fb1 Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/e/objects/88/34b635dd468a83cb012f6feace968c1c9f5d6e differ diff --git a/tests/resources/typechanges/.gitted/modules/e/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 b/tests/resources/typechanges/.gitted/modules/e/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 new file mode 100644 index 000000000..55bda40ef Binary files /dev/null and b/tests/resources/typechanges/.gitted/modules/e/objects/d0/5f2cd5cc77addf68ed6f50d622c9a4f732e6c5 differ diff --git a/tests/resources/typechanges/.gitted/modules/e/packed-refs b/tests/resources/typechanges/.gitted/modules/e/packed-refs new file mode 100644 index 000000000..5a4ebc47c --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/e/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +480095882d281ed676fe5b863569520e54a7d5c0 refs/remotes/origin/master diff --git a/tests/resources/typechanges/.gitted/modules/e/refs/heads/master b/tests/resources/typechanges/.gitted/modules/e/refs/heads/master new file mode 100644 index 000000000..e12c44d7a --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/e/refs/heads/master @@ -0,0 +1 @@ +480095882d281ed676fe5b863569520e54a7d5c0 diff --git a/tests/resources/typechanges/.gitted/modules/e/refs/remotes/origin/HEAD b/tests/resources/typechanges/.gitted/modules/e/refs/remotes/origin/HEAD new file mode 100644 index 000000000..6efe28fff --- /dev/null +++ b/tests/resources/typechanges/.gitted/modules/e/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/tests/resources/typechanges/.gitted/objects/0d/78578795b7ca49fd8df6c4b6d27c5c02d991d8 b/tests/resources/typechanges/.gitted/objects/0d/78578795b7ca49fd8df6c4b6d27c5c02d991d8 new file mode 100644 index 000000000..f2d02f4f7 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/0d/78578795b7ca49fd8df6c4b6d27c5c02d991d8 differ diff --git a/tests/resources/typechanges/.gitted/objects/0e/7ed140b514b8cae23254cb8656fe1674403aff b/tests/resources/typechanges/.gitted/objects/0e/7ed140b514b8cae23254cb8656fe1674403aff new file mode 100644 index 000000000..527964c92 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/0e/7ed140b514b8cae23254cb8656fe1674403aff differ diff --git a/tests/resources/typechanges/.gitted/objects/0f/f461da9689266f482d8f6654a4400b4e33c586 b/tests/resources/typechanges/.gitted/objects/0f/f461da9689266f482d8f6654a4400b4e33c586 new file mode 100644 index 000000000..2694e4fa0 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/0f/f461da9689266f482d8f6654a4400b4e33c586 differ diff --git a/tests/resources/typechanges/.gitted/objects/18/aa7e45bbe4c3cc24a0b079696c59d36675af97 b/tests/resources/typechanges/.gitted/objects/18/aa7e45bbe4c3cc24a0b079696c59d36675af97 new file mode 100644 index 000000000..032a960b4 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/18/aa7e45bbe4c3cc24a0b079696c59d36675af97 differ diff --git a/tests/resources/typechanges/.gitted/objects/1b/63caae4a5ca96f78e8dfefc376c6a39a142475 b/tests/resources/typechanges/.gitted/objects/1b/63caae4a5ca96f78e8dfefc376c6a39a142475 new file mode 100644 index 000000000..d32622e67 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/1b/63caae4a5ca96f78e8dfefc376c6a39a142475 differ diff --git a/tests/resources/typechanges/.gitted/objects/1e/abe82aa3b2365a394f6108f24435df6e193d02 b/tests/resources/typechanges/.gitted/objects/1e/abe82aa3b2365a394f6108f24435df6e193d02 new file mode 100644 index 000000000..42d5f92f3 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/1e/abe82aa3b2365a394f6108f24435df6e193d02 differ diff --git a/tests/resources/typechanges/.gitted/objects/42/061c01a1c70097d1e4579f29a5adf40abdec95 b/tests/resources/typechanges/.gitted/objects/42/061c01a1c70097d1e4579f29a5adf40abdec95 new file mode 100644 index 000000000..0a8f32e15 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/42/061c01a1c70097d1e4579f29a5adf40abdec95 differ diff --git a/tests/resources/typechanges/.gitted/objects/46/2838cee476a87e7cff32196b66fa18ed756592 b/tests/resources/typechanges/.gitted/objects/46/2838cee476a87e7cff32196b66fa18ed756592 new file mode 100644 index 000000000..52af51f74 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/46/2838cee476a87e7cff32196b66fa18ed756592 differ diff --git a/tests/resources/typechanges/.gitted/objects/63/499e4ea8e096b831515ceb1d5a7593e4d87ae5 b/tests/resources/typechanges/.gitted/objects/63/499e4ea8e096b831515ceb1d5a7593e4d87ae5 new file mode 100644 index 000000000..afafa89f4 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/63/499e4ea8e096b831515ceb1d5a7593e4d87ae5 differ diff --git a/tests/resources/typechanges/.gitted/objects/68/1af94e10eaf262f3ab7cb9b8fd5f4158ba4d3e b/tests/resources/typechanges/.gitted/objects/68/1af94e10eaf262f3ab7cb9b8fd5f4158ba4d3e new file mode 100644 index 000000000..9e518fc28 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/68/1af94e10eaf262f3ab7cb9b8fd5f4158ba4d3e differ diff --git a/tests/resources/typechanges/.gitted/objects/6a/9008602b811e69a9b7a2d83496f39a794fdeeb b/tests/resources/typechanges/.gitted/objects/6a/9008602b811e69a9b7a2d83496f39a794fdeeb new file mode 100644 index 000000000..a245727a1 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/6a/9008602b811e69a9b7a2d83496f39a794fdeeb differ diff --git a/tests/resources/typechanges/.gitted/objects/6e/ae26c90e8ccc4d16208972119c40635489c6f0 b/tests/resources/typechanges/.gitted/objects/6e/ae26c90e8ccc4d16208972119c40635489c6f0 new file mode 100644 index 000000000..ea35cd311 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/6e/ae26c90e8ccc4d16208972119c40635489c6f0 differ diff --git a/tests/resources/typechanges/.gitted/objects/6f/39eabbb8a7541515e0d35971078bccb502e7e0 b/tests/resources/typechanges/.gitted/objects/6f/39eabbb8a7541515e0d35971078bccb502e7e0 new file mode 100644 index 000000000..c54817598 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/6f/39eabbb8a7541515e0d35971078bccb502e7e0 differ diff --git a/tests/resources/typechanges/.gitted/objects/71/54d3083461536dfc71ad5542f3e65e723a06c4 b/tests/resources/typechanges/.gitted/objects/71/54d3083461536dfc71ad5542f3e65e723a06c4 new file mode 100644 index 000000000..9fdd8f245 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/71/54d3083461536dfc71ad5542f3e65e723a06c4 differ diff --git a/tests/resources/typechanges/.gitted/objects/75/56c1d893a4c0ca85ac8ac51de47ff399758729 b/tests/resources/typechanges/.gitted/objects/75/56c1d893a4c0ca85ac8ac51de47ff399758729 new file mode 100644 index 000000000..d43630f44 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/75/56c1d893a4c0ca85ac8ac51de47ff399758729 differ diff --git a/tests/resources/typechanges/.gitted/objects/76/fef844064c26d5e06c2508240dae661e7231b2 b/tests/resources/typechanges/.gitted/objects/76/fef844064c26d5e06c2508240dae661e7231b2 new file mode 100644 index 000000000..355ce4b5b Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/76/fef844064c26d5e06c2508240dae661e7231b2 differ diff --git a/tests/resources/typechanges/.gitted/objects/79/b9f23e85f55ea36a472a902e875bc1121a94cb b/tests/resources/typechanges/.gitted/objects/79/b9f23e85f55ea36a472a902e875bc1121a94cb new file mode 100644 index 000000000..2b07ad256 --- /dev/null +++ b/tests/resources/typechanges/.gitted/objects/79/b9f23e85f55ea36a472a902e875bc1121a94cb @@ -0,0 +1,2 @@ +xA E]sfJbq `I@ +yH;ZeBr6LPY%8&v4Jm֢^*qpJµ;Z Ơ3ZD1)"%%38_ \ No newline at end of file diff --git a/tests/resources/typechanges/.gitted/objects/85/28da0ea65eacf1f74f9ed6696adbac547963ad b/tests/resources/typechanges/.gitted/objects/85/28da0ea65eacf1f74f9ed6696adbac547963ad new file mode 100644 index 000000000..6d2da6c93 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/85/28da0ea65eacf1f74f9ed6696adbac547963ad differ diff --git a/tests/resources/typechanges/.gitted/objects/8b/3726b365824ad5a07c537247f4bc73ed7d37ea b/tests/resources/typechanges/.gitted/objects/8b/3726b365824ad5a07c537247f4bc73ed7d37ea new file mode 100644 index 000000000..3dc333bc6 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/8b/3726b365824ad5a07c537247f4bc73ed7d37ea differ diff --git a/tests/resources/typechanges/.gitted/objects/93/3e28c1c8a68838a763d250bdf0b2c6068289c3 b/tests/resources/typechanges/.gitted/objects/93/3e28c1c8a68838a763d250bdf0b2c6068289c3 new file mode 100644 index 000000000..02ad0e97a Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/93/3e28c1c8a68838a763d250bdf0b2c6068289c3 differ diff --git a/tests/resources/typechanges/.gitted/objects/96/2710fe5b4e453e9e827945b3487c525968ec4a b/tests/resources/typechanges/.gitted/objects/96/2710fe5b4e453e9e827945b3487c525968ec4a new file mode 100644 index 000000000..d06b06a52 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/96/2710fe5b4e453e9e827945b3487c525968ec4a differ diff --git a/tests/resources/typechanges/.gitted/objects/96/6cf1b3598e195b31b2cde3784f9a19f0728a6f b/tests/resources/typechanges/.gitted/objects/96/6cf1b3598e195b31b2cde3784f9a19f0728a6f new file mode 100644 index 000000000..5f9ffd4ed Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/96/6cf1b3598e195b31b2cde3784f9a19f0728a6f differ diff --git a/tests/resources/typechanges/.gitted/objects/99/e8bab9ece009f0fba7eb41f850f4c12bedb9b7 b/tests/resources/typechanges/.gitted/objects/99/e8bab9ece009f0fba7eb41f850f4c12bedb9b7 new file mode 100644 index 000000000..ac17defac Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/99/e8bab9ece009f0fba7eb41f850f4c12bedb9b7 differ diff --git a/tests/resources/typechanges/.gitted/objects/9b/19edf33a03a0c59cdfc113bfa5c06179bf9b1a b/tests/resources/typechanges/.gitted/objects/9b/19edf33a03a0c59cdfc113bfa5c06179bf9b1a new file mode 100644 index 000000000..7ab83aefe --- /dev/null +++ b/tests/resources/typechanges/.gitted/objects/9b/19edf33a03a0c59cdfc113bfa5c06179bf9b1a @@ -0,0 +1,5 @@ +xI +1E]LT AJЃ7WpyӶ,ZѩUf cXcR C43Y2"NN:HɈo6,sjf#kG +cys +MGm2B +.K)k֑w8CC \ No newline at end of file diff --git a/tests/resources/typechanges/.gitted/objects/9b/db75b73836a99e3dbeea640a81de81031fdc29 b/tests/resources/typechanges/.gitted/objects/9b/db75b73836a99e3dbeea640a81de81031fdc29 new file mode 100644 index 000000000..aed4d8165 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/9b/db75b73836a99e3dbeea640a81de81031fdc29 differ diff --git a/tests/resources/typechanges/.gitted/objects/9d/0235c7a7edc0889a18f97a42ee6db9fe688447 b/tests/resources/typechanges/.gitted/objects/9d/0235c7a7edc0889a18f97a42ee6db9fe688447 new file mode 100644 index 000000000..3e02a41b2 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/9d/0235c7a7edc0889a18f97a42ee6db9fe688447 differ diff --git a/tests/resources/typechanges/.gitted/objects/9e/ffc457877f109b2a4319e14bee613a15f2a00d b/tests/resources/typechanges/.gitted/objects/9e/ffc457877f109b2a4319e14bee613a15f2a00d new file mode 100644 index 000000000..fb24100fc Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/9e/ffc457877f109b2a4319e14bee613a15f2a00d differ diff --git a/tests/resources/typechanges/.gitted/objects/a0/a9bad6f6f40325198f938a0e3ae981622d7707 b/tests/resources/typechanges/.gitted/objects/a0/a9bad6f6f40325198f938a0e3ae981622d7707 new file mode 100644 index 000000000..b6b7db785 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/a0/a9bad6f6f40325198f938a0e3ae981622d7707 differ diff --git a/tests/resources/typechanges/.gitted/objects/b1/977dc4e573b812d4619754c98138c56999dc0d b/tests/resources/typechanges/.gitted/objects/b1/977dc4e573b812d4619754c98138c56999dc0d new file mode 100644 index 000000000..e1334057c Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/b1/977dc4e573b812d4619754c98138c56999dc0d differ diff --git a/tests/resources/typechanges/.gitted/objects/d7/5992dd02391e128dac332dcc78d649dd9ab095 b/tests/resources/typechanges/.gitted/objects/d7/5992dd02391e128dac332dcc78d649dd9ab095 new file mode 100644 index 000000000..65f1f530f Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/d7/5992dd02391e128dac332dcc78d649dd9ab095 differ diff --git a/tests/resources/typechanges/.gitted/objects/da/e2709d638df52212b1f43ff61797ebfedfcc7c b/tests/resources/typechanges/.gitted/objects/da/e2709d638df52212b1f43ff61797ebfedfcc7c new file mode 100644 index 000000000..355faa61f Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/da/e2709d638df52212b1f43ff61797ebfedfcc7c differ diff --git a/tests/resources/typechanges/.gitted/objects/e1/152adcb9adf37ec551ada9ba377ab53aec3bad b/tests/resources/typechanges/.gitted/objects/e1/152adcb9adf37ec551ada9ba377ab53aec3bad new file mode 100644 index 000000000..c68fdcfab Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/e1/152adcb9adf37ec551ada9ba377ab53aec3bad differ diff --git a/tests/resources/typechanges/.gitted/objects/e4/ed436a9eb0f198cda722886a5f8d6d6c836b7b b/tests/resources/typechanges/.gitted/objects/e4/ed436a9eb0f198cda722886a5f8d6d6c836b7b new file mode 100644 index 000000000..c9229ba25 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/e4/ed436a9eb0f198cda722886a5f8d6d6c836b7b differ diff --git a/tests/resources/typechanges/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/tests/resources/typechanges/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 new file mode 100644 index 000000000..711223894 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 differ diff --git a/tests/resources/typechanges/.gitted/objects/f2/0b79342712e0b2315647cd8227a573fd3bc46e b/tests/resources/typechanges/.gitted/objects/f2/0b79342712e0b2315647cd8227a573fd3bc46e new file mode 100644 index 000000000..3962ba6b4 Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/f2/0b79342712e0b2315647cd8227a573fd3bc46e differ diff --git a/tests/resources/typechanges/.gitted/objects/fd/e0147e3b59f381635a3b016e3fe6dacb70779d b/tests/resources/typechanges/.gitted/objects/fd/e0147e3b59f381635a3b016e3fe6dacb70779d new file mode 100644 index 000000000..e3663da9f Binary files /dev/null and b/tests/resources/typechanges/.gitted/objects/fd/e0147e3b59f381635a3b016e3fe6dacb70779d differ diff --git a/tests/resources/typechanges/.gitted/refs/heads/master b/tests/resources/typechanges/.gitted/refs/heads/master new file mode 100644 index 000000000..546481a33 --- /dev/null +++ b/tests/resources/typechanges/.gitted/refs/heads/master @@ -0,0 +1 @@ +6eae26c90e8ccc4d16208972119c40635489c6f0 diff --git a/tests/resources/typechanges/README.md b/tests/resources/typechanges/README.md new file mode 100644 index 000000000..1f5a95a9f --- /dev/null +++ b/tests/resources/typechanges/README.md @@ -0,0 +1,43 @@ +This is a test repo for libgit2 where tree entries have type changes + +Types +----- + +The key types that could be found in tree entries are: + +1. GIT_FILEMODE_NEW = 0000000 (i.e. file does not exist) +2. GIT_FILEMODE_TREE = 0040000 +3. GIT_FILEMODE_BLOB = 0100644 +4. GIT_FILEMODE_BLOB_EXECUTABLE = 0100755 +5. GIT_FILEMODE_LINK = 0120000 +6. GIT_FILEMODE_COMMIT = 0160000 + +I will try to have every type of transition somewhere in the history +of this repo. + +Commits +------- + +* `a(1--1) b(1--1) c(1--1) d(1--1) e(1--1)` + **Initial commit**
+ `79b9f23e85f55ea36a472a902e875bc1121a94cb` +* `a(1->2) b(1->3) c(1->4) d(1->5) e(1->6)` + **Create content**
+ `9bdb75b73836a99e3dbeea640a81de81031fdc29` +* `a(2->3) b(3->4) c(4->5) d(5->6) e(6->2)` + **Changes #1**
+ `0e7ed140b514b8cae23254cb8656fe1674403aff` +* `a(3->5) b(4->6) c(5->2) d(6->3) e(2->4)` + **Changes #2**
+ `9d0235c7a7edc0889a18f97a42ee6db9fe688447` +* `a(5->3) b(6->4) c(2->5) d(3->6) e(4->2)` + **Changes #3**
+ `9b19edf33a03a0c59cdfc113bfa5c06179bf9b1a` +* `a(3->2) b(4->3) c(5->4) d(6->5) e(2->6)` + **Changes #4**
+ `1b63caae4a5ca96f78e8dfefc376c6a39a142475`
+ Matches **Changes #1** except README.md +* `a(2->1) b(3->1) c(4->1) d(5->1) e(6->1)` + **Changes #5**
+ `6eae26c90e8ccc4d16208972119c40635489c6f0`
+ Matches **Initial commit** except README.md and .gitmodules diff --git a/tests/resources/typechanges/gitmodules b/tests/resources/typechanges/gitmodules new file mode 100644 index 000000000..e69de29bb diff --git a/tests/resources/unsymlinked.git/HEAD b/tests/resources/unsymlinked.git/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/unsymlinked.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/unsymlinked.git/config b/tests/resources/unsymlinked.git/config new file mode 100644 index 000000000..f57351fd5 --- /dev/null +++ b/tests/resources/unsymlinked.git/config @@ -0,0 +1,6 @@ +[core] + bare = true + repositoryformatversion = 0 + filemode = false + logallrefupdates = true + ignorecase = true diff --git a/tests/resources/unsymlinked.git/description b/tests/resources/unsymlinked.git/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/unsymlinked.git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/unsymlinked.git/info/exclude b/tests/resources/unsymlinked.git/info/exclude new file mode 100644 index 000000000..6d05881d3 --- /dev/null +++ b/tests/resources/unsymlinked.git/info/exclude @@ -0,0 +1,2 @@ +# File patterns to ignore; see `git help ignore` for more information. +# Lines that start with '#' are comments. diff --git a/tests/resources/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf b/tests/resources/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf new file mode 100644 index 000000000..953262fa9 Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf differ diff --git a/tests/resources/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b b/tests/resources/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b new file mode 100644 index 000000000..91ec8fa5e Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b differ diff --git a/tests/resources/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c b/tests/resources/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c new file mode 100644 index 000000000..94afd01e8 Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c differ diff --git a/tests/resources/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 b/tests/resources/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 new file mode 100644 index 000000000..5b33d027c Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 differ diff --git a/tests/resources/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c b/tests/resources/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c new file mode 100644 index 000000000..67eb14930 Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c differ diff --git a/tests/resources/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 b/tests/resources/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 new file mode 100644 index 000000000..c1ea0de75 Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 differ diff --git a/tests/resources/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d b/tests/resources/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d new file mode 100644 index 000000000..028505563 Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d differ diff --git a/tests/resources/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 b/tests/resources/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 new file mode 100644 index 000000000..e866a75a6 Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 differ diff --git a/tests/resources/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 b/tests/resources/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 new file mode 100644 index 000000000..189ab044d Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 differ diff --git a/tests/resources/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 b/tests/resources/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 new file mode 100644 index 000000000..a2ef6be45 --- /dev/null +++ b/tests/resources/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 @@ -0,0 +1,2 @@ +x[ +0E*_y݀{4ShZ))| N[ks=KߙŚ[Q"4&&M*i/޴!1S*AGt)-'Um7O ccչ=z崵;(PY+*Dq^E!*/0}Z?<P慥Jp \ No newline at end of file diff --git a/tests/resources/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 b/tests/resources/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 new file mode 100644 index 000000000..ec274cb1d Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 differ diff --git a/tests/resources/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a b/tests/resources/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a new file mode 100644 index 000000000..c1b6a5101 Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a differ diff --git a/tests/resources/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 b/tests/resources/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 new file mode 100644 index 000000000..ad751adbe Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 differ diff --git a/tests/resources/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 b/tests/resources/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 new file mode 100644 index 000000000..f87cd42fb Binary files /dev/null and b/tests/resources/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 differ diff --git a/tests/resources/unsymlinked.git/refs/heads/exe-file b/tests/resources/unsymlinked.git/refs/heads/exe-file new file mode 100644 index 000000000..b96ef46ca --- /dev/null +++ b/tests/resources/unsymlinked.git/refs/heads/exe-file @@ -0,0 +1 @@ +a8595ccca04f40818ae0155c8f9c77a230e597b6 diff --git a/tests/resources/unsymlinked.git/refs/heads/master b/tests/resources/unsymlinked.git/refs/heads/master new file mode 100644 index 000000000..96c17ab17 --- /dev/null +++ b/tests/resources/unsymlinked.git/refs/heads/master @@ -0,0 +1 @@ +7fccd75616ec188b8f1b23d67506a334cc34a49d diff --git a/tests/resources/unsymlinked.git/refs/heads/reg-file b/tests/resources/unsymlinked.git/refs/heads/reg-file new file mode 100644 index 000000000..b428c00d5 --- /dev/null +++ b/tests/resources/unsymlinked.git/refs/heads/reg-file @@ -0,0 +1 @@ +806999882bf91d24241e4077906b9017605eb1f3 diff --git a/tests/revwalk/basic.c b/tests/revwalk/basic.c new file mode 100644 index 000000000..6d55aed54 --- /dev/null +++ b/tests/revwalk/basic.c @@ -0,0 +1,254 @@ +#include "clar_libgit2.h" + +/* + * a4a7dce [0] Merge branch 'master' into br2 + |\ + | * 9fd738e [1] a fourth commit + | * 4a202b3 [2] a third commit + * | c47800c [3] branch commit one + |/ + * 5b5b025 [5] another commit + * 8496071 [4] testing +*/ +static const char *commit_head = "a4a7dce85cf63874e984719f4fdd239f5145052f"; + +static const char *commit_ids[] = { + "a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */ + "9fd738e8f7967c078dceed8190330fc8648ee56a", /* 1 */ + "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", /* 2 */ + "c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */ + "8496071c1b46c854b31185ea97743be6a8774479", /* 4 */ + "5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */ +}; + +/* Careful: there are two possible topological sorts */ +static const int commit_sorting_topo[][6] = { + {0, 1, 2, 3, 5, 4}, {0, 3, 1, 2, 5, 4} +}; + +static const int commit_sorting_time[][6] = { + {0, 3, 1, 2, 5, 4} +}; + +static const int commit_sorting_topo_reverse[][6] = { + {4, 5, 3, 2, 1, 0}, {4, 5, 2, 1, 3, 0} +}; + +static const int commit_sorting_time_reverse[][6] = { + {4, 5, 2, 1, 3, 0} +}; + +static const int commit_sorting_segment[][6] = { + {1, 2, -1, -1, -1, -1} +}; + +#define commit_count 6 +static const int result_bytes = 24; + + +static int get_commit_index(git_oid *raw_oid) +{ + int i; + char oid[40]; + + git_oid_fmt(oid, raw_oid); + + for (i = 0; i < commit_count; ++i) + if (memcmp(oid, commit_ids[i], 40) == 0) + return i; + + return -1; +} + +static int test_walk_only(git_revwalk *walk, + const int possible_results[][commit_count], int results_count) +{ + git_oid oid; + int i; + int result_array[commit_count]; + + for (i = 0; i < commit_count; ++i) + result_array[i] = -1; + + i = 0; + while (git_revwalk_next(&oid, walk) == 0) { + result_array[i++] = get_commit_index(&oid); + /*{ + char str[41]; + git_oid_fmt(str, &oid); + str[40] = 0; + printf(" %d) %s\n", i, str); + }*/ + } + + for (i = 0; i < results_count; ++i) + if (memcmp(possible_results[i], + result_array, result_bytes) == 0) + return 0; + + return GIT_ERROR; +} + +static int test_walk(git_revwalk *walk, const git_oid *root, + int flags, const int possible_results[][6], int results_count) +{ + git_revwalk_sorting(walk, flags); + git_revwalk_push(walk, root); + + return test_walk_only(walk, possible_results, results_count); +} + +static git_repository *_repo = NULL; +static git_revwalk *_walk = NULL; +static const char *_fixture = NULL; + +void test_revwalk_basic__initialize(void) +{ +} + +void test_revwalk_basic__cleanup(void) +{ + git_revwalk_free(_walk); + + if (_fixture) + cl_git_sandbox_cleanup(); + else + git_repository_free(_repo); + + _fixture = NULL; + _repo = NULL; + _walk = NULL; +} + +static void revwalk_basic_setup_walk(const char *fixture) +{ + if (fixture) { + _fixture = fixture; + _repo = cl_git_sandbox_init(fixture); + } else { + cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); + } + + cl_git_pass(git_revwalk_new(&_walk, _repo)); +} + +void test_revwalk_basic__sorting_modes(void) +{ + git_oid id; + + revwalk_basic_setup_walk(NULL); + + git_oid_fromstr(&id, commit_head); + + cl_git_pass(test_walk(_walk, &id, GIT_SORT_TIME, commit_sorting_time, 1)); + cl_git_pass(test_walk(_walk, &id, GIT_SORT_TOPOLOGICAL, commit_sorting_topo, 2)); + cl_git_pass(test_walk(_walk, &id, GIT_SORT_TIME | GIT_SORT_REVERSE, commit_sorting_time_reverse, 1)); + cl_git_pass(test_walk(_walk, &id, GIT_SORT_TOPOLOGICAL | GIT_SORT_REVERSE, commit_sorting_topo_reverse, 2)); +} + +void test_revwalk_basic__glob_heads(void) +{ + int i = 0; + git_oid oid; + + revwalk_basic_setup_walk(NULL); + + cl_git_pass(git_revwalk_push_glob(_walk, "heads")); + + while (git_revwalk_next(&oid, _walk) == 0) { + i++; + } + + /* git log --branches --oneline | wc -l => 14 */ + cl_assert(i == 14); +} + +void test_revwalk_basic__glob_heads_with_invalid(void) +{ + int i; + git_oid oid; + + revwalk_basic_setup_walk("testrepo"); + + cl_git_mkfile("testrepo/.git/refs/heads/garbage", "not-a-ref"); + cl_git_pass(git_revwalk_push_glob(_walk, "heads")); + + for (i = 0; !git_revwalk_next(&oid, _walk); ++i) + /* walking */; + + /* git log --branches --oneline | wc -l => 16 */ + cl_assert_equal_i(17, i); +} + +void test_revwalk_basic__push_head(void) +{ + int i = 0; + git_oid oid; + + revwalk_basic_setup_walk(NULL); + + cl_git_pass(git_revwalk_push_head(_walk)); + + while (git_revwalk_next(&oid, _walk) == 0) { + i++; + } + + /* git log HEAD --oneline | wc -l => 7 */ + cl_assert(i == 7); +} + +void test_revwalk_basic__push_head_hide_ref(void) +{ + int i = 0; + git_oid oid; + + revwalk_basic_setup_walk(NULL); + + cl_git_pass(git_revwalk_push_head(_walk)); + cl_git_pass(git_revwalk_hide_ref(_walk, "refs/heads/packed-test")); + + while (git_revwalk_next(&oid, _walk) == 0) { + i++; + } + + /* git log HEAD --oneline --not refs/heads/packed-test | wc -l => 4 */ + cl_assert(i == 4); +} + +void test_revwalk_basic__push_head_hide_ref_nobase(void) +{ + int i = 0; + git_oid oid; + + revwalk_basic_setup_walk(NULL); + + cl_git_pass(git_revwalk_push_head(_walk)); + cl_git_pass(git_revwalk_hide_ref(_walk, "refs/heads/packed")); + + while (git_revwalk_next(&oid, _walk) == 0) { + i++; + } + + /* git log HEAD --oneline --not refs/heads/packed | wc -l => 7 */ + cl_assert(i == 7); +} + +void test_revwalk_basic__disallow_non_commit(void) +{ + git_oid oid; + + revwalk_basic_setup_walk(NULL); + + cl_git_pass(git_oid_fromstr(&oid, "521d87c1ec3aef9824daf6d96cc0ae3710766d91")); + cl_git_fail(git_revwalk_push(_walk, &oid)); +} + +void test_revwalk_basic__push_range(void) +{ + revwalk_basic_setup_walk(NULL); + + git_revwalk_reset(_walk); + git_revwalk_sorting(_walk, 0); + cl_git_pass(git_revwalk_push_range(_walk, "9fd738e~2..9fd738e")); + cl_git_pass(test_walk_only(_walk, commit_sorting_segment, 1)); +} diff --git a/tests/revwalk/mergebase.c b/tests/revwalk/mergebase.c new file mode 100644 index 000000000..2d01647fd --- /dev/null +++ b/tests/revwalk/mergebase.c @@ -0,0 +1,392 @@ +#include "clar_libgit2.h" +#include "vector.h" +#include + +static git_repository *_repo; +static git_repository *_repo2; + +void test_revwalk_mergebase__initialize(void) +{ + cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_repository_open(&_repo2, cl_fixture("twowaymerge.git"))); +} + +void test_revwalk_mergebase__cleanup(void) +{ + git_repository_free(_repo); + _repo = NULL; + + git_repository_free(_repo2); + _repo2 = NULL; +} + +void test_revwalk_mergebase__single1(void) +{ + git_oid result, one, two, expected; + size_t ahead, behind; + + cl_git_pass(git_oid_fromstr(&one, "c47800c7266a2be04c571c04d5a6614691ea99bd ")); + cl_git_pass(git_oid_fromstr(&two, "9fd738e8f7967c078dceed8190330fc8648ee56a")); + cl_git_pass(git_oid_fromstr(&expected, "5b5b025afb0b4c913b4c338a42934a3863bf3644")); + + cl_git_pass(git_merge_base(&result, _repo, &one, &two)); + cl_assert(git_oid_cmp(&result, &expected) == 0); + + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); + cl_assert_equal_sz(ahead, 2); + cl_assert_equal_sz(behind, 1); + + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &two, &one)); + cl_assert_equal_sz(ahead, 1); + cl_assert_equal_sz(behind, 2); +} + +void test_revwalk_mergebase__single2(void) +{ + git_oid result, one, two, expected; + size_t ahead, behind; + + cl_git_pass(git_oid_fromstr(&one, "763d71aadf09a7951596c9746c024e7eece7c7af")); + cl_git_pass(git_oid_fromstr(&two, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750")); + cl_git_pass(git_oid_fromstr(&expected, "c47800c7266a2be04c571c04d5a6614691ea99bd")); + + cl_git_pass(git_merge_base(&result, _repo, &one, &two)); + cl_assert(git_oid_cmp(&result, &expected) == 0); + + cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &one, &two)); + cl_assert_equal_sz(ahead, 4); + cl_assert_equal_sz(behind, 1); + + cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &two, &one)); + cl_assert_equal_sz(ahead, 1); + cl_assert_equal_sz(behind, 4); +} + +void test_revwalk_mergebase__merged_branch(void) +{ + git_oid result, one, two, expected; + size_t ahead, behind; + + cl_git_pass(git_oid_fromstr(&one, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750")); + cl_git_pass(git_oid_fromstr(&two, "9fd738e8f7967c078dceed8190330fc8648ee56a")); + cl_git_pass(git_oid_fromstr(&expected, "9fd738e8f7967c078dceed8190330fc8648ee56a")); + + cl_git_pass(git_merge_base(&result, _repo, &one, &two)); + cl_assert(git_oid_cmp(&result, &expected) == 0); + + cl_git_pass(git_merge_base(&result, _repo, &two, &one)); + cl_assert(git_oid_cmp(&result, &expected) == 0); + + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); + cl_assert_equal_sz(ahead, 0); + cl_assert_equal_sz(behind, 3); + + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &two, &one)); + cl_assert_equal_sz(ahead, 3); + cl_assert_equal_sz(behind, 0); +} + +void test_revwalk_mergebase__two_way_merge(void) +{ + git_oid one, two; + size_t ahead, behind; + + cl_git_pass(git_oid_fromstr(&one, "9b219343610c88a1187c996d0dc58330b55cee28")); + cl_git_pass(git_oid_fromstr(&two, "a953a018c5b10b20c86e69fef55ebc8ad4c5a417")); + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo2, &one, &two)); + + cl_assert_equal_sz(ahead, 2); + cl_assert_equal_sz(behind, 8); + + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo2, &two, &one)); + + cl_assert_equal_sz(ahead, 8); + cl_assert_equal_sz(behind, 2); +} + +void test_revwalk_mergebase__no_common_ancestor_returns_ENOTFOUND(void) +{ + git_oid result, one, two; + size_t ahead, behind; + int error; + + cl_git_pass(git_oid_fromstr(&one, "763d71aadf09a7951596c9746c024e7eece7c7af")); + cl_git_pass(git_oid_fromstr(&two, "e90810b8df3e80c413d903f631643c716887138d")); + + error = git_merge_base(&result, _repo, &one, &two); + cl_git_fail(error); + + cl_assert_equal_i(GIT_ENOTFOUND, error); + + cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); + cl_assert_equal_sz(2, ahead); + cl_assert_equal_sz(4, behind); +} + +void test_revwalk_mergebase__prefer_youngest_merge_base(void) +{ + git_oid result, one, two, expected; + + cl_git_pass(git_oid_fromstr(&one, "a4a7dce85cf63874e984719f4fdd239f5145052f ")); + cl_git_pass(git_oid_fromstr(&two, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); + cl_git_pass(git_oid_fromstr(&expected, "c47800c7266a2be04c571c04d5a6614691ea99bd")); + + cl_git_pass(git_merge_base(&result, _repo, &one, &two)); + cl_assert(git_oid_cmp(&result, &expected) == 0); +} + +void test_revwalk_mergebase__no_off_by_one_missing(void) +{ + git_oid result, one, two; + + cl_git_pass(git_oid_fromstr(&one, "1a443023183e3f2bfbef8ac923cd81c1018a18fd")); + cl_git_pass(git_oid_fromstr(&two, "9f13f7d0a9402c681f91dc590cf7b5470e6a77d2")); + cl_git_pass(git_merge_base(&result, _repo, &one, &two)); +} + +static void assert_mergebase_many(const char *expected_sha, int count, ...) +{ + va_list ap; + int i; + git_oid *oids; + git_oid oid, expected; + char *partial_oid; + git_object *object; + + oids = git__malloc(count * sizeof(git_oid)); + cl_assert(oids != NULL); + + memset(oids, 0x0, count * sizeof(git_oid)); + + va_start(ap, count); + + for (i = 0; i < count; ++i) { + partial_oid = va_arg(ap, char *); + cl_git_pass(git_oid_fromstrn(&oid, partial_oid, strlen(partial_oid))); + + cl_git_pass(git_object_lookup_prefix(&object, _repo, &oid, strlen(partial_oid), GIT_OBJ_COMMIT)); + git_oid_cpy(&oids[i], git_object_id(object)); + git_object_free(object); + } + + va_end(ap); + + if (expected_sha == NULL) + cl_assert_equal_i(GIT_ENOTFOUND, git_merge_base_many(&oid, _repo, count, oids)); + else { + cl_git_pass(git_merge_base_many(&oid, _repo, count, oids)); + cl_git_pass(git_oid_fromstr(&expected, expected_sha)); + + cl_assert(git_oid_cmp(&expected, &oid) == 0); + } + + git__free(oids); +} + +void test_revwalk_mergebase__many_no_common_ancestor_returns_ENOTFOUND(void) +{ + assert_mergebase_many(NULL, 3, "41bc8c", "e90810", "a65fed"); + assert_mergebase_many(NULL, 3, "e90810", "41bc8c", "a65fed"); + assert_mergebase_many(NULL, 3, "e90810", "a65fed", "41bc8c"); + assert_mergebase_many(NULL, 3, "a65fed", "e90810", "41bc8c"); + assert_mergebase_many(NULL, 3, "a65fed", "e90810", "41bc8c"); + assert_mergebase_many(NULL, 3, "a65fed", "41bc8c", "e90810"); + + assert_mergebase_many(NULL, 3, "e90810", "763d71", "a65fed"); +} + +void test_revwalk_mergebase__many_merge_branch(void) +{ + assert_mergebase_many("c47800c7266a2be04c571c04d5a6614691ea99bd", 3, "a65fed", "763d71", "849607"); + + assert_mergebase_many("c47800c7266a2be04c571c04d5a6614691ea99bd", 3, "763d71", "e90810", "a65fed"); + assert_mergebase_many("c47800c7266a2be04c571c04d5a6614691ea99bd", 3, "763d71", "a65fed", "e90810"); + + assert_mergebase_many("c47800c7266a2be04c571c04d5a6614691ea99bd", 3, "a65fed", "763d71", "849607"); + assert_mergebase_many("c47800c7266a2be04c571c04d5a6614691ea99bd", 3, "a65fed", "849607", "763d71"); + assert_mergebase_many("8496071c1b46c854b31185ea97743be6a8774479", 3, "849607", "a65fed", "763d71"); + + assert_mergebase_many("5b5b025afb0b4c913b4c338a42934a3863bf3644", 5, "5b5b02", "763d71", "a4a7dc", "a65fed", "41bc8c"); +} + +/* + * testrepo.git $ git log --graph --all + * * commit 763d71aadf09a7951596c9746c024e7eece7c7af + * | Author: nulltoken + * | Date: Sun Oct 9 12:54:47 2011 +0200 + * | + * | Add some files into subdirectories + * | + * | * commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750 + * | | Author: Scott Chacon + * | | Date: Tue Aug 9 19:33:46 2011 -0700 + * | | + * | * commit be3563ae3f795b2b4353bcce3a527ad0a4f7f644 + * | |\ Merge: 9fd738e c47800c + * | |/ Author: Scott Chacon + * |/| Date: Tue May 25 11:58:27 2010 -0700 + * | | + * | | Merge branch 'br2' + * | | + * | | * commit e90810b8df3e80c413d903f631643c716887138d + * | | | Author: Vicent Marti + * | | | Date: Thu Aug 5 18:42:20 2010 +0200 + * | | | + * | | | Test commit 2 + * | | | + * | | * commit 6dcf9bf7541ee10456529833502442f385010c3d + * | | Author: Vicent Marti + * | | Date: Thu Aug 5 18:41:33 2010 +0200 + * | | + * | | Test commit 1 + * | | + * | | * commit a4a7dce85cf63874e984719f4fdd239f5145052f + * | | |\ Merge: c47800c 9fd738e + * | |/ / Author: Scott Chacon + * |/| / Date: Tue May 25 12:00:23 2010 -0700 + * | |/ + * | | Merge branch 'master' into br2 + * | | + * | * commit 9fd738e8f7967c078dceed8190330fc8648ee56a + * | | Author: Scott Chacon + * | | Date: Mon May 24 10:19:19 2010 -0700 + * | | + * | | a fourth commit + * | | + * | * commit 4a202b346bb0fb0db7eff3cffeb3c70babbd2045 + * | | Author: Scott Chacon + * | | Date: Mon May 24 10:19:04 2010 -0700 + * | | + * | | a third commit + * | | + * * | commit c47800c7266a2be04c571c04d5a6614691ea99bd + * |/ Author: Scott Chacon + * | Date: Tue May 25 11:58:14 2010 -0700 + * | + * | branch commit one + * | + * * commit 5b5b025afb0b4c913b4c338a42934a3863bf3644 + * | Author: Scott Chacon + * | Date: Tue May 11 13:38:42 2010 -0700 + * | + * | another commit + * | + * * commit 8496071c1b46c854b31185ea97743be6a8774479 + * Author: Scott Chacon + * Date: Sat May 8 16:13:06 2010 -0700 + * + * testing + * + * * commit 41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9 + * | Author: Scott Chacon + * | Date: Tue May 11 13:40:41 2010 -0700 + * | + * | packed commit two + * | + * * commit 5001298e0c09ad9c34e4249bc5801c75e9754fa5 + * Author: Scott Chacon + * Date: Tue May 11 13:40:23 2010 -0700 + * + * packed commit one + */ + +/* + * twowaymerge.git $ git log --graph --all + * * commit 9b219343610c88a1187c996d0dc58330b55cee28 + * |\ Merge: c37a783 2224e19 + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:31:04 2012 -0800 + * | | + * | | Merge branch 'first-branch' into second-branch + * | | + * | * commit 2224e191514cb4bd8c566d80dac22dfcb1e9bb83 + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:28:51 2012 -0800 + * | | + * | | j + * | | + * | * commit a41a49f8f5cd9b6cb14a076bf8394881ed0b4d19 + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:28:39 2012 -0800 + * | | + * | | i + * | | + * | * commit 82bf9a1a10a4b25c1f14c9607b60970705e92545 + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:28:28 2012 -0800 + * | | + * | | h + * | | + * * | commit c37a783c20d92ac92362a78a32860f7eebf938ef + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:30:57 2012 -0800 + * | | + * | | n + * | | + * * | commit 8b82fb1794cb1c8c7f172ec730a4c2db0ae3e650 + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:30:43 2012 -0800 + * | | + * | | m + * | | + * * | commit 6ab5d28acbf3c3bdff276f7ccfdf29c1520e542f + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:30:38 2012 -0800 + * | | + * | | l + * | | + * * | commit 7b8c336c45fc6895c1c60827260fe5d798e5d247 + * | | Author: Scott J. Goldman + * | | Date: Tue Nov 27 20:30:24 2012 -0800 + * | | + * | | k + * | | + * | | * commit 1c30b88f5f3ee66d78df6520a7de9e89b890818b + * | | | Author: Scott J. Goldman + * | | | Date: Tue Nov 27 20:28:10 2012 -0800 + * | | | + * | | | e + * | | | + * | | * commit 42b7311aa626e712891940c1ec5d5cba201946a4 + * | | | Author: Scott J. Goldman + * | | | Date: Tue Nov 27 20:28:06 2012 -0800 + * | | | + * | | | d + * | | | + * | | * commit a953a018c5b10b20c86e69fef55ebc8ad4c5a417 + * | | |\ Merge: bd1732c cdf97fd + * | | |/ Author: Scott J. Goldman + * | |/| Date: Tue Nov 27 20:26:43 2012 -0800 + * | | | + * | | | Merge branch 'first-branch' + * | | | + * | * | commit cdf97fd3bb48eb3827638bb33d208f5fd32d0aa6 + * | | | Author: Scott J. Goldman + * | | | Date: Tue Nov 27 20:24:46 2012 -0800 + * | | | + * | | | g + * | | | + * | * | commit ef0488f0b722f0be8bcb90a7730ac7efafd1d694 + * | | | Author: Scott J. Goldman + * | | | Date: Tue Nov 27 20:24:39 2012 -0800 + * | | | + * | | | f + * | | | + * | | * commit bd1732c43c68d712ad09e1d872b9be6d4b9efdc4 + * | |/ Author: Scott J. Goldman + * | | Date: Tue Nov 27 17:43:58 2012 -0800 + * | | + * | | c + * | | + * | * commit 0c8a3f1f3d5f421cf83048c7c73ee3b55a5e0f29 + * |/ Author: Scott J. Goldman + * | Date: Tue Nov 27 17:43:48 2012 -0800 + * | + * | b + * | + * * commit 1f4c0311a24b63f6fc209a59a1e404942d4a5006 + * Author: Scott J. Goldman + * Date: Tue Nov 27 17:43:41 2012 -0800 + * + * a + */ diff --git a/tests/revwalk/signatureparsing.c b/tests/revwalk/signatureparsing.c new file mode 100644 index 000000000..5c7d8813d --- /dev/null +++ b/tests/revwalk/signatureparsing.c @@ -0,0 +1,47 @@ +#include "clar_libgit2.h" + +static git_repository *_repo; +static git_revwalk *_walk; + +void test_revwalk_signatureparsing__initialize(void) +{ + cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_revwalk_new(&_walk, _repo)); +} + +void test_revwalk_signatureparsing__cleanup(void) +{ + git_revwalk_free(_walk); + _walk = NULL; + + git_repository_free(_repo); + _repo = NULL; +} + +void test_revwalk_signatureparsing__do_not_choke_when_name_contains_angle_brackets(void) +{ + git_reference *ref; + git_oid commit_oid; + git_commit *commit; + const git_signature *signature; + + /* + * The branch below points at a commit with angle brackets in the committer/author name + * committer 1323847743 +0100 + */ + cl_git_pass(git_reference_lookup(&ref, _repo, "refs/heads/haacked")); + + git_revwalk_push(_walk, git_reference_target(ref)); + cl_git_pass(git_revwalk_next(&commit_oid, _walk)); + + cl_git_pass(git_commit_lookup(&commit, _repo, git_reference_target(ref))); + + signature = git_commit_committer(commit); + cl_assert_equal_s("foo@example.com", signature->email); + cl_assert_equal_s("", signature->name); + cl_assert_equal_i(1323847743, (int)signature->when.time); + cl_assert_equal_i(60, signature->when.offset); + + git_commit_free(commit); + git_reference_free(ref); +} diff --git a/tests/revwalk/simplify.c b/tests/revwalk/simplify.c new file mode 100644 index 000000000..81c19d366 --- /dev/null +++ b/tests/revwalk/simplify.c @@ -0,0 +1,55 @@ +#include "clar_libgit2.h" + +void test_revwalk_simplify__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +/* + * a4a7dce [0] Merge branch 'master' into br2 + |\ + | * 9fd738e [1] a fourth commit + | * 4a202b3 [2] a third commit + * | c47800c [3] branch commit one + |/ + * 5b5b025 [5] another commit + * 8496071 [4] testing +*/ +static const char *commit_head = "a4a7dce85cf63874e984719f4fdd239f5145052f"; + +static const char *expected_str[] = { + "a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */ + "c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */ + "8496071c1b46c854b31185ea97743be6a8774479", /* 4 */ + "5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */ +}; + +void test_revwalk_simplify__first_parent(void) +{ + git_repository *repo; + git_revwalk *walk; + git_oid id, expected[4]; + int i, error; + + for (i = 0; i < 4; i++) { + git_oid_fromstr(&expected[i], expected_str[i]); + } + + repo = cl_git_sandbox_init("testrepo.git"); + cl_git_pass(git_revwalk_new(&walk, repo)); + + git_oid_fromstr(&id, commit_head); + cl_git_pass(git_revwalk_push(walk, &id)); + git_revwalk_simplify_first_parent(walk); + + i = 0; + while ((error = git_revwalk_next(&id, walk)) == 0) { + git_oid_cmp(&id, &expected[i]); + i++; + } + + cl_assert_equal_i(i, 4); + cl_assert_equal_i(error, GIT_ITEROVER); + + git_revwalk_free(walk); +} diff --git a/tests/stash/drop.c b/tests/stash/drop.c new file mode 100644 index 000000000..63ff0377c --- /dev/null +++ b/tests/stash/drop.c @@ -0,0 +1,174 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "stash_helpers.h" +#include "refs.h" + +static git_repository *repo; +static git_signature *signature; + +void test_stash_drop__initialize(void) +{ + cl_git_pass(git_repository_init(&repo, "stash", 0)); + cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ +} + +void test_stash_drop__cleanup(void) +{ + git_signature_free(signature); + signature = NULL; + + git_repository_free(repo); + repo = NULL; + + cl_git_pass(git_futils_rmdir_r("stash", NULL, GIT_RMDIR_REMOVE_FILES)); +} + +void test_stash_drop__cannot_drop_from_an_empty_stash(void) +{ + cl_git_fail_with(git_stash_drop(repo, 0), GIT_ENOTFOUND); +} + +static void push_three_states(void) +{ + git_oid oid; + git_index *index; + + cl_git_mkfile("stash/zero.txt", "content\n"); + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_bypath(index, "zero.txt")); + cl_repo_commit_from_index(NULL, repo, signature, 0, "Initial commit"); + cl_assert(git_path_exists("stash/zero.txt")); + git_index_free(index); + + cl_git_mkfile("stash/one.txt", "content\n"); + cl_git_pass(git_stash_save( + &oid, repo, signature, "First", GIT_STASH_INCLUDE_UNTRACKED)); + cl_assert(!git_path_exists("stash/one.txt")); + cl_assert(git_path_exists("stash/zero.txt")); + + cl_git_mkfile("stash/two.txt", "content\n"); + cl_git_pass(git_stash_save( + &oid, repo, signature, "Second", GIT_STASH_INCLUDE_UNTRACKED)); + cl_assert(!git_path_exists("stash/two.txt")); + cl_assert(git_path_exists("stash/zero.txt")); + + cl_git_mkfile("stash/three.txt", "content\n"); + cl_git_pass(git_stash_save( + &oid, repo, signature, "Third", GIT_STASH_INCLUDE_UNTRACKED)); + cl_assert(!git_path_exists("stash/three.txt")); + cl_assert(git_path_exists("stash/zero.txt")); +} + +void test_stash_drop__cannot_drop_a_non_existing_stashed_state(void) +{ + push_three_states(); + + cl_git_fail_with(git_stash_drop(repo, 666), GIT_ENOTFOUND); + cl_git_fail_with(git_stash_drop(repo, 42), GIT_ENOTFOUND); + cl_git_fail_with(git_stash_drop(repo, 3), GIT_ENOTFOUND); +} + +void test_stash_drop__can_purge_the_stash_from_the_top(void) +{ + push_three_states(); + + cl_git_pass(git_stash_drop(repo, 0)); + cl_git_pass(git_stash_drop(repo, 0)); + cl_git_pass(git_stash_drop(repo, 0)); + + cl_git_fail_with(git_stash_drop(repo, 0), GIT_ENOTFOUND); +} + +void test_stash_drop__can_purge_the_stash_from_the_bottom(void) +{ + push_three_states(); + + cl_git_pass(git_stash_drop(repo, 2)); + cl_git_pass(git_stash_drop(repo, 1)); + cl_git_pass(git_stash_drop(repo, 0)); + + cl_git_fail_with(git_stash_drop(repo, 0), GIT_ENOTFOUND); +} + +void test_stash_drop__dropping_an_entry_rewrites_reflog_history(void) +{ + git_reference *stash; + git_reflog *reflog; + const git_reflog_entry *entry; + git_oid oid; + size_t count; + + push_three_states(); + + cl_git_pass(git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE)); + + cl_git_pass(git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)); + entry = git_reflog_entry_byindex(reflog, 1); + + git_oid_cpy(&oid, git_reflog_entry_id_old(entry)); + count = git_reflog_entrycount(reflog); + + git_reflog_free(reflog); + + cl_git_pass(git_stash_drop(repo, 1)); + + cl_git_pass(git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)); + entry = git_reflog_entry_byindex(reflog, 0); + + cl_assert_equal_i(0, git_oid_cmp(&oid, git_reflog_entry_id_old(entry))); + cl_assert_equal_sz(count - 1, git_reflog_entrycount(reflog)); + + git_reflog_free(reflog); + + git_reference_free(stash); +} + +void test_stash_drop__dropping_the_last_entry_removes_the_stash(void) +{ + git_reference *stash; + + push_three_states(); + + cl_git_pass(git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE)); + git_reference_free(stash); + + cl_git_pass(git_stash_drop(repo, 0)); + cl_git_pass(git_stash_drop(repo, 0)); + cl_git_pass(git_stash_drop(repo, 0)); + + cl_git_fail_with( + git_reference_lookup(&stash, repo, GIT_REFS_STASH_FILE), GIT_ENOTFOUND); +} + +void retrieve_top_stash_id(git_oid *out) +{ + git_object *top_stash; + + cl_git_pass(git_revparse_single(&top_stash, repo, "stash@{0}")); + cl_git_pass(git_reference_name_to_id(out, repo, GIT_REFS_STASH_FILE)); + + cl_assert_equal_i(true, git_oid_cmp(out, git_object_id(top_stash)) == 0); + + git_object_free(top_stash); +} + +void test_stash_drop__dropping_the_top_stash_updates_the_stash_reference(void) +{ + git_object *next_top_stash; + git_oid oid; + + push_three_states(); + + retrieve_top_stash_id(&oid); + + cl_git_pass(git_revparse_single(&next_top_stash, repo, "stash@{1}")); + cl_assert(git_oid_cmp(&oid, git_object_id(next_top_stash)) != 0); + + cl_git_pass(git_stash_drop(repo, 0)); + + retrieve_top_stash_id(&oid); + + cl_git_pass(git_oid_cmp(&oid, git_object_id(next_top_stash))); + + git_object_free(next_top_stash); +} diff --git a/tests/stash/foreach.c b/tests/stash/foreach.c new file mode 100644 index 000000000..f1983625f --- /dev/null +++ b/tests/stash/foreach.c @@ -0,0 +1,124 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "stash_helpers.h" + +struct callback_data +{ + char **oids; + int invokes; +}; + +static git_repository *repo; +static git_signature *signature; +static git_oid stash_tip_oid; +struct callback_data data; + +#define REPO_NAME "stash" + +void test_stash_foreach__initialize(void) +{ + cl_git_pass(git_signature_new( + &signature, + "nulltoken", + "emeric.fermas@gmail.com", + 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ + + memset(&data, 0, sizeof(struct callback_data)); +} + +void test_stash_foreach__cleanup(void) +{ + git_signature_free(signature); + signature = NULL; + + git_repository_free(repo); + repo = NULL; + + cl_git_pass(git_futils_rmdir_r(REPO_NAME, NULL, GIT_RMDIR_REMOVE_FILES)); +} + +static int callback_cb( + size_t index, + const char* message, + const git_oid *stash_oid, + void *payload) +{ + struct callback_data *data = (struct callback_data *)payload; + + GIT_UNUSED(index); + GIT_UNUSED(message); + + cl_assert_equal_i(0, git_oid_streq(stash_oid, data->oids[data->invokes++])); + + return 0; +} + +void test_stash_foreach__enumerating_a_empty_repository_doesnt_fail(void) +{ + char *oids[] = { NULL }; + + data.oids = oids; + + cl_git_pass(git_repository_init(&repo, REPO_NAME, 0)); + + cl_git_pass(git_stash_foreach(repo, callback_cb, &data)); + + cl_assert_equal_i(0, data.invokes); +} + +void test_stash_foreach__can_enumerate_a_repository(void) +{ + char *oids_default[] = { + "1d91c842a7cdfc25872b3a763e5c31add8816c25", NULL }; + + char *oids_untracked[] = { + "7f89a8b15c878809c5c54d1ff8f8c9674154017b", + "1d91c842a7cdfc25872b3a763e5c31add8816c25", NULL }; + + char *oids_ignored[] = { + "c95599a8fef20a7e57582c6727b1a0d02e0a5828", + "7f89a8b15c878809c5c54d1ff8f8c9674154017b", + "1d91c842a7cdfc25872b3a763e5c31add8816c25", NULL }; + + cl_git_pass(git_repository_init(&repo, REPO_NAME, 0)); + + setup_stash(repo, signature); + + cl_git_pass(git_stash_save( + &stash_tip_oid, + repo, + signature, + NULL, + GIT_STASH_DEFAULT)); + + data.oids = oids_default; + + cl_git_pass(git_stash_foreach(repo, callback_cb, &data)); + cl_assert_equal_i(1, data.invokes); + + data.oids = oids_untracked; + data.invokes = 0; + + cl_git_pass(git_stash_save( + &stash_tip_oid, + repo, + signature, + NULL, + GIT_STASH_INCLUDE_UNTRACKED)); + + cl_git_pass(git_stash_foreach(repo, callback_cb, &data)); + cl_assert_equal_i(2, data.invokes); + + data.oids = oids_ignored; + data.invokes = 0; + + cl_git_pass(git_stash_save( + &stash_tip_oid, + repo, + signature, + NULL, + GIT_STASH_INCLUDE_IGNORED)); + + cl_git_pass(git_stash_foreach(repo, callback_cb, &data)); + cl_assert_equal_i(3, data.invokes); +} diff --git a/tests/stash/save.c b/tests/stash/save.c new file mode 100644 index 000000000..3d92b26bd --- /dev/null +++ b/tests/stash/save.c @@ -0,0 +1,354 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "stash_helpers.h" + +static git_repository *repo; +static git_signature *signature; +static git_oid stash_tip_oid; + +/* + * Friendly reminder, in order to ease the reading of the following tests: + * + * "stash" points to the worktree commit + * "stash^1" points to the base commit (HEAD when the stash was created) + * "stash^2" points to the index commit + * "stash^3" points to the untracked commit + */ + +void test_stash_save__initialize(void) +{ + cl_git_pass(git_repository_init(&repo, "stash", 0)); + cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ + + setup_stash(repo, signature); +} + +void test_stash_save__cleanup(void) +{ + git_signature_free(signature); + signature = NULL; + + git_repository_free(repo); + repo = NULL; + + cl_git_pass(git_futils_rmdir_r("stash", NULL, GIT_RMDIR_REMOVE_FILES)); + cl_fixture_cleanup("sorry-it-is-a-non-bare-only-party"); +} + +static void assert_object_oid(const char* revision, const char* expected_oid, git_otype type) +{ + int result; + git_object *obj; + + result = git_revparse_single(&obj, repo, revision); + + if (!expected_oid) { + cl_assert_equal_i(GIT_ENOTFOUND, result); + return; + } else + cl_assert_equal_i(0, result); + + cl_git_pass(git_oid_streq(git_object_id(obj), expected_oid)); + cl_assert_equal_i(type, git_object_type(obj)); + git_object_free(obj); +} + +static void assert_blob_oid(const char* revision, const char* expected_oid) +{ + assert_object_oid(revision, expected_oid, GIT_OBJ_BLOB); +} + +void test_stash_save__does_not_keep_index_by_default(void) +{ +/* +$ git stash + +$ git show refs/stash:what +see you later + +$ git show refs/stash:how +not so small and + +$ git show refs/stash:who +funky world + +$ git show refs/stash:when +fatal: Path 'when' exists on disk, but not in 'stash'. + +$ git show refs/stash^2:what +goodbye + +$ git show refs/stash^2:how +not so small and + +$ git show refs/stash^2:who +world + +$ git show refs/stash^2:when +fatal: Path 'when' exists on disk, but not in 'stash^2'. + +$ git status --short +?? when + +*/ + unsigned int status; + + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); + cl_git_pass(git_status_file(&status, repo, "when")); + + assert_blob_oid("refs/stash:what", "bc99dc98b3eba0e9157e94769cd4d49cb49de449"); /* see you later */ + assert_blob_oid("refs/stash:how", "e6d64adb2c7f3eb8feb493b556cc8070dca379a3"); /* not so small and */ + assert_blob_oid("refs/stash:who", "a0400d4954659306a976567af43125a0b1aa8595"); /* funky world */ + assert_blob_oid("refs/stash:when", NULL); + assert_blob_oid("refs/stash:just.ignore", NULL); + + assert_blob_oid("refs/stash^2:what", "dd7e1c6f0fefe118f0b63d9f10908c460aa317a6"); /* goodbye */ + assert_blob_oid("refs/stash^2:how", "e6d64adb2c7f3eb8feb493b556cc8070dca379a3"); /* not so small and */ + assert_blob_oid("refs/stash^2:who", "cc628ccd10742baea8241c5924df992b5c019f71"); /* world */ + assert_blob_oid("refs/stash^2:when", NULL); + assert_blob_oid("refs/stash^2:just.ignore", NULL); + + assert_blob_oid("refs/stash^3", NULL); + + cl_assert_equal_i(GIT_STATUS_WT_NEW, status); +} + +void test_stash_save__can_keep_index(void) +{ + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_KEEP_INDEX)); + + assert_status(repo, "what", GIT_STATUS_INDEX_MODIFIED); + assert_status(repo, "how", GIT_STATUS_INDEX_MODIFIED); + assert_status(repo, "who", GIT_STATUS_CURRENT); + assert_status(repo, "when", GIT_STATUS_WT_NEW); + assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); +} + +static void assert_commit_message_contains(const char *revision, const char *fragment) +{ + git_commit *commit; + + cl_git_pass(git_revparse_single((git_object**)&commit, repo, revision)); + + cl_assert(strstr(git_commit_message(commit), fragment) != NULL); + + git_commit_free(commit); +} + +void test_stash_save__can_include_untracked_files(void) +{ + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); + + assert_commit_message_contains("refs/stash^3", "untracked files on master: "); + + assert_blob_oid("refs/stash^3:what", NULL); + assert_blob_oid("refs/stash^3:how", NULL); + assert_blob_oid("refs/stash^3:who", NULL); + assert_blob_oid("refs/stash^3:when", "b6ed15e81e2593d7bb6265eb4a991d29dc3e628b"); + assert_blob_oid("refs/stash^3:just.ignore", NULL); +} + +void test_stash_save__can_include_untracked_and_ignored_files(void) +{ + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED | GIT_STASH_INCLUDE_IGNORED)); + + assert_commit_message_contains("refs/stash^3", "untracked files on master: "); + + assert_blob_oid("refs/stash^3:what", NULL); + assert_blob_oid("refs/stash^3:how", NULL); + assert_blob_oid("refs/stash^3:who", NULL); + assert_blob_oid("refs/stash^3:when", "b6ed15e81e2593d7bb6265eb4a991d29dc3e628b"); + assert_blob_oid("refs/stash^3:just.ignore", "78925fb1236b98b37a35e9723033e627f97aa88b"); +} + +#define MESSAGE "Look Ma! I'm on TV!" +void test_stash_save__can_accept_a_message(void) +{ + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, MESSAGE, GIT_STASH_DEFAULT)); + + assert_commit_message_contains("refs/stash^2", "index on master: "); + assert_commit_message_contains("refs/stash", "On master: " MESSAGE); +} + +void test_stash_save__cannot_stash_against_an_unborn_branch(void) +{ + git_reference *head; + + cl_git_pass(git_reference_symbolic_create(&head, repo, "HEAD", "refs/heads/unborn", 1)); + + cl_assert_equal_i(GIT_EUNBORNBRANCH, + git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); + + git_reference_free(head); +} + +void test_stash_save__cannot_stash_against_a_bare_repository(void) +{ + git_repository *local; + + cl_git_pass(git_repository_init(&local, "sorry-it-is-a-non-bare-only-party", 1)); + + cl_assert_equal_i(GIT_EBAREREPO, + git_stash_save(&stash_tip_oid, local, signature, NULL, GIT_STASH_DEFAULT)); + + git_repository_free(local); +} + +void test_stash_save__can_stash_against_a_detached_head(void) +{ + git_repository_detach_head(repo); + + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); + + assert_commit_message_contains("refs/stash^2", "index on (no branch): "); + assert_commit_message_contains("refs/stash", "WIP on (no branch): "); +} + +void test_stash_save__stashing_updates_the_reflog(void) +{ + char *sha; + + assert_object_oid("refs/stash@{0}", NULL, GIT_OBJ_COMMIT); + + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); + + sha = git_oid_allocfmt(&stash_tip_oid); + + assert_object_oid("refs/stash@{0}", sha, GIT_OBJ_COMMIT); + assert_object_oid("refs/stash@{1}", NULL, GIT_OBJ_COMMIT); + + git__free(sha); +} + +void test_stash_save__cannot_stash_when_there_are_no_local_change(void) +{ + git_index *index; + git_oid stash_tip_oid; + + cl_git_pass(git_repository_index(&index, repo)); + + /* + * 'what' and 'who' are being committed. + * 'when' remain untracked. + */ + cl_git_pass(git_index_add_bypath(index, "what")); + cl_git_pass(git_index_add_bypath(index, "who")); + cl_repo_commit_from_index(NULL, repo, signature, 0, "Initial commit"); + git_index_free(index); + + cl_assert_equal_i(GIT_ENOTFOUND, + git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); + + p_unlink("stash/when"); + cl_assert_equal_i(GIT_ENOTFOUND, + git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); +} + +void test_stash_save__can_stage_normal_then_stage_untracked(void) +{ + /* + * $ git ls-tree stash@{1}^0 + * 100644 blob ac4d88de61733173d9959e4b77c69b9f17a00980 .gitignore + * 100644 blob e6d64adb2c7f3eb8feb493b556cc8070dca379a3 how + * 100644 blob bc99dc98b3eba0e9157e94769cd4d49cb49de449 what + * 100644 blob a0400d4954659306a976567af43125a0b1aa8595 who + * + * $ git ls-tree stash@{1}^1 + * 100644 blob ac4d88de61733173d9959e4b77c69b9f17a00980 .gitignore + * 100644 blob ac790413e2d7a26c3767e78c57bb28716686eebc how + * 100644 blob ce013625030ba8dba906f756967f9e9ca394464a what + * 100644 blob cc628ccd10742baea8241c5924df992b5c019f71 who + * + * $ git ls-tree stash@{1}^2 + * 100644 blob ac4d88de61733173d9959e4b77c69b9f17a00980 .gitignore + * 100644 blob e6d64adb2c7f3eb8feb493b556cc8070dca379a3 how + * 100644 blob dd7e1c6f0fefe118f0b63d9f10908c460aa317a6 what + * 100644 blob cc628ccd10742baea8241c5924df992b5c019f71 who + * + * $ git ls-tree stash@{1}^3 + * fatal: Not a valid object name stash@{1}^3 + * + * $ git ls-tree stash@{0}^0 + * 100644 blob ac4d88de61733173d9959e4b77c69b9f17a00980 .gitignore + * 100644 blob ac790413e2d7a26c3767e78c57bb28716686eebc how + * 100644 blob ce013625030ba8dba906f756967f9e9ca394464a what + * 100644 blob cc628ccd10742baea8241c5924df992b5c019f71 who + * + * $ git ls-tree stash@{0}^1 + * 100644 blob ac4d88de61733173d9959e4b77c69b9f17a00980 .gitignore + * 100644 blob ac790413e2d7a26c3767e78c57bb28716686eebc how + * 100644 blob ce013625030ba8dba906f756967f9e9ca394464a what + * 100644 blob cc628ccd10742baea8241c5924df992b5c019f71 who + * + * $ git ls-tree stash@{0}^2 + * 100644 blob ac4d88de61733173d9959e4b77c69b9f17a00980 .gitignore + * 100644 blob ac790413e2d7a26c3767e78c57bb28716686eebc how + * 100644 blob ce013625030ba8dba906f756967f9e9ca394464a what + * 100644 blob cc628ccd10742baea8241c5924df992b5c019f71 who + * + * $ git ls-tree stash@{0}^3 + * 100644 blob b6ed15e81e2593d7bb6265eb4a991d29dc3e628b when + */ + + assert_status(repo, "what", GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED); + assert_status(repo, "how", GIT_STATUS_INDEX_MODIFIED); + assert_status(repo, "who", GIT_STATUS_WT_MODIFIED); + assert_status(repo, "when", GIT_STATUS_WT_NEW); + assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); + + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); + assert_status(repo, "what", GIT_STATUS_CURRENT); + assert_status(repo, "how", GIT_STATUS_CURRENT); + assert_status(repo, "who", GIT_STATUS_CURRENT); + assert_status(repo, "when", GIT_STATUS_WT_NEW); + assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); + + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); + assert_status(repo, "what", GIT_STATUS_CURRENT); + assert_status(repo, "how", GIT_STATUS_CURRENT); + assert_status(repo, "who", GIT_STATUS_CURRENT); + assert_status(repo, "when", GIT_ENOTFOUND); + assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); + + + assert_blob_oid("stash@{1}^0:what", "bc99dc98b3eba0e9157e94769cd4d49cb49de449"); /* see you later */ + assert_blob_oid("stash@{1}^0:how", "e6d64adb2c7f3eb8feb493b556cc8070dca379a3"); /* not so small and */ + assert_blob_oid("stash@{1}^0:who", "a0400d4954659306a976567af43125a0b1aa8595"); /* funky world */ + assert_blob_oid("stash@{1}^0:when", NULL); + + assert_blob_oid("stash@{1}^2:what", "dd7e1c6f0fefe118f0b63d9f10908c460aa317a6"); /* goodbye */ + assert_blob_oid("stash@{1}^2:how", "e6d64adb2c7f3eb8feb493b556cc8070dca379a3"); /* not so small and */ + assert_blob_oid("stash@{1}^2:who", "cc628ccd10742baea8241c5924df992b5c019f71"); /* world */ + assert_blob_oid("stash@{1}^2:when", NULL); + + assert_object_oid("stash@{1}^3", NULL, GIT_OBJ_COMMIT); + + assert_blob_oid("stash@{0}^0:what", "ce013625030ba8dba906f756967f9e9ca394464a"); /* hello */ + assert_blob_oid("stash@{0}^0:how", "ac790413e2d7a26c3767e78c57bb28716686eebc"); /* small */ + assert_blob_oid("stash@{0}^0:who", "cc628ccd10742baea8241c5924df992b5c019f71"); /* world */ + assert_blob_oid("stash@{0}^0:when", NULL); + + assert_blob_oid("stash@{0}^2:what", "ce013625030ba8dba906f756967f9e9ca394464a"); /* hello */ + assert_blob_oid("stash@{0}^2:how", "ac790413e2d7a26c3767e78c57bb28716686eebc"); /* small */ + assert_blob_oid("stash@{0}^2:who", "cc628ccd10742baea8241c5924df992b5c019f71"); /* world */ + assert_blob_oid("stash@{0}^2:when", NULL); + + assert_blob_oid("stash@{0}^3:when", "b6ed15e81e2593d7bb6265eb4a991d29dc3e628b"); /* now */ +} + +#define EMPTY_TREE "4b825dc642cb6eb9a060e54bf8d69288fbee4904" + +void test_stash_save__including_untracked_without_any_untracked_file_creates_an_empty_tree(void) +{ + cl_git_pass(p_unlink("stash/when")); + + assert_status(repo, "what", GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED); + assert_status(repo, "how", GIT_STATUS_INDEX_MODIFIED); + assert_status(repo, "who", GIT_STATUS_WT_MODIFIED); + assert_status(repo, "when", GIT_ENOTFOUND); + assert_status(repo, "just.ignore", GIT_STATUS_IGNORED); + + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); + + assert_object_oid("stash^3^{tree}", EMPTY_TREE, GIT_OBJ_TREE); +} diff --git a/tests/stash/stash_helpers.c b/tests/stash/stash_helpers.c new file mode 100644 index 000000000..8b7d685f8 --- /dev/null +++ b/tests/stash/stash_helpers.c @@ -0,0 +1,56 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "stash_helpers.h" + +void setup_stash(git_repository *repo, git_signature *signature) +{ + git_index *index; + + cl_git_pass(git_repository_index(&index, repo)); + + cl_git_mkfile("stash/what", "hello\n"); /* ce013625030ba8dba906f756967f9e9ca394464a */ + cl_git_mkfile("stash/how", "small\n"); /* ac790413e2d7a26c3767e78c57bb28716686eebc */ + cl_git_mkfile("stash/who", "world\n"); /* cc628ccd10742baea8241c5924df992b5c019f71 */ + cl_git_mkfile("stash/when", "now\n"); /* b6ed15e81e2593d7bb6265eb4a991d29dc3e628b */ + cl_git_mkfile("stash/just.ignore", "me\n"); /* 78925fb1236b98b37a35e9723033e627f97aa88b */ + + cl_git_mkfile("stash/.gitignore", "*.ignore\n"); + + cl_git_pass(git_index_add_bypath(index, "what")); + cl_git_pass(git_index_add_bypath(index, "how")); + cl_git_pass(git_index_add_bypath(index, "who")); + cl_git_pass(git_index_add_bypath(index, ".gitignore")); + + cl_repo_commit_from_index(NULL, repo, signature, 0, "Initial commit"); + + cl_git_rewritefile("stash/what", "goodbye\n"); /* dd7e1c6f0fefe118f0b63d9f10908c460aa317a6 */ + cl_git_rewritefile("stash/how", "not so small and\n"); /* e6d64adb2c7f3eb8feb493b556cc8070dca379a3 */ + cl_git_rewritefile("stash/who", "funky world\n"); /* a0400d4954659306a976567af43125a0b1aa8595 */ + + cl_git_pass(git_index_add_bypath(index, "what")); + cl_git_pass(git_index_add_bypath(index, "how")); + cl_git_pass(git_index_write(index)); + + cl_git_rewritefile("stash/what", "see you later\n"); /* bc99dc98b3eba0e9157e94769cd4d49cb49de449 */ + + git_index_free(index); +} + +void assert_status( + git_repository *repo, + const char *path, + int status_flags) +{ + unsigned int status; + int error; + + error = git_status_file(&status, repo, path); + + if (status_flags < 0) { + cl_assert_equal_i(status_flags, error); + return; + } + + cl_assert_equal_i(0, error); + cl_assert_equal_i((unsigned int)status_flags, status); +} diff --git a/tests/stash/stash_helpers.h b/tests/stash/stash_helpers.h new file mode 100644 index 000000000..66d758fe2 --- /dev/null +++ b/tests/stash/stash_helpers.h @@ -0,0 +1,8 @@ +void setup_stash( + git_repository *repo, + git_signature *signature); + +void assert_status( + git_repository *repo, + const char *path, + int status_flags); diff --git a/tests/stash/submodules.c b/tests/stash/submodules.c new file mode 100644 index 000000000..137c4408c --- /dev/null +++ b/tests/stash/submodules.c @@ -0,0 +1,80 @@ +#include "clar_libgit2.h" +#include "stash_helpers.h" +#include "../submodule/submodule_helpers.h" + +static git_repository *repo; +static git_signature *signature; +static git_oid stash_tip_oid; + +static git_submodule *sm; + +void test_stash_submodules__initialize(void) +{ + cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ + + repo = setup_fixture_submodules(); + + cl_git_pass(git_submodule_lookup(&sm, repo, "testrepo")); +} + +void test_stash_submodules__cleanup(void) +{ + git_signature_free(signature); + signature = NULL; +} + +void test_stash_submodules__does_not_stash_modified_submodules(void) +{ + static git_index *smindex; + static git_repository *smrepo; + + assert_status(repo, "modified", GIT_STATUS_WT_MODIFIED); + + /* modify file in submodule */ + cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); + assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); + + /* add file to index in submodule */ + cl_git_pass(git_submodule_open(&smrepo, sm)); + cl_git_pass(git_repository_index(&smindex, smrepo)); + cl_git_pass(git_index_add_bypath(smindex, "README")); + + /* commit changed index of submodule */ + cl_repo_commit_from_index(NULL, smrepo, NULL, 1372350000, "Modify it"); + assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); + + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); + + assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); + assert_status(repo, "modified", GIT_STATUS_CURRENT); + + git_index_free(smindex); + git_repository_free(smrepo); +} + +void test_stash_submodules__stash_is_empty_with_modified_submodules(void) +{ + static git_index *smindex; + static git_repository *smrepo; + + cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT)); + assert_status(repo, "modified", GIT_STATUS_CURRENT); + + /* modify file in submodule */ + cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); + assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); + + /* add file to index in submodule */ + cl_git_pass(git_submodule_open(&smrepo, sm)); + cl_git_pass(git_repository_index(&smindex, smrepo)); + cl_git_pass(git_index_add_bypath(smindex, "README")); + + /* commit changed index of submodule */ + cl_repo_commit_from_index(NULL, smrepo, NULL, 1372350000, "Modify it"); + assert_status(repo, "testrepo", GIT_STATUS_WT_MODIFIED); + + cl_git_fail_with(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_DEFAULT), GIT_ENOTFOUND); + + git_index_free(smindex); + git_repository_free(smrepo); +} diff --git a/tests/status/ignore.c b/tests/status/ignore.c new file mode 100644 index 000000000..acdc8fb58 --- /dev/null +++ b/tests/status/ignore.c @@ -0,0 +1,582 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "git2/attr.h" +#include "ignore.h" +#include "attr.h" +#include "status_helpers.h" + +static git_repository *g_repo = NULL; + +void test_status_ignore__initialize(void) +{ +} + +void test_status_ignore__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_status_ignore__0(void) +{ + struct { + const char *path; + int expected; + } test_cases[] = { + /* pattern "ign" from .gitignore */ + { "file", 0 }, + { "ign", 1 }, + { "sub", 0 }, + { "sub/file", 0 }, + { "sub/ign", 1 }, + { "sub/ign/file", 1 }, + { "sub/ign/sub", 1 }, + { "sub/ign/sub/file", 1 }, + { "sub/sub", 0 }, + { "sub/sub/file", 0 }, + { "sub/sub/ign", 1 }, + { "sub/sub/sub", 0 }, + /* pattern "dir/" from .gitignore */ + { "dir", 1 }, + { "dir/", 1 }, + { "sub/dir", 1 }, + { "sub/dir/", 1 }, + { "sub/dir/file", 1 }, /* contained in ignored parent */ + { "sub/sub/dir", 0 }, /* dir is not actually a dir, but a file */ + { NULL, 0 } + }, *one_test; + + g_repo = cl_git_sandbox_init("attr"); + + for (one_test = test_cases; one_test->path != NULL; one_test++) { + int ignored; + cl_git_pass(git_status_should_ignore(&ignored, g_repo, one_test->path)); + cl_assert_(ignored == one_test->expected, one_test->path); + } + + /* confirm that ignore files were cached */ + cl_assert(git_attr_cache__is_cached(g_repo, 0, ".git/info/exclude")); + cl_assert(git_attr_cache__is_cached(g_repo, 0, ".gitignore")); +} + + +void test_status_ignore__1(void) +{ + int ignored; + + g_repo = cl_git_sandbox_init("attr"); + + cl_git_rewritefile("attr/.gitignore", "/*.txt\n/dir/\n"); + git_attr_cache_flush(g_repo); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "root_test4.txt")); + cl_assert(ignored); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "sub/subdir_test2.txt")); + cl_assert(!ignored); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "dir")); + cl_assert(ignored); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "dir/")); + cl_assert(ignored); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "sub/dir")); + cl_assert(!ignored); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "sub/dir/")); + cl_assert(!ignored); +} + + +void test_status_ignore__empty_repo_with_gitignore_rewrite(void) +{ + status_entry_single st; + int ignored; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_mkfile( + "empty_standard_repo/look-ma.txt", "I'm going to be ignored!"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); + cl_assert(st.count == 1); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "look-ma.txt")); + cl_assert(!ignored); + + cl_git_rewritefile("empty_standard_repo/.gitignore", "*.nomatch\n"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); + cl_assert(st.count == 2); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "look-ma.txt")); + cl_assert(!ignored); + + cl_git_rewritefile("empty_standard_repo/.gitignore", "*.txt\n"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); + cl_assert(st.count == 2); + cl_assert(st.status == GIT_STATUS_IGNORED); + + cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); + cl_assert(st.status == GIT_STATUS_IGNORED); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "look-ma.txt")); + cl_assert(ignored); +} + +void test_status_ignore__ignore_pattern_contains_space(void) +{ + unsigned int flags; + const mode_t mode = 0777; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_rewritefile("empty_standard_repo/.gitignore", "foo bar.txt\n"); + + cl_git_mkfile( + "empty_standard_repo/foo bar.txt", "I'm going to be ignored!"); + + cl_git_pass(git_status_file(&flags, g_repo, "foo bar.txt")); + cl_assert(flags == GIT_STATUS_IGNORED); + + cl_git_pass(git_futils_mkdir_r("empty_standard_repo/foo", NULL, mode)); + cl_git_mkfile("empty_standard_repo/foo/look-ma.txt", "I'm not going to be ignored!"); + + cl_git_pass(git_status_file(&flags, g_repo, "foo/look-ma.txt")); + cl_assert(flags == GIT_STATUS_WT_NEW); +} + +void test_status_ignore__ignore_pattern_ignorecase(void) +{ + unsigned int flags; + bool ignore_case; + git_index *index; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_rewritefile("empty_standard_repo/.gitignore", "a.txt\n"); + + cl_git_mkfile("empty_standard_repo/A.txt", "Differs in case"); + + cl_git_pass(git_repository_index(&index, g_repo)); + ignore_case = (git_index_caps(index) & GIT_INDEXCAP_IGNORE_CASE) != 0; + git_index_free(index); + + cl_git_pass(git_status_file(&flags, g_repo, "A.txt")); + cl_assert(flags == ignore_case ? GIT_STATUS_IGNORED : GIT_STATUS_WT_NEW); +} + +void test_status_ignore__subdirectories(void) +{ + status_entry_single st; + int ignored; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_mkfile( + "empty_standard_repo/ignore_me", "I'm going to be ignored!"); + + cl_git_rewritefile("empty_standard_repo/.gitignore", "ignore_me\n"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); + cl_assert_equal_i(2, st.count); + cl_assert(st.status == GIT_STATUS_IGNORED); + + cl_git_pass(git_status_file(&st.status, g_repo, "ignore_me")); + cl_assert(st.status == GIT_STATUS_IGNORED); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "ignore_me")); + cl_assert(ignored); + + /* I've changed libgit2 so that the behavior here now differs from + * core git but seems to make more sense. In core git, the following + * items are skipped completed, even if --ignored is passed to status. + * It you mirror these steps and run "git status -uall --ignored" then + * you will not see "test/ignore_me/" in the results. + * + * However, we had a couple reports of this as a bug, plus there is a + * similar circumstance where we were differing for core git when you + * used a rooted path for an ignore, so I changed this behavior. + */ + cl_git_pass(git_futils_mkdir_r( + "empty_standard_repo/test/ignore_me", NULL, 0775)); + cl_git_mkfile( + "empty_standard_repo/test/ignore_me/file", "I'm going to be ignored!"); + cl_git_mkfile( + "empty_standard_repo/test/ignore_me/file2", "Me, too!"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); + cl_assert_equal_i(3, st.count); + + cl_git_pass(git_status_file(&st.status, g_repo, "test/ignore_me/file")); + cl_assert(st.status == GIT_STATUS_IGNORED); + + cl_git_pass( + git_status_should_ignore(&ignored, g_repo, "test/ignore_me/file")); + cl_assert(ignored); +} + +void test_status_ignore__subdirectories_recursion(void) +{ + /* Let's try again with recursing into ignored dirs turned on */ + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts; + static const char *paths_r[] = { + ".gitignore", + "ignore_also/file", + "ignore_me", + "test/ignore_me/and_me/file", + "test/ignore_me/file", + "test/ignore_me/file2", + }; + static const unsigned int statuses_r[] = { + GIT_STATUS_WT_NEW, + GIT_STATUS_IGNORED, + GIT_STATUS_IGNORED, + GIT_STATUS_IGNORED, + GIT_STATUS_IGNORED, + GIT_STATUS_IGNORED, + }; + static const char *paths_nr[] = { + ".gitignore", + "ignore_also/", + "ignore_me", + "test/ignore_me/", + }; + static const unsigned int statuses_nr[] = { + GIT_STATUS_WT_NEW, + GIT_STATUS_IGNORED, + GIT_STATUS_IGNORED, + GIT_STATUS_IGNORED, + }; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_rewritefile("empty_standard_repo/.gitignore", "ignore_me\n/ignore_also\n"); + + cl_git_mkfile( + "empty_standard_repo/ignore_me", "I'm going to be ignored!"); + cl_git_pass(git_futils_mkdir_r( + "empty_standard_repo/test/ignore_me", NULL, 0775)); + cl_git_mkfile( + "empty_standard_repo/test/ignore_me/file", "I'm going to be ignored!"); + cl_git_mkfile( + "empty_standard_repo/test/ignore_me/file2", "Me, too!"); + cl_git_pass(git_futils_mkdir_r( + "empty_standard_repo/test/ignore_me/and_me", NULL, 0775)); + cl_git_mkfile( + "empty_standard_repo/test/ignore_me/and_me/file", "Deeply ignored"); + cl_git_pass(git_futils_mkdir_r( + "empty_standard_repo/ignore_also", NULL, 0775)); + cl_git_mkfile( + "empty_standard_repo/ignore_also/file", "I'm going to be ignored!"); + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = 6; + counts.expected_paths = paths_r; + counts.expected_statuses = statuses_r; + + opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; + + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, cb_status__normal, &counts)); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); + + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = 4; + counts.expected_paths = paths_nr; + counts.expected_statuses = statuses_nr; + + opts.flags = GIT_STATUS_OPT_DEFAULTS; + + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, cb_status__normal, &counts)); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +void test_status_ignore__adding_internal_ignores(void) +{ + int ignored; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.txt")); + cl_assert(!ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); + cl_assert(!ignored); + + cl_git_pass(git_ignore_add_rule(g_repo, "*.nomatch\n")); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.txt")); + cl_assert(!ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); + cl_assert(!ignored); + + cl_git_pass(git_ignore_add_rule(g_repo, "*.txt\n")); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.txt")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); + cl_assert(!ignored); + + cl_git_pass(git_ignore_add_rule(g_repo, "*.bar\n")); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.txt")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); + cl_assert(ignored); + + cl_git_pass(git_ignore_clear_internal_rules(g_repo)); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.txt")); + cl_assert(!ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); + cl_assert(!ignored); + + cl_git_pass(git_ignore_add_rule( + g_repo, "multiple\n*.rules\n# comment line\n*.bar\n")); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.txt")); + cl_assert(!ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); + cl_assert(ignored); +} + +void test_status_ignore__add_internal_as_first_thing(void) +{ + int ignored; + const char *add_me = "\n#################\n## Eclipse\n#################\n\n*.pydevproject\n.project\n.metadata\nbin/\ntmp/\n*.tmp\n\n"; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_ignore_add_rule(g_repo, add_me)); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "one.tmp")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "two.bar")); + cl_assert(!ignored); +} + +void test_status_ignore__internal_ignores_inside_deep_paths(void) +{ + int ignored; + const char *add_me = "Debug\nthis/is/deep\npatterned*/dir\n"; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_ignore_add_rule(g_repo, add_me)); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "Debug")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "and/Debug")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "really/Debug/this/file")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "Debug/what/I/say")); + cl_assert(ignored); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "and/NoDebug")); + cl_assert(!ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "NoDebug/this")); + cl_assert(!ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "please/NoDebug/this")); + cl_assert(!ignored); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/is/deep")); + cl_assert(ignored); + /* pattern containing slash gets FNM_PATHNAME so all slashes must match */ + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "and/this/is/deep")); + cl_assert(!ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/is/deep/too")); + cl_assert(ignored); + /* pattern containing slash gets FNM_PATHNAME so all slashes must match */ + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "but/this/is/deep/and/ignored")); + cl_assert(!ignored); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/is/not/deep")); + cl_assert(!ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "is/this/not/as/deep")); + cl_assert(!ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/is/deepish")); + cl_assert(!ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "xthis/is/deep")); + cl_assert(!ignored); +} + +void test_status_ignore__automatically_ignore_bad_files(void) +{ + int ignored; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, ".git")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/file/.")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/../funky")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/whatever.c")); + cl_assert(!ignored); + + cl_git_pass(git_ignore_add_rule(g_repo, "*.c\n")); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, ".git")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/file/.")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/../funky")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/whatever.c")); + cl_assert(ignored); + + cl_git_pass(git_ignore_clear_internal_rules(g_repo)); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, ".git")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/file/.")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/../funky")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/whatever.c")); + cl_assert(!ignored); +} + +void test_status_ignore__filenames_with_special_prefixes_do_not_interfere_with_status_retrieval(void) +{ + status_entry_single st; + char *test_cases[] = { + "!file", + "#blah", + "[blah]", + "[attr]", + "[attr]blah", + NULL + }; + int i; + + for (i = 0; *(test_cases + i) != NULL; i++) { + git_buf file = GIT_BUF_INIT; + char *file_name = *(test_cases + i); + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_buf_joinpath(&file, "empty_standard_repo", file_name)); + cl_git_mkfile(git_buf_cstr(&file), "Please don't ignore me!"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); + cl_assert(st.count == 1); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&st.status, repo, file_name)); + cl_assert(st.status == GIT_STATUS_WT_NEW); + + cl_git_sandbox_cleanup(); + git_buf_free(&file); + } +} + +void test_status_ignore__issue_1766_negated_ignores(void) +{ + int ignored = 0; + unsigned int status; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_futils_mkdir_r( + "empty_standard_repo/a", NULL, 0775)); + cl_git_mkfile( + "empty_standard_repo/a/.gitignore", "*\n!.gitignore\n"); + cl_git_mkfile( + "empty_standard_repo/a/ignoreme", "I should be ignored\n"); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "a/.gitignore")); + cl_assert(!ignored); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "a/ignoreme")); + cl_assert(ignored); + + cl_git_pass(git_futils_mkdir_r( + "empty_standard_repo/b", NULL, 0775)); + cl_git_mkfile( + "empty_standard_repo/b/.gitignore", "*\n!.gitignore\n"); + cl_git_mkfile( + "empty_standard_repo/b/ignoreme", "I should be ignored\n"); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "b/.gitignore")); + cl_assert(!ignored); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "b/ignoreme")); + cl_assert(ignored); + + /* shouldn't have changed results from first couple either */ + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "a/.gitignore")); + cl_assert(!ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "a/ignoreme")); + cl_assert(ignored); + + /* status should find the two ignore files and nothing else */ + + cl_git_pass(git_status_file(&status, g_repo, "a/.gitignore")); + cl_assert_equal_i(GIT_STATUS_WT_NEW, (int)status); + + cl_git_pass(git_status_file(&status, g_repo, "a/ignoreme")); + cl_assert_equal_i(GIT_STATUS_IGNORED, (int)status); + + cl_git_pass(git_status_file(&status, g_repo, "b/.gitignore")); + cl_assert_equal_i(GIT_STATUS_WT_NEW, (int)status); + + cl_git_pass(git_status_file(&status, g_repo, "b/ignoreme")); + cl_assert_equal_i(GIT_STATUS_IGNORED, (int)status); + + { + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts; + static const char *paths[] = { + "a/.gitignore", + "a/ignoreme", + "b/.gitignore", + "b/ignoreme", + }; + static const unsigned int statuses[] = { + GIT_STATUS_WT_NEW, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_NEW, + GIT_STATUS_IGNORED, + }; + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = 4; + counts.expected_paths = paths; + counts.expected_statuses = statuses; + + opts.flags = GIT_STATUS_OPT_DEFAULTS; + + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, cb_status__normal, &counts)); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); + } +} + diff --git a/tests/status/renames.c b/tests/status/renames.c new file mode 100644 index 000000000..16fd02676 --- /dev/null +++ b/tests/status/renames.c @@ -0,0 +1,557 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "path.h" +#include "posix.h" +#include "status_helpers.h" +#include "util.h" +#include "status.h" + +static git_repository *g_repo = NULL; + +void test_status_renames__initialize(void) +{ + g_repo = cl_git_sandbox_init("renames"); + + cl_repo_set_bool(g_repo, "core.autocrlf", false); +} + +void test_status_renames__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +static void rename_file(git_repository *repo, const char *oldname, const char *newname) +{ + git_buf oldpath = GIT_BUF_INIT, newpath = GIT_BUF_INIT; + + git_buf_joinpath(&oldpath, git_repository_workdir(repo), oldname); + git_buf_joinpath(&newpath, git_repository_workdir(repo), newname); + + cl_git_pass(p_rename(oldpath.ptr, newpath.ptr)); + + git_buf_free(&oldpath); + git_buf_free(&newpath); +} + +static void rename_and_edit_file(git_repository *repo, const char *oldname, const char *newname) +{ + git_buf oldpath = GIT_BUF_INIT, newpath = GIT_BUF_INIT; + + git_buf_joinpath(&oldpath, git_repository_workdir(repo), oldname); + git_buf_joinpath(&newpath, git_repository_workdir(repo), newname); + + cl_git_pass(p_rename(oldpath.ptr, newpath.ptr)); + cl_git_append2file(newpath.ptr, "Added at the end to keep similarity!"); + + git_buf_free(&oldpath); + git_buf_free(&newpath); +} + +struct status_entry { + git_status_t status; + const char *oldname; + const char *newname; +}; + +static void test_status( + git_status_list *status_list, + struct status_entry *expected_list, + size_t expected_len) +{ + const git_status_entry *actual; + const struct status_entry *expected; + const char *oldname, *newname; + size_t i; + + cl_assert_equal_sz(expected_len, git_status_list_entrycount(status_list)); + + for (i = 0; i < expected_len; i++) { + actual = git_status_byindex(status_list, i); + expected = &expected_list[i]; + + oldname = actual->head_to_index ? actual->head_to_index->old_file.path : + actual->index_to_workdir ? actual->index_to_workdir->old_file.path : NULL; + + newname = actual->index_to_workdir ? actual->index_to_workdir->new_file.path : + actual->head_to_index ? actual->head_to_index->new_file.path : NULL; + + cl_assert_equal_i_fmt(expected->status, actual->status, "%04x"); + + if (oldname) + cl_assert(git__strcmp(oldname, expected->oldname) == 0); + else + cl_assert(expected->oldname == NULL); + + if (newname) + cl_assert(git__strcmp(newname, expected->newname) == 0); + else + cl_assert(expected->newname == NULL); + } +} + +void test_status_renames__head2index_one(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_INDEX_RENAMED, "ikeepsix.txt", "newname.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + + cl_git_pass(git_repository_index(&index, g_repo)); + + rename_file(g_repo, "ikeepsix.txt", "newname.txt"); + + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "newname.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 1); + git_status_list_free(statuslist); + + git_index_free(index); +} + +void test_status_renames__head2index_two(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED, + "sixserving.txt", "aaa.txt" }, + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED, + "untimely.txt", "bbb.txt" }, + { GIT_STATUS_INDEX_RENAMED, "songof7cities.txt", "ccc.txt" }, + { GIT_STATUS_INDEX_RENAMED, "ikeepsix.txt", "ddd.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + + cl_git_pass(git_repository_index(&index, g_repo)); + + rename_file(g_repo, "ikeepsix.txt", "ddd.txt"); + rename_and_edit_file(g_repo, "sixserving.txt", "aaa.txt"); + rename_file(g_repo, "songof7cities.txt", "ccc.txt"); + rename_and_edit_file(g_repo, "untimely.txt", "bbb.txt"); + + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_remove_bypath(index, "sixserving.txt")); + cl_git_pass(git_index_remove_bypath(index, "songof7cities.txt")); + cl_git_pass(git_index_remove_bypath(index, "untimely.txt")); + cl_git_pass(git_index_add_bypath(index, "ddd.txt")); + cl_git_pass(git_index_add_bypath(index, "aaa.txt")); + cl_git_pass(git_index_add_bypath(index, "ccc.txt")); + cl_git_pass(git_index_add_bypath(index, "bbb.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 4); + git_status_list_free(statuslist); + + git_index_free(index); +} + +void test_status_renames__head2index_no_rename_from_rewrite(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_INDEX_MODIFIED, "ikeepsix.txt", "ikeepsix.txt" }, + { GIT_STATUS_INDEX_MODIFIED, "sixserving.txt", "sixserving.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + + cl_git_pass(git_repository_index(&index, g_repo)); + + rename_file(g_repo, "ikeepsix.txt", "_temp_.txt"); + rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); + rename_file(g_repo, "_temp_.txt", "sixserving.txt"); + + cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "sixserving.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 2); + git_status_list_free(statuslist); + + git_index_free(index); +} + +void test_status_renames__head2index_rename_from_rewrite(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_INDEX_RENAMED, "sixserving.txt", "ikeepsix.txt" }, + { GIT_STATUS_INDEX_RENAMED, "ikeepsix.txt", "sixserving.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES; + + cl_git_pass(git_repository_index(&index, g_repo)); + + rename_file(g_repo, "ikeepsix.txt", "_temp_.txt"); + rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); + rename_file(g_repo, "_temp_.txt", "sixserving.txt"); + + cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "sixserving.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 2); + git_status_list_free(statuslist); + + git_index_free(index); +} + +void test_status_renames__index2workdir_one(void) +{ + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_WT_RENAMED, "ikeepsix.txt", "newname.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + + rename_file(g_repo, "ikeepsix.txt", "newname.txt"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 1); + git_status_list_free(statuslist); +} + +void test_status_renames__index2workdir_two(void) +{ + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, + "sixserving.txt", "aaa.txt" }, + { GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, + "untimely.txt", "bbb.txt" }, + { GIT_STATUS_WT_RENAMED, "songof7cities.txt", "ccc.txt" }, + { GIT_STATUS_WT_RENAMED, "ikeepsix.txt", "ddd.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + + rename_file(g_repo, "ikeepsix.txt", "ddd.txt"); + rename_and_edit_file(g_repo, "sixserving.txt", "aaa.txt"); + rename_file(g_repo, "songof7cities.txt", "ccc.txt"); + rename_and_edit_file(g_repo, "untimely.txt", "bbb.txt"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 4); + git_status_list_free(statuslist); +} + +void test_status_renames__index2workdir_rename_from_rewrite(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_WT_RENAMED, "sixserving.txt", "ikeepsix.txt" }, + { GIT_STATUS_WT_RENAMED, "ikeepsix.txt", "sixserving.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES; + + cl_git_pass(git_repository_index(&index, g_repo)); + + rename_file(g_repo, "ikeepsix.txt", "_temp_.txt"); + rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); + rename_file(g_repo, "_temp_.txt", "sixserving.txt"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 2); + git_status_list_free(statuslist); + + git_index_free(index); +} + +void test_status_renames__both_one(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, + "ikeepsix.txt", "newname-workdir.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + + cl_git_pass(git_repository_index(&index, g_repo)); + + rename_file(g_repo, "ikeepsix.txt", "newname-index.txt"); + + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "newname-index.txt")); + cl_git_pass(git_index_write(index)); + + rename_file(g_repo, "newname-index.txt", "newname-workdir.txt"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 1); + git_status_list_free(statuslist); + + git_index_free(index); +} + +void test_status_renames__both_two(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED | + GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, + "ikeepsix.txt", "ikeepsix-both.txt" }, + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED, + "sixserving.txt", "sixserving-index.txt" }, + { GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, + "songof7cities.txt", "songof7cities-workdir.txt" }, + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, + "untimely.txt", "untimely-both.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + + cl_git_pass(git_repository_index(&index, g_repo)); + + rename_and_edit_file(g_repo, "ikeepsix.txt", "ikeepsix-index.txt"); + rename_and_edit_file(g_repo, "sixserving.txt", "sixserving-index.txt"); + rename_file(g_repo, "untimely.txt", "untimely-index.txt"); + + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_remove_bypath(index, "sixserving.txt")); + cl_git_pass(git_index_remove_bypath(index, "untimely.txt")); + cl_git_pass(git_index_add_bypath(index, "ikeepsix-index.txt")); + cl_git_pass(git_index_add_bypath(index, "sixserving-index.txt")); + cl_git_pass(git_index_add_bypath(index, "untimely-index.txt")); + cl_git_pass(git_index_write(index)); + + rename_and_edit_file(g_repo, "ikeepsix-index.txt", "ikeepsix-both.txt"); + rename_and_edit_file(g_repo, "songof7cities.txt", "songof7cities-workdir.txt"); + rename_file(g_repo, "untimely-index.txt", "untimely-both.txt"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 4); + git_status_list_free(statuslist); + + git_index_free(index); +} + + +void test_status_renames__both_rename_from_rewrite(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, + "songof7cities.txt", "ikeepsix.txt" }, + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, + "ikeepsix.txt", "sixserving.txt" }, + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, + "sixserving.txt", "songof7cities.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES; + + cl_git_pass(git_repository_index(&index, g_repo)); + + rename_file(g_repo, "ikeepsix.txt", "_temp_.txt"); + rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); + rename_file(g_repo, "songof7cities.txt", "sixserving.txt"); + rename_file(g_repo, "_temp_.txt", "songof7cities.txt"); + + cl_git_pass(git_index_add_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "sixserving.txt")); + cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); + cl_git_pass(git_index_write(index)); + + rename_file(g_repo, "songof7cities.txt", "_temp_.txt"); + rename_file(g_repo, "ikeepsix.txt", "songof7cities.txt"); + rename_file(g_repo, "sixserving.txt", "ikeepsix.txt"); + rename_file(g_repo, "_temp_.txt", "sixserving.txt"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 3); + git_status_list_free(statuslist); + + git_index_free(index); +} + +void test_status_renames__rewrites_only_for_renames(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected[] = { + { GIT_STATUS_WT_MODIFIED, "ikeepsix.txt", "ikeepsix.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + opts.flags |= GIT_STATUS_OPT_RENAMES_FROM_REWRITES; + + cl_git_pass(git_repository_index(&index, g_repo)); + + cl_git_rewritefile("renames/ikeepsix.txt", + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n" \ + "This is enough content for the file to be rewritten.\n"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + test_status(statuslist, expected, 1); + git_status_list_free(statuslist); + + git_index_free(index); +} + +void test_status_renames__both_casechange_one(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + int index_caps; + struct status_entry expected_icase[] = { + { GIT_STATUS_INDEX_RENAMED, + "ikeepsix.txt", "IKeepSix.txt" }, + }; + struct status_entry expected_case[] = { + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, + "ikeepsix.txt", "IKEEPSIX.txt" }, + }; + + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + + cl_git_pass(git_repository_index(&index, g_repo)); + index_caps = git_index_caps(index); + + rename_file(g_repo, "ikeepsix.txt", "IKeepSix.txt"); + + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "IKeepSix.txt")); + cl_git_pass(git_index_write(index)); + + /* on a case-insensitive file system, this change won't matter. + * on a case-sensitive one, it will. + */ + rename_file(g_repo, "IKeepSix.txt", "IKEEPSIX.txt"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + + test_status(statuslist, (index_caps & GIT_INDEXCAP_IGNORE_CASE) ? + expected_icase : expected_case, 1); + + git_status_list_free(statuslist); + + git_index_free(index); +} + +void test_status_renames__both_casechange_two(void) +{ + git_index *index; + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + int index_caps; + struct status_entry expected_icase[] = { + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED | + GIT_STATUS_WT_MODIFIED, + "ikeepsix.txt", "IKeepSix.txt" }, + { GIT_STATUS_INDEX_MODIFIED, + "sixserving.txt", "sixserving.txt" }, + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_MODIFIED, + "songof7cities.txt", "songof7.txt" }, + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, + "untimely.txt", "untimeliest.txt" } + }; + struct status_entry expected_case[] = { + { GIT_STATUS_INDEX_RENAMED | + GIT_STATUS_WT_MODIFIED | GIT_STATUS_WT_RENAMED, + "songof7cities.txt", "SONGOF7.txt" }, + { GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_RENAMED, + "sixserving.txt", "SixServing.txt" }, + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_INDEX_MODIFIED | + GIT_STATUS_WT_RENAMED | GIT_STATUS_WT_MODIFIED, + "ikeepsix.txt", "ikeepsix.txt" }, + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, + "untimely.txt", "untimeliest.txt" } + }; + + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + opts.flags |= GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX; + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + + cl_git_pass(git_repository_index(&index, g_repo)); + index_caps = git_index_caps(index); + + rename_and_edit_file(g_repo, "ikeepsix.txt", "IKeepSix.txt"); + rename_and_edit_file(g_repo, "sixserving.txt", "sixserving.txt"); + rename_file(g_repo, "songof7cities.txt", "songof7.txt"); + rename_file(g_repo, "untimely.txt", "untimelier.txt"); + + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_remove_bypath(index, "sixserving.txt")); + cl_git_pass(git_index_remove_bypath(index, "songof7cities.txt")); + cl_git_pass(git_index_remove_bypath(index, "untimely.txt")); + cl_git_pass(git_index_add_bypath(index, "IKeepSix.txt")); + cl_git_pass(git_index_add_bypath(index, "sixserving.txt")); + cl_git_pass(git_index_add_bypath(index, "songof7.txt")); + cl_git_pass(git_index_add_bypath(index, "untimelier.txt")); + cl_git_pass(git_index_write(index)); + + rename_and_edit_file(g_repo, "IKeepSix.txt", "ikeepsix.txt"); + rename_file(g_repo, "sixserving.txt", "SixServing.txt"); + rename_and_edit_file(g_repo, "songof7.txt", "SONGOF7.txt"); + rename_file(g_repo, "untimelier.txt", "untimeliest.txt"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + + test_status(statuslist, (index_caps & GIT_INDEXCAP_IGNORE_CASE) ? + expected_icase : expected_case, 4); + + git_status_list_free(statuslist); + + git_index_free(index); +} diff --git a/tests/status/single.c b/tests/status/single.c new file mode 100644 index 000000000..292c9120a --- /dev/null +++ b/tests/status/single.c @@ -0,0 +1,45 @@ +#include "clar_libgit2.h" +#include "posix.h" + +static void +cleanup__remove_file(void *_file) +{ + cl_must_pass(p_unlink((char *)_file)); +} + +/* test retrieving OID from a file apart from the ODB */ +void test_status_single__hash_single_file(void) +{ + static const char file_name[] = "new_file"; + static const char file_contents[] = "new_file\n"; + static const char file_hash[] = "d4fa8600b4f37d7516bef4816ae2c64dbf029e3a"; + + git_oid expected_id, actual_id; + + /* initialization */ + git_oid_fromstr(&expected_id, file_hash); + cl_git_mkfile(file_name, file_contents); + cl_set_cleanup(&cleanup__remove_file, (void *)file_name); + + cl_git_pass(git_odb_hashfile(&actual_id, file_name, GIT_OBJ_BLOB)); + cl_assert(git_oid_cmp(&expected_id, &actual_id) == 0); +} + +/* test retrieving OID from an empty file apart from the ODB */ +void test_status_single__hash_single_empty_file(void) +{ + static const char file_name[] = "new_empty_file"; + static const char file_contents[] = ""; + static const char file_hash[] = "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"; + + git_oid expected_id, actual_id; + + /* initialization */ + git_oid_fromstr(&expected_id, file_hash); + cl_git_mkfile(file_name, file_contents); + cl_set_cleanup(&cleanup__remove_file, (void *)file_name); + + cl_git_pass(git_odb_hashfile(&actual_id, file_name, GIT_OBJ_BLOB)); + cl_assert(git_oid_cmp(&expected_id, &actual_id) == 0); +} + diff --git a/tests/status/status_data.h b/tests/status/status_data.h new file mode 100644 index 000000000..8ad4235fd --- /dev/null +++ b/tests/status/status_data.h @@ -0,0 +1,326 @@ +#include "status_helpers.h" + +// A utf-8 string with 83 characters, but 249 bytes. +static const char *longname = "\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97\xe5\x8f\x97"; + + +/* entries for a plain copy of tests/resources/status */ + +static const char *entry_paths0[] = { + "file_deleted", + "ignored_file", + "modified_file", + "new_file", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + + "subdir/deleted_file", + "subdir/modified_file", + "subdir/new_file", + + "\xe8\xbf\x99", +}; + +static const unsigned int entry_statuses0[] = { + GIT_STATUS_WT_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_DELETED, + GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_MODIFIED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_DELETED, + GIT_STATUS_INDEX_NEW | GIT_STATUS_WT_MODIFIED, + + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + + GIT_STATUS_WT_NEW, +}; + +static const int entry_count0 = 16; + +/* entries for a copy of tests/resources/status with all content + * deleted from the working directory + */ + +static const char *entry_paths2[] = { + "current_file", + "file_deleted", + "modified_file", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "subdir.txt", + "subdir/current_file", + "subdir/deleted_file", + "subdir/modified_file", +}; + +static const unsigned int entry_statuses2[] = { + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, +}; + +static const int entry_count2 = 15; + +/* entries for a copy of tests/resources/status with some mods */ + +static const char *entry_paths3_icase[] = { + ".HEADER", + "42-is-not-prime.sigh", + "current_file", + "current_file/", + "file_deleted", + "ignored_file", + "modified_file", + "new_file", + "README.md", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "subdir", + "subdir/current_file", + "subdir/deleted_file", + "subdir/modified_file", + "\xe8\xbf\x99", +}; + +static const unsigned int entry_statuses3_icase[] = { + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_WT_NEW | GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_NEW, +}; + +static const char *entry_paths3[] = { + ".HEADER", + "42-is-not-prime.sigh", + "README.md", + "current_file", + "current_file/", + "file_deleted", + "ignored_file", + "modified_file", + "new_file", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "subdir", + "subdir/current_file", + "subdir/deleted_file", + "subdir/modified_file", + "\xe8\xbf\x99", +}; + +static const unsigned int entry_statuses3[] = { + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_WT_NEW | GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_NEW, +}; + +static const int entry_count3 = 22; + + +/* entries for a copy of tests/resources/status with some mods + * and different options to the status call + */ + +static const char *entry_paths4[] = { + ".new_file", + "current_file", + "current_file/current_file", + "current_file/modified_file", + "current_file/new_file", + "file_deleted", + "modified_file", + "new_file", + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "subdir", + "subdir/current_file", + "subdir/deleted_file", + "subdir/modified_file", + "zzz_new_dir/new_file", + "zzz_new_file", + "\xe8\xbf\x99", +}; + +static const unsigned int entry_statuses4[] = { + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_WT_NEW | GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, +}; + +static const int entry_count4 = 23; + + +/* entries for a copy of tests/resources/status with options + * passed to the status call in order to only get the differences + * between the HEAD and the index (changes to be committed) + */ + +static const char *entry_paths5[] = { + "staged_changes", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_file_deleted", + "staged_delete_modified_file", + "staged_new_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", +}; + +static const unsigned int entry_statuses5[] = { + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_NEW, +}; + +static const int entry_count5 = 8; + + +/* entries for a copy of tests/resources/status with options + * passed to the status call in order to only get the differences + * between the workdir and the index (changes not staged, untracked files) + */ + +static const char *entry_paths6[] = { + "file_deleted", + "ignored_file", + "modified_file", + "new_file", + "staged_changes_file_deleted", + "staged_changes_modified_file", + "staged_delete_modified_file", + "staged_new_file_deleted_file", + "staged_new_file_modified_file", + "subdir/deleted_file", + "subdir/modified_file", + "subdir/new_file", + "\xe8\xbf\x99", +}; + +static const unsigned int entry_statuses6[] = { + GIT_STATUS_WT_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_WT_NEW, +}; + +static const int entry_count6 = 13; diff --git a/tests/status/status_helpers.c b/tests/status/status_helpers.c new file mode 100644 index 000000000..902b65c4f --- /dev/null +++ b/tests/status/status_helpers.c @@ -0,0 +1,101 @@ +#include "clar_libgit2.h" +#include "status_helpers.h" + +int cb_status__normal( + const char *path, unsigned int status_flags, void *payload) +{ + status_entry_counts *counts = payload; + + if (counts->debug) + cb_status__print(path, status_flags, NULL); + + if (counts->entry_count >= counts->expected_entry_count) { + counts->wrong_status_flags_count++; + goto exit; + } + + if (strcmp(path, counts->expected_paths[counts->entry_count])) { + counts->wrong_sorted_path++; + goto exit; + } + + if (status_flags != counts->expected_statuses[counts->entry_count]) + counts->wrong_status_flags_count++; + +exit: + counts->entry_count++; + return 0; +} + +int cb_status__count(const char *p, unsigned int s, void *payload) +{ + volatile int *count = (int *)payload; + + GIT_UNUSED(p); + GIT_UNUSED(s); + + (*count)++; + + return 0; +} + +int cb_status__single(const char *p, unsigned int s, void *payload) +{ + status_entry_single *data = (status_entry_single *)payload; + + if (data->debug) + fprintf(stderr, "%02d: %s (%04x)\n", data->count, p, s); + + data->count++; + data->status = s; + + return 0; +} + +int cb_status__print( + const char *path, unsigned int status_flags, void *payload) +{ + char istatus = ' ', wstatus = ' '; + int icount = 0, wcount = 0; + + if (status_flags & GIT_STATUS_INDEX_NEW) { + istatus = 'A'; icount++; + } + if (status_flags & GIT_STATUS_INDEX_MODIFIED) { + istatus = 'M'; icount++; + } + if (status_flags & GIT_STATUS_INDEX_DELETED) { + istatus = 'D'; icount++; + } + if (status_flags & GIT_STATUS_INDEX_RENAMED) { + istatus = 'R'; icount++; + } + if (status_flags & GIT_STATUS_INDEX_TYPECHANGE) { + istatus = 'T'; icount++; + } + + if (status_flags & GIT_STATUS_WT_NEW) { + wstatus = 'A'; wcount++; + } + if (status_flags & GIT_STATUS_WT_MODIFIED) { + wstatus = 'M'; wcount++; + } + if (status_flags & GIT_STATUS_WT_DELETED) { + wstatus = 'D'; wcount++; + } + if (status_flags & GIT_STATUS_WT_TYPECHANGE) { + wstatus = 'T'; wcount++; + } + if (status_flags & GIT_STATUS_IGNORED) { + wstatus = 'I'; wcount++; + } + + fprintf(stderr, "%c%c %s (%d/%d%s)\n", + istatus, wstatus, path, icount, wcount, + (icount > 1 || wcount > 1) ? " INVALID COMBO" : ""); + + if (payload) + *((int *)payload) += 1; + + return 0; +} diff --git a/tests/status/status_helpers.h b/tests/status/status_helpers.h new file mode 100644 index 000000000..f1f009e02 --- /dev/null +++ b/tests/status/status_helpers.h @@ -0,0 +1,39 @@ +#ifndef INCLUDE_cl_status_helpers_h__ +#define INCLUDE_cl_status_helpers_h__ + +typedef struct { + int wrong_status_flags_count; + int wrong_sorted_path; + int entry_count; + const unsigned int* expected_statuses; + const char** expected_paths; + int expected_entry_count; + bool debug; +} status_entry_counts; + +/* cb_status__normal takes payload of "status_entry_counts *" */ + +extern int cb_status__normal( + const char *path, unsigned int status_flags, void *payload); + + +/* cb_status__count takes payload of "int *" */ + +extern int cb_status__count(const char *p, unsigned int s, void *payload); + + +typedef struct { + int count; + unsigned int status; + bool debug; +} status_entry_single; + +/* cb_status__single takes payload of "status_entry_single *" */ + +extern int cb_status__single(const char *p, unsigned int s, void *payload); + +/* cb_status__print takes optional payload of "int *" */ + +extern int cb_status__print(const char *p, unsigned int s, void *payload); + +#endif diff --git a/tests/status/submodules.c b/tests/status/submodules.c new file mode 100644 index 000000000..ef2888f7d --- /dev/null +++ b/tests/status/submodules.c @@ -0,0 +1,223 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "path.h" +#include "posix.h" +#include "status_helpers.h" +#include "../submodule/submodule_helpers.h" + +static git_repository *g_repo = NULL; + +void test_status_submodules__initialize(void) +{ +} + +void test_status_submodules__cleanup(void) +{ +} + +void test_status_submodules__api(void) +{ + git_submodule *sm; + + g_repo = setup_fixture_submodules(); + + cl_assert(git_submodule_lookup(NULL, g_repo, "nonexistent") == GIT_ENOTFOUND); + + cl_assert(git_submodule_lookup(NULL, g_repo, "modified") == GIT_ENOTFOUND); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo")); + cl_assert(sm != NULL); + cl_assert_equal_s("testrepo", git_submodule_name(sm)); + cl_assert_equal_s("testrepo", git_submodule_path(sm)); +} + +void test_status_submodules__0(void) +{ + int counts = 0; + + g_repo = setup_fixture_submodules(); + + cl_assert(git_path_isdir("submodules/.git")); + cl_assert(git_path_isdir("submodules/testrepo/.git")); + cl_assert(git_path_isfile("submodules/.gitmodules")); + + cl_git_pass( + git_status_foreach(g_repo, cb_status__count, &counts) + ); + + cl_assert_equal_i(6, counts); +} + +static const char *expected_files[] = { + ".gitmodules", + "added", + "deleted", + "ignored", + "modified", + "untracked" +}; + +static unsigned int expected_status[] = { + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW +}; + +static int cb_status__match(const char *p, unsigned int s, void *payload) +{ + status_entry_counts *counts = payload; + int idx = counts->entry_count++; + + cl_assert_equal_s(counts->expected_paths[idx], p); + cl_assert(counts->expected_statuses[idx] == s); + + return 0; +} + +void test_status_submodules__1(void) +{ + status_entry_counts counts; + + g_repo = setup_fixture_submodules(); + + cl_assert(git_path_isdir("submodules/.git")); + cl_assert(git_path_isdir("submodules/testrepo/.git")); + cl_assert(git_path_isfile("submodules/.gitmodules")); + + memset(&counts, 0, sizeof(counts)); + counts.expected_paths = expected_files; + counts.expected_statuses = expected_status; + + cl_git_pass( + git_status_foreach(g_repo, cb_status__match, &counts) + ); + + cl_assert_equal_i(6, counts.entry_count); +} + +void test_status_submodules__single_file(void) +{ + unsigned int status = 0; + g_repo = setup_fixture_submodules(); + cl_git_pass( git_status_file(&status, g_repo, "testrepo") ); + cl_assert(!status); +} + +void test_status_submodules__moved_head(void) +{ + git_submodule *sm; + git_repository *smrepo; + git_oid oid; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts; + static const char *expected_files_with_sub[] = { + ".gitmodules", + "added", + "deleted", + "ignored", + "modified", + "testrepo", + "untracked" + }; + static unsigned int expected_status_with_sub[] = { + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW + }; + + g_repo = setup_fixture_submodules(); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo")); + cl_git_pass(git_submodule_open(&smrepo, sm)); + + /* move submodule HEAD to c47800c7266a2be04c571c04d5a6614691ea99bd */ + cl_git_pass( + git_oid_fromstr(&oid, "c47800c7266a2be04c571c04d5a6614691ea99bd")); + cl_git_pass(git_repository_set_head_detached(smrepo, &oid)); + + /* first do a normal status, which should now include the submodule */ + + memset(&counts, 0, sizeof(counts)); + counts.expected_paths = expected_files_with_sub; + counts.expected_statuses = expected_status_with_sub; + + opts.flags = GIT_STATUS_OPT_DEFAULTS; + + cl_git_pass( + git_status_foreach_ext(g_repo, &opts, cb_status__match, &counts)); + cl_assert_equal_i(7, counts.entry_count); + + /* try again with EXCLUDE_SUBMODULES which should skip it */ + + memset(&counts, 0, sizeof(counts)); + counts.expected_paths = expected_files; + counts.expected_statuses = expected_status; + + opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_EXCLUDE_SUBMODULES; + + cl_git_pass( + git_status_foreach_ext(g_repo, &opts, cb_status__match, &counts)); + cl_assert_equal_i(6, counts.entry_count); + + git_repository_free(smrepo); +} + +void test_status_submodules__dirty_workdir_only(void) +{ + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts; + static const char *expected_files_with_sub[] = { + ".gitmodules", + "added", + "deleted", + "ignored", + "modified", + "testrepo", + "untracked" + }; + static unsigned int expected_status_with_sub[] = { + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_INDEX_NEW, + GIT_STATUS_INDEX_DELETED, + GIT_STATUS_IGNORED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW + }; + + g_repo = setup_fixture_submodules(); + + cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); + cl_git_mkfile("submodules/testrepo/all_new.txt", "never seen before"); + + /* first do a normal status, which should now include the submodule */ + + memset(&counts, 0, sizeof(counts)); + counts.expected_paths = expected_files_with_sub; + counts.expected_statuses = expected_status_with_sub; + + opts.flags = GIT_STATUS_OPT_DEFAULTS; + + cl_git_pass( + git_status_foreach_ext(g_repo, &opts, cb_status__match, &counts)); + cl_assert_equal_i(7, counts.entry_count); + + /* try again with EXCLUDE_SUBMODULES which should skip it */ + + memset(&counts, 0, sizeof(counts)); + counts.expected_paths = expected_files; + counts.expected_statuses = expected_status; + + opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_EXCLUDE_SUBMODULES; + + cl_git_pass( + git_status_foreach_ext(g_repo, &opts, cb_status__match, &counts)); + cl_assert_equal_i(6, counts.entry_count); +} diff --git a/tests/status/worktree.c b/tests/status/worktree.c new file mode 100644 index 000000000..34be6d34c --- /dev/null +++ b/tests/status/worktree.c @@ -0,0 +1,875 @@ +#include "clar_libgit2.h" +#include "fileops.h" +#include "ignore.h" +#include "status_data.h" +#include "posix.h" +#include "util.h" +#include "path.h" + +/** + * Cleanup + * + * This will be called once after each test finishes, even + * if the test failed + */ +void test_status_worktree__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +/** + * Tests - Status determination on a working tree + */ +/* this test is equivalent to t18-status.c:statuscb0 */ +void test_status_worktree__whole_repository(void) +{ + status_entry_counts counts; + git_repository *repo = cl_git_sandbox_init("status"); + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = entry_count0; + counts.expected_paths = entry_paths0; + counts.expected_statuses = entry_statuses0; + + cl_git_pass( + git_status_foreach(repo, cb_status__normal, &counts) + ); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +void assert_show(const int entry_counts, const char *entry_paths[], + const unsigned int entry_statuses[], git_status_show_t show) +{ + status_entry_counts counts; + git_repository *repo = cl_git_sandbox_init("status"); + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = entry_counts; + counts.expected_paths = entry_paths; + counts.expected_statuses = entry_statuses; + + opts.flags = GIT_STATUS_OPT_DEFAULTS; + opts.show = show; + + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) + ); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +void test_status_worktree__show_index_and_workdir(void) +{ + assert_show(entry_count0, entry_paths0, entry_statuses0, + GIT_STATUS_SHOW_INDEX_AND_WORKDIR); +} + +void test_status_worktree__show_index_only(void) +{ + assert_show(entry_count5, entry_paths5, entry_statuses5, + GIT_STATUS_SHOW_INDEX_ONLY); +} + +void test_status_worktree__show_workdir_only(void) +{ + assert_show(entry_count6, entry_paths6, entry_statuses6, + GIT_STATUS_SHOW_WORKDIR_ONLY); +} + +/* this test is equivalent to t18-status.c:statuscb1 */ +void test_status_worktree__empty_repository(void) +{ + int count = 0; + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_status_foreach(repo, cb_status__count, &count)); + + cl_assert_equal_i(0, count); +} + +static int remove_file_cb(void *data, git_buf *file) +{ + const char *filename = git_buf_cstr(file); + + GIT_UNUSED(data); + + if (git__suffixcmp(filename, ".git") == 0) + return 0; + + if (git_path_isdir(filename)) + cl_git_pass(git_futils_rmdir_r(filename, NULL, GIT_RMDIR_REMOVE_FILES)); + else + cl_git_pass(p_unlink(git_buf_cstr(file))); + + return 0; +} + +/* this test is equivalent to t18-status.c:statuscb2 */ +void test_status_worktree__purged_worktree(void) +{ + status_entry_counts counts; + git_repository *repo = cl_git_sandbox_init("status"); + git_buf workdir = GIT_BUF_INIT; + + /* first purge the contents of the worktree */ + cl_git_pass(git_buf_sets(&workdir, git_repository_workdir(repo))); + cl_git_pass(git_path_direach(&workdir, 0, remove_file_cb, NULL)); + git_buf_free(&workdir); + + /* now get status */ + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = entry_count2; + counts.expected_paths = entry_paths2; + counts.expected_statuses = entry_statuses2; + + cl_git_pass( + git_status_foreach(repo, cb_status__normal, &counts) + ); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +/* this test is similar to t18-status.c:statuscb3 */ +void test_status_worktree__swap_subdir_and_file(void) +{ + status_entry_counts counts; + git_repository *repo = cl_git_sandbox_init("status"); + git_index *index; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + bool ignore_case; + + cl_git_pass(git_repository_index(&index, repo)); + ignore_case = (git_index_caps(index) & GIT_INDEXCAP_IGNORE_CASE) != 0; + git_index_free(index); + + /* first alter the contents of the worktree */ + cl_git_pass(p_rename("status/current_file", "status/swap")); + cl_git_pass(p_rename("status/subdir", "status/current_file")); + cl_git_pass(p_rename("status/swap", "status/subdir")); + + cl_git_mkfile("status/.HEADER", "dummy"); + cl_git_mkfile("status/42-is-not-prime.sigh", "dummy"); + cl_git_mkfile("status/README.md", "dummy"); + + /* now get status */ + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = entry_count3; + counts.expected_paths = ignore_case ? entry_paths3_icase : entry_paths3; + counts.expected_statuses = ignore_case ? entry_statuses3_icase : entry_statuses3; + + opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | + GIT_STATUS_OPT_INCLUDE_IGNORED; + + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) + ); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +void test_status_worktree__swap_subdir_with_recurse_and_pathspec(void) +{ + status_entry_counts counts; + git_repository *repo = cl_git_sandbox_init("status"); + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + + /* first alter the contents of the worktree */ + cl_git_pass(p_rename("status/current_file", "status/swap")); + cl_git_pass(p_rename("status/subdir", "status/current_file")); + cl_git_pass(p_rename("status/swap", "status/subdir")); + cl_git_mkfile("status/.new_file", "dummy"); + cl_git_pass(git_futils_mkdir_r("status/zzz_new_dir", NULL, 0777)); + cl_git_mkfile("status/zzz_new_dir/new_file", "dummy"); + cl_git_mkfile("status/zzz_new_file", "dummy"); + + /* now get status */ + memset(&counts, 0x0, sizeof(status_entry_counts)); + counts.expected_entry_count = entry_count4; + counts.expected_paths = entry_paths4; + counts.expected_statuses = entry_statuses4; + + opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | + GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; + /* TODO: set pathspec to "current_file" eventually */ + + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) + ); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +/* this test is equivalent to t18-status.c:singlestatus0 */ +void test_status_worktree__single_file(void) +{ + int i; + unsigned int status_flags; + git_repository *repo = cl_git_sandbox_init("status"); + + for (i = 0; i < (int)entry_count0; i++) { + cl_git_pass( + git_status_file(&status_flags, repo, entry_paths0[i]) + ); + cl_assert(entry_statuses0[i] == status_flags); + } +} + +/* this test is equivalent to t18-status.c:singlestatus1 */ +void test_status_worktree__single_nonexistent_file(void) +{ + int error; + unsigned int status_flags; + git_repository *repo = cl_git_sandbox_init("status"); + + error = git_status_file(&status_flags, repo, "nonexistent"); + cl_git_fail(error); + cl_assert(error == GIT_ENOTFOUND); +} + +/* this test is equivalent to t18-status.c:singlestatus2 */ +void test_status_worktree__single_nonexistent_file_empty_repo(void) +{ + int error; + unsigned int status_flags; + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + + error = git_status_file(&status_flags, repo, "nonexistent"); + cl_git_fail(error); + cl_assert(error == GIT_ENOTFOUND); +} + +/* this test is equivalent to t18-status.c:singlestatus3 */ +void test_status_worktree__single_file_empty_repo(void) +{ + unsigned int status_flags; + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_mkfile("empty_standard_repo/new_file", "new_file\n"); + + cl_git_pass(git_status_file(&status_flags, repo, "new_file")); + cl_assert(status_flags == GIT_STATUS_WT_NEW); +} + +/* this test is equivalent to t18-status.c:singlestatus4 */ +void test_status_worktree__single_folder(void) +{ + int error; + unsigned int status_flags; + git_repository *repo = cl_git_sandbox_init("status"); + + error = git_status_file(&status_flags, repo, "subdir"); + cl_git_fail(error); + cl_assert(error != GIT_ENOTFOUND); +} + + +void test_status_worktree__ignores(void) +{ + int i, ignored; + git_repository *repo = cl_git_sandbox_init("status"); + + for (i = 0; i < (int)entry_count0; i++) { + cl_git_pass( + git_status_should_ignore(&ignored, repo, entry_paths0[i]) + ); + cl_assert(ignored == (entry_statuses0[i] == GIT_STATUS_IGNORED)); + } + + cl_git_pass( + git_status_should_ignore(&ignored, repo, "nonexistent_file") + ); + cl_assert(!ignored); + + cl_git_pass( + git_status_should_ignore(&ignored, repo, "ignored_nonexistent_file") + ); + cl_assert(ignored); +} + +static int cb_status__check_592(const char *p, unsigned int s, void *payload) +{ + if (s != GIT_STATUS_WT_DELETED || + (payload != NULL && strcmp(p, (const char *)payload) != 0)) + return -1; + + return 0; +} + +void test_status_worktree__issue_592(void) +{ + git_repository *repo; + git_buf path = GIT_BUF_INIT; + + repo = cl_git_sandbox_init("issue_592"); + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "l.txt")); + cl_git_pass(p_unlink(git_buf_cstr(&path))); + cl_assert(!git_path_exists("issue_592/l.txt")); + + cl_git_pass(git_status_foreach(repo, cb_status__check_592, "l.txt")); + + git_buf_free(&path); +} + +void test_status_worktree__issue_592_2(void) +{ + git_repository *repo; + git_buf path = GIT_BUF_INIT; + + repo = cl_git_sandbox_init("issue_592"); + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "c/a.txt")); + cl_git_pass(p_unlink(git_buf_cstr(&path))); + cl_assert(!git_path_exists("issue_592/c/a.txt")); + + cl_git_pass(git_status_foreach(repo, cb_status__check_592, "c/a.txt")); + + git_buf_free(&path); +} + +void test_status_worktree__issue_592_3(void) +{ + git_repository *repo; + git_buf path = GIT_BUF_INIT; + + repo = cl_git_sandbox_init("issue_592"); + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "c")); + cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); + cl_assert(!git_path_exists("issue_592/c/a.txt")); + + cl_git_pass(git_status_foreach(repo, cb_status__check_592, "c/a.txt")); + + git_buf_free(&path); +} + +void test_status_worktree__issue_592_4(void) +{ + git_repository *repo; + git_buf path = GIT_BUF_INIT; + + repo = cl_git_sandbox_init("issue_592"); + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "t/b.txt")); + cl_git_pass(p_unlink(git_buf_cstr(&path))); + + cl_git_pass(git_status_foreach(repo, cb_status__check_592, "t/b.txt")); + + git_buf_free(&path); +} + +void test_status_worktree__issue_592_5(void) +{ + git_repository *repo; + git_buf path = GIT_BUF_INIT; + + repo = cl_git_sandbox_init("issue_592"); + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(repo), "t")); + cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); + cl_git_pass(p_mkdir(git_buf_cstr(&path), 0777)); + + cl_git_pass(git_status_foreach(repo, cb_status__check_592, NULL)); + + git_buf_free(&path); +} + +void test_status_worktree__issue_592_ignores_0(void) +{ + int count = 0; + status_entry_single st; + git_repository *repo = cl_git_sandbox_init("issue_592"); + + cl_git_pass(git_status_foreach(repo, cb_status__count, &count)); + cl_assert_equal_i(0, count); + + cl_git_rewritefile("issue_592/.gitignore", + ".gitignore\n*.txt\nc/\n[tT]*/\n"); + + cl_git_pass(git_status_foreach(repo, cb_status__count, &count)); + cl_assert_equal_i(1, count); + + /* This is a situation where the behavior of libgit2 is + * different from core git. Core git will show ignored.txt + * in the list of ignored files, even though the directory + * "t" is ignored and the file is untracked because we have + * the explicit "*.txt" ignore rule. Libgit2 just excludes + * all untracked files that are contained within ignored + * directories without explicitly listing them. + */ + cl_git_rewritefile("issue_592/t/ignored.txt", "ping"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); + cl_assert_equal_i(1, st.count); + cl_assert(st.status == GIT_STATUS_IGNORED); + + cl_git_rewritefile("issue_592/c/ignored_by_dir", "ping"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); + cl_assert_equal_i(1, st.count); + cl_assert(st.status == GIT_STATUS_IGNORED); + + cl_git_rewritefile("issue_592/t/ignored_by_dir_pattern", "ping"); + + memset(&st, 0, sizeof(st)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); + cl_assert_equal_i(1, st.count); + cl_assert(st.status == GIT_STATUS_IGNORED); +} + +void test_status_worktree__issue_592_ignored_dirs_with_tracked_content(void) +{ + int count = 0; + git_repository *repo = cl_git_sandbox_init("issue_592b"); + + cl_git_pass(git_status_foreach(repo, cb_status__count, &count)); + cl_assert_equal_i(1, count); + + /* if we are really mimicking core git, then only ignored1.txt + * at the top level will show up in the ignores list here. + * everything else will be unmodified or skipped completely. + */ +} + +void test_status_worktree__conflict_with_diff3(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + git_index *index; + unsigned int status; + git_index_entry ancestor_entry, our_entry, their_entry; + + memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); + memset(&our_entry, 0x0, sizeof(git_index_entry)); + memset(&their_entry, 0x0, sizeof(git_index_entry)); + + ancestor_entry.path = "modified_file"; + git_oid_fromstr(&ancestor_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + our_entry.path = "modified_file"; + git_oid_fromstr(&our_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + their_entry.path = "modified_file"; + git_oid_fromstr(&their_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + cl_git_pass(git_status_file(&status, repo, "modified_file")); + cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_remove(index, "modified_file", 0)); + cl_git_pass(git_index_conflict_add( + index, &ancestor_entry, &our_entry, &their_entry)); + cl_git_pass(git_index_write(index)); + git_index_free(index); + + cl_git_pass(git_status_file(&status, repo, "modified_file")); + + cl_assert_equal_i(GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW, status); +} + +static const char *filemode_paths[] = { + "exec_off", + "exec_off2on_staged", + "exec_off2on_workdir", + "exec_off_untracked", + "exec_on", + "exec_on2off_staged", + "exec_on2off_workdir", + "exec_on_untracked", +}; + +static unsigned int filemode_statuses[] = { + GIT_STATUS_CURRENT, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW, + GIT_STATUS_CURRENT, + GIT_STATUS_INDEX_MODIFIED, + GIT_STATUS_WT_MODIFIED, + GIT_STATUS_WT_NEW +}; + +static const int filemode_count = 8; + +void test_status_worktree__filemode_changes(void) +{ + git_repository *repo = cl_git_sandbox_init("filemodes"); + status_entry_counts counts; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + + /* overwrite stored filemode with platform appropriate value */ + if (cl_is_chmod_supported()) + cl_repo_set_bool(repo, "core.filemode", true); + else { + int i; + + cl_repo_set_bool(repo, "core.filemode", false); + + /* won't trust filesystem mode diffs, so these will appear unchanged */ + for (i = 0; i < filemode_count; ++i) + if (filemode_statuses[i] == GIT_STATUS_WT_MODIFIED) + filemode_statuses[i] = GIT_STATUS_CURRENT; + } + + opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | + GIT_STATUS_OPT_INCLUDE_IGNORED | + GIT_STATUS_OPT_INCLUDE_UNMODIFIED; + + memset(&counts, 0, sizeof(counts)); + counts.expected_entry_count = filemode_count; + counts.expected_paths = filemode_paths; + counts.expected_statuses = filemode_statuses; + + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) + ); + + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +static int cb_status__interrupt(const char *p, unsigned int s, void *payload) +{ + volatile int *count = (int *)payload; + + GIT_UNUSED(p); + GIT_UNUSED(s); + + (*count)++; + + return (*count == 8); +} + +void test_status_worktree__interruptable_foreach(void) +{ + int count = 0; + git_repository *repo = cl_git_sandbox_init("status"); + + cl_assert_equal_i( + GIT_EUSER, git_status_foreach(repo, cb_status__interrupt, &count) + ); + + cl_assert_equal_i(8, count); +} + +void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + unsigned int status; + + cl_repo_set_bool(repo, "core.autocrlf", true); + + cl_git_rewritefile("status/current_file", "current_file\r\n"); + + cl_git_pass(git_status_file(&status, repo, "current_file")); + + cl_assert_equal_i(GIT_STATUS_CURRENT, status); +} + +void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf_issue_1397(void) +{ + git_repository *repo = cl_git_sandbox_init("issue_1397"); + unsigned int status; + + cl_repo_set_bool(repo, "core.autocrlf", true); + + cl_git_pass(git_status_file(&status, repo, "crlf_file.txt")); + + cl_assert_equal_i(GIT_STATUS_CURRENT, status); +} + +void test_status_worktree__conflicted_item(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + git_index *index; + unsigned int status; + git_index_entry ancestor_entry, our_entry, their_entry; + + memset(&ancestor_entry, 0x0, sizeof(git_index_entry)); + memset(&our_entry, 0x0, sizeof(git_index_entry)); + memset(&their_entry, 0x0, sizeof(git_index_entry)); + + ancestor_entry.path = "modified_file"; + git_oid_fromstr(&ancestor_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + our_entry.path = "modified_file"; + git_oid_fromstr(&our_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + their_entry.path = "modified_file"; + git_oid_fromstr(&their_entry.oid, + "452e4244b5d083ddf0460acf1ecc74db9dcfa11a"); + + cl_git_pass(git_status_file(&status, repo, "modified_file")); + cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_conflict_add(index, &ancestor_entry, + &our_entry, &their_entry)); + + cl_git_pass(git_status_file(&status, repo, "modified_file")); + cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); + + git_index_free(index); +} + +static void stage_and_commit(git_repository *repo, const char *path) +{ + git_index *index; + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_bypath(index, path)); + cl_repo_commit_from_index(NULL, repo, NULL, 1323847743, "Initial commit\n"); + git_index_free(index); +} + +static void assert_ignore_case( + bool should_ignore_case, + int expected_lower_cased_file_status, + int expected_camel_cased_file_status) +{ + unsigned int status; + git_buf lower_case_path = GIT_BUF_INIT, camel_case_path = GIT_BUF_INIT; + git_repository *repo, *repo2; + + repo = cl_git_sandbox_init("empty_standard_repo"); + cl_git_remove_placeholders(git_repository_path(repo), "dummy-marker.txt"); + + cl_repo_set_bool(repo, "core.ignorecase", should_ignore_case); + + cl_git_pass(git_buf_joinpath(&lower_case_path, + git_repository_workdir(repo), "plop")); + + cl_git_mkfile(git_buf_cstr(&lower_case_path), ""); + + stage_and_commit(repo, "plop"); + + cl_git_pass(git_repository_open(&repo2, "./empty_standard_repo")); + + cl_git_pass(git_status_file(&status, repo2, "plop")); + cl_assert_equal_i(GIT_STATUS_CURRENT, status); + + cl_git_pass(git_buf_joinpath(&camel_case_path, + git_repository_workdir(repo), "Plop")); + + cl_git_pass(p_rename(git_buf_cstr(&lower_case_path), git_buf_cstr(&camel_case_path))); + + cl_git_pass(git_status_file(&status, repo2, "plop")); + cl_assert_equal_i(expected_lower_cased_file_status, status); + + cl_git_pass(git_status_file(&status, repo2, "Plop")); + cl_assert_equal_i(expected_camel_cased_file_status, status); + + git_repository_free(repo2); + git_buf_free(&lower_case_path); + git_buf_free(&camel_case_path); +} + +void test_status_worktree__file_status_honors_core_ignorecase_true(void) +{ + assert_ignore_case(true, GIT_STATUS_CURRENT, GIT_STATUS_CURRENT); +} + +void test_status_worktree__file_status_honors_core_ignorecase_false(void) +{ + assert_ignore_case(false, GIT_STATUS_WT_DELETED, GIT_STATUS_WT_NEW); +} + +void test_status_worktree__file_status_honors_case_ignorecase_regarding_untracked_files(void) +{ + git_repository *repo = cl_git_sandbox_init("status"); + unsigned int status; + git_index *index; + + cl_repo_set_bool(repo, "core.ignorecase", false); + + repo = cl_git_sandbox_reopen(); + + /* Actually returns GIT_STATUS_IGNORED on Windows */ + cl_git_fail_with(git_status_file(&status, repo, "NEW_FILE"), GIT_ENOTFOUND); + + cl_git_pass(git_repository_index(&index, repo)); + + cl_git_pass(git_index_add_bypath(index, "new_file")); + cl_git_pass(git_index_write(index)); + git_index_free(index); + + /* Actually returns GIT_STATUS_IGNORED on Windows */ + cl_git_fail_with(git_status_file(&status, repo, "NEW_FILE"), GIT_ENOTFOUND); +} + +void test_status_worktree__simple_delete(void) +{ + git_repository *repo = cl_git_sandbox_init("renames"); + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + int count; + + opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | + GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH | + GIT_STATUS_OPT_EXCLUDE_SUBMODULES | + GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; + + count = 0; + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__count, &count) ); + cl_assert_equal_i(0, count); + + cl_must_pass(p_unlink("renames/untimely.txt")); + + count = 0; + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__count, &count) ); + cl_assert_equal_i(1, count); +} + +void test_status_worktree__simple_delete_indexed(void) +{ + git_repository *repo = cl_git_sandbox_init("renames"); + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + git_status_list *status; + + opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | + GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH | + GIT_STATUS_OPT_EXCLUDE_SUBMODULES | + GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; + + cl_git_pass(git_status_list_new(&status, repo, &opts)); + cl_assert_equal_sz(0, git_status_list_entrycount(status)); + git_status_list_free(status); + + cl_must_pass(p_unlink("renames/untimely.txt")); + + cl_git_pass(git_status_list_new(&status, repo, &opts)); + cl_assert_equal_sz(1, git_status_list_entrycount(status)); + cl_assert_equal_i( + GIT_STATUS_WT_DELETED, git_status_byindex(status, 0)->status); + git_status_list_free(status); +} + +static const char *icase_paths[] = { "B", "c", "g", "H" }; +static unsigned int icase_statuses[] = { + GIT_STATUS_WT_MODIFIED, GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_MODIFIED, GIT_STATUS_WT_DELETED, +}; + +static const char *case_paths[] = { "B", "H", "c", "g" }; +static unsigned int case_statuses[] = { + GIT_STATUS_WT_MODIFIED, GIT_STATUS_WT_DELETED, + GIT_STATUS_WT_DELETED, GIT_STATUS_WT_MODIFIED, +}; + +void test_status_worktree__sorting_by_case(void) +{ + git_repository *repo = cl_git_sandbox_init("icase"); + git_index *index; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + bool native_ignore_case; + status_entry_counts counts; + + cl_git_pass(git_repository_index(&index, repo)); + native_ignore_case = + (git_index_caps(index) & GIT_INDEXCAP_IGNORE_CASE) != 0; + git_index_free(index); + + memset(&counts, 0, sizeof(counts)); + counts.expected_entry_count = 0; + counts.expected_paths = NULL; + counts.expected_statuses = NULL; + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__normal, &counts)); + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); + + cl_git_rewritefile("icase/B", "new stuff"); + cl_must_pass(p_unlink("icase/c")); + cl_git_rewritefile("icase/g", "new stuff"); + cl_must_pass(p_unlink("icase/H")); + + memset(&counts, 0, sizeof(counts)); + counts.expected_entry_count = 4; + if (native_ignore_case) { + counts.expected_paths = icase_paths; + counts.expected_statuses = icase_statuses; + } else { + counts.expected_paths = case_paths; + counts.expected_statuses = case_statuses; + } + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__normal, &counts)); + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); + + opts.flags = GIT_STATUS_OPT_SORT_CASE_SENSITIVELY; + + memset(&counts, 0, sizeof(counts)); + counts.expected_entry_count = 4; + counts.expected_paths = case_paths; + counts.expected_statuses = case_statuses; + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__normal, &counts)); + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); + + opts.flags = GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY; + + memset(&counts, 0, sizeof(counts)); + counts.expected_entry_count = 4; + counts.expected_paths = icase_paths; + counts.expected_statuses = icase_statuses; + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__normal, &counts)); + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + +void test_status_worktree__long_filenames(void) +{ + char path[260*4+1]; + const char *expected_paths[] = {path}; + const unsigned int expected_statuses[] = {GIT_STATUS_WT_NEW}; + + git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + status_entry_counts counts = {0}; + + // Create directory with amazingly long filename + sprintf(path, "empty_standard_repo/%s", longname); + cl_git_pass(git_futils_mkdir_r(path, NULL, 0777)); + sprintf(path, "empty_standard_repo/%s/foo", longname); + cl_git_mkfile(path, "dummy"); + + sprintf(path, "%s/foo", longname); + counts.expected_entry_count = 1; + counts.expected_paths = expected_paths; + counts.expected_statuses = expected_statuses; + + opts.show = GIT_STATUS_SHOW_WORKDIR_ONLY; + opts.flags = GIT_STATUS_OPT_DEFAULTS; + + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__normal, &counts) ); + cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); + cl_assert_equal_i(0, counts.wrong_status_flags_count); + cl_assert_equal_i(0, counts.wrong_sorted_path); +} + diff --git a/tests/status/worktree_init.c b/tests/status/worktree_init.c new file mode 100644 index 000000000..296c27c86 --- /dev/null +++ b/tests/status/worktree_init.c @@ -0,0 +1,341 @@ +#include "clar_libgit2.h" +#include "git2/sys/repository.h" + +#include "fileops.h" +#include "ignore.h" +#include "status_helpers.h" +#include "posix.h" +#include "util.h" +#include "path.h" + +static void cleanup_new_repo(void *path) +{ + cl_fixture_cleanup((char *)path); +} + +void test_status_worktree_init__cannot_retrieve_the_status_of_a_bare_repository(void) +{ + git_repository *repo; + unsigned int status = 0; + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + cl_assert_equal_i(GIT_EBAREREPO, git_status_file(&status, repo, "dummy")); + git_repository_free(repo); +} + +void test_status_worktree_init__first_commit_in_progress(void) +{ + git_repository *repo; + git_index *index; + status_entry_single result; + + cl_set_cleanup(&cleanup_new_repo, "getting_started"); + + cl_git_pass(git_repository_init(&repo, "getting_started", 0)); + cl_git_mkfile("getting_started/testfile.txt", "content\n"); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(1, result.count); + cl_assert(result.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_bypath(index, "testfile.txt")); + cl_git_pass(git_index_write(index)); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(1, result.count); + cl_assert(result.status == GIT_STATUS_INDEX_NEW); + + git_index_free(index); + git_repository_free(repo); +} + + + +void test_status_worktree_init__status_file_without_index_or_workdir(void) +{ + git_repository *repo; + unsigned int status = 0; + git_index *index; + + cl_git_pass(p_mkdir("wd", 0777)); + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_repository_set_workdir(repo, "wd", false)); + + cl_git_pass(git_index_open(&index, "empty-index")); + cl_assert_equal_i(0, (int)git_index_entrycount(index)); + git_repository_set_index(repo, index); + + cl_git_pass(git_status_file(&status, repo, "branch_file.txt")); + + cl_assert_equal_i(GIT_STATUS_INDEX_DELETED, status); + + git_repository_free(repo); + git_index_free(index); + cl_git_pass(p_rmdir("wd")); +} + +static void fill_index_wth_head_entries(git_repository *repo, git_index *index) +{ + git_oid oid; + git_commit *commit; + git_tree *tree; + + cl_git_pass(git_reference_name_to_id(&oid, repo, "HEAD")); + cl_git_pass(git_commit_lookup(&commit, repo, &oid)); + cl_git_pass(git_commit_tree(&tree, commit)); + + cl_git_pass(git_index_read_tree(index, tree)); + cl_git_pass(git_index_write(index)); + + git_tree_free(tree); + git_commit_free(commit); +} + +void test_status_worktree_init__status_file_with_clean_index_and_empty_workdir(void) +{ + git_repository *repo; + unsigned int status = 0; + git_index *index; + + cl_git_pass(p_mkdir("wd", 0777)); + + cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); + cl_git_pass(git_repository_set_workdir(repo, "wd", false)); + + cl_git_pass(git_index_open(&index, "my-index")); + fill_index_wth_head_entries(repo, index); + + git_repository_set_index(repo, index); + + cl_git_pass(git_status_file(&status, repo, "branch_file.txt")); + + cl_assert_equal_i(GIT_STATUS_WT_DELETED, status); + + git_repository_free(repo); + git_index_free(index); + cl_git_pass(p_rmdir("wd")); + cl_git_pass(p_unlink("my-index")); +} + +void test_status_worktree_init__bracket_in_filename(void) +{ + git_repository *repo; + git_index *index; + status_entry_single result; + unsigned int status_flags; + int error; + + #define FILE_WITH_BRACKET "LICENSE[1].md" + #define FILE_WITHOUT_BRACKET "LICENSE1.md" + + cl_set_cleanup(&cleanup_new_repo, "with_bracket"); + + cl_git_pass(git_repository_init(&repo, "with_bracket", 0)); + cl_git_mkfile("with_bracket/" FILE_WITH_BRACKET, "I have a bracket in my name\n"); + + /* file is new to working directory */ + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(1, result.count); + cl_assert(result.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); + cl_assert(status_flags == GIT_STATUS_WT_NEW); + + /* ignore the file */ + + cl_git_rewritefile("with_bracket/.gitignore", "*.md\n.gitignore\n"); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(2, result.count); + cl_assert(result.status == GIT_STATUS_IGNORED); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); + cl_assert(status_flags == GIT_STATUS_IGNORED); + + /* don't ignore the file */ + + cl_git_rewritefile("with_bracket/.gitignore", ".gitignore\n"); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(2, result.count); + cl_assert(result.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); + cl_assert(status_flags == GIT_STATUS_WT_NEW); + + /* add the file to the index */ + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_bypath(index, FILE_WITH_BRACKET)); + cl_git_pass(git_index_write(index)); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(2, result.count); + cl_assert(result.status == GIT_STATUS_INDEX_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_BRACKET)); + cl_assert(status_flags == GIT_STATUS_INDEX_NEW); + + /* Create file without bracket */ + + cl_git_mkfile("with_bracket/" FILE_WITHOUT_BRACKET, "I have no bracket in my name!\n"); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITHOUT_BRACKET)); + cl_assert(status_flags == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, "LICENSE\\[1\\].md")); + cl_assert(status_flags == GIT_STATUS_INDEX_NEW); + + error = git_status_file(&status_flags, repo, FILE_WITH_BRACKET); + cl_git_fail(error); + cl_assert_equal_i(GIT_EAMBIGUOUS, error); + + git_index_free(index); + git_repository_free(repo); +} + +void test_status_worktree_init__space_in_filename(void) +{ + git_repository *repo; + git_index *index; + status_entry_single result; + unsigned int status_flags; + +#define FILE_WITH_SPACE "LICENSE - copy.md" + + cl_set_cleanup(&cleanup_new_repo, "with_space"); + cl_git_pass(git_repository_init(&repo, "with_space", 0)); + cl_git_mkfile("with_space/" FILE_WITH_SPACE, "I have a space in my name\n"); + + /* file is new to working directory */ + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(1, result.count); + cl_assert(result.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); + cl_assert(status_flags == GIT_STATUS_WT_NEW); + + /* ignore the file */ + + cl_git_rewritefile("with_space/.gitignore", "*.md\n.gitignore\n"); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(2, result.count); + cl_assert(result.status == GIT_STATUS_IGNORED); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); + cl_assert(status_flags == GIT_STATUS_IGNORED); + + /* don't ignore the file */ + + cl_git_rewritefile("with_space/.gitignore", ".gitignore\n"); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(2, result.count); + cl_assert(result.status == GIT_STATUS_WT_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); + cl_assert(status_flags == GIT_STATUS_WT_NEW); + + /* add the file to the index */ + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_bypath(index, FILE_WITH_SPACE)); + cl_git_pass(git_index_write(index)); + + memset(&result, 0, sizeof(result)); + cl_git_pass(git_status_foreach(repo, cb_status__single, &result)); + cl_assert_equal_i(2, result.count); + cl_assert(result.status == GIT_STATUS_INDEX_NEW); + + cl_git_pass(git_status_file(&status_flags, repo, FILE_WITH_SPACE)); + cl_assert(status_flags == GIT_STATUS_INDEX_NEW); + + git_index_free(index); + git_repository_free(repo); +} + +static int cb_status__expected_path(const char *p, unsigned int s, void *payload) +{ + const char *expected_path = (const char *)payload; + + GIT_UNUSED(s); + + if (payload == NULL) + cl_fail("Unexpected path"); + + cl_assert_equal_s(expected_path, p); + + return 0; +} + +void test_status_worktree_init__disable_pathspec_match(void) +{ + git_repository *repo; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + char *file_with_bracket = "LICENSE[1].md", + *imaginary_file_with_bracket = "LICENSE[1-2].md"; + + cl_set_cleanup(&cleanup_new_repo, "pathspec"); + cl_git_pass(git_repository_init(&repo, "pathspec", 0)); + cl_git_mkfile("pathspec/LICENSE[1].md", "screaming bracket\n"); + cl_git_mkfile("pathspec/LICENSE1.md", "no bracket\n"); + + opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | + GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH; + opts.pathspec.count = 1; + opts.pathspec.strings = &file_with_bracket; + + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__expected_path, + file_with_bracket) + ); + + /* Test passing a pathspec matching files in the workdir. */ + /* Must not match because pathspecs are disabled. */ + opts.pathspec.strings = &imaginary_file_with_bracket; + cl_git_pass( + git_status_foreach_ext(repo, &opts, cb_status__expected_path, NULL) + ); + + git_repository_free(repo); +} + +void test_status_worktree_init__new_staged_file_must_handle_crlf(void) +{ + git_repository *repo; + git_index *index; + unsigned int status; + + cl_set_cleanup(&cleanup_new_repo, "getting_started"); + cl_git_pass(git_repository_init(&repo, "getting_started", 0)); + + /* Ensure that repo has core.autocrlf=true */ + cl_repo_set_bool(repo, "core.autocrlf", true); + + cl_git_mkfile("getting_started/testfile.txt", "content\r\n"); /* Content with CRLF */ + + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_add_bypath(index, "testfile.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_status_file(&status, repo, "testfile.txt")); + cl_assert_equal_i(GIT_STATUS_INDEX_NEW, status); + + git_index_free(index); + git_repository_free(repo); +} + diff --git a/tests/stress/diff.c b/tests/stress/diff.c new file mode 100644 index 000000000..3d2092614 --- /dev/null +++ b/tests/stress/diff.c @@ -0,0 +1,146 @@ +#include "clar_libgit2.h" +#include "../diff/diff_helpers.h" + +static git_repository *g_repo = NULL; + +void test_stress_diff__initialize(void) +{ +} + +void test_stress_diff__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +#define ANOTHER_POEM \ +"OH, glorious are the guarded heights\nWhere guardian souls abide—\nSelf-exiled from our gross delights—\nAbove, beyond, outside:\nAn ampler arc their spirit swings—\nCommands a juster view—\nWe have their word for all these things,\nNo doubt their words are true.\n\nYet we, the bond slaves of our day,\nWhom dirt and danger press—\nCo-heirs of insolence, delay,\nAnd leagued unfaithfulness—\nSuch is our need must seek indeed\nAnd, having found, engage\nThe men who merely do the work\nFor which they draw the wage.\n\nFrom forge and farm and mine and bench,\nDeck, altar, outpost lone—\nMill, school, battalion, counter, trench,\nRail, senate, sheepfold, throne—\nCreation's cry goes up on high\nFrom age to cheated age:\n\"Send us the men who do the work\n\"For which they draw the wage!\"\n" + +static void test_with_many(int expected_new) +{ + git_index *index; + git_tree *tree, *new_tree; + git_diff *diff = NULL; + diff_expects exp; + git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; + git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass( + git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/ikeepsix2.txt")); + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, "ikeepsix2.txt")); + cl_git_pass(git_index_write(index)); + + cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &exp)); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(expected_new + 2, exp.files); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &exp)); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(expected_new + 1, exp.files); + + git_diff_free(diff); + + cl_repo_commit_from_index(NULL, g_repo, NULL, 1372350000, "yoyoyo"); + cl_git_pass(git_revparse_single( + (git_object **)&new_tree, g_repo, "HEAD^{tree}")); + + cl_git_pass(git_diff_tree_to_tree( + &diff, g_repo, tree, new_tree, &diffopts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &exp)); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); + cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(expected_new + 2, exp.files); + + opts.flags = GIT_DIFF_FIND_ALL; + cl_git_pass(git_diff_find_similar(diff, &opts)); + + memset(&exp, 0, sizeof(exp)); + cl_git_pass(git_diff_foreach( + diff, diff_file_cb, NULL, NULL, &exp)); + cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); + cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); + cl_assert_equal_i(expected_new + 1, exp.files); + + git_diff_free(diff); + + git_tree_free(new_tree); + git_tree_free(tree); + git_index_free(index); +} + +void test_stress_diff__rename_big_files(void) +{ + git_index *index; + char tmp[64]; + int i, j; + git_buf b = GIT_BUF_INIT; + + g_repo = cl_git_sandbox_init("renames"); + + cl_git_pass(git_repository_index(&index, g_repo)); + + for (i = 0; i < 100; i += 1) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + for (j = i * 256; j > 0; --j) + git_buf_printf(&b, "more content %d\n", i); + cl_git_mkfile(tmp, b.ptr); + } + + for (i = 0; i < 100; i += 1) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/"))); + } + + git_buf_free(&b); + git_index_free(index); + + test_with_many(100); +} + +void test_stress_diff__rename_many_files(void) +{ + git_index *index; + char tmp[64]; + int i; + git_buf b = GIT_BUF_INIT; + + g_repo = cl_git_sandbox_init("renames"); + + cl_git_pass(git_repository_index(&index, g_repo)); + + git_buf_printf(&b, "%08d\n" ANOTHER_POEM "%08d\n" ANOTHER_POEM ANOTHER_POEM, 0, 0); + + for (i = 0; i < 2500; i += 1) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + snprintf(b.ptr, 9, "%08d", i); + b.ptr[8] = '\n'; + cl_git_mkfile(tmp, b.ptr); + } + git_buf_free(&b); + + for (i = 0; i < 2500; i += 1) { + snprintf(tmp, sizeof(tmp), "renames/newfile%03d", i); + cl_git_pass(git_index_add_bypath(index, tmp + strlen("renames/"))); + } + + git_index_free(index); + + test_with_many(2500); +} diff --git a/tests/submodule/lookup.c b/tests/submodule/lookup.c new file mode 100644 index 000000000..5f320e702 --- /dev/null +++ b/tests/submodule/lookup.c @@ -0,0 +1,172 @@ +#include "clar_libgit2.h" +#include "submodule_helpers.h" +#include "posix.h" +#include "git2/sys/repository.h" + +static git_repository *g_repo = NULL; + +void test_submodule_lookup__initialize(void) +{ + g_repo = setup_fixture_submod2(); +} + +void test_submodule_lookup__simple_lookup(void) +{ + git_submodule *sm; + + /* lookup existing */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_assert(sm); + + /* lookup pending change in .gitmodules that is not in HEAD */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); + cl_assert(sm); + + /* lookup pending change in .gitmodules that is neither in HEAD nor index */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); + cl_assert(sm); + + /* lookup git repo subdir that is not added as submodule */ + cl_assert(git_submodule_lookup(&sm, g_repo, "not-submodule") == GIT_EEXISTS); + + /* lookup existing directory that is not a submodule */ + cl_assert(git_submodule_lookup(&sm, g_repo, "just_a_dir") == GIT_ENOTFOUND); + + /* lookup existing file that is not a submodule */ + cl_assert(git_submodule_lookup(&sm, g_repo, "just_a_file") == GIT_ENOTFOUND); + + /* lookup non-existent item */ + cl_assert(git_submodule_lookup(&sm, g_repo, "no_such_file") == GIT_ENOTFOUND); +} + +void test_submodule_lookup__accessors(void) +{ + git_submodule *sm; + const char *oid = "480095882d281ed676fe5b863569520e54a7d5c0"; + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_assert(git_submodule_owner(sm) == g_repo); + cl_assert_equal_s("sm_unchanged", git_submodule_name(sm)); + cl_assert(git__suffixcmp(git_submodule_path(sm), "sm_unchanged") == 0); + cl_assert(git__suffixcmp(git_submodule_url(sm), "/submod2_target") == 0); + + cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0); + cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0); + cl_assert(git_oid_streq(git_submodule_wd_id(sm), oid) == 0); + + cl_assert(git_submodule_ignore(sm) == GIT_SUBMODULE_IGNORE_NONE); + cl_assert(git_submodule_update(sm) == GIT_SUBMODULE_UPDATE_CHECKOUT); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); + cl_assert_equal_s("sm_changed_head", git_submodule_name(sm)); + + cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0); + cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0); + cl_assert(git_oid_streq(git_submodule_wd_id(sm), + "3d9386c507f6b093471a3e324085657a3c2b4247") == 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); + cl_assert_equal_s("sm_added_and_uncommited", git_submodule_name(sm)); + + cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0); + cl_assert(git_submodule_head_id(sm) == NULL); + cl_assert(git_oid_streq(git_submodule_wd_id(sm), oid) == 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); + cl_assert_equal_s("sm_missing_commits", git_submodule_name(sm)); + + cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0); + cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0); + cl_assert(git_oid_streq(git_submodule_wd_id(sm), + "5e4963595a9774b90524d35a807169049de8ccad") == 0); +} + +typedef struct { + int count; +} sm_lookup_data; + +static int sm_lookup_cb(git_submodule *sm, const char *name, void *payload) +{ + sm_lookup_data *data = payload; + data->count += 1; + cl_assert_equal_s(git_submodule_name(sm), name); + return 0; +} + +void test_submodule_lookup__foreach(void) +{ + sm_lookup_data data; + memset(&data, 0, sizeof(data)); + cl_git_pass(git_submodule_foreach(g_repo, sm_lookup_cb, &data)); + cl_assert_equal_i(8, data.count); +} + +void test_submodule_lookup__lookup_even_with_unborn_head(void) +{ + git_reference *head; + git_submodule *sm; + + /* put us on an unborn branch */ + cl_git_pass(git_reference_symbolic_create( + &head, g_repo, "HEAD", "refs/heads/garbage", 1)); + git_reference_free(head); + + /* lookup existing */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_assert(sm); + + /* lookup pending change in .gitmodules that is not in HEAD */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); + cl_assert(sm); + + /* lookup pending change in .gitmodules that is neither in HEAD nor index */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); + cl_assert(sm); + + /* lookup git repo subdir that is not added as submodule */ + cl_assert_equal_i(GIT_EEXISTS, git_submodule_lookup(&sm, g_repo, "not-submodule")); + + /* lookup existing directory that is not a submodule */ + cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_dir")); + + /* lookup existing file that is not a submodule */ + cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_file")); + + /* lookup non-existent item */ + cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "no_such_file")); +} + +void test_submodule_lookup__lookup_even_with_missing_index(void) +{ + git_index *idx; + git_submodule *sm; + + /* give the repo an empty index */ + cl_git_pass(git_index_new(&idx)); + git_repository_set_index(g_repo, idx); + git_index_free(idx); + + /* lookup existing */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_assert(sm); + + /* lookup pending change in .gitmodules that is not in HEAD */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); + cl_assert(sm); + + /* lookup pending change in .gitmodules that is neither in HEAD nor index */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); + cl_assert(sm); + + /* lookup git repo subdir that is not added as submodule */ + cl_assert_equal_i(GIT_EEXISTS, git_submodule_lookup(&sm, g_repo, "not-submodule")); + + /* lookup existing directory that is not a submodule */ + cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_dir")); + + /* lookup existing file that is not a submodule */ + cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_file")); + + /* lookup non-existent item */ + cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "no_such_file")); +} diff --git a/tests/submodule/modify.c b/tests/submodule/modify.c new file mode 100644 index 000000000..e326287a6 --- /dev/null +++ b/tests/submodule/modify.c @@ -0,0 +1,253 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "path.h" +#include "submodule_helpers.h" + +static git_repository *g_repo = NULL; + +#define SM_LIBGIT2_URL "https://github.com/libgit2/libgit2.git" +#define SM_LIBGIT2 "sm_libgit2" +#define SM_LIBGIT2B "sm_libgit2b" + +void test_submodule_modify__initialize(void) +{ + g_repo = setup_fixture_submod2(); +} + +void test_submodule_modify__add(void) +{ + git_submodule *sm; + git_config *cfg; + const char *s; + + /* re-add existing submodule */ + cl_assert( + git_submodule_add_setup(NULL, g_repo, "whatever", "sm_unchanged", 1) == + GIT_EEXISTS ); + + /* add a submodule using a gitlink */ + + cl_git_pass( + git_submodule_add_setup(&sm, g_repo, SM_LIBGIT2_URL, SM_LIBGIT2, 1) + ); + + cl_assert(git_path_isfile("submod2/" SM_LIBGIT2 "/.git")); + + cl_assert(git_path_isdir("submod2/.git/modules")); + cl_assert(git_path_isdir("submod2/.git/modules/" SM_LIBGIT2)); + cl_assert(git_path_isfile("submod2/.git/modules/" SM_LIBGIT2 "/HEAD")); + + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass( + git_config_get_string(&s, cfg, "submodule." SM_LIBGIT2 ".url")); + cl_assert_equal_s(s, SM_LIBGIT2_URL); + git_config_free(cfg); + + /* add a submodule not using a gitlink */ + + cl_git_pass( + git_submodule_add_setup(&sm, g_repo, SM_LIBGIT2_URL, SM_LIBGIT2B, 0) + ); + + cl_assert(git_path_isdir("submod2/" SM_LIBGIT2B "/.git")); + cl_assert(git_path_isfile("submod2/" SM_LIBGIT2B "/.git/HEAD")); + cl_assert(!git_path_exists("submod2/.git/modules/" SM_LIBGIT2B)); + + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass( + git_config_get_string(&s, cfg, "submodule." SM_LIBGIT2B ".url")); + cl_assert_equal_s(s, SM_LIBGIT2_URL); + git_config_free(cfg); +} + +static int delete_one_config(const git_config_entry *entry, void *payload) +{ + git_config *cfg = payload; + return git_config_delete_entry(cfg, entry->name); +} + +static int init_one_submodule( + git_submodule *sm, const char *name, void *payload) +{ + GIT_UNUSED(name); + GIT_UNUSED(payload); + return git_submodule_init(sm, false); +} + +void test_submodule_modify__init(void) +{ + git_config *cfg; + const char *str; + + /* erase submodule data from .git/config */ + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass( + git_config_foreach_match(cfg, "submodule\\..*", delete_one_config, cfg)); + git_config_free(cfg); + + /* confirm no submodule data in config */ + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_fail(git_config_get_string(&str, cfg, "submodule.sm_unchanged.url")); + cl_git_fail(git_config_get_string(&str, cfg, "submodule.sm_changed_head.url")); + cl_git_fail(git_config_get_string(&str, cfg, "submodule.sm_added_and_uncommited.url")); + git_config_free(cfg); + + /* call init and see that settings are copied */ + cl_git_pass(git_submodule_foreach(g_repo, init_one_submodule, NULL)); + + git_submodule_reload_all(g_repo); + + /* confirm submodule data in config */ + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_get_string(&str, cfg, "submodule.sm_unchanged.url")); + cl_assert(git__suffixcmp(str, "/submod2_target") == 0); + cl_git_pass(git_config_get_string(&str, cfg, "submodule.sm_changed_head.url")); + cl_assert(git__suffixcmp(str, "/submod2_target") == 0); + cl_git_pass(git_config_get_string(&str, cfg, "submodule.sm_added_and_uncommited.url")); + cl_assert(git__suffixcmp(str, "/submod2_target") == 0); + git_config_free(cfg); +} + +static int sync_one_submodule( + git_submodule *sm, const char *name, void *payload) +{ + GIT_UNUSED(name); + GIT_UNUSED(payload); + return git_submodule_sync(sm); +} + +void test_submodule_modify__sync(void) +{ + git_submodule *sm1, *sm2, *sm3; + git_config *cfg; + const char *str; + +#define SM1 "sm_unchanged" +#define SM2 "sm_changed_head" +#define SM3 "sm_added_and_uncommited" + + /* look up some submodules */ + cl_git_pass(git_submodule_lookup(&sm1, g_repo, SM1)); + cl_git_pass(git_submodule_lookup(&sm2, g_repo, SM2)); + cl_git_pass(git_submodule_lookup(&sm3, g_repo, SM3)); + + /* At this point, the .git/config URLs for the submodules have + * not be rewritten with the absolute paths (although the + * .gitmodules have. Let's confirm that they DO NOT match + * yet, then we can do a sync to make them match... + */ + + /* check submodule info does not match before sync */ + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM1".url")); + cl_assert(strcmp(git_submodule_url(sm1), str) != 0); + cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM2".url")); + cl_assert(strcmp(git_submodule_url(sm2), str) != 0); + cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM3".url")); + cl_assert(strcmp(git_submodule_url(sm3), str) != 0); + git_config_free(cfg); + + /* sync all the submodules */ + cl_git_pass(git_submodule_foreach(g_repo, sync_one_submodule, NULL)); + + /* check that submodule config is updated */ + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM1".url")); + cl_assert_equal_s(git_submodule_url(sm1), str); + cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM2".url")); + cl_assert_equal_s(git_submodule_url(sm2), str); + cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM3".url")); + cl_assert_equal_s(git_submodule_url(sm3), str); + git_config_free(cfg); +} + +void test_submodule_modify__edit_and_save(void) +{ + git_submodule *sm1, *sm2; + char *old_url; + git_submodule_ignore_t old_ignore; + git_submodule_update_t old_update; + git_repository *r2; + int old_fetchrecurse; + + cl_git_pass(git_submodule_lookup(&sm1, g_repo, "sm_changed_head")); + + old_url = git__strdup(git_submodule_url(sm1)); + + /* modify properties of submodule */ + cl_git_pass(git_submodule_set_url(sm1, SM_LIBGIT2_URL)); + old_ignore = git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_UNTRACKED); + old_update = git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_REBASE); + old_fetchrecurse = git_submodule_set_fetch_recurse_submodules(sm1, 1); + + cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm1)); + cl_assert_equal_i( + (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm1)); + cl_assert_equal_i( + (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm1)); + cl_assert_equal_i(1, git_submodule_fetch_recurse_submodules(sm1)); + + /* revert without saving (and confirm setters return old value) */ + cl_git_pass(git_submodule_set_url(sm1, old_url)); + cl_assert_equal_i( + (int)GIT_SUBMODULE_IGNORE_UNTRACKED, + (int)git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_RESET)); + cl_assert_equal_i( + (int)GIT_SUBMODULE_UPDATE_REBASE, + (int)git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_RESET)); + cl_assert_equal_i( + 1, git_submodule_set_fetch_recurse_submodules(sm1, old_fetchrecurse)); + + /* check that revert was successful */ + cl_assert_equal_s(old_url, git_submodule_url(sm1)); + cl_assert_equal_i((int)old_ignore, (int)git_submodule_ignore(sm1)); + cl_assert_equal_i((int)old_update, (int)git_submodule_update(sm1)); + cl_assert_equal_i( + old_fetchrecurse, git_submodule_fetch_recurse_submodules(sm1)); + + /* modify properties of submodule (again) */ + cl_git_pass(git_submodule_set_url(sm1, SM_LIBGIT2_URL)); + git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_UNTRACKED); + git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_REBASE); + git_submodule_set_fetch_recurse_submodules(sm1, 1); + + /* call save */ + cl_git_pass(git_submodule_save(sm1)); + + /* attempt to "revert" values */ + git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_RESET); + git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_RESET); + + /* but ignore and update should NOT revert because the RESET + * should now be the newly saved value... + */ + cl_assert_equal_i( + (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm1)); + cl_assert_equal_i( + (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm1)); + cl_assert_equal_i(1, git_submodule_fetch_recurse_submodules(sm1)); + + /* call reload and check that the new values are loaded */ + cl_git_pass(git_submodule_reload(sm1)); + + cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm1)); + cl_assert_equal_i( + (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm1)); + cl_assert_equal_i( + (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm1)); + cl_assert_equal_i(1, git_submodule_fetch_recurse_submodules(sm1)); + + /* open a second copy of the repo and compare submodule */ + cl_git_pass(git_repository_open(&r2, "submod2")); + cl_git_pass(git_submodule_lookup(&sm2, r2, "sm_changed_head")); + + cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm2)); + cl_assert_equal_i( + (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm2)); + cl_assert_equal_i( + (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm2)); + cl_assert_equal_i(1, git_submodule_fetch_recurse_submodules(sm2)); + + git_repository_free(r2); + git__free(old_url); +} diff --git a/tests/submodule/status.c b/tests/submodule/status.c new file mode 100644 index 000000000..f5111c84f --- /dev/null +++ b/tests/submodule/status.c @@ -0,0 +1,425 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "path.h" +#include "submodule_helpers.h" +#include "fileops.h" +#include "iterator.h" + +static git_repository *g_repo = NULL; + +void test_submodule_status__initialize(void) +{ + g_repo = setup_fixture_submod2(); +} + +void test_submodule_status__cleanup(void) +{ +} + +void test_submodule_status__unchanged(void) +{ + unsigned int status, expected; + git_submodule *sm; + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + expected = GIT_SUBMODULE_STATUS_IN_HEAD | + GIT_SUBMODULE_STATUS_IN_INDEX | + GIT_SUBMODULE_STATUS_IN_CONFIG | + GIT_SUBMODULE_STATUS_IN_WD; + + cl_assert(status == expected); +} + +/* 4 values of GIT_SUBMODULE_IGNORE to check */ + +void test_submodule_status__ignore_none(void) +{ + unsigned int status; + git_submodule *sm; + git_buf path = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged")); + cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); + + cl_assert_equal_i(GIT_ENOTFOUND, + git_submodule_lookup(&sm, g_repo, "just_a_dir")); + cl_assert_equal_i(GIT_EEXISTS, + git_submodule_lookup(&sm, g_repo, "not-submodule")); + cl_assert_equal_i(GIT_EEXISTS, + git_submodule_lookup(&sm, g_repo, "not")); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) != 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) != 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNTRACKED) != 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0); + + /* removed sm_unchanged for deleted workdir */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0); + + /* now mkdir sm_unchanged to test uninitialized */ + cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_git_pass(git_submodule_reload(sm)); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0); + + /* update sm_changed_head in index */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); + cl_git_pass(git_submodule_add_to_index(sm, true)); + /* reload is not needed because add_to_index updates the submodule data */ + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0); + + /* remove sm_changed_head from index */ + { + git_index *index; + size_t pos; + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_assert(!git_index_find(&pos, index, "sm_changed_head")); + cl_git_pass(git_index_remove(index, "sm_changed_head", 0)); + cl_git_pass(git_index_write(index)); + + git_index_free(index); + } + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); + cl_git_pass(git_submodule_reload(sm)); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_DELETED) != 0); + + git_buf_free(&path); +} + +static int set_sm_ignore(git_submodule *sm, const char *name, void *payload) +{ + git_submodule_ignore_t ignore = *(git_submodule_ignore_t *)payload; + GIT_UNUSED(name); + git_submodule_set_ignore(sm, ignore); + return 0; +} + +void test_submodule_status__ignore_untracked(void) +{ + unsigned int status; + git_submodule *sm; + git_buf path = GIT_BUF_INIT; + git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_UNTRACKED; + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged")); + cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); + + cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign)); + + cl_git_fail(git_submodule_lookup(&sm, g_repo, "not-submodule")); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) != 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) != 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0); + + /* removed sm_unchanged for deleted workdir */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0); + + /* now mkdir sm_unchanged to test uninitialized */ + cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_git_pass(git_submodule_reload(sm)); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0); + + /* update sm_changed_head in index */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); + cl_git_pass(git_submodule_add_to_index(sm, true)); + /* reload is not needed because add_to_index updates the submodule data */ + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0); + + git_buf_free(&path); +} + +void test_submodule_status__ignore_dirty(void) +{ + unsigned int status; + git_submodule *sm; + git_buf path = GIT_BUF_INIT; + git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_DIRTY; + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged")); + cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); + + cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign)); + + cl_assert_equal_i(GIT_ENOTFOUND, + git_submodule_lookup(&sm, g_repo, "just_a_dir")); + cl_assert_equal_i(GIT_EEXISTS, + git_submodule_lookup(&sm, g_repo, "not-submodule")); + cl_assert_equal_i(GIT_EEXISTS, + git_submodule_lookup(&sm, g_repo, "not")); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0); + + /* removed sm_unchanged for deleted workdir */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0); + + /* now mkdir sm_unchanged to test uninitialized */ + cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_git_pass(git_submodule_reload(sm)); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0); + + /* update sm_changed_head in index */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); + cl_git_pass(git_submodule_add_to_index(sm, true)); + /* reload is not needed because add_to_index updates the submodule data */ + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0); + + git_buf_free(&path); +} + +void test_submodule_status__ignore_all(void) +{ + unsigned int status; + git_submodule *sm; + git_buf path = GIT_BUF_INIT; + git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_ALL; + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged")); + cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); + + cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign)); + + cl_assert_equal_i(GIT_ENOTFOUND, + git_submodule_lookup(&sm, g_repo, "just_a_dir")); + cl_assert_equal_i(GIT_EEXISTS, + git_submodule_lookup(&sm, g_repo, "not-submodule")); + cl_assert_equal_i(GIT_EEXISTS, + git_submodule_lookup(&sm, g_repo, "not")); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + /* removed sm_unchanged for deleted workdir */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + /* now mkdir sm_unchanged to test uninitialized */ + cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_git_pass(git_submodule_reload(sm)); + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + /* update sm_changed_head in index */ + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); + cl_git_pass(git_submodule_add_to_index(sm, true)); + /* reload is not needed because add_to_index updates the submodule data */ + cl_git_pass(git_submodule_status(&status, sm)); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + git_buf_free(&path); +} + +typedef struct { + size_t counter; + const char **paths; + int *statuses; +} submodule_expectations; + +static int confirm_submodule_status( + const char *path, unsigned int status_flags, void *payload) +{ + submodule_expectations *exp = payload; + + while (git__suffixcmp(exp->paths[exp->counter], "/") == 0) + exp->counter++; + + cl_assert_equal_i(exp->statuses[exp->counter], (int)status_flags); + cl_assert_equal_s(exp->paths[exp->counter++], path); + + GIT_UNUSED(status_flags); + + return 0; +} + +void test_submodule_status__iterator(void) +{ + git_iterator *iter; + const git_index_entry *entry; + size_t i; + static const char *expected[] = { + ".gitmodules", + "just_a_dir/", + "just_a_dir/contents", + "just_a_file", + "not", + "not-submodule", + "README.txt", + "sm_added_and_uncommited", + "sm_changed_file", + "sm_changed_head", + "sm_changed_index", + "sm_changed_untracked_file", + "sm_missing_commits", + "sm_unchanged", + NULL + }; + static int expected_flags[] = { + GIT_STATUS_INDEX_MODIFIED | GIT_STATUS_WT_MODIFIED, /* ".gitmodules" */ + 0, /* "just_a_dir/" will be skipped */ + GIT_STATUS_CURRENT, /* "just_a_dir/contents" */ + GIT_STATUS_CURRENT, /* "just_a_file" */ + GIT_STATUS_IGNORED, /* "not" (contains .git) */ + GIT_STATUS_IGNORED, /* "not-submodule" (contains .git) */ + GIT_STATUS_CURRENT, /* "README.txt */ + GIT_STATUS_INDEX_NEW, /* "sm_added_and_uncommited" */ + GIT_STATUS_WT_MODIFIED, /* "sm_changed_file" */ + GIT_STATUS_WT_MODIFIED, /* "sm_changed_head" */ + GIT_STATUS_WT_MODIFIED, /* "sm_changed_index" */ + GIT_STATUS_WT_MODIFIED, /* "sm_changed_untracked_file" */ + GIT_STATUS_WT_MODIFIED, /* "sm_missing_commits" */ + GIT_STATUS_CURRENT, /* "sm_unchanged" */ + 0 + }; + submodule_expectations exp = { 0, expected, expected_flags }; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + + cl_git_pass(git_iterator_for_workdir(&iter, g_repo, + GIT_ITERATOR_IGNORE_CASE | GIT_ITERATOR_INCLUDE_TREES, NULL, NULL)); + + for (i = 0; !git_iterator_advance(&entry, iter); ++i) + cl_assert_equal_s(expected[i], entry->path); + + git_iterator_free(iter); + + opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | + GIT_STATUS_OPT_INCLUDE_UNMODIFIED | + GIT_STATUS_OPT_INCLUDE_IGNORED | + GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS | + GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY; + + cl_git_pass(git_status_foreach_ext( + g_repo, &opts, confirm_submodule_status, &exp)); +} + +void test_submodule_status__untracked_dirs_containing_ignored_files(void) +{ + git_buf path = GIT_BUF_INIT; + unsigned int status, expected; + git_submodule *sm; + + cl_git_pass(git_buf_joinpath(&path, git_repository_path(g_repo), "modules/sm_unchanged/info/exclude")); + cl_git_append2file(git_buf_cstr(&path), "\n*.ignored\n"); + + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged/directory")); + cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); + cl_git_pass(git_buf_joinpath(&path, git_buf_cstr(&path), "i_am.ignored")); + cl_git_mkfile(git_buf_cstr(&path), "ignored this file, please\n"); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_git_pass(git_submodule_status(&status, sm)); + + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + + expected = GIT_SUBMODULE_STATUS_IN_HEAD | + GIT_SUBMODULE_STATUS_IN_INDEX | + GIT_SUBMODULE_STATUS_IN_CONFIG | + GIT_SUBMODULE_STATUS_IN_WD; + + cl_assert(status == expected); + + git_buf_free(&path); +} diff --git a/tests/submodule/submodule_helpers.c b/tests/submodule/submodule_helpers.c new file mode 100644 index 000000000..d5750675c --- /dev/null +++ b/tests/submodule/submodule_helpers.c @@ -0,0 +1,127 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "path.h" +#include "util.h" +#include "posix.h" +#include "submodule_helpers.h" +#include "git2/sys/repository.h" + +/* rewrite gitmodules -> .gitmodules + * rewrite the empty or relative urls inside each module + * rename the .gitted directory inside any submodule to .git + */ +void rewrite_gitmodules(const char *workdir) +{ + git_buf in_f = GIT_BUF_INIT, out_f = GIT_BUF_INIT, path = GIT_BUF_INIT; + FILE *in, *out; + char line[256]; + + cl_git_pass(git_buf_joinpath(&in_f, workdir, "gitmodules")); + cl_git_pass(git_buf_joinpath(&out_f, workdir, ".gitmodules")); + + cl_assert((in = fopen(in_f.ptr, "r")) != NULL); + cl_assert((out = fopen(out_f.ptr, "w")) != NULL); + + while (fgets(line, sizeof(line), in) != NULL) { + char *scan = line; + + while (*scan == ' ' || *scan == '\t') scan++; + + /* rename .gitted -> .git in submodule directories */ + if (git__prefixcmp(scan, "path =") == 0) { + scan += strlen("path ="); + while (*scan == ' ') scan++; + + git_buf_joinpath(&path, workdir, scan); + git_buf_rtrim(&path); + git_buf_joinpath(&path, path.ptr, ".gitted"); + + if (!git_buf_oom(&path) && p_access(path.ptr, F_OK) == 0) { + git_buf_joinpath(&out_f, workdir, scan); + git_buf_rtrim(&out_f); + git_buf_joinpath(&out_f, out_f.ptr, ".git"); + + if (!git_buf_oom(&out_f)) + p_rename(path.ptr, out_f.ptr); + } + } + + /* copy non-"url =" lines verbatim */ + if (git__prefixcmp(scan, "url =") != 0) { + fputs(line, out); + continue; + } + + /* convert relative URLs in "url =" lines */ + scan += strlen("url ="); + while (*scan == ' ') scan++; + + if (*scan == '.') { + git_buf_joinpath(&path, workdir, scan); + git_buf_rtrim(&path); + } else if (!*scan || *scan == '\n') { + git_buf_joinpath(&path, workdir, "../testrepo.git"); + } else { + fputs(line, out); + continue; + } + + git_path_prettify(&path, path.ptr, NULL); + git_buf_putc(&path, '\n'); + cl_assert(!git_buf_oom(&path)); + + fwrite(line, scan - line, sizeof(char), out); + fputs(path.ptr, out); + } + + fclose(in); + fclose(out); + + cl_must_pass(p_unlink(in_f.ptr)); + + git_buf_free(&in_f); + git_buf_free(&out_f); + git_buf_free(&path); +} + +static void cleanup_fixture_submodules(void *payload) +{ + cl_git_sandbox_cleanup(); /* either "submodules" or "submod2" */ + + if (payload) + cl_fixture_cleanup(payload); +} + +git_repository *setup_fixture_submodules(void) +{ + git_repository *repo = cl_git_sandbox_init("submodules"); + + cl_fixture_sandbox("testrepo.git"); + + rewrite_gitmodules(git_repository_workdir(repo)); + p_rename("submodules/testrepo/.gitted", "submodules/testrepo/.git"); + + cl_set_cleanup(cleanup_fixture_submodules, "testrepo.git"); + + cl_git_pass(git_repository_reinit_filesystem(repo, 1)); + + return repo; +} + +git_repository *setup_fixture_submod2(void) +{ + git_repository *repo = cl_git_sandbox_init("submod2"); + + cl_fixture_sandbox("submod2_target"); + p_rename("submod2_target/.gitted", "submod2_target/.git"); + + rewrite_gitmodules(git_repository_workdir(repo)); + p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git"); + p_rename("submod2/not/.gitted", "submod2/not/.git"); + + cl_set_cleanup(cleanup_fixture_submodules, "submod2_target"); + + cl_git_pass(git_repository_reinit_filesystem(repo, 1)); + + return repo; +} diff --git a/tests/submodule/submodule_helpers.h b/tests/submodule/submodule_helpers.h new file mode 100644 index 000000000..610c40720 --- /dev/null +++ b/tests/submodule/submodule_helpers.h @@ -0,0 +1,5 @@ +extern void rewrite_gitmodules(const char *workdir); + +/* these will automatically set a cleanup callback */ +extern git_repository *setup_fixture_submodules(void); +extern git_repository *setup_fixture_submod2(void); diff --git a/tests/threads/basic.c b/tests/threads/basic.c new file mode 100644 index 000000000..a329ee7f9 --- /dev/null +++ b/tests/threads/basic.c @@ -0,0 +1,36 @@ +#include "clar_libgit2.h" + +#include "cache.h" + + +static git_repository *g_repo; + +void test_threads_basic__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_threads_basic__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + + +void test_threads_basic__cache(void) +{ + // run several threads polling the cache at the same time + cl_assert(1 == 1); +} + +void test_threads_basic__multiple_init(void) +{ + git_repository *nested_repo; + + git_threads_init(); + cl_git_pass(git_repository_open(&nested_repo, cl_fixture("testrepo.git"))); + git_repository_free(nested_repo); + + git_threads_shutdown(); + cl_git_pass(git_repository_open(&nested_repo, cl_fixture("testrepo.git"))); + git_repository_free(nested_repo); +} diff --git a/tests/threads/refdb.c b/tests/threads/refdb.c new file mode 100644 index 000000000..3c651e341 --- /dev/null +++ b/tests/threads/refdb.c @@ -0,0 +1,213 @@ +#include "clar_libgit2.h" +#include "git2/refdb.h" +#include "refdb.h" + +static git_repository *g_repo; +static int g_expected = 0; + +void test_threads_refdb__initialize(void) +{ + g_repo = NULL; +} + +void test_threads_refdb__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; +} + +#define REPEAT 20 +#define THREADS 20 + +static void *iterate_refs(void *arg) +{ + git_reference_iterator *i; + git_reference *ref; + int count = 0; + + cl_git_pass(git_reference_iterator_new(&i, g_repo)); + + for (count = 0; !git_reference_next(&ref, i); ++count) { + cl_assert(ref != NULL); + git_reference_free(ref); + } + + if (g_expected > 0) + cl_assert_equal_i(g_expected, count); + + git_reference_iterator_free(i); + + return arg; +} + +void test_threads_refdb__iterator(void) +{ + int r, t; + git_thread th[THREADS]; + int id[THREADS]; + git_oid head; + git_reference *ref; + char name[128]; + git_refdb *refdb; + + g_repo = cl_git_sandbox_init("testrepo2"); + + cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); + + /* make a bunch of references */ + + for (r = 0; r < 200; ++r) { + snprintf(name, sizeof(name), "refs/heads/direct-%03d", r); + cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0)); + git_reference_free(ref); + } + + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + git_refdb_free(refdb); + + g_expected = 206; + + for (r = 0; r < REPEAT; ++r) { + g_repo = cl_git_sandbox_reopen(); /* reopen to flush caches */ + + for (t = 0; t < THREADS; ++t) { + id[t] = t; +#ifdef GIT_THREADS + cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t])); +#else + th[t] = t; + iterate_refs(&id[t]); +#endif + } + +#ifdef GIT_THREADS + for (t = 0; t < THREADS; ++t) { + cl_git_pass(git_thread_join(th[t], NULL)); + } +#endif + + memset(th, 0, sizeof(th)); + } +} + +static void *create_refs(void *arg) +{ + int *id = arg, i; + git_oid head; + char name[128]; + git_reference *ref[10]; + + cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); + + for (i = 0; i < 10; ++i) { + snprintf(name, sizeof(name), "refs/heads/thread-%03d-%02d", *id, i); + cl_git_pass(git_reference_create(&ref[i], g_repo, name, &head, 0)); + + if (i == 5) { + git_refdb *refdb; + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + git_refdb_free(refdb); + } + } + + for (i = 0; i < 10; ++i) + git_reference_free(ref[i]); + + return arg; +} + +static void *delete_refs(void *arg) +{ + int *id = arg, i; + git_reference *ref; + char name[128]; + + for (i = 0; i < 10; ++i) { + snprintf( + name, sizeof(name), "refs/heads/thread-%03d-%02d", (*id) & ~0x3, i); + + if (!git_reference_lookup(&ref, g_repo, name)) { + cl_git_pass(git_reference_delete(ref)); + git_reference_free(ref); + } + + if (i == 5) { + git_refdb *refdb; + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + git_refdb_free(refdb); + } + } + + return arg; +} + +void test_threads_refdb__edit_while_iterate(void) +{ + int r, t; + int id[THREADS]; + git_oid head; + git_reference *ref; + char name[128]; + git_refdb *refdb; + +#ifdef GIT_THREADS + git_thread th[THREADS]; +#endif + + g_repo = cl_git_sandbox_init("testrepo2"); + + cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); + + /* make a bunch of references */ + + for (r = 0; r < 50; ++r) { + snprintf(name, sizeof(name), "refs/heads/starter-%03d", r); + cl_git_pass(git_reference_create(&ref, g_repo, name, &head, 0)); + git_reference_free(ref); + } + + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + git_refdb_free(refdb); + + g_expected = -1; + + g_repo = cl_git_sandbox_reopen(); /* reopen to flush caches */ + + for (t = 0; t < THREADS; ++t) { + void *(*fn)(void *arg); + + switch (t & 0x3) { + case 0: fn = create_refs; break; + case 1: fn = delete_refs; break; + default: fn = iterate_refs; break; + } + + id[t] = t; +#ifdef GIT_THREADS + cl_git_pass(git_thread_create(&th[t], NULL, fn, &id[t])); +#else + fn(&id[t]); +#endif + } + +#ifdef GIT_THREADS + for (t = 0; t < THREADS; ++t) { + cl_git_pass(git_thread_join(th[t], NULL)); + } + + memset(th, 0, sizeof(th)); + + for (t = 0; t < THREADS; ++t) { + id[t] = t; + cl_git_pass(git_thread_create(&th[t], NULL, iterate_refs, &id[t])); + } + + for (t = 0; t < THREADS; ++t) { + cl_git_pass(git_thread_join(th[t], NULL)); + } +#endif +} diff --git a/tests/trace/trace.c b/tests/trace/trace.c new file mode 100644 index 000000000..87b325378 --- /dev/null +++ b/tests/trace/trace.c @@ -0,0 +1,87 @@ +#include "clar_libgit2.h" +#include "trace.h" + +static int written = 0; + +static void trace_callback(git_trace_level_t level, const char *message) +{ + GIT_UNUSED(level); + + cl_assert(strcmp(message, "Hello world!") == 0); + + written = 1; +} + +void test_trace_trace__initialize(void) +{ + git_trace_set(GIT_TRACE_INFO, trace_callback); + written = 0; +} + +void test_trace_trace__cleanup(void) +{ + git_trace_set(GIT_TRACE_NONE, NULL); +} + +void test_trace_trace__sets(void) +{ +#ifdef GIT_TRACE + cl_assert(git_trace_level() == GIT_TRACE_INFO); +#endif +} + +void test_trace_trace__can_reset(void) +{ +#ifdef GIT_TRACE + cl_assert(git_trace_level() == GIT_TRACE_INFO); + cl_git_pass(git_trace_set(GIT_TRACE_ERROR, trace_callback)); + + cl_assert(written == 0); + git_trace(GIT_TRACE_INFO, "Hello %s!", "world"); + cl_assert(written == 0); + + git_trace(GIT_TRACE_ERROR, "Hello %s!", "world"); + cl_assert(written == 1); +#endif +} + +void test_trace_trace__can_unset(void) +{ +#ifdef GIT_TRACE + cl_assert(git_trace_level() == GIT_TRACE_INFO); + cl_git_pass(git_trace_set(GIT_TRACE_NONE, NULL)); + + cl_assert(git_trace_level() == GIT_TRACE_NONE); + + cl_assert(written == 0); + git_trace(GIT_TRACE_FATAL, "Hello %s!", "world"); + cl_assert(written == 0); +#endif +} + +void test_trace_trace__skips_higher_level(void) +{ +#ifdef GIT_TRACE + cl_assert(written == 0); + git_trace(GIT_TRACE_DEBUG, "Hello %s!", "world"); + cl_assert(written == 0); +#endif +} + +void test_trace_trace__writes(void) +{ +#ifdef GIT_TRACE + cl_assert(written == 0); + git_trace(GIT_TRACE_INFO, "Hello %s!", "world"); + cl_assert(written == 1); +#endif +} + +void test_trace_trace__writes_lower_level(void) +{ +#ifdef GIT_TRACE + cl_assert(written == 0); + git_trace(GIT_TRACE_ERROR, "Hello %s!", "world"); + cl_assert(written == 1); +#endif +} diff --git a/tests/valgrind-supp-mac.txt b/tests/valgrind-supp-mac.txt new file mode 100644 index 000000000..99833d091 --- /dev/null +++ b/tests/valgrind-supp-mac.txt @@ -0,0 +1,184 @@ +{ + libgit2-giterr-set-buffer + Memcheck:Leak + ... + fun:git__realloc + fun:git_buf_try_grow + fun:git_buf_grow + fun:git_buf_vprintf + fun:giterr_set +} +{ + mac-setenv-leak-1 + Memcheck:Leak + fun:malloc_zone_malloc + fun:__setenv + fun:setenv +} +{ + mac-setenv-leak-2 + Memcheck:Leak + fun:malloc_zone_malloc + fun:malloc_set_zone_name + ... + fun:init__zone0 + fun:setenv +} +{ + mac-dyld-initializer-leak + Memcheck:Leak + fun:malloc + ... + fun:dyld_register_image_state_change_handler + fun:_dyld_initializer +} +{ + mac-tz-leak-1 + Memcheck:Leak + ... + fun:token_table_add + fun:notify_register_check + fun:notify_register_tz +} +{ + mac-tz-leak-2 + Memcheck:Leak + fun:malloc + fun:tzload +} +{ + mac-tz-leak-3 + Memcheck:Leak + fun:malloc + fun:tzsetwall_basic +} +{ + mac-tz-leak-4 + Memcheck:Leak + fun:malloc + fun:gmtsub +} +{ + mac-system-init-leak-1 + Memcheck:Leak + ... + fun:_libxpc_initializer + fun:libSystem_initializer +} +{ + mac-system-init-leak-2 + Memcheck:Leak + ... + fun:__keymgr_initializer + fun:libSystem_initializer +} +{ + mac-puts-leak + Memcheck:Leak + fun:malloc + fun:__smakebuf + ... + fun:puts +} +{ + mac-ssl-uninitialized-1 + Memcheck:Cond + obj:/usr/lib/libcrypto.0.9.8.dylib + ... + fun:ssl23_connect +} +{ + mac-ssl-uninitialized-2 + Memcheck:Cond + ... + obj:/usr/lib/libssl.0.9.8.dylib + ... + fun:ssl23_connect +} +{ + mac-ssl-uninitialized-3 + Memcheck:Value8 + obj:/usr/lib/libcrypto.0.9.8.dylib + ... + fun:ssl23_connect +} +{ + mac-ssl-uninitialized-4 + Memcheck:Param + ... + obj:/usr/lib/libcrypto.0.9.8.dylib + ... + fun:ssl23_connect +} +{ + mac-ssl-leak-1 + Memcheck:Leak + ... + fun:ERR_load_strings +} +{ + mac-ssl-leak-2 + Memcheck:Leak + ... + fun:SSL_library_init +} +{ + mac-ssl-leak-3 + Memcheck:Leak + ... + fun:si_module_with_name + fun:getaddrinfo +} +{ + mac-ssl-leak-4 + Memcheck:Leak + fun:malloc + fun:CRYPTO_malloc + ... + fun:ssl3_get_server_certificate +} +{ + mac-ssl-leak-5 + Memcheck:Leak + fun:malloc + fun:CRYPTO_malloc + ... + fun:ERR_put_error +} +{ + clar-printf-buf + Memcheck:Leak + fun:malloc + fun:__smakebuf + ... + fun:printf + fun:clar_print_init +} +{ + molo-1 + Memcheck:Leak + fun:malloc_zone_malloc + ... + fun:_objc_init +} +{ + molo-2 + Memcheck:Leak + fun:malloc_zone_calloc + ... + fun:_objc_init +} +{ + molo-3 + Memcheck:Leak + fun:malloc + ... + fun:_objc_init +} +{ + molo-4 + Memcheck:Leak + fun:malloc + ... + fun:dyld_register_image_state_change_handler +} -- cgit v1.2.1 From 83e1efbf462347dac3e1c884bb0b017d495b6f38 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 14 Nov 2013 14:10:32 -0800 Subject: Update files that reference tests-clar --- .gitignore | 6 +++--- CMakeLists.txt | 8 ++++---- examples/general.c | 2 +- examples/test/test-rev-list.sh | 2 +- include/git2/pack.h | 2 +- tests/odb/foreach.c | 2 +- tests/pack/packbuilder.c | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index bba9d5d5c..d4e0454fa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ -/tests-clar/clar.suite -/tests-clar/clar.suite.rule -/tests-clar/.clarcache +/tests/clar.suite +/tests/clar.suite.rule +/tests/.clarcache /apidocs /trash-*.exe /libgit2.pc diff --git a/CMakeLists.txt b/CMakeLists.txt index 271af690c..ac1032acf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,7 +97,7 @@ ENDFUNCTION() # explorer does. This is esp. useful with the libgit2_clar project, were # usually 2 or more files share the same name. Sadly, this file grouping # is a per-directory option in cmake and not per-target, resulting in -# empty virtual folders "tests-clar" for the git2.dll +# empty virtual folders "tests" for the git2.dll FUNCTION(MSVC_SPLIT_SOURCES target) IF(MSVC_IDE) GET_TARGET_PROPERTY(sources ${target} SOURCES) @@ -393,9 +393,9 @@ INSTALL(FILES include/git2.h DESTINATION ${INCLUDE_INSTALL_DIR} ) IF (BUILD_CLAR) FIND_PACKAGE(PythonInterp REQUIRED) - SET(CLAR_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/tests-clar/resources/") - SET(CLAR_PATH "${CMAKE_CURRENT_SOURCE_DIR}/tests-clar") - SET(CLAR_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tests-clar/resources" CACHE PATH "Path to test resources.") + SET(CLAR_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/tests/resources/") + SET(CLAR_PATH "${CMAKE_CURRENT_SOURCE_DIR}/tests") + SET(CLAR_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tests/resources" CACHE PATH "Path to test resources.") ADD_DEFINITIONS(-DCLAR_FIXTURE_PATH=\"${CLAR_FIXTURES}\") ADD_DEFINITIONS(-DCLAR_RESOURCES=\"${TEST_RESOURCES}\") diff --git a/examples/general.c b/examples/general.c index f23dccb47..58e141b35 100644 --- a/examples/general.c +++ b/examples/general.c @@ -66,7 +66,7 @@ int main (int argc, char** argv) // simplest. There are also [methods][me] for specifying the index file // and work tree locations, here we assume they are in the normal places. // - // (Try running this program against tests-clar/resources/testrepo.git.) + // (Try running this program against tests/resources/testrepo.git.) // // [me]: http://libgit2.github.com/libgit2/#HEAD/group/repository int error; diff --git a/examples/test/test-rev-list.sh b/examples/test/test-rev-list.sh index bc0eea7cf..aa645be5e 100755 --- a/examples/test/test-rev-list.sh +++ b/examples/test/test-rev-list.sh @@ -4,7 +4,7 @@ THIS_FILE="$(readlink -f "$0")" ROOT="$(dirname "$(dirname "$(dirname "$THIS_FILE")")")" PROGRAM="$ROOT"/examples/rev-list LIBDIR="$ROOT"/build -REPO="$ROOT"/tests-clar/resources/testrepo.git +REPO="$ROOT"/tests/resources/testrepo.git cd "$REPO" diff --git a/include/git2/pack.h b/include/git2/pack.h index 52e7adad2..88a2716bb 100644 --- a/include/git2/pack.h +++ b/include/git2/pack.h @@ -38,7 +38,7 @@ * `git_packbuilder_set_threads` can be used to adjust the number of * threads used for the process. * - * See tests-clar/pack/packbuilder.c for an example. + * See tests/pack/packbuilder.c for an example. * * @ingroup Git * @{ diff --git a/tests/odb/foreach.c b/tests/odb/foreach.c index f643d9621..ebb8866f7 100644 --- a/tests/odb/foreach.c +++ b/tests/odb/foreach.c @@ -27,7 +27,7 @@ static int foreach_cb(const git_oid *oid, void *data) } /* - * $ git --git-dir tests-clar/resources/testrepo.git count-objects --verbose + * $ git --git-dir tests/resources/testrepo.git count-objects --verbose * count: 47 * size: 4 * in-pack: 1640 diff --git a/tests/pack/packbuilder.c b/tests/pack/packbuilder.c index 54d1e8022..1ae2322a5 100644 --- a/tests/pack/packbuilder.c +++ b/tests/pack/packbuilder.c @@ -106,7 +106,7 @@ void test_pack_packbuilder__create_pack(void) * we create exactly the same pack as git.git does when *not* * reusing existing deltas (as libgit2). * - * $ cd tests-clar/resources/testrepo.git + * $ cd tests/resources/testrepo.git * $ git rev-list --objects HEAD | \ * git pack-objects -q --no-reuse-delta --threads=1 pack * $ sha1sum git-80e61eb315239ef3c53033e37fee43b744d57122.pack -- cgit v1.2.1 From a0f13ffaeecc6d6958e9321473e621db3b6d57eb Mon Sep 17 00:00:00 2001 From: nulltoken Date: Fri, 15 Nov 2013 14:32:52 +0000 Subject: Add missing mappings to .mailmap file --- .mailmap | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.mailmap b/.mailmap index 3f5a087ea..c656f64c7 100644 --- a/.mailmap +++ b/.mailmap @@ -16,3 +16,6 @@ Xavier L. Sascha Cunz Authmillenon Authmillenon +Edward Thomson +J. David Ibáñez +Russell Belfer -- cgit v1.2.1 From 80fc7d6bf08834acc5696c8f0c73680236f84375 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 13 Nov 2013 16:46:45 -0500 Subject: Propagate auth error codes as GIT_EUSER in winhttp --- src/remote.c | 71 +++++++++++++++++++++++++---------------- src/transports/smart_protocol.c | 18 ++++++----- src/transports/winhttp.c | 4 +-- tests/online/clone.c | 33 +++++++++++++++++++ 4 files changed, 89 insertions(+), 37 deletions(-) diff --git a/src/remote.c b/src/remote.c index c0f35e5ea..d072eb9d5 100644 --- a/src/remote.c +++ b/src/remote.c @@ -82,29 +82,35 @@ static int ensure_remote_name_is_valid(const char *name) return error; } -static int get_check_cert(git_repository *repo) +static int get_check_cert(int *out, git_repository *repo) { git_config *cfg; const char *val; - int check_cert; + int error = 0; + + assert(out && repo); - assert(repo); + /* By default, we *DO* want to verify the certificate. */ + *out = 1; /* Go through the possible sources for SSL verification settings, from * most specific to least specific. */ /* GIT_SSL_NO_VERIFY environment variable */ - if ((val = getenv("GIT_SSL_NO_VERIFY")) && - !git_config_parse_bool(&check_cert, val)) - return !check_cert; + if (val = getenv("GIT_SSL_NO_VERIFY")) + return git_config_parse_bool(out, val); /* http.sslVerify config setting */ - if (!git_repository_config__weakptr(&cfg, repo) && - !git_config_get_bool(&check_cert, cfg, "http.sslVerify")) - return check_cert; + if ((error = git_repository_config__weakptr(&cfg, repo)) < 0) + return error; - /* By default, we *DO* want to verify the certificate. */ - return 1; + if ((error = git_config_get_bool(out, cfg, "http.sslVerify")) == 0) + return 0; + else if (error != GIT_ENOTFOUND) + return error; + + giterr_clear(); + return 0; } static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch) @@ -120,9 +126,11 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n GITERR_CHECK_ALLOC(remote); remote->repo = repo; - remote->check_cert = (unsigned)get_check_cert(repo); remote->update_fetchhead = 1; + if (get_check_cert(&remote->check_cert, repo) < 0) + goto on_error; + if (git_vector_init(&remote->refs, 32, NULL) < 0) goto on_error; @@ -314,11 +322,13 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name) GITERR_CHECK_ALLOC(remote); memset(remote, 0x0, sizeof(git_remote)); - remote->check_cert = (unsigned)get_check_cert(repo); remote->update_fetchhead = 1; remote->name = git__strdup(name); GITERR_CHECK_ALLOC(remote->name); + if ((error = get_check_cert(&remote->check_cert, repo)) < 0) + goto cleanup; + if ((git_vector_init(&remote->refs, 32, NULL) < 0) || (git_vector_init(&remote->refspecs, 2, NULL) < 0) || (git_vector_init(&remote->active_refspecs, 2, NULL) < 0)) { @@ -610,13 +620,14 @@ int git_remote_connect(git_remote *remote, git_direction direction) git_transport *t; const char *url; int flags = GIT_TRANSPORTFLAGS_NONE; + int error; assert(remote); t = remote->transport; url = git_remote__urlfordirection(remote, direction); - if (url == NULL ) { + if (url == NULL) { giterr_set(GITERR_INVALID, "Malformed remote '%s' - missing URL", remote->name); return -1; @@ -624,17 +635,17 @@ int git_remote_connect(git_remote *remote, git_direction direction) /* A transport could have been supplied in advance with * git_remote_set_transport */ - if (!t && git_transport_new(&t, remote, url) < 0) - return -1; + if (!t && (error = git_transport_new(&t, remote, url)) < 0) + return error; if (t->set_callbacks && - t->set_callbacks(t, remote->callbacks.progress, NULL, remote->callbacks.payload) < 0) + (error = t->set_callbacks(t, remote->callbacks.progress, NULL, remote->callbacks.payload)) < 0) goto on_error; if (!remote->check_cert) flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT; - if (t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags) < 0) + if ((error = t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags)) < 0) goto on_error; remote->transport = t; @@ -647,7 +658,7 @@ on_error: if (t == remote->transport) remote->transport = NULL; - return -1; + return error; } int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote) @@ -661,6 +672,7 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur { git_config *cfg; const char *val; + int error; assert(remote); @@ -669,8 +681,8 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur *proxy_url = NULL; - if (git_repository_config__weakptr(&cfg, remote->repo) < 0) - return -1; + if ((error = git_repository_config__weakptr(&cfg, remote->repo)) < 0) + return error; /* Go through the possible sources for proxy configuration, from most specific * to least specific. */ @@ -679,28 +691,33 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur if (remote->name && 0 != *(remote->name)) { git_buf buf = GIT_BUF_INIT; - if (git_buf_printf(&buf, "remote.%s.proxy", remote->name) < 0) - return -1; + if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0) + return error; - if (!git_config_get_string(&val, cfg, git_buf_cstr(&buf)) && + if ((error = git_config_get_string(&val, cfg, git_buf_cstr(&buf))) == 0 && val && ('\0' != *val)) { git_buf_free(&buf); *proxy_url = git__strdup(val); GITERR_CHECK_ALLOC(*proxy_url); return 0; - } + } else if (error != GIT_ENOTFOUND) + return error; + giterr_clear(); git_buf_free(&buf); } /* http.proxy config setting */ - if (!git_config_get_string(&val, cfg, "http.proxy") && + if ((error = git_config_get_string(&val, cfg, "http.proxy")) == 0 && val && ('\0' != *val)) { *proxy_url = git__strdup(val); GITERR_CHECK_ALLOC(*proxy_url); return 0; - } + } else if (error != GIT_ENOTFOUND) + return error; + + giterr_clear(); /* HTTP_PROXY / HTTPS_PROXY environment variables */ val = use_ssl ? getenv("HTTPS_PROXY") : getenv("HTTP_PROXY"); diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 7288a4820..3bf1f9329 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -49,7 +49,7 @@ int git_smart__store_refs(transport_smart *t, int flushes) if (error == GIT_EBUFS) { if ((recvd = gitno_recv(buf)) < 0) - return -1; + return recvd; if (recvd == 0 && !flush) { giterr_set(GITERR_NET, "Early EOF"); @@ -164,10 +164,10 @@ static int recv_pkt(git_pkt **out, gitno_buffer *buf) break; /* return the pkt */ if (error < 0 && error != GIT_EBUFS) - return -1; + return error; if ((ret = gitno_recv(buf)) < 0) - return -1; + return ret; } while (error); gitno_consume(buf, line_end); @@ -184,10 +184,11 @@ static int store_common(transport_smart *t) { git_pkt *pkt = NULL; gitno_buffer *buf = &t->buffer; + int error; do { - if (recv_pkt(&pkt, buf) < 0) - return -1; + if ((error = recv_pkt(&pkt, buf)) < 0) + return error; if (pkt->type == GIT_PKT_ACK) { if (git_vector_insert(&t->common, pkt) < 0) @@ -227,6 +228,7 @@ static int fetch_setup_walk(git_revwalk **out, git_repository *repo) if (git_reference_type(ref) == GIT_REF_SYMBOLIC) continue; + if (git_revwalk_push(walk, git_reference_target(ref)) < 0) goto on_error; @@ -436,10 +438,10 @@ static int no_sideband(transport_smart *t, struct git_odb_writepack *writepack, gitno_consume_n(buf, buf->offset); if ((recvd = gitno_recv(buf)) < 0) - return -1; + return recvd; } while(recvd > 0); - if (writepack->commit(writepack, stats)) + if (writepack->commit(writepack, stats) < 0) return -1; return 0; @@ -697,7 +699,7 @@ static int parse_report(gitno_buffer *buf, git_push *push) if (error == GIT_EBUFS) { if ((recvd = gitno_recv(buf)) < 0) - return -1; + return recvd; if (recvd == 0) { giterr_set(GITERR_NET, "Early EOF"); diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index a25fa301e..f7566458e 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -640,8 +640,8 @@ replay: (!t->cred || 0 == (t->cred->credtype & allowed_types))) { if (t->owner->cred_acquire_cb(&t->cred, t->owner->url, t->connection_data.user, allowed_types, - t->owner->cred_acquire_payload) < 0) - return -1; + t->owner->cred_acquire_payload) < 0) + return GIT_EUSER; assert(t->cred); diff --git a/tests/online/clone.c b/tests/online/clone.c index aa3d6b26a..d036a5a47 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -183,6 +183,39 @@ void test_online_clone__custom_remote_callbacks(void) cl_assert(callcount > 0); } +static int cred_failure_cb( + git_cred **cred, + const char *url, + const char *username_from_url, + unsigned int allowed_types, + void *data) +{ + return -1; +} + +void test_online_clone__cred_callback_failure_is_euser(void) +{ + const char *remote_url = cl_getenv("GITTEST_REMOTE_URL"); + const char *remote_user = cl_getenv("GITTEST_REMOTE_USER"); + const char *remote_default = cl_getenv("GITTEST_REMOTE_DEFAULT"); + int error; + + if (!remote_url) { + printf("GITTEST_REMOTE_URL unset; skipping clone test\n"); + return; + } + + if (!remote_user && !remote_default) { + printf("GITTEST_REMOTE_USER and GITTEST_REMOTE_DEFAULT unset; skipping clone test\n"); + return; + } + + g_options.remote_callbacks.credentials = cred_failure_cb; + + cl_git_fail(error = git_clone(&g_repo, remote_url, "./foo", &g_options)); + cl_assert_equal_i(error, GIT_EUSER); +} + void test_online_clone__credentials(void) { /* Remote URL environment variable must be set. User and password are optional. */ -- cgit v1.2.1 From 84efffc33ab352d68cf981da0d6c8d358244cabc Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 13 Nov 2013 16:57:51 -0500 Subject: Introduce git_cred_default for NTLM/SPNEGO auth --- include/git2/transport.h | 20 +++++++++++++++++--- src/transports/cred.c | 27 +++++++++++++++++++++++++++ src/transports/winhttp.c | 28 ++++++++++++++++++++++++++++ tests/online/push.c | 16 +++++++++++++++- 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/include/git2/transport.h b/include/git2/transport.h index 81ebf4dc9..fe4883f99 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -31,13 +31,16 @@ GIT_BEGIN_DECL /** Authentication type requested */ typedef enum { /* git_cred_userpass_plaintext */ - GIT_CREDTYPE_USERPASS_PLAINTEXT = (1u << 0), + GIT_CREDTYPE_USERPASS_PLAINTEXT = (1u << 0), /* git_cred_ssh_key */ GIT_CREDTYPE_SSH_KEY = (1u << 1), /* git_cred_ssh_custom */ - GIT_CREDTYPE_SSH_CUSTOM = (1u << 2), + GIT_CREDTYPE_SSH_CUSTOM = (1u << 2), + + /* git_cred_default */ + GIT_CREDTYPE_DEFAULT = (1u << 3), } git_credtype_t; /* The base structure for all credential types */ @@ -48,7 +51,7 @@ struct git_cred { void (*free)(git_cred *cred); }; -/* A plaintext username and password */ +/** A plaintext username and password */ typedef struct { git_cred parent; char *username; @@ -84,6 +87,9 @@ typedef struct git_cred_ssh_custom { void *sign_data; } git_cred_ssh_custom; +/** A key for NTLM/Kerberos "default" credentials */ +typedef struct git_cred git_cred_default; + /** * Check whether a credential object contains username information. * @@ -150,6 +156,14 @@ GIT_EXTERN(int) git_cred_ssh_custom_new( git_cred_sign_callback sign_fn, void *sign_data); +/** + * Create a "default" credential usable for Negotiate mechanisms like NTLM + * or Kerberos authentication. + * + * @return 0 for success or an error code for failure + */ +GIT_EXTERN(int) git_cred_default_new(git_cred **out); + /** * Signature of a function which acquires a credential object. * diff --git a/src/transports/cred.c b/src/transports/cred.c index cc7fdab4b..05d2c8dc6 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -29,6 +29,10 @@ int git_cred_has_username(git_cred *cred) ret = !!c->username; break; } + case GIT_CREDTYPE_DEFAULT: { + ret = 0; + break; + } } return ret; @@ -115,6 +119,13 @@ static void ssh_custom_free(struct git_cred *cred) git__free(c); } +static void default_free(struct git_cred *cred) +{ + git_cred_default *c = (git_cred_default *)cred; + + git__free(c); +} + int git_cred_ssh_key_new( git_cred **cred, const char *username, @@ -191,3 +202,19 @@ int git_cred_ssh_custom_new( *cred = &c->parent; return 0; } + +int git_cred_default_new(git_cred **cred) +{ + git_cred_default *c; + + assert(cred); + + c = git__calloc(1, sizeof(git_cred_default)); + GITERR_CHECK_ALLOC(c); + + c->credtype = GIT_CREDTYPE_DEFAULT; + c->free = default_free; + + *cred = c; + return 0; +} diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index f7566458e..673cd0faf 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -52,6 +52,7 @@ static const int no_check_cert_flags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | typedef enum { GIT_WINHTTP_AUTH_BASIC = 1, + GIT_WINHTTP_AUTH_NEGOTIATE = 2, } winhttp_authmechanism_t; typedef struct { @@ -138,6 +139,22 @@ on_error: return error; } +static int apply_default_credentials(HINTERNET request) +{ + /* If we are explicitly asked to deliver default credentials, turn set + * the security level to low which will guarantee they are delivered. + * The default is "medium" which applies to the intranet and sounds + * like it would correspond to Internet Explorer security zones, but + * in fact does not. + */ + DWORD data = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW; + + if (!WinHttpSetOption(request, WINHTTP_OPTION_AUTOLOGON_POLICY, &data, sizeof(DWORD))) + return -1; + + return 0; +} + static int winhttp_stream_connect(winhttp_stream *s) { winhttp_subtransport *t = OWNING_SUBTRANSPORT(s); @@ -317,6 +334,11 @@ static int winhttp_stream_connect(winhttp_stream *s) t->auth_mechanism == GIT_WINHTTP_AUTH_BASIC && apply_basic_credential(s->request, 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) + goto on_error; /* If no other credentials have been applied and the URL has username and * password, use those */ @@ -361,6 +383,12 @@ static int parse_unauthorized_response( *auth_mechanism = GIT_WINHTTP_AUTH_BASIC; } + if ((WINHTTP_AUTH_SCHEME_NTLM & supported) || + (WINHTTP_AUTH_SCHEME_NEGOTIATE & supported)) { + *allowed_types |= GIT_CREDTYPE_DEFAULT; + *auth_mechanism = GIT_WINHTTP_AUTH_NEGOTIATE; + } + return 0; } diff --git a/tests/online/push.c b/tests/online/push.c index aeb1ab47d..be505c3a1 100644 --- a/tests/online/push.c +++ b/tests/online/push.c @@ -9,14 +9,17 @@ static git_repository *_repo; +static char *_remote_url; + static char *_remote_ssh_key; static char *_remote_ssh_pubkey; static char *_remote_ssh_passphrase; -static char *_remote_url; static char *_remote_user; static char *_remote_pass; +static char *_remote_default; + static int cred_acquire_cb(git_cred **, const char *, const char *, unsigned int, void *); static git_remote *_remote; @@ -47,11 +50,21 @@ static int cred_acquire_cb( GIT_UNUSED(user_from_url); GIT_UNUSED(payload); + if (GIT_CREDTYPE_DEFAULT & allowed_types) { + if (!_remote_default) { + printf("GITTEST_REMOTE_DEFAULT must be set to use NTLM/Negotiate credentials\n"); + return -1; + } + + return git_cred_default_new(cred); + } + if (GIT_CREDTYPE_SSH_KEY & allowed_types) { if (!_remote_user || !_remote_ssh_pubkey || !_remote_ssh_key || !_remote_ssh_passphrase) { printf("GITTEST_REMOTE_USER, GITTEST_REMOTE_SSH_PUBKEY, GITTEST_REMOTE_SSH_KEY and GITTEST_REMOTE_SSH_PASSPHRASE must be set\n"); return -1; } + return git_cred_ssh_key_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase); } @@ -298,6 +311,7 @@ void test_online_push__initialize(void) _remote_ssh_key = cl_getenv("GITTEST_REMOTE_SSH_KEY"); _remote_ssh_pubkey = cl_getenv("GITTEST_REMOTE_SSH_PUBKEY"); _remote_ssh_passphrase = cl_getenv("GITTEST_REMOTE_SSH_PASSPHRASE"); + _remote_default = cl_getenv("GITTEST_REMOTE_DEFAULT"); _remote = NULL; if (_remote_url) { -- cgit v1.2.1 From 8f2a3d6251291c0468e074563e16d4c41f59acb1 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 18 Nov 2013 12:14:50 -0800 Subject: Fix warnings --- src/remote.c | 6 +++--- src/remote.h | 4 ++-- tests/online/clone.c | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/remote.c b/src/remote.c index d072eb9d5..a032f00ad 100644 --- a/src/remote.c +++ b/src/remote.c @@ -97,7 +97,7 @@ static int get_check_cert(int *out, git_repository *repo) * most specific to least specific. */ /* GIT_SSL_NO_VERIFY environment variable */ - if (val = getenv("GIT_SSL_NO_VERIFY")) + if ((val = getenv("GIT_SSL_NO_VERIFY")) != NULL) return git_config_parse_bool(out, val); /* http.sslVerify config setting */ @@ -1494,12 +1494,12 @@ int git_remote_rename( int git_remote_update_fetchhead(git_remote *remote) { - return remote->update_fetchhead; + return (remote->update_fetchhead != 0); } void git_remote_set_update_fetchhead(git_remote *remote, int value) { - remote->update_fetchhead = value; + remote->update_fetchhead = (value != 0); } int git_remote_is_valid_name( diff --git a/src/remote.h b/src/remote.h index 33e4d68f8..4164a14b3 100644 --- a/src/remote.h +++ b/src/remote.h @@ -28,8 +28,8 @@ struct git_remote { git_transfer_progress stats; unsigned int need_pack; git_remote_autotag_option_t download_tags; - unsigned int check_cert; - unsigned int update_fetchhead; + int check_cert; + int update_fetchhead; }; const char* git_remote__urlfordirection(struct git_remote *remote, int direction); diff --git a/tests/online/clone.c b/tests/online/clone.c index d036a5a47..efc76d958 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -190,6 +190,8 @@ static int cred_failure_cb( unsigned int allowed_types, void *data) { + GIT_UNUSED(cred); GIT_UNUSED(url); GIT_UNUSED(username_from_url); + GIT_UNUSED(allowed_types); GIT_UNUSED(data); return -1; } -- cgit v1.2.1 From e1ce5249e52e9c5271727d7e2ef5bba4c45277b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 18 Nov 2013 21:40:19 +0100 Subject: netops: fix leak --- src/netops.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/netops.c b/src/netops.c index 15ed0fc26..ad27d84cf 100644 --- a/src/netops.c +++ b/src/netops.c @@ -632,10 +632,13 @@ int gitno_connection_data_from_url( size_t suffixlen = service_suffix ? strlen(service_suffix) : 0; if (suffixlen && - !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen)) + !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen)) { + git__free(data->path); data->path = git__strndup(path, pathlen - suffixlen); - else + } else { + git__free(data->path); data->path = git__strdup(path); + } /* Check for errors in the resulting data */ if (original_host && url[0] != '/' && strcmp(original_host, data->host)) { -- cgit v1.2.1 From d8e7ffc2a246491aa139875e840fff34c832a739 Mon Sep 17 00:00:00 2001 From: Nick Hengeveld Date: Mon, 18 Nov 2013 14:03:25 -0800 Subject: Add content offset to git_diff_line For additions and deletions, external consumers like subversion can make use of the content offset to generate diffs in their proprietary formats. --- include/git2/diff.h | 1 + src/diff_xdiff.c | 17 +++++++++++++---- tests/diff/patch.c | 6 ++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/git2/diff.h b/include/git2/diff.h index a16f86a46..61d288380 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -446,6 +446,7 @@ struct git_diff_line { int new_lineno; /** Line number in new file or -1 for deleted line */ int num_lines; /** Number of newline characters in content */ size_t content_len; /** Number of bytes of data */ + git_off_t content_offset; /** Offset in the original file to the content */ const char *content; /** Pointer to diff text, not NUL-byte terminated */ }; diff --git a/src/diff_xdiff.c b/src/diff_xdiff.c index 2aca76f87..e0bc11f7f 100644 --- a/src/diff_xdiff.c +++ b/src/diff_xdiff.c @@ -54,6 +54,7 @@ typedef struct { git_patch *patch; git_diff_hunk hunk; int old_lineno, new_lineno; + mmfile_t xd_old_data, xd_new_data; } git_xdiff_info; static int diff_update_lines( @@ -135,6 +136,13 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) (*bufs[0].ptr == '-') ? GIT_DIFF_LINE_DELETION : GIT_DIFF_LINE_CONTEXT; + if (line.origin == GIT_DIFF_LINE_ADDITION) + line.content_offset = bufs[1].ptr - info->xd_new_data.ptr; + else if (line.origin == GIT_DIFF_LINE_DELETION) + line.content_offset = bufs[1].ptr - info->xd_old_data.ptr; + else + line.content_offset = -1; + output->error = diff_update_lines( info, &line, bufs[1].ptr, bufs[1].size); @@ -155,6 +163,8 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) (*bufs[0].ptr == '-') ? GIT_DIFF_LINE_ADD_EOFNL : GIT_DIFF_LINE_CONTEXT_EOFNL; + line.content_offset = -1; + output->error = diff_update_lines( info, &line, bufs[2].ptr, bufs[2].size); @@ -172,7 +182,6 @@ static int git_xdiff(git_diff_output *output, git_patch *patch) git_xdiff_output *xo = (git_xdiff_output *)output; git_xdiff_info info; git_diff_find_context_payload findctxt; - mmfile_t xd_old_data, xd_new_data; memset(&info, 0, sizeof(info)); info.patch = patch; @@ -193,10 +202,10 @@ static int git_xdiff(git_diff_output *output, git_patch *patch) * updates are needed to xo->params.flags */ - git_patch__old_data(&xd_old_data.ptr, &xd_old_data.size, patch); - git_patch__new_data(&xd_new_data.ptr, &xd_new_data.size, patch); + git_patch__old_data(&info.xd_old_data.ptr, &info.xd_old_data.size, patch); + git_patch__new_data(&info.xd_new_data.ptr, &info.xd_new_data.size, patch); - xdl_diff(&xd_old_data, &xd_new_data, + xdl_diff(&info.xd_old_data, &info.xd_new_data, &xo->params, &xo->config, &xo->callback); git_diff_find_context_clear(&findctxt); diff --git a/tests/diff/patch.c b/tests/diff/patch.c index 366e5da58..bd1598b21 100644 --- a/tests/diff/patch.c +++ b/tests/diff/patch.c @@ -275,6 +275,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_s("Ivory their outposts were--the guardrooms of them gilded,\n", actual.ptr); cl_assert_equal_i(6, line->old_lineno); cl_assert_equal_i(6, line->new_lineno); + cl_assert_equal_i(-1, line->content_offset); cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 3)); cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); @@ -282,6 +283,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_s("All the world went softly when it walked before my Cities--\n", actual.ptr); cl_assert_equal_i(9, line->old_lineno); cl_assert_equal_i(-1, line->new_lineno); + cl_assert_equal_i(252, line->content_offset); cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 12)); cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); @@ -289,6 +291,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_s("This is some new text;\n", actual.ptr); cl_assert_equal_i(-1, line->old_lineno); cl_assert_equal_i(9, line->new_lineno); + cl_assert_equal_i(252, line->content_offset); /* check hunk 1 */ @@ -309,6 +312,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_s("My rulers and their treasure and their unborn populations,\n", actual.ptr); cl_assert_equal_i(31, line->old_lineno); cl_assert_equal_i(25, line->new_lineno); + cl_assert_equal_i(-1, line->content_offset); cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 3)); cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); @@ -316,6 +320,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_s("The Daughters of the Palace whom they cherished in my Cities,\n", actual.ptr); cl_assert_equal_i(34, line->old_lineno); cl_assert_equal_i(-1, line->new_lineno); + cl_assert_equal_i(1468, line->content_offset); cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 12)); cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); @@ -323,6 +328,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) cl_assert_equal_s("Another replacement;\n", actual.ptr); cl_assert_equal_i(-1, line->old_lineno); cl_assert_equal_i(28, line->new_lineno); + cl_assert_equal_i(1066, line->content_offset); git_patch_free(patch); git_diff_free(diff); -- cgit v1.2.1 From 10b6678f9495b2b4b7f4885ea0bcd88c5e16a7fe Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 19 Nov 2013 11:57:32 +0100 Subject: cleaning code, removing unused variables --- src/remote.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/remote.c b/src/remote.c index c0f35e5ea..c3baf3243 100644 --- a/src/remote.c +++ b/src/remote.c @@ -211,7 +211,6 @@ on_error: int git_remote_create_with_fetchspec(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch) { - git_buf buf = GIT_BUF_INIT; git_remote *remote = NULL; int error; @@ -224,8 +223,6 @@ int git_remote_create_with_fetchspec(git_remote **out, git_repository *repo, con if (create_internal(&remote, repo, name, url, fetch) < 0) goto on_error; - git_buf_free(&buf); - if (git_remote_save(remote) < 0) goto on_error; @@ -234,7 +231,6 @@ int git_remote_create_with_fetchspec(git_remote **out, git_repository *repo, con return 0; on_error: - git_buf_free(&buf); git_remote_free(remote); return -1; } -- cgit v1.2.1 From 7b69289f4e9249f61fb48593ddbf66b6f9ad6494 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 19 Nov 2013 12:54:57 +0100 Subject: tree-cache: Free the tree upon the detection of a corrupted child --- src/tree-cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tree-cache.c b/src/tree-cache.c index 97ffc2acf..d1762821c 100644 --- a/src/tree-cache.c +++ b/src/tree-cache.c @@ -140,7 +140,7 @@ static int read_tree_internal(git_tree_cache **out, for (i = 0; i < tree->children_count; ++i) { if (read_tree_internal(&tree->children[i], &buffer, buffer_end, tree) < 0) - return -1; + goto corrupted; } } -- cgit v1.2.1 From 82e6a42c6c387a584df1b2efb4fa3bfdb8c290a2 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 19 Nov 2013 13:13:51 +0100 Subject: tree-cache: Zero out the allocated tree children array --- src/tree-cache.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tree-cache.c b/src/tree-cache.c index d1762821c..a693f4f30 100644 --- a/src/tree-cache.c +++ b/src/tree-cache.c @@ -138,6 +138,8 @@ static int read_tree_internal(git_tree_cache **out, tree->children = git__malloc(tree->children_count * sizeof(git_tree_cache *)); GITERR_CHECK_ALLOC(tree->children); + memset(tree->children, 0x0, tree->children_count * sizeof(git_tree_cache *)); + for (i = 0; i < tree->children_count; ++i) { if (read_tree_internal(&tree->children[i], &buffer, buffer_end, tree) < 0) goto corrupted; -- cgit v1.2.1 From 3d5233455b2483fe78c82cabf89b568d079d6742 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 19 Nov 2013 13:15:47 +0100 Subject: tree-cache: Don't segfault upon corruption --- src/tree-cache.c | 9 ++++++--- tests/index/tests.c | 9 +++++++++ tests/resources/bad.index | Bin 0 -> 412 bytes 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 tests/resources/bad.index diff --git a/src/tree-cache.c b/src/tree-cache.c index a693f4f30..57cc2946f 100644 --- a/src/tree-cache.c +++ b/src/tree-cache.c @@ -178,9 +178,12 @@ void git_tree_cache_free(git_tree_cache *tree) if (tree == NULL) return; - for (i = 0; i < tree->children_count; ++i) - git_tree_cache_free(tree->children[i]); + if (tree->children != NULL) { + for (i = 0; i < tree->children_count; ++i) + git_tree_cache_free(tree->children[i]); + + git__free(tree->children); + } - git__free(tree->children); git__free(tree); } diff --git a/tests/index/tests.c b/tests/index/tests.c index e5202980c..217e1bb55 100644 --- a/tests/index/tests.c +++ b/tests/index/tests.c @@ -6,6 +6,7 @@ static const size_t index_entry_count_2 = 1437; #define TEST_INDEX_PATH cl_fixture("testrepo.git/index") #define TEST_INDEX2_PATH cl_fixture("gitgit.index") #define TEST_INDEXBIG_PATH cl_fixture("big.index") +#define TEST_INDEXBAD_PATH cl_fixture("bad.index") /* Suite data */ @@ -535,3 +536,11 @@ void test_index_tests__reload_from_disk(void) git_index_free(write_index); git_repository_free(repo); } + +void test_index_tests__corrupted_extension(void) +{ + /* sort the entires in an empty index */ + git_index *index; + + cl_git_fail_with(git_index_open(&index, TEST_INDEXBAD_PATH), GIT_ERROR); +} diff --git a/tests/resources/bad.index b/tests/resources/bad.index new file mode 100644 index 000000000..53746549f Binary files /dev/null and b/tests/resources/bad.index differ -- cgit v1.2.1 From a5d73188023cf0ae0b6fc42dfeddce5a9ee8ad5f Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 19 Nov 2013 13:16:09 +0100 Subject: tree-cache: Fix error message typo --- src/tree-cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tree-cache.c b/src/tree-cache.c index 57cc2946f..1d3997154 100644 --- a/src/tree-cache.c +++ b/src/tree-cache.c @@ -152,7 +152,7 @@ static int read_tree_internal(git_tree_cache **out, corrupted: git_tree_cache_free(tree); - giterr_set(GITERR_INDEX, "Corruped TREE extension in index"); + giterr_set(GITERR_INDEX, "Corrupted TREE extension in index"); return -1; } @@ -164,7 +164,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, "Corruped TREE extension in index (unexpected trailing data)"); + giterr_set(GITERR_INDEX, "Corrupted TREE extension in index (unexpected trailing data)"); return -1; } -- cgit v1.2.1 From bd15b513058afc53543b48383ec5bc56605f6c1e Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 19 Nov 2013 13:24:10 +0100 Subject: index: Free the index on git_index_open() failure --- src/index.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/index.c b/src/index.c index ecab15024..09e7b2346 100644 --- a/src/index.c +++ b/src/index.c @@ -321,6 +321,7 @@ void git_index__set_ignore_case(git_index *index, bool ignore_case) int git_index_open(git_index **index_out, const char *index_path) { git_index *index; + int error; assert(index_out); @@ -346,10 +347,15 @@ int git_index_open(git_index **index_out, const char *index_path) index->entries_search_path = index_srch_path; index->reuc_search = reuc_srch; + if ((index_path != NULL) && ((error = git_index_read(index, true)) < 0)) { + git_index_free(index); + return error; + } + *index_out = index; GIT_REFCOUNT_INC(index); - return (index_path != NULL) ? git_index_read(index, true) : 0; + return 0; } int git_index_new(git_index **out) -- cgit v1.2.1 From 65f67857ab8653212d85d5ea4ef22d95c244ca85 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Tue, 19 Nov 2013 14:25:30 +0100 Subject: tests: Drop unrelated comment --- tests/index/tests.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/index/tests.c b/tests/index/tests.c index 217e1bb55..5a05bd8a9 100644 --- a/tests/index/tests.c +++ b/tests/index/tests.c @@ -539,7 +539,6 @@ void test_index_tests__reload_from_disk(void) void test_index_tests__corrupted_extension(void) { - /* sort the entires in an empty index */ git_index *index; cl_git_fail_with(git_index_open(&index, TEST_INDEXBAD_PATH), GIT_ERROR); -- cgit v1.2.1 From 963edd9bff9f2ae008a99e92e17b46f42fe40641 Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Tue, 19 Nov 2013 17:58:58 +0100 Subject: util: NetBSD doesn't have qsort_r either --- src/util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/util.c b/src/util.c index 162ed6f70..47516a8f7 100644 --- a/src/util.c +++ b/src/util.c @@ -726,7 +726,8 @@ static int GIT_STDLIB_CALL git__qsort_r_glue_cmp( void git__qsort_r( void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload) { -#if defined(__MINGW32__) || defined(__OpenBSD__) || defined(AMIGA) || \ +#if defined(__MINGW32__) || defined(AMIGA) || \ + defined(__OpenBSD__) || defined(__NetBSD__) || \ defined(__gnu_hurd__) || defined(__ANDROID_API__) || \ (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8) git__insertsort_r(els, nel, elsize, NULL, cmp, payload); -- cgit v1.2.1 From 1b3fe73c8dba597a8c7ff97e4e78acac6d58b1a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 20 Nov 2013 11:52:57 +0100 Subject: Formatting fix for cred_acquire_cb --- include/git2/transport.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/git2/transport.h b/include/git2/transport.h index fe4883f99..caabd0465 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -167,13 +167,13 @@ GIT_EXTERN(int) git_cred_default_new(git_cred **out); /** * Signature of a function which acquires a credential object. * - * @param cred The newly created credential object. - * @param url The resource for which we are demanding a credential. - * @param username_from_url The username that was embedded in a "user@host" + * - cred: The newly created credential object. + * - url: The resource for which we are demanding a credential. + * - username_from_url: The username that was embedded in a "user@host" * remote url, or NULL if not included. - * @param allowed_types A bitmask stating which cred types are OK to return. - * @param payload The payload provided when specifying this callback. - * @return 0 for success or an error code for failure + * - allowed_types: A bitmask stating which cred types are OK to return. + * - payload: The payload provided when specifying this callback. + * - returns 0 for success or non-zero to indicate an error */ typedef int (*git_cred_acquire_cb)( git_cred **cred, -- cgit v1.2.1 From 43cb8b32428b1b29994874349ec22eb5372e152c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 20 Nov 2013 12:53:33 +0100 Subject: libgit2 0.20.0 "anmeldung" Apologies for the delay. This release is chunky, but you're probably used to chunky releases by now. Full changelog follows: Internal changes + Added support for decomposed Unicode paths in Mac OS X + Added support for junctions in win32 + Fixed issues with HTTP redirects in the network stack + Performance improvements (as always) git2/blame.h + added full support for blame operations git2/blob.h + added `git_blob_filtered_content` to load blobs in memory with their corresponding filters applied git2/branch.h + added branch iterators as an alternative to the callback-based API git2/buffer.h + exported the git_buf struct to allow binary buffers to be passed from/to the library. This simplifies several APIs git2/checkout.h + implemented additional checkout options ('skip unmerged', 'use ours' and 'use theirs') git2/clone.h + simplified the clone API + added new `git_clone_into` to clone into an existing (empty) repository git2/commit.h + added APIs to access the raw (uncleaned) text of a commit message git2/common.h + added global options to set the default paths to load templates from git2/config.h + added multivar iterators + added globbing iterator + added `git_config_foreach_match` to perform operations on every single var in a config file git2/diff.h + restructured and simplified the diff API git2/filter.h + added external APIs to configure and apply custom filters to checked out blobs git2/index.h + `git_index_read` can now force a reload of the index file even if it hasn't changed on-disk git2/indexer.h + improved the streaming indexer APIs git2/merge.h + added support for merge! git2/object.h + added helper API to lookup a generic object by path git2/pack.h + added progress callbacks to the packbuilder git2/patch.h + added support for patch generation as part of the Diff API revamp git2/pathspec.h + added helper APIs to work with pathspecs and match files in the workdir or diffs git2/push.h + added progress callbacks to push git2/reflog.h + changed reflog APIs to work on reference names instead of the references themselves, so they become less racy git2/remote.h + added support for setting refspecs on remotes, either at creation or on existing ones + simplified the remotes API git2/revwalk.h + add API to simplify parents during a walk git2/signature.h + add helper to create a signature with the default values for a repository (i.e. the set `user.name` and `user.email` values, and the current time) git2/submodules.h + improve the status detection for submodules git2/sys/ + exported many new internal APIs, such as pluggabe transport APIs -vmg, out --- include/git2/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/git2/version.h b/include/git2/version.h index d8a915fac..c4c5e8eb1 100644 --- a/include/git2/version.h +++ b/include/git2/version.h @@ -7,9 +7,9 @@ #ifndef INCLUDE_git_version_h__ #define INCLUDE_git_version_h__ -#define LIBGIT2_VERSION "0.19.0" +#define LIBGIT2_VERSION "0.20.0" #define LIBGIT2_VER_MAJOR 0 -#define LIBGIT2_VER_MINOR 19 +#define LIBGIT2_VER_MINOR 20 #define LIBGIT2_VER_REVISION 0 #endif -- cgit v1.2.1